socketcan.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. /*
  2. * Copyright (C) 2014-2015 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. * Ilia Sheremet <illia.sheremet@gmail.com>
  4. */
  5. #pragma once
  6. #include <cassert>
  7. #include <cstdint>
  8. #include <queue>
  9. #include <vector>
  10. #include <map>
  11. #include <unordered_set>
  12. #include <memory>
  13. #include <algorithm>
  14. #include <fcntl.h>
  15. #include <sys/socket.h>
  16. #include <sys/ioctl.h>
  17. #include <net/if.h>
  18. #include <linux/can.h>
  19. #include <linux/can/raw.h>
  20. #include <poll.h>
  21. #include <uavcan/uavcan.hpp>
  22. #include <uavcan_linux/clock.hpp>
  23. #include <uavcan_linux/exception.hpp>
  24. namespace uavcan_linux
  25. {
  26. /**
  27. * SocketCan driver class keeps number of each kind of errors occurred since the object was created.
  28. */
  29. enum class SocketCanError
  30. {
  31. SocketReadFailure,
  32. SocketWriteFailure,
  33. TxTimeout
  34. };
  35. /**
  36. * Single SocketCAN socket interface.
  37. *
  38. * SocketCAN socket adapter maintains TX and RX queues in user space. At any moment socket's buffer contains
  39. * no more than 'max_frames_in_socket_tx_queue_' TX frames, rest is waiting in the user space TX queue; when the
  40. * socket produces loopback for the previously sent TX frame the next frame from the user space TX queue will
  41. * be sent into the socket.
  42. *
  43. * This approach allows to properly maintain TX timeouts (http://stackoverflow.com/questions/19633015/).
  44. * TX timestamping is implemented by means of reading RX timestamps of loopback frames (see "TX timestamping" on
  45. * linux-can mailing list, http://permalink.gmane.org/gmane.linux.can/5322).
  46. *
  47. * Note that if max_frames_in_socket_tx_queue_ is greater than one, frame reordering may occur (depending on the
  48. * unrderlying logic).
  49. *
  50. * This class is too complex and needs to be refactored later. At least, basic socket IO and configuration
  51. * should be extracted into a different class.
  52. */
  53. class SocketCanIface : public uavcan::ICanIface
  54. {
  55. static inline ::can_frame makeSocketCanFrame(const uavcan::CanFrame& uavcan_frame)
  56. {
  57. ::can_frame sockcan_frame { uavcan_frame.id& uavcan::CanFrame::MaskExtID, uavcan_frame.dlc, { } };
  58. (void)std::copy(uavcan_frame.data, uavcan_frame.data + uavcan_frame.dlc, sockcan_frame.data);
  59. if (uavcan_frame.isExtended())
  60. {
  61. sockcan_frame.can_id |= CAN_EFF_FLAG;
  62. }
  63. if (uavcan_frame.isErrorFrame())
  64. {
  65. sockcan_frame.can_id |= CAN_ERR_FLAG;
  66. }
  67. if (uavcan_frame.isRemoteTransmissionRequest())
  68. {
  69. sockcan_frame.can_id |= CAN_RTR_FLAG;
  70. }
  71. return sockcan_frame;
  72. }
  73. static inline uavcan::CanFrame makeUavcanFrame(const ::can_frame& sockcan_frame)
  74. {
  75. uavcan::CanFrame uavcan_frame(sockcan_frame.can_id & CAN_EFF_MASK, sockcan_frame.data, sockcan_frame.can_dlc);
  76. if (sockcan_frame.can_id & CAN_EFF_FLAG)
  77. {
  78. uavcan_frame.id |= uavcan::CanFrame::FlagEFF;
  79. }
  80. if (sockcan_frame.can_id & CAN_ERR_FLAG)
  81. {
  82. uavcan_frame.id |= uavcan::CanFrame::FlagERR;
  83. }
  84. if (sockcan_frame.can_id & CAN_RTR_FLAG)
  85. {
  86. uavcan_frame.id |= uavcan::CanFrame::FlagRTR;
  87. }
  88. return uavcan_frame;
  89. }
  90. struct TxItem
  91. {
  92. uavcan::CanFrame frame;
  93. uavcan::MonotonicTime deadline;
  94. uavcan::CanIOFlags flags = 0;
  95. std::uint64_t order = 0;
  96. TxItem(const uavcan::CanFrame& arg_frame, uavcan::MonotonicTime arg_deadline,
  97. uavcan::CanIOFlags arg_flags, std::uint64_t arg_order)
  98. : frame(arg_frame)
  99. , deadline(arg_deadline)
  100. , flags(arg_flags)
  101. , order(arg_order)
  102. { }
  103. bool operator<(const TxItem& rhs) const
  104. {
  105. if (frame.priorityLowerThan(rhs.frame))
  106. {
  107. return true;
  108. }
  109. if (frame.priorityHigherThan(rhs.frame))
  110. {
  111. return false;
  112. }
  113. return order > rhs.order;
  114. }
  115. };
  116. struct RxItem
  117. {
  118. uavcan::CanFrame frame;
  119. uavcan::MonotonicTime ts_mono;
  120. uavcan::UtcTime ts_utc;
  121. uavcan::CanIOFlags flags;
  122. RxItem()
  123. : flags(0)
  124. { }
  125. };
  126. const SystemClock& clock_;
  127. const int fd_;
  128. const unsigned max_frames_in_socket_tx_queue_;
  129. unsigned frames_in_socket_tx_queue_ = 0;
  130. std::uint64_t tx_frame_counter_ = 0; ///< Increments with every frame pushed into the TX queue
  131. std::map<SocketCanError, std::uint64_t> errors_;
  132. std::priority_queue<TxItem> tx_queue_; // TODO: Use pool allocator
  133. std::queue<RxItem> rx_queue_; // TODO: Use pool allocator
  134. std::unordered_multiset<std::uint32_t> pending_loopback_ids_; // TODO: Use pool allocator
  135. std::vector<::can_filter> hw_filters_container_;
  136. void registerError(SocketCanError e) { errors_[e]++; }
  137. void incrementNumFramesInSocketTxQueue()
  138. {
  139. assert(frames_in_socket_tx_queue_ < max_frames_in_socket_tx_queue_);
  140. frames_in_socket_tx_queue_++;
  141. }
  142. void confirmSentFrame()
  143. {
  144. if (frames_in_socket_tx_queue_ > 0)
  145. {
  146. frames_in_socket_tx_queue_--;
  147. }
  148. else
  149. {
  150. assert(0); // Loopback for a frame that we didn't send.
  151. }
  152. }
  153. bool wasInPendingLoopbackSet(const uavcan::CanFrame& frame)
  154. {
  155. if (pending_loopback_ids_.count(frame.id) > 0)
  156. {
  157. (void)pending_loopback_ids_.erase(frame.id);
  158. return true;
  159. }
  160. return false;
  161. }
  162. int write(const uavcan::CanFrame& frame) const
  163. {
  164. errno = 0;
  165. const ::can_frame sockcan_frame = makeSocketCanFrame(frame);
  166. const int res = ::write(fd_, &sockcan_frame, sizeof(sockcan_frame));
  167. if (res <= 0)
  168. {
  169. if (errno == ENOBUFS || errno == EAGAIN) // Writing is not possible atm, not an error
  170. {
  171. return 0;
  172. }
  173. return res;
  174. }
  175. if (res != sizeof(sockcan_frame))
  176. {
  177. return -1;
  178. }
  179. return 1;
  180. }
  181. /**
  182. * SocketCAN git show 1e55659ce6ddb5247cee0b1f720d77a799902b85
  183. * MSG_DONTROUTE is set for any packet from localhost,
  184. * MSG_CONFIRM is set for any pakcet of your socket.
  185. * Diff: https://git.ucsd.edu/abuss/linux/commit/1e55659ce6ddb5247cee0b1f720d77a799902b85
  186. * Man: https://www.kernel.org/doc/Documentation/networking/can.txt (chapter 4.1.6).
  187. */
  188. int read(uavcan::CanFrame& frame, uavcan::UtcTime& ts_utc, bool& loopback) const
  189. {
  190. auto iov = ::iovec();
  191. auto sockcan_frame = ::can_frame();
  192. iov.iov_base = &sockcan_frame;
  193. iov.iov_len = sizeof(sockcan_frame);
  194. struct Control
  195. {
  196. cmsghdr cm;
  197. std::uint8_t data[sizeof(::timeval)];
  198. };
  199. auto control = Control();
  200. auto msg = ::msghdr();
  201. msg.msg_iov = &iov;
  202. msg.msg_iovlen = 1;
  203. msg.msg_control = &control;
  204. msg.msg_controllen = sizeof(control);
  205. const int res = ::recvmsg(fd_, &msg, MSG_DONTWAIT);
  206. if (res <= 0)
  207. {
  208. return (res < 0 && errno == EWOULDBLOCK) ? 0 : res;
  209. }
  210. /*
  211. * Flags
  212. */
  213. loopback = (msg.msg_flags & static_cast<int>(MSG_CONFIRM)) != 0;
  214. if (!loopback && !checkHWFilters(sockcan_frame))
  215. {
  216. return 0;
  217. }
  218. frame = makeUavcanFrame(sockcan_frame);
  219. /*
  220. * Timestamp
  221. */
  222. const ::cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
  223. assert(cmsg != nullptr);
  224. if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP)
  225. {
  226. auto tv = ::timeval();
  227. (void)std::memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv)); // Copy to avoid alignment problems
  228. assert(tv.tv_sec >= 0 && tv.tv_usec >= 0);
  229. ts_utc = uavcan::UtcTime::fromUSec(std::uint64_t(tv.tv_sec) * 1000000ULL + tv.tv_usec);
  230. }
  231. else
  232. {
  233. assert(0);
  234. return -1;
  235. }
  236. return 1;
  237. }
  238. void pollWrite()
  239. {
  240. while (hasReadyTx())
  241. {
  242. const TxItem tx = tx_queue_.top();
  243. if (tx.deadline >= clock_.getMonotonic())
  244. {
  245. const int res = write(tx.frame);
  246. if (res == 1) // Transmitted successfully
  247. {
  248. incrementNumFramesInSocketTxQueue();
  249. if (tx.flags & uavcan::CanIOFlagLoopback)
  250. {
  251. (void)pending_loopback_ids_.insert(tx.frame.id);
  252. }
  253. }
  254. else if (res == 0) // Not transmitted, nor is it an error
  255. {
  256. break; // Leaving the loop, the frame remains enqueued for the next retry
  257. }
  258. else // Transmission error
  259. {
  260. registerError(SocketCanError::SocketWriteFailure);
  261. }
  262. }
  263. else
  264. {
  265. registerError(SocketCanError::TxTimeout);
  266. }
  267. // Removing the frame from the queue even if transmission failed
  268. tx_queue_.pop();
  269. }
  270. }
  271. void pollRead()
  272. {
  273. while (true)
  274. {
  275. RxItem rx;
  276. rx.ts_mono = clock_.getMonotonic(); // Monotonic timestamp is not required to be precise (unlike UTC)
  277. bool loopback = false;
  278. const int res = read(rx.frame, rx.ts_utc, loopback);
  279. if (res == 1)
  280. {
  281. assert(!rx.ts_utc.isZero());
  282. bool accept = true;
  283. if (loopback) // We receive loopback for all CAN frames
  284. {
  285. confirmSentFrame();
  286. rx.flags |= uavcan::CanIOFlagLoopback;
  287. accept = wasInPendingLoopbackSet(rx.frame); // Do we need to send this loopback into the lib?
  288. }
  289. if (accept)
  290. {
  291. rx.ts_utc += clock_.getPrivateAdjustment();
  292. rx_queue_.push(rx);
  293. }
  294. }
  295. else if (res == 0)
  296. {
  297. break;
  298. }
  299. else
  300. {
  301. registerError(SocketCanError::SocketReadFailure);
  302. break;
  303. }
  304. }
  305. }
  306. /**
  307. * Returns true if a frame accepted by HW filters
  308. */
  309. bool checkHWFilters(const ::can_frame& frame) const
  310. {
  311. if (!hw_filters_container_.empty())
  312. {
  313. for (auto& f : hw_filters_container_)
  314. {
  315. if (((frame.can_id & f.can_mask) ^ f.can_id) == 0)
  316. {
  317. return true;
  318. }
  319. }
  320. return false;
  321. }
  322. else
  323. {
  324. return true;
  325. }
  326. }
  327. public:
  328. /**
  329. * Takes ownership of socket's file descriptor.
  330. *
  331. * @ref max_frames_in_socket_tx_queue See a note in the class comment.
  332. */
  333. SocketCanIface(const SystemClock& clock, int socket_fd, int max_frames_in_socket_tx_queue = 2)
  334. : clock_(clock)
  335. , fd_(socket_fd)
  336. , max_frames_in_socket_tx_queue_(max_frames_in_socket_tx_queue)
  337. {
  338. assert(fd_ >= 0);
  339. }
  340. /**
  341. * Socket file descriptor will be closed.
  342. */
  343. virtual ~SocketCanIface()
  344. {
  345. UAVCAN_TRACE("SocketCAN", "SocketCanIface: Closing fd %d", fd_);
  346. (void)::close(fd_);
  347. }
  348. /**
  349. * Assumes that the socket is writeable
  350. */
  351. std::int16_t send(const uavcan::CanFrame& frame, const uavcan::MonotonicTime tx_deadline,
  352. const uavcan::CanIOFlags flags) override
  353. {
  354. tx_queue_.emplace(frame, tx_deadline, flags, tx_frame_counter_);
  355. tx_frame_counter_++;
  356. pollRead(); // Read poll is necessary because it can release the pending TX flag
  357. pollWrite();
  358. return 1;
  359. }
  360. /**
  361. * Will read the socket only if RX queue is empty.
  362. * Normally, poll() needs to be executed first.
  363. */
  364. std::int16_t receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic,
  365. uavcan::UtcTime& out_ts_utc, uavcan::CanIOFlags& out_flags) override
  366. {
  367. if (rx_queue_.empty())
  368. {
  369. pollRead(); // This allows to use the socket not calling poll() explicitly.
  370. if (rx_queue_.empty())
  371. {
  372. return 0;
  373. }
  374. }
  375. {
  376. const RxItem& rx = rx_queue_.front();
  377. out_frame = rx.frame;
  378. out_ts_monotonic = rx.ts_mono;
  379. out_ts_utc = rx.ts_utc;
  380. out_flags = rx.flags;
  381. }
  382. rx_queue_.pop();
  383. return 1;
  384. }
  385. /**
  386. * Performs socket read/write.
  387. * @param read Socket is readable
  388. * @param write Socket is writeable
  389. */
  390. void poll(bool read, bool write)
  391. {
  392. if (read)
  393. {
  394. pollRead(); // Read poll must be executed first because it may decrement frames_in_socket_tx_queue_
  395. }
  396. if (write)
  397. {
  398. pollWrite();
  399. }
  400. }
  401. bool hasReadyRx() const { return !rx_queue_.empty(); }
  402. bool hasReadyTx() const
  403. {
  404. return !tx_queue_.empty() && (frames_in_socket_tx_queue_ < max_frames_in_socket_tx_queue_);
  405. }
  406. std::int16_t configureFilters(const uavcan::CanFilterConfig* const filter_configs,
  407. const std::uint16_t num_configs) override
  408. {
  409. if (filter_configs == nullptr)
  410. {
  411. assert(0);
  412. return -1;
  413. }
  414. hw_filters_container_.clear();
  415. hw_filters_container_.resize(num_configs);
  416. for (unsigned i = 0; i < num_configs; i++)
  417. {
  418. const uavcan::CanFilterConfig& fc = filter_configs[i];
  419. hw_filters_container_[i].can_id = fc.id & uavcan::CanFrame::MaskExtID;
  420. hw_filters_container_[i].can_mask = fc.mask & uavcan::CanFrame::MaskExtID;
  421. if (fc.id & uavcan::CanFrame::FlagEFF)
  422. {
  423. hw_filters_container_[i].can_id |= CAN_EFF_FLAG;
  424. }
  425. if (fc.id & uavcan::CanFrame::FlagRTR)
  426. {
  427. hw_filters_container_[i].can_id |= CAN_RTR_FLAG;
  428. }
  429. if (fc.mask & uavcan::CanFrame::FlagEFF)
  430. {
  431. hw_filters_container_[i].can_mask |= CAN_EFF_FLAG;
  432. }
  433. if (fc.mask & uavcan::CanFrame::FlagRTR)
  434. {
  435. hw_filters_container_[i].can_mask |= CAN_RTR_FLAG;
  436. }
  437. }
  438. return 0;
  439. }
  440. /**
  441. * SocketCAN emulates the CAN filters in software, so the number of filters is virtually unlimited.
  442. * This method returns a constant value.
  443. */
  444. static constexpr unsigned NumFilters = 8;
  445. std::uint16_t getNumFilters() const override { return NumFilters; }
  446. /**
  447. * Returns total number of errors of each kind detected since the object was created.
  448. */
  449. std::uint64_t getErrorCount() const override
  450. {
  451. std::uint64_t ec = 0;
  452. for (auto& kv : errors_) { ec += kv.second; }
  453. return ec;
  454. }
  455. /**
  456. * Returns number of errors of each kind in a map.
  457. */
  458. const decltype(errors_) & getErrors() const { return errors_; }
  459. int getFileDescriptor() const { return fd_; }
  460. /**
  461. * Open and configure a CAN socket on iface specified by name.
  462. * @param iface_name String containing iface name, e.g. "can0", "vcan1", "slcan0"
  463. * @return Socket descriptor or negative number on error.
  464. */
  465. static int openSocket(const std::string& iface_name)
  466. {
  467. errno = 0;
  468. const int s = ::socket(PF_CAN, SOCK_RAW, CAN_RAW);
  469. if (s < 0)
  470. {
  471. return s;
  472. }
  473. class RaiiCloser
  474. {
  475. int fd_;
  476. public:
  477. RaiiCloser(int filedesc) : fd_(filedesc)
  478. {
  479. assert(fd_ >= 0);
  480. }
  481. ~RaiiCloser()
  482. {
  483. if (fd_ >= 0)
  484. {
  485. UAVCAN_TRACE("SocketCAN", "RaiiCloser: Closing fd %d", fd_);
  486. (void)::close(fd_);
  487. }
  488. }
  489. void disarm() { fd_ = -1; }
  490. } raii_closer(s);
  491. // Detect the iface index
  492. auto ifr = ::ifreq();
  493. if (iface_name.length() >= IFNAMSIZ)
  494. {
  495. errno = ENAMETOOLONG;
  496. return -1;
  497. }
  498. (void)std::strncpy(ifr.ifr_name, iface_name.c_str(), iface_name.length());
  499. if (::ioctl(s, SIOCGIFINDEX, &ifr) < 0 || ifr.ifr_ifindex < 0)
  500. {
  501. return -1;
  502. }
  503. // Bind to the specified CAN iface
  504. {
  505. auto addr = ::sockaddr_can();
  506. addr.can_family = AF_CAN;
  507. addr.can_ifindex = ifr.ifr_ifindex;
  508. if (::bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0)
  509. {
  510. return -1;
  511. }
  512. }
  513. // Configure
  514. {
  515. const int on = 1;
  516. // Timestamping
  517. if (::setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0)
  518. {
  519. return -1;
  520. }
  521. // Socket loopback
  522. if (::setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &on, sizeof(on)) < 0)
  523. {
  524. return -1;
  525. }
  526. // Non-blocking
  527. if (::fcntl(s, F_SETFL, O_NONBLOCK) < 0)
  528. {
  529. return -1;
  530. }
  531. }
  532. // Validate the resulting socket
  533. {
  534. int socket_error = 0;
  535. ::socklen_t errlen = sizeof(socket_error);
  536. (void)::getsockopt(s, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&socket_error), &errlen);
  537. if (socket_error != 0)
  538. {
  539. errno = socket_error;
  540. return -1;
  541. }
  542. }
  543. raii_closer.disarm();
  544. return s;
  545. }
  546. };
  547. /**
  548. * Multiplexing container for multiple SocketCAN sockets.
  549. * Uses ppoll() for multiplexing.
  550. *
  551. * When an interface becomes down/disconnected while the node is running,
  552. * the driver will silently exclude it from the IO loop and continue to run on the remaining interfaces.
  553. * When all interfaces become down/disconnected, the driver will throw @ref AllIfacesDownException
  554. * from @ref SocketCanDriver::select().
  555. * Whether a certain interface is down can be checked with @ref SocketCanDriver::isIfaceDown().
  556. */
  557. class SocketCanDriver : public uavcan::ICanDriver
  558. {
  559. class IfaceWrapper : public SocketCanIface
  560. {
  561. bool down_ = false;
  562. public:
  563. IfaceWrapper(const SystemClock& clock, int fd) : SocketCanIface(clock, fd) { }
  564. void updateDownStatusFromPollResult(const ::pollfd& pfd)
  565. {
  566. assert(pfd.fd == this->getFileDescriptor());
  567. if (!down_ && (pfd.revents & POLLERR))
  568. {
  569. int error = 0;
  570. ::socklen_t errlen = sizeof(error);
  571. (void)::getsockopt(pfd.fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&error), &errlen);
  572. down_ = error == ENETDOWN || error == ENODEV;
  573. UAVCAN_TRACE("SocketCAN", "Iface %d is dead; error %d", this->getFileDescriptor(), error);
  574. }
  575. }
  576. bool isDown() const { return down_; }
  577. };
  578. const SystemClock& clock_;
  579. std::vector<std::unique_ptr<IfaceWrapper>> ifaces_;
  580. public:
  581. /**
  582. * Reference to the clock object shall remain valid.
  583. */
  584. explicit SocketCanDriver(const SystemClock& clock)
  585. : clock_(clock)
  586. {
  587. ifaces_.reserve(uavcan::MaxCanIfaces);
  588. }
  589. /**
  590. * This function may return before deadline expiration even if no requested IO operations become possible.
  591. * This behavior makes implementation way simpler, and it is OK since libuavcan can properly handle such
  592. * early returns.
  593. * Also it can return more events than were originally requested by uavcan, which is also acceptable.
  594. */
  595. std::int16_t select(uavcan::CanSelectMasks& inout_masks,
  596. const uavcan::CanFrame* (&)[uavcan::MaxCanIfaces],
  597. uavcan::MonotonicTime blocking_deadline) override
  598. {
  599. // Detecting whether we need to block at all
  600. bool need_block = (inout_masks.write == 0); // Write queue is infinite
  601. for (unsigned i = 0; need_block && (i < ifaces_.size()); i++)
  602. {
  603. const bool need_read = inout_masks.read & (1 << i);
  604. if (need_read && ifaces_[i]->hasReadyRx())
  605. {
  606. need_block = false;
  607. }
  608. }
  609. if (need_block)
  610. {
  611. // Poll FD set setup
  612. ::pollfd pollfds[uavcan::MaxCanIfaces] = {};
  613. unsigned num_pollfds = 0;
  614. IfaceWrapper* pollfd_index_to_iface[uavcan::MaxCanIfaces] = { };
  615. for (unsigned i = 0; i < ifaces_.size(); i++)
  616. {
  617. if (!ifaces_[i]->isDown())
  618. {
  619. pollfds[num_pollfds].fd = ifaces_[i]->getFileDescriptor();
  620. pollfds[num_pollfds].events = POLLIN;
  621. if (ifaces_[i]->hasReadyTx() || (inout_masks.write & (1U << i)))
  622. {
  623. pollfds[num_pollfds].events |= POLLOUT;
  624. }
  625. pollfd_index_to_iface[num_pollfds] = ifaces_[i].get();
  626. num_pollfds++;
  627. }
  628. }
  629. // This is where we abort when the last iface goes down
  630. if (num_pollfds == 0)
  631. {
  632. throw AllIfacesDownException();
  633. }
  634. // Timeout conversion
  635. const std::int64_t timeout_usec = (blocking_deadline - clock_.getMonotonic()).toUSec();
  636. auto ts = ::timespec();
  637. if (timeout_usec > 0)
  638. {
  639. ts.tv_sec = timeout_usec / 1000000LL;
  640. ts.tv_nsec = (timeout_usec % 1000000LL) * 1000;
  641. }
  642. // Blocking here
  643. const int res = ::ppoll(pollfds, num_pollfds, &ts, nullptr);
  644. if (res < 0)
  645. {
  646. return res;
  647. }
  648. // Handling poll output
  649. for (unsigned i = 0; i < num_pollfds; i++)
  650. {
  651. pollfd_index_to_iface[i]->updateDownStatusFromPollResult(pollfds[i]);
  652. const bool poll_read = pollfds[i].revents & POLLIN;
  653. const bool poll_write = pollfds[i].revents & POLLOUT;
  654. pollfd_index_to_iface[i]->poll(poll_read, poll_write);
  655. }
  656. }
  657. // Writing the output masks
  658. inout_masks = uavcan::CanSelectMasks();
  659. for (unsigned i = 0; i < ifaces_.size(); i++)
  660. {
  661. if (!ifaces_[i]->isDown())
  662. {
  663. inout_masks.write |= std::uint8_t(1U << i); // Always ready to write if not down
  664. }
  665. if (ifaces_[i]->hasReadyRx())
  666. {
  667. inout_masks.read |= std::uint8_t(1U << i); // Readability depends only on RX buf, even if down
  668. }
  669. }
  670. // Return value is irrelevant as long as it's non-negative
  671. return ifaces_.size();
  672. }
  673. SocketCanIface* getIface(std::uint8_t iface_index) override
  674. {
  675. return (iface_index >= ifaces_.size()) ? nullptr : ifaces_[iface_index].get();
  676. }
  677. std::uint8_t getNumIfaces() const override { return ifaces_.size(); }
  678. /**
  679. * Adds one iface by name. Will fail if there are @ref MaxIfaces ifaces registered already.
  680. * @param iface_name E.g. "can0", "vcan1"
  681. * @return Negative on error, interface index on success.
  682. * @throws uavcan_linux::Exception.
  683. */
  684. int addIface(const std::string& iface_name)
  685. {
  686. if (ifaces_.size() >= uavcan::MaxCanIfaces)
  687. {
  688. return -1;
  689. }
  690. // Open the socket
  691. const int fd = SocketCanIface::openSocket(iface_name);
  692. if (fd < 0)
  693. {
  694. return fd;
  695. }
  696. // Construct the iface - upon successful construction the iface will take ownership of the fd.
  697. try
  698. {
  699. ifaces_.emplace_back(new IfaceWrapper(clock_, fd));
  700. }
  701. catch (...)
  702. {
  703. (void)::close(fd);
  704. throw;
  705. }
  706. UAVCAN_TRACE("SocketCAN", "New iface '%s' fd %d", iface_name.c_str(), fd);
  707. return ifaces_.size() - 1;
  708. }
  709. /**
  710. * Returns false if the specified interface is functioning, true if it became unavailable.
  711. */
  712. bool isIfaceDown(std::uint8_t iface_index) const
  713. {
  714. return ifaces_.at(iface_index)->isDown();
  715. }
  716. };
  717. }