socketcan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2018 UAVCAN Team
3  *
4  * Distributed under the MIT License, available in the file LICENSE.
5  *
6  */
7 
8 // This is needed to enable necessary declarations in sys/
9 #ifndef _GNU_SOURCE
10 # define _GNU_SOURCE
11 #endif
12 
13 #include <net/if.h>
14 #include "socketcan.h"
15 #include <poll.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/ioctl.h>
19 #include <linux/can.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 
25 {
26  const int out = -abs(errno);
27  if (out < 0)
28  {
29  if (out >= INT16_MIN)
30  {
31  return (int16_t)out;
32  }
33  else
34  {
35  return INT16_MIN;
36  }
37  }
38  else
39  {
40  assert(false); // Requested an error when errno is zero?
41  return INT16_MIN;
42  }
43 }
44 
45 int16_t socketcanInit(SocketCANInstance* out_ins, const char* can_iface_name)
46 {
47  const size_t iface_name_size = strlen(can_iface_name) + 1;
48  if (iface_name_size > IFNAMSIZ)
49  {
50  goto fail0;
51  }
52 
53  const int fd = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW); // NOLINT
54  if (fd < 0)
55  {
56  goto fail0;
57  }
58 
59  struct ifreq ifr;
60  memset(&ifr, 0, sizeof(ifr));
61  memcpy(ifr.ifr_name, can_iface_name, iface_name_size);
62 
63  const int ioctl_result = ioctl(fd, SIOCGIFINDEX, &ifr);
64  if (ioctl_result < 0)
65  {
66  goto fail1;
67  }
68 
69  struct sockaddr_can addr;
70  memset(&addr, 0, sizeof(addr));
71  addr.can_family = AF_CAN;
72  addr.can_ifindex = ifr.ifr_ifindex;
73 
74  const int bind_result = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
75  if (bind_result < 0)
76  {
77  goto fail1;
78  }
79 
80  out_ins->fd = fd;
81  return 0;
82 
83 fail1:
84  (void)close(fd);
85 fail0:
86  return getErrorCode();
87 }
88 
90 {
91  const int close_result = close(ins->fd);
92  ins->fd = -1;
93  return (int16_t)((close_result == 0) ? 0 : getErrorCode());
94 }
95 
96 int16_t socketcanTransmit(SocketCANInstance* ins, const CanardCANFrame* frame, int32_t timeout_msec)
97 {
98  struct pollfd fds;
99  memset(&fds, 0, sizeof(fds));
100  fds.fd = ins->fd;
101  fds.events |= POLLOUT;
102 
103  const int poll_result = poll(&fds, 1, timeout_msec);
104  if (poll_result < 0)
105  {
106  return getErrorCode();
107  }
108  if (poll_result == 0)
109  {
110  return 0;
111  }
112  if (((uint32_t)fds.revents & (uint32_t)POLLOUT) == 0)
113  {
114  return -EIO;
115  }
116 
117  struct can_frame transmit_frame;
118  memset(&transmit_frame, 0, sizeof(transmit_frame));
119  transmit_frame.can_id = frame->id; // TODO: Map flags properly
120  transmit_frame.can_dlc = frame->data_len;
121  memcpy(transmit_frame.data, frame->data, frame->data_len);
122 
123  const ssize_t nbytes = write(ins->fd, &transmit_frame, sizeof(transmit_frame));
124  if (nbytes < 0)
125  {
126  return getErrorCode();
127  }
128  if ((size_t)nbytes != sizeof(transmit_frame))
129  {
130  return -EIO;
131  }
132 
133  return 1;
134 }
135 
136 int16_t socketcanReceive(SocketCANInstance* ins, CanardCANFrame* out_frame, int32_t timeout_msec)
137 {
138  struct pollfd fds;
139  memset(&fds, 0, sizeof(fds));
140  fds.fd = ins->fd;
141  fds.events |= POLLIN;
142 
143  const int poll_result = poll(&fds, 1, timeout_msec);
144  if (poll_result < 0)
145  {
146  return getErrorCode();
147  }
148  if (poll_result == 0)
149  {
150  return 0;
151  }
152  if (((uint32_t)fds.revents & (uint32_t)POLLIN) == 0)
153  {
154  return -EIO;
155  }
156 
157  struct can_frame receive_frame;
158  const ssize_t nbytes = read(ins->fd, &receive_frame, sizeof(receive_frame));
159  if (nbytes < 0)
160  {
161  return getErrorCode();
162  }
163  if ((size_t)nbytes != sizeof(receive_frame))
164  {
165  return -EIO;
166  }
167 
168  if (receive_frame.can_dlc > CAN_MAX_DLEN) // Appeasing Coverity Scan
169  {
170  return -EIO;
171  }
172 
173  out_frame->id = receive_frame.can_id; // TODO: Map flags properly
174  out_frame->data_len = receive_frame.can_dlc;
175  memcpy(out_frame->data, &receive_frame.data, receive_frame.can_dlc);
176 
177  return 1;
178 }
179 
181 {
182  return ins->fd;
183 }
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::CanFrame::id
uint32_t id
CAN ID with flags (above)
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:34
socketcanReceive
int16_t socketcanReceive(SocketCANInstance *ins, CanardCANFrame *out_frame, int32_t timeout_msec)
Definition: socketcan.c:136
socketcanGetSocketFileDescriptor
int socketcanGetSocketFileDescriptor(const SocketCANInstance *ins)
Definition: socketcan.c:180
uavcan::int16_t
std::int16_t int16_t
Definition: std.hpp:30
uavcan::int32_t
std::int32_t int32_t
Definition: std.hpp:31
socketcanTransmit
int16_t socketcanTransmit(SocketCANInstance *ins, const CanardCANFrame *frame, int32_t timeout_msec)
Definition: socketcan.c:96
SocketCANInstance::fd
int fd
Definition: socketcan.h:20
pyuavcan_v0.driver.socketcan.CAN_RAW
int CAN_RAW
Definition: socketcan.py:54
socketcanInit
int16_t socketcanInit(SocketCANInstance *out_ins, const char *can_iface_name)
Definition: socketcan.c:45
uavcan::CanFrame::data
uint8_t data[MaxDataLen]
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:35
frame
uavcan::CanFrame frame
Definition: can.cpp:78
getErrorCode
static int16_t getErrorCode()
Returns the current errno as negated int16_t.
Definition: socketcan.c:24
pyuavcan_v0.driver.socketcan.AF_CAN
int AF_CAN
Definition: socketcan.py:57
SocketCANInstance
Definition: socketcan.h:18
socketcan.h
socketcanClose
int16_t socketcanClose(SocketCANInstance *ins)
Definition: socketcan.c:89


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03