Get diag manager's socket into subscription obj
[apps/agl-service-can-low-level.git] / CAN-binder / low-can-binding / can / can-message.cpp
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include "can-message.hpp"
19
20 #include <cstring>
21
22 #include "../binding/low-can-hat.hpp"
23
24 ///
25 /// @brief Class constructor
26 ///
27 /// Constructor about can_message_t class.
28 ///
29 can_message_t::can_message_t()
30         : maxdlen_{0},
31          id_{0},
32          length_{0},
33          format_{can_message_format_t::INVALID},
34          rtr_flag_{false},
35          flags_{0},
36          timestamp_{0},
37          sub_id_{-1}
38 {}
39
40 can_message_t::can_message_t(uint8_t maxdlen,
41         uint32_t id,
42         uint8_t length,
43         can_message_format_t format,
44         bool rtr_flag,
45         uint8_t flags,
46         std::vector<uint8_t>& data,
47         uint64_t timestamp)
48         :  maxdlen_{maxdlen},
49         id_{id},
50         length_{length},
51         format_{format},
52         rtr_flag_{rtr_flag},
53         flags_{flags},
54         data_{data},
55         timestamp_{timestamp},
56         sub_id_{-1}
57 {}
58
59 ///
60 /// @brief Retrieve id_ member value.
61 ///
62 /// @return id_ class member
63 ///
64 uint32_t can_message_t::get_id() const
65 {
66         return id_;
67 }
68
69 int can_message_t::get_sub_id() const
70 {
71         return sub_id_;
72 }
73
74 ///
75 /// @brief Retrieve RTR flag member.
76 ///
77 /// @return rtr_flags_ class member
78 ///
79 bool can_message_t::get_rtr_flag_() const
80 {
81         return rtr_flag_;
82 }
83
84 ///
85 /// @brief Retrieve format_ member value.
86 ///
87 /// @return format_ class member
88 ///
89 can_message_format_t can_message_t::get_format() const
90 {
91         if (format_ != can_message_format_t::STANDARD || format_ != can_message_format_t::EXTENDED)
92                 return can_message_format_t::INVALID;
93         return format_;
94 }
95
96 ///
97 /// @brief Retrieve flags_ member value.
98 ///
99 /// @return flags_ class member
100 ///
101 uint8_t can_message_t::get_flags() const
102 {
103         return flags_;
104 }
105
106 ///
107 /// @brief Retrieve data_ member value.
108 ///
109 /// @return pointer to the first element
110 ///  of class member data_
111 ///
112 const uint8_t* can_message_t::get_data() const
113 {
114         return data_.data();
115 }
116
117 ///
118 /// @brief Retrieve data_ member whole vector
119 ///
120 /// @return the vector as is
121 ///
122 const std::vector<uint8_t> can_message_t::get_data_vector() const
123 {
124         return data_;
125 }
126
127 ///
128 /// @brief Retrieve length_ member value.
129 ///
130 /// @return length_ class member
131 ///
132 uint8_t can_message_t::get_length() const
133 {
134         return length_;
135 }
136
137 void can_message_t::set_sub_id(int sub_id)
138 {
139         sub_id_ = sub_id;
140 }
141
142 uint64_t can_message_t::get_timestamp() const
143 {
144         return timestamp_;
145 }
146
147 void can_message_t::set_timestamp(uint64_t timestamp)
148 {
149         timestamp_ = timestamp;
150 }
151
152 ///
153 /// @brief Control whether the object is correctly initialized
154 ///  to be sent over the CAN bus
155 ///
156 /// @return true if object correctly initialized and false if not.
157 ///
158 bool can_message_t::is_correct_to_send()
159 {
160         if (id_ != 0 && length_ != 0 && format_ != can_message_format_t::INVALID)
161         {
162                 int i;
163                 for(i=0;i<CAN_MESSAGE_SIZE;i++)
164                         if(data_[i] != 0)
165                                 return true;
166         }
167         return false;
168 }
169
170 ///
171 /// @brief Set format_ member value.
172 ///
173 /// Preferred way to initialize these members by using
174 /// convert_from_canfd_frame method.
175 ///
176 /// @param[in] new_format - class member
177 ///
178 void can_message_t::set_format(const can_message_format_t new_format)
179 {
180         if(new_format == can_message_format_t::STANDARD || new_format == can_message_format_t::EXTENDED || new_format == can_message_format_t::INVALID)
181                 format_ = new_format;
182         else
183                 ERROR(binder_interface, "%s: Can set format, wrong format chosen", __FUNCTION__);
184 }
185
186 /// @brief Take a canfd_frame struct to initialize class members
187 ///
188 /// This is the preferred way to initialize class members.
189 ///
190 /// @param[in] frame - canfd_frame to convert coming from a read of CAN socket
191 /// @param[in] nbytes - bytes read from socket read operation.
192 ///
193 /// @return A can_message_t object fully initialized with canfd_frame values.
194 ///
195 can_message_t can_message_t::convert_from_frame(const struct canfd_frame& frame, size_t nbytes, uint64_t timestamp)
196 {
197         uint8_t maxdlen, length, flags = (uint8_t)NULL;
198         uint32_t id;
199         can_message_format_t format;
200         bool rtr_flag;
201         std::vector<uint8_t> data;
202
203         switch(nbytes)
204         {
205                 case CANFD_MTU:
206                         DEBUG(binder_interface, "%s: Got an CAN FD frame", __FUNCTION__);
207                         maxdlen = CANFD_MAX_DLEN;
208                         break;
209                 case CAN_MTU:
210                         DEBUG(binder_interface, "%s: Got a legacy CAN frame", __FUNCTION__);
211                         maxdlen = CAN_MAX_DLEN;
212                         break;
213                 default:
214                         ERROR(binder_interface, "%s: unsupported CAN frame", __FUNCTION__);
215                         break;
216         }
217
218         if (frame.can_id & CAN_ERR_FLAG)
219         {
220                 format = can_message_format_t::INVALID;
221                 id = frame.can_id & (CAN_ERR_MASK|CAN_ERR_FLAG);
222         }
223         else if (frame.can_id & CAN_EFF_FLAG)
224         {
225                 format = can_message_format_t::EXTENDED;
226                 id = frame.can_id & CAN_EFF_MASK;
227         }
228         else
229         {
230                 format = can_message_format_t::STANDARD;
231                 id = frame.can_id & CAN_SFF_MASK;
232         }
233
234         /* Overwrite length_ if RTR flags is detected.
235          * standard CAN frames may have RTR enabled. There are no ERR frames with RTR */
236         if (frame.can_id & CAN_RTR_FLAG)
237         {
238                 rtr_flag = true;
239                 if(frame.len && frame.len <= CAN_MAX_DLC)
240                 {
241                         if(rtr_flag)
242                                 length = frame.len& 0xF;
243                         else
244                         {
245                                 length = (frame.len > maxdlen) ? maxdlen : frame.len;
246                         }
247                 }
248         }
249         else
250         {
251                 length = (frame.len > maxdlen) ? maxdlen : frame.len;
252
253                 /* Flags field only present for CAN FD frames*/
254                 if(maxdlen == CANFD_MAX_DLEN)
255                                 flags = frame.flags & 0xF;
256
257                 if (data.capacity() < maxdlen)
258                         data.reserve(maxdlen);
259                                 int i;
260
261                         data.clear();
262                         /* maxdlen_ is now set at CAN_MAX_DLEN or CANFD_MAX_DLEN, respectively 8 and 64 bytes*/
263                         for(i=0;i<maxdlen;i++)
264                         {
265                                 data.push_back(frame.data[i]);
266                         };
267
268                 DEBUG(binder_interface, "%s: Found id: %X, format: %X, length: %X, data %02X%02X%02X%02X%02X%02X%02X%02X", __FUNCTION__,
269                                                                 id, (uint8_t)format, length, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
270         }
271
272         return can_message_t(maxdlen, id, length, format, rtr_flag, flags, data, timestamp);
273 }
274
275 can_message_t can_message_t::convert_from_frame(const struct can_frame& frame, size_t nbytes, uint64_t timestamp)
276 {
277         uint8_t maxdlen, length, flags = (uint8_t)NULL;
278         uint32_t id;
279         can_message_format_t format;
280         bool rtr_flag;
281         std::vector<uint8_t> data;
282
283         if(nbytes <= CAN_MTU)
284         {
285                         DEBUG(binder_interface, "%s: Got a legacy CAN frame", __FUNCTION__);
286                         maxdlen = CAN_MAX_DLEN;
287         }
288         else
289         {
290                         ERROR(binder_interface, "%s: unsupported CAN frame", __FUNCTION__);
291         }
292
293         if (frame.can_id & CAN_ERR_FLAG)
294         {
295                 format = can_message_format_t::INVALID;
296                 id = frame.can_id & (CAN_ERR_MASK|CAN_ERR_FLAG);
297         }
298         else if (frame.can_id & CAN_EFF_FLAG)
299         {
300                 format = can_message_format_t::EXTENDED;
301                 id = frame.can_id & CAN_EFF_MASK;
302         }
303         else
304         {
305                 format = can_message_format_t::STANDARD;
306                 id = frame.can_id & CAN_SFF_MASK;
307         }
308
309         /* Overwrite length_ if RTR flags is detected.
310          * standard CAN frames may have RTR enabled. There are no ERR frames with RTR */
311         if (frame.can_id & CAN_RTR_FLAG)
312         {
313                 rtr_flag = true;
314                 if(frame.can_dlc && frame.can_dlc <= CAN_MAX_DLC)
315                 {
316                         if(rtr_flag)
317                                 length = frame.can_dlc& 0xF;
318                         else
319                         {
320                                 length = (frame.can_dlc > maxdlen) ? maxdlen : frame.can_dlc;
321                         }
322                 }
323         }
324         else
325         {
326                 length = (frame.can_dlc > maxdlen) ? maxdlen : frame.can_dlc;
327
328                 if (data.capacity() < maxdlen)
329                         data.reserve(maxdlen);
330                                 int i;
331
332                         data.clear();
333                         /* maxdlen_ is now set at CAN_MAX_DLEN or CANFD_MAX_DLEN, respectively 8 and 64 bytes*/
334                         for(i=0;i<maxdlen;i++)
335                         {
336                                 data.push_back(frame.data[i]);
337                         };
338
339 //              DEBUG(binder_interface, "%s: Found id: %X, format: %X, length: %X, data %02X%02X%02X%02X%02X%02X%02X%02X", __FUNCTION__,
340 //                                                              id, (uint8_t)format, length, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
341         }
342
343         return can_message_t(maxdlen, id, length, format, rtr_flag, flags, data, timestamp);
344 }
345
346 ///
347 /// @brief Take all initialized class's members and build an
348 /// canfd_frame struct that can be use to send a CAN message over
349 /// the bus.
350 ///
351 /// @return canfd_frame struct built from class members.
352 ///
353 struct canfd_frame can_message_t::convert_to_canfd_frame()
354 {
355         canfd_frame frame;
356
357         if(is_correct_to_send())
358         {
359                 frame.can_id = get_id();
360                 frame.len = get_length();
361                 ::memcpy(frame.data, get_data(), length_);
362         }
363         else
364                 ERROR(binder_interface, "%s: can_message_t not correctly initialized to be sent", __FUNCTION__);
365
366         return frame;
367 }
368
369 struct can_frame can_message_t::convert_to_can_frame()
370 {
371         can_frame frame;
372
373         if(is_correct_to_send())
374         {
375                 frame.can_id = get_id();
376                 frame.can_dlc = get_length();
377                 ::memcpy(frame.data, get_data(), length_);
378         }
379         else
380                 ERROR(binder_interface, "%s: can_message_t not correctly initialized to be sent", __FUNCTION__);
381
382         return frame;
383 }