| 1 | /* @title: USB */ |
| 2 | #pragma once |
| 3 | #include <compiler.h> |
| 4 | #include <linker/symbols.h> |
| 5 | #include <log.h> |
| 6 | #include <stdatomic.h> |
| 7 | #include <stdbool.h> |
| 8 | #include <stddef.h> |
| 9 | #include <stdint.h> |
| 10 | #include <structures/list.h> |
| 11 | #include <types/refcount.h> |
| 12 | struct usb_controller; |
| 13 | struct usb_device; |
| 14 | struct usb_request; |
| 15 | struct io_wait_token; |
| 16 | |
| 17 | /* Defines generic USB constants, functions, and structures */ |
| 18 | |
| 19 | /* All page numbers are for the USB 2.0 Specification */ |
| 20 | |
| 21 | /* Page 279 - Descriptor types */ |
| 22 | #define USB_DESC_TYPE_DEVICE 1 |
| 23 | #define USB_DESC_TYPE_CONFIG 2 |
| 24 | #define USB_DESC_TYPE_STRING 3 |
| 25 | #define USB_DESC_TYPE_INTERFACE 4 |
| 26 | #define USB_DESC_TYPE_ENDPOINT 5 |
| 27 | #define USB_DESC_TYPE_DEV_QUALIFIER 6 |
| 28 | #define USB_DESC_TYPE_OTHER_SPEED_CONFIG 7 |
| 29 | #define USB_DESC_TYPE_INTERFACE_POWER 8 |
| 30 | |
| 31 | #define USB_DESC_TYPE_SHIFT 8 |
| 32 | |
| 33 | /* Request bitmap field definitions */ |
| 34 | #define USB_REQUEST_TRANS_HTD 0 |
| 35 | #define USB_REQUEST_TRANS_DTH 1 |
| 36 | |
| 37 | #define USB_REQUEST_TYPE_STANDARD 0 |
| 38 | #define USB_REQUEST_TYPE_CLASS 1 |
| 39 | #define USB_REQUEST_TYPE_VENDOR 2 |
| 40 | |
| 41 | #define USB_REQUEST_RECIPIENT_DEVICE 0 |
| 42 | #define USB_REQUEST_RECIPIENT_INTERFACE 1 |
| 43 | #define USB_REQUEST_RECIPIENT_ENDPOINT 2 |
| 44 | #define USB_REQUEST_RECIPIENT_OTHER 3 |
| 45 | |
| 46 | #define USB_REQUEST_TRANSFER_SHIFT 7 |
| 47 | #define USB_REQUEST_TRANSFER_MASK 1 |
| 48 | |
| 49 | #define USB_REQUEST_TYPE_SHIFT 5 |
| 50 | #define USB_REQUEST_TYPE_MASK 3 |
| 51 | |
| 52 | #define USB_REQUEST_RECIPIENT_MASK 0x1F |
| 53 | |
| 54 | #define USB_REQUEST_TRANSFER(byte) ((byte >> 7) & 1) |
| 55 | #define USB_REQUEST_TYPE(byte) ((byte >> 5) & 3) |
| 56 | #define USB_REQUEST_RECIPIENT(byte) (byte & 0x1F) |
| 57 | |
| 58 | /* Config bitmap definitions */ |
| 59 | #define USB_CONFIG_SELF_POWERED (1 << 7) |
| 60 | #define USB_CONFIG_REMOTE_WAKEUP (1 << 6) |
| 61 | |
| 62 | /* Endpoint address bitmap definitions */ |
| 63 | #define USB_ENDPOINT_ADDR_EP_DIRECTION_OUT 0 |
| 64 | #define USB_ENDPOINT_ADDR_EP_DIRECTION_IN 1 |
| 65 | #define USB_ENDPOINT_ADDR_EP_NUM(byte) (byte & 0xF) |
| 66 | #define USB_ENDPOINT_ADDR_EP_DIRECTION(byte) ((byte >> 7) & 1) |
| 67 | |
| 68 | /* Endpoint attribute bitmap definitions */ |
| 69 | #define USB_ENDPOINT_ATTR_TRANS_TYPE_CONTROL 0 |
| 70 | #define USB_ENDPOINT_ATTR_TRANS_TYPE_ISOCHRONOUS 1 |
| 71 | #define USB_ENDPOINT_ATTR_TRANS_TYPE_BULK 2 |
| 72 | #define USB_ENDPOINT_ATTR_TRANS_TYPE_INTERRUPT 3 |
| 73 | |
| 74 | #define USB_ENDPOINT_ATTR_SYNC_TYPE_NO_SYNC 0 |
| 75 | #define USB_ENDPOINT_ATTR_SYNC_TYPE_ASYNC 1 |
| 76 | #define USB_ENDPOINT_ATTR_SYNC_TYPE_ADAPTIVE 2 |
| 77 | #define USB_ENDPOINT_ATTR_SYNC_TYPE_SYNC 3 |
| 78 | |
| 79 | #define USB_ENDPOINT_ATTR_USAGE_TYPE_DATA 0 |
| 80 | #define USB_ENDPOINT_ATTR_USAGE_TYPE_FEEDBACK 1 |
| 81 | #define USB_ENDPOINT_ATTR_USAGE_TYPE_IMPLICIT_FEEDBACK_DATA 2 |
| 82 | |
| 83 | #define USB_ENDPOINT_ATTR_TRANS_TYPE(byte) (byte & 3) |
| 84 | #define USB_ENDPOINT_ATTR_SYNC_TYPE(byte) ((byte >> 2) & 3) |
| 85 | #define USB_ENDPOINT_ATTR_USAGE_TYPE(byte) ((byte >> 4) & 3) |
| 86 | |
| 87 | /* Endpoint max packet size bitmap definitions */ |
| 88 | #define USB_ENDPOINT_MAX_PACKET_SIZE_SIZE(byte) (byte & 0x3FF) |
| 89 | #define USB_ENDPOINT_MAX_PACKET_SIZE_TRANSACT_OPP(byte) ((byte >> 11) & 3) |
| 90 | |
| 91 | #define USB_ENDPOINT_MAX_PACKET_SIZE_TRANSACT_OPP_NUM(num) (num + 1) |
| 92 | |
| 93 | /* Endpoint interval conversion definitions */ |
| 94 | #define USB_ENDPOINT_INTERVAL_TO_INTEGER_LOW_SPEED(num) (num) |
| 95 | #define USB_ENDPOINT_INTEGER_TO_INTERVAL_LOW_SPEED(num) (num) |
| 96 | |
| 97 | #define USB_ENDPOINT_INTERVAL_TO_INTEGER_HIGH_SPEED(num) (2 << (num - 2)) |
| 98 | |
| 99 | /* Subclass codes are not defined in a centralized place. Add them as needed */ |
| 100 | #define USB_CLASS_AUDIO 0x1 |
| 101 | /* Audio subclasses go here */ |
| 102 | |
| 103 | #define USB_CLASS_COMMS 0x2 |
| 104 | /* Comms subclasses go here */ |
| 105 | |
| 106 | #define USB_CLASS_HID 0x3 |
| 107 | |
| 108 | #define USB_SUBCLASS_HID_NONE 0x0 |
| 109 | #define USB_SUBCLASS_HID_BOOT_INTERFACE 0x1 |
| 110 | /* 2 - 225 reserved for HID */ |
| 111 | |
| 112 | #define USB_PROTOCOL_HID_NONE 0x0 |
| 113 | #define USB_PROTOCOL_HID_KEYBOARD 0x1 |
| 114 | #define USB_PROTOCOL_HID_MOUSE 0x2 |
| 115 | /* 3 - 225 reserved */ |
| 116 | |
| 117 | #define USB_CLASS_PHYSICAL 0x5 |
| 118 | #define USB_CLASS_IMAGE 0x6 |
| 119 | #define USB_CLASS_PRINTER 0x7 |
| 120 | #define USB_CLASS_MASS_STORAGE 0x8 |
| 121 | #define USB_CLASS_HUB 0x9 |
| 122 | #define USB_CLASS_DATA 0xA |
| 123 | #define USB_CLASS_SMART_CARD 0xB |
| 124 | #define USB_CLASS_CONTENT_SECURITY 0xD |
| 125 | #define USB_CLASS_VIDEO 0xE |
| 126 | #define USB_CLASS_PERSONAL_HEALTHCARE 0xF |
| 127 | #define USB_CLASS_AUDIO_VIDEO 0x10 |
| 128 | #define USB_CLASS_BILLBOARD 0x11 |
| 129 | #define USB_CLASS_USB_TYPE_C 0x12 |
| 130 | #define USB_CLASS_BULK_DISPLAY 0x13 |
| 131 | #define USB_CLASS_MCTP_OVER_USB 0x14 |
| 132 | #define USB_CLASS_I3C_DEVICE 0x3C |
| 133 | #define USB_CLASS_DIAGNOSTIC_DEVICE 0xDC |
| 134 | #define USB_CLASS_WIRELESS 0xE0 |
| 135 | #define USB_CLASS_MISC 0xEF |
| 136 | #define USB_CLASS_APPLICATION_SPECIFIC 0xFE |
| 137 | #define USB_CLASS_VENDOR_SPECIFIC 0xFF |
| 138 | |
| 139 | LOG_SITE_EXTERN(usb); |
| 140 | LOG_HANDLE_EXTERN(usb); |
| 141 | |
| 142 | #define usb_log(lvl, fmt, ...) \ |
| 143 | log(LOG_SITE(usb), LOG_HANDLE(usb), lvl, fmt, ##__VA_ARGS__) |
| 144 | |
| 145 | #define usb_err(fmt, ...) usb_log(LOG_ERROR, fmt, ##__VA_ARGS__) |
| 146 | #define usb_warn(fmt, ...) usb_log(LOG_WARN, fmt, ##__VA_ARGS__) |
| 147 | #define usb_info(fmt, ...) usb_log(LOG_INFO, fmt, ##__VA_ARGS__) |
| 148 | #define usb_debug(fmt, ...) usb_log(LOG_DEBUG, fmt, ##__VA_ARGS__) |
| 149 | #define usb_trace(fmt, ...) usb_log(LOG_TRACE, fmt, ##__VA_ARGS__) |
| 150 | |
| 151 | /* Request codes */ |
| 152 | enum usb_rq_code : uint8_t { |
| 153 | USB_RQ_CODE_GET_STATUS = 0, /* Page 282 */ |
| 154 | USB_RQ_CODE_CLEAR_FEATURE = 1, /* Page 280 */ |
| 155 | USB_RQ_CODE_SET_FEATURE = 3, /* Page 286 */ |
| 156 | USB_RQ_CODE_SET_ADDR = 5, /* Page 284 */ |
| 157 | |
| 158 | USB_RQ_CODE_GET_DESCRIPTOR = 6, /* Page 281 */ |
| 159 | USB_RQ_CODE_SET_DESCRIPTOR = 7, /* Page 285 */ |
| 160 | |
| 161 | USB_RQ_CODE_GET_CONFIG = 8, /* Page 281 */ |
| 162 | USB_RQ_CODE_SET_CONFIG = 9, /* Page 285 */ |
| 163 | |
| 164 | USB_RQ_CODE_GET_INTERFACE = 10, /* Page 282 */ |
| 165 | USB_RQ_CODE_SET_INTERFACE = 11, /* Page 287 */ |
| 166 | |
| 167 | USB_RQ_CODE_SYNCH_FRAME = 12, /* Page 288 */ |
| 168 | }; |
| 169 | |
| 170 | enum usb_controller_type { |
| 171 | USB_CONTROLLER_UHCI, |
| 172 | USB_CONTROLLER_EHCI, |
| 173 | USB_CONTROLLER_XHCI, |
| 174 | }; |
| 175 | |
| 176 | enum usb_transfer_type { |
| 177 | USB_TRANSFER_CONTROL, |
| 178 | USB_TRANSFER_BULK, |
| 179 | USB_TRANSFER_INTERRUPT, |
| 180 | }; |
| 181 | |
| 182 | enum usb_error { |
| 183 | USB_OK = 0, |
| 184 | USB_ERR_STALL, |
| 185 | USB_ERR_TIMEOUT, |
| 186 | USB_ERR_DISCONNECT, |
| 187 | USB_ERR_OVERFLOW, |
| 188 | USB_ERR_CRC, |
| 189 | USB_ERR_IO, |
| 190 | USB_ERR_PROTO, |
| 191 | USB_ERR_NO_DEVICE, |
| 192 | USB_ERR_CANCELLED, |
| 193 | USB_ERR_OOM, |
| 194 | USB_ERR_INVALID_ARGUMENT, |
| 195 | USB_ERR_NO_ENDPOINT, |
| 196 | }; |
| 197 | |
| 198 | enum usb_dev_status { |
| 199 | USB_DEV_UNDEF, |
| 200 | USB_DEV_DISCONNECTED, |
| 201 | USB_DEV_CONNECTED, |
| 202 | USB_DEV_ENABLED, |
| 203 | USB_DEV_RESETTING, |
| 204 | USB_DEV_ERROR, |
| 205 | }; |
| 206 | |
| 207 | struct usb_setup_packet { /* Refer to page 276 */ |
| 208 | uint8_t bitmap_request_type; /* Characteristics */ |
| 209 | enum usb_rq_code request; /* Specific request */ |
| 210 | uint16_t value; /* Varies according to request */ |
| 211 | |
| 212 | union { |
| 213 | uint16_t index; |
| 214 | uint16_t offset; |
| 215 | }; |
| 216 | |
| 217 | uint16_t length; /* Number of bytes if there is a data stage */ |
| 218 | |
| 219 | } __packed; |
| 220 | static_assert_struct_size_eq(usb_setup_packet, 8); |
| 221 | |
| 222 | struct usb_device_descriptor { /* Refer to page 290 */ |
| 223 | uint8_t length; |
| 224 | uint8_t type; |
| 225 | uint16_t usb_num_bcd; /* USB number in binary coded |
| 226 | * decimal. 2.10 is 210H */ |
| 227 | |
| 228 | uint8_t class; /* Class code */ |
| 229 | uint8_t subclass; /* Subclass code */ |
| 230 | uint8_t protocol; |
| 231 | uint8_t max_packet_size; /* Only 8, 16, 32, or 64 are valid */ |
| 232 | |
| 233 | uint16_t vendor_id; |
| 234 | uint16_t product_id; |
| 235 | uint16_t device_num_bcd; /* Device number in binary coded decimal */ |
| 236 | |
| 237 | uint8_t manufacturer; /* Index of string desc. describing manufacturer */ |
| 238 | uint8_t product; /* Index of string desc. describing product */ |
| 239 | uint8_t serial_num; /* Index of string desc. describing serial number */ |
| 240 | |
| 241 | uint8_t num_configs; /* Number of possible configurations */ |
| 242 | } __packed; |
| 243 | static_assert_struct_size_eq(usb_device_descriptor, 18); |
| 244 | |
| 245 | struct usb_interface_descriptor { /* Page 296 */ |
| 246 | uint8_t length; |
| 247 | uint8_t type; |
| 248 | uint8_t interface_number; /* zero-based value ident. the index |
| 249 | * in the array of concurrent interfaces */ |
| 250 | |
| 251 | uint8_t alternate_setting; /* Select this alternate |
| 252 | * setting for the interface */ |
| 253 | |
| 254 | uint8_t num_endpoints; /* Number of endpoings excluding EP0 */ |
| 255 | uint8_t class; /* Interface class code */ |
| 256 | uint8_t subclass; /* Interface subclass code */ |
| 257 | |
| 258 | uint8_t protocol; /* Interface protocol code qualified by `class` and |
| 259 | `subclass` */ |
| 260 | |
| 261 | uint8_t interface; /* Index of string desc. describing this interface */ |
| 262 | |
| 263 | } __packed; |
| 264 | static_assert_struct_size_eq(usb_interface_descriptor, 9); |
| 265 | |
| 266 | struct usb_config_descriptor { /* Page 293 */ |
| 267 | uint8_t length; |
| 268 | uint8_t descriptor_type; |
| 269 | uint16_t total_length; /* Total length of data for this config */ |
| 270 | uint8_t num_interfaces; |
| 271 | uint8_t configuration_value; /* Value to use as argument |
| 272 | * to SetConfig() request */ |
| 273 | |
| 274 | uint8_t configuration; /* Index of string desc. describing this config */ |
| 275 | uint8_t bitmap_attributes; /* Bits 7 and 0..4 are reserved */ |
| 276 | |
| 277 | uint8_t max_power; /* Max power of USB device in milliamps */ |
| 278 | } __packed; |
| 279 | static_assert_struct_size_eq(usb_config_descriptor, 9); |
| 280 | |
| 281 | struct usb_endpoint_descriptor { /* Page 297 */ |
| 282 | uint8_t length; |
| 283 | uint8_t type; |
| 284 | uint8_t address; /* 3..0 is EP number, 7 is direction */ |
| 285 | uint8_t attributes; /* Refer to definitions */ |
| 286 | |
| 287 | uint16_t max_packet_size; /* Max packet size as a bitmap */ |
| 288 | |
| 289 | uint8_t interval; /* Interval for polling this EP for data transfer */ |
| 290 | } __packed; |
| 291 | static_assert_struct_size_eq(usb_endpoint_descriptor, 7); |
| 292 | |
| 293 | struct usb_endpoint { |
| 294 | struct usb_endpoint_descriptor *desc; |
| 295 | |
| 296 | /* Putting these here so code won't look like |
| 297 | * ep->desc.type, I think that looks bad */ |
| 298 | uint8_t type; |
| 299 | uint8_t number; |
| 300 | bool in; /* true - in, false - out */ |
| 301 | uint8_t *transfer_buffer; |
| 302 | uint16_t transfer_len; |
| 303 | uint16_t max_packet_size; |
| 304 | uint8_t address; |
| 305 | uint8_t attributes; |
| 306 | uint8_t interval; |
| 307 | |
| 308 | void *hc_data; |
| 309 | }; |
| 310 | |
| 311 | struct usb_controller_ops { |
| 312 | enum usb_error (*submit_control_transfer)(struct usb_request *); |
| 313 | enum usb_error (*submit_bulk_transfer)(struct usb_request *); |
| 314 | enum usb_error (*submit_interrupt_transfer)(struct usb_request *); |
| 315 | void (*reset_slot)(struct usb_device *dev); |
| 316 | enum usb_error (*configure_endpoint)(struct usb_device *dev); |
| 317 | void (*poll_ports)(struct usb_controller *); |
| 318 | }; |
| 319 | |
| 320 | struct usb_controller { /* Generic USB controller */ |
| 321 | enum usb_controller_type type; |
| 322 | struct usb_controller_ops *ops; |
| 323 | void *driver_data; |
| 324 | }; |
| 325 | |
| 326 | struct usb_driver { |
| 327 | const char *name; |
| 328 | uint8_t class_code; |
| 329 | uint8_t subclass; |
| 330 | uint8_t protocol; |
| 331 | |
| 332 | enum usb_error (*bringup)(struct usb_device *dev); /* Called on connect */ |
| 333 | void (*teardown)(struct usb_device *dev); /* Called on disconnect */ |
| 334 | void (*free)(struct usb_device *dev); /* Called on last ref drop */ |
| 335 | }; |
| 336 | |
| 337 | struct usb_device { |
| 338 | struct list_head hc_list; |
| 339 | _Atomic enum usb_dev_status status; |
| 340 | char manufacturer[128]; |
| 341 | char product[128]; |
| 342 | char config_str[128]; |
| 343 | uint8_t address; |
| 344 | uint8_t speed; |
| 345 | uint8_t port; /* Port number on the root hub */ |
| 346 | void *slot; |
| 347 | uint8_t max_packet_size; |
| 348 | |
| 349 | struct usb_device_descriptor *descriptor; |
| 350 | struct usb_config_descriptor config; |
| 351 | |
| 352 | struct usb_endpoint **endpoints; /* List of endpoints */ |
| 353 | uint8_t num_endpoints; |
| 354 | |
| 355 | struct usb_controller *host; |
| 356 | |
| 357 | struct usb_interface_descriptor **interfaces; /* List of interfaces */ |
| 358 | uint8_t num_interfaces; |
| 359 | |
| 360 | struct usb_driver *driver; /* Attached driver */ |
| 361 | |
| 362 | void *driver_private; |
| 363 | |
| 364 | bool configured; |
| 365 | refcount_t refcount; |
| 366 | atomic_bool alive; |
| 367 | |
| 368 | void (*teardown)(struct usb_device *dev); /* called during disconnect */ |
| 369 | void (*free)(struct usb_device *dev); /* called during last rc drop */ |
| 370 | }; |
| 371 | |
| 372 | struct usb_request { |
| 373 | struct usb_device *dev; |
| 374 | struct usb_endpoint *ep; |
| 375 | enum usb_transfer_type type; |
| 376 | struct usb_setup_packet *setup; |
| 377 | |
| 378 | void *buffer; |
| 379 | size_t length; |
| 380 | |
| 381 | volatile enum usb_error status; |
| 382 | |
| 383 | uint32_t flags; |
| 384 | uint64_t timeout_ns; |
| 385 | |
| 386 | void (*complete)(struct usb_request *); |
| 387 | void *context; |
| 388 | bool direction_in; |
| 389 | |
| 390 | /* Controller-private data */ |
| 391 | void *hc_priv; |
| 392 | }; |
| 393 | #define USB_REQ_INIT(_req, _dev) \ |
| 394 | do { \ |
| 395 | memset((_req), 0, sizeof(*(_req))); \ |
| 396 | (_req)->dev = (_dev); \ |
| 397 | } while (0) |
| 398 | |
| 399 | REFCOUNT_GENERATE_GET_FOR_STRUCT_WITH_FAILURE_COND(usb_device, refcount, status, |
| 400 | == USB_DEV_DISCONNECTED); |
| 401 | |
| 402 | void usb_free_device(struct usb_device *dev); |
| 403 | static inline void usb_device_put(struct usb_device *dev) { |
| 404 | if (refcount_dec_and_test(rc: &dev->refcount)) |
| 405 | usb_free_device(dev); |
| 406 | } |
| 407 | |
| 408 | void usb_teardown_device(struct usb_device *dev); |
| 409 | enum usb_error usb_get_string_descriptor(struct usb_device *dev, |
| 410 | uint8_t string_idx, char *out, |
| 411 | size_t max_len); |
| 412 | enum usb_error usb_get_device_descriptor(struct usb_device *dev); |
| 413 | enum usb_error usb_parse_config_descriptor(struct usb_device *dev); |
| 414 | enum usb_error usb_set_configuration(struct usb_device *dev); |
| 415 | enum usb_error usb_init_device(struct usb_device *dev); |
| 416 | void usb_try_bind_driver(struct usb_device *dev); |
| 417 | uint8_t usb_construct_rq_bitmap(uint8_t transfer, uint8_t type, uint8_t recip); |
| 418 | enum usb_error usb_transfer_sync(enum usb_error (*fn)(struct usb_request *), |
| 419 | struct usb_request *request, |
| 420 | struct io_wait_token *tok); |
| 421 | void usb_print_device(struct usb_device *dev); |
| 422 | struct usb_interface_descriptor *usb_find_interface(struct usb_device *dev, |
| 423 | uint8_t class, |
| 424 | uint8_t subclass, |
| 425 | uint8_t protocol); |
| 426 | |
| 427 | static inline uint8_t get_ep_index(struct usb_endpoint *ep) { |
| 428 | return (ep->number * 2) + (ep->in ? 1 : 0); |
| 429 | } |
| 430 | |
| 431 | static inline const char *usb_rq_code_str(const enum usb_rq_code code) { |
| 432 | switch (code) { |
| 433 | case USB_RQ_CODE_GET_STATUS: return "GET_STATUS" ; |
| 434 | case USB_RQ_CODE_CLEAR_FEATURE: return "CLEAR_FEATURE" ; |
| 435 | case USB_RQ_CODE_SET_FEATURE: return "SET_FEATURE" ; |
| 436 | case USB_RQ_CODE_SET_ADDR: return "SET_ADDR" ; |
| 437 | case USB_RQ_CODE_GET_DESCRIPTOR: return "GET_DESCRIPTOR" ; |
| 438 | case USB_RQ_CODE_SET_DESCRIPTOR: return "SET_DESCRIPTOR" ; |
| 439 | case USB_RQ_CODE_GET_CONFIG: return "GET_CONFIG" ; |
| 440 | case USB_RQ_CODE_SET_CONFIG: return "SET_CONFIG" ; |
| 441 | case USB_RQ_CODE_GET_INTERFACE: return "GET_INTERFACE" ; |
| 442 | case USB_RQ_CODE_SET_INTERFACE: return "SET_INTERFACE" ; |
| 443 | case USB_RQ_CODE_SYNCH_FRAME: return "SYNCH_FRAME" ; |
| 444 | default: return "UNKNOWN_CODE" ; |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | static inline const char * |
| 449 | usb_transfer_type_str(const enum usb_transfer_type type) { |
| 450 | switch (type) { |
| 451 | case USB_TRANSFER_CONTROL: return "USB TRANSFER CONTROL" ; |
| 452 | case USB_TRANSFER_BULK: return "USB TRANSFER BULK" ; |
| 453 | case USB_TRANSFER_INTERRUPT: return "USB TRANSFER INTERRUPT" ; |
| 454 | default: return "UNKNOWN" ; |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | static inline const char *usb_error_str(const enum usb_error err) { |
| 459 | switch (err) { |
| 460 | case USB_OK: return "USB OK" ; |
| 461 | case USB_ERR_STALL: return "USB ERR STALL" ; |
| 462 | case USB_ERR_TIMEOUT: return "USB ERR TIMEOUT" ; |
| 463 | case USB_ERR_DISCONNECT: return "USB ERR DISCONNECT" ; |
| 464 | case USB_ERR_OVERFLOW: return "USB ERR OVERFLOW" ; |
| 465 | case USB_ERR_CRC: return "USB ERR CRC" ; |
| 466 | case USB_ERR_IO: return "USB ERR IO" ; |
| 467 | case USB_ERR_PROTO: return "USB ERR PROTO" ; |
| 468 | case USB_ERR_NO_DEVICE: return "USB ERR NO DEVICE" ; |
| 469 | case USB_ERR_CANCELLED: return "USB ERR CANCELLED" ; |
| 470 | case USB_ERR_OOM: return "USB ERR OOM" ; |
| 471 | case USB_ERR_INVALID_ARGUMENT: return "USB ERR INVALID ARGUMENT" ; |
| 472 | case USB_ERR_NO_ENDPOINT: return "USB ERR NO ENDPOINT" ; |
| 473 | default: return "UNKNOWN ERROR" ; |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | LINKER_SECTION_DEFINE(struct usb_driver, usb_drivers); |
| 478 | #define USB_DRIVER_REGISTER(n, cc, sc, proto, bringup_fn, teardown_fn, \ |
| 479 | free_fn) \ |
| 480 | LINKER_SECTION_OBJECT(struct usb_driver, usb_drivers) \ |
| 481 | usb_driver_##n = {.name = #n, \ |
| 482 | .class_code = cc, \ |
| 483 | .subclass = sc, \ |
| 484 | .protocol = proto, \ |
| 485 | .bringup = bringup_fn, \ |
| 486 | .teardown = teardown_fn, \ |
| 487 | .free = free_fn}; |
| 488 | |