1 /*
2 * usb_pnp_notify.c
3 *
4 * usb pnp notify adapter of linux
5 *
6 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19 #include "usb_pnp_notify.h"
20 #include <linux/delay.h>
21 #include <linux/kthread.h>
22 #include <linux/notifier.h>
23 #include <linux/usb.h>
24 #include "hdf_device_desc.h"
25 #include "hdf_log.h"
26 #include "osal_mem.h"
27 #include "securec.h"
28
29 #define HDF_LOG_TAG USB_PNP_NOTIFY
30 #ifndef USB_GADGET_ADD
31 #define USB_GADGET_ADD 0x0005
32 #endif
33 #ifndef USB_GADGET_REMOVE
34 #define USB_GADGET_REMOVE 0x0006
35 #endif
36
37 static wait_queue_head_t g_usbPnpNotifyReportWait;
38 static wait_queue_head_t g_gadgetPnpNotifyReportWait;
39 static struct task_struct *g_usbPnpNotifyReportThread = NULL;
40 static struct task_struct *g_gadgetPnpNotifyReportThread = NULL;
41 static enum UsbPnpNotifyServiceCmd g_usbPnpNotifyCmdType = USB_PNP_NOTIFY_ADD_INTERFACE;
42 static enum UsbPnpNotifyRemoveType g_usbPnpNotifyRemoveType = USB_PNP_NOTIFY_REMOVE_BUS_DEV_NUM;
43 static uint8_t g_gadgetPnpNotifyType = 0;
44 static unsigned long g_preAcion = 0;
45 struct OsalMutex g_usbSendEventLock;
46 struct OsalMutex g_gadgetSendEventLock;
47 struct usb_device *g_usbDevice = NULL;
48 struct UsbPnpAddRemoveInfo g_usbPnpInfo;
49 struct DListHead g_usbPnpInfoListHead;
50 #if USB_PNP_NOTIFY_TEST_MODE == true
51 struct UsbPnpNotifyMatchInfoTable *g_testUsbPnpInfo = NULL;
52 #endif
53
UsbPnpNotifyCreateInfo(void)54 static struct UsbPnpDeviceInfo *UsbPnpNotifyCreateInfo(void)
55 {
56 struct UsbPnpDeviceInfo *infoTemp = NULL;
57 unsigned char *ptr = NULL;
58 static int32_t idNum = 0;
59 int32_t ret;
60
61 ptr = OsalMemCalloc(sizeof(struct UsbPnpDeviceInfo));
62 if (ptr == NULL) {
63 HDF_LOGE("%s:%d OsalMemAlloc faile ", __func__, __LINE__);
64 return NULL;
65 }
66 infoTemp = (struct UsbPnpDeviceInfo *)ptr;
67
68 if (idNum++ >= INT32_MAX) {
69 idNum = 0;
70 }
71 infoTemp->id = idNum;
72 OsalMutexInit(&infoTemp->lock);
73 infoTemp->status = USB_PNP_DEVICE_INIT_STATUS;
74 DListHeadInit(&infoTemp->list);
75 ret = memset_s(infoTemp->interfaceRemoveStatus, USB_PNP_INFO_MAX_INTERFACES, 0, sizeof(infoTemp->interfaceRemoveStatus));
76 if (ret != HDF_SUCCESS) {
77 HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__);
78 OsalMemFree(ptr);
79 return NULL;
80 }
81
82 DListInsertTail(&infoTemp->list, &g_usbPnpInfoListHead);
83 return infoTemp;
84 }
85
UsbPnpNotifyFindInfo(struct UsbInfoQueryPara queryPara)86 static struct UsbPnpDeviceInfo *UsbPnpNotifyFindInfo(struct UsbInfoQueryPara queryPara)
87 {
88 struct UsbPnpDeviceInfo *infoPos = NULL;
89 struct UsbPnpDeviceInfo *infoTemp = NULL;
90 bool findFlag = false;
91
92 if (DListIsEmpty(&g_usbPnpInfoListHead)) {
93 HDF_LOGE("%s:%d usb pnp list head is empty. ", __func__, __LINE__);
94 return NULL;
95 }
96
97 DLIST_FOR_EACH_ENTRY_SAFE(infoPos, infoTemp, &g_usbPnpInfoListHead, struct UsbPnpDeviceInfo, list) {
98 switch (queryPara.type) {
99 case USB_INFO_NORMAL_TYPE:
100 if ((infoPos->info.devNum == queryPara.devNum) && (infoPos->info.busNum == queryPara.busNum)) {
101 findFlag = true;
102 }
103 break;
104 case USB_INFO_ID_TYPE:
105 if (infoPos->id == queryPara.id) {
106 findFlag = true;
107 }
108 break;
109 case USB_INFO_DEVICE_ADDRESS_TYPE:
110 if (infoPos->info.usbDevAddr == queryPara.usbDevAddr) {
111 findFlag = true;
112 }
113 break;
114 default:
115 break;
116 }
117
118 if (findFlag == true) {
119 break;
120 }
121 }
122
123 if (findFlag == false) {
124 HDF_LOGE("%s:%d the usb pnp info to be find does not exist. ", __func__, __LINE__);
125 return NULL;
126 } else {
127 return infoPos;
128 }
129 }
130
UsbPnpNotifyDestroyInfo(struct UsbPnpDeviceInfo * deviceInfo)131 static HDF_STATUS UsbPnpNotifyDestroyInfo(struct UsbPnpDeviceInfo *deviceInfo)
132 {
133 HDF_STATUS ret = HDF_SUCCESS;
134 struct UsbPnpDeviceInfo *infoPos = NULL;
135 struct UsbPnpDeviceInfo *infoTemp = NULL;
136 bool findFlag = false;
137
138 if (deviceInfo == NULL) {
139 ret = HDF_FAILURE;
140 HDF_LOGE("%s:%d the deviceInfo is NULL, ret=%d ", __func__, __LINE__, ret);
141 return ret;
142 }
143
144 if (DListIsEmpty(&g_usbPnpInfoListHead)) {
145 HDF_LOGI("%s:%d the g_usbPnpInfoListHead is empty.", __func__, __LINE__);
146 return HDF_SUCCESS;
147 }
148
149 DLIST_FOR_EACH_ENTRY_SAFE(infoPos, infoTemp, &g_usbPnpInfoListHead, struct UsbPnpDeviceInfo, list) {
150 if (infoPos->id == deviceInfo->id) {
151 findFlag = true;
152 DListRemove(&infoPos->list);
153 OsalMemFree((void *)infoPos);
154 infoPos = NULL;
155 break;
156 }
157 }
158
159 if (findFlag == false) {
160 ret = HDF_FAILURE;
161 HDF_LOGE("%s:%d the deviceInfoto be destroyed does not exist, ret=%d ", __func__, __LINE__, ret);
162 }
163
164 return ret;
165 }
166
UsbPnpNotifyAddInitInfo(struct UsbPnpDeviceInfo * deviceInfo,union UsbPnpDeviceInfoData infoData)167 static int32_t UsbPnpNotifyAddInitInfo(struct UsbPnpDeviceInfo *deviceInfo, union UsbPnpDeviceInfoData infoData)
168 {
169 int32_t ret = HDF_SUCCESS;
170 uint8_t i;
171
172 deviceInfo->info.usbDevAddr = (uint64_t)infoData.usbDev;
173 deviceInfo->info.devNum = infoData.usbDev->devnum;
174 if (infoData.usbDev->bus == NULL) {
175 HDF_LOGE("%s infoData.usbDev->bus=%px is NULL", __func__, infoData.usbDev->bus);
176 ret = HDF_ERR_INVALID_PARAM;
177 goto OUT;
178 }
179 deviceInfo->info.busNum = infoData.usbDev->bus->busnum;
180
181 deviceInfo->info.deviceInfo.vendorId = le16_to_cpu(infoData.usbDev->descriptor.idVendor);
182 deviceInfo->info.deviceInfo.productId = le16_to_cpu(infoData.usbDev->descriptor.idProduct);
183 deviceInfo->info.deviceInfo.bcdDeviceLow = le16_to_cpu(infoData.usbDev->descriptor.bcdDevice);
184 deviceInfo->info.deviceInfo.bcdDeviceHigh = le16_to_cpu(infoData.usbDev->descriptor.bcdDevice);
185 deviceInfo->info.deviceInfo.deviceClass = infoData.usbDev->descriptor.bDeviceClass;
186 deviceInfo->info.deviceInfo.deviceSubClass = infoData.usbDev->descriptor.bDeviceSubClass;
187 deviceInfo->info.deviceInfo.deviceProtocol = infoData.usbDev->descriptor.bDeviceProtocol;
188
189 if (infoData.usbDev->actconfig == NULL) {
190 HDF_LOGE("%s infoData.usbDev->actconfig=%p is NULL", __func__, infoData.usbDev->actconfig);
191 ret = HDF_ERR_INVALID_PARAM;
192 goto OUT;
193 }
194 deviceInfo->info.numInfos = infoData.usbDev->actconfig->desc.bNumInterfaces;
195 for (i = 0; i < deviceInfo->info.numInfos; i++) {
196 if ((infoData.usbDev->actconfig->interface[i] == NULL) ||
197 (infoData.usbDev->actconfig->interface[i]->cur_altsetting == NULL)) {
198 HDF_LOGE("%{public}s interface[%{public}d] or interface[%{public}d]->cur_altsetting is NULL",
199 __func__, i, i);
200 ret = HDF_ERR_INVALID_PARAM;
201 goto OUT;
202 }
203 deviceInfo->info.interfaceInfo[i].interfaceClass =
204 infoData.usbDev->actconfig->interface[i]->cur_altsetting->desc.bInterfaceClass;
205 deviceInfo->info.interfaceInfo[i].interfaceSubClass =
206 infoData.usbDev->actconfig->interface[i]->cur_altsetting->desc.bInterfaceSubClass;
207 deviceInfo->info.interfaceInfo[i].interfaceProtocol =
208 infoData.usbDev->actconfig->interface[i]->cur_altsetting->desc.bInterfaceProtocol;
209 deviceInfo->info.interfaceInfo[i].interfaceNumber =
210 infoData.usbDev->actconfig->interface[i]->cur_altsetting->desc.bInterfaceNumber;
211
212 HDF_LOGI("%s:%d i=%d, interfaceInfo=0x%x-0x%x-0x%x-0x%x",
213 __func__, __LINE__, i, deviceInfo->info.interfaceInfo[i].interfaceClass,
214 deviceInfo->info.interfaceInfo[i].interfaceSubClass,
215 deviceInfo->info.interfaceInfo[i].interfaceProtocol,
216 deviceInfo->info.interfaceInfo[i].interfaceNumber);
217 }
218
219 OUT:
220 return ret;
221 }
222
UsbPnpNotifyAddInterfaceInitInfo(struct UsbPnpDeviceInfo * deviceInfo,union UsbPnpDeviceInfoData infoData,struct UsbPnpNotifyMatchInfoTable * infoTable)223 static void UsbPnpNotifyAddInterfaceInitInfo(struct UsbPnpDeviceInfo *deviceInfo,
224 union UsbPnpDeviceInfoData infoData, struct UsbPnpNotifyMatchInfoTable *infoTable)
225 {
226 uint8_t i;
227 uint8_t j;
228
229 for (i = 0; i < deviceInfo->info.numInfos; i++) {
230 if ((infoData.infoData->interfaceClass == deviceInfo->info.interfaceInfo[i].interfaceClass)
231 && (infoData.infoData->interfaceSubClass == deviceInfo->info.interfaceInfo[i].interfaceSubClass)
232 && (infoData.infoData->interfaceProtocol == deviceInfo->info.interfaceInfo[i].interfaceProtocol)
233 && (infoData.infoData->interfaceNumber == deviceInfo->info.interfaceInfo[i].interfaceNumber)) {
234 if (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_INTERFACE) {
235 deviceInfo->interfaceRemoveStatus[i] = true;
236 } else if (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_INTERFACE) {
237 deviceInfo->interfaceRemoveStatus[i] = false;
238 }
239 }
240 }
241
242 if (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_INTERFACE) {
243 infoTable->numInfos = 1;
244 infoTable->interfaceInfo[0].interfaceClass = infoData.infoData->interfaceClass;
245 infoTable->interfaceInfo[0].interfaceSubClass = infoData.infoData->interfaceSubClass;
246 infoTable->interfaceInfo[0].interfaceProtocol = infoData.infoData->interfaceProtocol;
247 infoTable->interfaceInfo[0].interfaceNumber = infoData.infoData->interfaceNumber;
248 } else {
249 for (i = 0, j = 0; i < deviceInfo->info.numInfos; i++) {
250 if (deviceInfo->interfaceRemoveStatus[i] == true) {
251 HDF_LOGI("%s:%d j=%d deviceInfo->interfaceRemoveStatus[%d] is true!", __func__, __LINE__, j, i);
252 continue;
253 }
254 infoTable->interfaceInfo[j].interfaceClass = deviceInfo->info.interfaceInfo[i].interfaceClass;
255 infoTable->interfaceInfo[j].interfaceSubClass = deviceInfo->info.interfaceInfo[i].interfaceSubClass;
256 infoTable->interfaceInfo[j].interfaceProtocol = deviceInfo->info.interfaceInfo[i].interfaceProtocol;
257 infoTable->interfaceInfo[j].interfaceNumber = deviceInfo->info.interfaceInfo[i].interfaceNumber;
258 j++;
259
260 HDF_LOGI("%s:%d i=%d, j=%d, interfaceInfo=0x%x-0x%x-0x%x-0x%x",
261 __func__, __LINE__, i, j - 1, infoTable->interfaceInfo[j - 1].interfaceClass,
262 infoTable->interfaceInfo[j - 1].interfaceSubClass,
263 infoTable->interfaceInfo[j - 1].interfaceProtocol,
264 infoTable->interfaceInfo[j - 1].interfaceNumber);
265 }
266 infoTable->numInfos = j;
267 }
268 }
269
UsbPnpNotifyInitInfo(struct HdfSBuf * sbuf,struct UsbPnpDeviceInfo * deviceInfo,union UsbPnpDeviceInfoData infoData)270 static int32_t UsbPnpNotifyInitInfo(
271 struct HdfSBuf *sbuf, struct UsbPnpDeviceInfo *deviceInfo, union UsbPnpDeviceInfoData infoData)
272 {
273 int32_t ret = HDF_SUCCESS;
274 const void *data = NULL;
275
276 if ((g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_INTERFACE)
277 || (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_INTERFACE)) {
278 static struct UsbPnpNotifyMatchInfoTable infoTable;
279
280 infoTable.usbDevAddr = deviceInfo->info.usbDevAddr;
281 infoTable.devNum = deviceInfo->info.devNum;
282 infoTable.busNum = deviceInfo->info.busNum;
283 infoTable.deviceInfo.vendorId = deviceInfo->info.deviceInfo.vendorId;
284 infoTable.deviceInfo.productId = deviceInfo->info.deviceInfo.productId;
285 infoTable.deviceInfo.bcdDeviceLow = deviceInfo->info.deviceInfo.bcdDeviceLow;
286 infoTable.deviceInfo.bcdDeviceHigh = deviceInfo->info.deviceInfo.bcdDeviceHigh;
287 infoTable.deviceInfo.deviceClass = deviceInfo->info.deviceInfo.deviceClass;
288 infoTable.deviceInfo.deviceSubClass = deviceInfo->info.deviceInfo.deviceSubClass;
289 infoTable.deviceInfo.deviceProtocol = deviceInfo->info.deviceInfo.deviceProtocol;
290 infoTable.removeType = g_usbPnpNotifyRemoveType;
291
292 UsbPnpNotifyAddInterfaceInitInfo(deviceInfo, infoData, &infoTable);
293
294 data = (const void *)(&infoTable);
295 } else if (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REPORT_INTERFACE) {
296 ret = UsbPnpNotifyAddInitInfo(deviceInfo, infoData);
297 if (ret != HDF_SUCCESS) {
298 goto OUT;
299 }
300
301 data = (const void *)(&deviceInfo->info);
302 } else {
303 data = (const void *)(&deviceInfo->info);
304 }
305
306 if (!HdfSbufWriteBuffer(sbuf, data, sizeof(struct UsbPnpNotifyMatchInfoTable))) {
307 HDF_LOGE("%s:%d sbuf write data failed", __func__, __LINE__);
308 ret = HDF_FAILURE;
309 goto OUT;
310 }
311
312 OUT:
313 return ret;
314 }
315
UsbPnpNotifyGetDeviceInfo(void * eventData,union UsbPnpDeviceInfoData * pnpInfoData,struct UsbPnpDeviceInfo ** deviceInfo)316 static int32_t UsbPnpNotifyGetDeviceInfo(void *eventData, union UsbPnpDeviceInfoData *pnpInfoData,
317 struct UsbPnpDeviceInfo **deviceInfo)
318 {
319 struct UsbInfoQueryPara infoQueryPara;
320
321 if ((g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_INTERFACE)
322 || (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_INTERFACE)) {
323 pnpInfoData->infoData = (struct UsbPnpAddRemoveInfo *)eventData;
324 } else {
325 pnpInfoData->usbDev = (struct usb_device *)eventData;
326 }
327
328 if ((g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_INTERFACE)
329 || (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_INTERFACE)) {
330 infoQueryPara.type = USB_INFO_NORMAL_TYPE;
331 infoQueryPara.devNum = pnpInfoData->infoData->devNum;
332 infoQueryPara.busNum = pnpInfoData->infoData->busNum;
333 *deviceInfo = UsbPnpNotifyFindInfo(infoQueryPara);
334 } else if ((g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_DEVICE)
335 || (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_DEVICE)) {
336 infoQueryPara.type = USB_INFO_DEVICE_ADDRESS_TYPE;
337 infoQueryPara.usbDevAddr = (uint64_t)pnpInfoData->usbDev;
338 *deviceInfo = UsbPnpNotifyFindInfo(infoQueryPara);
339 } else {
340 *deviceInfo = UsbPnpNotifyCreateInfo();
341 }
342
343 if (*deviceInfo == NULL) {
344 HDF_LOGE("%s:%d create or find info failed", __func__, __LINE__);
345 return HDF_FAILURE;
346 }
347
348 (*deviceInfo)->info.removeType = g_usbPnpNotifyRemoveType;
349
350 return HDF_SUCCESS;
351 }
352
UsbPnpNotifyHdfSendEvent(const struct HdfDeviceObject * deviceObject,void * eventData)353 static int32_t UsbPnpNotifyHdfSendEvent(const struct HdfDeviceObject *deviceObject,
354 void *eventData)
355 {
356 int32_t ret;
357 struct UsbPnpDeviceInfo *deviceInfo = NULL;
358 struct HdfSBuf *data = NULL;
359 union UsbPnpDeviceInfoData pnpInfoData;
360
361 if ((deviceObject == NULL) || (eventData == NULL)) {
362 HDF_LOGE("%s deviceObject=%p or eventData=%p is NULL", __func__, deviceObject, eventData);
363 return HDF_ERR_INVALID_PARAM;
364 }
365
366 data = HdfSbufObtainDefaultSize();
367 if (data == NULL) {
368 HDF_LOGE("%s:%d InitDataBlock failed", __func__, __LINE__);
369 return HDF_FAILURE;
370 }
371
372 ret = UsbPnpNotifyGetDeviceInfo(eventData, &pnpInfoData, &deviceInfo);
373 if (ret != HDF_SUCCESS) {
374 HDF_LOGE("%s:%d UsbPnpNotifyGetDeviceInfo failed, ret=%d", __func__, __LINE__, ret);
375 goto ERROR_DEVICE_INFO;
376 }
377
378 ret = UsbPnpNotifyInitInfo(data, deviceInfo, pnpInfoData);
379 if (ret != HDF_SUCCESS) {
380 HDF_LOGE("%s:%d UsbPnpNotifyInitInfo failed, ret=%d", __func__, __LINE__, ret);
381 goto OUT;
382 }
383
384 HDF_LOGI("%s:%d report one device information, %d usbDevAddr=%llu, devNum=%d, busNum=%d, infoTable=%d-0x%x-0x%x!",
385 __func__, __LINE__, g_usbPnpNotifyCmdType, deviceInfo->info.usbDevAddr, deviceInfo->info.devNum,
386 deviceInfo->info.busNum, deviceInfo->info.numInfos, deviceInfo->info.deviceInfo.vendorId,
387 deviceInfo->info.deviceInfo.productId);
388
389 OsalMutexLock(&deviceInfo->lock);
390 if (deviceInfo->status == USB_PNP_DEVICE_INIT_STATUS) {
391 ret = HdfDeviceSendEvent(deviceObject, g_usbPnpNotifyCmdType, data);
392 if (ret != HDF_SUCCESS) {
393 OsalMutexUnlock(&deviceInfo->lock);
394 HDF_LOGE("%s:%d HdfDeviceSendEvent ret=%d", __func__, __LINE__, ret);
395 goto OUT;
396 }
397 deviceInfo->status = USB_PNP_DEVICE_ADD_STATUS;
398 } else {
399 ret = HDF_ERR_INVALID_OBJECT;
400 }
401 OsalMutexUnlock(&deviceInfo->lock);
402
403 OUT:
404 if ((ret != HDF_SUCCESS) || (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_DEVICE)) {
405 if (UsbPnpNotifyDestroyInfo(deviceInfo) != HDF_SUCCESS) {
406 HDF_LOGE("%s:%d UsbPnpNotifyDestroyInfo fail", __func__, __LINE__);
407 }
408 }
409 ERROR_DEVICE_INFO:
410 HdfSbufRecycle(data);
411 return ret;
412 }
413
414 #if USB_PNP_NOTIFY_TEST_MODE == true
TestReadPnpInfo(struct HdfSBuf * data)415 static void TestReadPnpInfo(struct HdfSBuf *data)
416 {
417 uint32_t infoSize;
418 bool flag;
419
420 flag = HdfSbufReadBuffer(data, (const void **)(&g_testUsbPnpInfo), &infoSize);
421 if ((flag == false) || (g_testUsbPnpInfo == NULL)) {
422 HDF_LOGE("%s: fail to read g_testUsbPnpInfo, flag=%d, g_testUsbPnpInfo=%px", \
423 __func__, flag, g_testUsbPnpInfo);
424 return;
425 }
426
427 HDF_LOGI("%s:%d infoSize=%d g_testUsbPnpInfo=%px read success!", __func__, __LINE__, infoSize, g_testUsbPnpInfo);
428 }
429
TestPnpNotifyFillInfoTable(struct UsbPnpNotifyMatchInfoTable * infoTable)430 static void TestPnpNotifyFillInfoTable(struct UsbPnpNotifyMatchInfoTable *infoTable)
431 {
432 int8_t i;
433
434 infoTable->usbDevAddr = g_testUsbPnpInfo->usbDevAddr;
435 infoTable->devNum = g_testUsbPnpInfo->devNum;
436 if (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_TEST) {
437 infoTable->busNum = -1;
438 } else {
439 infoTable->busNum = g_testUsbPnpInfo->busNum;
440 }
441
442 infoTable->deviceInfo.vendorId = g_testUsbPnpInfo->deviceInfo.vendorId;
443 infoTable->deviceInfo.productId = g_testUsbPnpInfo->deviceInfo.productId;
444 infoTable->deviceInfo.bcdDeviceLow = g_testUsbPnpInfo->deviceInfo.bcdDeviceLow;
445 infoTable->deviceInfo.bcdDeviceHigh = g_testUsbPnpInfo->deviceInfo.bcdDeviceHigh;
446 infoTable->deviceInfo.deviceClass = g_testUsbPnpInfo->deviceInfo.deviceClass;
447 infoTable->deviceInfo.deviceSubClass = g_testUsbPnpInfo->deviceInfo.deviceSubClass;
448 infoTable->deviceInfo.deviceProtocol = g_testUsbPnpInfo->deviceInfo.deviceProtocol;
449
450 infoTable->removeType = g_usbPnpNotifyRemoveType;
451
452 if (g_usbPnpNotifyCmdType != USB_PNP_NOTIFY_REMOVE_TEST) {
453 infoTable->numInfos = g_testUsbPnpInfo->numInfos;
454 for (i = 0; i < infoTable->numInfos; i++) {
455 infoTable->interfaceInfo[i].interfaceClass = g_testUsbPnpInfo->interfaceInfo[i].interfaceClass;
456 infoTable->interfaceInfo[i].interfaceSubClass = g_testUsbPnpInfo->interfaceInfo[i].interfaceSubClass;
457 infoTable->interfaceInfo[i].interfaceProtocol = g_testUsbPnpInfo->interfaceInfo[i].interfaceProtocol;
458 infoTable->interfaceInfo[i].interfaceNumber = g_testUsbPnpInfo->interfaceInfo[i].interfaceNumber;
459 }
460 }
461 }
462
TestPnpNotifyHdfSendEvent(const struct HdfDeviceObject * deviceObject)463 static int32_t TestPnpNotifyHdfSendEvent(const struct HdfDeviceObject *deviceObject)
464 {
465 struct UsbPnpNotifyMatchInfoTable infoTable;
466 struct HdfSBuf *data = NULL;
467
468 if ((deviceObject == NULL) || (g_testUsbPnpInfo == NULL)) {
469 HDF_LOGE("%s deviceObject=%px or g_testUsbPnpInfo=%px is NULL", __func__, deviceObject, g_testUsbPnpInfo);
470 return HDF_ERR_INVALID_PARAM;
471 }
472
473 data = HdfSbufObtainDefaultSize();
474 if (data == NULL) {
475 HDF_LOGE("%s InitDataBlock failed", __func__);
476 return HDF_FAILURE;
477 }
478
479 TestPnpNotifyFillInfoTable(&infoTable);
480
481 if (!HdfSbufWriteBuffer(data, (const void *)(&infoTable), sizeof(struct UsbPnpNotifyMatchInfoTable))) {
482 HDF_LOGE("%s: sbuf write infoTable failed", __func__);
483 goto OUT;
484 }
485
486 HDF_LOGI("%s: report one device information, %d usbDev=%llu, devNum=%d, busNum=%d, infoTable=%d-0x%x-0x%x!", \
487 __func__, g_usbPnpNotifyCmdType, infoTable.usbDevAddr, infoTable.devNum, infoTable.busNum, \
488 infoTable.numInfos, infoTable.deviceInfo.vendorId, infoTable.deviceInfo.productId);
489
490 int32_t ret = HdfDeviceSendEvent(deviceObject, g_usbPnpNotifyCmdType, data);
491 if (ret != HDF_SUCCESS) {
492 HDF_LOGE("%s: HdfDeviceSendEvent error=%d", __func__, ret);
493 goto OUT;
494 }
495
496 HdfSbufRecycle(data);
497 return ret;
498
499 OUT:
500 HdfSbufRecycle(data);
501 return HDF_FAILURE;
502 }
503 #endif
504
GadgetPnpNotifyHdfSendEvent(const struct HdfDeviceObject * deviceObject)505 static int32_t GadgetPnpNotifyHdfSendEvent(const struct HdfDeviceObject *deviceObject)
506 {
507 if (deviceObject == NULL) {
508 HDF_LOGE("%s deviceObject=%p", __func__, deviceObject);
509 return HDF_ERR_INVALID_PARAM;
510 }
511
512 struct HdfSBuf *data = NULL;
513 data = HdfSbufObtainDefaultSize();
514 if (data == NULL) {
515 HDF_LOGE("%s:%d InitDataBlock failed", __func__, __LINE__);
516 return HDF_FAILURE;
517 }
518 if (!HdfSbufWriteUint8(data, g_gadgetPnpNotifyType)) {
519 HDF_LOGE("%s, UsbEcmRead HdfSbufWriteInt8 error", __func__);
520 HdfSbufRecycle(data);
521 return HDF_FAILURE;
522 }
523 int32_t ret = HdfDeviceSendEvent(deviceObject, g_gadgetPnpNotifyType, data);
524 if (ret != HDF_SUCCESS) {
525 HDF_LOGE("%s:%d HdfDeviceSendEvent ret=%d", __func__, __LINE__, ret);
526 }
527
528 HdfSbufRecycle(data);
529 return ret;
530 }
531
UsbPnpNotifyFirstReport(struct usb_device * usbDev,void * data)532 static int32_t UsbPnpNotifyFirstReport(struct usb_device *usbDev, void *data)
533 {
534 int32_t ret;
535 struct HdfDeviceIoClient *client = (struct HdfDeviceIoClient *)data;
536
537 ret = UsbPnpNotifyHdfSendEvent(client->device, usbDev);
538
539 HDF_LOGI("%s: report all device information!", __func__);
540
541 return ret;
542 }
543
UsbPnpNotifyReportThread(void * arg)544 static int32_t UsbPnpNotifyReportThread(void* arg)
545 {
546 int32_t ret;
547 struct HdfDeviceObject *deviceObject = (struct HdfDeviceObject *)arg;
548
549 while (!kthread_should_stop()) {
550 #if USB_PNP_NOTIFY_TEST_MODE == false
551 ret = wait_event_interruptible(g_usbPnpNotifyReportWait, g_usbDevice != NULL);
552 #else
553 ret = wait_event_interruptible(g_usbPnpNotifyReportWait,
554 ((g_usbDevice != NULL) || (g_testUsbPnpInfo != NULL)));
555 #endif
556 if (!ret) {
557 HDF_LOGI("%s: UsbPnpNotifyReportThread start!", __func__);
558 }
559
560 OsalMutexLock(&g_usbSendEventLock);
561 #if USB_PNP_NOTIFY_TEST_MODE == true
562 if ((g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_TEST) || \
563 (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_TEST)) {
564 ret = TestPnpNotifyHdfSendEvent(deviceObject);
565 } else {
566 #endif
567 if ((g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_ADD_INTERFACE)
568 || (g_usbPnpNotifyCmdType == USB_PNP_NOTIFY_REMOVE_INTERFACE)) {
569 ret = UsbPnpNotifyHdfSendEvent(deviceObject, &g_usbPnpInfo);
570 } else {
571 ret = UsbPnpNotifyHdfSendEvent(deviceObject, g_usbDevice);
572 }
573 #if USB_PNP_NOTIFY_TEST_MODE == true
574 }
575 #endif
576 if (ret != HDF_SUCCESS) {
577 HDF_LOGI("%s: UsbPnpNotifyHdfSendEvent error=%d!", __func__, ret);
578 }
579
580 g_usbDevice = NULL;
581 #if USB_PNP_NOTIFY_TEST_MODE == true
582 g_testUsbPnpInfo = NULL;
583 #endif
584 OsalMutexUnlock(&g_usbSendEventLock);
585
586 msleep(USB_PNP_NOTIFY_MSLEEP_TIME);
587 }
588
589 HDF_LOGI("%s: usb pnp notify handle kthread exiting!", __func__);
590
591 return 0;
592 }
593
GadgetPnpNotifyReportThread(void * arg)594 static int32_t GadgetPnpNotifyReportThread(void* arg)
595 {
596 int32_t ret;
597 struct HdfDeviceObject *deviceObject = (struct HdfDeviceObject *)arg;
598
599 while (!kthread_should_stop()) {
600 ret = wait_event_interruptible(g_gadgetPnpNotifyReportWait,
601 (g_gadgetPnpNotifyType != 0));
602 if (!ret) {
603 HDF_LOGI("%s: GadgetPnpNotifyReportThread start!", __func__);
604 }
605 OsalMutexLock(&g_gadgetSendEventLock);
606 ret = GadgetPnpNotifyHdfSendEvent(deviceObject);
607 if (ret != HDF_SUCCESS) {
608 HDF_LOGI("%s: UsbPnpNotifyHdfSendEvent error=%d!", __func__, ret);
609 }
610 g_gadgetPnpNotifyType = 0;
611 OsalMutexUnlock(&g_gadgetSendEventLock);
612 msleep(USB_PNP_NOTIFY_MSLEEP_TIME);
613 }
614
615 HDF_LOGI("%s: gadget pnp notify handle kthread exiting!", __func__);
616
617 return 0;
618 }
619
UsbPnpNotifyCallback(struct notifier_block * self,unsigned long action,void * dev)620 static int32_t UsbPnpNotifyCallback(struct notifier_block *self, unsigned long action, void *dev)
621 {
622 int32_t ret;
623 struct UsbInfoQueryPara infoQueryPara;
624 struct UsbPnpDeviceInfo *deviceInfo = NULL;
625 union UsbPnpDeviceInfoData pnpInfoData;
626
627 HDF_LOGI("%s: action=0x%lx", __func__, action);
628
629 switch (action) {
630 case USB_DEVICE_ADD:
631 pnpInfoData.usbDev = dev;
632 deviceInfo = UsbPnpNotifyCreateInfo();
633 if (deviceInfo == NULL) {
634 HDF_LOGE("%s:%d USB_DEVICE_ADD create info failed", __func__, __LINE__);
635 } else {
636 ret = UsbPnpNotifyAddInitInfo(deviceInfo, pnpInfoData);
637 if (ret != HDF_SUCCESS) {
638 HDF_LOGE("%s:%d USB_DEVICE_ADD UsbPnpNotifyAddInitInfo error", __func__, __LINE__);
639 } else {
640 OsalMutexLock(&g_usbSendEventLock);
641 g_usbDevice = dev;
642 g_usbPnpNotifyCmdType = USB_PNP_NOTIFY_ADD_DEVICE;
643 OsalMutexUnlock(&g_usbSendEventLock);
644 wake_up_interruptible(&g_usbPnpNotifyReportWait);
645 }
646 }
647 break;
648 case USB_DEVICE_REMOVE:
649 infoQueryPara.type = USB_INFO_DEVICE_ADDRESS_TYPE;
650 infoQueryPara.usbDevAddr = (uint64_t)dev;
651 deviceInfo = UsbPnpNotifyFindInfo(infoQueryPara);
652 if (deviceInfo == NULL) {
653 HDF_LOGE("%s:%d USB_DEVICE_REMOVE find info failed", __func__, __LINE__);
654 } else {
655 OsalMutexLock(&deviceInfo->lock);
656 if (deviceInfo->status != USB_PNP_DEVICE_INIT_STATUS) {
657 deviceInfo->status = USB_PNP_DEVICE_INIT_STATUS;
658 } else {
659 deviceInfo->status = USB_PNP_DEVICE_REMOVE_STATUS;
660 }
661 OsalMutexUnlock(&deviceInfo->lock);
662 OsalMutexLock(&g_usbSendEventLock);
663 g_usbDevice = dev;
664 g_usbPnpNotifyCmdType = USB_PNP_NOTIFY_REMOVE_DEVICE;
665 g_usbPnpNotifyRemoveType = USB_PNP_NOTIFY_REMOVE_BUS_DEV_NUM;
666 OsalMutexUnlock(&g_usbSendEventLock);
667 wake_up_interruptible(&g_usbPnpNotifyReportWait);
668 }
669 break;
670 case USB_GADGET_ADD:
671 case USB_GADGET_REMOVE:
672 OsalMutexLock(&g_gadgetSendEventLock);
673 if (g_preAcion == action) {
674 OsalMutexUnlock(&g_gadgetSendEventLock);
675 break;
676 }
677 if (action == USB_GADGET_ADD) {
678 g_gadgetPnpNotifyType = USB_PNP_DRIVER_GADGET_ADD;
679 } else {
680 g_gadgetPnpNotifyType = USB_PNP_DRIVER_GADGET_REMOVE;
681 }
682 OsalMutexUnlock(&g_gadgetSendEventLock);
683 HDF_LOGI("%s:%d g_gadgetPnpNotifyType = %d", __func__, __LINE__, g_gadgetPnpNotifyType);
684 wake_up_interruptible(&g_gadgetPnpNotifyReportWait);
685 g_preAcion = action;
686 break;
687 default:
688 HDF_LOGI("%s: the action = 0x%lx is not defined!", __func__, action);
689 break;
690 }
691
692 return NOTIFY_OK;
693 }
694
695 static struct notifier_block g_usbPnpNotifyNb = {
696 .notifier_call = UsbPnpNotifyCallback,
697 };
698
UsbPnpNotifyReadPnpInfo(struct HdfSBuf * data)699 static void UsbPnpNotifyReadPnpInfo(struct HdfSBuf *data)
700 {
701 struct UsbInfoQueryPara infoQueryPara;
702 struct UsbPnpDeviceInfo *deviceInfo = NULL;
703 struct UsbPnpAddRemoveInfo *usbPnpInfo = NULL;
704 uint32_t infoSize;
705 bool flag;
706
707 flag = HdfSbufReadBuffer(data, (const void **)(&usbPnpInfo), &infoSize);
708 if ((flag == false) || (usbPnpInfo == NULL)) {
709 HDF_LOGE("%s: fail to read g_usbPnpInfo, flag=%d, usbPnpInfo=%px", \
710 __func__, flag, usbPnpInfo);
711 return;
712 }
713
714 g_usbPnpInfo.devNum = usbPnpInfo->devNum;
715 g_usbPnpInfo.busNum = usbPnpInfo->busNum;
716 g_usbPnpInfo.interfaceNumber = usbPnpInfo->interfaceNumber;
717 g_usbPnpInfo.interfaceClass = usbPnpInfo->interfaceClass;
718 g_usbPnpInfo.interfaceSubClass = usbPnpInfo->interfaceSubClass;
719 g_usbPnpInfo.interfaceProtocol = usbPnpInfo->interfaceProtocol;
720
721 g_usbDevice = (struct usb_device *)&g_usbPnpInfo;
722
723 infoQueryPara.type = USB_INFO_NORMAL_TYPE;
724 infoQueryPara.devNum = usbPnpInfo->devNum;
725 infoQueryPara.busNum = usbPnpInfo->busNum;
726 deviceInfo = UsbPnpNotifyFindInfo(infoQueryPara);
727 if (deviceInfo == NULL) {
728 HDF_LOGE("%s:%d add or remove interface find info failed", __func__, __LINE__);
729 } else {
730 OsalMutexLock(&deviceInfo->lock);
731 if (deviceInfo->status != USB_PNP_DEVICE_INIT_STATUS) {
732 deviceInfo->status = USB_PNP_DEVICE_INIT_STATUS;
733 } else {
734 deviceInfo->status = USB_PNP_DEVICE_INTERFACE_STATUS;
735 }
736 OsalMutexUnlock(&deviceInfo->lock);
737 }
738
739 HDF_LOGI("%s:%d infoSize=%d g_usbPnpInfo=%px-%d-%d-%d-%d-%d-%d read success!",
740 __func__, __LINE__, infoSize, &g_usbPnpInfo, g_usbPnpInfo.devNum, g_usbPnpInfo.busNum,
741 g_usbPnpInfo.interfaceNumber, g_usbPnpInfo.interfaceClass, g_usbPnpInfo.interfaceSubClass,
742 g_usbPnpInfo.interfaceProtocol);
743 }
744
UsbPnpGetDevices(struct HdfSBuf * reply)745 static int32_t UsbPnpGetDevices(struct HdfSBuf *reply)
746 {
747 int32_t ret = HDF_SUCCESS;
748 struct UsbPnpDeviceInfo *infoPos = NULL;
749 struct UsbPnpDeviceInfo *infoTemp = NULL;
750
751 if (DListIsEmpty(&g_usbPnpInfoListHead)) {
752 return ret;
753 }
754 DLIST_FOR_EACH_ENTRY_SAFE(infoPos, infoTemp, &g_usbPnpInfoListHead, struct UsbPnpDeviceInfo, list){
755 if (!HdfSbufWriteInt32(reply, infoPos->info.busNum)) {
756 break;
757 }
758 if (!HdfSbufWriteInt32(reply, infoPos->info.devNum)) {
759 break;
760 }
761 if (!HdfSbufWriteUint8(reply, infoPos->info.deviceInfo.deviceClass)) {
762 break;
763 }
764 if (!HdfSbufWriteUint8(reply, infoPos->info.deviceInfo.deviceSubClass)) {
765 break;
766 }
767 if (!HdfSbufWriteUint8(reply, infoPos->info.deviceInfo.deviceProtocol)) {
768 break;
769 }
770 if (!HdfSbufWriteUint8(reply, infoPos->status)) {
771 break;
772 }
773 }
774 return ret;
775 }
776
UsbPnpNotifyDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)777 static int32_t UsbPnpNotifyDispatch(struct HdfDeviceIoClient *client, int32_t cmd,
778 struct HdfSBuf *data, struct HdfSBuf *reply)
779 {
780 int32_t ret = HDF_SUCCESS;
781
782 HDF_LOGI("%s: received cmd = %d", __func__, cmd);
783
784 OsalMutexLock(&g_usbSendEventLock);
785 if (USB_PNP_DRIVER_GETDEVICES != cmd) {
786 g_usbPnpNotifyCmdType = cmd;
787 }
788
789 switch (cmd) {
790 case USB_PNP_NOTIFY_ADD_INTERFACE:
791 UsbPnpNotifyReadPnpInfo(data);
792 wake_up_interruptible(&g_usbPnpNotifyReportWait);
793 break;
794 case USB_PNP_NOTIFY_REMOVE_INTERFACE:
795 UsbPnpNotifyReadPnpInfo(data);
796 g_usbPnpNotifyRemoveType = USB_PNP_NOTIFY_REMOVE_INTERFACE_NUM;
797 wake_up_interruptible(&g_usbPnpNotifyReportWait);
798 break;
799 case USB_PNP_NOTIFY_REPORT_INTERFACE:
800 usb_for_each_dev((void *)client, UsbPnpNotifyFirstReport);
801 break;
802 #if USB_PNP_NOTIFY_TEST_MODE == true
803 case USB_PNP_NOTIFY_ADD_TEST:
804 TestReadPnpInfo(data);
805 wake_up_interruptible(&g_usbPnpNotifyReportWait);
806 break;
807 case USB_PNP_NOTIFY_REMOVE_TEST:
808 TestReadPnpInfo(data);
809 g_usbPnpNotifyRemoveType = g_testUsbPnpInfo->removeType;
810 wake_up_interruptible(&g_usbPnpNotifyReportWait);
811 break;
812 #endif
813 case USB_PNP_DRIVER_GETDEVICES:
814 UsbPnpGetDevices(reply);
815 break;
816 default:
817 ret = HDF_ERR_NOT_SUPPORT;
818 break;
819 }
820 OsalMutexUnlock(&g_usbSendEventLock);
821
822 if (!HdfSbufWriteInt32(reply, INT32_MAX)) {
823 HDF_LOGE("%s: reply int32 fail", __func__);
824 }
825
826 return ret;
827 }
828
UsbPnpNotifyBind(struct HdfDeviceObject * device)829 static int32_t UsbPnpNotifyBind(struct HdfDeviceObject *device)
830 {
831 static struct IDeviceIoService pnpNotifyService = {
832 .Dispatch = UsbPnpNotifyDispatch,
833 };
834
835 HDF_LOGI("%s: Enter!", __func__);
836
837 if (device == NULL) {
838 HDF_LOGE("%s: device is NULL!", __func__);
839 return HDF_ERR_INVALID_OBJECT;
840 }
841
842 device->service = &pnpNotifyService;
843
844 return HDF_SUCCESS;
845 }
846
UsbPnpNotifyInit(struct HdfDeviceObject * device)847 static int32_t UsbPnpNotifyInit(struct HdfDeviceObject *device)
848 {
849 static bool firstInitFlag = true;
850
851 HDF_LOGI("%s: Enter!", __func__);
852
853 if (device == NULL) {
854 HDF_LOGE("%s: device is NULL", __func__);
855 return HDF_ERR_INVALID_OBJECT;
856 }
857
858 if (firstInitFlag == true) {
859 firstInitFlag = false;
860
861 DListHeadInit(&g_usbPnpInfoListHead);
862 }
863
864 init_waitqueue_head(&g_usbPnpNotifyReportWait);
865 init_waitqueue_head(&g_gadgetPnpNotifyReportWait);
866
867 OsalMutexInit(&g_usbSendEventLock);
868 OsalMutexInit(&g_gadgetSendEventLock);
869
870 /* Add a new notify for usb pnp notify module. */
871 usb_register_notify(&g_usbPnpNotifyNb);
872
873 /* Creat thread to handle send usb interface information. */
874 if (NULL == g_usbPnpNotifyReportThread) {
875 g_usbPnpNotifyReportThread = kthread_run(UsbPnpNotifyReportThread,
876 (void *)device, "usb pnp notify handle kthread");
877 if (g_usbPnpNotifyReportThread == NULL) {
878 HDF_LOGE("%s: kthread_run g_usbPnpNotifyReportThread is NULL", __func__);
879 }
880 } else {
881 HDF_LOGI("%s: g_usbPnpNotifyReportThread is already running!", __func__);
882 }
883
884 /* Creat thread to handle gadeget information. */
885 if (NULL == g_gadgetPnpNotifyReportThread) {
886 g_gadgetPnpNotifyReportThread = kthread_run(GadgetPnpNotifyReportThread,
887 (void *)device, "gadget pnp notify handle kthread");
888 if (g_usbPnpNotifyReportThread == NULL) {
889 HDF_LOGE("%s: kthread_run g_usbPnpNotifyReportThread is NULL", __func__);
890 }
891 } else {
892 HDF_LOGI("%s: g_devPnpNotifyReportThread is already running!", __func__);
893 }
894
895 return HDF_SUCCESS;
896 }
897
UsbPnpNotifyRelease(struct HdfDeviceObject * device)898 static void UsbPnpNotifyRelease(struct HdfDeviceObject *device)
899 {
900 if (device == NULL) {
901 HDF_LOGI("%s: device is null", __func__);
902 return;
903 }
904
905 if (g_usbPnpNotifyReportThread == NULL) {
906 HDF_LOGI("%s: g_usbPnpNotifyReportThread is not running!", __func__);
907 } else {
908 kthread_stop(g_usbPnpNotifyReportThread);
909 }
910 if (g_gadgetPnpNotifyReportThread == NULL) {
911 HDF_LOGI("%s: g_usbPnpNotifyReportThread is not running!", __func__);
912 } else {
913 kthread_stop(g_gadgetPnpNotifyReportThread);
914 }
915
916 usb_unregister_notify(&g_usbPnpNotifyNb);
917
918 OsalMutexDestroy(&g_usbSendEventLock);
919 OsalMutexDestroy(&g_gadgetSendEventLock);
920
921 HDF_LOGI("%s: release done!", __func__);
922
923 return;
924 }
925
926 struct HdfDriverEntry g_usbPnpNotifyEntry = {
927 .moduleVersion = 1,
928 .Bind = UsbPnpNotifyBind,
929 .Init = UsbPnpNotifyInit,
930 .Release = UsbPnpNotifyRelease,
931 .moduleName = "HDF_USB_PNP_NOTIFY",
932 };
933
934 HDF_INIT(g_usbPnpNotifyEntry);
935