1f9f848faSopenharmony_ci/*
2f9f848faSopenharmony_ci * Copyright (c) 2013-2023, Huawei Technologies Co., Ltd. All rights reserved.
3f9f848faSopenharmony_ci * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
4f9f848faSopenharmony_ci *
5f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
6f9f848faSopenharmony_ci * are permitted provided that the following conditions are met:
7f9f848faSopenharmony_ci *
8f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
9f9f848faSopenharmony_ci *    conditions and the following disclaimer.
10f9f848faSopenharmony_ci *
11f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12f9f848faSopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
13f9f848faSopenharmony_ci *    provided with the distribution.
14f9f848faSopenharmony_ci *
15f9f848faSopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16f9f848faSopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
17f9f848faSopenharmony_ci *    permission.
18f9f848faSopenharmony_ci *
19f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20f9f848faSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21f9f848faSopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f9f848faSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23f9f848faSopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24f9f848faSopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25f9f848faSopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26f9f848faSopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27f9f848faSopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28f9f848faSopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29f9f848faSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30f9f848faSopenharmony_ci */
31f9f848faSopenharmony_ci
32f9f848faSopenharmony_ci#include "usb_init.h"
33f9f848faSopenharmony_ci#include "usb_api_pri.h"
34f9f848faSopenharmony_ci#include "devmgr_service.h"
35f9f848faSopenharmony_ci#include "devsvc_manager_clnt.h"
36f9f848faSopenharmony_ci#include "hdf_device_object.h"
37f9f848faSopenharmony_ci
38f9f848faSopenharmony_citypedef struct usb_info {
39f9f848faSopenharmony_ci	bool b_init;
40f9f848faSopenharmony_ci	controller_type ctype;
41f9f848faSopenharmony_ci	device_type dtype;
42f9f848faSopenharmony_ci} usb_info_t;
43f9f848faSopenharmony_ci
44f9f848faSopenharmony_cistatic char *dev_name = NULL;
45f9f848faSopenharmony_cistatic bool uvc_enable = false;
46f9f848faSopenharmony_cistatic usb_info_t usb_info = { false, (controller_type)0xFFFF, (device_type)0xFFFF };
47f9f848faSopenharmony_cistatic struct mtx usb_mtx = PTHREAD_MUTEX_INITIALIZER;
48f9f848faSopenharmony_ci
49f9f848faSopenharmony_cistatic struct driver_module_data* usb_driver_mode_list[] = {
50f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_HOST_EHCI
51f9f848faSopenharmony_ci	/* xxx controller modules */
52f9f848faSopenharmony_ci	/* usb generial controller modules */
53f9f848faSopenharmony_ci	&usbus_ehci_driver_mod,
54f9f848faSopenharmony_ci#endif
55f9f848faSopenharmony_ci
56f9f848faSopenharmony_ci#if defined (LOSCFG_DRIVERS_USB_HOST_XHCI)
57f9f848faSopenharmony_ci	&usbus_xhci_driver_mod,
58f9f848faSopenharmony_ci#endif
59f9f848faSopenharmony_ci
60f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_HOST_DRIVER
61f9f848faSopenharmony_ci	/* xxx driver modules */
62f9f848faSopenharmony_ci	&uhub_uhub_driver_mod,
63f9f848faSopenharmony_ci	&uhub_usbus_driver_mod,
64f9f848faSopenharmony_ci#endif
65f9f848faSopenharmony_ci
66f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_4G_MODEM
67f9f848faSopenharmony_ci#ifndef LOSCFG_DRIVERS_HDF_USB_DDK_HOST
68f9f848faSopenharmony_ci	&cdce_uhub_driver_mod,
69f9f848faSopenharmony_ci#endif
70f9f848faSopenharmony_ci	//&bsd_u3g_uhub_driver_mod,
71f9f848faSopenharmony_ci#endif
72f9f848faSopenharmony_ci
73f9f848faSopenharmony_ci#if defined (LOSCFG_DRIVERS_USB_SERIAL) || defined (LOSCFG_DRIVERS_USB_4G_MODEM)
74f9f848faSopenharmony_ci	&u3g_uhub_driver_mod,
75f9f848faSopenharmony_ci#endif
76f9f848faSopenharmony_ci
77f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_MASS_STORAGE
78f9f848faSopenharmony_ci	&umass_uhub_driver_mod,
79f9f848faSopenharmony_ci#endif
80f9f848faSopenharmony_ci
81f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_ETHERNET
82f9f848faSopenharmony_ci	&axe_uhub_driver_mod,
83f9f848faSopenharmony_ci	&axge_uhub_driver_mod,
84f9f848faSopenharmony_ci#endif
85f9f848faSopenharmony_ci
86f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_RNDIS_HOST
87f9f848faSopenharmony_ci	&urndis_uhub_driver_mod,
88f9f848faSopenharmony_ci#endif
89f9f848faSopenharmony_ci
90f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_WIRELESS
91f9f848faSopenharmony_ci	&usb_linux_uhub_driver_mod,
92f9f848faSopenharmony_ci#endif
93f9f848faSopenharmony_ci
94f9f848faSopenharmony_ci#if defined (LOSCFG_DRIVERS_USB_HID_CLASS) && defined (LOSCFG_DRIVERS_HDF_INPUT)
95f9f848faSopenharmony_ci	&uhid_uhub_driver_mod,
96f9f848faSopenharmony_ci#endif
97f9f848faSopenharmony_ci
98f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_HDF_USB_DDK_DEVICE
99f9f848faSopenharmony_ci	&composite_hiudc3_driver_mod,
100f9f848faSopenharmony_ci#endif
101f9f848faSopenharmony_ci	NULL
102f9f848faSopenharmony_ci};
103f9f848faSopenharmony_ci
104f9f848faSopenharmony_ciextern device_t
105f9f848faSopenharmony_cibus_get_device(device_t dev, const char *name);
106f9f848faSopenharmony_ci
107f9f848faSopenharmony_civoid
108f9f848faSopenharmony_ciusbinfo_clean(void)
109f9f848faSopenharmony_ci{
110f9f848faSopenharmony_ci	dev_name = NULL;
111f9f848faSopenharmony_ci	uvc_enable = false;
112f9f848faSopenharmony_ci	usb_info.ctype = (controller_type)0xFFFF;
113f9f848faSopenharmony_ci	usb_info.dtype = (device_type)0xFFFF;
114f9f848faSopenharmony_ci	usb_info.b_init = false;
115f9f848faSopenharmony_ci	return;
116f9f848faSopenharmony_ci}
117f9f848faSopenharmony_ci
118f9f848faSopenharmony_cichar *
119f9f848faSopenharmony_cidev_name_get(void)
120f9f848faSopenharmony_ci{
121f9f848faSopenharmony_ci	return (dev_name);
122f9f848faSopenharmony_ci}
123f9f848faSopenharmony_ci
124f9f848faSopenharmony_cistatic uint32_t
125f9f848faSopenharmony_ciusb_loadonce(void)
126f9f848faSopenharmony_ci{
127f9f848faSopenharmony_ci	struct driver_module_data *data;
128f9f848faSopenharmony_ci	uint32_t i;
129f9f848faSopenharmony_ci
130f9f848faSopenharmony_ci	dprintf("usb %s\n",fetach_usbversion());
131f9f848faSopenharmony_ci
132f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB
133f9f848faSopenharmony_ci	/* init quirk */
134f9f848faSopenharmony_ci	usb_quirk_init(NULL);
135f9f848faSopenharmony_ci
136f9f848faSopenharmony_ci	for (i = 0; (data = usb_driver_mode_list[i]) && (data != NULL); i++) {
137f9f848faSopenharmony_ci		driver_module_handler(NULL, MOD_LOAD, data);
138f9f848faSopenharmony_ci	}
139f9f848faSopenharmony_ci#endif
140f9f848faSopenharmony_ci
141f9f848faSopenharmony_ci#ifdef LOSCFG_USB_DEBUG
142f9f848faSopenharmony_ci	usb_debug_module_regsiter();
143f9f848faSopenharmony_ci#endif
144f9f848faSopenharmony_ci
145f9f848faSopenharmony_ci	return (0);
146f9f848faSopenharmony_ci}
147f9f848faSopenharmony_ci
148f9f848faSopenharmony_cistatic void
149f9f848faSopenharmony_ciusb_unloadonce(void)
150f9f848faSopenharmony_ci{
151f9f848faSopenharmony_ci	uint32_t i;
152f9f848faSopenharmony_ci
153f9f848faSopenharmony_ci#ifdef LOSCFG_USB_DEBUG
154f9f848faSopenharmony_ci	usb_debug_module_unregsiter();
155f9f848faSopenharmony_ci#endif
156f9f848faSopenharmony_ci
157f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB
158f9f848faSopenharmony_ci	for (i = 0; usb_driver_mode_list[i] != NULL; i++) {
159f9f848faSopenharmony_ci		driver_module_handler(NULL, MOD_UNLOAD, usb_driver_mode_list[i]);
160f9f848faSopenharmony_ci	}
161f9f848faSopenharmony_ci#endif
162f9f848faSopenharmony_ci
163f9f848faSopenharmony_ci	return;
164f9f848faSopenharmony_ci}
165f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_HDF_USB_DDK_DEVICE
166f9f848faSopenharmony_cistatic struct HdfDeviceObject *HdfLoadUsbDevice(const char *serv_name)
167f9f848faSopenharmony_ci{
168f9f848faSopenharmony_ci	struct IDevmgrService *devmgr = DevmgrServiceGetInstance();
169f9f848faSopenharmony_ci	if(devmgr== NULL || devmgr->LoadDevice(devmgr, serv_name) != HDF_SUCCESS) {
170f9f848faSopenharmony_ci		dprintf("failed to load %s", serv_name);
171f9f848faSopenharmony_ci		return NULL;
172f9f848faSopenharmony_ci	}
173f9f848faSopenharmony_ci
174f9f848faSopenharmony_ci	return DevSvcManagerClntGetDeviceObject(serv_name);
175f9f848faSopenharmony_ci}
176f9f848faSopenharmony_ci
177f9f848faSopenharmony_cistruct HdfDeviceObject *HdfRegisterUsbDevice(struct HdfDeviceObject *usb_fn_master,
178f9f848faSopenharmony_ci	const char *driver_name, const char *serv_name)
179f9f848faSopenharmony_ci{
180f9f848faSopenharmony_ci	struct HdfDeviceObject *dev = HdfDeviceObjectAlloc(usb_fn_master, driver_name);
181f9f848faSopenharmony_ci	if (dev == NULL) {
182f9f848faSopenharmony_ci		dprintf("%s: failed to alloc device object", __func__);
183f9f848faSopenharmony_ci		return NULL;
184f9f848faSopenharmony_ci	}
185f9f848faSopenharmony_ci
186f9f848faSopenharmony_ci	if (HdfDeviceObjectRegister(dev) != HDF_SUCCESS) {
187f9f848faSopenharmony_ci		dprintf("%s: failed to regitst device %s", __func__, serv_name);
188f9f848faSopenharmony_ci		HdfDeviceObjectRelease(dev);
189f9f848faSopenharmony_ci		return NULL;
190f9f848faSopenharmony_ci	}
191f9f848faSopenharmony_ci
192f9f848faSopenharmony_ci	if (HdfDeviceObjectPublishService(dev, serv_name, SERVICE_POLICY_PUBLIC, 0664) != HDF_SUCCESS) {
193f9f848faSopenharmony_ci		dprintf("%s: failed to regitst device %s", __func__, serv_name);
194f9f848faSopenharmony_ci		HdfDeviceObjectRelease(dev);
195f9f848faSopenharmony_ci		return NULL;
196f9f848faSopenharmony_ci	}
197f9f848faSopenharmony_ci
198f9f848faSopenharmony_ci	return dev;
199f9f848faSopenharmony_ci}
200f9f848faSopenharmony_ci
201f9f848faSopenharmony_cistatic int composite_add(void)
202f9f848faSopenharmony_ci{
203f9f848faSopenharmony_ci	device_t udc;
204f9f848faSopenharmony_ci	device_t composite;
205f9f848faSopenharmony_ci
206f9f848faSopenharmony_ci	udc = bus_get_device(nexus, "hiudc3");
207f9f848faSopenharmony_ci	if (udc == NULL) {
208f9f848faSopenharmony_ci		return -1;
209f9f848faSopenharmony_ci	}
210f9f848faSopenharmony_ci
211f9f848faSopenharmony_ci	composite = device_add_child(udc, "composite", -1);
212f9f848faSopenharmony_ci	if (composite == NULL) {
213f9f848faSopenharmony_ci		return -1;
214f9f848faSopenharmony_ci	}
215f9f848faSopenharmony_ci
216f9f848faSopenharmony_ci	if (device_probe_and_attach(composite)) {
217f9f848faSopenharmony_ci		device_printf(composite, "WARNING: Probe and attach failed!\n");
218f9f848faSopenharmony_ci		return -1;
219f9f848faSopenharmony_ci	}
220f9f848faSopenharmony_ci	struct HdfDeviceObject *usb_fn_dev = HdfLoadUsbDevice("usbfn");
221f9f848faSopenharmony_ci	if (usb_fn_dev == NULL) {
222f9f848faSopenharmony_ci		dprintf("%s register usbfn may failed\n", __func__);
223f9f848faSopenharmony_ci	}
224f9f848faSopenharmony_ci
225f9f848faSopenharmony_ci	struct HdfDeviceObject *devobj = HdfRegisterUsbDevice(usb_fn_dev, "usbfn_cdcacm", "usbfn_cdcacm");
226f9f848faSopenharmony_ci	if (devobj == NULL) {
227f9f848faSopenharmony_ci		dprintf("%s register usbfn_cdcacm may failed\n", __func__);
228f9f848faSopenharmony_ci	}
229f9f848faSopenharmony_ci
230f9f848faSopenharmony_ci	devobj = HdfRegisterUsbDevice(usb_fn_dev, "usbfn_cdcecm", "usbfn_cdcecm");
231f9f848faSopenharmony_ci	if (devobj == NULL) {
232f9f848faSopenharmony_ci		dprintf("%s register usbfn_cdcecm may failed\n", __func__);
233f9f848faSopenharmony_ci	}
234f9f848faSopenharmony_ci	dprintf("%s success\n", __func__);
235f9f848faSopenharmony_ci	return 0;
236f9f848faSopenharmony_ci}
237f9f848faSopenharmony_ci#endif
238f9f848faSopenharmony_ci/*
239f9f848faSopenharmony_ci * step1: modify DRIVER_MODULE,register all driver module
240f9f848faSopenharmony_ci * step2: make ehci/ohci device (direct skip pci bus)
241f9f848faSopenharmony_ci * step3: insert ehci/ohci device into usb controller
242f9f848faSopenharmony_ci * step4: create ehci/ohci root hub device
243f9f848faSopenharmony_ci * step5: ehci/ohci transfer setup/start
244f9f848faSopenharmony_ci */
245f9f848faSopenharmony_ciuint32_t
246f9f848faSopenharmony_ciusb_init(controller_type ctype, device_type dtype)
247f9f848faSopenharmony_ci{
248f9f848faSopenharmony_ci	uint32_t ret;
249f9f848faSopenharmony_ci	static int usb_loaded = 0;
250f9f848faSopenharmony_ci
251f9f848faSopenharmony_ci	dprintf("\n******** %s in **********\n", __FUNCTION__);
252f9f848faSopenharmony_ci
253f9f848faSopenharmony_ci	mtx_lock(&usb_mtx);
254f9f848faSopenharmony_ci	if (usb_info.b_init) {
255f9f848faSopenharmony_ci		dprintf("\n duplicate usb_init %s, ctype:%d dtype:%d\n", __FUNCTION__, usb_info.ctype, usb_info.dtype);
256f9f848faSopenharmony_ci		mtx_unlock(&usb_mtx);
257f9f848faSopenharmony_ci		return (LOS_NOK);
258f9f848faSopenharmony_ci	}
259f9f848faSopenharmony_ci
260f9f848faSopenharmony_ci	if (usb_loaded == 0) {
261f9f848faSopenharmony_ci		ret = usb_loadonce();
262f9f848faSopenharmony_ci		if (ret) {
263f9f848faSopenharmony_ci			goto err;
264f9f848faSopenharmony_ci		}
265f9f848faSopenharmony_ci		usb_loaded = 1;
266f9f848faSopenharmony_ci	}
267f9f848faSopenharmony_ci
268f9f848faSopenharmony_ci	usb_dev_init(NULL);
269f9f848faSopenharmony_ci
270f9f848faSopenharmony_ci	if (ctype == HOST) {
271f9f848faSopenharmony_ci#if defined (LOSCFG_DRIVERS_USB_HOST_XHCI)
272f9f848faSopenharmony_ci		ret = hixhci_init();
273f9f848faSopenharmony_ci#endif
274f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB_HOST_EHCI
275f9f848faSopenharmony_ci		ret = hiehci_init();
276f9f848faSopenharmony_ci#endif
277f9f848faSopenharmony_ci	} else {
278f9f848faSopenharmony_ci#ifdef LOSCFG_DRIVERS_HDF_USB_DDK_DEVICE
279f9f848faSopenharmony_ci		ret = usbd_load_driver();
280f9f848faSopenharmony_ci		if (ret != LOS_OK) {
281f9f848faSopenharmony_ci			dprintf("usbd_load_driver failed ,ret = %d\n", ret);
282f9f848faSopenharmony_ci			goto err;
283f9f848faSopenharmony_ci		}
284f9f848faSopenharmony_ci		ret = composite_add();
285f9f848faSopenharmony_ci		if (ret != LOS_OK) {
286f9f848faSopenharmony_ci			dprintf("composite_add failed ,ret = %d\n", ret);
287f9f848faSopenharmony_ci			goto err;
288f9f848faSopenharmony_ci		}
289f9f848faSopenharmony_ci		ret = usbd_enable_interrupt();
290f9f848faSopenharmony_ci		if (ret != LOS_OK) {
291f9f848faSopenharmony_ci			dprintf("usbd_enable_interrupt failed, ret = %d\n", ret);
292f9f848faSopenharmony_ci			goto err;
293f9f848faSopenharmony_ci		}
294f9f848faSopenharmony_ci#endif
295f9f848faSopenharmony_ci	}
296f9f848faSopenharmony_ci
297f9f848faSopenharmony_ci	usb_info.b_init = true;
298f9f848faSopenharmony_ci	usb_info.ctype = ctype;
299f9f848faSopenharmony_ci	usb_info.dtype = dtype;
300f9f848faSopenharmony_ci
301f9f848faSopenharmony_ci	mtx_unlock(&usb_mtx);
302f9f848faSopenharmony_ci	dprintf("******** %s ok**********\n\n", __FUNCTION__);
303f9f848faSopenharmony_ci	return (LOS_OK);
304f9f848faSopenharmony_ci
305f9f848faSopenharmony_cierr:
306f9f848faSopenharmony_ci	mtx_unlock(&usb_mtx);
307f9f848faSopenharmony_ci	if (!usb_loaded) {
308f9f848faSopenharmony_ci		usb_unloadonce();
309f9f848faSopenharmony_ci	}
310f9f848faSopenharmony_ci	dprintf("******** %s fail**********\n\n", __FUNCTION__);
311f9f848faSopenharmony_ci
312f9f848faSopenharmony_ci	return (LOS_NOK);
313f9f848faSopenharmony_ci}
314f9f848faSopenharmony_ci
315f9f848faSopenharmony_ciuint32_t
316f9f848faSopenharmony_ciusb_deinit(void)
317f9f848faSopenharmony_ci{
318f9f848faSopenharmony_ci	uint32_t ret = LOS_OK;
319f9f848faSopenharmony_ci
320f9f848faSopenharmony_ci	dprintf("******** %s in **********\n\n", __FUNCTION__);
321f9f848faSopenharmony_ci	mtx_lock(&usb_mtx);
322f9f848faSopenharmony_ci
323f9f848faSopenharmony_ci	if (usb_info.b_init == false) {
324f9f848faSopenharmony_ci		dprintf("******** %s out, no init **********\n\n", __FUNCTION__);
325f9f848faSopenharmony_ci		goto err;
326f9f848faSopenharmony_ci	}
327f9f848faSopenharmony_ci
328f9f848faSopenharmony_ci	if (usb_info.ctype == HOST) {
329f9f848faSopenharmony_ci		dprintf("******** %s fail, host not support **********\n\n", __FUNCTION__);
330f9f848faSopenharmony_ci		goto err;
331f9f848faSopenharmony_ci	}
332f9f848faSopenharmony_ci
333f9f848faSopenharmony_ci	if (ret) {
334f9f848faSopenharmony_ci		dprintf("******** %s fail, %d **********\n\n", __FUNCTION__, ret);
335f9f848faSopenharmony_ci		goto err;
336f9f848faSopenharmony_ci	}
337f9f848faSopenharmony_ci
338f9f848faSopenharmony_ci	usb_dev_uninit(NULL);
339f9f848faSopenharmony_ci
340f9f848faSopenharmony_ci	dprintf(" ** %s uninit success **\n", dev_name_get());
341f9f848faSopenharmony_ci	usbinfo_clean();
342f9f848faSopenharmony_ci	mtx_unlock(&usb_mtx);
343f9f848faSopenharmony_ci	return (LOS_OK);
344f9f848faSopenharmony_ci
345f9f848faSopenharmony_cierr:
346f9f848faSopenharmony_ci	mtx_unlock(&usb_mtx);
347f9f848faSopenharmony_ci	return (LOS_NOK);
348f9f848faSopenharmony_ci}
349f9f848faSopenharmony_ci
350f9f848faSopenharmony_cibool
351f9f848faSopenharmony_ciusb_is_devicemode(void)
352f9f848faSopenharmony_ci{
353f9f848faSopenharmony_ci	return (HiUsbIsDeviceMode());
354f9f848faSopenharmony_ci}
355f9f848faSopenharmony_ci
356