Line data Source code
1 : // Copyright 2024 Accenture. 2 : 3 : #pragma once 4 : 5 : #include <can/transceiver/AbstractCANTransceiver.h> 6 : #include <io/MemoryQueue.h> 7 : 8 : #include <atomic> 9 : 10 : namespace can 11 : { 12 : 13 : /** 14 : * The implementation of ICanTransceiver using Linux SocketCAN stack 15 : * 16 : * The class assumes that all its methods except write(), the constructor, and the destructor are 17 : * run in the same task context. The deviation from this can result in unobvious UBs. 18 : * The transceiver state change detection is currently not implemented, 19 : * the corresponding callback is never called. 20 : */ 21 1 : class SocketCanTransceiver final : public AbstractCANTransceiver 22 : { 23 : public: 24 : /** 25 : * The transceiver device (static) configuration 26 : * 27 : * The instance of this class is provided to SocketCanTransceiver constructor 28 : * and is kept by reference during the lifetime of the constructed object. 29 : */ 30 : struct DeviceConfig 31 : { 32 : char const* name; /// SocketCAN interface name 33 : uint8_t busId; /// currently not used 34 : }; 35 : 36 : explicit SocketCanTransceiver(DeviceConfig const& config); 37 : 38 : SocketCanTransceiver(SocketCanTransceiver const&) = delete; 39 : SocketCanTransceiver& operator=(SocketCanTransceiver const&) = delete; 40 : 41 : ICanTransceiver::ErrorCode init() final; 42 : ICanTransceiver::ErrorCode open() final; 43 : ICanTransceiver::ErrorCode open(CANFrame const& frame) final; 44 : ICanTransceiver::ErrorCode close() final; 45 : void shutdown() final; 46 : 47 : ICanTransceiver::ErrorCode write(CANFrame const& frame) final; 48 : ICanTransceiver::ErrorCode write(CANFrame const& frame, ICANFrameSentListener& listener) final; 49 : 50 : ICanTransceiver::ErrorCode mute() final; 51 : ICanTransceiver::ErrorCode unmute() final; 52 : 53 : uint32_t getBaudrate() const final; 54 : uint16_t getHwQueueTimeout() const final; 55 : 56 : /** 57 : * This function is supposed to be run periodically. 58 : * The callbacks registered with the ICanTransceiver will be triggered from inside this call. 59 : */ 60 : void run(int maxSentPerRun, int maxReceivedPerRun); 61 : 62 : private: 63 : static size_t const TX_QUEUE_SIZE_BYTES = 512; 64 : 65 0 : struct FrameWithListener 66 : { 67 : CANFrame frame; 68 : ICANFrameSentListener* listener; 69 : }; 70 : 71 : using TxQueue = ::io::MemoryQueue<TX_QUEUE_SIZE_BYTES, sizeof(FrameWithListener)>; 72 : 73 : // these functions are making system calls and shall be signal-masked 74 : void guardedOpen(); 75 : void guardedClose(); 76 : void guardedRun(int maxSentPerRun, int maxReceivedPerRun); 77 : 78 : TxQueue _txQueue; 79 : ::io::MemoryQueueReader<TxQueue> _txReader; 80 : ::io::MemoryQueueWriter<TxQueue> _txWriter; 81 : 82 : DeviceConfig const& _config; 83 : 84 : int _fileDescriptor; 85 : 86 : ::std::atomic_bool _writable; 87 : }; 88 : 89 : } // namespace can