Added JSON conf file read and initialize CanBus
[apps/agl-service-can-low-level.git] / obsolete / ll-can-binding.cpp
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  * Author "Loic Collignon" <loic.collignon@iot.bzh>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/ioctl.h>
24 #include <net/if.h>
25 #include <linux/can.h>
26 #include <linux/can/raw.h>
27 #include <fcntl.h>
28 #include <systemd/sd-event.h>
29 #include <errno.h>
30 #include <vector>
31 #include <map>
32 #include <queue>
33 #include <string>
34 #include <functional>
35 #include <memory>
36
37
38 #include <json-c/json.h>
39 #include <openxc.pb.h>
40
41 #include <afb/afb-binding.h>
42 #include <afb/afb-service-itf.h>
43
44 #include "ll-can-binding.h"
45 #include "obd2.h"
46
47 /*************************************************************************/
48 /*************************************************************************/
49 /**                                                                     **/
50 /**                                                                     **/
51 /**        SECTION: UTILITY FUNCTIONS                                   **/
52 /**                                                                     **/
53 /**                                                                     **/
54 /*************************************************************************/
55 /*************************************************************************/
56
57 /*
58  * Browse chained list and return the one with specified id
59  *
60  * param uint32_t id : can arbitration identifier
61  *
62  * return can_event
63  */
64 static can_event *get_event_list_of_id(uint32_t id)
65 {
66         can_event *current;
67
68         /* create and return if lists not exists */
69         if (!can_events_list)
70         {
71                 can_events_list = (can_event*)calloc(1, sizeof(can_event));
72                 can_events_list->id = id;
73                 return can_events_list;
74         }
75
76         /* search for id */
77         current = can_events_list;
78         while(current)
79         {
80                 if (current->id == id)
81                         return current;
82                 if (!current->next)
83                 {
84                         current->next = (can_event*)calloc(1, sizeof(can_event));
85                         current->next->id = id;
86                         return current->next;
87                 }
88                 current = current->next;
89         }
90
91         return nullptr;
92 }
93
94 /*
95  * Take an id and return it into a char array
96  */
97 static char* create_name(uint32_t id)
98 {
99         char name[32];
100         size_t nchar;
101
102         nchar = (size_t)sprintf(name, "can_%u", id);
103         if (nchar > 0)
104         {
105                 char *result = (char*)malloc(nchar + 1);
106                 memcpy(result, name, nchar);
107                 result[nchar] = 0;
108                 return result;
109         }
110
111         return nullptr;
112 }
113
114 /*
115  * Create json object that will be pushed through event_loop to any subscriber
116  *
117  *  param : openxc_CanMessage structure complete with data to put into json
118  *  object.
119  *
120  *  return : json object
121  */
122 static json_object* create_json_from_openxc_CanMessage(event *event)
123 {
124         struct json_object *json;
125
126         /*
127          * TODO: process the openxc_CanMessage struct. Should be a call to a
128          * decoder function relative to that msg
129
130         openxc_CanMessage can_message;
131         can_message = event->can_message;
132          */
133
134         json = json_object_new_object();
135         json_object_object_add(json, "name", json_object_new_string(event->name));
136
137         return json;
138 }
139
140 /*************************************************************************/
141 /*************************************************************************/
142 /**                                                                     **/
143 /**                                                                     **/
144 /**        SECTION: HANDLE CAN DEVICE                                   **/
145 /**                                                                     **/
146 /**                                                                     **/
147 /*************************************************************************/
148 /*************************************************************************/
149
150 /*
151  * open the can socket
152  */
153 int CanBus::open()
154 {
155         const int canfd_on = 1;
156         struct ifreq ifr;
157         struct timeval timeout = {1, 0};
158
159         DEBUG(interface, "open_can_dev: CAN Handler socket : %d", socket);
160         if (socket >= 0)
161                 close(socket);
162
163         socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
164         if (socket < 0)
165         {
166                 ERROR(interface, "open_can_dev: socket could not be created");
167         }
168         else
169         {
170                 /* Set timeout for read */
171                 setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
172                 /* try to switch the socket into CAN_FD mode */
173                 if (setsockopt(socket, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)) < 0)
174                 {
175                         NOTICE(interface, "open_can_dev: Can not switch into CAN Extended frame format.");
176                         is_fdmode_on = false;
177                 } else {
178                         is_fdmode_on = true;
179                 }
180
181                 /* Attempts to open a socket to CAN bus */
182                 strcpy(ifr.ifr_name, device);
183                 if(ioctl(socket, SIOCGIFINDEX, &ifr) < 0)
184                         ERROR(interface, "open_can_dev: ioctl failed");
185                 else
186                 {
187                         txAddress.can_family = AF_CAN;
188                         txAddress.can_ifindex = ifr.ifr_ifindex;
189
190                         /* And bind it to txAddress */
191                         if (bind(socket, (struct sockaddr *)&txAddress, sizeof(txAddress)) < 0)
192                         {
193                                 ERROR(interface, "open_can_dev: bind failed");
194                         }
195                         else
196                         {
197                                 fcntl(socket, F_SETFL, O_NONBLOCK);
198                                 return 0;
199                         }
200                 }
201                 close(socket);
202                 socket = -1;
203         }
204         return -1;
205 }
206
207 /*
208  * TODO : test that socket is really opened
209  */
210 static int write_can()
211 {
212         ssize_t nbytes;
213         int rc;
214
215         rc = socket;
216         if (rc >= 0)
217         {
218 /*
219  * TODO change old hvac write can frame to generic on_event
220  */
221                 nbytes = sendto(socket, &canfd_frame, sizeof(struct canfd_frame), 0,
222                             (struct sockaddr*)&txAddress, sizeof(txAddress));
223                 if (nbytes < 0)
224                 {
225                         ERROR(interface, "write_can: Sending CAN frame failed.");
226                 }
227         }
228         else
229         {
230                 ERROR(interface, "write_can: socket not initialized. Attempt to reopen can device socket.");
231                 open_can_dev();
232         }
233         return rc;
234 }
235
236 /*
237  * Parse the CAN frame data payload as a CAN packet
238  * TODO: parse as an OpenXC Can Message. Don't translate as ASCII and put bytes
239  * directly into openxc_CanMessage
240  */
241 static int parse_can_frame(openxc_CanMessage *can_message, struct canfd_frame *canfd_frame, int maxdlen)
242 {
243         int i, len;
244         //size_t n_msg;
245
246         len = (canfd_frame->len > maxdlen) ? maxdlen : canfd_frame->len;
247
248         can_message->has_id = true;
249         if (canfd_frame->can_id & CAN_ERR_FLAG)
250                 can_message->id = canfd_frame->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG);
251         else if (canfd_frame->can_id & CAN_EFF_FLAG)
252         {
253                 can_message->has_frame_format = true;
254                 can_message->frame_format = openxc_CanMessage_FrameFormat_EXTENDED;
255                 can_message->id = canfd_frame->can_id & CAN_EFF_MASK;
256         } else
257         {
258                 can_message->has_frame_format = true;
259                 can_message->frame_format = openxc_CanMessage_FrameFormat_STANDARD;
260                 can_message->id = canfd_frame->can_id & CAN_SFF_MASK;
261         }
262
263         /* Don't know what to do with that for now as we haven't
264          * len fields in openxc_CanMessage struct
265
266          * standard CAN frames may have RTR enabled. There are no ERR frames with RTR
267         if (maxdlen == CAN_MAX_DLEN && canfd_frame->can_id & CAN_RTR_FLAG)
268         {
269                 // print a given CAN 2.0B DLC if it's not zero
270                 if (canfd_frame->len && canfd_frame->len <= CAN_MAX_DLC)
271                         buf[offset++] = hex_asc_upper[canfd_frame->len & 0xF];
272
273                 buf[offset] = 0;
274                 return nullptr;
275         }
276         */
277
278         /* Doesn't handle real canfd_frame for now
279         if (maxdlen == CANFD_MAX_DLEN)
280         {
281                 // add CAN FD specific escape char and flags
282                 canfd_frame->flags & 0xF;
283         } */
284
285         if (sizeof(canfd_frame->data) <= sizeof(can_message->data.bytes))
286         {
287                 for (i = 0; i < len; i++)
288                         can_message->data.bytes[i] = canfd_frame->data[i];
289                 return 0;
290         } else if (sizeof(canfd_frame->data) <= CAN_MAX_DLEN)
291         {
292                 ERROR(interface, "parse_can_frame: can_frame data too long to be stored into openxc_CanMessage data field");
293                 return -1;
294                 /* TODO create as many as needed openxc_CanMessage into an array to store all data from canfd_frame
295                 n_msg = CAN_MAX_DLEN / sizeof(canfd_frame->data.bytes);
296                 for (i = 0; i < len; i++)
297                         can_message->data.bytes[i] = canfd_frame->data[i]; */
298         } else
299         {
300                 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 ?");
301                 return -2;
302         }
303
304         /* You should not reach this return statement */
305         return -3;
306 }
307
308
309 /*
310  * Read on CAN bus and return how much bytes has been read.
311  */
312 static int read_can(openxc_CanMessage *can_message)
313 {
314         ssize_t nbytes;
315         int maxdlen;
316
317         /* Test that socket is really opened */
318         if ( socket_test() < 0)
319         {
320                 if (open_can_dev() < 0)
321                 {
322                         ERROR(interface, "read_can: Socket unavailable");
323                         return -1;
324                 }
325         }
326
327         nbytes = read(socket, &canfd_frame, CANFD_MTU);
328
329         if (nbytes == CANFD_MTU)
330         {
331                 DEBUG(interface, "read_can: Got an CAN FD frame with length %d", canfd_frame.len);
332         }
333         else if (nbytes == CAN_MTU)
334         {
335                 DEBUG(interface, "read_can: Got a legacy CAN frame with length %d", canfd_frame.len);
336         }
337         else
338         {
339                 if (errno == ENETDOWN)
340                         ERROR(interface, "read_can: %s interface down", device);
341                 ERROR(interface, "read_can: Error reading CAN bus");
342                 return -2;
343         }
344
345         /* CAN frame integrity check */
346         if ((size_t)nbytes == CAN_MTU)
347                 maxdlen = CAN_MAX_DLEN;
348         else if ((size_t)nbytes == CANFD_MTU)
349                 maxdlen = CANFD_MAX_DLEN;
350         else
351         {
352                 ERROR(interface, "read_can: CAN frame incomplete");
353                 return -3;
354         }
355
356         if (parse_can_frame(can_message, &canfd_frame, maxdlen))
357         {
358                 ERROR(interface, "read_can: Can't parse the can frame. ID: %i, DLC: %i, DATA: %s", 
359                       canfd_frame.can_id, canfd_frame.len, canfd_frame.data);
360                 return -4;
361         }
362
363         return 0;
364 }
365 /*************************************************************************/
366 /*************************************************************************/
367 /**                                                                     **/
368 /**                                                                     **/
369 /**       SECTION: MANAGING EVENTS                                      **/
370 /**                                                                     **/
371 /**                                                                     **/
372 /*************************************************************************/
373 /*************************************************************************/
374 static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata);
375
376 /*
377  * Get the event loop running.
378  * Will trigger on_event function on EPOLLIN event on socket
379  *
380  * Return 0 or positive value on success. Else negative value for failure.
381  */
382 static int connect_to_event_loop(CanBus &CanBus_handler)
383 {
384         sd_event *event_loop;
385         sd_event_source *source;
386         int rc;
387
388         if (CanBus_handler.socket < 0)
389         {
390                 return CanBus_handler.socket;
391         }
392
393         event_loop = afb_daemon_get_event_loop(interface->daemon);
394         rc = sd_event_add_io(event_loop, &source, CanBus_handler.socket, EPOLLIN, on_event, NULL);
395         if (rc < 0)
396         {
397                 CanBus_handler.close();
398                 ERROR(interface, "Can't connect CAN bus %s to the event loop", CanBus_handler.device);
399         } else
400         {
401                 NOTICE(interface, "Connected CAN bus %s to the event loop", CanBus_handler.device);
402         }
403
404         return rc;
405 }
406 /*
407  * Send all events
408  */
409 static void send_event()
410 {
411         can_event *current;
412         event *events;
413         json_object *object;
414
415         /* Browse can_events */
416         current = can_events_list;
417         while(current)
418         {
419                 /* Browse event for each can_events no matter what the id */
420                 events = current->events;
421                 while(events)
422                 {
423                         object = create_json_from_openxc_CanMessage(events);
424                         afb_event_push(events->afb_event, object);
425                         events = events->next;
426                 }
427                 current = current->next;
428         }
429 }
430
431 /*
432  * called on event on the CAN bus
433  */
434 static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata)
435 {
436         openxc_CanMessage can_message;
437
438         can_message = openxc_CanMessage_init_default;
439
440         /* read available data */
441         if ((revents & EPOLLIN) != 0)
442         {
443                 read_can(&can_message);
444                 send_event();
445         }
446
447         /* check if error or hangup */
448         if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0)
449         {
450                 sd_event_source_unref(s);
451                 close(fd);
452                 connect_to_event_loop();
453         }
454
455         return 0;
456 }
457
458 /*
459  * get or create an event handler for the type
460  */
461 static event *get_event(uint32_t id, enum type type)
462 {
463         event *event_elt;
464         can_event *list;
465
466         /* find the can list by id */
467         list = get_event_list_of_id(id);
468
469         /* make the new event */
470         event_elt = (event*)calloc(1, sizeof(event));
471         event_elt->next = event_elt;
472         list->events = event_elt;
473         event_elt->name = create_name(id);
474         event_elt->afb_event = afb_daemon_make_event(interface->daemon, event_elt->name);
475
476         return event_elt;
477 }
478
479 /*************************************************************************/
480 /*************************************************************************/
481 /**                                                                     **/
482 /**                                                                     **/
483 /**        SECTION: BINDING VERBS IMPLEMENTATION                        **/
484 /**                                                                     **/
485 /**                                                                     **/
486 /*************************************************************************/
487 /*************************************************************************/
488 /*
489  * Returns the type corresponding to the given name
490  */
491 static enum type type_of_name(const char *name)
492 {
493         enum type result;
494         if (name == NULL)
495                 return type_DEFAULT;
496         for (result = 0 ; (size_t)result < type_size; result++)
497                 if (strcmp(type_NAMES[result], name) == 0)
498                         return result;
499         return type_INVALID;
500 }
501
502 /*
503  * extract a valid type from the request
504  */
505 static int get_type_for_req(struct afb_req req, enum type *type)
506 {
507         if ((*type = type_of_name(afb_req_value(req, "type"))) != type_INVALID)
508                 return 1;
509         afb_req_fail(req, "unknown-type", NULL);
510         return 0;
511 }
512
513 static int subscribe_unsubscribe_sig(struct afb_req request, int subscribe, struct signal *sig)
514 {
515         if (!afb_event_is_valid(sig->event)) {
516                 if (!subscribe)
517                         return 1;
518                 sig->event = afb_daemon_make_event(afbitf->daemon, sig->name);
519                 if (!afb_event_is_valid(sig->event)) {
520                         return 0;
521                 }
522         }
523
524         if (((subscribe ? afb_req_subscribe : afb_req_unsubscribe)(request, sig->event)) < 0) {
525                 return 0;
526         }
527
528         return 1;
529 }
530
531 static int subscribe_unsubscribe_all(struct afb_req request, int subscribe)
532 {
533         int i, n, e;
534
535         n = sizeof OBD2_PIDS / sizeof * OBD2_PIDS;
536         e = 0;
537         for (i = 0 ; i < n ; i++)
538                 e += !subscribe_unsubscribe_sig(request, subscribe, &OBD2_PIDS[i]);
539         return e == 0;
540 }
541
542 static int subscribe_unsubscribe_name(struct afb_req request, int subscribe, const char *name)
543 {
544         struct signal *sig;
545
546         if (0 == strcmp(name, "*"))
547                 return subscribe_unsubscribe_all(request, subscribe);
548
549         sig = get_signals(name);
550         if (sig == NULL) {
551                 return 0;
552         }
553
554         return subscribe_unsubscribe_sig(request, subscribe, sig);
555 }
556
557 static void subscribe_unsubscribe(struct afb_req request, int subscribe)
558 {
559         int ok, i, n;
560         struct json_object *args, *a, *x;
561
562         /* makes the subscription/unsubscription */
563         args = afb_req_json(request);
564         if (args == NULL || !json_object_object_get_ex(args, "event", &a)) {
565                 ok = subscribe_unsubscribe_all(request, subscribe);
566         } else if (json_object_get_type(a) != json_type_array) {
567                 ok = subscribe_unsubscribe_name(request, subscribe, json_object_get_string(a));
568         } else {
569                 n = json_object_array_length(a);
570                 ok = 0;
571                 for (i = 0 ; i < n ; i++) {
572                         x = json_object_array_get_idx(a, i);
573                         if (subscribe_unsubscribe_name(request, subscribe, json_object_get_string(x)))
574                                 ok++;
575                 }
576                 ok = (ok == n);
577         }
578
579         /* send the report */
580         if (ok)
581                 afb_req_success(request, NULL, NULL);
582         else
583                 afb_req_fail(request, "error", NULL);
584 }
585
586 static void subscribe(struct afb_req request)
587 {
588         subscribe_unsubscribe(request, 1);
589 }
590
591 static void unsubscribe(struct afb_req request)
592 {
593         subscribe_unsubscribe(request, 0);
594 }
595
596 static const struct afb_verb_desc_v1 verbs[]=
597 {
598   { .name= "subscribe",    .session= AFB_SESSION_NONE, .callback= subscribe,    .info= "subscribe to notification of CAN bus messages." },
599   { .name= "unsubscribe",  .session= AFB_SESSION_NONE, .callback= unsubscribe,  .info= "unsubscribe a previous subscription." },
600         {NULL}
601 };
602
603 static const struct afb_binding binding_desc = {
604         .type = AFB_BINDING_VERSION_1,
605         .v1 = {
606                 .info = "CAN bus service",
607                 .prefix = "can",
608                 .verbs = verbs
609         }
610 };
611
612 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
613 {
614         interface = itf;
615
616         return &binding_desc;
617 }
618
619 int afbBindingV1ServiceInit(struct afb_service service)
620 {
621         std::ifstream fd_conf;
622         std::string fd_conf_content;
623         json_object jo_canbus;
624
625         /* Open JSON conf file */
626         /* TODO: can't use this method in c++ for now. Need to reimplement it ? */
627         jo_canbus = json_object_new_object();
628         fd_conf = afb_daemon_rootdir_open_locale(interface->daemon, "canbus.json", O_RDONLY, NULL);
629         if (fd_conf)
630         {
631                 fd_conf.seekg(0, std::ios::end);
632                 fd_conf_content.resize(fd_conf.tellg());
633                 fd_conf.seekg(0, std::ios::beg);
634                 fd_conf.read(&fd_conf_content[0], fd_conf_content.size());
635                 fd_conf.close();
636         }
637
638         jo_canbus = json_tokener_parse(&fd_conf_content);
639
640         CanBus CanBus_handler;
641         CanBus_handler.deviceName = json_object_get_string("deviceName")
642
643         /* Open CAN socket */
644         CanBus_handler.open();
645
646         return connect_to_event_loop(CanBus_handler);
647 }