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 : #include <list>
11 : #include "securec.h"
12 : #include "mmpa_api.h"
13 : #include "log/adx_log.h"
14 : #include "common/memory_utils.h"
15 : #include "common/config.h"
16 : #include "ide_os_type.h"
17 : #include "hdc_api.h"
18 :
19 : #define IDE_FREE_HDC_MSG_AND_SET_NULL(ptr) \
20 : do { \
21 : if ((ptr) != nullptr) { \
22 : (void)drvHdcFreeMsg(ptr); \
23 : ptr = nullptr; \
24 : } \
25 : } while (0)
26 :
27 : using namespace IdeDaemon::Common::Config;
28 :
29 : namespace Adx {
30 : struct DataSendMsg {
31 : IdeSendBuffT buf;
32 : int32_t bufLen;
33 : uint32_t maxSendLen;
34 : };
35 :
36 : /**
37 : * @brief initial HDC client
38 : * @param client: HDC initialization handle
39 : *
40 : * @return
41 : * IDE_DAEMON_OK: init succ
42 : * IDE_DAEMON_ERROR: init failed
43 : */
44 0 : int32_t HdcClientInit(HDC_CLIENT* client)
45 : {
46 : hdcError_t error;
47 0 : int32_t flag = 0;
48 0 : IDE_CTRL_VALUE_FAILED(client != nullptr, return IDE_DAEMON_ERROR, "client is nullptr");
49 :
50 : // create HDC client
51 0 : error = drvHdcClientCreate(client, MAX_SESSION_NUM, HDC_SERVICE_TYPE_IDE1, flag);
52 0 : if (error != DRV_ERROR_NONE || *client == nullptr) {
53 0 : IDE_LOGE("Hdc Client Create Failed, error: %d", error);
54 0 : return IDE_DAEMON_ERROR;
55 : }
56 :
57 0 : return IDE_DAEMON_OK;
58 : }
59 :
60 : /**
61 : * @brief crete HDC client
62 : * @param [in] client : HDC initialization handle
63 : * @param [in] type : create client hdc service type
64 : * @return
65 : * IDE_DAEMON_OK: init succ
66 : * IDE_DAEMON_ERROR: init failed
67 : */
68 38 : HDC_CLIENT HdcClientCreate(drvHdcServiceType type)
69 : {
70 : hdcError_t error;
71 38 : constexpr int32_t flag = 0;
72 38 : HDC_CLIENT client = nullptr;
73 :
74 : // create HDC client
75 38 : error = drvHdcClientCreate(&client, MAX_SESSION_NUM, type, flag);
76 38 : if (error != DRV_ERROR_NONE || client == nullptr) {
77 1 : IDE_LOGW("Can not create HDC client , ret: %d", error);
78 1 : return nullptr;
79 : }
80 :
81 37 : return client;
82 : }
83 :
84 : /**
85 : * @brief destroy HDC client
86 : * @param [in] client: HDC handle
87 : *
88 : * @return
89 : * IDE_DAEMON_OK: destroy succ
90 : * IDE_DAEMON_ERROR: destroy failed
91 : */
92 41 : int32_t HdcClientDestroy(HDC_CLIENT client)
93 : {
94 41 : if (client != nullptr) {
95 41 : const hdcError_t error = drvHdcClientDestroy(client);
96 41 : if (error != DRV_ERROR_NONE) {
97 0 : IDE_LOGE("Hdc Client Destroy error: %d", error);
98 0 : return IDE_DAEMON_ERROR;
99 : }
100 : }
101 :
102 41 : return IDE_DAEMON_OK;
103 : }
104 :
105 19 : HDC_SERVER HdcServerCreate(int32_t logDevId, drvHdcServiceType type)
106 : {
107 19 : HDC_SERVER server = nullptr;
108 19 : const hdcError_t error = drvHdcServerCreate(logDevId, type, &server);
109 19 : if (error == DRV_ERROR_DEVICE_NOT_READY) {
110 0 : IDE_LOGW("logDevId %d HDC not ready", logDevId);
111 0 : return nullptr;
112 : }
113 19 : if (error != DRV_ERROR_NONE) {
114 0 : IDE_LOGW("logDevId %d create HDC failed, error: %d", logDevId, error);
115 0 : return nullptr;
116 : }
117 19 : IDE_RUN_LOGI("logDevId %d create HDC server successfully", logDevId);
118 19 : return server;
119 : }
120 :
121 : /**
122 : * @brief destroy HDC server
123 : * @param [in] server: HDC server handle
124 : *
125 : * @return
126 : * IDE_DAEMON_OK: destroy succ
127 : * IDE_DAEMON_ERROR: destroy failed
128 : */
129 21 : int32_t HdcServerDestroy(HDC_SERVER server)
130 : {
131 21 : constexpr int32_t hdcMaxTimes = 30;
132 21 : constexpr uint32_t hdcWaitBaseSleepTime = 100U;
133 21 : hdcError_t error = DRV_ERROR_NONE;
134 :
135 21 : IDE_CTRL_VALUE_FAILED(server != nullptr, return IDE_DAEMON_ERROR, "server is nullptr");
136 21 : int32_t times = 0;
137 : do {
138 50 : error = drvHdcServerDestroy(server);
139 50 : if (error != DRV_ERROR_NONE) {
140 30 : IDE_LOGW("hdc server destroy error : %d, times %d", error, times);
141 30 : times++;
142 30 : (void)mmSleep(hdcWaitBaseSleepTime);
143 : }
144 50 : } while (times < hdcMaxTimes && error == DRV_ERROR_CLIENT_BUSY);
145 :
146 21 : if (times >= hdcMaxTimes && error == DRV_ERROR_CLIENT_BUSY) {
147 1 : return IDE_DAEMON_ERROR;
148 : }
149 20 : return IDE_DAEMON_OK;
150 : }
151 :
152 12 : HDC_SESSION HdcServerAccept(HDC_SERVER server)
153 : {
154 12 : HDC_SESSION session = nullptr;
155 12 : hdcError_t ret = drvHdcSessionAccept(server, &session);
156 12 : if (ret != DRV_ERROR_NONE || session == nullptr) {
157 1 : IDE_LOGW("hdc accept exception, ret: %d", static_cast<int32_t>(ret));
158 1 : return nullptr;
159 : }
160 :
161 11 : ret = drvHdcSetSessionReference(session);
162 11 : if (ret != DRV_ERROR_NONE) {
163 1 : IDE_LOGE("set reference error, ret: %d", static_cast<int32_t>(ret));
164 1 : (void)HdcSessionClose(session);
165 1 : return nullptr;
166 : }
167 10 : return session;
168 : }
169 :
170 : /**
171 : * @brief add iovec to list
172 : * @param [in] base : iovec slice of receive data
173 : * @param [out] ioList : iovec slice list
174 : */
175 5 : static void IoVecAddToList(struct IoVec& base, std::list<struct IoVec>& ioList)
176 : {
177 5 : if (base.base != nullptr && base.len > 0) {
178 5 : ioList.push_back(base);
179 5 : base.base = nullptr;
180 5 : base.len = 0;
181 : }
182 5 : }
183 :
184 : /**
185 : * @brief transfer iovec list to memory
186 : * @param [in] ioList : iovec slice list
187 : * @param [out] base : save receive data of all slice
188 : * @return IDE_DAEMON_OK : success
189 : */
190 1 : static int32_t IoVecListToMem(std::list<struct IoVec>& ioList, struct IoVec& base)
191 : {
192 1 : uint32_t offset = 0;
193 4 : for (const auto& eit : ioList) {
194 3 : if (base.len >= eit.len && offset <= base.len - eit.len) {
195 6 : const errno_t err = memcpy_s(
196 3 : static_cast<IdeU8Pt>(base.base) + offset, static_cast<size_t>(base.len - offset), eit.base,
197 3 : static_cast<size_t>(eit.len));
198 3 : if (err != EOK) {
199 0 : return IDE_DAEMON_ERROR;
200 : }
201 : }
202 3 : offset += eit.len;
203 : }
204 1 : return IDE_DAEMON_OK;
205 : }
206 :
207 : /**
208 : * @brief free list of iovec
209 : * @param [in] ioList ide daemon hdc client
210 : */
211 5 : static void IoVecListFree(std::list<struct IoVec>& ioList)
212 : {
213 10 : for (auto& eit : ioList) {
214 5 : IDE_XFREE_AND_SET_NULL(eit.base);
215 : }
216 5 : ioList.clear();
217 5 : }
218 :
219 : /**
220 : * @brief get packet to recv_buf
221 : * @param packet: HDC packet
222 : * @param ioVec: a buffer that stores the result
223 : *
224 : * @return
225 : * IDE_DAEMON_OK: store data succ
226 : * IDE_DAEMON_ERROR: store data failed
227 : */
228 6 : int32_t HdcStorePackage(const IdeHdcPacket& packet, struct IoVec& ioVec)
229 : {
230 6 : IdeStringBuffer buf = reinterpret_cast<IdeStringBuffer>(ioVec.base);
231 : // little package packet type
232 6 : if (packet.type == IdeDaemonPackageType::IDE_DAEMON_LITTLE_PACKAGE) {
233 6 : if ((static_cast<uint64_t>(ioVec.len) + packet.len) > UINT32_MAX) {
234 0 : IDE_LOGE("buffer length: %u bytes, packet length: %u bytes", ioVec.len, packet.len);
235 0 : return IDE_DAEMON_ERROR;
236 : }
237 :
238 6 : const uint32_t len = ioVec.len + packet.len;
239 : // malloc new buffer for adding new data
240 : IdeStringBuffer newBuf =
241 6 : static_cast<IdeStringBuffer>(IdeXrmalloc(buf, static_cast<size_t>(ioVec.len), static_cast<size_t>(len)));
242 6 : if (newBuf == nullptr) {
243 0 : IDE_LOGE("Ide Xrmalloc Failed");
244 0 : return IDE_DAEMON_ERROR;
245 : }
246 6 : IDE_XFREE_AND_SET_NULL(buf);
247 6 : buf = newBuf;
248 : // add new package data
249 : const errno_t ret =
250 6 : memcpy_s(buf + ioVec.len, static_cast<size_t>(packet.len), packet.value, static_cast<size_t>(packet.len));
251 6 : if (ret != EOK) {
252 0 : IDE_LOGE("memory copy failed, ret: %d", ret);
253 0 : IDE_XFREE_AND_SET_NULL(buf);
254 0 : return IDE_DAEMON_ERROR;
255 : }
256 :
257 6 : ioVec.len = len;
258 6 : ioVec.base = buf;
259 6 : return IDE_DAEMON_OK;
260 : }
261 :
262 0 : return IDE_DAEMON_ERROR;
263 : }
264 :
265 5 : static int32_t HdcReadPackage(struct drvHdcMsg& pmsg, IdeLastPacket& isLast, int32_t recvBufCount, struct IoVec& ioVec)
266 : {
267 5 : IdeStringBuffer pBuf = nullptr;
268 5 : int32_t pBufLen = 0;
269 : // Traverse the descriptor and fetch the read buf
270 5 : int32_t i = 0;
271 11 : for (; i < recvBufCount; i++) {
272 7 : const hdcError_t error = drvHdcGetMsgBuffer(&pmsg, i, &pBuf, &pBufLen);
273 7 : IDE_CTRL_VALUE_FAILED(error == DRV_ERROR_NONE, return IDE_DAEMON_ERROR, "Hdc Get Msg Buffer, error %d", error);
274 7 : if (pBuf != nullptr && pBufLen > 0) {
275 7 : struct IdeHdcPacket* packet = reinterpret_cast<struct IdeHdcPacket*>(pBuf);
276 7 : IDE_CTRL_VALUE_FAILED(
277 : static_cast<uint32_t>(pBufLen) >= sizeof(IdeHdcPacket) + packet->len, return IDE_DAEMON_ERROR,
278 : "packet len is larger than pBufLen");
279 : // store package by packet type
280 6 : const int32_t err = HdcStorePackage(*packet, ioVec);
281 6 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return IDE_DAEMON_ERROR, "Hdc store package, error");
282 : // receive the last package is true
283 6 : if (packet->isLast == IdeLastPacket::IDE_LAST_PACK) {
284 1 : isLast = IdeLastPacket::IDE_LAST_PACK;
285 : }
286 : }
287 : }
288 :
289 4 : return IDE_DAEMON_OK;
290 : }
291 :
292 : /**
293 : * @brief transfer iovec list to memory of hdc read data
294 : * @param [in] hdcIoList : iovec slice list of hdc data
295 : * @param [in] bufLen : length of hdc data
296 : * @param [out] recvBuf : memory of hdc data
297 : * @param [out] recvLen : length of hdc data
298 : * @return IDE_DAEMON_OK : success; IDE_DAEMON_ERROR:failed
299 : */
300 1 : static int32_t HdcReadIovecToMem(
301 : std::list<struct IoVec>& hdcIoList, uint32_t bufLen, IdeRecvBuffT recvBuf, IdeI32Pt recvLen)
302 : {
303 1 : struct IoVec ioBase = {nullptr, 0};
304 1 : IDE_CTRL_VALUE_FAILED(recvBuf != nullptr, return IDE_DAEMON_ERROR, "recvBuf is nullptr");
305 1 : IDE_CTRL_VALUE_FAILED(recvLen != nullptr, return IDE_DAEMON_ERROR, "recvLen is nullptr");
306 1 : IDE_CTRL_VALUE_FAILED(bufLen > 0, return IDE_DAEMON_ERROR, "bufLen is nullptr");
307 1 : IdeStringBuffer buf = static_cast<IdeStringBuffer>(IdeXmalloc(bufLen));
308 1 : if (buf == nullptr) {
309 0 : IoVecListFree(hdcIoList);
310 0 : return IDE_DAEMON_ERROR;
311 : }
312 1 : ioBase.base = buf;
313 1 : ioBase.len = bufLen;
314 1 : if (IoVecListToMem(hdcIoList, ioBase) == IDE_DAEMON_ERROR) {
315 0 : IoVecListFree(hdcIoList);
316 0 : IDE_XFREE_AND_SET_NULL(buf);
317 0 : return IDE_DAEMON_ERROR;
318 : }
319 1 : IoVecListFree(hdcIoList);
320 1 : *recvBuf = buf;
321 1 : *recvLen = bufLen;
322 1 : return IDE_DAEMON_OK;
323 : }
324 :
325 4 : static inline void HdcReadBuffFree(struct drvHdcMsg* pmsg, std::list<struct IoVec>& ioList)
326 : {
327 4 : IDE_FREE_HDC_MSG_AND_SET_NULL(pmsg);
328 4 : IoVecListFree(ioList);
329 4 : }
330 :
331 7 : static int32_t HdcRecvData(
332 : HDC_SESSION session, struct drvHdcMsg* pmsg, int32_t nbFlag, int32_t* recvBufCount, uint32_t timeout)
333 : {
334 7 : uint32_t len = 0;
335 7 : const hdcError_t error = halHdcRecv(session, pmsg, len, nbFlag, recvBufCount, timeout);
336 7 : if (error != DRV_ERROR_NONE) {
337 2 : if (error == DRV_ERROR_NON_BLOCK) {
338 0 : return IDE_DAEMON_RECV_NODATA;
339 : }
340 2 : if (error == DRV_ERROR_SOCKET_CLOSE) {
341 0 : IDE_LOGW("Session(%p) is closed.", session);
342 0 : return IDE_DAEMON_SOCK_CLOSE;
343 : }
344 2 : if (error == DRV_ERROR_WAIT_TIMEOUT) {
345 : // Do not add any log print here to avoid potential blocking issue
346 1 : return DRV_ERROR_WAIT_TIMEOUT;
347 : }
348 1 : IDE_LOGE("Hdc Receive, error %d", error);
349 1 : return IDE_DAEMON_ERROR;
350 : }
351 5 : return IDE_DAEMON_OK;
352 : }
353 : /**
354 : * @brief get data from hdc session
355 : * @param session: HDC session
356 : * @param recv_buf: a buffer that stores the result
357 : * @param recv_len: the length of recv_buf
358 : * @param nb_flag: IDE_DAEMON_HDC_BLOCK: read by block mode; IDE_DAEMON_HDC_NOBLOCK: read by non-block mode
359 : *
360 : * @return
361 : * IDE_DAEMON_OK: read succ
362 : * IDE_DAEMON_ERROR: read failed
363 : */
364 13 : static int32_t HdcSessionRead(
365 : HDC_SESSION session, const IdeRecvBuffT recvBuf, const IdeI32Pt recvLen, int32_t nbFlag, uint32_t timeout)
366 : {
367 13 : struct drvHdcMsg* pmsg = nullptr;
368 13 : constexpr int32_t count = 1;
369 13 : int32_t recvBufCount = 0;
370 13 : IdeLastPacket isLast = IdeLastPacket::IDE_NOT_LAST_PACK;
371 13 : uint32_t bufLen = 0;
372 13 : std::list<struct IoVec> hdcIoList;
373 13 : struct IoVec ioBase = {nullptr, 0};
374 :
375 13 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
376 13 : IDE_CTRL_VALUE_FAILED(recvBuf != nullptr, return IDE_DAEMON_ERROR, "recv_buf is nullptr");
377 13 : IDE_CTRL_VALUE_FAILED(recvLen != nullptr, return IDE_DAEMON_ERROR, "recv_len is nullptr");
378 :
379 : // 1.request alloc hdc message, count is 1
380 13 : hdcError_t error = drvHdcAllocMsg(session, &pmsg, count);
381 13 : IDE_CTRL_VALUE_FAILED(
382 : (error == DRV_ERROR_NONE) && (pmsg != nullptr), return IDE_DAEMON_ERROR, "Hdc Alloc Msg, error %d", error);
383 5 : uint32_t pkgCount = 0;
384 : while (true) {
385 : // 2.Receive data, since the count is 1 when applying the descriptor, read up to 1 buf at a time.
386 : // len no use just for parameter
387 7 : int32_t err = HdcRecvData(session, pmsg, nbFlag, &recvBufCount, timeout);
388 7 : if (err == IDE_DAEMON_ERROR) {
389 1 : IDE_LOGE("receive data failed, err=%d, package count=%u", err, pkgCount);
390 : }
391 7 : if (err != IDE_DAEMON_OK) {
392 2 : HdcReadBuffFree(pmsg, hdcIoList);
393 2 : return err;
394 : }
395 :
396 5 : pkgCount++;
397 : // 3.trans read data to Iolist
398 5 : err = HdcReadPackage(*pmsg, isLast, recvBufCount, ioBase);
399 5 : bufLen += ioBase.len;
400 5 : IoVecAddToList(ioBase, hdcIoList);
401 5 : if (err != IDE_DAEMON_OK) {
402 1 : HdcReadBuffFree(pmsg, hdcIoList);
403 1 : IDE_LOGE("read package by hdc failed, err=%d, package count=%u", err, pkgCount);
404 1 : return IDE_DAEMON_ERROR;
405 : }
406 : // if isLast is true the last package is received, not receive again;
407 4 : if (isLast == IdeLastPacket::IDE_LAST_PACK) {
408 1 : IDE_LOGD("receive last package, package count=%u", pkgCount);
409 1 : break;
410 : }
411 :
412 : // 4.reuse hdc message
413 3 : error = drvHdcReuseMsg(pmsg);
414 3 : if (error != DRV_ERROR_NONE) {
415 1 : HdcReadBuffFree(pmsg, hdcIoList);
416 1 : IDE_LOGE("reuse message by hdc failed, error=%d, package count=%u", error, pkgCount);
417 1 : return IDE_DAEMON_ERROR;
418 : }
419 2 : }
420 :
421 : // 5.free hdc message
422 1 : error = drvHdcFreeMsg(pmsg);
423 1 : pmsg = nullptr;
424 1 : if (error != DRV_ERROR_NONE) {
425 0 : HdcReadBuffFree(pmsg, hdcIoList);
426 0 : IDE_LOGE("Hdc Free Msg, error: %d", error);
427 0 : return IDE_DAEMON_ERROR;
428 : }
429 :
430 1 : return HdcReadIovecToMem(hdcIoList, bufLen, recvBuf, recvLen);
431 13 : }
432 :
433 : /**
434 : * @brief get data from hdc session by block mode
435 : * @param session: HDC session
436 : * @param recv_buf: a buffer that stores the result
437 : * @param recv_len: the length of recv_buf
438 : *
439 : * @return
440 : * IDE_DAEMON_OK: read succ
441 : * IDE_DAEMON_ERROR: read failed
442 : */
443 2 : int32_t HdcRead(HDC_SESSION session, IdeRecvBuffT recvBuf, IdeI32Pt recvLen)
444 : {
445 2 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
446 2 : IDE_CTRL_VALUE_FAILED(recvBuf != nullptr, return IDE_DAEMON_ERROR, "recv_buf is nullptr");
447 2 : IDE_CTRL_VALUE_FAILED(recvLen != nullptr, return IDE_DAEMON_ERROR, "recv_len is nullptr");
448 :
449 2 : return HdcSessionRead(session, recvBuf, recvLen, IDE_DAEMON_BLOCK, 0);
450 : }
451 :
452 : /**
453 : * @brief get data from hdc session by non-block mode
454 : * @param session: HDC session
455 : * @param recv_buf: a buffer that stores the result
456 : * @param recv_len: the length of recv_buf
457 : *
458 : * @return
459 : * IDE_DAEMON_OK: read succ
460 : * IDE_DAEMON_ERROR: read failed
461 : */
462 1 : int32_t HdcReadNb(HDC_SESSION session, IdeRecvBuffT recvBuf, IdeI32Pt recvLen)
463 : {
464 1 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
465 1 : IDE_CTRL_VALUE_FAILED(recvBuf != nullptr, return IDE_DAEMON_ERROR, "recv_buf is nullptr");
466 1 : IDE_CTRL_VALUE_FAILED(recvLen != nullptr, return IDE_DAEMON_ERROR, "recv_len is nullptr");
467 :
468 1 : return HdcSessionRead(session, recvBuf, recvLen, IDE_DAEMON_NOBLOCK, 0);
469 : }
470 :
471 : /**
472 : * @brief get data from hdc session by non-block mode
473 : * @param session: HDC session
474 : * @param timeout: max wait time
475 : * @param recv_buf: a buffer that stores the result
476 : * @param recv_len: the length of recv_buf
477 : *
478 : * @return
479 : * IDE_DAEMON_OK: read succ
480 : * IDE_DAEMON_ERROR: read failed
481 : */
482 10 : int32_t HdcReadTimeout(HDC_SESSION session, uint32_t timeout, IdeRecvBuffT recvBuf, IdeI32Pt recvLen)
483 : {
484 10 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
485 10 : IDE_CTRL_VALUE_FAILED(recvBuf != nullptr, return IDE_DAEMON_ERROR, "recv_buf is nullptr");
486 10 : IDE_CTRL_VALUE_FAILED(recvLen != nullptr, return IDE_DAEMON_ERROR, "recv_len is nullptr");
487 :
488 10 : return HdcSessionRead(session, recvBuf, recvLen, IDE_DAEMON_TIMEOUT, timeout);
489 : }
490 :
491 : /**
492 : * @brief send data through hdc
493 : * @param session: HDC session
494 : * @param dataSendMsg: send buffer and length
495 : * @param pmsg: the pointer to send data to hdc driver
496 : * @param packet: the pointer of send packet
497 : *
498 : * @return
499 : * DRV_ERROR_NONE: send succ
500 : * others: send failed
501 : */
502 5 : static hdcError_t HdcWritePackage(
503 : HDC_SESSION session, DataSendMsg dataSendMsg, struct drvHdcMsg* pmsg, struct IdeHdcPacket* packet, int32_t flag)
504 : {
505 5 : hdcError_t hdcError = DRV_ERROR_NONE;
506 5 : uint32_t reservedLen = dataSendMsg.bufLen;
507 5 : uint32_t totalLen = reservedLen;
508 5 : uint32_t sendLen = 0;
509 5 : IdeSendBuffT buf = dataSendMsg.buf;
510 5 : uint32_t timeout = 0;
511 :
512 5 : IDE_CTRL_VALUE_FAILED(session != nullptr, return DRV_ERROR_INVALID_VALUE, "session is nullptr");
513 5 : IDE_CTRL_VALUE_FAILED(buf != nullptr, return DRV_ERROR_INVALID_VALUE, "buf is nullptr");
514 5 : IDE_CTRL_VALUE_FAILED(pmsg != nullptr, return DRV_ERROR_INVALID_VALUE, "pmsg is nullptr");
515 5 : IDE_CTRL_VALUE_FAILED(packet != nullptr, return DRV_ERROR_INVALID_VALUE, "packet is nullptr");
516 :
517 : do {
518 : // calculate package data size for this time
519 : // if reserved data size is bigger than the max size which should subcontract package
520 5 : if (reservedLen > dataSendMsg.maxSendLen) {
521 0 : sendLen = dataSendMsg.maxSendLen;
522 0 : packet->isLast = IdeLastPacket::IDE_NOT_LAST_PACK;
523 : } else {
524 5 : sendLen = reservedLen;
525 5 : packet->isLast = IdeLastPacket::IDE_LAST_PACK;
526 : }
527 5 : packet->type = IdeDaemonPackageType::IDE_DAEMON_LITTLE_PACKAGE;
528 5 : packet->len = sendLen;
529 :
530 10 : const errno_t ret = memcpy_s(
531 5 : packet->value, dataSendMsg.maxSendLen,
532 5 : static_cast<IdeU8Pt>(const_cast<IdeBuffT>(buf)) + (totalLen - reservedLen), sendLen);
533 5 : IDE_CTRL_VALUE_FAILED(ret == EOK, return DRV_ERROR_INVALID_VALUE, "memory copy failed");
534 :
535 : // add buffer to hdc message
536 10 : hdcError = drvHdcAddMsgBuffer(
537 5 : pmsg, reinterpret_cast<IdeStringBuffer>(packet), sizeof(struct IdeHdcPacket) + packet->len);
538 5 : IDE_CTRL_VALUE_FAILED(hdcError == DRV_ERROR_NONE, return hdcError, "Hdc Add Msg Buffer, error: %d", hdcError);
539 :
540 : // send hdc message
541 5 : hdcError = halHdcSend(session, pmsg, flag, timeout);
542 5 : IDE_CTRL_VALUE_WARN(
543 : hdcError == DRV_ERROR_NONE, return hdcError, "Hdc Send, error: %d, session: %zu", hdcError,
544 : reinterpret_cast<uintptr_t>(session));
545 :
546 : // reuse hdc message
547 5 : hdcError = drvHdcReuseMsg(pmsg);
548 5 : IDE_CTRL_VALUE_FAILED(hdcError == DRV_ERROR_NONE, return hdcError, "Hdc Reuse Msg, error: %d", hdcError);
549 :
550 5 : reservedLen -= sendLen;
551 5 : } while (reservedLen > 0 && hdcError == DRV_ERROR_NONE);
552 :
553 5 : return hdcError;
554 : }
555 :
556 : /**
557 : * @brief write data by hdc session
558 : * @param session: HDC session
559 : * @param buf: a buffer that store data to send
560 : * @param len: the length of buffer
561 : *
562 : * @return
563 : * IDE_DAEMON_OK: write succ
564 : * IDE_DAEMON_ERROR: write failed
565 : */
566 13 : int32_t HdcSessionWrite(HDC_SESSION session, IdeSendBuffT buf, int32_t len, int32_t flag)
567 : {
568 : hdcError_t hdcError;
569 13 : struct drvHdcMsg* pmsg = nullptr;
570 13 : constexpr int32_t count = 1;
571 13 : uint32_t capacity = 0;
572 13 : struct IdeHdcPacket* packet = nullptr;
573 :
574 13 : IDE_CTRL_VALUE_FAILED(
575 : (session != nullptr && buf != nullptr && len > 0), return IDE_DAEMON_ERROR, "Invalid Parameter");
576 :
577 13 : const int32_t err = HdcCapacity(&capacity);
578 13 : IDE_CTRL_VALUE_FAILED(err == IDE_DAEMON_OK, return IDE_DAEMON_ERROR, "Hdc Capacity Failed, err: %d", err);
579 :
580 : // 1.request alloc hdc message, count is 1
581 12 : hdcError = drvHdcAllocMsg(session, &pmsg, count);
582 12 : IDE_CTRL_VALUE_FAILED(
583 : (hdcError == DRV_ERROR_NONE) && (pmsg != nullptr), return IDE_DAEMON_ERROR, "Hdc Alloc Msg, error: %d",
584 : hdcError);
585 :
586 6 : const uint32_t maxDatalen = capacity - sizeof(struct IdeHdcPacket);
587 6 : const size_t packetLen = sizeof(struct IdeHdcPacket) + maxDatalen;
588 6 : packet = static_cast<struct IdeHdcPacket*>(IdeXmalloc(packetLen));
589 6 : if (packet == nullptr) {
590 1 : IDE_LOGE("IdeXmalloc %zu bytes failed", packetLen);
591 1 : IDE_FREE_HDC_MSG_AND_SET_NULL(pmsg);
592 1 : return IDE_DAEMON_ERROR;
593 : }
594 :
595 5 : struct DataSendMsg dataSendMsg = {buf, len, maxDatalen};
596 5 : hdcError = HdcWritePackage(session, dataSendMsg, pmsg, packet, flag);
597 :
598 : // free packet
599 5 : IDE_XFREE_AND_SET_NULL(packet);
600 :
601 : // 6. free hdc message
602 5 : const hdcError_t ret = drvHdcFreeMsg(pmsg);
603 5 : IDE_CTRL_VALUE_FAILED(ret == DRV_ERROR_NONE, return IDE_DAEMON_ERROR, "Hdc Free Msg, error: %d", ret);
604 5 : pmsg = nullptr;
605 :
606 5 : return hdcError == DRV_ERROR_NONE ? IDE_DAEMON_OK :
607 5 : (hdcError == DRV_ERROR_SOCKET_CLOSE ? IDE_DAEMON_SOCK_CLOSE : IDE_DAEMON_ERROR);
608 : }
609 :
610 : /**
611 : * @brief write data by hdc session
612 : * @param session: HDC session
613 : * @param buf: a buffer that store data to send
614 : * @param len: the length of buffer
615 : *
616 : * @return
617 : * IDE_DAEMON_OK: write succ
618 : * IDE_DAEMON_ERROR: write failed
619 : */
620 13 : int32_t HdcWrite(HDC_SESSION session, IdeSendBuffT buf, int32_t len)
621 : {
622 13 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
623 12 : IDE_CTRL_VALUE_FAILED(buf != nullptr, return IDE_DAEMON_ERROR, "buf is nullptr");
624 12 : IDE_CTRL_VALUE_FAILED(len > 0, return IDE_DAEMON_ERROR, "len is invalid");
625 :
626 12 : return HdcSessionWrite(session, buf, len, IDE_DAEMON_BLOCK);
627 : }
628 :
629 : /**
630 : * @brief write data by hdc session
631 : * @param session: HDC session
632 : * @param buf: a buffer that store data to send
633 : * @param len: the length of buffer
634 : *
635 : * @return
636 : * IDE_DAEMON_OK: write succ
637 : * IDE_DAEMON_ERROR: write failed
638 : */
639 1 : int32_t HdcWriteNb(HDC_SESSION session, IdeSendBuffT buf, int32_t len)
640 : {
641 1 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
642 1 : IDE_CTRL_VALUE_FAILED(buf != nullptr, return IDE_DAEMON_ERROR, "buf is nullptr");
643 1 : IDE_CTRL_VALUE_FAILED(len > 0, return IDE_DAEMON_ERROR, "len is invalid");
644 :
645 1 : return HdcSessionWrite(session, buf, len, IDE_DAEMON_NOBLOCK);
646 : }
647 :
648 : /**
649 : * @brief connect remote hdc server
650 : * @param peer_node: Node number of the node where Device is located
651 : * @param peer_devid: Device ID of the unified number in the host
652 : * @param client: HDC Client handle corresponding to the newly created Session
653 : * @param session: created session
654 : *
655 : * @return
656 : * IDE_DAEMON_OK: connect succ
657 : * IDE_DAEMON_ERROR: connect failed
658 : */
659 38 : int32_t HdcSessionConnect(int32_t peerNode, int32_t peerDevId, HDC_CLIENT client, HDC_SESSION* session)
660 : {
661 38 : IDE_CTRL_VALUE_FAILED(peerNode >= 0, return IDE_DAEMON_ERROR, "peer_node is invalid");
662 38 : IDE_CTRL_VALUE_FAILED(peerDevId >= 0, return IDE_DAEMON_ERROR, "peer_devid is invalid");
663 38 : IDE_CTRL_VALUE_FAILED(client != nullptr, return IDE_DAEMON_ERROR, "client is nullptr");
664 38 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
665 :
666 : // hdc connect
667 38 : hdcError_t error = drvHdcSessionConnect(peerNode, peerDevId, client, session);
668 38 : if (error != DRV_ERROR_NONE || *session == nullptr) {
669 2 : IDE_LOGW("Hdc session connect exception, ret: %d", error);
670 2 : return IDE_DAEMON_ERROR;
671 : }
672 :
673 36 : error = drvHdcSetSessionReference(*session);
674 36 : if (error != DRV_ERROR_NONE) {
675 1 : IDE_LOGE("set reference error, error: %d", static_cast<int32_t>(error));
676 1 : (void)HdcSessionClose(*session);
677 1 : return IDE_DAEMON_ERROR;
678 : }
679 :
680 35 : IDE_LOGI("connect succ, peer_node: %d, peer_devid: %d", peerNode, peerDevId);
681 35 : return IDE_DAEMON_OK;
682 : }
683 :
684 : /**
685 : * @brief connect remote hal hdc server
686 : * @param peer_node: Node number of the node where Device is located
687 : * @param peer_devid: Device ID of the unified number in the host
688 : * @param host_pid: pid of host app process
689 : * @param client: HDC Client handle corresponding to the newly created Session
690 : * @param session: created session
691 : *
692 : * @return
693 : * IDE_DAEMON_OK: connect succ
694 : * IDE_DAEMON_ERROR: connect failed
695 : */
696 5 : int32_t HalHdcSessionConnect(
697 : int32_t peerNode, int32_t peerDevId, int32_t hostPid, HDC_CLIENT client, HDC_SESSION* session)
698 : {
699 5 : IDE_CTRL_VALUE_FAILED(peerNode >= 0, return IDE_DAEMON_ERROR, "peer_node is invalid");
700 5 : IDE_CTRL_VALUE_FAILED(peerDevId >= 0, return IDE_DAEMON_ERROR, "peer_devid is invalid");
701 5 : IDE_CTRL_VALUE_FAILED(hostPid >= 0, return IDE_DAEMON_ERROR, "host_pid is invalid");
702 5 : IDE_CTRL_VALUE_FAILED(client != nullptr, return IDE_DAEMON_ERROR, "client is nullptr");
703 5 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
704 :
705 : // hdc connect
706 5 : hdcError_t error = halHdcSessionConnectEx(peerNode, peerDevId, hostPid, client, session);
707 5 : if (error != DRV_ERROR_NONE || *session == nullptr) {
708 1 : IDE_LOGW("Hdc session connect exception, ret: %d", error);
709 1 : return IDE_DAEMON_ERROR;
710 : }
711 :
712 4 : error = drvHdcSetSessionReference(*session);
713 4 : if (error != DRV_ERROR_NONE) {
714 1 : IDE_LOGE("set reference error, error: %d", static_cast<int32_t>(error));
715 1 : (void)HdcSessionClose(*session);
716 1 : return IDE_DAEMON_ERROR;
717 : }
718 :
719 3 : IDE_LOGI("connect succ, peer_node: %d, peer_devid: %d, host_pid: %d", peerNode, peerDevId, hostPid);
720 3 : return IDE_DAEMON_OK;
721 : }
722 :
723 : /**
724 : * @brief destroy hdc_connect session
725 : * @param session: the session created by hdc connect
726 : *
727 : * @return
728 : * IDE_DAEMON_OK: destroy succ
729 : * IDE_DAEMON_ERROR: destroy failed
730 : */
731 12 : int32_t HdcSessionDestroy(HDC_SESSION session)
732 : {
733 12 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
734 :
735 12 : return HdcSessionClose(session);
736 : }
737 :
738 : /**
739 : * @brief destroy hdc_accpet session
740 : * @param session: the session created by hdc_accept
741 : *
742 : * @return
743 : * IDE_DAEMON_OK: close succ
744 : * IDE_DAEMON_ERROR: close failed
745 : */
746 52 : int32_t HdcSessionClose(HDC_SESSION session)
747 : {
748 52 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
749 :
750 : // close hdc session, use for hdc_accept session
751 52 : const hdcError_t error = drvHdcSessionClose(session);
752 52 : if (error != DRV_ERROR_NONE) {
753 0 : IDE_LOGE("Hdc Session Close Failed, error: %d", error);
754 0 : return IDE_DAEMON_ERROR;
755 : }
756 :
757 52 : return IDE_DAEMON_OK;
758 : }
759 :
760 : /**
761 : * @brief get hdc capacity
762 : * @param segment: hdc max segment size
763 : *
764 : * @return
765 : * IDE_DAEMON_OK: read succ
766 : * IDE_DAEMON_ERROR: read failed
767 : */
768 13 : int32_t HdcCapacity(IdeU32Pt segment)
769 : {
770 : hdcError_t error;
771 13 : struct drvHdcCapacity capacity = {HDC_CHAN_TYPE_MAX, 0};
772 :
773 13 : error = drvHdcGetCapacity(&capacity);
774 13 : if (error != DRV_ERROR_NONE) {
775 0 : IDE_LOGE("Get Hdc Capacity Failed,error: %d", error);
776 0 : return IDE_DAEMON_ERROR;
777 : }
778 13 : uint32_t maxSegment = capacity.maxSegment;
779 13 : if (maxSegment > IDE_MAX_HDC_SEGMENT || maxSegment < IDE_MIN_HDC_SEGMENT) {
780 1 : IDE_LOGE("Get Hdc Capacity Segment Invalid: %u", capacity.maxSegment);
781 1 : return IDE_DAEMON_ERROR;
782 : }
783 :
784 12 : if (segment != nullptr) {
785 12 : *segment = capacity.maxSegment;
786 12 : return IDE_DAEMON_OK;
787 : }
788 :
789 0 : return IDE_DAEMON_ERROR;
790 : }
791 :
792 : /**
793 : * @brief get device id by HDC session
794 : * @param session: hdc session handle
795 : *
796 : * @return
797 : * IDE_DAEMON_OK: get hdc session succ
798 : * IDE_DAEMON_ERROR: get hdc session failed
799 : */
800 6 : int32_t IdeGetDevIdBySession(HDC_SESSION session, IdeI32Pt devId)
801 : {
802 6 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
803 6 : IDE_CTRL_VALUE_FAILED(devId != nullptr, return IDE_DAEMON_ERROR, "devId is nullptr");
804 :
805 : #if (OS_TYPE != WIN)
806 6 : const hdcError_t err = halHdcGetSessionAttr(session, HDC_SESSION_ATTR_DEV_ID, devId);
807 6 : if (err != DRV_ERROR_NONE) {
808 0 : IDE_LOGE("Hdc Get Session DevId Failed, err: %d", err);
809 0 : return IDE_DAEMON_ERROR;
810 : }
811 : #else
812 : *devId = 0;
813 : #endif
814 :
815 6 : return IDE_DAEMON_OK;
816 : }
817 :
818 : /**
819 : * @brief get env info by HDC session, is docker or not
820 : * @param session: hdc session handle
821 : * @param runEnv: 1 non-docker 2 docker
822 : *
823 : * @return
824 : * IDE_DAEMON_OK: get hdc session succ
825 : * IDE_DAEMON_ERROR: get hdc session failed
826 : */
827 1 : int32_t IdeGetRunEnvBySession(HDC_SESSION session, IdeI32Pt runEnv)
828 : {
829 1 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
830 1 : IDE_CTRL_VALUE_FAILED(runEnv != nullptr, return IDE_DAEMON_ERROR, "runEnv is nullptr");
831 :
832 : #if (OS_TYPE != WIN)
833 1 : hdcError_t err = halHdcGetSessionAttr(session, HDC_SESSION_ATTR_RUN_ENV, runEnv);
834 1 : if (err != DRV_ERROR_NONE) {
835 0 : IDE_LOGE("Hdc Get Session runEnv Failed, err: %d", err);
836 0 : return IDE_DAEMON_ERROR;
837 : }
838 : #else
839 : *runEnv = 1;
840 : #endif
841 :
842 1 : return IDE_DAEMON_OK;
843 : }
844 :
845 : /**
846 : * @brief get vfid by HDC session
847 : * @param session: hdc session handle
848 : *
849 : * @return
850 : * IDE_DAEMON_OK: get hdc session succ
851 : * IDE_DAEMON_ERROR: get hdc session failed
852 : */
853 1 : int32_t IdeGetVfIdBySession(HDC_SESSION session, IdeI32Pt vfId)
854 : {
855 1 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
856 1 : IDE_CTRL_VALUE_FAILED(vfId != nullptr, return IDE_DAEMON_ERROR, "vfId is nullptr");
857 :
858 : #if (OS_TYPE != WIN)
859 1 : hdcError_t err = halHdcGetSessionAttr(session, HDC_SESSION_ATTR_VFID, vfId);
860 1 : if (err != DRV_ERROR_NONE) {
861 0 : IDE_LOGE("Hdc Get Session VfId Failed, err: %d", err);
862 0 : return IDE_DAEMON_ERROR;
863 : }
864 : #else
865 : *vfId = 0;
866 : #endif
867 :
868 1 : return IDE_DAEMON_OK;
869 : }
870 :
871 : /**
872 : * @brief get pid info by HDC session
873 : * @param session: hdc session handle
874 : * @param pid: app pid
875 : *
876 : * @return
877 : * IDE_DAEMON_OK: get hdc session succ
878 : * IDE_DAEMON_ERROR: get hdc session failed
879 : */
880 1 : int32_t IdeGetPidBySession(HDC_SESSION session, IdeI32Pt pid)
881 : {
882 1 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
883 1 : IDE_CTRL_VALUE_FAILED(pid != nullptr, return IDE_DAEMON_ERROR, "pid is nullptr");
884 :
885 : #if (OS_TYPE != WIN)
886 1 : const hdcError_t err = halHdcGetSessionAttr(session, HDC_SESSION_ATTR_PEER_CREATE_PID, pid);
887 1 : if (err != DRV_ERROR_NONE) {
888 0 : IDE_LOGE("Hdc Get Session runEnv Failed, err: %d", err);
889 0 : return IDE_DAEMON_ERROR;
890 : }
891 : #else
892 : *pid = 0;
893 : #endif
894 :
895 1 : return IDE_DAEMON_OK;
896 : }
897 :
898 : /**
899 : * @brief : get attribute value by HDC session and attribute type
900 : * @param [in] : handle hdc session
901 : * @param [in] : attr attribute type
902 : * @param [out] : value attribute value
903 : * @return : IDE_DAEMON_OK succeed; IDE_DAEMON_ERROR failed
904 : */
905 6 : int32_t IdeGetAttrBySession(HDC_SESSION session, int32_t attr, IdeI32Pt value)
906 : {
907 6 : IDE_CTRL_VALUE_FAILED(session != nullptr, return IDE_DAEMON_ERROR, "session is nullptr");
908 6 : IDE_CTRL_VALUE_FAILED(value != nullptr, return IDE_DAEMON_ERROR, "value is nullptr");
909 :
910 : #if (OS_TYPE != WIN)
911 6 : const hdcError_t err = halHdcGetSessionAttr(session, attr, value);
912 6 : if (err != DRV_ERROR_NONE) {
913 1 : IDE_LOGE("Hdc get attribute value failed, err: %d", err);
914 1 : return IDE_DAEMON_ERROR;
915 : }
916 : #else
917 : *value = 0;
918 : #endif
919 :
920 5 : return IDE_DAEMON_OK;
921 : }
922 : } // namespace Adx
|