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>
30 #include <systemd/sd-event.h>
32 #include <json-c/json.h>
34 #include <afb/afb-binding.h>
35 #include <afb/afb-service-itf.h>
37 /*****************************************************************************************/
38 /*****************************************************************************************/
41 /** SECTION: GLOBAL VARIABLES **/
44 /*****************************************************************************************/
45 /*****************************************************************************************/
48 * Interface between the daemon and the binding
50 static const struct afb_binding_interface *interface;
53 * the type of position expected
55 * here, this type is the selection of protocol
60 type_DEFAULT = type_CAN,
64 #define type_size sizeof(enum type)-2
69 static const char * const type_NAMES[type_size] = {
79 struct sockaddr_can txAddress;
82 static struct can_handler can_handler = {
87 struct can_frame can_frame;
89 /*****************************************************************************************/
90 /*****************************************************************************************/
93 /** SECTION: UTILITY FUNCTIONS **/
96 /*****************************************************************************************/
97 /*****************************************************************************************/
100 * @brief Retry a function 3 times
102 * @param int function(): function that return an int wihtout any parameter
104 * @ return : 0 if ok, -1 if failed
107 static int retry( int(*func)());
108 static int retry( int(*func)())
123 /*****************************************************************************************/
124 /*****************************************************************************************/
127 /** SECTION: HANDLE CAN DEVICE **/
130 /*****************************************************************************************/
131 /*****************************************************************************************/
133 static int connect_to_event_loop();
136 * Parse the CAN frame data payload as a CANopen packet
137 * TODO: define can_frame_t
139 int can_frame_parse(canopen_frame_t *canopen_frame, struct can_frame *can_frame)
143 if (canopen_frame == NULL || can_frame == NULL)
148 bzero((void *)canopen_frame, sizeof(canopen_frame_t));
151 // Parse basic protocol fields
154 if (can_frame->can_id & CAN_EFF_FLAG)
156 canopen_frame->type = CANOPEN_FLAG_EXTENDED;
157 canopen_frame->id = can_frame->can_id & CAN_EFF_MASK;
161 canopen_frame->type = CANOPEN_FLAG_STANDARD;
162 canopen_frame->function_code = (can_frame->can_id & 0x00000780U) >> 7;
163 canopen_frame->id = (can_frame->can_id & 0x0000007FU);
166 canopen_frame->rtr = (can_frame->can_id & CAN_RTR_FLAG) ?
167 CANOPEN_FLAG_RTR : CANOPEN_FLAG_NORMAL;
169 canopen_frame->data_len = can_frame->can_dlc;
170 for (i = 0; i < can_frame->can_dlc; i++)
172 canopen_frame->payload.data[i] = can_frame->data[i];
176 // Parse payload data
180 switch (canopen_frame->function_code)
182 // ---------------------------------------------------------------------
183 // Network ManagemenT frame: Module Control
185 case CANOPEN_FC_NMT_MC:
189 // ---------------------------------------------------------------------
190 // Network ManagemenT frame: Node Guarding
192 case CANOPEN_FC_NMT_NG:
207 static int read_can()
211 byte_read = read(can_handler.socket, &can_frame, sizeof(struct can_frame));
215 ERROR(interface, "Error reading CAN bus");
219 if (byte_read < (int)sizeof(struct can_frame))
221 ERROR(interface, "CAN frame incomplete");
227 * called on an event on the CAN bus
229 static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata)
231 /* read available data */
232 if ((revents & EPOLLIN) != 0)
238 /* check if error or hangup */
239 if ((revents & (EPOLLERR|EPOLLRDHUP|EPOLLHUP)) != 0)
241 sd_event_source_unref(s);
243 connect_to_event_loop();
250 * open the can socket
252 static int open_can_dev()
255 struct timeval timeout = {1,0};
257 DEBUG(interface, "open_can_dev: CAN Handler socket : %d", can_handler.socket);
258 close(can_handler.socket);
260 can_handler.socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
261 if (can_handler.socket < 0)
263 ERROR(interface, "open_can_dev: socket could not be created");
267 // Set timeout for read
268 setsockopt(can_handler.socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
269 // Attempts to open a socket to CAN bus
270 strcpy(ifr.ifr_name, can_handler.device);
271 if(ioctl(can_handler.socket, SIOCGIFINDEX, &ifr) < 0)
273 ERROR(interface, "open_can_dev: ioctl failed");
277 can_handler.txAddress.can_family = AF_CAN;
278 can_handler.txAddress.can_ifindex = ifr.ifr_ifindex;
280 // And bind it to txAddress
281 if (bind(can_handler.socket, (struct sockaddr *)&can_handler.txAddress, sizeof(can_handler.txAddress)) < 0)
283 ERROR(interface, "open_can_dev: bind failed");
287 fcntl(can_handler.socket, F_SETFL, O_NONBLOCK);
291 close(can_handler.socket);
292 can_handler.socket = -1;
297 static int write_can()
301 rc = can_handler.socket;
305 * TODO change old hvac write can frame to generic on_event
307 can_frame.can_id = 0x30;
308 can_frame.can_dlc = 8;
309 can_frame.data[0] = 0;
310 can_frame.data[1] = 0;
311 can_frame.data[2] = 0;
312 can_frame.data[3] = 0xf0;
313 can_frame.data[4] = 0;
314 can_frame.data[5] = 1;
315 can_frame.data[6] = 0;
316 can_frame.data[7] = 0;
318 DEBUG(interface, "%s: %d %d [%02x %02x %02x %02x %02x %02x %02x %02x]\n",
319 can_handler.send_msg,
320 can_frame.can_id, can_frame.can_dlc,
321 can_frame.data[0], can_frame.data[1], can_frame.data[2], can_frame.data[3],
322 can_frame.data[4], can_frame.data[5], can_frame.data[6], can_frame.data[7]);
324 rc = sendto(can_handler.socket, &can_frame, sizeof(struct can_frame), 0,
325 (struct sockaddr*)&can_handler.txAddress, sizeof(can_handler.txAddress));
328 ERROR(interface, "Sending CAN frame failed.");
333 ERROR(interface, "socket not initialized. Attempt to reopen can device socket.");
339 /***************************************************************************************/
340 /***************************************************************************************/
343 /** SECTION: MANAGING EVENTS **/
346 /***************************************************************************************/
347 /***************************************************************************************/
350 * get or create an event handler for the type
351 * TODO: implement function and handle retrieve or create an event as needed
353 static struct event *event_get(enum type type)
358 static struct event *event_of_id(int id)
363 /*****************************************************************************************/
364 /*****************************************************************************************/
367 /** SECTION: BINDING VERBS IMPLEMENTATION **/
370 /*****************************************************************************************/
371 /*****************************************************************************************/
373 * Returns the type corresponding to the given name
375 static enum type type_of_name(const char *name)
380 for (result = 0 ; result < type_size; result++)
381 if (strcmp(type_NAMES[result], name) == 0)
387 * extract a valid type from the request
389 static int get_type_for_req(struct afb_req req, enum type *type)
391 if ((*type = type_of_name(afb_req_value(req, "type"))) != type_INVALID)
393 afb_req_fail(req, "unknown-type", NULL);
398 * subscribe to notification of new CAN messages
400 * parameters of the subscription are:
402 * TODO type: string: choose between CAN and OBDII messages formats.
404 * returns an object with 2 fields:
406 * name: string: the name of the event without its prefix
407 * id: integer: a numeric identifier of the event to be used for unsubscribing
409 static void subscribe(struct afb_req req)
414 struct json_object *json;
416 if (get_type_for_req(req, &type))
418 event = event_get(type);
420 afb_req_fail(req, "out-of-memory", NULL);
421 else if (afb_req_subscribe(req, event->event) != 0)
422 afb_req_fail_f(req, "failed", "afb_req_subscribe returned an error: %m");
425 json = json_object_new_object();
426 json_object_object_add(json, "name", json_object_new_string(event->name));
427 json_object_object_add(json, "id", json_object_new_int(event->id));
428 afb_req_success(req, json, NULL);
434 * unsubscribe a previous subscription
436 * parameters of the unsubscription are:
438 * id: integer: the numeric identifier of the event as returned when subscribing
440 static void unsubscribe(struct afb_req req)
445 id = afb_req_value(req, "id");
447 afb_req_fail(req, "missing-id", NULL);
450 event = event_of_id(atoi(id));
452 afb_req_fail(req, "bad-id", NULL);
455 afb_req_unsubscribe(req, event->event);
456 afb_req_success(req, NULL, NULL);
461 static int connect_to_event_loop()
463 sd_event_source *source;
468 if (can_handler.socket < 0)
470 return can_handler.socket;
473 rc = sd_event_add_io(afb_daemon_get_event_loop(interface->daemon), &source, can_handler.socket, EPOLLIN, on_event, NULL);
476 close(can_handler.socket);
477 ERROR(interface, "Can't connect CAN bus %s to the event loop", can_handler.device);
480 NOTICE(interface, "Connected CAN bus %s to the event loop", can_handler.device);
487 // TODO: Have to change session management flag to AFB_SESSION_CHECK to use token auth
488 static const struct afb_verb_desc_v1 verbs[]=
490 { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." },
491 { .name= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info= "unsubscribe a previous subscription." },
495 static const struct afb_binding binding_desc = {
496 .type = AFB_BINDING_VERSION_1,
498 .info = "CAN bus service",
504 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
508 return &binding_desc;
511 int afbBindingV1ServiceInit(struct afb_service service)
513 return connect_to_event_loop();