1 | // Copyright (C) 2017 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef SOCKETCANBACKEND_H |
5 | #define SOCKETCANBACKEND_H |
6 | |
7 | #include <QtSerialBus/qcanbusframe.h> |
8 | #include <QtSerialBus/qcanbusdevice.h> |
9 | #include <QtSerialBus/qcanbusdeviceinfo.h> |
10 | |
11 | #include <QtCore/qsocketnotifier.h> |
12 | #include <QtCore/qstring.h> |
13 | #include <QtCore/qvariant.h> |
14 | |
15 | // The order of the following includes is mandatory, because some |
16 | // distributions use sa_family_t in can.h without including socket.h |
17 | #include <sys/socket.h> |
18 | #include <sys/uio.h> |
19 | #include <linux/can.h> |
20 | #include <sys/time.h> |
21 | |
22 | #include <memory> |
23 | |
24 | #ifndef CANFD_MTU |
25 | // CAN FD support was added by Linux kernel 3.6 |
26 | // For prior kernels we redefine the missing defines here |
27 | // they are taken from linux/can/raw.h & linux/can.h |
28 | |
29 | enum { |
30 | CAN_RAW_FD_FRAMES = 5 |
31 | }; |
32 | |
33 | #define CAN_MAX_DLEN 8 |
34 | #define CANFD_MAX_DLEN 64 |
35 | struct canfd_frame { |
36 | canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ |
37 | __u8 len; /* frame payload length in byte */ |
38 | __u8 flags; /* additional flags for CAN FD */ |
39 | __u8 __res0; /* reserved / padding */ |
40 | __u8 __res1; /* reserved / padding */ |
41 | __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8))); |
42 | }; |
43 | #define CAN_MTU (sizeof(struct can_frame)) |
44 | #define CANFD_MTU (sizeof(struct canfd_frame)) |
45 | |
46 | #endif |
47 | |
48 | QT_BEGIN_NAMESPACE |
49 | |
50 | class LibSocketCan; |
51 | |
52 | class SocketCanBackend : public QCanBusDevice |
53 | { |
54 | Q_OBJECT |
55 | public: |
56 | explicit SocketCanBackend(const QString &name); |
57 | ~SocketCanBackend(); |
58 | |
59 | bool open() override; |
60 | void close() override; |
61 | |
62 | void setConfigurationParameter(ConfigurationKey key, const QVariant &value) override; |
63 | |
64 | bool writeFrame(const QCanBusFrame &newData) override; |
65 | |
66 | QString interpretErrorFrame(const QCanBusFrame &errorFrame) override; |
67 | |
68 | static QCanBusDeviceInfo socketCanDeviceInfo(const QString &deviceName); |
69 | static QList<QCanBusDeviceInfo> interfaces(); |
70 | |
71 | void resetController() override; |
72 | bool hasBusStatus() const override; |
73 | CanBusStatus busStatus() override; |
74 | QCanBusDeviceInfo deviceInfo() const override; |
75 | |
76 | private Q_SLOTS: |
77 | void readSocket(); |
78 | |
79 | private: |
80 | void resetConfigurations(); |
81 | bool connectSocket(); |
82 | bool applyConfigurationParameter(ConfigurationKey key, const QVariant &value); |
83 | |
84 | int protocol = CAN_RAW; |
85 | canfd_frame m_frame; |
86 | sockaddr_can m_address; |
87 | msghdr m_msg; |
88 | iovec m_iov; |
89 | sockaddr_can m_addr; |
90 | char m_ctrlmsg[CMSG_SPACE(sizeof(timeval)) + CMSG_SPACE(sizeof(__u32))]; |
91 | |
92 | qint64 canSocket = -1; |
93 | QSocketNotifier *notifier = nullptr; |
94 | std::unique_ptr<LibSocketCan> libSocketCan; |
95 | QString canSocketName; |
96 | bool canFdOptionEnabled = false; |
97 | }; |
98 | |
99 | QT_END_NAMESPACE |
100 | |
101 | #endif // SOCKETCANBACKEND_H |
102 | |