summaryrefslogtreecommitdiffstats
path: root/scripts/ias_image_app
blob: 6a9b55f30f8c75d8c3ef2e5c81485486cb77933b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env python
#
# Copyright (c) 2012, Intel Corporation.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# The CRC is a python translation of c code generated by (available under MIT license)
# pycrc 0.7.1 (http://www.tty1.net/pycrc/). Command line used:
# './pycrc.py --model=crc-32c --generate c --algorithm=table-driven'
#

import argparse
import os
import struct
import errno

__version__ = "0.0.1a"

#========================================================================
# IAS image creation
#========================================================================

MAGIC  = 0x2E6B7069
HEADER = struct.Struct('IIIIIII')

def image (payload, ext_hdr=''):

    payload_len = round_up(len(payload))
    image_len   = HEADER.size + len(ext_hdr) + payload_len + 4
    bytes       = bytearray (image_len)

    type = 0x30000
    version = 0
    length  = payload_len
    offset  = HEADER.size + len(ext_hdr)
    uncomp  = length	## compression not supported (yet)
    hcrc    = 0
    HEADER.pack_into (bytes, 0,
                      MAGIC, type, version, length, offset, uncomp, hcrc)
    crc = crc32c_buf (bytes[0:24])
    struct.pack_into ('I', bytes, 24, crc)

    bytes[HEADER.size:offset] = ext_hdr
    bytes[offset:offset+len(payload)] = payload
    crc = crc32c_buf(bytes[HEADER.size:offset+length])
    struct.pack_into ('I', bytes, offset+length, crc)

    return bytes

def multi_image (files):

    nfile = len(files)

    subimg = []
    o = 0
    for f in files:
        l = len(f)
        subimg.append((o, l))
        o += round_up(l)

    sizes   = bytearray(4*nfile)
    payload = bytearray(o)
    for i in range(nfile):
        o, l = subimg[i]
        struct.pack_into ('I', sizes, 4*i, l)
        payload[o:o+l] = files[i]

    return image (payload, sizes)

# ========================================================================
# Support functions.
# ========================================================================

def round_up (value, div=4):
    """Round VALUE up to the next multiple of DIV (a power of two)."""
    return (value + div - 1) & ~(div - 1)

# ========================================================================
#
#  CRC32C 
#
# Prehashed table of value to speed script execution
#
_CRC32C_TABLE = (

    0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
    0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
    0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
    0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
    0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
    0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
    0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
    0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
    0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
    0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
    0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
    0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
    0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
    0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
    0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
    0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
    0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
    0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
    0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
    0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
    0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
    0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
    0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
    0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
    0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
    0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
    0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
    0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
    0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
    0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
    0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
    0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
)

def crc32c (byte, crc=0xffffffff):

    crc = (crc >> 8) ^ _CRC32C_TABLE[(crc ^ byte) & 0xff]
    return crc

def crc32c_buf (buf, crc=0xffffffff):

    for b in buf:
        crc = crc32c (b, crc)
    return crc

# ========================================================================

#========================================================================
# Main program: Argument handling.
#========================================================================

def parse_args():
    """Parse the command line and return an argparse.Namespace object."""

    parser = argparse.ArgumentParser(description='Create a NON SIGNED IAS image to be used with DEVEL-ABL.')

    parser.add_argument ('-V', '--version',
                         action='version', version='%(prog)s ' + __version__)
    parser.add_argument ('-o', '--output',
                         default='image.bin',
                         help='write final image to OUTPUT')
    parser.add_argument ('-i', '--ignore',
                         default='',
                         help='provided for script compatibility with full featured ias_image_app',)

    parser.add_argument ('file',
                         help='add FILE to payload of IMAGE being created',
                         nargs='+',
                         metavar='file')

    return parser.parse_args()

# ------------------------------------------------------------------------

def main():

    a = parse_args()
    try:
        data = [open(f, 'rb').read() for f in a.file]
    except IOError:
        print ('error: Cannot open', a.file)
        exit (1) 
    print ('Creating NON signed Linux Kernel for ABL')
    img = multi_image(data)
    try:
        open (a.output, 'wb').write (img)
    except IOError as err:
        print ('error: Cannot open for write', a.output)
        exit (2)     

if __name__ == '__main__':
    main()

# ========================================================================
E("There isn't any valid subscriptions for that request."); return ret; } else if (subscription_exists && ! afb_event_is_valid(s[sub_index]->get_event()) ) { AFB_NOTICE("Event isn't valid, no need to unsubscribed."); return ret; } if( (ret = s[sub_index]->unsubscribe(request)) < 0) return ret; s.erase(sub_index); return ret; } static int add_to_event_loop(std::shared_ptr<low_can_subscription_t>& can_subscription) { struct sd_event_source* event_source = nullptr; return ( sd_event_add_io(afb_daemon_get_event_loop(), &event_source, can_subscription->get_socket()->socket(), EPOLLIN, read_message, can_subscription.get())); } static int subscribe_unsubscribe_diagnostic_messages(afb_req_t request, bool subscribe, std::vector<std::shared_ptr<diagnostic_message_t> > diagnostic_messages, struct event_filter_t& event_filter, std::map<int, std::shared_ptr<low_can_subscription_t> >& s, bool perm_rec_diag_req) { int rets = 0; application_t& app = application_t::instance(); diagnostic_manager_t& diag_m = app.get_diagnostic_manager(); for(const auto& sig : diagnostic_messages) { DiagnosticRequest* diag_req = new DiagnosticRequest(sig->build_diagnostic_request()); event_filter.frequency = event_filter.frequency == 0 ? sig->get_frequency() : event_filter.frequency; std::shared_ptr<low_can_subscription_t> can_subscription; auto it = std::find_if(s.begin(), s.end(), [&sig](std::pair<int, std::shared_ptr<low_can_subscription_t> > sub){ return (! sub.second->get_diagnostic_message().empty());}); can_subscription = it != s.end() ? it->second : std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter)); // If the requested diagnostic message is not supported by the car then unsubcribe it // no matter what we want, worst case will be a failed unsubscription but at least we won't // poll a PID for nothing. if(sig->get_supported() && subscribe) { if (!app.isEngineOn()) AFB_WARNING("signal: Engine is off, %s won't received responses until it's on", sig->get_name().c_str()); diag_m.add_recurring_request(diag_req, sig->get_name().c_str(), false, sig->get_decoder(), sig->get_callback(), event_filter.frequency, perm_rec_diag_req); if(can_subscription->create_rx_filter(sig) < 0) {return -1;} AFB_DEBUG("Signal: %s subscribed", sig->get_name().c_str()); if(it == s.end() && add_to_event_loop(can_subscription) < 0) { diag_m.cleanup_request( diag_m.find_recurring_request(*diag_req), true); AFB_WARNING("signal: %s isn't supported. Canceling operation.", sig->get_name().c_str()); return -1; } } else { if(sig->get_supported()) {AFB_DEBUG("%s cancelled due to unsubscribe", sig->get_name().c_str());} else { AFB_WARNING("signal: %s isn't supported. Canceling operation.", sig->get_name().c_str()); return -1; } } int ret = subscribe_unsubscribe_signal(request, subscribe, can_subscription, s); if(ret < 0) return ret; rets++; } return rets; } static int subscribe_unsubscribe_can_signals(afb_req_t request, bool subscribe, std::vector<std::shared_ptr<can_signal_t> > can_signals, struct event_filter_t& event_filter, std::map<int, std::shared_ptr<low_can_subscription_t> >& s) { int rets = 0; for(const auto& sig: can_signals) { auto it = std::find_if(s.begin(), s.end(), [&sig, &event_filter](std::pair<int, std::shared_ptr<low_can_subscription_t> > sub){ return sub.second->is_signal_subscription_corresponding(sig, event_filter) ; }); std::shared_ptr<low_can_subscription_t> can_subscription; if(it != s.end()) {can_subscription = it->second;} else { can_subscription = std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter)); if(can_subscription->create_rx_filter(sig) < 0) {return -1;} if(add_to_event_loop(can_subscription) < 0) {return -1;} } if(subscribe_unsubscribe_signal(request, subscribe, can_subscription, s) < 0) {return -1;} rets++; AFB_DEBUG("%s Signal: %s %ssubscribed", sig->get_message()->is_fd() ? "FD": "", sig->get_name().c_str(), subscribe ? "":"un"); } return rets; } /// /// @brief subscribe to all signals in the vector signals /// /// @param[in] afb_req request : contains original request use to subscribe or unsubscribe /// @param[in] subscribe boolean value, which chooses between a subscription operation or an unsubscription /// @param[in] signals - struct containing vectors with can_signal_t and diagnostic_messages to subscribe /// /// @return Number of correctly subscribed signal /// static int subscribe_unsubscribe_signals(afb_req_t request, bool subscribe, const struct utils::signals_found& signals, struct event_filter_t& event_filter) { int rets = 0; utils::signals_manager_t& sm = utils::signals_manager_t::instance(); std::lock_guard<std::mutex> subscribed_signals_lock(sm.get_subscribed_signals_mutex()); std::map<int, std::shared_ptr<low_can_subscription_t> >& s = sm.get_subscribed_signals(); rets += subscribe_unsubscribe_diagnostic_messages(request, subscribe, signals.diagnostic_messages, event_filter, s, false); rets += subscribe_unsubscribe_can_signals(request, subscribe, signals.can_signals, event_filter, s); return rets; } static int one_subscribe_unsubscribe(afb_req_t request, bool subscribe, const std::string& tag, json_object* args) { int ret = 0; struct event_filter_t event_filter; struct json_object *filter, *obj; struct utils::signals_found sf; // computes the filter if (json_object_object_get_ex(args, "filter", &filter)) { if (json_object_object_get_ex(filter, "frequency", &obj) && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int))) {event_filter.frequency = (float)json_object_get_double(obj);} if (json_object_object_get_ex(filter, "min", &obj) && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int))) {event_filter.min = (float)json_object_get_double(obj);} if (json_object_object_get_ex(filter, "max", &obj) && (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int))) {event_filter.max = (float)json_object_get_double(obj);} } // subscribe or unsubscribe openxc_DynamicField search_key = build_DynamicField(tag); sf = utils::signals_manager_t::instance().find_signals(search_key); if (sf.can_signals.empty() && sf.diagnostic_messages.empty()) { AFB_NOTICE("No signal(s) found for %s.", tag.c_str()); ret = -1; } else {ret = subscribe_unsubscribe_signals(request, subscribe, sf, event_filter);} return ret; } static int process_one_subscribe_args(afb_req_t request, bool subscribe, json_object *args) { int rc = 0, rc2=0; json_object *x = nullptr, *event = nullptr; if(args == NULL || !json_object_object_get_ex(args, "event", &event)) { rc = one_subscribe_unsubscribe(request, subscribe, "*", args); } else if (json_object_get_type(event) != json_type_array) { rc = one_subscribe_unsubscribe(request, subscribe, json_object_get_string(event), args); } else { for (int i = 0 ; i < json_object_array_length(event); i++) { x = json_object_array_get_idx(event, i); rc2 = one_subscribe_unsubscribe(request, subscribe, json_object_get_string(x), args); if (rc >= 0) rc = rc2 >= 0 ? rc + rc2 : rc2; } } return rc; } static void do_subscribe_unsubscribe(afb_req_t request, bool subscribe) { int rc = 0; struct json_object *args, *x; args = afb_req_json(request); if (json_object_get_type(args) == json_type_array) { for(int i = 0; i < json_object_array_length(args); i++) { x = json_object_array_get_idx(args, i); rc += process_one_subscribe_args(request, subscribe, x); } } else { rc += process_one_subscribe_args(request, subscribe, args); } if (rc >= 0) afb_req_success(request, NULL, NULL); else afb_req_fail(request, "error", NULL); } void auth(afb_req_t request) { afb_req_session_set_LOA(request, 1); afb_req_success(request, NULL, NULL); } void subscribe(afb_req_t request) { do_subscribe_unsubscribe(request, true); } void unsubscribe(afb_req_t request) { do_subscribe_unsubscribe(request, false); } static int send_frame(struct canfd_frame& cfd, const std::string& bus_name) { if(bus_name.empty()) { return -1; } std::map<std::string, std::shared_ptr<low_can_subscription_t> >& cd = application_t::instance().get_can_devices(); if( cd.count(bus_name) == 0) {cd[bus_name] = std::make_shared<low_can_subscription_t>(low_can_subscription_t());} return cd[bus_name]->tx_send(*cd[bus_name], cfd, bus_name); } static void write_raw_frame(afb_req_t request, const std::string& bus_name, json_object *json_value) { struct canfd_frame cfd; struct json_object *can_data = nullptr; ::memset(&cfd, 0, sizeof(cfd)); if(wrap_json_unpack(json_value, "{si, si, so !}", "can_id", &cfd.can_id, "can_dlc", &cfd.len, "can_data", &can_data)) { afb_req_fail(request, "Invalid", "Frame object malformed"); return; } if(cfd.len <= 8 && cfd.len > 0) { for (int i = 0 ; i < cfd.len ; i++) { struct json_object *one_can_data = json_object_array_get_idx(can_data, i); cfd.data[i] = (json_object_is_type(one_can_data, json_type_int)) ? (uint8_t)json_object_get_int(one_can_data) : 0; } } else { afb_req_fail(request, "Invalid", "Data array must hold 1 to 8 values."); return; } if(! send_frame(cfd, application_t::instance().get_can_bus_manager().get_can_device_name(bus_name))) afb_req_success(request, nullptr, "Message correctly sent"); else afb_req_fail(request, "Error", "sending the message. See the log for more details."); } static void write_signal(afb_req_t request, const std::string& name, json_object *json_value) { struct canfd_frame cfd; struct utils::signals_found sf; signal_encoder encoder = nullptr; bool send = true; ::memset(&cfd, 0, sizeof(cfd)); openxc_DynamicField search_key = build_DynamicField(name); sf = utils::signals_manager_t::instance().find_signals(search_key); openxc_DynamicField dynafield_value = build_DynamicField(json_value); if (sf.can_signals.empty()) { afb_req_fail_f(request, "No signal(s) found for %s. Message not sent.", name.c_str()); return; } std::shared_ptr<can_signal_t>& sig = sf.can_signals[0]; if(! sig->get_writable()) { afb_req_fail_f(request, "%s isn't writable. Message not sent.", sig->get_name().c_str()); return; } uint64_t value = (encoder = sig->get_encoder()) ? encoder(*sig, dynafield_value, &send) : encoder_t::encode_DynamicField(*sig, dynafield_value, &send); cfd = encoder_t::build_frame(sig, value); if(! send_frame(cfd, sig->get_message()->get_bus_device_name()) && send) afb_req_success(request, nullptr, "Message correctly sent"); else afb_req_fail(request, "Error", "Sending the message. See the log for more details."); } void write(afb_req_t request) { struct json_object* args = nullptr, *json_value = nullptr; const char *name = nullptr; args = afb_req_json(request); // Process about Raw CAN message on CAN bus directly if (args != NULL && ! wrap_json_unpack(args, "{ss, so !}", "bus_name", &name, "frame", &json_value)) write_raw_frame(request, name, json_value); // Search signal then encode value. else if(args != NULL && ! wrap_json_unpack(args, "{ss, so !}", "signal_name", &name, "signal_value", &json_value)) write_signal(request, std::string(name), json_value); else afb_req_fail(request, "Error", "Request argument malformed"); } static struct json_object *get_signals_value(const std::string& name) { struct utils::signals_found sf; struct json_object *ans = nullptr; openxc_DynamicField search_key = build_DynamicField(name); sf = utils::signals_manager_t::instance().find_signals(search_key); if (sf.can_signals.empty()) { AFB_WARNING("No signal(s) found for %s.", name.c_str()); return NULL; } ans = json_object_new_array(); for(const auto& sig: sf.can_signals) { struct json_object *jobj = json_object_new_object(); json_object_object_add(jobj, "event", json_object_new_string(sig->get_name().c_str())); json_object_object_add(jobj, "value", json_object_new_double(sig->get_last_value())); json_object_array_add(ans, jobj); } return ans; } void get(afb_req_t request) { int rc = 0; struct json_object* args = nullptr, *json_name = nullptr; json_object *ans = nullptr; args = afb_req_json(request); // Process about Raw CAN message on CAN bus directly if (args != nullptr && (json_object_object_get_ex(args, "event", &json_name) && json_object_is_type(json_name, json_type_string) )) { ans = get_signals_value(json_object_get_string(json_name)); if (!ans) rc = -1; } else { AFB_ERROR("Request argument malformed. Please use the following syntax:"); rc = -1; } if (rc >= 0) afb_req_success(request, ans, NULL); else afb_req_fail(request, "error", NULL); } static struct json_object *list_can_message(const std::string& name) { struct utils::signals_found sf; struct json_object *ans = nullptr; openxc_DynamicField search_key = build_DynamicField(name); sf = utils::signals_manager_t::instance().find_signals(search_key); if (sf.can_signals.empty() && sf.diagnostic_messages.empty()) { AFB_WARNING("No signal(s) found for %s.", name.c_str()); return NULL; } ans = json_object_new_array(); for(const auto& sig: sf.can_signals) { json_object_array_add(ans, json_object_new_string(sig->get_name().c_str())); } for(const auto& sig: sf.diagnostic_messages) { json_object_array_add(ans, json_object_new_string(sig->get_name().c_str())); } return ans; } void list(afb_req_t request) { int rc = 0; json_object *ans = nullptr; struct json_object* args = nullptr, *json_name = nullptr; args = afb_req_json(request); const char *name; if ((args != nullptr) && (json_object_object_get_ex(args, "event", &json_name) && json_object_is_type(json_name, json_type_string))) { name = json_object_get_string(json_name); } else { name = "*"; } ans = list_can_message(name); if (!ans) rc = -1; if (rc >= 0) afb_req_success(request, ans, NULL); else afb_req_fail(request, "error", NULL); } /// @brief Initialize the binding. /// /// @param[in] service Structure which represent the Application Framework Binder. /// /// @return Exit code, zero if success. int init_binding(afb_api_t api) { uint32_t ret = 1; can_bus_t& can_bus_manager = application_t::instance().get_can_bus_manager(); can_bus_manager.set_can_devices(); can_bus_manager.start_threads(); /// Initialize Diagnostic manager that will handle obd2 requests. /// We pass by default the first CAN bus device to its Initialization. /// TODO: be able to choose the CAN bus device that will be use as Diagnostic bus. if(application_t::instance().get_diagnostic_manager().initialize()) ret = 0; // Add a recurring dignostic message request to get engine speed at all times. openxc_DynamicField search_key = build_DynamicField("diagnostic_messages.engine.speed"); struct utils::signals_found sf = utils::signals_manager_t::instance().find_signals(search_key); if(sf.can_signals.empty() && sf.diagnostic_messages.size() == 1) { afb_req_t request = nullptr; struct event_filter_t event_filter; event_filter.frequency = sf.diagnostic_messages.front()->get_frequency(); utils::signals_manager_t& sm = utils::signals_manager_t::instance(); std::map<int, std::shared_ptr<low_can_subscription_t> >& s = sm.get_subscribed_signals(); subscribe_unsubscribe_diagnostic_messages(request, true, sf.diagnostic_messages, event_filter, s, true); } if(ret) AFB_ERROR("There was something wrong with CAN device Initialization."); return ret; }