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