2 * @copyright Copyright (c) 2016-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.
17 #include "CAN_Delivery.h"
20 #include <native_service/frameworkunified_framework_if.h>
21 #include <peripheral_service/Canif_API.h>
26 #include "CAN_TxMsg.h"
27 #include "CAN_CommWatch.h"
28 #include "Canif_API_Local.h"
29 #include "API_Local_Common.h"
30 #include "Thread_Common.h"
32 static CAN_DeliveryEntryList g_map_delivery_list_can;
33 // Member of g_msg_rx_msg exist as long as communication exists.
34 static std::map<CANID, CanMessage *> g_can_rx_msg;
36 void CANDeliveryInit(void) {
37 g_map_delivery_list_can.clear();
41 static CanMessage *CANMsgFind(CANID k) {
42 std::map<CANID, CanMessage *>::iterator it;
44 it = g_can_rx_msg.find(k);
45 if (it == g_can_rx_msg.end())
50 static void CANMsgInsert(CANID k, CanMessage *msg) {
51 CanMessage *latest = CANMsgFind(k);
53 latest = new CanMessage();
55 g_can_rx_msg[k] = latest;
56 memcpy(latest, msg, sizeof(CanMessage));
59 static CAN_DeliveryEntryListIt CANDeliveryFind(CANID canid, std::string s) {
60 std::pair<CAN_DeliveryEntryListIt, CAN_DeliveryEntryListIt> range;
61 CAN_DeliveryEntryListPair p = std::make_pair(canid, s);
62 CAN_DeliveryEntryListIt it;
64 range = g_map_delivery_list_can.equal_range(canid);
65 for (it = range.first; it != range.second; ++it) {
73 it = g_map_delivery_list_can.end();
78 bool CANDeliveryInsert(CANID canid, std::string s) {
79 CAN_DeliveryEntryListIt it = CANDeliveryFind(canid, s);
80 CAN_DeliveryEntryListPair p = std::make_pair(canid, s);
81 bool inserted = false;
83 if (it == g_map_delivery_list_can.end()) {
84 g_map_delivery_list_can.insert(p);
91 static EFrameworkunifiedStatus CANDeliverySndCmdSingle(HANDLE h_app, CANID cmd,
92 CanMessage *msg, std::string dest) {
93 CAN_MSG_CANCMD st_delivery_msg;
94 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusFail;
98 // Create delivery data
99 memset(&st_delivery_msg, 0, sizeof(st_delivery_msg));
101 case CAN_CMDID_FUELCALC_RST_REQ_RX:
102 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_FUELCALC_RST_SIZE;
104 case CAN_CMDID_STARTUP_FIN_RESP_RX:
105 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_STARTUP_FIN_SIZE;
107 case CAN_CMDID_MRST_INFO_RESP_RX:
108 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_MRST_INFO_SIZE;
110 case CAN_CMDID_VERSION_RESP_RX:
111 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_VERSION_SIZE;
113 case CAN_CMDID_CONNECTION_NODE_RESP_RX:
114 len = (uint16_t)(CAN_TX_CMD_DELIVERY_SIZE + msg->data[0] + 1);
119 st_delivery_msg.hdr.hdr.rid = 0;
120 st_delivery_msg.hdr.hdr.cid = (uint16_t)CID_CAN_CMD_DELIVERY;
121 st_delivery_msg.hdr.hdr.msgbodysize = len;
122 st_delivery_msg.data.cmd_id = (uint8_t)cmd;
123 memcpy(&st_delivery_msg.data.data, msg->data,
124 (size_t)(len - CAN_TX_CMD_DELIVERY_SIZE));
126 h_client = CommonFindSender(h_app, dest);
131 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__, "cid=%x msgbodysize=%x cmd_id=%x",
132 st_delivery_msg.hdr.hdr.cid, st_delivery_msg.hdr.hdr.msgbodysize,
133 st_delivery_msg.data.cmd_id);
134 FRAMEWORKUNIFIEDLOG(ZONE_DEBUG, __func__, "msg_data=%s",
135 MessageDataOutputLog(st_delivery_msg.data.data, len).c_str());
137 e_status = FrameworkunifiedSendMsg(h_client, CID_CAN_CMD_DELIVERY,
138 sizeof(st_delivery_msg), &st_delivery_msg);
139 if (e_status != eFrameworkunifiedStatusOK) {
140 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__, "FrameworkunifiedSendMsg Error(e_status:%d to:%s)",
141 e_status, dest.c_str());
143 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__,
144 "CAN Delivery : dst = %s, CMD = %x, DLC = %x",
145 dest.c_str(), cmd, msg->dlc);
150 static EFrameworkunifiedStatus CANDeliverySndMsgSingle(HANDLE h_app, CANID ul_canid,
151 uint8_t uc_dlc, const uint8_t *puc_data,
152 enum CanIfEchoBackFlags flag, std::string dest) {
153 CAN_MSG_CANDATA st_delivery_msg;
154 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusFail;
156 uint8_t uc_size = uc_dlc;
158 // Create delivery data
159 memset(&st_delivery_msg, 0, sizeof(st_delivery_msg));
160 st_delivery_msg.hdr.hdr.cid = CID_CAN_DATA_DELIVERY;
161 st_delivery_msg.hdr.hdr.msgbodysize = (uint16_t)(CAN_TRX_CANID_SIZE +
164 st_delivery_msg.hdr.hdr.rid = 0;
165 st_delivery_msg.data.can_id = ul_canid;
166 st_delivery_msg.data.dlc = uc_size;
167 st_delivery_msg.echoback = flag;
168 if (uc_size > (uint8_t)CAN_DATA_SIZE)
169 uc_size = CAN_DATA_SIZE;
170 memcpy(st_delivery_msg.data.data, puc_data, (size_t)uc_size);
172 h_client = CommonFindSender(h_app, dest);
177 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__, "can_id=%x dlc=%x echoback=%d",
178 st_delivery_msg.data.can_id, st_delivery_msg.data.dlc,
179 st_delivery_msg.echoback);
180 FRAMEWORKUNIFIEDLOG(ZONE_DEBUG, __func__, "msg_data=%s",
181 MessageDataOutputLog(st_delivery_msg.data.data, uc_size).c_str());
183 e_status = FrameworkunifiedSendMsg(h_client, CID_CAN_DATA_DELIVERY,
184 sizeof(st_delivery_msg), &st_delivery_msg);
185 if (e_status != eFrameworkunifiedStatusOK) {
186 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__, "FrameworkunifiedSendMsg Error(e_status:%d to:%s)",
187 e_status, dest.c_str());
189 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__,
190 "CAN Delivery : dst = %s, CANID = %x, DLC = %x",
191 dest.c_str(), ul_canid, uc_dlc);
196 EFrameworkunifiedStatus CANDeliveryEntry(HANDLE h_app) {
197 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __func__, "@@@ Start communication CanRecv");
200 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusOK;
201 CAN_DELIVERY_ENTRY rcv_msg;
202 CAN_DeliveryEntryListIt it;
205 memset(&rcv_msg, 0, sizeof(rcv_msg));
206 e_status = FrameworkunifiedGetMsgDataOfSize(h_app, &rcv_msg,
207 sizeof(rcv_msg), eSMRRelease);
208 if (e_status != eFrameworkunifiedStatusOK) {
209 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__,
210 "CAN DeliveryEntry FrameworkunifiedGetMsgDataOfSize Error(%d)", e_status);
211 if (e_status == eFrameworkunifiedStatusInvldBufSize) {
212 FrameworkunifiedClearMsgData(h_app);
217 for (i = 0; i < rcv_msg.usCanNum; i++) {
218 CANID canid = rcv_msg.ulCanid[i];
219 CanMessage *latest = CANMsgFind(canid);
221 if (CANDeliveryInsert(canid, rcv_msg.notifyName)) {
222 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__, "(cnd:%lu) : CANID=0x%x, dst=%s",
223 g_map_delivery_list_can.size(), canid, rcv_msg.notifyName);
228 case CAN_CMDID_FUELCALC_RST_REQ_RX:
229 case CAN_CMDID_STARTUP_FIN_RESP_RX:
230 case CAN_CMDID_MRST_INFO_RESP_RX:
231 case CAN_CMDID_VERSION_RESP_RX:
232 case CAN_CMDID_CONNECTION_NODE_RESP_RX:
233 if (eFrameworkunifiedStatusOK != CANDeliverySndCmdSingle(h_app, canid,
234 latest, rcv_msg.notifyName)) {
239 if (eFrameworkunifiedStatusOK != CANDeliverySndMsgSingle(h_app, canid,
240 static_cast<uint8_t>(latest->dlc),
241 latest->data, CANIF_PURERECV, rcv_msg.notifyName)) {
250 e_status = eFrameworkunifiedStatusFail;
256 static EFrameworkunifiedStatus CANDeliverySndMsgToClient(HANDLE h_app, CANID ul_canid,
257 void *data, size_t size, PS_CommunicationProtocol cid) {
258 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusFail;
259 HANDLE h_client = NULL;
260 CAN_DeliveryEntryListIt it;
261 std::pair<CAN_DeliveryEntryListIt, CAN_DeliveryEntryListIt> range;
264 it = g_map_delivery_list_can.find(ul_canid);
265 range = g_map_delivery_list_can.equal_range(ul_canid);
266 for (it = range.first; it != range.second; ++it) {
267 h_client = CommonFindSender(h_app, it->second);
272 e_status = FrameworkunifiedSendMsg(h_client, cid, (UI_32)size, data);
273 if (e_status != eFrameworkunifiedStatusOK) {
274 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__, "FrameworkunifiedSendMsg Error(e_status:%d to:%s)",
275 e_status, it->second.c_str());
279 return fail ? eFrameworkunifiedStatusFail : eFrameworkunifiedStatusOK;
282 EFrameworkunifiedStatus CANDeliverySndMsg(HANDLE h_app, CANID ul_canid, uint8_t n_ta,
283 uint8_t uc_dlc, const uint8_t *puc_data,
284 PS_CommunicationProtocol cid, enum CanIfEchoBackFlags flag) {
285 CAN_MSG_CANDATA st_delivery_msg;
286 uint8_t uc_size = uc_dlc;
288 // Create delivery data
289 memset(&st_delivery_msg, 0, sizeof(st_delivery_msg));
290 st_delivery_msg.hdr.hdr.cid = cid;
291 st_delivery_msg.hdr.hdr.msgbodysize = (uint16_t)(CAN_TRX_CANID_SIZE +
294 st_delivery_msg.hdr.hdr.rid = 0;
295 st_delivery_msg.data.can_id = ul_canid;
296 st_delivery_msg.data.dlc = uc_size;
297 st_delivery_msg.echoback = flag;
299 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__, "can_id=%x dlc=%x echoback=%d",
300 st_delivery_msg.data.can_id, st_delivery_msg.data.dlc,
301 st_delivery_msg.echoback);
302 FRAMEWORKUNIFIEDLOG(ZONE_DEBUG, __func__, "msg_data=%s",
303 MessageDataOutputLog(st_delivery_msg.data.data, uc_size).c_str());
306 if (uc_size > (uint8_t)CAN_DATA_SIZE)
307 uc_size = CAN_DATA_SIZE;
308 memcpy(st_delivery_msg.data.data, puc_data, (size_t)uc_size);
310 return CANDeliverySndMsgToClient(h_app, ul_canid, &st_delivery_msg,
311 sizeof(st_delivery_msg), cid);
314 EFrameworkunifiedStatus CANCommandDeliveryRcvProcess(HANDLE h_app,
315 CanMessage *msg, uint8_t cmd) {
316 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusFail;
317 CAN_MSG_CANCMD st_delivery_msg;
320 memset(&st_delivery_msg, 0, sizeof(st_delivery_msg));
322 case CAN_CMDID_FUELCALC_RST_REQ_RX:
323 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_FUELCALC_RST_SIZE;
325 case CAN_CMDID_STARTUP_FIN_RESP_RX:
326 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_STARTUP_FIN_SIZE;
328 case CAN_CMDID_MRST_INFO_RESP_RX:
329 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_MRST_INFO_SIZE;
331 case CAN_CMDID_VERSION_RESP_RX:
332 len = CAN_TX_CMD_DELIVERY_SIZE + CAN_TX_CMD_VERSION_SIZE;
334 case CAN_CMDID_CONNECTION_NODE_RESP_RX:
335 len = (uint16_t)(CAN_TX_CMD_DELIVERY_SIZE + msg->data[0] + 1);
340 st_delivery_msg.hdr.hdr.rid = 0;
341 st_delivery_msg.hdr.hdr.cid = (uint16_t)CID_CAN_CMD_DELIVERY;
342 st_delivery_msg.hdr.hdr.msgbodysize = len;
343 st_delivery_msg.data.cmd_id = cmd;
344 memcpy(&st_delivery_msg.data.data, msg->data,
345 (size_t)(len - CAN_TX_CMD_DELIVERY_SIZE));
346 CANMsgInsert(cmd, msg);
348 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __func__, "cid=%x msgbodysize=%x cmd_id=%x",
349 st_delivery_msg.hdr.hdr.cid, st_delivery_msg.hdr.hdr.msgbodysize,
350 st_delivery_msg.data.cmd_id);
351 FRAMEWORKUNIFIEDLOG(ZONE_DEBUG, __func__, "msg_data=%s",
352 MessageDataOutputLog(st_delivery_msg.data.data, len).c_str());
354 return CANDeliverySndMsgToClient(h_app, msg->can_id, &st_delivery_msg,
355 sizeof(st_delivery_msg), CID_CAN_CMD_DELIVERY);
358 EFrameworkunifiedStatus CANDeliveryRcvProcess(HANDLE h_app, CanMessage *msg) {
359 if (!Canif_CheckCanID(msg->can_id)) {
360 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__, "CANID is invalid (%x)", msg->can_id);
361 return eFrameworkunifiedStatusFail;
364 CANCommWatchClear(h_app, msg->can_id);
365 CANMsgInsert(msg->can_id, msg);
366 if (eFrameworkunifiedStatusOK != CANDeliverySndMsg(h_app, msg->can_id, CAN_NTA_INVALID,
367 (uint8_t)msg->dlc, msg->data, CID_CAN_DATA_DELIVERY)) {
368 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__, "CAN Delivery Error");
369 return eFrameworkunifiedStatusFail;
372 return eFrameworkunifiedStatusOK;
375 EFrameworkunifiedStatus CANClearEntry(HANDLE h_app) {
376 char notify_name[CANIF_NOTIFY_NAME_MAX_SIZE + 1] = {0};
377 CAN_DeliveryEntryListIt it;
378 EFrameworkunifiedStatus e_status = eFrameworkunifiedStatusOK;
380 e_status = FrameworkunifiedGetMsgDataOfSize(h_app, ¬ify_name,
381 CANIF_NOTIFY_NAME_MAX_SIZE, eSMRRelease);
382 if (e_status != eFrameworkunifiedStatusOK) {
383 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __func__,
384 "#CAN thread# FrameworkunifiedGetMsgDataOfSize Error(%d)", e_status);
385 if (e_status == eFrameworkunifiedStatusInvldBufSize) {
386 FrameworkunifiedClearMsgData(h_app);
391 FRAMEWORKUNIFIEDLOG(ZONE_DEBUG, __func__, "notify_name=%s", notify_name);
393 // To avoid destruction of iterator.
394 it = g_map_delivery_list_can.begin();
395 while (it != g_map_delivery_list_can.end()) {
396 size_t n = strnlen(it->second.c_str(), CANIF_NOTIFY_NAME_MAX_SIZE);
397 if (!strncmp(it->second.c_str(), notify_name, n)) {
398 g_map_delivery_list_can.erase(it++);
404 return eFrameworkunifiedStatusOK;