socketcan.c 4.1 KB

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