2 * @copyright Copyright (c) 2017-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.
18 #include "can_hal_core.h"
19 #include "can_hal_internal.h"
20 #include "can_hal_frameworkunifiedlog.h"
21 #include "can_hal_stm.h"
23 #include "can_mng_api.h"
25 #include <native_service/ns_message_center_if.h>
26 #include <native_service/frameworkunified_framework_if.h>
27 #include <native_service/frameworkunified_multithreading.h>
32 static CanCtlApiObj g_driver_obj; // can driver handler
34 typedef struct MessageWrapper {
41 CANHAL_FRAME_SF = 0x00,
44 CANHAL_FRAME_NONE = 0xFF,
47 // Declaration of the local functions
48 static EFrameworkunifiedStatus CanSendData(HANDLE h_app);
49 static UINT8 PackageSendData(const CanMessage *send_msg,
51 static UINT8 PackageRecvData(const UINT8 *recv_data, CanMessage *message);
52 static uint32_t GetCanId(const UINT8 *recv_data);
54 #define CANHAL_VALID_NUM_INDEX 0x00
55 #define CANHAL_CANID_HI_INDEX 0x00
56 #define CANHAL_CANID_LO_INDEX 0x01
57 #define CANHAL_DLC_INDEX 0x02
58 #define CANHAL_DATA_START_INDEX 0x03
60 #define CANHAL_RECV_DATA_LENGTH_INVALID 0xFF
62 #define CANHAL_RECV_DATABLOCK_SIZE (0x0B)
63 #define CANHAL_RECV_NTA_INDEX (0x03)
65 // Register table for framework callback
66 static const FrameworkunifiedProtocolCallbackHandler kCanHalPcbhs[] = {
67 { TX_INTERNAL, CanSendData },
70 void *CanHalPackMessage(HANDLE h_app, const void *msg, ssize_t msg_sz,
72 *packed_sz = msg_sz + sizeof(ssize_t) + sizeof(HANDLE);
73 void *p = malloc(*packed_sz);
76 // Set HANDLE to new buffer.
77 memcpy(_p, &h_app, sizeof(HANDLE));
78 // Set message size to new buffer
80 *(ssize_t *)_p = msg_sz;
81 // Set message body to new buffer
82 _p += (sizeof(ssize_t));
83 memcpy(_p, msg, msg_sz);
88 void CanHalUnPackMessage(void *packed, HANDLE *h_app, void **msg,
90 char *_p = (char *)packed;
91 *h_app = *(HANDLE *)_p;
93 *msg_sz = *((ssize_t *)_p);
94 _p += sizeof(ssize_t);
98 void CanHalDestroyPackedMessage(void *packed) {
102 // Start function of the receive thread
103 void *CanRecvRun(void *arg) {
104 UINT8 data_start_index = 0;
107 CanCtlApiCmd recv_cmd;
108 memset(&recv_cmd, 0x00, sizeof(CanCtlApiCmd));
109 CanMessage recv_data_can;
110 memset(&recv_data_can, 0x00, sizeof(recv_data_can));
111 enum CanHalType *type = (enum CanHalType *)arg;
114 // call driver API to receive the can data
115 ret = CanCtlApiRcvCmd(&g_driver_obj, &recv_cmd);
116 if (CAN_CTL_RET_SUCCESS != ret) {
121 * Receive data in the following structure:
123 * BYTE 01 | num of can data |
125 * BYTE 02 | CAN ID (Hi) |
127 * BYTE 03 | CAN ID (Lo) |
131 * BYTE 05 | DATA #1 |
135 * BYTE 12 | DATA #8 |
137 * BYTE 13 | CAN ID (Hi) |
139 * BYTE 14 | CAN ID (Lo) |
143 * BYTE 16 | DATA #1 |
147 * BYTE 23 | DATA #8 |
154 * BYTE 0 for the invalid number of the can data
155 * CAN ID (Hi) and (Lo) combine for the CAN ID
156 * CAN ID (Hi) byte's low 7 bits is the high 7 bits of the CAN ID
157 * CAN ID (Lo) byte's high 4 bits is the low 4 bits of the CAN ID
158 * DLC for the length of the following data
159 * DATA #1 ~ #8 for the receive data, its actual length changes
160 * according to the previous DLC byte
162 UINT8 total_data_num = recv_cmd.data[CANHAL_VALID_NUM_INDEX];
163 data_start_index = 1;
165 for (loop_num = 0; loop_num < total_data_num; loop_num++) {
167 can_id = GetCanId(&(recv_cmd.data[data_start_index]));
170 // Return value of the PackageRecvData is the total length
171 // of one can data package, so add to the data_start_index
172 // for the next can data package.
173 ret = PackageRecvData(&(recv_cmd.data[data_start_index]),
175 if (CANHAL_RECV_DATA_LENGTH_INVALID == ret) {
178 data_start_index += ret;
179 CanHalReceiveNotify(*type, &(recv_data_can), sizeof(recv_data_can));
183 memset(&recv_cmd, 0x00, sizeof(CanCtlApiCmd));
190 // get can id from recive buffer
191 static uint32_t GetCanId(const UINT8 *recv_data) {
193 can_id = (recv_data[CANHAL_CANID_HI_INDEX] & 0x7F);
195 can_id |= ((recv_data[CANHAL_CANID_LO_INDEX] & 0xF0) >> 4);
199 static CANHAL_RET_API CanOpenCoreCAN(void) {
200 CanCtlRcvId recv_can_id;
201 memset(recv_can_id.id, 0xFF, sizeof(recv_can_id.id));
202 if (CAN_CTL_RET_SUCCESS != CanCtlApiOpen(&g_driver_obj))
203 return CANHAL_RET_ERR_ERR;
205 if (CAN_CTL_RET_SUCCESS != CanCtlApiSetRcvId(&g_driver_obj, &recv_can_id)) {
206 return CANHAL_RET_ERR_ERR;
209 return CANHAL_RET_NORMAL;
212 CANHAL_RET_API CanOpenCore(CanHalType type) {
213 CANHAL_RET_API ret = CANHAL_RET_ERR_ERR;
215 case CAN_HAL_TYPE_CAN:
216 ret = CanOpenCoreCAN();
225 // Initialize the sending thread
226 EFrameworkunifiedStatus CanSendThreadStart(HANDLE h_app) {
227 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusOK;
229 e_status = FrameworkunifiedAttachCallbacksToDispatcher(h_app,
230 FRAMEWORKUNIFIED_ANY_SOURCE,
232 _countof(kCanHalPcbhs));
233 if (e_status != eFrameworkunifiedStatusOK)
236 e_status = FrameworkunifiedGetMsgDataOfSize(h_app, &ptr, sizeof(ptr));
237 if (e_status != eFrameworkunifiedStatusOK)
240 *((HANDLE *)ptr) = FrameworkunifiedMcOpenSender(h_app, FrameworkunifiedGetAppName(h_app));
241 if (!(*(HANDLE *)ptr))
242 e_status = eFrameworkunifiedStatusFail;
248 // Clean the sending thread
249 EFrameworkunifiedStatus CanSendThreadStop(HANDLE h_app) {
250 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusOK;
252 e_status = FrameworkunifiedGetMsgDataOfSize(h_app, &ptr, sizeof(ptr));
253 if (e_status != eFrameworkunifiedStatusOK)
256 FrameworkunifiedMcClose(*((HANDLE*)ptr));
261 static CANHAL_RET_API CanCloseCoreCAN(void) {
262 CanCtlApiClose(&g_driver_obj);
263 return CANHAL_RET_NORMAL;
267 CANHAL_RET_API CanCloseCore(CanHalType type) {
268 CANHAL_RET_API ret = CANHAL_RET_NORMAL;
270 case CAN_HAL_TYPE_CAN:
271 ret = CanCloseCoreCAN();
272 if (ret != CANHAL_RET_NORMAL)
283 // Callback for the sending thread to send the can data
284 static EFrameworkunifiedStatus CanSendData(HANDLE h_app) {
286 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusOK;
290 void *send_msg = NULL;
291 HANDLE unpacked_h_app;
292 CanMessage *unpacked_msg;
295 send_msg = CanHalPackMessage(hb, (const void *)&mb, sizeof(mb), &sz);
297 return eFrameworkunifiedStatusFail;
299 e_status = FrameworkunifiedGetMsgDataOfSize(h_app, send_msg, sz, eSMRRelease);
300 if (eFrameworkunifiedStatusOK != e_status) {
301 if (eFrameworkunifiedStatusInvldBufSize == e_status) {
302 FrameworkunifiedClearMsgData(h_app);
304 return eFrameworkunifiedStatusFail;
307 CanHalUnPackMessage(send_msg, &unpacked_h_app,
308 (void **)&unpacked_msg, &unpacked_sz);
310 CanCtlApiCmd send_can_data;
311 memset(&send_can_data, 0, sizeof(CanCtlApiCmd));
312 send_can_data.data[CANHAL_VALID_NUM_INDEX] = 1;
313 ret = PackageSendData(unpacked_msg, &(send_can_data.data[1]));
314 send_can_data.len = ret + 1;
315 CanSendResult send_result;
316 send_result.can_id = unpacked_msg->can_id;
317 send_result.rid = unpacked_msg->rid;
319 if (CAN_CTL_RET_SUCCESS == CanCtlApiSndCmd(&g_driver_obj, &send_can_data)) {
320 send_result.result = CAN_SEND_RESULT_SUCCESS;
322 send_result.result = CAN_SEND_RESULT_FAILURE;
324 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Send status is %d.", send_result.result);
326 if (CANHAL_RET_NORMAL != CanHalSendStatus(CAN_HAL_TYPE_CAN,
327 unpacked_h_app, &send_result, sizeof(send_result))) {
328 CanHalDestroyPackedMessage(send_msg);
329 return eFrameworkunifiedStatusFail;
332 CanHalDestroyPackedMessage(send_msg);
333 return eFrameworkunifiedStatusOK;
337 * param [in] send_msg
338 * param [out] send_can_data
340 static UINT8 PackageSendData(const CanMessage *send_msg,
341 UINT8 *send_can_data) {
342 // package according to the rule of the data structure,
343 // refer to the line 108 and 109
344 send_can_data[CANHAL_CANID_HI_INDEX] = (send_msg->can_id & 0x7F0) >> 4;
345 send_can_data[CANHAL_CANID_LO_INDEX] = (send_msg->can_id & 0x0F) << 4;
346 send_can_data[CANHAL_DLC_INDEX] = send_msg->dlc;
347 memcpy(&(send_can_data[CANHAL_DATA_START_INDEX]),
350 return (send_msg->dlc + CANHAL_DATA_START_INDEX);
354 * param [in] recv_data
355 * param [out] message
357 static UINT8 PackageRecvData(const UINT8 *recv_data, CanMessage *message) {
358 if (CAN_NORMAL_MESSAGE_LEN < recv_data[CANHAL_DLC_INDEX]) {
359 // receive data's length is invalid
360 return CANHAL_RECV_DATA_LENGTH_INVALID;
362 // package according to the rule of the data structure,
363 // refer to the line 108 and 109
364 message->can_id = recv_data[CANHAL_CANID_HI_INDEX] & 0x7F;
365 message->can_id <<= 4;
366 message->can_id |= (recv_data[CANHAL_CANID_LO_INDEX] & 0xF0) >> 4;
367 message->dlc = recv_data[CANHAL_DLC_INDEX];
368 memcpy(message->data, &(recv_data[CANHAL_DATA_START_INDEX]), CAN_NORMAL_MESSAGE_LEN);
370 return CANHAL_RECV_DATABLOCK_SIZE;