1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "ddk_device_manager.h"
17094332d3Sopenharmony_ci
18094332d3Sopenharmony_ci#include <ctype.h>
19094332d3Sopenharmony_ci#include <dirent.h>
20094332d3Sopenharmony_ci#include <fcntl.h>
21094332d3Sopenharmony_ci#include <unistd.h>
22094332d3Sopenharmony_ci
23094332d3Sopenharmony_ci#include "ddk_sysfs_device.h"
24094332d3Sopenharmony_ci#include "hdf_base.h"
25094332d3Sopenharmony_ci#include "hdf_dlist.h"
26094332d3Sopenharmony_ci#include "hdf_io_service_if.h"
27094332d3Sopenharmony_ci#include "hdf_log.h"
28094332d3Sopenharmony_ci#include "hdf_sbuf.h"
29094332d3Sopenharmony_ci#include "osal_mem.h"
30094332d3Sopenharmony_ci#include "osal_mutex.h"
31094332d3Sopenharmony_ci#include "securec.h"
32094332d3Sopenharmony_ci#include "usbd_wrapper.h"
33094332d3Sopenharmony_ci
34094332d3Sopenharmony_ci#define HDF_LOG_TAG usb_ddk_dev_mgr
35094332d3Sopenharmony_ci#define USB_GADGET_STATE_PATH "/sys/devices/virtual/"
36094332d3Sopenharmony_cistruct UsbDdkDeviceInfo {
37094332d3Sopenharmony_ci    struct OsalMutex deviceMutex;
38094332d3Sopenharmony_ci    struct DListHead list;
39094332d3Sopenharmony_ci    struct UsbPnpNotifyMatchInfoTable info;
40094332d3Sopenharmony_ci};
41094332d3Sopenharmony_ci
42094332d3Sopenharmony_cistruct UsbDdkDeviceList {
43094332d3Sopenharmony_ci    bool isInit;
44094332d3Sopenharmony_ci    struct OsalMutex listMutex;
45094332d3Sopenharmony_ci    struct DListHead devList;
46094332d3Sopenharmony_ci};
47094332d3Sopenharmony_ci
48094332d3Sopenharmony_ci#ifdef USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
49094332d3Sopenharmony_cistatic struct UsbDdkDeviceList g_ddkDevList = {.isInit = false};
50094332d3Sopenharmony_ci#define STATE_STRING_LENGTH 20
51094332d3Sopenharmony_ci
52094332d3Sopenharmony_cichar *g_gadgetStatePath = "invalid_path";
53094332d3Sopenharmony_ci
54094332d3Sopenharmony_cistatic struct UsbDdkDeviceInfo *DdkDevMgrIsDevExists(uint64_t devAddr)
55094332d3Sopenharmony_ci{
56094332d3Sopenharmony_ci    OsalMutexLock(&g_ddkDevList.listMutex);
57094332d3Sopenharmony_ci    if (DListIsEmpty(&g_ddkDevList.devList)) {
58094332d3Sopenharmony_ci        HDF_LOGI("%{public}s: the devList is empty.", __func__);
59094332d3Sopenharmony_ci        OsalMutexUnlock(&g_ddkDevList.listMutex);
60094332d3Sopenharmony_ci        return NULL;
61094332d3Sopenharmony_ci    }
62094332d3Sopenharmony_ci
63094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *res = NULL;
64094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *infoPos = NULL;
65094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *infoTemp = NULL;
66094332d3Sopenharmony_ci    DLIST_FOR_EACH_ENTRY_SAFE(infoPos, infoTemp, &g_ddkDevList.devList, struct UsbDdkDeviceInfo, list) {
67094332d3Sopenharmony_ci        if (infoPos->info.usbDevAddr == devAddr) {
68094332d3Sopenharmony_ci            res = infoPos;
69094332d3Sopenharmony_ci            break;
70094332d3Sopenharmony_ci        }
71094332d3Sopenharmony_ci    }
72094332d3Sopenharmony_ci    OsalMutexUnlock(&g_ddkDevList.listMutex);
73094332d3Sopenharmony_ci    return res;
74094332d3Sopenharmony_ci}
75094332d3Sopenharmony_ci
76094332d3Sopenharmony_cistatic int32_t DdkDevMgrAddDevice(struct UsbDdkDeviceInfo *device)
77094332d3Sopenharmony_ci{
78094332d3Sopenharmony_ci    if (device == NULL) {
79094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param", __func__);
80094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
81094332d3Sopenharmony_ci    }
82094332d3Sopenharmony_ci
83094332d3Sopenharmony_ci    HDF_LOGI("%{public}s: make device address and whether the device exists", __func__);
84094332d3Sopenharmony_ci    if (DdkDevMgrIsDevExists(DdkSysfsMakeDevAddr(device->info.busNum, device->info.devNum)) != NULL) {
85094332d3Sopenharmony_ci        HDF_LOGW("%{public}s: add device repeatedly busNum:%{public}d, devNum:%{public}d", __func__,
86094332d3Sopenharmony_ci            device->info.busNum, device->info.devNum);
87094332d3Sopenharmony_ci        return HDF_SUCCESS;
88094332d3Sopenharmony_ci    }
89094332d3Sopenharmony_ci
90094332d3Sopenharmony_ci    OsalMutexLock(&g_ddkDevList.listMutex);
91094332d3Sopenharmony_ci    DListInsertTail(&device->list, &g_ddkDevList.devList);
92094332d3Sopenharmony_ci    OsalMutexUnlock(&g_ddkDevList.listMutex);
93094332d3Sopenharmony_ci    HDF_LOGI("%{public}s: add device successed", __func__);
94094332d3Sopenharmony_ci    return HDF_SUCCESS;
95094332d3Sopenharmony_ci}
96094332d3Sopenharmony_ci
97094332d3Sopenharmony_ciint32_t DdkDevMgrRemoveDevice(int32_t busNum, int32_t devNum, struct UsbPnpNotifyMatchInfoTable *info)
98094332d3Sopenharmony_ci{
99094332d3Sopenharmony_ci    uint64_t devAddr = DdkSysfsMakeDevAddr(busNum, devNum);
100094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *dev = DdkDevMgrIsDevExists(devAddr);
101094332d3Sopenharmony_ci    if (dev == NULL) {
102094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: no device busNum:%{public}d, devNum:%{public}d", __func__, busNum, devNum);
103094332d3Sopenharmony_ci        return HDF_DEV_ERR_NO_DEVICE;
104094332d3Sopenharmony_ci    }
105094332d3Sopenharmony_ci
106094332d3Sopenharmony_ci    int32_t ret = memcpy_s(
107094332d3Sopenharmony_ci        info, sizeof(struct UsbPnpNotifyMatchInfoTable), &dev->info, sizeof(struct UsbPnpNotifyMatchInfoTable));
108094332d3Sopenharmony_ci    if (ret != EOK) {
109094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: memcpy_s failed", __func__);
110094332d3Sopenharmony_ci        return HDF_FAILURE;
111094332d3Sopenharmony_ci    }
112094332d3Sopenharmony_ci
113094332d3Sopenharmony_ci    OsalMutexLock(&g_ddkDevList.listMutex);
114094332d3Sopenharmony_ci    DListRemove(&dev->list);
115094332d3Sopenharmony_ci    OsalMemFree(dev);
116094332d3Sopenharmony_ci    dev = NULL;
117094332d3Sopenharmony_ci    OsalMutexUnlock(&g_ddkDevList.listMutex);
118094332d3Sopenharmony_ci    return HDF_SUCCESS;
119094332d3Sopenharmony_ci}
120094332d3Sopenharmony_ci
121094332d3Sopenharmony_cistatic int32_t DdkDevMgrInitDevice(struct UsbDdkDeviceInfo *deviceInfo)
122094332d3Sopenharmony_ci{
123094332d3Sopenharmony_ci    (void)memset_s(deviceInfo, sizeof(struct UsbDdkDeviceInfo), 0, sizeof(struct UsbDdkDeviceInfo));
124094332d3Sopenharmony_ci    int32_t ret = OsalMutexInit(&deviceInfo->deviceMutex);
125094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
126094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init mutex failed", __func__);
127094332d3Sopenharmony_ci        return HDF_FAILURE;
128094332d3Sopenharmony_ci    }
129094332d3Sopenharmony_ci    DListHeadInit(&deviceInfo->list);
130094332d3Sopenharmony_ci
131094332d3Sopenharmony_ci    return HDF_SUCCESS;
132094332d3Sopenharmony_ci}
133094332d3Sopenharmony_ci
134094332d3Sopenharmony_ciconst struct UsbPnpNotifyMatchInfoTable *DdkDevMgrCreateDevice(const char *deviceDir)
135094332d3Sopenharmony_ci{
136094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *device = (struct UsbDdkDeviceInfo *)OsalMemCalloc(sizeof(struct UsbDdkDeviceInfo));
137094332d3Sopenharmony_ci    if (device == NULL) {
138094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init device failed", __func__);
139094332d3Sopenharmony_ci        return NULL;
140094332d3Sopenharmony_ci    }
141094332d3Sopenharmony_ci
142094332d3Sopenharmony_ci    int32_t status = HDF_SUCCESS;
143094332d3Sopenharmony_ci    do {
144094332d3Sopenharmony_ci        // init device
145094332d3Sopenharmony_ci        status = DdkDevMgrInitDevice(device);
146094332d3Sopenharmony_ci        if (status != HDF_SUCCESS) {
147094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: init device failed:%{public}d", __func__, status);
148094332d3Sopenharmony_ci            break;
149094332d3Sopenharmony_ci        }
150094332d3Sopenharmony_ci
151094332d3Sopenharmony_ci        // get device from sysfs
152094332d3Sopenharmony_ci        status = DdkSysfsGetDevice(deviceDir, &device->info);
153094332d3Sopenharmony_ci        if (status != HDF_SUCCESS) {
154094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: sysfs get device failed:%{public}d", __func__, status);
155094332d3Sopenharmony_ci            break;
156094332d3Sopenharmony_ci        }
157094332d3Sopenharmony_ci
158094332d3Sopenharmony_ci        // insert device to list
159094332d3Sopenharmony_ci        status = DdkDevMgrAddDevice(device);
160094332d3Sopenharmony_ci        if (status != HDF_SUCCESS) {
161094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: add device failed:%{public}d", __func__, status);
162094332d3Sopenharmony_ci            break;
163094332d3Sopenharmony_ci        }
164094332d3Sopenharmony_ci        return &device->info;
165094332d3Sopenharmony_ci    } while (0);
166094332d3Sopenharmony_ci
167094332d3Sopenharmony_ci    OsalMemFree(device);
168094332d3Sopenharmony_ci    return status == HDF_SUCCESS ? &device->info : NULL;
169094332d3Sopenharmony_ci}
170094332d3Sopenharmony_ci
171094332d3Sopenharmony_cistatic int32_t DdkDevMgrScanSysfs(const char *sysfsDevDir)
172094332d3Sopenharmony_ci{
173094332d3Sopenharmony_ci    if (sysfsDevDir == NULL) {
174094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param", __func__);
175094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
176094332d3Sopenharmony_ci    }
177094332d3Sopenharmony_ci
178094332d3Sopenharmony_ci    DIR *dir = opendir(sysfsDevDir);
179094332d3Sopenharmony_ci    if (dir == NULL) {
180094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: opendir failed sysfsDevDir:%{public}s", __func__, sysfsDevDir);
181094332d3Sopenharmony_ci        return HDF_ERR_BAD_FD;
182094332d3Sopenharmony_ci    }
183094332d3Sopenharmony_ci
184094332d3Sopenharmony_ci    struct dirent *devHandle;
185094332d3Sopenharmony_ci    while ((devHandle = readdir(dir))) {
186094332d3Sopenharmony_ci        // only read dir like 3-1
187094332d3Sopenharmony_ci        if (devHandle->d_name[0] > '9' || devHandle->d_name[0] < '0' || strchr(devHandle->d_name, ':')) {
188094332d3Sopenharmony_ci            continue;
189094332d3Sopenharmony_ci        }
190094332d3Sopenharmony_ci
191094332d3Sopenharmony_ci        if (DdkDevMgrCreateDevice(devHandle->d_name) == NULL) {
192094332d3Sopenharmony_ci            HDF_LOGW("%{public}s: create device failed d_name:%{public}s", __func__, devHandle->d_name);
193094332d3Sopenharmony_ci        }
194094332d3Sopenharmony_ci    }
195094332d3Sopenharmony_ci    closedir(dir);
196094332d3Sopenharmony_ci    return HDF_SUCCESS;
197094332d3Sopenharmony_ci}
198094332d3Sopenharmony_ci
199094332d3Sopenharmony_ciint32_t DdkDevMgrInit(const char *gadgetStatePath)
200094332d3Sopenharmony_ci{
201094332d3Sopenharmony_ci    if (g_ddkDevList.isInit) {
202094332d3Sopenharmony_ci        return HDF_SUCCESS;
203094332d3Sopenharmony_ci    }
204094332d3Sopenharmony_ci
205094332d3Sopenharmony_ci    if (gadgetStatePath == NULL) {
206094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid gadgetStatePath", __func__);
207094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
208094332d3Sopenharmony_ci    }
209094332d3Sopenharmony_ci
210094332d3Sopenharmony_ci    g_gadgetStatePath = (char *)gadgetStatePath;
211094332d3Sopenharmony_ci    int32_t ret = OsalMutexInit(&g_ddkDevList.listMutex);
212094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
213094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init mutex failed", __func__);
214094332d3Sopenharmony_ci        return HDF_FAILURE;
215094332d3Sopenharmony_ci    }
216094332d3Sopenharmony_ci
217094332d3Sopenharmony_ci    DListHeadInit(&g_ddkDevList.devList);
218094332d3Sopenharmony_ci    ret = DdkDevMgrScanSysfs(SYSFS_DEVICES_DIR);
219094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
220094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: Scan sysfs failed ret=%{public}d", __func__, ret);
221094332d3Sopenharmony_ci        return HDF_FAILURE;
222094332d3Sopenharmony_ci    }
223094332d3Sopenharmony_ci    g_ddkDevList.isInit = true;
224094332d3Sopenharmony_ci    return HDF_SUCCESS;
225094332d3Sopenharmony_ci}
226094332d3Sopenharmony_ci
227094332d3Sopenharmony_ciint32_t DdkDevMgrForEachDeviceSafe(DdkDevMgrHandleDev handle, void *priv)
228094332d3Sopenharmony_ci{
229094332d3Sopenharmony_ci    OsalMutexLock(&g_ddkDevList.listMutex);
230094332d3Sopenharmony_ci    if (DListIsEmpty(&g_ddkDevList.devList)) {
231094332d3Sopenharmony_ci        HDF_LOGI("%{public}s:the devList is empty", __func__);
232094332d3Sopenharmony_ci        OsalMutexUnlock(&g_ddkDevList.listMutex);
233094332d3Sopenharmony_ci        return HDF_SUCCESS;
234094332d3Sopenharmony_ci    }
235094332d3Sopenharmony_ci
236094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *pos = NULL;
237094332d3Sopenharmony_ci    struct UsbDdkDeviceInfo *tmp = NULL;
238094332d3Sopenharmony_ci    DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &g_ddkDevList.devList, struct UsbDdkDeviceInfo, list) {
239094332d3Sopenharmony_ci        if (handle(&pos->info, priv) != HDF_SUCCESS) {
240094332d3Sopenharmony_ci            HDF_LOGW("%{public}s: handle failed", __func__);
241094332d3Sopenharmony_ci        }
242094332d3Sopenharmony_ci    }
243094332d3Sopenharmony_ci
244094332d3Sopenharmony_ci    OsalMutexUnlock(&g_ddkDevList.listMutex);
245094332d3Sopenharmony_ci    return HDF_SUCCESS;
246094332d3Sopenharmony_ci}
247094332d3Sopenharmony_ci
248094332d3Sopenharmony_ciint32_t DdkDevMgrGetGadgetLinkStatusSafe(DdkDevMgrHandleGadget handle, void *priv)
249094332d3Sopenharmony_ci{
250094332d3Sopenharmony_ci    if (priv == NULL || handle == NULL) {
251094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param.", __func__);
252094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
253094332d3Sopenharmony_ci    }
254094332d3Sopenharmony_ci
255094332d3Sopenharmony_ci    char pathBuf[PATH_MAX] = {'\0'};
256094332d3Sopenharmony_ci    if (realpath(g_gadgetStatePath, pathBuf) == NULL) {
257094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: path conversion failed", __func__);
258094332d3Sopenharmony_ci        return HDF_FAILURE;
259094332d3Sopenharmony_ci    }
260094332d3Sopenharmony_ci
261094332d3Sopenharmony_ci    if (strncmp(USB_GADGET_STATE_PATH, pathBuf, strlen(USB_GADGET_STATE_PATH)) != 0) {
262094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: The file path is incorrect", __func__);
263094332d3Sopenharmony_ci        return HDF_FAILURE;
264094332d3Sopenharmony_ci    }
265094332d3Sopenharmony_ci
266094332d3Sopenharmony_ci    int32_t fd = open(pathBuf, O_RDONLY | O_CLOEXEC);
267094332d3Sopenharmony_ci    if (fd == -1) {
268094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: open %{public}s failed  errno:%{public}d", __func__, g_gadgetStatePath, errno);
269094332d3Sopenharmony_ci        return HDF_ERR_IO;
270094332d3Sopenharmony_ci    }
271094332d3Sopenharmony_ci
272094332d3Sopenharmony_ci    char buf[STATE_STRING_LENGTH] = {0};
273094332d3Sopenharmony_ci    ssize_t numRead = read(fd, buf, STATE_STRING_LENGTH);
274094332d3Sopenharmony_ci    close(fd);
275094332d3Sopenharmony_ci    if (numRead <= 0) {
276094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: read state failed errno:%{public}d", __func__, errno);
277094332d3Sopenharmony_ci        return HDF_ERR_IO;
278094332d3Sopenharmony_ci    }
279094332d3Sopenharmony_ci
280094332d3Sopenharmony_ci    if ((strncmp(buf, "CONNECTED", strlen("CONNECTED")) == 0) ||
281094332d3Sopenharmony_ci        (strncmp(buf, "CONFIGURED", strlen("CONFIGURED")) == 0)) {
282094332d3Sopenharmony_ci        // call back
283094332d3Sopenharmony_ci        if (handle(priv) != HDF_SUCCESS) {
284094332d3Sopenharmony_ci            HDF_LOGW("%{public}s: handle failed", __func__);
285094332d3Sopenharmony_ci        }
286094332d3Sopenharmony_ci    }
287094332d3Sopenharmony_ci
288094332d3Sopenharmony_ci    return HDF_SUCCESS;
289094332d3Sopenharmony_ci}
290094332d3Sopenharmony_cibool DdkDevMgrGetGadgetLinkStatus()
291094332d3Sopenharmony_ci{
292094332d3Sopenharmony_ci    char pathBuf[PATH_MAX] = {'\0'};
293094332d3Sopenharmony_ci    if (realpath(g_gadgetStatePath, pathBuf) == NULL) {
294094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: path conversion failed", __func__);
295094332d3Sopenharmony_ci        return false;
296094332d3Sopenharmony_ci    }
297094332d3Sopenharmony_ci
298094332d3Sopenharmony_ci    if (strncmp(USB_GADGET_STATE_PATH, pathBuf, strlen(USB_GADGET_STATE_PATH)) != 0) {
299094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: The file path is incorrect", __func__);
300094332d3Sopenharmony_ci        return false;
301094332d3Sopenharmony_ci    }
302094332d3Sopenharmony_ci
303094332d3Sopenharmony_ci    int32_t fd = open(pathBuf, O_RDONLY | O_CLOEXEC);
304094332d3Sopenharmony_ci    if (fd == -1) {
305094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: open %{public}s failed  errno:%{public}d", __func__, g_gadgetStatePath, errno);
306094332d3Sopenharmony_ci        return false;
307094332d3Sopenharmony_ci    }
308094332d3Sopenharmony_ci
309094332d3Sopenharmony_ci    char buf[STATE_STRING_LENGTH] = {0};
310094332d3Sopenharmony_ci    ssize_t numRead = read(fd, buf, STATE_STRING_LENGTH);
311094332d3Sopenharmony_ci    close(fd);
312094332d3Sopenharmony_ci    if (numRead <= 0) {
313094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: read state failed errno:%{public}d", __func__, errno);
314094332d3Sopenharmony_ci        return false;
315094332d3Sopenharmony_ci    }
316094332d3Sopenharmony_ci    HDF_LOGE("%{public}s: read status:%{public}s", __func__, buf);
317094332d3Sopenharmony_ci    if ((strncmp(buf, "CONNECTED", strlen("CONNECTED")) == 0) ||
318094332d3Sopenharmony_ci        (strncmp(buf, "CONFIGURED", strlen("CONFIGURED")) == 0)) {
319094332d3Sopenharmony_ci        return true;
320094332d3Sopenharmony_ci    }
321094332d3Sopenharmony_ci    return false;
322094332d3Sopenharmony_ci}
323094332d3Sopenharmony_ci#else                                                                           // USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
324094332d3Sopenharmony_cistruct HdfIoService *g_usbPnpSrv = NULL;
325094332d3Sopenharmony_ci#define HDF_USB_INFO_MAX_SIZE (127 * sizeof(struct UsbPnpNotifyMatchInfoTable)) // 127  is max deivce num
326094332d3Sopenharmony_ciint32_t DdkDevMgrInit(const char *gadgetStatePath)
327094332d3Sopenharmony_ci{
328094332d3Sopenharmony_ci    (void)gadgetStatePath;
329094332d3Sopenharmony_ci    g_usbPnpSrv = HdfIoServiceBind(USB_PNP_NOTIFY_SERVICE_NAME);
330094332d3Sopenharmony_ci    if (g_usbPnpSrv == NULL) {
331094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: HdfIoServiceBind failed.", __func__);
332094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
333094332d3Sopenharmony_ci    }
334094332d3Sopenharmony_ci    return HDF_SUCCESS;
335094332d3Sopenharmony_ci}
336094332d3Sopenharmony_ci
337094332d3Sopenharmony_ciint32_t DdkDevMgrForEachDeviceSafe(DdkDevMgrHandleDev handle, void *priv)
338094332d3Sopenharmony_ci{
339094332d3Sopenharmony_ci    if (g_usbPnpSrv == NULL || handle == NULL) {
340094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param.", __func__);
341094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
342094332d3Sopenharmony_ci    }
343094332d3Sopenharmony_ci
344094332d3Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufObtain(HDF_USB_INFO_MAX_SIZE);
345094332d3Sopenharmony_ci    if (reply == NULL) {
346094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: HdfSbufObtain reply failed", __func__);
347094332d3Sopenharmony_ci        return HDF_DEV_ERR_NO_MEMORY;
348094332d3Sopenharmony_ci    }
349094332d3Sopenharmony_ci
350094332d3Sopenharmony_ci    // request device list from pnp service
351094332d3Sopenharmony_ci    int32_t ret = g_usbPnpSrv->dispatcher->Dispatch(&g_usbPnpSrv->object, USB_PNP_DRIVER_GETDEVICES, NULL, reply);
352094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
353094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:failed to send service call, ret:%{public}d", __func__, ret);
354094332d3Sopenharmony_ci        HdfSbufRecycle(reply);
355094332d3Sopenharmony_ci        return ret;
356094332d3Sopenharmony_ci    }
357094332d3Sopenharmony_ci
358094332d3Sopenharmony_ci    // read device list
359094332d3Sopenharmony_ci    int32_t count = 0;
360094332d3Sopenharmony_ci    if (!HdfSbufReadInt32(reply, &count)) {
361094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: failed to read count from reply", __func__);
362094332d3Sopenharmony_ci        HdfSbufRecycle(reply);
363094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
364094332d3Sopenharmony_ci    }
365094332d3Sopenharmony_ci
366094332d3Sopenharmony_ci    HDF_LOGI("%{public}s: total obj num count:%{public}d ", __func__, count);
367094332d3Sopenharmony_ci    struct UsbPnpNotifyMatchInfoTable *info = NULL;
368094332d3Sopenharmony_ci    uint32_t infoSize = 0;
369094332d3Sopenharmony_ci    for (int32_t i = 0; i < count; ++i) {
370094332d3Sopenharmony_ci        if (!HdfSbufReadBuffer(reply, (const void **)(&info), &infoSize) || info == NULL) {
371094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: HdfSbufReadBuffer failed", __func__);
372094332d3Sopenharmony_ci            HdfSbufRecycle(reply);
373094332d3Sopenharmony_ci            return HDF_ERR_INVALID_PARAM;
374094332d3Sopenharmony_ci        }
375094332d3Sopenharmony_ci        // call back
376094332d3Sopenharmony_ci        if (handle(info, priv) != HDF_SUCCESS) {
377094332d3Sopenharmony_ci            HDF_LOGW("%{public}s: handle failed", __func__);
378094332d3Sopenharmony_ci        }
379094332d3Sopenharmony_ci    }
380094332d3Sopenharmony_ci
381094332d3Sopenharmony_ci    HdfSbufRecycle(reply);
382094332d3Sopenharmony_ci    return HDF_SUCCESS;
383094332d3Sopenharmony_ci}
384094332d3Sopenharmony_ci
385094332d3Sopenharmony_cistatic int32_t DdkDevMgrGetGadgetStatus(int32_t *gadgetStatus)
386094332d3Sopenharmony_ci{
387094332d3Sopenharmony_ci    if (g_usbPnpSrv == NULL) {
388094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param.", __func__);
389094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
390094332d3Sopenharmony_ci    }
391094332d3Sopenharmony_ci
392094332d3Sopenharmony_ci    struct HdfSBuf *reply = HdfSbufObtain(HDF_USB_INFO_MAX_SIZE);
393094332d3Sopenharmony_ci    if (reply == NULL) {
394094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: HdfSbufObtain reply failed", __func__);
395094332d3Sopenharmony_ci        return HDF_DEV_ERR_NO_MEMORY;
396094332d3Sopenharmony_ci    }
397094332d3Sopenharmony_ci
398094332d3Sopenharmony_ci    int32_t ret =
399094332d3Sopenharmony_ci        g_usbPnpSrv->dispatcher->Dispatch(&g_usbPnpSrv->object, USB_PNP_DRIVER_GET_GADGET_LINK_STATUS, NULL, reply);
400094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
401094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:failed to send service call, ret:%{public}d", __func__, ret);
402094332d3Sopenharmony_ci        HdfSbufRecycle(reply);
403094332d3Sopenharmony_ci        return ret;
404094332d3Sopenharmony_ci    }
405094332d3Sopenharmony_ci
406094332d3Sopenharmony_ci    if (!HdfSbufReadInt32(reply, gadgetStatus)) {
407094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: failed to read count from reply", __func__);
408094332d3Sopenharmony_ci        HdfSbufRecycle(reply);
409094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
410094332d3Sopenharmony_ci    }
411094332d3Sopenharmony_ci
412094332d3Sopenharmony_ci    HdfSbufRecycle(reply);
413094332d3Sopenharmony_ci    return HDF_SUCCESS;
414094332d3Sopenharmony_ci}
415094332d3Sopenharmony_ci
416094332d3Sopenharmony_ciint32_t DdkDevMgrGetGadgetLinkStatusSafe(DdkDevMgrHandleGadget handle, void *priv)
417094332d3Sopenharmony_ci{
418094332d3Sopenharmony_ci    if (priv == NULL || handle == NULL) {
419094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param.", __func__);
420094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
421094332d3Sopenharmony_ci    }
422094332d3Sopenharmony_ci    int32_t gadgetStatus = 0;
423094332d3Sopenharmony_ci    if (DdkDevMgrGetGadgetStatus(&gadgetStatus) != HDF_SUCCESS) {
424094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: DdkDevMgrGetGadgetStatus failed", __func__);
425094332d3Sopenharmony_ci        return HDF_FAILURE;
426094332d3Sopenharmony_ci    }
427094332d3Sopenharmony_ci    // gadget add
428094332d3Sopenharmony_ci    if (gadgetStatus != 0) {
429094332d3Sopenharmony_ci        // call back
430094332d3Sopenharmony_ci        if (handle(priv) != HDF_SUCCESS) {
431094332d3Sopenharmony_ci            HDF_LOGW("%{public}s: handle failed", __func__);
432094332d3Sopenharmony_ci        }
433094332d3Sopenharmony_ci    }
434094332d3Sopenharmony_ci    return HDF_SUCCESS;
435094332d3Sopenharmony_ci}
436094332d3Sopenharmony_ci
437094332d3Sopenharmony_cibool DdkDevMgrGetGadgetLinkStatus()
438094332d3Sopenharmony_ci{
439094332d3Sopenharmony_ci    int32_t gadgetStatus = 0;
440094332d3Sopenharmony_ci    if (DdkDevMgrGetGadgetStatus(&gadgetStatus) != HDF_SUCCESS) {
441094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: DdkDevMgrGetGadgetStatus failed", __func__);
442094332d3Sopenharmony_ci        return false;
443094332d3Sopenharmony_ci    }
444094332d3Sopenharmony_ci    // gadget add
445094332d3Sopenharmony_ci    if (gadgetStatus != 0) {
446094332d3Sopenharmony_ci        return gadgetStatus == USB_PNP_DRIVER_GADGET_ADD ? true : false;
447094332d3Sopenharmony_ci    }
448094332d3Sopenharmony_ci    return false;
449094332d3Sopenharmony_ci}
450094332d3Sopenharmony_ci#endif                                                                          // USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
451