canard_nuttx.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) 2016 UAVCAN Team
  3. *
  4. * Distributed under the MIT License, available in the file LICENSE.
  5. *
  6. */
  7. #include "canard_nuttx.h"
  8. #include <fcntl.h>
  9. #include <poll.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <nuttx/can/can.h>
  13. int canardNuttXInit(CanardNuttXInstance* out_ins, const char* can_iface_name)
  14. {
  15. const int fd = open(can_iface_name, O_RDWR | O_NONBLOCK);
  16. if (fd < 0)
  17. {
  18. return -1;
  19. }
  20. out_ins->fd = fd;
  21. return 0;
  22. }
  23. int canardNuttXClose(CanardNuttXInstance* ins)
  24. {
  25. const int close_result = close(ins->fd);
  26. ins->fd = -1;
  27. return close_result;
  28. }
  29. int canardNuttXTransmit(CanardNuttXInstance* ins, const CanardCANFrame* frame, int timeout_msec)
  30. {
  31. struct pollfd fds;
  32. memset(&fds, 0, sizeof(fds));
  33. fds.fd = ins->fd;
  34. fds.events |= POLLOUT;
  35. const int poll_result = poll(&fds, 1, timeout_msec);
  36. if (poll_result < 0)
  37. {
  38. return -1;
  39. }
  40. if (poll_result == 0)
  41. {
  42. return 0;
  43. }
  44. if ((fds.revents & POLLOUT) == 0)
  45. {
  46. return -1;
  47. }
  48. struct can_msg_s transmit_msg;
  49. memset(&transmit_msg, 0, sizeof(transmit_msg));
  50. transmit_msg.cm_hdr.ch_id = frame->id & CANARD_CAN_EXT_ID_MASK;
  51. transmit_msg.cm_hdr.ch_dlc = frame->data_len;
  52. transmit_msg.cm_hdr.ch_extid = (frame->id & CANARD_CAN_FRAME_EFF) != 0;
  53. memcpy(transmit_msg.cm_data, frame->data, frame->data_len);
  54. const size_t msg_len = CAN_MSGLEN(transmit_msg.cm_hdr.ch_dlc);
  55. const ssize_t nbytes = write(ins->fd, &transmit_msg, msg_len);
  56. if (nbytes < 0 || (size_t)nbytes != msg_len)
  57. {
  58. return -1;
  59. }
  60. return 1;
  61. }
  62. int canardNuttXReceive(CanardNuttXInstance* ins, CanardCANFrame* out_frame, int timeout_msec)
  63. {
  64. struct pollfd fds;
  65. memset(&fds, 0, sizeof(fds));
  66. fds.fd = ins->fd;
  67. fds.events |= POLLIN;
  68. const int poll_result = poll(&fds, 1, timeout_msec);
  69. if (poll_result < 0)
  70. {
  71. return -1;
  72. }
  73. if (poll_result == 0)
  74. {
  75. return 0;
  76. }
  77. if ((fds.revents & POLLIN) == 0)
  78. {
  79. return -1;
  80. }
  81. struct can_msg_s receive_msg;
  82. const ssize_t nbytes = read(ins->fd, &receive_msg, sizeof(receive_msg));
  83. if (nbytes < 0 || (size_t)nbytes < CAN_MSGLEN(0) || (size_t)nbytes > sizeof(receive_msg))
  84. {
  85. return -1;
  86. }
  87. out_frame->id = receive_msg.cm_hdr.ch_id;
  88. out_frame->data_len = receive_msg.cm_hdr.ch_dlc;
  89. memcpy(out_frame->data, receive_msg.cm_data, receive_msg.cm_hdr.ch_dlc);
  90. if (receive_msg.cm_hdr.ch_extid != 0)
  91. {
  92. out_frame->id |= CANARD_CAN_FRAME_EFF;
  93. }
  94. return 1;
  95. }
  96. int canardNuttXGetDeviceFileDescriptor(const CanardNuttXInstance* ins)
  97. {
  98. return ins->fd;
  99. }