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-3-12 Yi Qiu first version
9 * 2021-02-23 Leslie Lee provide possibility for multi usb host
10 */
11
12 #ifndef __RT_USB_HOST_H__
13 #define __RT_USB_HOST_H__
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19 #include <rtthread.h>
20 #include "usb_common.h"
21
22 #define USB_MAX_DEVICE 0x20
23 #define USB_MAX_INTERFACE 0x08
24 #define USB_HUB_PORT_NUM 0x04
25 #define SIZEOF_USB_REQUEST 0x08
26
27 #define DEV_STATUS_IDLE 0x00
28 #define DEV_STATUS_BUSY 0x01
29 #define DEV_STATUS_ERROR 0x02
30
31 #define UPIPE_STATUS_OK 0x00
32 #define UPIPE_STATUS_STALL 0x01
33 #define UPIPE_STATUS_ERROR 0x02
34
35 #define USBH_PID_SETUP 0x00
36 #define USBH_PID_DATA 0x01
37
38 struct uhcd;
39 struct uhintf;
40 struct uhub;
41 struct upipe;
42
43 struct uclass_driver
44 {
45 rt_list_t list;
46 int class_code;
47 int subclass_code;
48
49 rt_err_t (*enable)(void* arg);
50 rt_err_t (*disable)(void* arg);
51
52 void* user_data;
53 };
54 typedef struct uclass_driver* ucd_t;
55
56 struct uprotocal
57 {
58 rt_list_t list;
59 int pro_id;
60
61 rt_err_t (*init)(void* arg);
62 rt_err_t (*callback)(void* arg);
63 };
64 typedef struct uprotocal* uprotocal_t;
65
66 struct uinstance
67 {
68 struct rt_device parent;
69
70 struct udevice_descriptor dev_desc;
71 ucfg_desc_t cfg_desc;
72 struct uhcd *hcd;
73
74 struct upipe * pipe_ep0_out;
75 struct upipe * pipe_ep0_in;
76 rt_list_t pipe;
77
78 rt_uint8_t status;
79 rt_uint8_t type;
80 rt_uint8_t index;
81 rt_uint8_t address;
82 rt_uint8_t speed;
83 rt_uint8_t max_packet_size;
84 rt_uint8_t port;
85
86 struct uhub* parent_hub;
87 struct uhintf* intf[USB_MAX_INTERFACE];
88 };
89 typedef struct uinstance* uinst_t;
90
91 struct uhintf
92 {
93 struct uinstance* device;
94 uintf_desc_t intf_desc;
95
96 ucd_t drv;
97 void *user_data;
98 };
99
100 struct upipe
101 {
102 rt_list_t list;
103 rt_uint8_t pipe_index;
104 rt_uint32_t status;
105 struct uendpoint_descriptor ep;
106 uinst_t inst;
107 func_callback callback;
108 void* user_data;
109 };
110 typedef struct upipe* upipe_t;
111
112 struct uhub
113 {
114 struct uhub_descriptor hub_desc;
115 rt_uint8_t num_ports;
116 rt_uint32_t port_status[USB_HUB_PORT_NUM];
117 struct uinstance* child[USB_HUB_PORT_NUM];
118
119 rt_bool_t is_roothub;
120
121 rt_uint8_t buffer[8];
122 struct uinstance* self;
123 struct uhcd *hcd;
124 };
125 typedef struct uhub* uhub_t;
126
127 struct uhcd_ops
128 {
129 rt_err_t (*reset_port) (rt_uint8_t port);
130 int (*pipe_xfer) (upipe_t pipe, rt_uint8_t token, void* buffer, int nbytes, int timeout);
131 rt_err_t (*open_pipe) (upipe_t pipe);
132 rt_err_t (*close_pipe) (upipe_t pipe);
133 };
134 typedef struct uhcd_ops* uhcd_ops_t;
135 struct uhcd
136 {
137 struct rt_device parent;
138 uhcd_ops_t ops;
139 rt_uint8_t num_ports;
140 uhub_t roothub;
141 struct rt_messagequeue *usb_mq;
142 };
143 typedef struct uhcd* uhcd_t;
144
145 enum uhost_msg_type
146 {
147 USB_MSG_CONNECT_CHANGE,
148 USB_MSG_CALLBACK,
149 };
150 typedef enum uhost_msg_type uhost_msg_type;
151
152 struct uhost_msg
153 {
154 uhost_msg_type type;
155 union
156 {
157 struct uhub* hub;
158 struct
159 {
160 func_callback function;
161 void *context;
162 }cb;
163 }content;
164 };
165 typedef struct uhost_msg* uhost_msg_t;
166
167 /* usb host system interface */
168 rt_err_t rt_usb_host_init(const char *name);
169 void rt_usbh_hub_init(struct uhcd *hcd);
170
171 /* usb host core interface */
172 struct uinstance* rt_usbh_alloc_instance(uhcd_t uhcd);
173 rt_err_t rt_usbh_attatch_instance(struct uinstance* device);
174 rt_err_t rt_usbh_detach_instance(struct uinstance* device);
175 rt_err_t rt_usbh_get_descriptor(struct uinstance* device, rt_uint8_t type, void* buffer, int nbytes);
176 rt_err_t rt_usbh_set_configure(struct uinstance* device, int config);
177 rt_err_t rt_usbh_set_address(struct uinstance* device);
178 rt_err_t rt_usbh_set_interface(struct uinstance* device, int intf);
179 rt_err_t rt_usbh_clear_feature(struct uinstance* device, int endpoint, int feature);
180 rt_err_t rt_usbh_get_interface_descriptor(ucfg_desc_t cfg_desc, int num, uintf_desc_t* intf_desc);
181 rt_err_t rt_usbh_get_endpoint_descriptor(uintf_desc_t intf_desc, int num, uep_desc_t* ep_desc);
182
183 /* usb class driver interface */
184 rt_err_t rt_usbh_class_driver_init(void);
185 rt_err_t rt_usbh_class_driver_register(ucd_t drv);
186 rt_err_t rt_usbh_class_driver_unregister(ucd_t drv);
187 rt_err_t rt_usbh_class_driver_enable(ucd_t drv, void* args);
188 rt_err_t rt_usbh_class_driver_disable(ucd_t drv, void* args);
189 ucd_t rt_usbh_class_driver_find(int class_code, int subclass_code);
190
191 /* usb class driver implement */
192 ucd_t rt_usbh_class_driver_hub(void);
193 ucd_t rt_usbh_class_driver_storage(void);
194
195
196
197 /* usb hub interface */
198 rt_err_t rt_usbh_hub_get_descriptor(struct uinstance* device, rt_uint8_t *buffer,
199 rt_size_t size);
200 rt_err_t rt_usbh_hub_get_status(struct uinstance* device, rt_uint32_t* buffer);
201 rt_err_t rt_usbh_hub_get_port_status(uhub_t uhub, rt_uint16_t port,
202 rt_uint32_t* buffer);
203 rt_err_t rt_usbh_hub_clear_port_feature(uhub_t uhub, rt_uint16_t port,
204 rt_uint16_t feature);
205 rt_err_t rt_usbh_hub_set_port_feature(uhub_t uhub, rt_uint16_t port,
206 rt_uint16_t feature);
207 rt_err_t rt_usbh_hub_reset_port(uhub_t uhub, rt_uint16_t port);
208 rt_err_t rt_usbh_event_signal(uhcd_t uhcd, struct uhost_msg* msg);
209
210
211 void rt_usbh_root_hub_connect_handler(struct uhcd *hcd, rt_uint8_t port, rt_bool_t isHS);
212 void rt_usbh_root_hub_disconnect_handler(struct uhcd *hcd, rt_uint8_t port);
213
214 /* usb host controller driver interface */
rt_usb_instance_add_pipe(uinst_t inst,upipe_t pipe)215 rt_inline rt_err_t rt_usb_instance_add_pipe(uinst_t inst, upipe_t pipe)
216 {
217 RT_ASSERT(inst != RT_NULL);
218 RT_ASSERT(pipe != RT_NULL);
219 rt_list_insert_before(&inst->pipe, &pipe->list);
220 return RT_EOK;
221 }
rt_usb_instance_find_pipe(uinst_t inst,rt_uint8_t ep_address)222 rt_inline upipe_t rt_usb_instance_find_pipe(uinst_t inst,rt_uint8_t ep_address)
223 {
224 rt_list_t * l;
225 for(l = inst->pipe.next;l != &inst->pipe;l = l->next)
226 {
227 if(rt_list_entry(l,struct upipe,list)->ep.bEndpointAddress == ep_address)
228 {
229 return rt_list_entry(l,struct upipe,list);
230 }
231 }
232 return RT_NULL;
233 }
rt_usb_hcd_alloc_pipe(uhcd_t hcd,upipe_t * pipe,uinst_t inst,uep_desc_t ep)234 rt_inline rt_err_t rt_usb_hcd_alloc_pipe(uhcd_t hcd, upipe_t* pipe, uinst_t inst, uep_desc_t ep)
235 {
236 *pipe = (upipe_t)rt_malloc(sizeof(struct upipe));
237 if(*pipe == RT_NULL)
238 {
239 return -RT_ERROR;
240 }
241 rt_memset(*pipe,0,sizeof(struct upipe));
242 (*pipe)->inst = inst;
243 rt_memcpy(&(*pipe)->ep,ep,sizeof(struct uendpoint_descriptor));
244 return hcd->ops->open_pipe(*pipe);
245 }
rt_usb_pipe_add_callback(upipe_t pipe,func_callback callback)246 rt_inline void rt_usb_pipe_add_callback(upipe_t pipe, func_callback callback)
247 {
248 pipe->callback = callback;
249 }
250
rt_usb_hcd_free_pipe(uhcd_t hcd,upipe_t pipe)251 rt_inline rt_err_t rt_usb_hcd_free_pipe(uhcd_t hcd, upipe_t pipe)
252 {
253 RT_ASSERT(pipe != RT_NULL);
254 hcd->ops->close_pipe(pipe);
255 rt_free(pipe);
256 return RT_EOK;
257 }
258
259 int rt_usb_hcd_pipe_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, int nbytes, int timeout);
rt_usb_hcd_setup_xfer(uhcd_t hcd,upipe_t pipe,ureq_t setup,int timeout)260 rt_inline int rt_usb_hcd_setup_xfer(uhcd_t hcd, upipe_t pipe, ureq_t setup, int timeout)
261 {
262 return hcd->ops->pipe_xfer(pipe, USBH_PID_SETUP, (void *)setup, 8, timeout);
263 }
264
265 #ifdef __cplusplus
266 }
267 #endif
268
269 #endif
270