2 * Copyright (C) 2015, 2016 "IoT.bzh"
3 * Author "Romain Forlot" <romain.forlot@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/ioctl.h>
27 #include <linux/can.h>
28 #include <linux/can/raw.h>
31 #include <systemd/sd-event.h>
34 #include <json-c/json.h>
35 #include <openxc.pb.h>
37 #include <afb/afb-binding.h>
38 #include <afb/afb-service-itf.h>
40 /*****************************************************************************************/
41 /*****************************************************************************************/
44 /** SECTION: GLOBAL VARIABLES **/
47 /*****************************************************************************************/
48 /*****************************************************************************************/
49 /* max. number of CAN interfaces given on the cmdline */
52 /* buffer sizes for CAN frame string representations */
53 #define CL_ID (sizeof("12345678##1"))
54 #define CL_DATA sizeof(".AA")
55 #define CL_BINDATA sizeof(".10101010")
57 /* CAN FD ASCII hex short representation with DATA_SEPERATORs */
58 #define CL_CFSZ (2*CL_ID + 64*CL_DATA)
60 #define CANID_DELIM '#'
63 * Interface between the daemon and the binding
65 static const struct afb_binding_interface *interface;
68 * the type of position expected
70 * here, this type is the selection of protocol
75 type_DEFAULT = type_CAN,
79 #define type_size sizeof(enum type)-2
81 /* CAN variable initialization */
82 struct canfd_frame canfd_frame;
87 openxc_CanMessage *msg;
88 struct sockaddr_can txAddress;
92 * each generated event
95 struct event *next; /* link for the same period */
96 const char *name; /* name of the event */
97 struct afb_event event; /* the event for the binder */
98 enum type type; /* the type of data expected */
99 int id; /* id of the event for unsubscribe */
102 /*****************************************************************************************/
103 /*****************************************************************************************/
106 /** SECTION: UTILITY FUNCTIONS **/
109 /*****************************************************************************************/
110 /*****************************************************************************************/
113 * @brief Retry a function 3 times
115 * @param int function(): function that return an int wihtout any parameter
117 * @ return : 0 if ok, -1 if failed
120 static int retry( int(*func)());
121 static int retry( int(*func)())
136 /*****************************************************************************************/
137 /*****************************************************************************************/
140 /** SECTION: HANDLE CAN DEVICE **/
143 /*****************************************************************************************/
144 /*****************************************************************************************/
145 const char hex_asc_upper[] = "0123456789ABCDEF";
147 #define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0F)]
148 #define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xF0) >> 4]
150 static inline void put_hex_byte(char *buf, __u8 byte)
152 buf[0] = hex_asc_upper_hi(byte);
153 buf[1] = hex_asc_upper_lo(byte);
156 static inline void _put_id(char *buf, int end_offset, canid_t id)
158 /* build 3 (SFF) or 8 (EFF) digit CAN identifier */
159 while (end_offset >= 0) {
160 buf[end_offset--] = hex_asc_upper[id & 0xF];
165 #define put_sff_id(buf, id) _put_id(buf, 2, id)
166 #define put_eff_id(buf, id) _put_id(buf, 7, id)
168 static void canread_frame_parse(struct canfd_frame *canfd_frame, int maxdlen);
173 static const char * const type_NAMES[type_size] = {
179 // Initialize default can_handler values
180 static struct can_handler can_handler = {
187 * open the can socket
189 static int open_can_dev()
191 const int canfd_on = 1;
193 struct timeval timeout = {1,0};
194 openxc_CanMessage can_msg = {
198 .has_frame_format = false,
201 DEBUG(interface, "open_can_dev: CAN Handler socket : %d", can_handler.socket);
202 close(can_handler.socket);
204 can_handler.socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
205 if (can_handler.socket < 0)
207 ERROR(interface, "open_can_dev: socket could not be created");
211 /* Set timeout for read */
212 setsockopt(can_handler.socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
213 /* try to switch the socket into CAN_FD mode */
214 can_msg.has_frame_format = true;
215 if (setsockopt(can_handler.socket, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)) < 0)
217 NOTICE(interface, "open_can_dev: Can not switch into CAN Extended frame format.");
218 can_msg.frame_format = openxc_CanMessage_FrameFormat_STANDARD;
220 can_msg.frame_format = openxc_CanMessage_FrameFormat_EXTENDED;
223 /* Attempts to open a socket to CAN bus */
224 strcpy(ifr.ifr_name, can_handler.device);
225 if(ioctl(can_handler.socket, SIOCGIFINDEX, &ifr) < 0)
227 ERROR(interface, "open_can_dev: ioctl failed");
231 can_handler.txAddress.can_family = AF_CAN;
232 can_handler.txAddress.can_ifindex = ifr.ifr_ifindex;
234 /* And bind it to txAddress */
235 if (bind(can_handler.socket, (struct sockaddr *)&can_handler.txAddress, sizeof(can_handler.txAddress)) < 0)
237 ERROR(interface, "open_can_dev: bind failed");
241 fcntl(can_handler.socket, F_SETFL, O_NONBLOCK);
242 can_handler.msg = &can_msg;
246 close(can_handler.socket);
247 can_handler.socket = -1;
252 static int write_can()
257 rc = can_handler.socket;
261 * TODO change old hvac write can frame to generic on_event
263 nbytes = sendto(can_handler.socket, &canfd_frame, sizeof(struct canfd_frame), 0,
264 (struct sockaddr*)&can_handler.txAddress, sizeof(can_handler.txAddress));
267 ERROR(interface, "write_can: Sending CAN frame failed.");
272 ERROR(interface, "write_can: socket not initialized. Attempt to reopen can device socket.");
279 * Read on CAN bus and return how much bytes has been read.
281 static int read_can()
286 nbytes = read(can_handler.socket, &canfd_frame, CANFD_MTU);
288 if (nbytes == CANFD_MTU)
290 DEBUG(interface, "read_can: Got an CAN FD frame with length %d", canfd_frame.len);
292 else if (nbytes == CAN_MTU)
294 DEBUG(interface, "read_can: Got a legacy CAN frame with length %d", canfd_frame.len);
298 if (errno == ENETDOWN) {
299 ERROR(interface, "read_can: %s interface down", can_handler.device);
301 ERROR(interface, "read_can: Error reading CAN bus");
305 /* CAN frame integrity check */
306 if ((size_t)nbytes == CAN_MTU)
307 maxdlen = CAN_MAX_DLEN;
308 else if ((size_t)nbytes == CANFD_MTU)
309 maxdlen = CANFD_MAX_DLEN;
312 ERROR(interface, "read_can: CAN frame incomplete");
316 canread_frame_parse(&canfd_frame, maxdlen);
320 * Parse the CAN frame data payload as a CAN packet
321 * TODO: parse as an OpenXC Can Message
323 static void canread_frame_parse(struct canfd_frame *canfd_frame, int maxdlen)
326 int len = (canfd_frame->len > maxdlen) ? maxdlen : canfd_frame->len;
329 if (canfd_frame->can_id & CAN_ERR_FLAG) {
330 put_eff_id(buf, canfd_frame->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
333 } else if (canfd_frame->can_id & CAN_EFF_FLAG) {
334 put_eff_id(buf, canfd_frame->can_id & CAN_EFF_MASK);
338 put_sff_id(buf, canfd_frame->can_id & CAN_SFF_MASK);
343 /* standard CAN frames may have RTR enabled. There are no ERR frames with RTR */
344 if (maxdlen == CAN_MAX_DLEN && canfd_frame->can_id & CAN_RTR_FLAG) {
346 /* print a given CAN 2.0B DLC if it's not zero */
347 if (canfd_frame->len && canfd_frame->len <= CAN_MAX_DLC)
348 buf[offset++] = hex_asc_upper[canfd_frame->len & 0xF];
353 if (maxdlen == CANFD_MAX_DLEN) {
354 /* add CAN FD specific escape char and flags */
356 buf[offset++] = hex_asc_upper[canfd_frame->flags & 0xF];
359 for (i = 0; i < len; i++) {
360 put_hex_byte(buf + offset, canfd_frame->data[i]);
367 /***************************************************************************************/
368 /***************************************************************************************/
371 /** SECTION: MANAGING EVENTS **/
374 /***************************************************************************************/
375 /***************************************************************************************/
376 static int connect_to_event_loop();
379 * called on an event on the CAN bus
381 static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata)
383 openxc_CanMessage can_message;
385 /* read available data */
386 if ((revents & EPOLLIN) != 0)
388 read_can(&can_message);
392 /* check if error or hangup */
393 if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0)
395 sd_event_source_unref(s);
397 connect_to_event_loop();
404 * get or create an event handler for the type
405 * TODO: implement function and handle retrieve or create an event as needed
407 static struct event *event_get(enum type type)
413 static struct event *event_of_id(int id)
418 /*****************************************************************************************/
419 /*****************************************************************************************/
422 /** SECTION: BINDING VERBS IMPLEMENTATION **/
425 /*****************************************************************************************/
426 /*****************************************************************************************/
428 * Returns the type corresponding to the given name
430 static enum type type_of_name(const char *name)
435 for (result = 0 ; result < type_size; result++)
436 if (strcmp(type_NAMES[result], name) == 0)
442 * extract a valid type from the request
444 static int get_type_for_req(struct afb_req req, enum type *type)
446 if ((*type = type_of_name(afb_req_value(req, "type"))) != type_INVALID)
448 afb_req_fail(req, "unknown-type", NULL);
453 * subscribe to notification of new CAN messages
455 * parameters of the subscription are:
457 * TODO type: string: choose between CAN and OBDII messages formats.
459 * returns an object with 2 fields:
461 * name: string: the name of the event without its prefix
462 * id: integer: a numeric identifier of the event to be used for unsubscribing
464 static void subscribe(struct afb_req req)
469 struct json_object *json;
471 if (get_type_for_req(req, &type))
473 event = afb_daemon_make_event(interface->daemon, type_NAMES[type]);
475 afb_req_fail(req, "out-of-memory", NULL);
476 else if (afb_req_subscribe(req, event->event) != 0)
477 afb_req_fail_f(req, "failed", "afb_req_subscribe returned an error: %m");
480 json = json_object_new_object();
481 json_object_object_add(json, "name", json_object_new_string(event->name));
482 json_object_object_add(json, "id", json_object_new_int(event->id));
483 afb_req_success(req, json, NULL);
489 * unsubscribe a previous subscription
491 * parameters of the unsubscription are:
493 * id: integer: the numeric identifier of the event as returned when subscribing
495 static void unsubscribe(struct afb_req req)
500 id = afb_req_value(req, "id");
502 afb_req_fail(req, "missing-id", NULL);
505 event = event_of_id(atoi(id));
507 afb_req_fail(req, "bad-id", NULL);
510 afb_req_unsubscribe(req, event->event);
511 afb_req_success(req, NULL, NULL);
516 static int connect_to_event_loop()
518 sd_event_source *source;
523 if (can_handler.socket < 0)
525 return can_handler.socket;
528 rc = sd_event_add_io(afb_daemon_get_event_loop(interface->daemon), &source, can_handler.socket, EPOLLIN, on_event, NULL);
531 close(can_handler.socket);
532 ERROR(interface, "Can't connect CAN bus %s to the event loop", can_handler.device);
535 NOTICE(interface, "Connected CAN bus %s to the event loop", can_handler.device);
542 // TODO: Have to change session management flag to AFB_SESSION_CHECK to use token auth
543 static const struct afb_verb_desc_v1 verbs[]=
545 { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." },
546 { .name= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info= "unsubscribe a previous subscription." },
550 static const struct afb_binding binding_desc = {
551 .type = AFB_BINDING_VERSION_1,
553 .info = "CAN bus service",
559 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
563 return &binding_desc;
566 int afbBindingV1ServiceInit(struct afb_service service)
568 return connect_to_event_loop();