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