+/*
+ * Read on CAN bus and return how much bytes has been read.
+ */
+static int read_can(openxc_CanMessage *can_message)
+{
+ int byte_read, maxdlen;
+ iov.iov_base = &can_frame;
+ msg.msg_name = &can_handler.txAddress;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &ctrlmsg;
+
+ byte_read = recvmsg(can_handler.socket, &msg, 0);
+
+ if (byte_read < 0)
+ {
+ if (errno == ENETDOWN) {
+ ERROR(interface, "%s: interface down", can_handler.device);
+ }
+ ERROR(interface, "Error reading CAN bus");
+ return -1;
+ }
+
+ // CAN frame integrity check
+ if ((size_t)byte_read == CAN_MTU)
+ maxdlen = CAN_MAX_DLEN;
+ else if ((size_t)byte_read == CANFD_MTU)
+ maxdlen = CANFD_MAX_DLEN;
+ else
+ {
+ ERROR(interface, "CAN frame incomplete");
+ return -2;
+ }
+
+ for ( cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg && (cmsg->cmsg_level == SOL_SOCKET);
+ cmsg = CMSG_NXTHDR(&msg,cmsg))
+ {
+ if (cmsg->cmsg_type == SO_TIMESTAMP)
+ tv = *(struct timeval *)CMSG_DATA(cmsg);
+ else if (cmsg->cmsg_type == SO_RXQ_OVFL)
+ dropcnt[can_handler.socket] = *(__u32 *)CMSG_DATA(cmsg);
+ }
+
+ // Check if there is a new CAN frame dropped.
+ if (dropcnt[can_handler.socket] != last_dropcnt[can_handler.socket])
+ {
+ __u32 frames = dropcnt[can_handler.socket] - last_dropcnt[can_handler.socket];
+ WARNING(interface, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)",
+ frames, (frames > 1)?"s":"", can_handler.device, dropcnt[can_handler.socket]);
+ if (log)
+ WARNING(interface, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
+ frames, (frames > 1)?"s":"", can_handler.device, dropcnt[can_handler.socket]);
+
+ last_dropcnt[can_handler.socket] = dropcnt[can_handler.socket];
+ }
+
+ can_message->has_id = true;
+ can_message->id = msg.id; // TODO make the parsing to extract id from data and only return left data into msg.msg_iov
+ can_message->has_data = true;
+ can_message->data = msg.msg_iov;
+}
+