Some cleanup and rearrange the code
[apps/low-level-can-service.git] / iotbzh-CAN-binding.c
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  *
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
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 #define _GNU_SOURCE
18
19 #include <string.h>
20 #include <stdbool.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/ioctl.h>
25 #include <net/if.h>
26 #include <sys/time.h>
27 #include <linux/can.h>
28 #include <math.h>
29 #include <fcntl.h>
30 #include <systemd/sd-event.h>
31 #include <errno.h>
32
33 #include <json-c/json.h>
34 #include <openxc.pb.h>
35
36 #include <afb/afb-binding.h>
37 #include <afb/afb-service-itf.h>
38
39 /*****************************************************************************************/
40 /*****************************************************************************************/
41 /**                                                                                     **/
42 /**                                                                                     **/
43 /**        SECTION: GLOBAL VARIABLES                                                    **/
44 /**                                                                                     **/
45 /**                                                                                     **/
46 /*****************************************************************************************/
47 /*****************************************************************************************/
48
49 /* max. number of CAN interfaces given on the cmdline */
50 #define MAXSOCK 16
51
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")
56
57  /* CAN FD ASCII hex short representation with DATA_SEPERATORs */
58 #define CL_CFSZ (2*CL_ID + 64*CL_DATA)
59
60 /*
61  * the type of position expected
62  *
63  * here, this type is the selection of protocol
64  */
65 enum type {
66         type_OBDII,
67         type_CAN,
68         type_DEFAULT = type_CAN,
69         type_INVALID = -1
70 };
71
72 #define type_size sizeof(enum type)-2
73
74 /*
75  * each generated event
76  */
77 struct event {
78         struct event *next;     /* link for the same period */
79         const char *name;       /* name of the event */
80         struct afb_event event; /* the event for the binder */
81         enum type type;         /* the type of data expected */
82         int id;                 /* id of the event for unsubscribe */
83 };
84
85 struct can_handler {
86         int socket;
87         char *device;
88         struct sockaddr_can txAddress;
89 };
90
91 static __u32 dropcnt[MAXSOCK];
92 static __u32 last_dropcnt[MAXSOCK];
93 char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
94 struct timeval tv;
95 struct iovec iov;
96 struct msghdr msg;
97 struct cmsghdr *cmsg;
98 struct canfd_frame can_frame;
99
100 /*****************************************************************************************/
101 /*****************************************************************************************/
102 /**                                                                                     **/
103 /**                                                                                     **/
104 /**        SECTION: UTILITY FUNCTIONS                                                   **/
105 /**                                                                                     **/
106 /**                                                                                     **/
107 /*****************************************************************************************/
108 /*****************************************************************************************/
109 /*
110  * Interface between the daemon and the binding
111  */
112 static const struct afb_binding_interface *interface;
113
114 /*
115  * @brief Retry a function 3 times
116  *
117  * @param int function(): function that return an int wihtout any parameter
118  *
119  * @ return : 0 if ok, -1 if failed
120  *
121  */
122 static int retry( int(*func)());
123 static int retry( int(*func)())
124 {
125         int i;
126
127         for (i=0;i<4;i++)
128         {
129                 if ( (*func)() >= 0)
130                 {
131                         return 0;
132                 }
133                 usleep(100000);
134         }
135         return -1;
136 }
137
138 /*****************************************************************************************/
139 /*****************************************************************************************/
140 /**                                                                                     **/
141 /**                                                                                     **/
142 /**        SECTION: HANDLE CAN DEVICE                                                   **/
143 /**                                                                                     **/
144 /**                                                                                     **/
145 /*****************************************************************************************/
146 /*****************************************************************************************/
147 /*
148  * names of the types
149  */
150 static const char * const type_NAMES[type_size] = {
151         "OBDII",
152         "CAN"
153 };
154
155
156 // Initialize default can_handler values
157 static struct can_handler can_handler = {
158         .socket = -1,
159         .device = "vcan0"
160 };
161
162 /*
163  * Parse the CAN frame data payload as a CAN packet
164  * TODO: parse as an OpenXC Can Message
165  */
166 int can_frame_parse(openxc_CanMessage *can_message, struct can_frame *can_frame)
167 {
168
169 }
170
171
172 /*
173  * open the can socket
174  */
175 static int open_can_dev()
176 {
177         struct ifreq ifr;
178         struct timeval timeout = {1,0};
179
180         DEBUG(interface, "open_can_dev: CAN Handler socket : %d", can_handler.socket);
181         close(can_handler.socket);
182
183         can_handler.socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
184         if (can_handler.socket < 0)
185         {
186                 ERROR(interface, "open_can_dev: socket could not be created");
187         }
188         else
189         {
190                 // Set timeout for read
191                 setsockopt(can_handler.socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
192                 // Attempts to open a socket to CAN bus
193                 strcpy(ifr.ifr_name, can_handler.device);
194                 if(ioctl(can_handler.socket, SIOCGIFINDEX, &ifr) < 0)
195                 {
196                         ERROR(interface, "open_can_dev: ioctl failed");
197                 }
198                 else
199                 {
200                         can_handler.txAddress.can_family = AF_CAN;
201                         can_handler.txAddress.can_ifindex = ifr.ifr_ifindex;
202
203                         // And bind it to txAddress
204                         if (bind(can_handler.socket, (struct sockaddr *)&can_handler.txAddress, sizeof(can_handler.txAddress)) < 0)
205                         {
206                                 ERROR(interface, "open_can_dev: bind failed");
207                         }
208                         else
209                         {
210                                 fcntl(can_handler.socket, F_SETFL, O_NONBLOCK);
211                                 return 0;
212                         }
213                 }
214                 close(can_handler.socket);
215                 can_handler.socket = -1;
216         }
217         return -1;
218 }
219
220 static int write_can()
221 {
222         int rc = 0;
223
224         rc = can_handler.socket;
225         if (rc >= 0)
226         {
227 /*
228  * TODO change old hvac write can frame to generic on_event
229  */
230                 rc = sendto(can_handler.socket, &can_frame, sizeof(struct can_frame), 0,
231                             (struct sockaddr*)&can_handler.txAddress, sizeof(can_handler.txAddress));
232                 if (rc < 0)
233                 {
234                         ERROR(interface, "Sending CAN frame failed.");
235                 }
236         }
237         else
238         {
239                 ERROR(interface, "socket not initialized. Attempt to reopen can device socket.");
240                 retry(open_can_dev);
241         }
242         return rc;
243 }
244
245 /*
246  * Read on CAN bus and return how much bytes has been read.
247  */
248 static int read_can(openxc_CanMessage *can_message)
249 {
250         int byte_read, maxdlen;
251         iov.iov_base = &can_frame;
252         msg.msg_name = &can_handler.txAddress;
253         msg.msg_iov = &iov;
254         msg.msg_iovlen = 1;
255         msg.msg_control = &ctrlmsg;
256
257         byte_read = recvmsg(can_handler.socket, &msg, 0);
258
259         if (byte_read < 0)
260         {
261                 if (errno == ENETDOWN) {
262                         ERROR(interface, "%s: interface down", can_handler.device);
263                 }
264                 ERROR(interface, "Error reading CAN bus");
265                 return -1;
266         }
267
268         // CAN frame integrity check
269         if ((size_t)byte_read == CAN_MTU)
270                 maxdlen = CAN_MAX_DLEN;
271         else if ((size_t)byte_read == CANFD_MTU)
272                 maxdlen = CANFD_MAX_DLEN;
273         else
274         {
275                 ERROR(interface, "CAN frame incomplete");
276                 return -2;
277         }
278
279         for (   cmsg = CMSG_FIRSTHDR(&msg);
280                 cmsg && (cmsg->cmsg_level == SOL_SOCKET);
281                 cmsg = CMSG_NXTHDR(&msg,cmsg))
282         {
283                 if (cmsg->cmsg_type == SO_TIMESTAMP)
284                         tv = *(struct timeval *)CMSG_DATA(cmsg);
285                         else if (cmsg->cmsg_type == SO_RXQ_OVFL)
286                                 dropcnt[can_handler.socket] = *(__u32 *)CMSG_DATA(cmsg);
287         }
288
289         // Check if there is a new CAN frame dropped.
290         if (dropcnt[can_handler.socket] != last_dropcnt[can_handler.socket])
291         {
292                 __u32 frames = dropcnt[can_handler.socket] - last_dropcnt[can_handler.socket];
293                 WARNING(interface, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)",
294                         frames, (frames > 1)?"s":"", can_handler.device, dropcnt[can_handler.socket]);
295                         if (log)
296                                 WARNING(interface, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
297                                         frames, (frames > 1)?"s":"", can_handler.device, dropcnt[can_handler.socket]);
298
299                         last_dropcnt[can_handler.socket] = dropcnt[can_handler.socket];
300         }
301
302         can_message->has_id = true;
303         can_message->id = msg.id; // TODO make the parsing to extract id from data and only return left data into msg.msg_iov
304         can_message->has_data = true;
305         can_message->data = msg.msg_iov;
306 }
307
308 /***************************************************************************************/
309 /***************************************************************************************/
310 /**                                                                                   **/
311 /**                                                                                   **/
312 /**       SECTION: MANAGING EVENTS                                                    **/
313 /**                                                                                   **/
314 /**                                                                                   **/
315 /***************************************************************************************/
316 /***************************************************************************************/
317 static int connect_to_event_loop();
318
319 /*
320  * called on an event on the CAN bus
321  */
322 static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata)
323 {
324         openxc_CanMessage can_message;
325
326         /* read available data */
327         if ((revents & EPOLLIN) != 0)
328         {
329                 read_can(&can_message);
330 //              event_send();
331         }
332
333         /* check if error or hangup */
334         if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0)
335         {
336                 sd_event_source_unref(s);
337                 close(fd);
338                 connect_to_event_loop();
339         }
340
341         return 0;
342 }
343
344 /*
345  * get or create an event handler for the type
346  * TODO: implement function and handle retrieve or create an event as needed
347  */
348 static struct event *event_get(enum type type)
349 {
350
351 }
352
353 static struct event *event_of_id(int id)
354 {
355
356 }
357
358 /*****************************************************************************************/
359 /*****************************************************************************************/
360 /**                                                                                     **/
361 /**                                                                                     **/
362 /**        SECTION: BINDING VERBS IMPLEMENTATION                                        **/
363 /**                                                                                     **/
364 /**                                                                                     **/
365 /*****************************************************************************************/
366 /*****************************************************************************************/
367 /*
368  * Returns the type corresponding to the given name
369  */
370 static enum type type_of_name(const char *name)
371 {
372         enum type result;
373         if (name == NULL)
374                 return type_DEFAULT;
375         for (result = 0 ; result < type_size; result++)
376                 if (strcmp(type_NAMES[result], name) == 0)
377                         return result;
378         return type_INVALID;
379 }
380
381 /*
382  * extract a valid type from the request
383  */
384 static int get_type_for_req(struct afb_req req, enum type *type)
385 {
386         if ((*type = type_of_name(afb_req_value(req, "type"))) != type_INVALID)
387                 return 1;
388         afb_req_fail(req, "unknown-type", NULL);
389         return 0;
390 }
391
392 /*
393  * subscribe to notification of new CAN messages
394  *
395  * parameters of the subscription are:
396  *
397  *    TODO type: string:  choose between CAN and OBDII messages formats.
398  *
399  * returns an object with 2 fields:
400  *
401  *    name:   string:  the name of the event without its prefix
402  *    id:     integer: a numeric identifier of the event to be used for unsubscribing
403  */
404 static void subscribe(struct afb_req req)
405 {
406         enum type type;
407         const char *period;
408         struct event *event;
409         struct json_object *json;
410
411         if (get_type_for_req(req, &type))
412         {
413                 event = event_get(type);
414                 if (event == NULL)
415                         afb_req_fail(req, "out-of-memory", NULL);
416                 else if (afb_req_subscribe(req, event->event) != 0)
417                         afb_req_fail_f(req, "failed", "afb_req_subscribe returned an error: %m");
418                 else
419                 {
420                         json = json_object_new_object();
421                         json_object_object_add(json, "name", json_object_new_string(event->name));
422                         json_object_object_add(json, "id", json_object_new_int(event->id));
423                         afb_req_success(req, json, NULL);
424                 }
425         }
426 }
427
428 /*
429  * unsubscribe a previous subscription
430  *
431  * parameters of the unsubscription are:
432  *
433  *    id:   integer: the numeric identifier of the event as returned when subscribing
434  */
435 static void unsubscribe(struct afb_req req)
436 {
437         const char *id;
438         struct event *event;
439
440         id = afb_req_value(req, "id");
441         if (id == NULL)
442                 afb_req_fail(req, "missing-id", NULL);
443         else
444         {
445                 event = event_of_id(atoi(id));
446                 if (event == NULL)
447                         afb_req_fail(req, "bad-id", NULL);
448                 else
449                 {
450                         afb_req_unsubscribe(req, event->event);
451                         afb_req_success(req, NULL, NULL);
452                 }
453         }
454 }
455
456 static int connect_to_event_loop()
457 {
458         sd_event_source *source;
459         int rc;
460
461         retry(open_can_dev);
462
463         if (can_handler.socket < 0)
464         {
465                 return can_handler.socket;
466         }
467
468         rc = sd_event_add_io(afb_daemon_get_event_loop(interface->daemon), &source, can_handler.socket, EPOLLIN, on_event, NULL);
469         if (rc < 0)
470         {
471                 close(can_handler.socket);
472                 ERROR(interface, "Can't connect CAN bus %s to the event loop", can_handler.device);
473         } else
474         {
475                 NOTICE(interface, "Connected CAN bus %s to the event loop", can_handler.device);
476         }
477
478         return rc;
479 }
480
481
482 // TODO: Have to change session management flag to AFB_SESSION_CHECK to use token auth
483 static const struct afb_verb_desc_v1 verbs[]=
484 {
485   { .name= "subscribe",    .session= AFB_SESSION_NONE, .callback= subscribe,    .info= "subscribe to notification of CAN bus messages." },
486   { .name= "unsubscribe",  .session= AFB_SESSION_NONE, .callback= unsubscribe,  .info= "unsubscribe a previous subscription." },
487         {NULL}
488 };
489
490 static const struct afb_binding binding_desc = {
491         .type = AFB_BINDING_VERSION_1,
492         .v1 = {
493                 .info = "CAN bus service",
494                 .prefix = "can",
495                 .verbs = verbs
496         }
497 };
498
499 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
500 {
501         interface = itf;
502
503         return &binding_desc;
504 }
505
506 int afbBindingV1ServiceInit(struct afb_service service)
507 {
508         return connect_to_event_loop();
509 }