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(
30 : const HDC_SESSION session, const AdxStringBuffer resultBuf, uint32_t resultLen, 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(
64 : AdxHdcServiceType type, IdeTlvConReq req, const AdxStringBuffer result, 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(
88 5 : handle, req->type, MsgStatus::MSG_STATUS_NONE_ERROR, 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(
101 : AdxHdcServiceType type, IdeTlvConReq req, const AdxStringBuffer result, 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(
129 : *handle, type, MsgStatus::MSG_STATUS_NONE_ERROR, static_cast<IdeSendBuffT>(data), len) ==
130 2 : IDE_DAEMON_NONE_ERROR) ?
131 : IDE_DAEMON_OK :
132 2 : IDE_DAEMON_ERROR;
133 2 : }
134 :
135 5 : int32_t AdxSendFileByHandle(
136 : AdxCommConHandle handle, CmdClassT type, AdxString srcPath, AdxString desPath, SendFileType flag)
137 : {
138 5 : if ((handle == nullptr) || (srcPath == nullptr) || (desPath == nullptr)) {
139 0 : return IDE_DAEMON_ERROR;
140 : }
141 10 : if (!Adx::FileUtils::IsFileExist(std::string(srcPath))) {
142 1 : IDE_LOGE("File %s does not exist.", srcPath);
143 1 : return IDE_DAEMON_ERROR;
144 : }
145 :
146 4 : std::unique_ptr<AdxCommOpt> opt(CreateAdxCommOpt(handle->type));
147 4 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return IDE_DAEMON_ERROR, "create hdc commopt exception");
148 4 : bool err = AdxCommOptManager::Instance().CommOptsRegister(opt);
149 4 : IDE_CTRL_VALUE_FAILED(err, return IDE_DAEMON_ERROR, "register hdc failed");
150 :
151 4 : int32_t fd = mmOpen2(srcPath, M_RDONLY | M_BINARY, S_IREAD);
152 4 : if (fd < 0) {
153 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
154 1 : IDE_LOGE(
155 : "open send file failed, info : %s, open file is %s",
156 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN), srcPath);
157 1 : return IDE_DAEMON_ERROR;
158 : }
159 :
160 : // send file name
161 6 : int32_t ret = Adx::AdxMsgProto::SendMsgData(
162 3 : *handle, type, MsgStatus::MSG_STATUS_NONE_ERROR, static_cast<IdeSendBuffT>(desPath), strlen(desPath) + 1U);
163 3 : if (ret != IDE_DAEMON_NONE_ERROR) {
164 1 : if (fd >= 0) {
165 1 : mmClose(fd);
166 1 : fd = -1;
167 : }
168 1 : IDE_LOGE("send file path failed, file path name is %s", srcPath);
169 1 : return IDE_DAEMON_ERROR;
170 : }
171 :
172 : // send file data
173 2 : if (flag == SEND_FILE_TYPE_REAL_FILE) {
174 2 : ret = Adx::AdxMsgProto::SendEventFile(*handle, type, 0, fd);
175 : } else {
176 0 : ret = Adx::AdxMsgProto::SendFile(*handle, type, 0, fd);
177 : }
178 2 : if (fd >= 0) {
179 2 : mmClose(fd);
180 2 : fd = -1;
181 : }
182 :
183 2 : if (ret != IDE_DAEMON_NONE_ERROR) {
184 1 : IDE_LOGE("read or send file failed, start to send ctrl msg to notice host, ret=%d", ret);
185 1 : ret = IDE_DAEMON_ERROR;
186 : }
187 2 : return ret;
188 4 : }
189 :
190 : /**
191 : * @brief : convert component type to CmdClassT
192 : * @param [in] : cmptType component type
193 : * @return : NR_IDE_CMD_CLASS failed; others succeed
194 : */
195 35 : static CmdClassT GetReqTypeByComponentType(ComponentType cmptType)
196 : {
197 35 : CmdClassT cmdType = NR_IDE_CMD_CLASS;
198 335 : for (uint32_t i = 0; i < ARRAY_LEN(g_componentsInfo, AdxComponentMap); i++) {
199 312 : if (cmptType == g_componentsInfo[i].cmptType) {
200 12 : cmdType = g_componentsInfo[i].cmdType;
201 12 : break;
202 : }
203 : }
204 35 : return cmdType;
205 : }
206 :
207 : /**
208 : * @brief : get attribute value by communication handle
209 : * @param [in] : handle hdc session
210 : * @param [in] : attr attribute type
211 : * @param [out] : value attribute value
212 : * @return : IDE_DAEMON_OK succeed; IDE_DAEMON_ERROR failed
213 : */
214 8 : int32_t AdxGetAttrByCommHandle(AdxCommConHandle handle, int32_t attr, int32_t* value)
215 : {
216 8 : if (handle == nullptr || value == nullptr) {
217 2 : IDE_LOGE("get attribute failed, invalid input");
218 2 : return IDE_DAEMON_ERROR;
219 : }
220 6 : return IdeGetAttrBySession(reinterpret_cast<HDC_SESSION>(handle->session), attr, value);
221 : }
222 :
223 : /**
224 : * @brief : create long link communication handle
225 : * @param [in] : type server type
226 : * @param [in] : devId device id
227 : * @param [in] : compType component type
228 : * @return : nullptr failed; others succeed
229 : */
230 8 : AdxCommHandle AdxCreateCommHandle(AdxHdcServiceType type, int32_t devId, ComponentType compType)
231 : {
232 8 : std::unique_ptr<AdxCommOpt> opt(CreateAdxCommOpt(OptType::COMM_HDC));
233 8 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return nullptr, "create hdc commopt exception");
234 8 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
235 8 : IDE_CTRL_VALUE_FAILED(ret, return nullptr, "register hdc failed");
236 :
237 8 : HDC_CLIENT client = Adx::HdcClientCreate(type);
238 8 : IDE_CTRL_VALUE_FAILED(client != nullptr, return nullptr, "Hdc client create exception");
239 :
240 7 : HDC_SESSION session = nullptr;
241 7 : int32_t err = Adx::HdcSessionConnect(0, devId, client, &session);
242 7 : if (err != IDE_DAEMON_OK) {
243 1 : IDE_LOGW("Connect to device exception, please make sure device id is valid, device id = %d.", devId);
244 1 : (void)Adx::HdcClientDestroy(client);
245 1 : return nullptr;
246 : }
247 :
248 6 : AdxCommHandle handle = static_cast<AdxCommHandle>(IdeXmalloc(sizeof(CommHandle)));
249 6 : IDE_CTRL_VALUE_FAILED(handle != nullptr, return handle, "Malloc handle failed.");
250 6 : handle->type = OptType::COMM_HDC;
251 6 : handle->session = reinterpret_cast<OptHandle>(session);
252 6 : handle->client = client;
253 6 : handle->comp = compType;
254 6 : handle->timeout = 0;
255 :
256 6 : const std::string defaultMessage = "LONG_LINK_DEFAULT";
257 6 : err = Adx::AdxMsgProto::SendMsgData(
258 : *handle, GetReqTypeByComponentType(compType), MsgStatus::MSG_STATUS_LONG_LINK,
259 6 : static_cast<IdeSendBuffT>(defaultMessage.c_str()), defaultMessage.size());
260 6 : if (err != IDE_DAEMON_OK) {
261 3 : IDE_LOGE("Write default info to device failed by hdc, result=%d.", err);
262 3 : (void)Adx::HdcSessionDestroy(session);
263 3 : (void)Adx::HdcClientDestroy(client);
264 3 : handle->session = 0;
265 3 : handle->client = nullptr;
266 3 : IDE_XFREE_AND_SET_NULL(handle);
267 : }
268 6 : return handle;
269 8 : }
270 :
271 : /**
272 : * @brief : check if handle is valid
273 : * @param [in] : handle checked handle
274 : * @return : IDE_DAEMON_OK valid; IDE_DAEMON_ERROR invalid
275 : */
276 8 : int32_t AdxIsCommHandleValid(AdxCommConHandle handle)
277 : {
278 8 : if ((handle == nullptr) || (handle->session == 0)) {
279 6 : IDE_LOGE("the handle is invalid");
280 6 : return IDE_DAEMON_ERROR;
281 : }
282 2 : return IDE_DAEMON_OK;
283 : }
284 :
285 : /**
286 : * @brief : destroy and free communication handle
287 : * @param [in] : handle communication handle
288 : */
289 5 : void AdxDestroyCommHandle(AdxCommHandle handle)
290 : {
291 5 : if (handle != nullptr && handle->session != 0) {
292 4 : (void)Adx::HdcSessionDestroy(reinterpret_cast<HDC_SESSION>(handle->session));
293 4 : if (handle->client != nullptr) {
294 3 : (void)Adx::HdcClientDestroy(handle->client);
295 : }
296 4 : IdeXfree(handle);
297 : } else {
298 1 : IDE_LOGE("Can not destroy invalid handle.");
299 : }
300 5 : }
301 :
302 : /**
303 : * @brief : send message by communication handle
304 : * @param [in] : handle communication handle
305 : * @param [in] : data message data
306 : * @param [in] : len data length
307 : * @return : IDE_DAEMON_OK succeed; others failed
308 : */
309 26 : int32_t AdxSendMsg(AdxCommConHandle handle, AdxString data, uint32_t len)
310 : {
311 26 : if ((handle == nullptr) || (data == nullptr)) {
312 2 : return IDE_DAEMON_ERROR;
313 : }
314 :
315 24 : std::unique_ptr<AdxCommOpt> opt(CreateAdxCommOpt(handle->type));
316 24 : IDE_CTRL_VALUE_FAILED(opt != nullptr, return IDE_DAEMON_ERROR, "create hdc commopt exception");
317 24 : bool ret = AdxCommOptManager::Instance().CommOptsRegister(opt);
318 24 : IDE_CTRL_VALUE_FAILED(ret, return IDE_DAEMON_ERROR, "register hdc failed");
319 :
320 24 : return (Adx::AdxMsgProto::SendMsgData(
321 24 : *handle, GetReqTypeByComponentType(handle->comp), MsgStatus::MSG_STATUS_NONE_ERROR,
322 24 : static_cast<IdeSendBuffT>(data), len) == IDE_DAEMON_NONE_ERROR) ?
323 : IDE_DAEMON_OK :
324 24 : IDE_DAEMON_ERROR;
325 24 : }
326 :
327 : /**
328 : * @brief : receive message by communication handle
329 : * @param [in] : handle communication handle
330 : * @param [out] : data message data
331 : * @param [in|out] : len data length
332 : * @param [in] : timeout max wait time; unit: ms
333 : * @return : IDE_DAEMON_OK succeed; others failed
334 : */
335 30 : int32_t AdxRecvMsg(AdxCommHandle handle, IdeStrBufAddrT data, uint32_t* len, uint32_t timeout)
336 : {
337 30 : int32_t err = IDE_DAEMON_ERROR;
338 30 : if (len == nullptr) {
339 1 : IDE_LOGE("receive message failed, invalid length");
340 1 : return err;
341 : }
342 29 : if ((handle == nullptr) || (data == nullptr)) {
343 2 : *len = 0;
344 2 : IDE_LOGE("receive message failed, invalid input.");
345 2 : return err;
346 : }
347 :
348 27 : handle->timeout = static_cast<int32_t>(timeout);
349 27 : std::string value;
350 27 : err = AdxMsgProto::GetStringMsgData(*handle, value);
351 27 : if (err != IDE_DAEMON_OK) {
352 7 : *len = 0;
353 7 : return err;
354 : }
355 20 : if (value.empty()) {
356 0 : *len = 0;
357 0 : return IDE_DAEMON_RECV_NODATA;
358 : }
359 20 : if (*len < value.length()) {
360 1 : IDE_LOGE("input length(%u bytes) less than read message length(%zu bytes)", *len, value.length());
361 1 : *len = 0;
362 1 : return IDE_DAEMON_ERROR;
363 : }
364 19 : err = memcpy_s(*data, *len, value.c_str(), value.length());
365 19 : if (err != EOK) {
366 0 : IDE_LOGE("memcpy_s failed, result=%d.", err);
367 0 : *len = 0;
368 0 : return IDE_DAEMON_ERROR;
369 : }
370 19 : *len = value.length();
371 19 : return err;
372 27 : }
373 :
374 9 : static int32_t AdxServerCommProcess(
375 : AdxHdcServiceType type, AdxTlvConReq req, AdxStringBuffer result, uint32_t length, uint32_t timeout)
376 : {
377 9 : if (req == nullptr) {
378 2 : IDE_LOGE("invalid input, tlv struct is null");
379 2 : return IDE_DAEMON_ERROR;
380 : }
381 7 : if (req->len < 0) {
382 1 : IDE_LOGE("invalid input, length of tlv struct is %d bytes", req->len);
383 1 : return IDE_DAEMON_ERROR;
384 : }
385 6 : IdeTlvReq ide = static_cast<IdeTlvReq>(IdeXmalloc(sizeof(TlvReqT) + req->len));
386 6 : if (ide == nullptr) {
387 1 : IDE_LOGE("malloc ide tlv failed, size=%zu bytes", sizeof(TlvReqT) + req->len);
388 1 : return IDE_DAEMON_ERROR;
389 : }
390 5 : ide->type = GetReqTypeByComponentType(req->type);
391 5 : if (ide->type == NR_IDE_CMD_CLASS) {
392 1 : IDE_LOGE("invalid input, component type of tlv struct is %d", static_cast<int32_t>(req->type));
393 1 : IDE_XFREE_AND_SET_NULL(ide);
394 1 : return IDE_DAEMON_ERROR;
395 : }
396 4 : ide->dev_id = req->devId;
397 4 : ide->len = req->len;
398 4 : int32_t ret = memcpy_s(ide->value, ide->len, req->value, req->len);
399 4 : if (ret != EOK) {
400 1 : IDE_LOGE("memcpy_s from cmptype to req failed, result=%d", ret);
401 1 : IDE_XFREE_AND_SET_NULL(ide);
402 1 : return IDE_DAEMON_ERROR;
403 : }
404 3 : if (result == nullptr) {
405 2 : IDE_LOGI(
406 : "AdxDevCommShortLink, no results needed, cmpt=%d, cmd=%d, devId=%d", static_cast<int32_t>(req->type),
407 : static_cast<int32_t>(ide->type), ide->dev_id);
408 2 : ret = AdxSendMsgAndNoResultByType(type, ide);
409 : } else {
410 1 : IDE_LOGI(
411 : "AdxDevCommShortLink, result wait timeout:%u, cmpt=%d, cmd=%d, devId=%d", timeout,
412 : static_cast<int32_t>(req->type), static_cast<int32_t>(ide->type), ide->dev_id);
413 1 : (void)memset_s(result, length, 0, length);
414 1 : ret = AdxSendMsgToServerByType(type, ide, result, length, static_cast<int32_t>(timeout));
415 : }
416 3 : IDE_XFREE_AND_SET_NULL(ide);
417 3 : return ret;
418 : }
419 :
420 : /**
421 : * @brief : communication with the specific hdc server and get result if needed
422 : * @param [in] : type server type
423 : * @param [in] : req including device id, component type, message data
424 : * @param [in|out] : result get result data from device, pass nullptr if result is not needed
425 : * @param [in] : length result data length
426 : * @param [in] : timeout 0 : wait_always, > 0 wait_timeout; unit: ms
427 : * @return : IDE_DAEMON_OK succeed; others failed
428 : */
429 9 : int32_t AdxDevCommShortLink(
430 : AdxHdcServiceType type, AdxTlvConReq req, AdxStringBuffer result, uint32_t length, uint32_t timeout)
431 : {
432 9 : int32_t ret = AdxServerCommProcess(type, req, result, length, timeout);
433 9 : if ((ret != IDE_DAEMON_OK) && (result != nullptr) && (strlen(result) == 0)) {
434 5 : const std::string value = "get result data from server failed";
435 5 : int32_t err = strncpy_s(result, length, value.c_str(), value.length());
436 5 : if (err != EOK) {
437 1 : IDE_LOGE("strncpy_s null result data failed, result: %d.", err);
438 : }
439 5 : }
440 9 : return ret;
441 : }
|