X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=ucs2-afb%2Fucs_binding.c;h=bf0fd8e8957cff48d3cc2a953630c6cb107e00b1;hb=b79d0efc90f30918d64024bc0807c023e44c5325;hp=b72aca91394fcd77449093fc921e44f4e04cc00e;hpb=6eb714dcedb35abf97b939df1965628c068ab6ce;p=apps%2Fagl-service-unicens.git diff --git a/ucs2-afb/ucs_binding.c b/ucs2-afb/ucs_binding.c index b72aca9..bf0fd8e 100644 --- a/ucs2-afb/ucs_binding.c +++ b/ucs2-afb/ucs_binding.c @@ -41,10 +41,11 @@ #include "ucs_binding.h" #include "ucs_interface.h" +#include #define MAX_FILENAME_LEN (100) #define RX_BUFFER (64) -#define XML_CONFIG_FOLDER "/data/" +#define XML_CONFIG_FOLDER "/var/" #define XML_CONFIG_FILE "config_multichannel_audio_kit.xml" /** Internal structure, enabling multiple instances of this component. @@ -68,11 +69,15 @@ typedef struct { typedef struct { struct afb_event node_event; - } EventData_t; +typedef struct { + struct afb_event rx_event; +} EventDataRx_t; + static ucsContextT *ucsContextS = NULL; static EventData_t *eventData = NULL; +static EventDataRx_t *eventDataRx = NULL; PUBLIC void UcsXml_CB_OnError(const char format[], uint16_t vargsCnt, ...) { /*AFB_DEBUG (afbIface, format, args); */ @@ -208,12 +213,63 @@ void UCSI_CB_OnStop(void *pTag) { sd_event_add_time(afb_daemon_get_event_loop(), NULL, CLOCK_MONOTONIC, 0, 0, OnStopCB, pTag); } +/* helper function: wraps Rx message in json and triggers notification */ +STATIC void NotifyEventRxMsg(uint16_t src_addr, uint16_t msg_id, uint8_t *data_ptr, uint32_t data_sz) { + + if (!eventDataRx) + return; + + if (data_sz > CTRL_MAX_DATA_SZ) { + AFB_NOTICE("RX-MSG: discarded, payload exceeds %d bytes", CTRL_MAX_DATA_SZ); + return; + } + + json_object *j_query = NULL; + int node = (int)src_addr; + int msgid = (int)msg_id; + size_t data_size = (size_t)data_sz; + + /* skip data attribute if possible, wrap_json_unpack may fail to deal with + * an empty Base64 string */ + if (data_size > 0) + wrap_json_pack(&j_query, "{s:i, s:i, s:Y*}", "node", node, "msgid", msgid, "data", data_ptr, data_size); + else + wrap_json_pack(&j_query, "{s:i, s:i}", "node", node, "msgid", msgid); + + afb_event_push(eventDataRx->rx_event, j_query); +} + +/** Asynchronous processing of Rx messages in mainloop is recommended */ +STATIC int OnAmsMessageReceivedCB (sd_event_source *source, void *pTag) { + ucsContextT *ucsContext = (ucsContextT*) pTag; + uint32_t data_sz = 0U; + uint8_t *data_ptr = NULL; + uint16_t msg_id = 0U; + uint16_t src_addr = 0U; + + while (UCSI_GetAmsMessage(&ucsContext->ucsiData, &msg_id, &src_addr, &data_ptr, &data_sz)) { + NotifyEventRxMsg(src_addr, msg_id, data_ptr, data_sz); + AFB_DEBUG("RX-MSG: src=0x%04X, msg_id=0x%04X, size=%d", src_addr, msg_id, data_sz); + UCSI_ReleaseAmsMessage(&ucsContext->ucsiData); + } + + return 0; +} + /** This callback will be raised, when ever an applicative message on the control channel arrived */ void UCSI_CB_OnAmsMessageReceived(void *pTag) { - /* If not interested, just ignore this event. - Otherwise UCSI_GetAmsMessage may now be called asynchronous (mainloop) to get the content. - Don't forget to call UCSI_ReleaseAmsMessage after that */ + static sd_event_source *src_ptr = NULL; + + if (!src_ptr) + { + /* first time usage: create and trigger event source */ + sd_event_add_defer(afb_daemon_get_event_loop(), &src_ptr, &OnAmsMessageReceivedCB, pTag); + } + else + { + sd_event_source_set_enabled(src_ptr, SD_EVENT_ONESHOT); + } } void UCSI_CB_OnRouteResult(void *pTag, uint16_t routeId, bool isActive, uint16_t connectionLabel) @@ -511,6 +567,33 @@ OnExitError: return; } +PUBLIC void ucs2_subscriberx (struct afb_req request) { + + if (!eventDataRx) { + + eventDataRx = malloc(sizeof(EventDataRx_t)); + if (eventDataRx) { + eventDataRx->rx_event = afb_daemon_make_event("rx-message"); + } + + if (!eventDataRx || !afb_event_is_valid(eventDataRx->rx_event)) { + afb_req_fail_f(request, "create-event", "Cannot create or register event"); + goto OnExitError; + } + } + + if (afb_req_subscribe(request, eventDataRx->rx_event) != 0) { + + afb_req_fail_f (request, "subscribe-event", "Cannot subscribe to event"); + goto OnExitError; + } + + afb_req_success(request,NULL,"event subscription successful"); + +OnExitError: + return; +} + static json_object * ucs2_validate_command (struct afb_req request, const char* func_name) { @@ -671,97 +754,37 @@ PUBLIC void ucs2_writei2c (struct afb_req request) { } } -/* write a single control message */ -STATIC void ucs2_sendmessage_cmd(struct afb_req request, json_object *j_obj) { +PUBLIC void ucs2_sendmessage(struct afb_req req) { + uint8_t *data_ptr = NULL; + size_t data_sz = 0; + int ret, node_addr, msg_id = 0; + struct json_object *j_obj; - static uint8_t ctrl_data[CTRL_MAX_DATA_SZ]; - uint8_t ctrl_data_sz = 0; - uint16_t node_addr = 0; - uint16_t msg_id = 0; - json_object *j_tmp; + j_obj = ucs2_validate_command(req, "sendmessageb64"); - if (json_object_object_get_ex(j_obj, "node", &j_tmp)) { - node_addr = (uint16_t)json_object_get_int(j_tmp); - AFB_NOTICE("node_address: 0x%02X", node_addr); - if (node_addr == 0) { - afb_req_fail_f(request, "query-params","param node invalid type"); - goto OnErrorExit; - } - } - else { - afb_req_fail_f(request, "query-params","param node missing"); - goto OnErrorExit; - } - - if (json_object_object_get_ex(j_obj, "msgid", &j_tmp)) { - if (json_object_get_type(j_tmp) == json_type_int) { - msg_id = (uint16_t)json_object_get_int(j_tmp); - AFB_NOTICE("msgid: 0x%02X", msg_id); - } - else { - afb_req_fail_f(request, "query-params","param msgid invalid type"); - goto OnErrorExit; - } - } - else { - afb_req_fail_f(request, "query-params","param msgid missing"); + if (!j_obj) { + AFB_NOTICE("validation of command failed"); goto OnErrorExit; } - if (json_object_object_get_ex(j_obj, "data", &j_tmp)) { - if (json_object_get_type(j_tmp)==json_type_array) { - int size = json_object_array_length(j_tmp); - if ((size > 0) && (size <= CTRL_MAX_DATA_SZ)) { - int32_t i; - int32_t val; - struct json_object *j_elem; - - for (i = 0; i < size; i++) { - j_elem = json_object_array_get_idx(j_tmp, i); - val = json_object_get_int(j_elem); - if ((val < 0) && (val > 0xFF)){ - i = 0; - break; - } - ctrl_data[i] = (uint8_t)json_object_get_int(j_elem); - } - - if (i != size) { /* check if size matches */ - afb_req_fail_f(request, "query-params", - "parameter data is ambiguous"); - goto OnErrorExit; - } - - ctrl_data_sz = (uint8_t)i; - } - } - } + ret = wrap_json_unpack(j_obj, "{s:i, s:i, s?Y}", "node", &node_addr, "msgid", &msg_id, "data", &data_ptr, &data_sz); - if (UCSI_SendAmsMessage(&ucsContextS->ucsiData, /* UCSI_Data_t *pPriv*/ - msg_id, - node_addr, - &ctrl_data[0], - ctrl_data_sz)) { - afb_req_success(request, NULL, "sendmessage started successful"); + if ((ret==0) && + UCSI_SendAmsMessage(&ucsContextS->ucsiData, msg_id, node_addr, &data_ptr[0], data_sz) + ) { + afb_req_success(req, NULL, "sendmessageb64 started successful"); } else { - AFB_NOTICE("sendmessage: scheduling command failed"); - afb_req_fail_f(request, "query-command-queue","command queue overload"); + AFB_ERROR("sendmessageb64: scheduling command failed. ret: %d", ret); + afb_req_fail_f(req, "query-command-queue","ambiguous command or queue overload"); goto OnErrorExit; } OnErrorExit: - return; -} - -PUBLIC void ucs2_sendmessage(struct afb_req request) { - struct json_object *j_obj; - - j_obj = ucs2_validate_command(request, "sendmessage"); - - if (j_obj) { - ucs2_sendmessage_cmd(request, j_obj); + if (data_ptr) { + free(data_ptr); } + return; } PUBLIC int ucs2_initbinding(void) {