1 /**
2  * CAN module object for Linux socketCAN.
3  *
4  * This file is a template for other microcontrollers.
5  *
6  * @file        CO_driver_target.h
7  * @ingroup     CO_driver
8  * @author      Janez Paternoster, Martin Wagner
9  * @copyright   2004 - 2015 Janez Paternoster, 2017 - 2020 Neuberger Gebaeudeautomation GmbH
10  *
11  *
12  * This file is part of CANopenNode, an opensource CANopen Stack.
13  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
14  * For more information on CANopen see <http://www.can-cia.org/>.
15  *
16  * Licensed under the Apache License, Version 2.0 (the "License");
17  * you may not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  *     http://www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an "AS IS" BASIS,
24  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 
30 #ifndef CO_DRIVER_TARGET_H
31 #define CO_DRIVER_TARGET_H
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif /* __cplusplus */
36 
37 
38 /**
39  * @name multi interface support
40  *
41  * Enable this to use interface combining at driver level. This
42  * adds functions to broadcast/selective transmit messages on the
43  * given interfaces as well as combining all received message into
44  * one queue.
45  *
46  * This is not intended to realize interface redundancy!!!
47  */
48 //#define CO_DRIVER_MULTI_INTERFACE
49 
50 /**
51  * @name CAN bus error reporting
52  *
53  * Enable this to add support for socketCAN error detection- and
54  * handling functions inside the driver. This is needed when you have
55  * CANopen with "0" connected nodes as a use case, as this is normally
56  * forbidden in CAN.
57  *
58  * you need to enable error reporting in your kernel driver using
59  * "ip link set canX type can berr-reporting on". Of course, the kernel
60  * driver for your hardware needs this functionallity to be implemented...
61  */
62 //#define CO_DRIVER_ERROR_REPORTING
63 
64 
65 #include "CO_driver_base.h"
66 #include "CO_notify_pipe.h"
67 
68 #ifdef CO_DRIVER_ERROR_REPORTING
69   #include "CO_error.h"
70 #endif /* CO_DRIVER_ERROR_REPORTING */
71 
72 /**
73  * socketCAN interface object
74  */
75 typedef struct {
76     const void         *CANdriverState;   /**< CAN Interface identifier */
77     char                ifName[IFNAMSIZ]; /**< CAN Interface name */
78     int                 fd;               /**< socketCAN file descriptor */
79 #ifdef CO_DRIVER_ERROR_REPORTING
80     CO_CANinterfaceErrorhandler_t errorhandler;
81 #endif
82 } CO_CANinterface_t;
83 
84 /**
85  * CAN module object. It may be different in different microcontrollers.
86  */
87 typedef struct{
88     /** List of can interfaces. From CO_CANmodule_init()/ one per CO_CANmodule_addInterface() call */
89     CO_CANinterface_t  *CANinterfaces;
90     uint32_t            CANinterfaceCount; /** interface count */
91     CO_CANrx_t         *rxArray;        /**< From CO_CANmodule_init() */
92     uint16_t            rxSize;         /**< From CO_CANmodule_init() */
93     struct can_filter  *rxFilter;       /**< socketCAN filter list, one per rx buffer */
94     uint32_t            rxDropCount;    /**< messages dropped on rx socket queue */
95     CO_CANtx_t         *txArray;        /**< From CO_CANmodule_init() */
96     uint16_t            txSize;         /**< From CO_CANmodule_init() */
97     volatile bool_t     CANnormal;      /**< CAN module is in normal mode */
98     void               *em;             /**< Emergency object */
99     CO_NotifyPipe_t    *pipe;           /**< Notification Pipe */
100     int                 fdEpoll;        /**< epoll FD */
101     int                 fdTimerRead;    /**< timer handle from CANrxWait() */
102 #ifdef CO_DRIVER_MULTI_INTERFACE
103     /**
104      * Lookup tables Cob ID to rx/tx array index. Only feasible for SFF Messages.
105      */
106     uint32_t            rxIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID]; /**< COB ID to index assignment */
107     uint32_t            txIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID]; /**< COB ID to index assignment */
108 #endif /* CO_DRIVER_MULTI_INTERFACE */
109 }CO_CANmodule_t;
110 
111 
112 #ifdef CO_DRIVER_MULTI_INTERFACE
113 /**
114  * Initialize CAN module object
115  *
116  * Function must be called in the communication reset section. CAN module must
117  * be in Configuration Mode before.
118  *
119  * @param CANmodule This object will be initialized.
120  * @param CANdriverState unused
121  * @param rxArray Array for handling received CAN messages
122  * @param rxSize Size of the above array. Must be equal to number of receiving CAN objects.
123  * @param txArray Array for handling transmitting CAN messages
124  * @param txSize Size of the above array. Must be equal to number of transmitting CAN objects.
125  * @param CANbitRate not supported in this driver. Needs to be set by OS
126  *
127  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT.
128  */
129 #else
130 /**
131  * Initialize CAN module object and open socketCAN connection.
132  *
133  * Function must be called in the communication reset section. CAN module must
134  * be in Configuration Mode before.
135  *
136  * @param CANmodule This object will be initialized.
137  * @param CANdriverState CAN module interface index (return value if_nametoindex(), NO pointer!).
138  * @param rxArray Array for handling received CAN messages
139  * @param rxSize Size of the above array. Must be equal to number of receiving CAN objects.
140  * @param txArray Array for handling transmitting CAN messages
141  * @param txSize Size of the above array. Must be equal to number of transmitting CAN objects.
142  * @param CANbitRate not supported in this driver. Needs to be set by OS
143  *
144  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or
145  * CO_ERROR_SYSCALL.
146  */
147 #endif /* CO_DRIVER_MULTI_INTERFACE */
148 CO_ReturnError_t CO_CANmodule_init(
149         CO_CANmodule_t         *CANmodule,
150         void                   *CANdriverState,
151         CO_CANrx_t              rxArray[],
152         uint16_t                rxSize,
153         CO_CANtx_t              txArray[],
154         uint16_t                txSize,
155         uint16_t                CANbitRate);
156 
157 #ifdef CO_DRIVER_MULTI_INTERFACE
158 
159 /**
160  * Add socketCAN interface to can driver
161  *
162  * Function must be called after CO_CANmodule_init.
163  *
164  * @param CANmodule This object will be initialized.
165  * @param CANdriverState CAN module interface index (return value if_nametoindex(), NO pointer!).
166  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
167  * CO_ERROR_SYSCALL or CO_ERROR_INVALID_STATE.
168  */
169 CO_ReturnError_t CO_CANmodule_addInterface(
170         CO_CANmodule_t         *CANmodule,
171         const void             *CANdriverState);
172 
173 #endif /* CO_DRIVER_MULTI_INTERFACE */
174 
175 
176 /**
177  * Configure CAN message receive buffer.
178  *
179  * Function configures specific CAN receive buffer. It sets CAN identifier
180  * and connects buffer with specific object. Function must be called for each
181  * member in _rxArray_ from CO_CANmodule_t.
182  *
183  * @param CANmodule This object.
184  * @param index Index of the specific buffer in _rxArray_.
185  * @param ident 11-bit standard CAN Identifier.
186  * @param mask 11-bit mask for identifier. Most usually set to 0x7FF.
187  * Received message (rcvMsg) will be accepted if the following
188  * condition is true: (((rcvMsgId ^ ident) & mask) == 0).
189  * @param rtr If true, 'Remote Transmit Request' messages will be accepted.
190  * @param object CANopen object, to which buffer is connected. It will be used as
191  * an argument to pFunct. Its type is (void), pFunct will change its
192  * type back to the correct object type.
193  * @param pFunct Pointer to function, which will be called, if received CAN
194  * message matches the identifier. It must be fast function.
195  *
196  * @return #CO_ReturnError_t: CO_ERROR_NO CO_ERROR_ILLEGAL_ARGUMENT or
197  * CO_ERROR_OUT_OF_MEMORY (not enough masks for configuration).
198  */
199 CO_ReturnError_t CO_CANrxBufferInit(
200         CO_CANmodule_t         *CANmodule,
201         uint16_t                index,
202         uint16_t                ident,
203         uint16_t                mask,
204         bool_t                  rtr,
205         void                   *object,
206         void                  (*pFunct)(void *object, const CO_CANrxMsg_t *message));
207 
208 #ifdef CO_DRIVER_MULTI_INTERFACE
209 
210 /**
211  * Check on which interface the last message for one message buffer was received
212  *
213  * It is in the responsibility of the user to check that this information is
214  * useful as some messages can be received at any time on any bus.
215  *
216  * @param CANmodule This object.
217  * @param ident 11-bit standard CAN Identifier.
218  * @param [out] CANdriverStateRx message was received on this interface
219  * @param [out] timestamp message was received at this time (system clock)
220  *
221  * @retval false message has never been received, therefore no base address
222  * and timestamp are available
223  * @retval true base address and timestamp are valid
224  */
225 bool_t CO_CANrxBuffer_getInterface(
226         CO_CANmodule_t         *CANmodule,
227         uint16_t                ident,
228         const void            **const CANdriverStateRx,
229         struct timespec        *timestamp);
230 
231 /**
232  * Set which interface should be used for message buffer transmission
233  *
234  * It is in the responsibility of the user to ensure that the correct interface
235  * is used. Some messages need to be transmitted on all interfaces.
236  *
237  * If given interface is unknown or NULL is used, a message is transmitted on
238  * all available interfaces.
239  *
240  * @param CANmodule This object.
241  * @param ident 11-bit standard CAN Identifier.
242  * @param CANdriverStateTx use this interface. NULL = not specified
243  *
244  * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
245  */
246 CO_ReturnError_t CO_CANtxBuffer_setInterface(
247         CO_CANmodule_t         *CANmodule,
248         uint16_t                ident,
249         const void             *CANdriverStateTx);
250 
251 #endif /* CO_DRIVER_MULTI_INTERFACE */
252 
253 
254 /**
255  * The same as #CO_CANsend(), but ensures that there is enough space remaining
256  * in the driver for more important messages.
257  *
258  * The default threshold is 50%, or at least 1 message buffer. If sending
259  * would violate those limits, #CO_ERROR_TX_OVERFLOW is returned and the
260  * message will not be sent.
261  *
262  * @param CANmodule This object.
263  * @param buffer Pointer to transmit buffer, returned by CO_CANtxBufferInit().
264  * Data bytes must be written in buffer before function call.
265  *
266  * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_TX_OVERFLOW, CO_ERROR_TX_BUSY or
267  * CO_ERROR_TX_PDO_WINDOW (Synchronous TPDO is outside window).
268  */
269 CO_ReturnError_t CO_CANCheckSend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer);
270 
271 
272 /**
273  * Functions receives CAN messages. It is blocking.
274  *
275  * This function can be used in two ways
276  * - automatic mode (call callback that is set by #CO_CANrxBufferInit() function)
277  * - manual mode (evaluate message filters, return received message)
278  *
279  * Both modes can be combined.
280  *
281  * @param CANmodule This object.
282  * @param fdTimer file descriptor with activated timeout. fd is not read after
283  *                expiring! -1 if not used.
284  * @param buffer [out] storage for received message or _NULL_
285  * @retval >= 0 index of received message in array set by #CO_CANmodule_init()
286  *         _rxArray_, copy available in _buffer_
287  * @retval -1 no message received
288  */
289 int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buffer);
290 
291 #ifdef __cplusplus
292 }
293 #endif /* __cplusplus */
294 
295 /** @} */
296 #endif
297