1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2011-03-12 Yi Qiu first version
9 * 2021-02-23 Leslie Lee provide possibility for multi usb host
10 */
11
12 #include <rtthread.h>
13 #include <rtservice.h>
14 #include <drivers/usb_host.h>
15
16 static rt_list_t _driver_list;
17 static rt_bool_t _driver_list_created = RT_FALSE;
18
19 /**
20 * This function will initilize the usb class driver related data structure,
21 * and it should be invoked in the usb system initialization.
22 *
23 * @return the error code, RT_EOK on successfully.
24 */
rt_usbh_class_driver_init(void)25 rt_err_t rt_usbh_class_driver_init(void)
26 {
27 if (_driver_list_created == RT_FALSE)
28 {
29 rt_list_init(&_driver_list);
30 _driver_list_created = RT_TRUE;
31 }
32 return RT_EOK;
33 }
34
35 /**
36 * This function will register an usb class driver to the class driver manager.
37 *
38 * @param drv the pointer of the usb class driver.
39 *
40 * @return the error code, RT_EOK on successfully.
41 */
42
rt_usbh_class_driver_register(ucd_t drv)43 rt_err_t rt_usbh_class_driver_register(ucd_t drv)
44 {
45 if (drv == RT_NULL) return -RT_ERROR;
46
47 if (rt_usbh_class_driver_find(drv->class_code, drv->subclass_code) == RT_NULL)
48 {
49 /* insert class driver into driver list */
50 rt_list_insert_after(&_driver_list, &(drv->list));
51 }
52
53 return RT_EOK;
54 }
55
56 /**
57 * This function will removes a previously registed usb class driver.
58 *
59 * @param drv the pointer of the usb class driver structure.
60 *
61 * @return the error code, RT_EOK on successfully.
62 */
rt_usbh_class_driver_unregister(ucd_t drv)63 rt_err_t rt_usbh_class_driver_unregister(ucd_t drv)
64 {
65 RT_ASSERT(drv != RT_NULL);
66
67 /* remove class driver from driver list */
68 rt_list_remove(&(drv->list));
69
70 return RT_EOK;
71 }
72
73 /**
74 * This function will run an usb class driver.
75 *
76 * @param drv the pointer of usb class driver.
77 * @param args the parameter of run function.
78 *
79 * @return the error code, RT_EOK on successfully.
80 */
rt_usbh_class_driver_enable(ucd_t drv,void * args)81 rt_err_t rt_usbh_class_driver_enable(ucd_t drv, void* args)
82 {
83 RT_ASSERT(drv != RT_NULL);
84
85 if(drv->enable != RT_NULL)
86 drv->enable(args);
87
88 return RT_EOK;
89 }
90
91 /**
92 * This function will stop a usb class driver.
93 *
94 * @param drv the pointer of usb class driver structure.
95 * @param args the argument of the stop function.
96 *
97 * @return the error code, RT_EOK on successfully.
98 */
rt_usbh_class_driver_disable(ucd_t drv,void * args)99 rt_err_t rt_usbh_class_driver_disable(ucd_t drv, void* args)
100 {
101 RT_ASSERT(drv != RT_NULL);
102
103 if(drv->disable != RT_NULL)
104 drv->disable(args);
105
106 return RT_EOK;
107 }
108
109
110 /**
111 * This function finds a usb class driver by specified class code and subclass code.
112 *
113 * @param class_code the usb class driver's class code.
114 * @param subclass_code the usb class driver's sub class code.
115 *
116 * @return the registered usb class driver on successful, or RT_NULL on failure.
117 */
rt_usbh_class_driver_find(int class_code,int subclass_code)118 ucd_t rt_usbh_class_driver_find(int class_code, int subclass_code)
119 {
120 struct rt_list_node *node;
121
122 /* enter critical */
123 if (rt_thread_self() != RT_NULL)
124 rt_enter_critical();
125
126 /* try to find driver object */
127 for (node = _driver_list.next; node != &_driver_list; node = node->next)
128 {
129 ucd_t drv =
130 (ucd_t)rt_list_entry(node, struct uclass_driver, list);
131 if (drv->class_code == class_code)
132 {
133 /* leave critical */
134 if (rt_thread_self() != RT_NULL)
135 rt_exit_critical();
136
137 return drv;
138 }
139 }
140
141 /* leave critical */
142 if (rt_thread_self() != RT_NULL)
143 rt_exit_critical();
144
145 /* not found */
146 return RT_NULL;
147 }
148