• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "usbd.h"
17 #include "hdf_log.h"
18 #include "securec.h"
19 #include "hdf_device_object.h"
20 #include "usb_ddk_pnp_loader.h"
21 #include "usbd_dispatcher.h"
22 
23 #define HDF_LOG_TAG Usbd
24 #define HEX_NUM_09 0x09
25 #define HDF_USB_INFO_MAX_SIZE (USB_MAX_DEVICE_NUMBER * 12) // all usb device info, 12 byte is reply size
26 
27 const int32_t DEFAULT_PORT_ID = 1;
28 const int32_t DEFAULT_POWER_ROLE = 2;
29 const int32_t DEFAULT_DATA_ROLE = 2;
30 
31 struct HdfIoService *g_usbPnpServ = NULL;
32 struct HdfDevEventlistener g_usbPnpListener = {0};
33 
34 int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);
35 
36 /* function defind in usbd_publisher.c */
37 int32_t UsbdRealseDevices(struct UsbdService *service);
38 int32_t UsbdDeviceCreateAndAttach(struct UsbdService *service, uint8_t busNum, uint8_t devAddr);
39 int32_t UsbdDeviceDettach(struct UsbdService *service, uint8_t busNum, uint8_t devAddr);
40 int32_t UsbdRemoveBusDev(struct UsbdService *service, uint8_t busNum);
41 
UsbdPnpLoaderEventReceived(void * priv,uint32_t id,struct HdfSBuf * data)42 static int32_t UsbdPnpLoaderEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
43 {
44     struct UsbPnpNotifyMatchInfoTable *infoTable = NULL;
45     struct UsbdService *super = (struct UsbdService *)priv;
46     if (super == NULL) {
47         HDF_LOGE("%{public}s priv super is NULL", __func__);
48         return HDF_ERR_INVALID_PARAM;
49     }
50     if (USB_PNP_DRIVER_GADGET_ADD == id) {
51         NotifySubscriberDevice(super->subscriber, ACT_UPDEVICE, 0, 0);
52         return HDF_SUCCESS;
53     } else if (USB_PNP_DRIVER_GADGET_REMOVE == id) {
54         NotifySubscriberDevice(super->subscriber, ACT_DOWNDEVICE, 0, 0);
55         return HDF_SUCCESS;
56     }
57     uint32_t infoSize;
58     bool flag = HdfSbufReadBuffer(data, (const void **)(&infoTable), &infoSize);
59     if ((flag == false) || (infoTable == NULL)) {
60         HDF_LOGE(
61             "%{public}s: fail to read infoTable in event data, "
62             "flag=%{public}d, infoTable=%{public}p",
63             __func__, flag, infoTable);
64         return HDF_ERR_INVALID_PARAM;
65     }
66     if (infoTable->deviceInfo.deviceClass == HEX_NUM_09) {
67         HDF_LOGI("%{public}s:%{public}d hub device", __func__, __LINE__);
68         if (USB_PNP_NOTIFY_REMOVE_DEVICE == id) {
69             HDF_LOGI("%{public}s:%{public}d UsbdRemoveBusDev busNum:%{public}d", __func__, __LINE__, infoTable->busNum);
70             UsbdRemoveBusDev(super, infoTable->busNum);
71         }
72         return HDF_SUCCESS;
73     }
74     if (id == USB_PNP_NOTIFY_ADD_DEVICE) {
75         UsbdDeviceCreateAndAttach(super, infoTable->busNum, infoTable->devNum);
76         NotifySubscriberDevice(super->subscriber, ACT_DEVUP, infoTable->busNum, infoTable->devNum);
77     } else if (id == USB_PNP_NOTIFY_REMOVE_DEVICE) {
78         UsbdDeviceDettach(super, infoTable->busNum, infoTable->devNum);
79         NotifySubscriberDevice(super->subscriber, ACT_DEVDOWN, infoTable->busNum, infoTable->devNum);
80     }
81     return HDF_SUCCESS;
82 }
83 
UsbdEventHandle(const struct UsbdService * inst)84 static int32_t UsbdEventHandle(const struct UsbdService *inst)
85 {
86     g_usbPnpServ = HdfIoServiceBind(USB_PNP_NOTIFY_SERVICE_NAME);
87     g_usbPnpListener.callBack = UsbdPnpLoaderEventReceived;
88     g_usbPnpListener.priv = (void *)(inst);
89 
90     if (g_usbPnpServ == NULL) {
91         HDF_LOGE("%{public}s: HdfIoServiceBind faile.", __func__);
92         return HDF_ERR_INVALID_OBJECT;
93     }
94 
95     int32_t status;
96     status = HdfDeviceRegisterEventListener(g_usbPnpServ, &g_usbPnpListener);
97     if (status != HDF_SUCCESS) {
98         HDF_LOGE("HdfDeviceRegisterEventListener faile status=%{public}d", status);
99     }
100 
101     return status;
102 }
103 
UsbdDriverBind(struct HdfDeviceObject * device)104 static int32_t UsbdDriverBind(struct HdfDeviceObject *device)
105 {
106     if (device == NULL) {
107         HDF_LOGE("%{public}s:%{public}d device is null", __func__, __LINE__);
108         return HDF_ERR_INVALID_OBJECT;
109     }
110     struct UsbdService *dev = (struct UsbdService *)OsalMemCalloc(sizeof(struct UsbdService));
111     if (dev == NULL) {
112         HDF_LOGE("%{public}s: Alloc dev device failed", __func__);
113         return HDF_FAILURE;
114     }
115     if (memset_s(dev, sizeof(struct UsbdService), 0, sizeof(struct UsbdService)) != EOK) {
116         HDF_LOGE("%{public}s:%{public}d  memset_s faild ", __func__, __LINE__);
117         OsalMemFree(dev);
118         return HDF_FAILURE;
119     }
120     if (OsalMutexInit(&dev->lock) != HDF_SUCCESS) {
121         HDF_LOGE(" init lock fail!");
122         OsalMemFree(dev);
123         return HDF_FAILURE;
124     }
125     int32_t ret = HDF_SUCCESS;
126     struct UsbPnpNotifyServiceInfo *info = (struct UsbPnpNotifyServiceInfo *)device->priv;
127     if (info != NULL) {
128         UsbdDeviceCreateAndAttach(dev, info->busNum, info->devNum);
129     }
130 
131     if (HdfDeviceObjectSetInterfaceDesc(device, HDF_USB_USBD_DESC) != HDF_SUCCESS) {
132         HDF_LOGE(" Set Desc fail!");
133         OsalMemFree(dev);
134         return HDF_FAILURE;
135     }
136 
137     device->service = &(dev->service);
138     device->service->Dispatch = UsbdServiceDispatch;
139     dev->device = device;
140     ret = UsbdEventHandle(dev);
141     if (ret != HDF_SUCCESS) {
142         HDF_LOGE("%{public}s:  UsbdEventHandle ret=%{public}d", __func__, ret);
143     }
144     return ret;
145 }
146 
UsbdDriverInit(struct HdfDeviceObject * device)147 static int32_t UsbdDriverInit(struct HdfDeviceObject *device)
148 {
149     if (device == NULL) {
150         HDF_LOGE("%{public}s:%{public}d device is null", __func__, __LINE__);
151         return HDF_ERR_INVALID_OBJECT;
152     }
153 
154     return HDF_SUCCESS;
155 }
156 
UsbdEventHandleRelease(void)157 static int32_t UsbdEventHandleRelease(void)
158 {
159     int32_t ret = HDF_SUCCESS;
160     if (g_usbPnpServ != NULL) {
161         ret = HdfDeviceUnregisterEventListener(g_usbPnpServ, &g_usbPnpListener);
162         HdfIoServiceRecycle(g_usbPnpServ);
163     }
164     g_usbPnpServ = NULL;
165     g_usbPnpListener.callBack = NULL;
166     g_usbPnpListener.priv = NULL;
167 
168     return ret;
169 }
170 
UsbdDriverRelease(struct HdfDeviceObject * device)171 static void UsbdDriverRelease(struct HdfDeviceObject *device)
172 {
173     if (device == NULL) {
174         HDF_LOGE("%{public}s: device is NULL", __func__);
175         return;
176     }
177     int32_t ret = UsbdEventHandleRelease();
178     if (ret != HDF_SUCCESS) {
179         HDF_LOGE("%{public}s:  UsbdEventHandleRelease ret=%{public}d", __func__, ret);
180     }
181     struct UsbdService *dev = (struct UsbdService *)device->service;
182     UsbdRealseDevices(dev);
183 }
184 
185 struct HdfDriverEntry g_usbdDriverEntry = {
186     .moduleVersion = 1,
187     .moduleName = "usbd",
188     .Bind = UsbdDriverBind,
189     .Init = UsbdDriverInit,
190     .Release = UsbdDriverRelease,
191 };
192 HDF_INIT(g_usbdDriverEntry);
193 
HdfReadDevice(struct UsbdService * service,int32_t * count,int32_t * size,struct HdfSBuf * reply)194 static int32_t HdfReadDevice(struct UsbdService *service, int32_t *count, int32_t *size, struct HdfSBuf *reply)
195 {
196     int32_t busNum;
197     int32_t devNum;
198     uint8_t devClass;
199     uint8_t subClass;
200     uint8_t protocol;
201     uint8_t status;
202     if (!HdfSbufReadInt32(reply, &busNum)) {
203         HDF_LOGE("%{public}s: fail to get service call reply", __func__);
204         return HDF_ERR_INVALID_PARAM;
205     }
206     if (!HdfSbufReadInt32(reply, &devNum)) {
207         HDF_LOGE("%{public}s: fail to get service call reply", __func__);
208         return HDF_ERR_INVALID_PARAM;
209     }
210     if (!HdfSbufReadUint8(reply, &devClass)) {
211         HDF_LOGE("%{public}s:%{public}d fail to get service call reply", __func__, __LINE__);
212         return HDF_ERR_INVALID_OBJECT;
213     }
214     if (!HdfSbufReadUint8(reply, &subClass)) {
215         HDF_LOGE("%{public}s:%{public}d fail to get service call reply", __func__, __LINE__);
216         return HDF_ERR_INVALID_OBJECT;
217     }
218     if (!HdfSbufReadUint8(reply, &protocol)) {
219         HDF_LOGE("%{public}s:%{public}d fail to get service call reply", __func__, __LINE__);
220         return HDF_ERR_INVALID_OBJECT;
221     }
222     if (!HdfSbufReadUint8(reply, &status)) {
223         HDF_LOGE("%{public}s:%{public}d fail to get service call reply", __func__, __LINE__);
224         return HDF_ERR_INVALID_OBJECT;
225     }
226     HDF_LOGI(
227         "%{public}s:%{public}d OnStart get "
228         "device[%{public}d]:%{public}d:%{public}d status:%{pubic}d "
229         "class:%{public}d subClass:%{public}d protocol:%{pubic}d",
230         __func__, __LINE__, *count, busNum, devNum, status, devClass, subClass, protocol);
231     if (devClass != HEX_NUM_09) {
232         UsbdDeviceCreateAndAttach(service, busNum, devNum);
233         NotifySubscriberDevice(service->subscriber, ACT_DEVUP, busNum, devNum);
234         ++(*size);
235     }
236     ++(*count);
237     return HDF_SUCCESS;
238 }
239 
UsbdAddDevicesOnStart(struct UsbdService * service)240 static int32_t UsbdAddDevicesOnStart(struct UsbdService *service)
241 {
242     struct HdfIoService *usbPnpServ = HdfIoServiceBind(USB_PNP_NOTIFY_SERVICE_NAME);
243     if (service == NULL || usbPnpServ == NULL) {
244         HDF_LOGE(
245             "%{public}s:%{public}d service is NULL or HdfIoServiceBind.faile "
246             "serv:%{public}s.",
247             __func__, __LINE__, USB_PNP_NOTIFY_SERVICE_NAME);
248         return HDF_ERR_INVALID_OBJECT;
249     }
250 
251     struct HdfSBuf *data = HdfSbufObtain(HDF_USB_INFO_MAX_SIZE);
252     if (data == NULL) {
253         HDF_LOGE("%{public}s: fail to obtain sbuf data", __func__);
254         return HDF_DEV_ERR_NO_MEMORY;
255     }
256     struct HdfSBuf *reply = HdfSbufObtain(HDF_USB_INFO_MAX_SIZE);
257     if (reply == NULL) {
258         HDF_LOGE("%{public}s: fail to obtain sbuf reply", __func__);
259         HdfSbufRecycle(data);
260         HdfSbufRecycle(reply);
261         HdfIoServiceRecycle(usbPnpServ);
262         return HDF_DEV_ERR_NO_MEMORY;
263     }
264     int32_t ret = usbPnpServ->dispatcher->Dispatch(&usbPnpServ->object, USB_PNP_DRIVER_GETDEVICES, data, reply);
265     if (ret != HDF_SUCCESS) {
266         HDF_LOGE("%{public}s: fail to send serivice call, ret=%{public}d", __func__, ret);
267         HdfSbufRecycle(data);
268         HdfSbufRecycle(reply);
269         HdfIoServiceRecycle(usbPnpServ);
270         return ret;
271     }
272 
273     int32_t count = 0;
274     int32_t size = 0;
275     do {
276         ret = HdfReadDevice(service, &count, &size, reply);
277     } while (ret == HDF_SUCCESS);
278 
279     HdfSbufRecycle(data);
280     HdfSbufRecycle(reply);
281     HdfIoServiceRecycle(usbPnpServ);
282     return ret;
283 }
284 
BindUsbSubscriber(struct UsbdService * service,struct UsbdSubscriber * subscriber)285 int32_t BindUsbSubscriber(struct UsbdService *service, struct UsbdSubscriber *subscriber)
286 {
287     if (service == NULL) {
288         HDF_LOGE("%{public}s  service is NULL", __func__);
289         return HDF_ERR_INVALID_PARAM;
290     }
291     service->subscriber = subscriber;
292     UsbdAddDevicesOnStart(service);
293     return HDF_SUCCESS;
294 }
295 
UnbindUsbSubscriber(struct UsbdService * service)296 int32_t UnbindUsbSubscriber(struct UsbdService *service)
297 {
298     if (service == NULL) {
299         HDF_LOGE("%{public}s service is NULL", __func__);
300         return HDF_ERR_INVALID_PARAM;
301     }
302     if (service->subscriber != NULL) {
303         HDF_LOGW("%{public}s:%{public}d entry", __func__, __LINE__);
304         OsalMemFree(service->subscriber);
305         service->subscriber = NULL;
306     }
307     return HDF_SUCCESS;
308 }
309