1 #pragma once
2 #include <common/sys/types.h>
3 
4 // usb设备在pci总线上的class
5 #define USB_CLASS 0xC
6 #define USB_SUBCLASS 0x3
7 
8 // 不同的usb设备在pci总线上的prog IF
9 #define USB_TYPE_UHCI 0x0
10 #define USB_TYPE_OHCI 0x10
11 #define USB_TYPE_EHCI 0x20
12 #define USB_TYPE_XHCI 0x30
13 #define USB_TYPE_UNSPEC 0x80 // Unspecified
14 #define USB_TYPE_DEVICE 0xfe // USB Device(Not controller)
15 
16 // Reset wait times(milliseconds) ,USB 2.0 specs, page 153, section 7.1.7.5, paragraph 3
17 #define USB_TIME_RST_RH 50    //  reset on a root hub
18 #define USB_TIME_RST_MIN 10   // minimum delay for a reset
19 #define USB_TIME_RST_NOMORE 3 // No more than this between resets for root hubs
20 #define USB_TIME_RST_REC 10   // reset recovery
21 
22 /**
23  * @brief usb描述符的头部
24  *
25  * String Descriptor:
26  * String Language Descriptor:
27  *      先获取头部,然后根据长度申请空间,再获取整个string desc
28  */
29 struct usb_desc_header
30 {
31     uint8_t len; // 整个描述符的大小(字节)
32     uint8_t type;
33 } __attribute__((packed));
34 
35 /**
36  * @brief usb 设备描述符
37  *
38  */
39 struct usb_device_desc
40 {
41     uint8_t len;
42     uint8_t type;
43     uint16_t usb_version;
44     uint8_t _class;
45     uint8_t subclass;
46     uint8_t protocol;
47     uint8_t max_packet_size;
48 
49     uint16_t vendor_id;
50     uint16_t product_id;
51     uint16_t device_rel;
52     uint8_t manufacturer_index;
53     uint8_t procuct_index;
54 
55     uint8_t serial_index;
56     uint8_t config; // number of configurations
57 } __attribute__((packed));
58 
59 /**
60  * @brief usb设备配置信息描述符
61  *
62  */
63 struct usb_config_desc
64 {
65     uint8_t len;            // 当前描述符的大小(字节)
66     uint8_t type;           // USB_DT_CONFIG
67     uint16_t total_len;     /*
68                                 Total length of data returned for this
69                                 configuration. Includes the combined length
70                                 of all descriptors (configuration, interface,
71                                 endpoint, and class- or vendor-specific)
72                                 returned for this configuration
73                             */
74     uint8_t num_interfaces; // 当前conf对应的接口数量
75     uint8_t value;          /*
76                                 Value to use as an argument to the
77                                 SetConfiguration() request to select this
78                                 configuration
79                             */
80     uint8_t index;          // Index of string descriptor describing this configuration
81     uint8_t bmAttr;         /*
82                                 Configuration characteristics:
83                                 D7: Reserved (要设置为1)
84                                 D6: Self-powered
85                                 D5: Remote Wakeup
86                                 D4...0: Reserved (设置为0)
87                             */
88     uint8_t max_power;      /*
89                                 当这个设备满载时,为在这个conf上提供对应的功能,需要消耗的电流值。
90                                 当设备是在High-speed时,这里的单位是2mA (也就是说,值为50,代表最大消耗100mA的电流)
91                                 当设备运行在Gen X speed时,这里的单位是8mA
92                             */
93 } __attribute__((packed));
94 
95 /**
96  * @brief usb接口描述符
97  *
98  */
99 struct usb_interface_desc
100 {
101     uint8_t len;
102     uint8_t type;                // USB_DT_INTERFACE
103     uint8_t interface_number;    // 当前接口序号(从0开始的)
104     uint8_t alternate_setting;   // used to select alt. setting
105     uint8_t num_endpoints;       // 当前interface的端点数量
106     uint8_t interface_class;     // Class code
107     uint8_t interface_sub_class; // Sub class code
108     uint8_t interface_protocol;  // 协议  These codes are qualified by the value of thebInterfaceClass and the
109                                  // bInterfaceSubClass fields.
110     uint8_t index;               // index of String Descriptor describing this interface
111 } __attribute__((packed));
112 
113 /**
114  * @brief usb端点描述符
115  *
116  * 详见usb3.2 Specification Table 9-26
117  */
118 struct usb_endpoint_desc
119 {
120     uint8_t len;
121     uint8_t type;          // descriptor type
122     uint8_t endpoint_addr; /*  Bit 3...0: The endpoint number
123                                Bit 6...4: Reserved, reset to zero
124                                Bit 7: Direction, ignored for
125                                control endpoints
126                                0 = OUT endpoint
127                                1 = IN endpoint
128                                */
129     uint8_t attributes;
130     uint16_t max_packet;
131     uint8_t interval;
132 };
133 
134 // 从endpoint描述符中获取max burst size大小
135 #define usb_get_max_burst_from_ep(__ep_desc) (((__ep_desc)->max_packet & 0x1800) >> 11)
136 
137 /**
138  * @brief usb设备请求包
139  *
140  */
141 struct usb_request_packet_t
142 {
143     uint8_t request_type;
144     uint8_t request;
145     uint16_t value;
146 
147     uint16_t index;
148     uint16_t length;
149 } __attribute__((packed));
150 // usb设备请求包的request_type字段的值
151 #define __USB_REQ_TYPE_H2D 0x00
152 #define __USB_REQ_TYPE_D2H 0x80
153 
154 #define __USB_REQ_TYPE_STANDARD 0x00
155 #define __USB_REQ_TYPE_CLASS 0x20
156 #define __USB_REQ_TYPE_VENDOR 0x40
157 #define __USB_REQ_TYPE_RSVD 0x60
158 
159 #define __USB_REQ_TYPE_DEVICE 0x00
160 #define __USB_REQ_TYPE_INTERFACE 0x01
161 #define __USB_REQ_TYPE_ENDPOINT 0x02
162 #define __USB_REQ_TYPE_OTHER 0x03
163 
164 #define USB_REQ_TYPE_GET_REQUEST (__USB_REQ_TYPE_D2H | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_DEVICE)
165 #define USB_REQ_TYPE_SET_REQUEST (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_DEVICE)
166 #define USB_REQ_TYPE_GET_INTERFACE_REQUEST (__USB_REQ_TYPE_D2H | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_INTERFACE)
167 #define USB_REQ_TYPE_SET_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_INTERFACE)
168 #define USB_REQ_TYPE_SET_CLASS_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_CLASS | __USB_REQ_TYPE_INTERFACE)
169 
170 // device requests
171 enum
172 {
173     USB_REQ_GET_STATUS = 0,
174     USB_REQ_CLEAR_FEATURE,
175     USB_REQ_SET_FEATURE = 3,
176     USB_REQ_SET_ADDRESS = 5,
177     USB_REQ_GET_DESCRIPTOR = 6,
178     USB_REQ_SET_DESCRIPTOR,
179     USB_REQ_GET_CONFIGURATION,
180     USB_REQ_SET_CONFIGURATION,
181     // interface requests
182     USB_REQ_GET_INTERFACE,
183     USB_REQ_SET_INTERFACE,
184     // standard endpoint requests
185     USB_REQ_SYNCH_FRAME,
186     USB_REQ_SET_ENCRYPTION,
187     USB_REQ_GET_ENCRYPTION,
188     USB_REQ_SET_HANDSHAKE,
189     USB_REQ_GET_HANDSHAKE,
190     USB_REQ_SET_CONNECTION,
191     USB_REQ_SET_SECURITY_DATA,
192     USB_REQ_GET_SECURITY_DATA,
193     USB_REQ_SET_WUSB_DATA,
194     USB_REQ_LOOPBACK_DATA_WRITE,
195     USB_REQ_LOOPBACK_DATA_READ,
196     USB_REQ_SET_INTERFACE_DS,
197     USB_REQ_GET_FW_STATUS = 26,
198     USB_REQ_SET_FW_STATUS,
199     USB_REQ_SET_SEL = 48,
200     USB_REQ_SET_ISOCH_DELAY,
201     // Device specific
202     USB_REQ_GET_MAX_LUNS = 0xFE,
203     USB_REQ_BULK_ONLY_RESET
204 };
205 
206 // Descriptor types
207 enum
208 {
209     USB_DT_DEVICE = 1,
210     USB_DT_CONFIG,
211     USB_DT_STRING,
212     USB_DT_INTERFACE,
213     USB_DT_ENDPOINT,
214     USB_DT_DEVICE_QUALIFIER,
215     USB_DT_OTHER_SPEED_CONFIG,
216     USB_DT_INTERFACE_POWER,
217     USB_DT_OTG,
218     USB_DT_DEBUG,
219     USB_DT_INTERFACE_ASSOSIATION,
220     USB_DT_BOS = 15,
221     USB_DT_DEVICE_CAPABILITY,
222 
223     USB_DT_HID = 0x21,
224     USB_DT_HID_REPORT,
225     USB_DT_HID_PHYSICAL,
226 
227     USB_DT_INTERFACE_FUNCTION = 0x24,
228     USB_DT_ENDPOINT_FUNCTION,
229 
230     // HUB = 0x29
231 
232     USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION = 48,
233     USB_DT_SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION,
234 };
235 
236 // transfer types (Endpoint types) (USB 2.0 page 270)
237 enum
238 {
239     USB_EP_CONTROL = 0,
240     USB_EP_ISOCHRONOUS,
241     USB_EP_BULK,
242     USB_EP_INTERRUPT
243 };
244 
245 /**
246  * @brief 该宏定义用于声明usb请求包,并初始化其中的各个字段
247  *
248  */
249 #define DECLARE_USB_PACKET(pak_name, _trans_req_type, _trans_request, _trans_value, _trans_index, _transfer_length)    \
250     struct usb_request_packet_t pak_name = {0};                                                                        \
251     pak_name.request_type = (_trans_req_type);                                                                         \
252     pak_name.request = (_trans_request);                                                                               \
253     pak_name.value = (_trans_value);                                                                                   \
254     pak_name.index = (_trans_index);                                                                                   \
255     pak_name.length = (_transfer_length);
256 
257 /*
258     usb class codes
259     refs: https://www.usb.org/defined-class-codes
260 */
261 enum
262 {
263     USB_CLASS_IF = 0x00,
264     USB_CLASS_AUDIO,
265     USB_CLASS_CDC,
266     USB_CLASS_HID,
267     USB_CLASS_PHYSICAL = 0x05,
268     USB_CLASS_IMAGE,
269     USB_CLASS_PRINTER,
270     USB_CLASS_MASS_STORAGE,
271     USB_CLASS_HUB,
272     USB_CLASS_CDC_DATA,
273     USB_CLASS_SMART_CARD,
274     USB_CLASS_CONTENT_SEC = 0x0d,
275     USB_CLASS_VIDEO,
276     USB_CLASS_PERSONAL_HEALTHCARE = 0x0f,
277     USB_CLASS_AV,
278     USB_CLASS_BILLBOARD,
279     USB_CLASS_TYPEC_BRIDGE,
280     USB_CLASS_I3C = 0x3c,
281     USB_CLASS_DIAGNOSTIC = 0xdc,
282     USB_CLASS_WIRELESS_CTRL = 0xe0,
283     USB_CLASS_MISC = 0xef,
284     USB_CLASS_APP_SPEC = 0xfe,
285     USB_CLASS_VENDOR_SPEC = 0XFF,
286 };
287 
288 /**
289  * @brief usb hid descriptor的结构体
290  *
291  */
292 struct usb_hid_desc
293 {
294     uint8_t len;
295     uint8_t type;    // USB_DT_HID
296     uint16_t bcdHID; // 标识HIDClass规范版本的数字表达式。
297 
298     uint8_t country_code;
299     uint8_t descriptors_num;  //  the number of class descriptors
300     uint8_t desc_type;        // Constant name identifying type of class descriptor
301     uint16_t report_desc_len; // Report descriptor的大小
302 };
303 
304 /**
305  * @brief 初始化usb驱动程序
306  *
307  */
308 int usb_init();