Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "adcore_api.h"
12 : #include "hdc_api.h"
13 : #include "memory_utils.h"
14 : #include "log/adx_log.h"
15 : #include "adx_msg_proto.h"
16 : #include "file_utils.h"
17 : #include "create_func.h"
18 : #include "adx_component.h"
19 : #include "adx_comm_opt_manager.h"
20 : using namespace Adx;
21 : constexpr int32_t TIME_ONE_THOUSAND = 1000;
22 : /**
23 : * @brief : watch hdc session to get result
24 : * @param [in] : session hdc session
25 : * @param [in] : resultBuf request info
26 : * @param [in] : timeout 0 : wait_always, > 0 wait_timeout, < 0 wait_default; unit: ms
27 : * @return : IDE_DAEMON_OK succeed; others failed
28 : */
29 2 : static int32_t ReadSettingResult(const HDC_SESSION session, const AdxStringBuffer resultBuf, uint32_t resultLen,
30 : int32_t timeout)
31 : {
32 2 : int32_t err = IDE_DAEMON_ERROR;
33 2 : if ((session == nullptr) || (resultBuf == nullptr)) {
34 0 : return err;
35 : }
36 :
37 : do {
38 2 : CommHandle handle{COMM_HDC, reinterpret_cast<OptHandle>(session), NR_COMPONENTS, timeout, nullptr};
39 2 : std::string value;
40 2 : err = AdxMsgProto::GetStringMsgData(handle, value);
41 2 : if (err == IDE_DAEMON_OK) {
42 2 : if (value.empty()) {
43 0 : (void)usleep(TIME_ONE_THOUSAND); // sleep 1ms, avoid frequent read hdc
44 0 : continue;
45 : }
46 :
47 2 : if (value.compare(0, strlen(HDC_END_MSG), HDC_END_MSG, strlen(HDC_END_MSG)) == 0) {
48 2 : break;
49 : }
50 :
51 0 : err = memcpy_s(resultBuf, resultLen, value.c_str(), value.length());
52 0 : if (err != EOK) {
53 0 : IDE_LOGE("memcpy_s failed, result = %d.", err);
54 0 : err = IDE_DAEMON_ERROR;
55 0 : break;
56 : }
57 : }
58 2 : } while (err == IDE_DAEMON_OK);
59 :
60 2 : return err;
61 : }
62 :
63 9 : static int32_t AdxSendMsgToServerByType(AdxHdcServiceType type, IdeTlvConReq req, const AdxStringBuffer result,
64 : uint32_t resultLen, int32_t timeout = -1)
65 : {
66 9 : int32_t err = IDE_DAEMON_ERROR;
67 9 : std::unique_ptr<AdxCommOpt> opt (CreateAdxCommOpt(OptType::COMM_HDC));
68 9 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return err, "create hdc commopt exception");
69 9 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
70 9 : IDE_CTRL_VALUE_FAILED(ret, return err, "register hdc failed");
71 :
72 9 : HDC_CLIENT client = Adx::HdcClientCreate(type);
73 9 : if (client == nullptr) {
74 2 : IDE_LOGW("Hdc client create exception");
75 2 : return err;
76 : }
77 :
78 7 : HDC_SESSION session = nullptr;
79 7 : err = Adx::HdcSessionConnect(0, req->dev_id, client, &session);
80 7 : if (err != IDE_DAEMON_OK) {
81 2 : IDE_LOGW("Connect to device exception, please make sure device id is valid, device id = %d.", req->dev_id);
82 2 : (void)Adx::HdcClientDestroy(client);
83 2 : return err;
84 : }
85 :
86 5 : CommHandle handle{COMM_HDC, reinterpret_cast<OptHandle>(session), NR_COMPONENTS, -1, nullptr};
87 10 : err = Adx::AdxMsgProto::SendMsgData(handle, req->type, MsgStatus::MSG_STATUS_NONE_ERROR,
88 5 : static_cast<IdeSendBuffT>(req->value), req->len);
89 5 : if (err != EN_OK) {
90 1 : IDE_LOGE("Write level info to device failed by hdc, result=%d.", err);
91 4 : } else if (result != nullptr) {
92 2 : err = ReadSettingResult(session, result, resultLen, timeout);
93 : }
94 :
95 5 : (void)Adx::HdcSessionDestroy(session);
96 5 : (void)Adx::HdcClientDestroy(client);
97 5 : return err;
98 9 : }
99 :
100 5 : int32_t AdxSendMsgAndGetResultByType(AdxHdcServiceType type, IdeTlvConReq req, const AdxStringBuffer result,
101 : uint32_t resultLen)
102 : {
103 5 : if ((req == nullptr) || (result == nullptr)) {
104 1 : return IDE_DAEMON_ERROR;
105 : }
106 4 : return AdxSendMsgToServerByType(type, req, result, resultLen);
107 : }
108 :
109 5 : int32_t AdxSendMsgAndNoResultByType(AdxHdcServiceType type, IdeTlvConReq req)
110 : {
111 5 : if (req == nullptr) {
112 1 : return IDE_DAEMON_ERROR;
113 : }
114 4 : return AdxSendMsgToServerByType(type, req, nullptr, 0);
115 : }
116 :
117 2 : int32_t AdxSendMsgByHandle(AdxCommConHandle handle, CmdClassT type, AdxString data, uint32_t len)
118 : {
119 2 : if ((handle == nullptr) || (data == nullptr)) {
120 0 : return IDE_DAEMON_ERROR;
121 : }
122 :
123 2 : std::unique_ptr<AdxCommOpt> opt (CreateAdxCommOpt(handle->type));
124 2 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return IDE_DAEMON_ERROR, "create hdc commopt exception");
125 2 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
126 2 : IDE_CTRL_VALUE_FAILED(ret, return IDE_DAEMON_ERROR, "register hdc failed");
127 :
128 2 : return (Adx::AdxMsgProto::SendMsgData(*handle, type, MsgStatus::MSG_STATUS_NONE_ERROR,
129 2 : static_cast<IdeSendBuffT>(data), len) == IDE_DAEMON_NONE_ERROR) ? IDE_DAEMON_OK : IDE_DAEMON_ERROR;
130 2 : }
131 :
132 5 : int32_t AdxSendFileByHandle(AdxCommConHandle handle, CmdClassT type, AdxString srcPath, AdxString desPath,
133 : SendFileType flag)
134 : {
135 5 : if ((handle == nullptr) || (srcPath == nullptr) || (desPath == nullptr)) {
136 0 : return IDE_DAEMON_ERROR;
137 : }
138 10 : if (!Adx::FileUtils::IsFileExist(std::string(srcPath))) {
139 1 : IDE_LOGE("File %s does not exist.", srcPath);
140 1 : return IDE_DAEMON_ERROR;
141 : }
142 :
143 4 : std::unique_ptr<AdxCommOpt> opt (CreateAdxCommOpt(handle->type));
144 4 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return IDE_DAEMON_ERROR, "create hdc commopt exception");
145 4 : bool err = AdxCommOptManager::Instance().CommOptsRegister(opt);
146 4 : IDE_CTRL_VALUE_FAILED(err, return IDE_DAEMON_ERROR, "register hdc failed");
147 :
148 4 : int32_t fd = mmOpen2(srcPath, M_RDONLY | M_BINARY, S_IREAD);
149 4 : if (fd < 0) {
150 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
151 1 : IDE_LOGE("open send file failed, info : %s, open file is %s",
152 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN), srcPath);
153 1 : return IDE_DAEMON_ERROR;
154 : }
155 :
156 : // send file name
157 6 : int32_t ret = Adx::AdxMsgProto::SendMsgData(*handle, type, MsgStatus::MSG_STATUS_NONE_ERROR,
158 3 : static_cast<IdeSendBuffT>(desPath), strlen(desPath) + 1U);
159 3 : if (ret != IDE_DAEMON_NONE_ERROR) {
160 1 : if (fd >= 0) {
161 1 : mmClose(fd);
162 1 : fd = -1;
163 : }
164 1 : IDE_LOGE("send file path failed, file path name is %s", srcPath);
165 1 : return IDE_DAEMON_ERROR;
166 : }
167 :
168 : // send file data
169 2 : if (flag == SEND_FILE_TYPE_REAL_FILE) {
170 2 : ret = Adx::AdxMsgProto::SendEventFile(*handle, type, 0, fd);
171 : } else {
172 0 : ret = Adx::AdxMsgProto::SendFile(*handle, type, 0, fd);
173 : }
174 2 : if (fd >= 0) {
175 2 : mmClose(fd);
176 2 : fd = -1;
177 : }
178 :
179 2 : if (ret != IDE_DAEMON_NONE_ERROR) {
180 1 : IDE_LOGE("read or send file failed, start to send ctrl msg to notice host, ret=%d", ret);
181 1 : ret = IDE_DAEMON_ERROR;
182 : }
183 2 : return ret;
184 4 : }
185 :
186 : /**
187 : * @brief : convert component type to CmdClassT
188 : * @param [in] : cmptType component type
189 : * @return : NR_IDE_CMD_CLASS failed; others succeed
190 : */
191 35 : static CmdClassT GetReqTypeByComponentType(ComponentType cmptType)
192 : {
193 35 : CmdClassT cmdType = NR_IDE_CMD_CLASS;
194 335 : for (uint32_t i = 0; i < ARRAY_LEN(g_componentsInfo, AdxComponentMap); i++) {
195 312 : if (cmptType == g_componentsInfo[i].cmptType) {
196 12 : cmdType = g_componentsInfo[i].cmdType;
197 12 : break;
198 : }
199 : }
200 35 : return cmdType;
201 : }
202 :
203 : /**
204 : * @brief : get attribute value by communication handle
205 : * @param [in] : handle hdc session
206 : * @param [in] : attr attribute type
207 : * @param [out] : value attribute value
208 : * @return : IDE_DAEMON_OK succeed; IDE_DAEMON_ERROR failed
209 : */
210 8 : int32_t AdxGetAttrByCommHandle(AdxCommConHandle handle, int32_t attr, int32_t *value)
211 : {
212 8 : if (handle == nullptr || value == nullptr) {
213 2 : IDE_LOGE("get attribute failed, invalid input");
214 2 : return IDE_DAEMON_ERROR;
215 : }
216 6 : return IdeGetAttrBySession(reinterpret_cast<HDC_SESSION>(handle->session), attr, value);
217 : }
218 :
219 : /**
220 : * @brief : create long link communication handle
221 : * @param [in] : type server type
222 : * @param [in] : devId device id
223 : * @param [in] : compType component type
224 : * @return : nullptr failed; others succeed
225 : */
226 8 : AdxCommHandle AdxCreateCommHandle(AdxHdcServiceType type, int32_t devId, ComponentType compType)
227 : {
228 8 : std::unique_ptr<AdxCommOpt> opt (CreateAdxCommOpt(OptType::COMM_HDC));
229 8 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return nullptr, "create hdc commopt exception");
230 8 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
231 8 : IDE_CTRL_VALUE_FAILED(ret, return nullptr, "register hdc failed");
232 :
233 8 : HDC_CLIENT client = Adx::HdcClientCreate(type);
234 8 : IDE_CTRL_VALUE_FAILED(client != nullptr, return nullptr, "Hdc client create exception");
235 :
236 7 : HDC_SESSION session = nullptr;
237 7 : int32_t err = Adx::HdcSessionConnect(0, devId, client, &session);
238 7 : if (err != IDE_DAEMON_OK) {
239 1 : IDE_LOGW("Connect to device exception, please make sure device id is valid, device id = %d.", devId);
240 1 : (void)Adx::HdcClientDestroy(client);
241 1 : return nullptr;
242 : }
243 :
244 6 : AdxCommHandle handle = static_cast<AdxCommHandle>(IdeXmalloc(sizeof(CommHandle)));
245 6 : IDE_CTRL_VALUE_FAILED(handle != nullptr, return handle, "Malloc handle failed.");
246 6 : handle->type = OptType::COMM_HDC;
247 6 : handle->session = reinterpret_cast<OptHandle>(session);
248 6 : handle->client = client;
249 6 : handle->comp = compType;
250 6 : handle->timeout = 0;
251 :
252 6 : const std::string defaultMessage = "LONG_LINK_DEFAULT";
253 6 : err = Adx::AdxMsgProto::SendMsgData(*handle, GetReqTypeByComponentType(compType), MsgStatus::MSG_STATUS_LONG_LINK,
254 6 : static_cast<IdeSendBuffT>(defaultMessage.c_str()), defaultMessage.size());
255 6 : if (err != IDE_DAEMON_OK) {
256 3 : IDE_LOGE("Write default info to device failed by hdc, result=%d.", err);
257 3 : (void)Adx::HdcSessionDestroy(session);
258 3 : (void)Adx::HdcClientDestroy(client);
259 3 : handle->session = 0;
260 3 : handle->client = nullptr;
261 3 : IDE_XFREE_AND_SET_NULL(handle);
262 : }
263 6 : return handle;
264 8 : }
265 :
266 : /**
267 : * @brief : check if handle is valid
268 : * @param [in] : handle checked handle
269 : * @return : IDE_DAEMON_OK valid; IDE_DAEMON_ERROR invalid
270 : */
271 8 : int32_t AdxIsCommHandleValid(AdxCommConHandle handle)
272 : {
273 8 : if ((handle == nullptr) || (handle->session == 0)) {
274 6 : IDE_LOGE("the handle is invalid");
275 6 : return IDE_DAEMON_ERROR;
276 : }
277 2 : return IDE_DAEMON_OK;
278 : }
279 :
280 : /**
281 : * @brief : destroy and free communication handle
282 : * @param [in] : handle communication handle
283 : */
284 5 : void AdxDestroyCommHandle(AdxCommHandle handle)
285 : {
286 5 : if (handle != nullptr && handle->session != 0) {
287 4 : (void)Adx::HdcSessionDestroy(reinterpret_cast<HDC_SESSION>(handle->session));
288 4 : if (handle->client != nullptr) {
289 3 : (void)Adx::HdcClientDestroy(handle->client);
290 : }
291 4 : IdeXfree(handle);
292 : } else {
293 1 : IDE_LOGE("Can not destroy invalid handle.");
294 : }
295 5 : }
296 :
297 : /**
298 : * @brief : send message by communication handle
299 : * @param [in] : handle communication handle
300 : * @param [in] : data message data
301 : * @param [in] : len data length
302 : * @return : IDE_DAEMON_OK succeed; others failed
303 : */
304 26 : int32_t AdxSendMsg(AdxCommConHandle handle, AdxString data, uint32_t len)
305 : {
306 26 : if ((handle == nullptr) || (data == nullptr)) {
307 2 : return IDE_DAEMON_ERROR;
308 : }
309 :
310 24 : std::unique_ptr<AdxCommOpt> opt (CreateAdxCommOpt(handle->type));
311 24 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return IDE_DAEMON_ERROR, "create hdc commopt exception");
312 24 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
313 24 : IDE_CTRL_VALUE_FAILED(ret, return IDE_DAEMON_ERROR, "register hdc failed");
314 :
315 24 : return (Adx::AdxMsgProto::SendMsgData(*handle, GetReqTypeByComponentType(handle->comp),
316 : MsgStatus::MSG_STATUS_NONE_ERROR, static_cast<IdeSendBuffT>(data), len) ==
317 24 : IDE_DAEMON_NONE_ERROR) ? IDE_DAEMON_OK : IDE_DAEMON_ERROR;
318 24 : }
319 :
320 : /**
321 : * @brief : receive message by communication handle
322 : * @param [in] : handle communication handle
323 : * @param [out] : data message data
324 : * @param [in|out] : len data length
325 : * @param [in] : timeout max wait time; unit: ms
326 : * @return : IDE_DAEMON_OK succeed; others failed
327 : */
328 30 : int32_t AdxRecvMsg(AdxCommHandle handle, IdeStrBufAddrT data, uint32_t *len, uint32_t timeout)
329 : {
330 30 : int32_t err = IDE_DAEMON_ERROR;
331 30 : if (len == nullptr) {
332 1 : IDE_LOGE("receive message failed, invalid length");
333 1 : return err;
334 : }
335 29 : if ((handle == nullptr) || (data == nullptr)) {
336 2 : *len = 0;
337 2 : IDE_LOGE("receive message failed, invalid input.");
338 2 : return err;
339 : }
340 :
341 27 : handle->timeout = static_cast<int32_t>(timeout);
342 27 : std::string value;
343 27 : err = AdxMsgProto::GetStringMsgData(*handle, value);
344 27 : if (err != IDE_DAEMON_OK) {
345 7 : *len = 0;
346 7 : return err;
347 : }
348 20 : if (value.empty()) {
349 0 : *len = 0;
350 0 : return IDE_DAEMON_RECV_NODATA;
351 : }
352 20 : if (*len < value.length()) {
353 1 : IDE_LOGE("input length(%u bytes) less than read message length(%zu bytes)", *len, value.length());
354 1 : *len = 0;
355 1 : return IDE_DAEMON_ERROR;
356 : }
357 19 : err = memcpy_s(*data, *len, value.c_str(), value.length());
358 19 : if (err != EOK) {
359 0 : IDE_LOGE("memcpy_s failed, result=%d.", err);
360 0 : *len = 0;
361 0 : return IDE_DAEMON_ERROR;
362 : }
363 19 : *len = value.length();
364 19 : return err;
365 27 : }
366 :
367 9 : static int32_t AdxServerCommProcess(AdxHdcServiceType type, AdxTlvConReq req, AdxStringBuffer result, uint32_t length,
368 : uint32_t timeout)
369 : {
370 9 : if (req == nullptr) {
371 2 : IDE_LOGE("invalid input, tlv struct is null");
372 2 : return IDE_DAEMON_ERROR;
373 : }
374 7 : if (req->len < 0) {
375 1 : IDE_LOGE("invalid input, length of tlv struct is %d bytes", req->len);
376 1 : return IDE_DAEMON_ERROR;
377 : }
378 6 : IdeTlvReq ide = static_cast<IdeTlvReq>(IdeXmalloc(sizeof(TlvReqT) + req->len));
379 6 : if (ide == nullptr) {
380 1 : IDE_LOGE("malloc ide tlv failed, size=%zu bytes", sizeof(TlvReqT) + req->len);
381 1 : return IDE_DAEMON_ERROR;
382 : }
383 5 : ide->type = GetReqTypeByComponentType(req->type);
384 5 : if (ide->type == NR_IDE_CMD_CLASS) {
385 1 : IDE_LOGE("invalid input, component type of tlv struct is %d", static_cast<int32_t>(req->type));
386 1 : IDE_XFREE_AND_SET_NULL(ide);
387 1 : return IDE_DAEMON_ERROR;
388 : }
389 4 : ide->dev_id = req->devId;
390 4 : ide->len = req->len;
391 4 : int32_t ret = memcpy_s(ide->value, ide->len, req->value, req->len);
392 4 : if (ret != EOK) {
393 1 : IDE_LOGE("memcpy_s from cmptype to req failed, result=%d", ret);
394 1 : IDE_XFREE_AND_SET_NULL(ide);
395 1 : return IDE_DAEMON_ERROR;
396 : }
397 3 : if (result == nullptr) {
398 2 : IDE_LOGI("AdxDevCommShortLink, no results needed, cmpt=%d, cmd=%d, devId=%d",
399 : static_cast<int32_t>(req->type), static_cast<int32_t>(ide->type), ide->dev_id);
400 2 : ret = AdxSendMsgAndNoResultByType(type, ide);
401 : } else {
402 1 : IDE_LOGI("AdxDevCommShortLink, result wait timeout:%u, cmpt=%d, cmd=%d, devId=%d", timeout,
403 : static_cast<int32_t>(req->type), static_cast<int32_t>(ide->type), ide->dev_id);
404 1 : (void)memset_s(result, length, 0, length);
405 1 : ret = AdxSendMsgToServerByType(type, ide, result, length, static_cast<int32_t>(timeout));
406 : }
407 3 : IDE_XFREE_AND_SET_NULL(ide);
408 3 : return ret;
409 : }
410 :
411 : /**
412 : * @brief : communication with the specific hdc server and get result if needed
413 : * @param [in] : type server type
414 : * @param [in] : req including device id, component type, message data
415 : * @param [in|out] : result get result data from device, pass nullptr if result is not needed
416 : * @param [in] : length result data length
417 : * @param [in] : timeout 0 : wait_always, > 0 wait_timeout; unit: ms
418 : * @return : IDE_DAEMON_OK succeed; others failed
419 : */
420 9 : int32_t AdxDevCommShortLink(AdxHdcServiceType type, AdxTlvConReq req, AdxStringBuffer result, uint32_t length,
421 : uint32_t timeout) {
422 9 : int32_t ret = AdxServerCommProcess(type, req, result, length, timeout);
423 9 : if ((ret != IDE_DAEMON_OK) && (result != nullptr) && (strlen(result) == 0)) {
424 5 : const std::string value = "get result data from server failed";
425 5 : int32_t err = strncpy_s(result, length, value.c_str(), value.length());
426 5 : if (err != EOK) {
427 1 : IDE_LOGE("strncpy_s null result data failed, result: %d.", err);
428 : }
429 5 : }
430 9 : return ret;
431 : }
|