X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=ll-can-binding.c;h=adf878b6e9ca4badb2ae42783beaf20a7f3539be;hb=d3eea564254da43803c9ad9a105ef93cdd053227;hp=ae748b9df04c1c381931a7dcaec6728e6920faee;hpb=9650f4238498e09230ff76bf458043be9ef00df2;p=apps%2Fagl-service-can-low-level.git diff --git a/ll-can-binding.c b/ll-can-binding.c index ae748b9d..adf878b6 100644 --- a/ll-can-binding.c +++ b/ll-can-binding.c @@ -97,7 +97,7 @@ static int socket_test() * * return can_event */ -static can_event *get_event_of_id(uint32_t id) +static can_event *get_event_list_of_id(uint32_t id) { can_event *current; @@ -154,19 +154,18 @@ static char* create_name(uint32_t id) * object. * * return : json object - * - * */ static json_object* create_json_from_openxc_CanMessage(event *event) { struct json_object *json; - openxc_CanMessage can_message; /* * TODO: process the openxc_CanMessage struct. Should be a call to a * decoder function relative to that msg - */ + + openxc_CanMessage can_message; can_message = event->can_message; + */ json = json_object_new_object(); json_object_object_add(json, "name", json_object_new_string(event->name)); @@ -269,6 +268,79 @@ static int write_can() return rc; } +/* + * Parse the CAN frame data payload as a CAN packet + * TODO: parse as an OpenXC Can Message. Don't translate as ASCII and put bytes + * directly into openxc_CanMessage + */ +static int parse_can_frame(openxc_CanMessage *can_message, struct canfd_frame *canfd_frame, int maxdlen) +{ + int i, len; + //size_t n_msg; + + len = (canfd_frame->len > maxdlen) ? maxdlen : canfd_frame->len; + + can_message->has_id = true; + if (canfd_frame->can_id & CAN_ERR_FLAG) + can_message->id = canfd_frame->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG); + else if (canfd_frame->can_id & CAN_EFF_FLAG) + { + can_message->has_frame_format = true; + can_message->frame_format = openxc_CanMessage_FrameFormat_EXTENDED; + can_message->id = canfd_frame->can_id & CAN_EFF_MASK; + } else + { + can_message->has_frame_format = true; + can_message->frame_format = openxc_CanMessage_FrameFormat_STANDARD; + can_message->id = canfd_frame->can_id & CAN_SFF_MASK; + } + + /* Don't know what to do with that for now as we haven't + * len fields in openxc_CanMessage struct + + * standard CAN frames may have RTR enabled. There are no ERR frames with RTR + if (maxdlen == CAN_MAX_DLEN && canfd_frame->can_id & CAN_RTR_FLAG) + { + // print a given CAN 2.0B DLC if it's not zero + if (canfd_frame->len && canfd_frame->len <= CAN_MAX_DLC) + buf[offset++] = hex_asc_upper[canfd_frame->len & 0xF]; + + buf[offset] = 0; + return NULL; + } + */ + + /* Doesn't handle real canfd_frame for now + if (maxdlen == CANFD_MAX_DLEN) + { + // add CAN FD specific escape char and flags + canfd_frame->flags & 0xF; + } */ + + if (sizeof(canfd_frame->data) <= sizeof(can_message->data.bytes)) + { + for (i = 0; i < len; i++) + can_message->data.bytes[i] = canfd_frame->data[i]; + return 0; + } else if (sizeof(canfd_frame->data) <= CAN_MAX_DLEN) + { + ERROR(interface, "parse_can_frame: can_frame data too long to be stored into openxc_CanMessage data field"); + return -1; + /* TODO create as many as needed openxc_CanMessage into an array to store all data from canfd_frame + n_msg = CAN_MAX_DLEN / sizeof(canfd_frame->data.bytes); + for (i = 0; i < len; i++) + can_message->data.bytes[i] = canfd_frame->data[i]; */ + } else + { + ERROR(interface, "parse_can_frame: can_frame is really too long here. Size of data greater than canfd maximum 64bytes size. Is it a CAN message ?"); + return -2; + } + + /* You should not reach this return statement */ + return -3; +} + + /* * Read on CAN bus and return how much bytes has been read. */ @@ -278,7 +350,7 @@ static int read_can(openxc_CanMessage *can_message) int maxdlen; /* Test that socket is really opened */ - if ( socket_test < 0) + if ( socket_test() < 0) { if (retry(open_can_dev) < 0) { @@ -316,64 +388,15 @@ static int read_can(openxc_CanMessage *can_message) return -3; } - parse_can_frame(can_message, &canfd_frame, maxdlen); -} - -/* - * Parse the CAN frame data payload as a CAN packet - * TODO: parse as an OpenXC Can Message. Don't translate as ASCII and put bytes - * directly into openxc_CanMessage - */ -static void parse_can_frame(openxc_CanMessage *can_message, struct canfd_frame *canfd_frame, int maxdlen) -{ - int i,offset; - int len = (canfd_frame->len > maxdlen) ? maxdlen : canfd_frame->len; - - can_message->has_id = true; - if (canfd_frame->can_id & CAN_ERR_FLAG) - can_message->id = canfd_frame->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG); - else if (canfd_frame->can_id & CAN_EFF_FLAG) + if (parse_can_frame(can_message, &canfd_frame, maxdlen)) { - can_message->has_frame_format = true; - can_message->frame_format = openxc_CanMessage_FrameFormat_EXTENDED; - can_message->id = canfd_frame->can_id & CAN_EFF_MASK; - } else - { - can_message->has_frame_format = true; - can_message->frame_format = openxc_CanMessage_FrameFormat_STANDARD; - can_message->id = canfd_frame->can_id & CAN_SFF_MASK; - } - - /* standard CAN frames may have RTR enabled. There are no ERR frames with RTR */ - if (maxdlen == CAN_MAX_DLEN && canfd_frame->can_id & CAN_RTR_FLAG) - { - /* Don't know what to do with that for now as we haven't - * len fields in openxc_CanMessage struct - * - * print a given CAN 2.0B DLC if it's not zero - if (canfd_frame->len && canfd_frame->len <= CAN_MAX_DLC) - buf[offset++] = hex_asc_upper[canfd_frame->len & 0xF]; - - buf[offset] = 0;*/ - return; + ERROR(interface, "read_can: Can't parse the can frame. ID: %i, DLC: %i, DATA: %s", + canfd_frame.can_id, canfd_frame.len, canfd_frame.data); + return -4; } - if (maxdlen == CANFD_MAX_DLEN) - { - /* add CAN FD specific escape char and flags */ - canfd_frame->flags & 0xF; - } - - for (i = 0; i < len; i++) - { - //put_hex_byte(buf + offset, canfd_frame->data[i]); - //offset += 2; - } - -// buf[offset] = 0; - return; + return 0; } - /*************************************************************************/ /*************************************************************************/ /** **/ @@ -383,53 +406,38 @@ static void parse_can_frame(openxc_CanMessage *can_message, struct canfd_frame * /** **/ /*************************************************************************/ /*************************************************************************/ +static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata); + /* - * called on an event on the CAN bus + * Get the event loop running. + * Will trigger on_event function on EPOLLIN event on socket + * + * Return 0 or positive value on success. Else negative value for failure. */ -static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) +static int connect_to_event_loop() { - openxc_CanMessage can_message; + sd_event *event_loop; + sd_event_source *source; + int rc; - /* read available data */ - if ((revents & EPOLLIN) != 0) + if (can_handler.socket < 0) { - read_can(&can_message); - send_event(); + return can_handler.socket; } - /* check if error or hangup */ - if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0) + event_loop = afb_daemon_get_event_loop(interface->daemon); + rc = sd_event_add_io(event_loop, &source, can_handler.socket, EPOLLIN, on_event, NULL); + if (rc < 0) { - sd_event_source_unref(s); - close(fd); - connect_to_event_loop(); + close(can_handler.socket); + ERROR(interface, "Can't connect CAN bus %s to the event loop", can_handler.device); + } else + { + NOTICE(interface, "Connected CAN bus %s to the event loop", can_handler.device); } - return 0; -} - -/* - * get or create an event handler for the type - * TODO: implement function and handle retrieve or create an event as needed - */ -static event *get_event(uint32_t id, enum type type) -{ - event *event; - can_event *list; - - /* find the can list by id */ - list = get_event_of_id(id); - - /* make the new event */ - event = (can_event*)calloc(1, sizeof(can_event)); - event->next = event; - list->events = event; - event->name = create_name(id); - event->afb_event = afb_daemon_make_event(interface->daemon, event->name); - - return event; + return rc; } - /* * Send all events */ @@ -456,34 +464,51 @@ static void send_event() } /* - * Get the event loop running. - * Will trigger on_event function on EPOLLIN event on socket - * - * Return 0 or positive value on success. Else negative value for failure. + * called on an event on the CAN bus */ -static int connect_to_event_loop() +static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - sd_event *event_loop; - sd_event_source *source; - int rc; + openxc_CanMessage can_message; - if (can_handler.socket < 0) + can_message = openxc_CanMessage_init_default; + + /* read available data */ + if ((revents & EPOLLIN) != 0) { - return can_handler.socket; + read_can(&can_message); + send_event(); } - event_loop = afb_daemon_get_event_loop(interface->daemon); - rc = sd_event_add_io(event_loop, &source, can_handler.socket, EPOLLIN, on_event, NULL); - if (rc < 0) - { - close(can_handler.socket); - ERROR(interface, "Can't connect CAN bus %s to the event loop", can_handler.device); - } else + /* check if error or hangup */ + if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0) { - NOTICE(interface, "Connected CAN bus %s to the event loop", can_handler.device); + sd_event_source_unref(s); + close(fd); + connect_to_event_loop(); } - return rc; + return 0; +} + +/* + * get or create an event handler for the type + */ +static event *get_event(uint32_t id, enum type type) +{ + event *event_elt; + can_event *list; + + /* find the can list by id */ + list = get_event_list_of_id(id); + + /* make the new event */ + event_elt = (event*)calloc(1, sizeof(event)); + event_elt->next = event_elt; + list->events = event_elt; + event_elt->name = create_name(id); + event_elt->afb_event = afb_daemon_make_event(interface->daemon, event_elt->name); + + return event_elt; } /*************************************************************************/ @@ -535,7 +560,6 @@ static int get_type_for_req(struct afb_req req, enum type *type) static void subscribe(struct afb_req req) { enum type type; - const char *period; event *event; uint32_t id; struct json_object *json; @@ -568,6 +592,7 @@ static void subscribe(struct afb_req req) static void unsubscribe(struct afb_req req) { const char *id; + can_event *events_list; event *event; id = afb_req_value(req, "id"); @@ -575,18 +600,22 @@ static void unsubscribe(struct afb_req req) afb_req_fail(req, "missing-id", NULL); else { - event = get_event_of_id(atoi(id)); - if (event == NULL) - afb_req_fail(req, "bad-id", NULL); - else + events_list = get_event_list_of_id((uint32_t)atoi(id)); + event = events_list->events; + while(event) { - afb_req_unsubscribe(req, event->afb_event); - afb_req_success(req, NULL, NULL); + if (event == NULL) + afb_req_fail(req, "bad-id", NULL); + else + { + afb_req_unsubscribe(req, event->afb_event); + afb_req_success(req, NULL, NULL); + } + event = event->next; } } } -// TODO: Have to change session management flag to AFB_SESSION_CHECK to use token auth static const struct afb_verb_desc_v1 verbs[]= { { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." },