2 * @copyright Copyright (c) 2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include "can_mng_api.h"
23 #include <sys/types.h>
26 #include <sys/ioctl.h>
32 #include <linux/can/raw.h>
36 #define DUMP_DIR "/var/local/lib/basesystem/nv/driver-can"
37 #define DUMP_RCVID "/var/local/lib/basesystem/nv/driver-can/dump_rcvid"
38 #define CAN_DATA_SIZE (sizeof(CanData))
40 static int fd_can = -1;
41 static struct sockaddr_can tx_address;
42 static CanCtlRcvId RcvId;
43 const char* device_name = "vcan0";
45 static UINT32 getData(CanCtlRcvId*, CanCtlApiCmd*);
46 static UINT32 getCanData(unsigned char*);
47 static UINT32 copyEnableCandata(UINT16* , unsigned char*, unsigned char*);
48 static UINT32 isOpendDriver(void);
50 UINT32 CanCtlApiOpen(CanCtlApiObj* pClientObj)
55 CAN_MNG_API_LOGT("FUNC IN");
57 /*----------------------------------------------------------------------*/
59 /*----------------------------------------------------------------------*/
60 if (pClientObj != NULL) {
61 memset(pClientObj, 0, sizeof(*pClientObj));
65 CAN_MNG_API_LOGT("Already Opened");
66 CAN_MNG_API_LOGT("FUNC OUT");
67 return CAN_CTL_RET_SUCCESS;
71 CAN_MNG_API_LOGT("open socket start");
72 struct ifreq ifr = {0};
73 fd_can = socket(PF_CAN, SOCK_RAW, CAN_RAW);
75 CAN_MNG_API_LOGT("open socket end");
77 CAN_MNG_API_LOGE("Socket Open Error.");
78 CAN_MNG_API_LOGE("(errno[%d]).", err_no);
79 return CAN_CTL_RET_ERR_ERR;
82 // ioctl(SIOCGIFINDEX)
83 strcpy(ifr.ifr_name, device_name);
84 ret = ioctl(fd_can, SIOCGIFINDEX, &ifr);
87 CAN_MNG_API_LOGE("ioctl(SIOCGIFINDEX) Error.");
88 CAN_MNG_API_LOGE("(errno[%d]).", err_no);
91 return CAN_CTL_RET_ERR_ERR;
95 tx_address.can_family = AF_CAN;
96 tx_address.can_ifindex = ifr.ifr_ifindex;
98 ret = bind(fd_can, (struct sockaddr *)&tx_address, sizeof(tx_address));
101 CAN_MNG_API_LOGE("Socket Bind Error.");
102 CAN_MNG_API_LOGE("(errno[%d]).", err_no);
108 // Initialize RcvId Map
109 memset(&RcvId, 0, sizeof(RcvId));
111 CAN_MNG_API_LOGT("FUNC OUT");
113 return CAN_CTL_RET_SUCCESS;
116 UINT32 CanCtlApiClose(CanCtlApiObj* pClientObj)
118 /*----------------------------------------------------------------------*/
120 /*----------------------------------------------------------------------*/
121 if (pClientObj != NULL) {
122 memset(pClientObj, 0, sizeof(*pClientObj));
129 // Initialize fd info
132 CAN_MNG_API_LOGT("FUNC OUT");
134 return CAN_CTL_RET_SUCCESS;
137 UINT32 CanCtlApiSndCmd(CanCtlApiObj* pClientObj, CanCtlApiCmd* pSndCmd)
140 printf("%s: call_id=0x%x len=%d\n",
141 __func__, pClientObj->call_id, pSndCmd->len);
142 for (i = 0; i < pSndCmd->len; i++) {
143 printf("[%d]0x%x ", i, pSndCmd->data[i]);
144 if ((i != 0) && ((i % 7) == 0))
153 CAN_MNG_API_LOGT("FUNC IN");
154 /*----------------------------------------------------------------------*/
155 /* Check Input Value */
156 /*----------------------------------------------------------------------*/
159 CAN_MNG_API_LOGE("%s(%p) invalid parameter.", __func__, pSndCmd);
160 return CAN_CTL_RET_ERR_PARAM;
163 ret = isOpendDriver();
164 if (ret != CAN_CTL_RET_SUCCESS) {
165 CAN_MNG_API_LOGE("Not Open Driver.");
166 return CAN_CTL_RET_ERR_ERR;
169 struct can_frame frame = {0};
171 frame.can_id = pSndCmd->data[1] & 0x7F;
173 frame.can_id |= (pSndCmd->data[2] & 0xF0) >> 4;
174 frame.can_dlc = pSndCmd->data[3];
175 frame.data[0] = pSndCmd->data[4];
176 frame.data[1] = pSndCmd->data[5];
177 frame.data[2] = pSndCmd->data[6];
178 frame.data[3] = pSndCmd->data[7];
179 frame.data[4] = pSndCmd->data[8];
180 frame.data[5] = pSndCmd->data[9];
181 frame.data[6] = pSndCmd->data[10];
182 frame.data[7] = pSndCmd->data[11];
184 CAN_MNG_API_LOGT("write() CanDataExtSendNotif start size = %d", (int)sizeof(frame));
185 ret = write(fd_can, &frame, sizeof(frame));
187 CAN_MNG_API_LOGE("write() ret = %d).", ret);
189 CAN_MNG_API_LOGT("write() CanDataExtSendNotif end");
191 CAN_MNG_API_LOGE("write() error(errno[%d]).", err_no);
192 return CAN_CTL_RET_ERR_ERR;
195 CAN_MNG_API_LOGT("FUNC OUT");
197 return CAN_CTL_RET_SUCCESS;
200 UINT32 CanCtlApiSetRcvId(CanCtlApiObj* pClientObj, CanCtlRcvId* pRcvId)
205 CAN_MNG_API_LOGT("FUNC IN");
206 /*----------------------------------------------------------------------*/
207 /* Check Input Value */
208 /*----------------------------------------------------------------------*/
211 CAN_MNG_API_LOGE("%s(%p) invalid parameter.", __func__, pRcvId);
212 return CAN_CTL_RET_ERR_PARAM;
217 if (stat(DUMP_DIR, &st) != 0) {
218 ret = mkdir(DUMP_DIR, 0755);
221 CAN_MNG_API_LOGE("Can not Created RcvId Dump dir.");
222 return CAN_CTL_RET_ERR_ERR;
224 CAN_MNG_API_LOGT("fopen(DUMP_RCVID) start");
225 fp = fopen(DUMP_RCVID, "wb");
226 CAN_MNG_API_LOGT("fopen(DUMP_RCVID) end");
228 CAN_MNG_API_LOGE("Can not Opened RcvId Dump file.");
229 return CAN_CTL_RET_ERR_ERR;
232 CAN_MNG_API_LOGT("fwrite(pRcvId) start");
233 nmemb = fwrite(pRcvId, sizeof(CanCtlRcvId), 1, fp);
234 CAN_MNG_API_LOGT("fwrite(pRcvId) end");
236 CAN_MNG_API_LOGE("RcvId Dump file write error.");
238 return CAN_CTL_RET_ERR_ERR;
241 CAN_MNG_API_LOGT("fclose() start");
243 CAN_MNG_API_LOGT("fclose() end");
245 CAN_MNG_API_LOGT("FUNC OUT");
247 return CAN_CTL_RET_SUCCESS;
250 UINT32 CanCtlApiRcvCmd(CanCtlApiObj* pClientObj, CanCtlApiCmd* pRcvCmd)
255 CanCtlRcvId InitialRcvId;
260 CAN_MNG_API_LOGT("FUNC IN");
261 /*----------------------------------------------------------------------*/
262 /* Check Input Value */
263 /*----------------------------------------------------------------------*/
266 CAN_MNG_API_LOGE("%s(%p) invalid parameter.", __func__, pRcvCmd);
267 return CAN_CTL_RET_ERR_PARAM;
270 ret = isOpendDriver();
271 if (ret != CAN_CTL_RET_SUCCESS) {
272 CAN_MNG_API_LOGE("Not Open Driver.");
273 return CAN_CTL_RET_ERR_ERR;
277 CAN_MNG_API_LOGT("fopen(DUMP_RCVID) start");
278 fp = fopen(DUMP_RCVID, "rb");
279 CAN_MNG_API_LOGT("fopen(DUMP_RCVID) end");
281 CAN_MNG_API_LOGE("Can not Opened RcvId Dump file.");
282 return CAN_CTL_RET_ERR_ERR;
285 CAN_MNG_API_LOGT("fread(RcvId) start");
286 nmemb = fread(&RcvId, sizeof(CanCtlRcvId), 1, fp);
287 CAN_MNG_API_LOGT("fread(RcvId) end");
289 CAN_MNG_API_LOGE("RcvId Dump file read error.");
291 return CAN_CTL_RET_ERR_ERR;
294 CAN_MNG_API_LOGT("fclose() start");
296 CAN_MNG_API_LOGT("fclose() end");
298 memset(&InitialRcvId.id, 0, sizeof(InitialRcvId.id));
300 if (memcmp(InitialRcvId.id, RcvId.id, sizeof(RcvId.id)) == 0) {
301 CAN_MNG_API_LOGE("No RecvId Maps.");
302 return CAN_CTL_RET_ERR_ERR;
305 enable_ret = getData(&RcvId, pRcvCmd);
307 if (enable_ret != CAN_CTL_RET_SUCCESS) {
308 CAN_MNG_API_LOGE("No data founds.");
312 CAN_MNG_API_LOGT("FUNC OUT");
314 return CAN_CTL_RET_SUCCESS;
317 static UINT32 getData(CanCtlRcvId* pRcvId, CanCtlApiCmd* pRcvCmd) {
322 unsigned char can_data[CAN_CTL_CMD_LEN_MAX+1];
323 unsigned char enable_can_data[CAN_CTL_CMD_LEN_MAX];
324 unsigned char store_can_data[CAN_CTL_CMD_LEN_MAX];
328 UINT16 id_map[CAN_CTL_CMD_ID_HI_NUM];
330 CAN_MNG_API_LOGT("FUNC IN");
332 memcpy(id_map, pRcvId->id, sizeof(id_map));
334 memset(store_can_data, 0, sizeof(store_can_data));
335 scd = store_can_data;
338 memset(can_data, 0, sizeof(can_data));
339 memset(enable_can_data, 0, sizeof(enable_can_data));
340 ret = getCanData(can_data);
341 if (ret != CAN_CTL_RET_SUCCESS) {
342 // In case of error, read next data
343 CAN_MNG_API_LOGE("getCanData error.");
347 // Extract data of "CAN data extended reception notification 4"
348 copy_cnt = copyEnableCandata(id_map, can_data, enable_can_data);
353 // Store in work buffer
354 for (i = 0; i < copy_cnt; i++) {
355 if (total_cnt >= CAN_CTL_MAX_RCV_CAN_SIZE) {
356 CAN_MNG_API_LOGE("buffer over");
359 memcpy(scd, &enable_can_data[CAN_DATA_SIZE * i], CAN_DATA_SIZE);
360 scd = scd + CAN_DATA_SIZE;
364 // Check work buffer overflow
365 if (total_cnt >= CAN_CTL_MAX_RCV_CAN_SIZE) {
366 CAN_MNG_API_LOGE("buffer over");
371 // If data exists, set and return
372 if (total_cnt != 0) {
373 pRcvCmd->len = 1 + (total_cnt * CAN_DATA_SIZE);
374 pRcvCmd->data[0] = total_cnt;
375 memcpy( &(pRcvCmd->data[1]), store_can_data, (total_cnt * CAN_DATA_SIZE));
377 // If there is no data, return with length 0
379 memset( &(pRcvCmd->data[0]), 0, sizeof(UINT8) * CAN_DAT_LEN_MAX );
380 CAN_MNG_API_LOGE("data not found");
383 CAN_MNG_API_LOGT("FUNC OUT");
385 return CAN_CTL_RET_SUCCESS;
388 static UINT32 getCanData(unsigned char *can_data) {
392 CAN_MNG_API_LOGT("FUNC IN");
394 CAN_MNG_API_LOGE("recvfrom start");
397 struct can_frame frame = {0};
398 socklen_t addrlen = sizeof(struct sockaddr_can);
399 nbytes = recvfrom(fd_can, &frame, sizeof(frame), 0, (struct sockaddr*)&tx_address, &addrlen);
401 CAN_MNG_API_LOGE("recvfrom end ret = %d",nbytes);
403 CAN_MNG_API_LOGE("Not Read CAN Driver(errno[%d]).", err_no);
404 return CAN_CTL_RET_ERR_ERR;
405 } else if (nbytes != CAN_MTU) {
406 CAN_MNG_API_LOGE("Receive Error size: %d.", nbytes);
407 return CAN_CTL_RET_ERR_ERR;
410 CAN_MNG_API_LOGT("Recvfrom CAN Data(start)");
411 can_data[0] = (frame.can_id & 0x7F0) >> 4;
412 can_data[1] = (frame.can_id & 0x0F) << 4;
413 can_data[2] = frame.can_dlc;
414 for (i = 0; i < frame.can_dlc; i++) {
415 can_data[3+i] = frame.data[i];
416 CAN_MNG_API_LOGE(" 0x%02x", frame.data[i]);
418 CAN_MNG_API_LOGT("");
419 CAN_MNG_API_LOGT("Recvfrom Data(end)");
421 CAN_MNG_API_LOGT("FUNC OUT");
422 return CAN_CTL_RET_SUCCESS;
425 static UINT32 copyEnableCandata(UINT16* id_map, unsigned char* can_data, unsigned char* enable_can_data) {
428 unsigned char* ecd = enable_can_data;
431 CAN_MNG_API_LOGT("FUNC IN");
432 // Search data of "CAN data extended reception notification 4"
434 val = can_data[1] >> 4; // Shift right 4 bits and determine search position
436 CAN_MNG_API_LOGE("data id =%x", id);
437 CAN_MNG_API_LOGE("data val=%x", val);
438 CAN_MNG_API_LOGE("file val=%x", id_map[id]);
440 // If the target data is found (If the bit is on ?)
441 if ((id_map[id] & (0x01 << val)) != 0) {
442 CAN_MNG_API_LOGT("matched.");
443 CAN_MNG_API_LOGE("id_map[%u]", id_map[id]);
445 // Store data in work buffer
446 memcpy(ecd, &can_data[0], CAN_DATA_SIZE);
450 CAN_MNG_API_LOGT("FUNC OUT");
454 UINT32 CanCtlApiRcvSpd(CanCtlApiObj* pClientObj, CanCtlApiCmd* pRcvCmd)
457 // If vendor needs the special implementation about receiving the vehicle speed,
458 // it should be implemented by vendor.
459 return CAN_CTL_RET_SUCCESS;
462 static UINT32 isOpendDriver() {
463 CAN_MNG_API_LOGT("FUNC IN");
466 CAN_MNG_API_LOGE("Not Open CAN Driver.");
467 return CAN_CTL_RET_ERR_ERR;
470 CAN_MNG_API_LOGT("FUNC OUT");
471 return CAN_CTL_RET_SUCCESS;