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