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