• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ddk_device_manager.h"
17 
18 #include <ctype.h>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 
23 #include "ddk_sysfs_device.h"
24 #include "default_config.h"
25 #include "hdf_base.h"
26 #include "hdf_dlist.h"
27 #include "hdf_io_service_if.h"
28 #include "hdf_log.h"
29 #include "hdf_sbuf.h"
30 #include "osal_mem.h"
31 #include "osal_mutex.h"
32 #include "securec.h"
33 
34 #define HDF_LOG_TAG usb_ddk_dev_mgr
35 
36 struct UsbDdkDeviceInfo {
37     struct OsalMutex deviceMutex;
38     struct DListHead list;
39     struct UsbPnpNotifyMatchInfoTable info;
40 };
41 
42 struct UsbDdkDeviceList {
43     bool isInit;
44     struct OsalMutex listMutex;
45     struct DListHead devList;
46 };
47 
48 #ifdef USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
49 static struct UsbDdkDeviceList g_ddkDevList = {.isInit = false};
50 #define STATE_STRING_LENGTH 20
51 
52 #ifndef USB_GADGET_STATE_PATH
53 #define USB_GADGET_STATE_PATH "invalid_path"
54 #endif
55 
DdkDevMgrIsDevExists(uint64_t devAddr)56 static struct UsbDdkDeviceInfo *DdkDevMgrIsDevExists(uint64_t devAddr)
57 {
58     OsalMutexLock(&g_ddkDevList.listMutex);
59     if (DListIsEmpty(&g_ddkDevList.devList)) {
60         HDF_LOGI("%{public}s: the devList is empty.", __func__);
61         OsalMutexUnlock(&g_ddkDevList.listMutex);
62         return NULL;
63     }
64 
65     struct UsbDdkDeviceInfo *res = NULL;
66     struct UsbDdkDeviceInfo *infoPos = NULL;
67     struct UsbDdkDeviceInfo *infoTemp = NULL;
68     DLIST_FOR_EACH_ENTRY_SAFE(infoPos, infoTemp, &g_ddkDevList.devList, struct UsbDdkDeviceInfo, list) {
69         if (infoPos->info.usbDevAddr == devAddr) {
70             res = infoPos;
71             break;
72         }
73     }
74     OsalMutexUnlock(&g_ddkDevList.listMutex);
75     return res;
76 }
77 
DdkDevMgrAddDevice(struct UsbDdkDeviceInfo * device)78 static int32_t DdkDevMgrAddDevice(struct UsbDdkDeviceInfo *device)
79 {
80     if (device == NULL) {
81         HDF_LOGE("%{public}s: invalid param", __func__);
82         return HDF_ERR_INVALID_PARAM;
83     }
84 
85     HDF_LOGI("%{public}s: make device address and whether the device exists", __func__);
86     if (DdkDevMgrIsDevExists(DdkSysfsMakeDevAddr(device->info.busNum, device->info.devNum)) != NULL) {
87         HDF_LOGW("%{public}s: add device repeatedly busNum:%{public}d, devNum:%{public}d", __func__,
88             device->info.busNum, device->info.devNum);
89         return HDF_SUCCESS;
90     }
91 
92     OsalMutexLock(&g_ddkDevList.listMutex);
93     DListInsertTail(&device->list, &g_ddkDevList.devList);
94     OsalMutexUnlock(&g_ddkDevList.listMutex);
95     HDF_LOGI("%{public}s: add device successed", __func__);
96     return HDF_SUCCESS;
97 }
98 
DdkDevMgrRemoveDevice(int32_t busNum,int32_t devNum,struct UsbPnpNotifyMatchInfoTable * info)99 int32_t DdkDevMgrRemoveDevice(int32_t busNum, int32_t devNum, struct UsbPnpNotifyMatchInfoTable *info)
100 {
101     uint64_t devAddr = DdkSysfsMakeDevAddr(busNum, devNum);
102     struct UsbDdkDeviceInfo *dev = DdkDevMgrIsDevExists(devAddr);
103     if (dev == NULL) {
104         HDF_LOGE("%{public}s: no device busNum:%{public}d, devNum:%{public}d", __func__, busNum, devNum);
105         return HDF_DEV_ERR_NO_DEVICE;
106     }
107 
108     int32_t ret = memcpy_s(
109         info, sizeof(struct UsbPnpNotifyMatchInfoTable), &dev->info, sizeof(struct UsbPnpNotifyMatchInfoTable));
110     if (ret != EOK) {
111         HDF_LOGE("%{public}s: memcpy_s failed", __func__);
112         return HDF_FAILURE;
113     }
114 
115     OsalMutexLock(&g_ddkDevList.listMutex);
116     DListRemove(&dev->list);
117     OsalMemFree(dev);
118     dev = NULL;
119     OsalMutexUnlock(&g_ddkDevList.listMutex);
120     return HDF_SUCCESS;
121 }
122 
DdkDevMgrInitDevice(struct UsbDdkDeviceInfo * deviceInfo)123 static int32_t DdkDevMgrInitDevice(struct UsbDdkDeviceInfo *deviceInfo)
124 {
125     (void)memset_s(deviceInfo, sizeof(struct UsbDdkDeviceInfo), 0, sizeof(struct UsbDdkDeviceInfo));
126     int32_t ret = OsalMutexInit(&deviceInfo->deviceMutex);
127     if (ret != HDF_SUCCESS) {
128         HDF_LOGE("%{public}s: init mutex failed", __func__);
129         return HDF_FAILURE;
130     }
131     DListHeadInit(&deviceInfo->list);
132 
133     return HDF_SUCCESS;
134 }
135 
DdkDevMgrCreateDevice(const char * deviceDir)136 const struct UsbPnpNotifyMatchInfoTable *DdkDevMgrCreateDevice(const char *deviceDir)
137 {
138     struct UsbDdkDeviceInfo *device = (struct UsbDdkDeviceInfo *)OsalMemCalloc(sizeof(struct UsbDdkDeviceInfo));
139     if (device == NULL) {
140         HDF_LOGE("%{public}s: init device failed", __func__);
141         return NULL;
142     }
143 
144     int32_t status = HDF_SUCCESS;
145     do {
146         // init device
147         status = DdkDevMgrInitDevice(device);
148         if (status != HDF_SUCCESS) {
149             HDF_LOGE("%{public}s: init device failed:%{public}d", __func__, status);
150             break;
151         }
152 
153         // get device from sysfs
154         status = DdkSysfsGetDevice(deviceDir, &device->info);
155         if (status != HDF_SUCCESS) {
156             HDF_LOGE("%{public}s: sysfs get device failed:%{public}d", __func__, status);
157             break;
158         }
159 
160         // insert device to list
161         status = DdkDevMgrAddDevice(device);
162         if (status != HDF_SUCCESS) {
163             HDF_LOGE("%{public}s: add device failed:%{public}d", __func__, status);
164             break;
165         }
166         return &device->info;
167     } while (0);
168 
169     OsalMemFree(device);
170     return status == HDF_SUCCESS ? &device->info : NULL;
171 }
172 
DdkDevMgrScanSysfs(const char * sysfsDevDir)173 static int32_t DdkDevMgrScanSysfs(const char *sysfsDevDir)
174 {
175     if (sysfsDevDir == NULL) {
176         HDF_LOGE("%{public}s: invalid param", __func__);
177         return HDF_ERR_INVALID_PARAM;
178     }
179 
180     DIR *dir = opendir(sysfsDevDir);
181     if (dir == NULL) {
182         HDF_LOGE("%{public}s: opendir failed sysfsDevDir:%{public}s", __func__, sysfsDevDir);
183         return HDF_ERR_BAD_FD;
184     }
185 
186     struct dirent *devHandle;
187     while ((devHandle = readdir(dir))) {
188         // only read dir like 3-1
189         if ((!isdigit(devHandle->d_name[0])) || strchr(devHandle->d_name, ':')) {
190             continue;
191         }
192 
193         if (DdkDevMgrCreateDevice(devHandle->d_name) == NULL) {
194             HDF_LOGW("%{public}s: create device failed d_name:%{public}s", __func__, devHandle->d_name);
195         }
196     }
197     closedir(dir);
198     return HDF_SUCCESS;
199 }
200 
DdkDevMgrInit(void)201 int32_t DdkDevMgrInit(void)
202 {
203     if (g_ddkDevList.isInit) {
204         return HDF_SUCCESS;
205     }
206 
207     int32_t ret = OsalMutexInit(&g_ddkDevList.listMutex);
208     if (ret != HDF_SUCCESS) {
209         HDF_LOGE("%{public}s: init mutex failed", __func__);
210         return HDF_FAILURE;
211     }
212 
213     DListHeadInit(&g_ddkDevList.devList);
214     ret = DdkDevMgrScanSysfs(SYSFS_DEVICES_DIR);
215     if (ret != HDF_SUCCESS) {
216         HDF_LOGE("%{public}s: Scan sysfs failed ret=%{public}d", __func__, ret);
217         return HDF_FAILURE;
218     }
219     g_ddkDevList.isInit = true;
220     return HDF_SUCCESS;
221 }
222 
DdkDevMgrForEachDeviceSafe(DdkDevMgrHandleDev handle,void * priv)223 int32_t DdkDevMgrForEachDeviceSafe(DdkDevMgrHandleDev handle, void *priv)
224 {
225     OsalMutexLock(&g_ddkDevList.listMutex);
226     if (DListIsEmpty(&g_ddkDevList.devList)) {
227         HDF_LOGI("%{public}s:the devList is empty", __func__);
228         OsalMutexUnlock(&g_ddkDevList.listMutex);
229         return HDF_SUCCESS;
230     }
231 
232     struct UsbDdkDeviceInfo *pos = NULL;
233     struct UsbDdkDeviceInfo *tmp = NULL;
234     DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &g_ddkDevList.devList, struct UsbDdkDeviceInfo, list) {
235         if (handle(&pos->info, priv) != HDF_SUCCESS) {
236             HDF_LOGW("%{public}s: handle failed", __func__);
237         }
238     }
239 
240     OsalMutexUnlock(&g_ddkDevList.listMutex);
241     return HDF_SUCCESS;
242 }
243 
DdkDevMgrGetGadgetLinkStatusSafe(DdkDevMgrHandleGadget handle,void * priv)244 int32_t DdkDevMgrGetGadgetLinkStatusSafe(DdkDevMgrHandleGadget handle, void *priv)
245 {
246     if (priv == NULL || handle == NULL) {
247         HDF_LOGE("%{public}s: invalid param.", __func__);
248         return HDF_ERR_INVALID_OBJECT;
249     }
250     int32_t fd = open(USB_GADGET_STATE_PATH, O_RDONLY | O_CLOEXEC);
251     if (fd == -1) {
252         HDF_LOGE("%{public}s: open %{public}s failed  errno:%{public}d", __func__, USB_GADGET_STATE_PATH, errno);
253         return HDF_ERR_IO;
254     }
255 
256     char buf[STATE_STRING_LENGTH] = {0};
257     ssize_t numRead = read(fd, buf, STATE_STRING_LENGTH);
258     close(fd);
259     if (numRead <= 0) {
260         HDF_LOGE("%{public}s: read state failed errno:%{public}d", __func__, errno);
261         return HDF_ERR_IO;
262     }
263 
264     if ((strncmp(buf, "CONNECTED", strlen("CONNECTED")) == 0) ||
265         (strncmp(buf, "CONFIGURED", strlen("CONFIGURED")) == 0)) {
266         // call back
267         if (handle(priv) != HDF_SUCCESS) {
268             HDF_LOGW("%{public}s: handle failed", __func__);
269         }
270     }
271 
272     return HDF_SUCCESS;
273 }
274 #else                                                                           // USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
275 struct HdfIoService *g_usbPnpSrv = NULL;
276 #define HDF_USB_INFO_MAX_SIZE (127 * sizeof(struct UsbPnpNotifyMatchInfoTable)) // 127  is max deivce num
DdkDevMgrInit(void)277 int32_t DdkDevMgrInit(void)
278 {
279     g_usbPnpSrv = HdfIoServiceBind(USB_PNP_NOTIFY_SERVICE_NAME);
280     if (g_usbPnpSrv == NULL) {
281         HDF_LOGE("%{public}s: HdfIoServiceBind failed.", __func__);
282         return HDF_ERR_INVALID_OBJECT;
283     }
284     return HDF_SUCCESS;
285 }
286 
DdkDevMgrForEachDeviceSafe(DdkDevMgrHandleDev handle,void * priv)287 int32_t DdkDevMgrForEachDeviceSafe(DdkDevMgrHandleDev handle, void *priv)
288 {
289     if (g_usbPnpSrv == NULL || handle == NULL) {
290         HDF_LOGE("%{public}s: invalid param.", __func__);
291         return HDF_ERR_INVALID_OBJECT;
292     }
293 
294     struct HdfSBuf *reply = HdfSbufObtain(HDF_USB_INFO_MAX_SIZE);
295     if (reply == NULL) {
296         HDF_LOGE("%{public}s: HdfSbufObtain reply failed", __func__);
297         return HDF_DEV_ERR_NO_MEMORY;
298     }
299 
300     // request device list from pnp service
301     int32_t ret = g_usbPnpSrv->dispatcher->Dispatch(&g_usbPnpSrv->object, USB_PNP_DRIVER_GETDEVICES, NULL, reply);
302     if (ret != HDF_SUCCESS) {
303         HDF_LOGE("%{public}s:failed to send service call, ret:%{public}d", __func__, ret);
304         HdfSbufRecycle(reply);
305         return ret;
306     }
307 
308     // read device list
309     int32_t count = 0;
310     if (!HdfSbufReadInt32(reply, &count)) {
311         HDF_LOGE("%{public}s: failed to read count from reply", __func__);
312         HdfSbufRecycle(reply);
313         return HDF_ERR_INVALID_PARAM;
314     }
315 
316     HDF_LOGI("%{public}s: total obj num count:%{public}d ", __func__, count);
317     struct UsbPnpNotifyMatchInfoTable *info = NULL;
318     uint32_t infoSize = 0;
319     for (int32_t i = 0; i < count; ++i) {
320         if (!HdfSbufReadBuffer(reply, (const void **)(&info), &infoSize) || info == NULL) {
321             HDF_LOGE("%{public}s: HdfSbufReadBuffer failed", __func__);
322             HdfSbufRecycle(reply);
323             return HDF_ERR_INVALID_PARAM;
324         }
325         // call back
326         if (handle(info, priv) != HDF_SUCCESS) {
327             HDF_LOGW("%{public}s: handle failed", __func__);
328         }
329     }
330 
331     HdfSbufRecycle(reply);
332     return HDF_SUCCESS;
333 }
334 
DdkDevMgrGetGadgetStatus(int32_t * gadgetStatus)335 static int32_t DdkDevMgrGetGadgetStatus(int32_t *gadgetStatus)
336 {
337     if (g_usbPnpSrv == NULL) {
338         HDF_LOGE("%{public}s: invalid param.", __func__);
339         return HDF_ERR_INVALID_OBJECT;
340     }
341 
342     struct HdfSBuf *reply = HdfSbufObtain(HDF_USB_INFO_MAX_SIZE);
343     if (reply == NULL) {
344         HDF_LOGE("%{public}s: HdfSbufObtain reply failed", __func__);
345         return HDF_DEV_ERR_NO_MEMORY;
346     }
347 
348     int32_t ret =
349         g_usbPnpSrv->dispatcher->Dispatch(&g_usbPnpSrv->object, USB_PNP_DRIVER_GET_GADGET_LINK_STATUS, NULL, reply);
350     if (ret != HDF_SUCCESS) {
351         HDF_LOGE("%{public}s:failed to send service call, ret:%{public}d", __func__, ret);
352         HdfSbufRecycle(reply);
353         return ret;
354     }
355 
356     if (!HdfSbufReadInt32(reply, gadgetStatus)) {
357         HDF_LOGE("%{public}s: failed to read count from reply", __func__);
358         HdfSbufRecycle(reply);
359         return HDF_ERR_INVALID_PARAM;
360     }
361 
362     HdfSbufRecycle(reply);
363     return HDF_SUCCESS;
364 }
365 
DdkDevMgrGetGadgetLinkStatusSafe(DdkDevMgrHandleGadget handle,void * priv)366 int32_t DdkDevMgrGetGadgetLinkStatusSafe(DdkDevMgrHandleGadget handle, void *priv)
367 {
368     if (priv == NULL || handle == NULL) {
369         HDF_LOGE("%{public}s: invalid param.", __func__);
370         return HDF_ERR_INVALID_OBJECT;
371     }
372     int32_t gadgetStatus = 0;
373     if (DdkDevMgrGetGadgetStatus(&gadgetStatus) != HDF_SUCCESS) {
374         HDF_LOGE("%{public}s: DdkDevMgrGetGadgetStatus failed", __func__);
375         return HDF_FAILURE;
376     }
377     // gadget add
378     if (gadgetStatus != 0) {
379         // call back
380         if (handle(priv) != HDF_SUCCESS) {
381             HDF_LOGW("%{public}s: handle failed", __func__);
382         }
383     }
384     return HDF_SUCCESS;
385 }
386 #endif                                                                          // USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
387