#ifndef _IPXE_USB_H #define _IPXE_USB_H /** @file * * Universal Serial Bus (USB) * */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include #include #include #include /** USB protocols */ enum usb_protocol { /** USB 2.0 */ USB_PROTO_2_0 = 0x0200, /** USB 3.0 */ USB_PROTO_3_0 = 0x0300, /** USB 3.1 */ USB_PROTO_3_1 = 0x0301, }; /** Define a USB speed * * @v mantissa Mantissa * @v exponent Exponent (in engineering terms: 1=k, 2=M, 3=G) * @ret speed USB speed */ #define USB_SPEED( mantissa, exponent ) ( (exponent << 16) | (mantissa) ) /** Extract USB speed mantissa */ #define USB_SPEED_MANTISSA(speed) ( (speed) & 0xffff ) /** Extract USB speed exponent */ #define USB_SPEED_EXPONENT(speed) ( ( (speed) >> 16 ) & 0x3 ) /** USB device speeds */ enum usb_speed { /** Not connected */ USB_SPEED_NONE = 0, /** Low speed (1.5Mbps) */ USB_SPEED_LOW = USB_SPEED ( 1500, 1 ), /** Full speed (12Mbps) */ USB_SPEED_FULL = USB_SPEED ( 12, 2 ), /** High speed (480Mbps) */ USB_SPEED_HIGH = USB_SPEED ( 480, 2 ), /** Super speed (5Gbps) */ USB_SPEED_SUPER = USB_SPEED ( 5, 3 ), }; /** USB packet IDs */ enum usb_pid { /** IN PID */ USB_PID_IN = 0x69, /** OUT PID */ USB_PID_OUT = 0xe1, /** SETUP PID */ USB_PID_SETUP = 0x2d, }; /** A USB setup data packet */ struct usb_setup_packet { /** Request */ uint16_t request; /** Value paramer */ uint16_t value; /** Index parameter */ uint16_t index; /** Length of data stage */ uint16_t len; } __attribute__ (( packed )); /** Data transfer is from host to device */ #define USB_DIR_OUT ( 0 << 7 ) /** Data transfer is from device to host */ #define USB_DIR_IN ( 1 << 7 ) /** Standard request type */ #define USB_TYPE_STANDARD ( 0 << 5 ) /** Class-specific request type */ #define USB_TYPE_CLASS ( 1 << 5 ) /** Vendor-specific request type */ #define USB_TYPE_VENDOR ( 2 << 5 ) /** Request recipient is the device */ #define USB_RECIP_DEVICE ( 0 << 0 ) /** Request recipient is an interface */ #define USB_RECIP_INTERFACE ( 1 << 0 ) /** Request recipient is an endpoint */ #define USB_RECIP_ENDPOINT ( 2 << 0 ) /** Construct USB request type */ #define USB_REQUEST_TYPE(type) ( (type) << 8 ) /** Get status */ #define USB_GET_STATUS ( USB_DIR_IN | USB_REQUEST_TYPE ( 0 ) ) /** Clear feature */ #define USB_CLEAR_FEATURE ( USB_DIR_OUT | USB_REQUEST_TYPE ( 1 ) ) /** Set feature */ #define USB_SET_FEATURE ( USB_DIR_OUT | USB_REQUEST_TYPE ( 3 ) ) /** Set address */ #define USB_SET_ADDRESS ( USB_DIR_OUT | USB_REQUEST_TYPE ( 5 ) ) /** Get descriptor */ #define USB_GET_DESCRIPTOR ( USB_DIR_IN | USB_REQUEST_TYPE ( 6 ) ) /** Set descriptor */ #define USB_SET_DESCRIPTOR ( USB_DIR_OUT | USB_REQUEST_TYPE ( 7 ) ) /** Get configuration */ #define USB_GET_CONFIGURATION ( USB_DIR_IN | USB_REQUEST_TYPE ( 8 ) ) /** Set configuration */ #define USB_SET_CONFIGURATION ( USB_DIR_OUT | USB_REQUEST_TYPE ( 9 ) ) /** Get interface */ #define USB_GET_INTERFACE \ ( USB_DIR_IN | USB_RECIP_INTERFACE | USB_REQUEST_TYPE ( 10 ) ) /** Set interface */ #define USB_SET_INTERFACE \ ( USB_DIR_OUT | USB_RECIP_INTERFACE | USB_REQUEST_TYPE ( 11 ) ) /** Endpoint halt feature */ #define USB_ENDPOINT_HALT 0 /** A USB class code tuple */ struct usb_class { /** Class code */ uint8_t class; /** Subclass code */ uint8_t subclass; /** Protocol code */ uint8_t protocol; } __attribute__ (( packed )); /** Class code for USB hubs */ #define USB_CLASS_HUB 9 /** A USB descriptor header */ struct usb_descriptor_header { /** Length of descriptor */ uint8_t len; /** Descriptor type */ uint8_t type; } __attribute__ (( packed )); /** A USB device descriptor */ struct usb_device_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** USB specification release number in BCD */ uint16_t protocol; /** Device class */ struct usb_class class; /** Maximum packet size for endpoint zero */ uint8_t mtu; /** Vendor ID */ uint16_t vendor; /** Product ID */ uint16_t product; /** Device release number in BCD */ uint16_t release; /** Manufacturer string */ uint8_t manufacturer; /** Product string */ uint8_t name; /** Serial number string */ uint8_t serial; /** Number of possible configurations */ uint8_t configurations; } __attribute__ (( packed )); /** A USB device descriptor */ #define USB_DEVICE_DESCRIPTOR 1 /** A USB configuration descriptor */ struct usb_configuration_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** Total length */ uint16_t len; /** Number of interfaces */ uint8_t interfaces; /** Configuration value */ uint8_t config; /** Configuration string */ uint8_t name; /** Attributes */ uint8_t attributes; /** Maximum power consumption */ uint8_t power; } __attribute__ (( packed )); /** A USB configuration descriptor */ #define USB_CONFIGURATION_DESCRIPTOR 2 /** A USB string descriptor */ struct usb_string_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** String */ char string[0]; } __attribute__ (( packed )); /** A USB string descriptor */ #define USB_STRING_DESCRIPTOR 3 /** A USB interface descriptor */ struct usb_interface_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** Interface number */ uint8_t interface; /** Alternate setting */ uint8_t alternate; /** Number of endpoints */ uint8_t endpoints; /** Interface class */ struct usb_class class; /** Interface name */ uint8_t name; } __attribute__ (( packed )); /** A USB interface descriptor */ #define USB_INTERFACE_DESCRIPTOR 4 /** A USB endpoint descriptor */ struct usb_endpoint_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** Endpoint address */ uint8_t endpoint; /** Attributes */ uint8_t attributes; /** Maximum packet size and burst size */ uint16_t sizes; /** Polling interval */ uint8_t interval; } __attribute__ (( packed )); /** A USB endpoint descriptor */ #define USB_ENDPOINT_DESCRIPTOR 5 /** Endpoint attribute transfer type mask */ #define USB_ENDPOINT_ATTR_TYPE_MASK 0x03 /** Endpoint periodic type */ #define USB_ENDPOINT_ATTR_PERIODIC 0x01 /** Control endpoint transfer type */ #define USB_ENDPOINT_ATTR_CONTROL 0x00 /** Bulk endpoint transfer type */ #define USB_ENDPOINT_ATTR_BULK 0x02 /** Interrupt endpoint transfer type */ #define USB_ENDPOINT_ATTR_INTERRUPT 0x03 /** Bulk OUT endpoint (internal) type */ #define USB_BULK_OUT ( USB_ENDPOINT_ATTR_BULK | USB_DIR_OUT ) /** Bulk IN endpoint (internal) type */ #define USB_BULK_IN ( USB_ENDPOINT_ATTR_BULK | USB_DIR_IN ) /** Interrupt IN endpoint (internal) type */ #define USB_INTERRUPT_IN ( USB_ENDPOINT_ATTR_INTERRUPT | USB_DIR_IN ) /** Interrupt OUT endpoint (internal) type */ #define USB_INTERRUPT_OUT ( USB_ENDPOINT_ATTR_INTERRUPT | USB_DIR_OUT ) /** USB endpoint MTU */ #define USB_ENDPOINT_MTU(sizes) ( ( (sizes) >> 0 ) & 0x07ff ) /** USB endpoint maximum burst size */ #define USB_ENDPOINT_BURST(sizes) ( ( (sizes) >> 11 ) & 0x0003 ) /** A USB endpoint companion descriptor */ struct usb_endpoint_companion_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** Maximum burst size */ uint8_t burst; /** Extended attributes */ uint8_t extended; /** Number of bytes per service interval */ uint16_t periodic; } __attribute__ (( packed )); /** A USB endpoint companion descriptor */ #define USB_ENDPOINT_COMPANION_DESCRIPTOR 48 /** A USB interface association descriptor */ struct usb_interface_association_descriptor { /** Descriptor header */ struct usb_descriptor_header header; /** First interface number */ uint8_t first; /** Interface count */ uint8_t count; /** Association class */ struct usb_class class; /** Association name */ uint8_t name; } __attribute__ (( packed )); /** A USB interface association descriptor */ #define USB_INTERFACE_ASSOCIATION_DESCRIPTOR 11 /** A class-specific interface descriptor */ #define USB_CS_INTERFACE_DESCRIPTOR 36 /** A class-specific endpoint descriptor */ #define USB_CS_ENDPOINT_DESCRIPTOR 37 /** * Get next USB descriptor * * @v desc USB descriptor header * @ret next Next USB descriptor header */ static inline __attribute__ (( always_inline )) struct usb_descriptor_header * usb_next_descriptor ( struct usb_descriptor_header *desc ) { return ( ( ( void * ) desc ) + desc->len ); } /** * Check that descriptor lies within a configuration descriptor * * @v config Configuration descriptor * @v desc Descriptor header * @v is_within Descriptor is within the configuration descriptor */ static inline __attribute__ (( always_inline )) int usb_is_within_config ( struct usb_configuration_descriptor *config, struct usb_descriptor_header *desc ) { struct usb_descriptor_header *end = ( ( ( void * ) config ) + le16_to_cpu ( config->len ) ); /* Check that descriptor starts within the configuration * descriptor, and that the length does not exceed the * configuration descriptor. This relies on the fact that * usb_next_descriptor() needs to access only the first byte * of the descriptor in order to determine the length. */ return ( ( desc < end ) && ( usb_next_descriptor ( desc ) <= end ) ); } /** Iterate over all configuration descriptors */ #define for_each_config_descriptor( desc, config ) \ for ( desc = container_of ( &(config)->header, \ typeof ( *desc ), header ) ; \ usb_is_within_config ( (config), &desc->header ) ; \ desc = container_of ( usb_next_descriptor ( &desc->header ), \ typeof ( *desc ), header ) ) /** Iterate over all configuration descriptors within an interface descriptor */ #define for_each_interface_descriptor( desc, config, interface ) \ for ( desc = container_of ( usb_next_descriptor ( &(interface)-> \ header ), \ typeof ( *desc ), header ) ; \ ( usb_is_within_config ( (config), &desc->header ) && \ ( desc->header.type != USB_INTERFACE_DESCRIPTOR ) ) ; \ desc = container_of ( usb_next_descriptor ( &desc->header ), \ typeof ( *desc ), header ) ) /** A USB endpoint */ struct usb_endpoint { /** USB device */ struct usb_device *usb; /** Endpoint address */ unsigned int address; /** Attributes */ unsigned int attributes; /** Maximum transfer size */ size_t mtu; /** Maximum burst size */ unsigned int burst; /** Interval (in microframes) */ unsigned int interval; /** Endpoint is open */ int open; /** Buffer fill level */ unsigned int fill; /** List of halted endpoints */ struct list_head halted; /** Host controller operations */ struct usb_endpoint_host_operations *host; /** Host controller private data */ void *priv; /** Driver operations */ struct usb_endpoint_driver_operations *driver; /** Recycled I/O buffer list */ struct list_head recycled; /** Refill buffer length */ size_t len; /** Maximum fill level */ unsigned int max; }; /** USB endpoint host controller operations */ struct usb_endpoint_host_operations { /** Open endpoint * * @v ep USB endpoint * @ret rc Return status code */ int ( * open ) ( struct usb_endpoint *ep ); /** Close endpoint * * @v ep USB endpoint */ void ( * close ) ( struct usb_endpoint *ep ); /** * Reset endpoint * * @v ep USB endpoint * @ret rc Return status code */ int ( * reset ) ( struct usb_endpoint *ep ); /** Update MTU * * @v ep USB endpoint * @ret rc Return status code */ int ( * mtu ) ( struct usb_endpoint *ep ); /** Enqueue message transfer * * @v ep USB endpoint * @v iobuf I/O buffer * @ret rc Return status code */ int ( * message ) ( struct usb_endpoint *ep, struct io_buffer *iobuf ); /** Enqueue stream transfer * * @v ep USB endpoint * @v iobuf I/O buffer * @v terminate Terminate using a short packet * @ret rc Return status code */ int ( * stream ) ( struct usb_endpoint *ep, struct io_buffer *iobuf, int terminate ); }; /** USB endpoint driver operations */ struct usb_endpoint_driver_operations { /** Complete transfer * * @v ep USB endpoint * @v iobuf I/O buffer * @v rc Completion status code */ void ( * complete ) ( struct usb_endpoint *ep, struct io_buffer *iobuf, int rc ); }; /** Control endpoint address */ #define USB_EP0_ADDRESS 0x00 /** Control endpoint attributes */ #define USB_EP0_ATTRIBUTES 0x00 /** Calculate default MTU based on device speed * * @v speed Device speed * @ret mtu Default MTU */ #define USB_EP0_DEFAULT_MTU(speed) \ ( ( (speed) >= USB_SPEED_SUPER ) ? 512 : \ ( ( (speed) >= USB_SPEED_FULL ) ? 64 : 8 ) ) /** Control endpoint maximum burst size */ #define USB_EP0_BURST 0 /** Control endpoint interval */ #define USB_EP0_INTERVAL 0 /** Maximum endpoint number */ #define USB_ENDPOINT_MAX 0x0f /** Endpoint direction is in */ #define USB_ENDPOINT_IN 0x80 /** Construct endpoint index from endpoint address */ #define USB_ENDPOINT_IDX(address) \ ( ( (address) & USB_ENDPOINT_MAX ) | \ ( ( (address) & USB_ENDPOINT_IN ) >> 3 ) ) /** * Initialise USB endpoint * * @v ep USB endpoint * @v usb USB device * @v driver Driver operations */ static inline __attribute__ (( always_inline )) void usb_endpoint_init ( struct usb_endpoint *ep, struct usb_device *usb, struct usb_endpoint_driver_operations *driver ) { ep->usb = usb; ep->driver = driver; } /** * Describe USB endpoint * * @v ep USB endpoint * @v address Endpoint address * @v attributes Attributes * @v mtu Maximum packet size * @v burst Maximum burst size * @v interval Interval (in microframes) */ static inline __attribute__ (( always_inline )) void usb_endpoint_describe ( struct usb_endpoint *ep, unsigned int address, unsigned int attributes, size_t mtu, unsigned int burst, unsigned int interval ) { ep->address = address; ep->attributes = attributes; ep->mtu = mtu; ep->burst = burst; ep->interval = interval; } /** * Set USB endpoint host controller private data * * @v ep USB endpoint * @v priv Host controller private data */ static inline __attribute__ (( always_inline )) void usb_endpoint_set_hostdata ( struct usb_endpoint *ep, void *priv ) { ep->priv = priv; } /** * Get USB endpoint host controller private data * * @v ep USB endpoint * @ret priv Host controller private data */ static inline __attribute__ (( always_inline )) void * usb_endpoint_get_hostdata ( struct usb_endpoint *ep ) { return ep->priv; } extern const char * usb_endpoint_name ( struct usb_endpoint *ep ); extern int usb_endpoint_described ( struct usb_endpoint *ep, struct usb_configuration_descriptor *config, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index ); extern int usb_endpoint_open ( struct usb_endpoint *ep ); extern void usb_endpoint_close ( struct usb_endpoint *ep ); extern int usb_message ( struct usb_endpoint *ep, unsigned int request, unsigned int value, unsigned int index, struct io_buffer *iobuf ); extern int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf, int terminate ); extern void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf, int rc ); /** * Initialise USB endpoint refill * * @v ep USB endpoint * @v len Refill buffer length (or zero to use endpoint's MTU) * @v max Maximum fill level */ static inline __attribute__ (( always_inline )) void usb_refill_init ( struct usb_endpoint *ep, size_t len, unsigned int max ) { INIT_LIST_HEAD ( &ep->recycled ); ep->len = len; ep->max = max; } /** * Recycle I/O buffer * * @v ep USB endpoint * @v iobuf I/O buffer */ static inline __attribute__ (( always_inline )) void usb_recycle ( struct usb_endpoint *ep, struct io_buffer *iobuf ) { list_add_tail ( &iobuf->list, &ep->recycled ); } extern int usb_prefill ( struct usb_endpoint *ep ); extern int usb_refill ( struct usb_endpoint *ep ); extern void usb_flush ( struct usb_endpoint *ep ); /** * A USB function * * A USB function represents an association of interfaces within a USB * device. */ struct usb_function { /** Name */ const char *name; /** USB device */ struct usb_device *usb; /** Class */ struct usb_class class; /** Number of interfaces */ unsigned int count; /** Generic device */ struct device dev; /** List of functions within this USB device */ struct list_head list; /** Driver */ struct usb_driver *driver; /** Driver private data */ void *priv; /** List of interface numbers * * This must be the last field within the structure. */ uint8_t interface[0]; }; /** * Set USB function driver private data * * @v func USB function * @v priv Driver private data */ static inline __attribute__ (( always_inline )) void usb_func_set_drvdata ( struct usb_function *func, void *priv ) { func->priv = priv; } /** * Get USB function driver private data * * @v function USB function * @ret priv Driver private data */ static inline __attribute__ (( always_inline )) void * usb_func_get_drvdata ( struct usb_function *func ) { return func->priv; } /** A USB device */ struct usb_device { /** Name */ char name[32]; /** USB port */ struct usb_port *port; /** List of devices on this bus */ struct list_head list; /** Device address, if assigned */ unsigned int address; /** Device descriptor */ struct usb_device_descriptor device; /** List of functions */ struct list_head functions; /** Host controller operations */ struct usb_device_host_operations *host; /** Host controller private data */ void *priv; /** Endpoint list */ struct usb_endpoint *ep[32]; /** Control endpoint */ struct usb_endpoint control; /** Completed control transfers */ struct list_head complete; }; /** USB device host controller operations */ struct usb_device_host_operations { /** Open device * * @v usb USB device * @ret rc Return status code */ int ( * open ) ( struct usb_device *usb ); /** Close device * * @v usb USB device */ void ( * close ) ( struct usb_device *usb ); /** Assign device address * * @v usb USB device * @ret rc Return status code */ int ( * address ) ( struct usb_device *usb ); }; /** * Set USB device host controller private data * * @v usb USB device * @v priv Host controller private data */ static inline __attribute__ (( always_inline )) void usb_set_hostdata ( struct usb_device *usb, void *priv ) { usb->priv = priv; } /** * Get USB device host controller private data * * @v usb USB device * @ret priv Host controller private data */ static inline __attribute__ (( always_inline )) void * usb_get_hostdata ( struct usb_device *usb ) { return usb->priv; } /** * Get USB endpoint * * @v usb USB device * @v address Endpoint address * @ret ep USB endpoint, or NULL if not opened */ static inline struct usb_endpoint * usb_endpoint ( struct usb_device *usb, unsigned int address ) { return usb->ep[ USB_ENDPOINT_IDX ( address ) ]; } /** A USB port */ struct usb_port { /** USB hub */ struct usb_hub *hub; /** Port address */ unsigned int address; /** Port protocol */ unsigned int protocol; /** Port speed */ unsigned int speed; /** Port disconnection has been detected * * This should be set whenever the underlying hardware reports * a connection status change. */ int disconnected; /** Port has an attached device */ int attached; /** Currently attached device (if in use) * * Note that this field will be NULL if the attached device * has been freed (e.g. because there were no drivers found). */ struct usb_device *usb; /** List of changed ports */ struct list_head changed; }; /** A USB hub */ struct usb_hub { /** Name */ const char *name; /** USB bus */ struct usb_bus *bus; /** Underlying USB device, if any */ struct usb_device *usb; /** Hub protocol */ unsigned int protocol; /** Number of ports */ unsigned int ports; /** List of hubs */ struct list_head list; /** Host controller operations */ struct usb_hub_host_operations *host; /** Driver operations */ struct usb_hub_driver_operations *driver; /** Driver private data */ void *priv; /** Port list * * This must be the last field within the structure. */ struct usb_port port[0]; }; /** USB hub host controller operations */ struct usb_hub_host_operations { /** Open hub * * @v hub USB hub * @ret rc Return status code */ int ( * open ) ( struct usb_hub *hub ); /** Close hub * * @v hub USB hub */ void ( * close ) ( struct usb_hub *hub ); }; /** USB hub driver operations */ struct usb_hub_driver_operations { /** Open hub * * @v hub USB hub * @ret rc Return status code */ int ( * open ) ( struct usb_hub *hub ); /** Close hub * * @v hub USB hub */ void ( * close ) ( struct usb_hub *hub ); /** Enable port * * @v hub USB hub * @v port USB port * @ret rc Return status code */ int ( * enable ) ( struct usb_hub *hub, struct usb_port *port ); /** Disable port * * @v hub USB hub * @v port USB port * @ret rc Return status code */ int ( * disable ) ( struct usb_hub *hub, struct usb_port *port ); /** Update port speed * * @v hub USB hub * @v port USB port * @ret rc Return status code */ int ( * speed ) ( struct usb_hub *hub, struct usb_port *port ); /** Clear transaction translator buffer * * @v hub USB hub * @v port USB port * @v ep USB endpoint * @ret rc Return status code */ int ( * clear_tt ) ( struct usb_hub *hub, struct usb_port *port, struct usb_endpoint *ep ); }; /** * Set USB hub driver private data * * @v hub USB hub * @v priv Driver private data */ static inline __attribute__ (( always_inline )) void usb_hub_set_drvdata ( struct usb_hub *hub, void *priv ) { hub->priv = priv; } /** * Get USB hub driver private data * * @v hub USB hub * @ret priv Driver private data */ static inline __attribute__ (( always_inline )) void * usb_hub_get_drvdata ( struct usb_hub *hub ) { return hub->priv; } /** * Get USB port * * @v hub USB hub * @v address Port address * @ret port USB port */ static inline __attribute__ (( always_inline )) struct usb_port * usb_port ( struct usb_hub *hub, unsigned int address ) { return &hub->port[ address - 1 ]; } /** A USB bus */ struct usb_bus { /** Name */ const char *name; /** Underlying hardware device */ struct device *dev; /** Host controller operations set */ struct usb_host_operations *op; /** Largest transfer allowed on the bus */ size_t mtu; /** Address in-use mask * * This is used only by buses which perform manual address * assignment. USB allows for addresses in the range [1,127]. * We use a simple bitmask which restricts us to the range * [1,64]; this is unlikely to be a problem in practice. For * comparison: controllers which perform autonomous address * assignment (such as xHCI) typically allow for only 32 * devices per bus anyway. */ unsigned long long addresses; /** Root hub */ struct usb_hub *hub; /** List of USB buses */ struct list_head list; /** List of devices */ struct list_head devices; /** List of hubs */ struct list_head hubs; /** Host controller operations */ struct usb_bus_host_operations *host; /** Host controller private data */ void *priv; }; /** USB bus host controller operations */ struct usb_bus_host_operations { /** Open bus * * @v bus USB bus * @ret rc Return status code */ int ( * open ) ( struct usb_bus *bus ); /** Close bus * * @v bus USB bus */ void ( * close ) ( struct usb_bus *bus ); /** Poll bus * * @v bus USB bus */ void ( * poll ) ( struct usb_bus *bus ); }; /** USB host controller operations */ struct usb_host_operations { /** Endpoint operations */ struct usb_endpoint_host_operations endpoint; /** Device operations */ struct usb_device_host_operations device; /** Bus operations */ struct usb_bus_host_operations bus; /** Hub operations */ struct usb_hub_host_operations hub; /** Root hub operations */ struct usb_hub_driver_operations root; }; /** * Set USB bus host controller private data * * @v bus USB bus * @v priv Host controller private data */ static inline __attribute__ (( always_inline )) void usb_bus_set_hostdata ( struct usb_bus *bus, void *priv ) { bus->priv = priv; } /** * Get USB bus host controller private data * * @v bus USB bus * @ret priv Host controller private data */ static inline __attribute__ (( always_inline )) void * usb_bus_get_hostdata ( struct usb_bus *bus ) { return bus->priv; } /** * Poll USB bus * * @v bus USB bus */ static inline __attribute__ (( always_inline )) void usb_poll ( struct usb_bus *bus ) { bus->host->poll ( bus ); } /** Iterate over all USB buses */ #define for_each_usb_bus( bus ) \ list_for_each_entry ( (bus), &usb_buses, list ) /** * Complete transfer (without error) * * @v ep USB endpoint * @v iobuf I/O buffer */ static inline __attribute__ (( always_inline )) void usb_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf ) { usb_complete_err ( ep, iobuf, 0 ); } extern int usb_control ( struct usb_device *usb, unsigned int request, unsigned int value, unsigned int index, void *data, size_t len ); extern int usb_get_string_descriptor ( struct usb_device *usb, unsigned int index, unsigned int language, char *buf, size_t len ); /** * Get status * * @v usb USB device * @v type Request type * @v index Target index * @v data Status to fill in * @v len Length of status descriptor * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_get_status ( struct usb_device *usb, unsigned int type, unsigned int index, void *data, size_t len ) { return usb_control ( usb, ( USB_GET_STATUS | type ), 0, index, data, len ); } /** * Clear feature * * @v usb USB device * @v type Request type * @v feature Feature selector * @v index Target index * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_clear_feature ( struct usb_device *usb, unsigned int type, unsigned int feature, unsigned int index ) { return usb_control ( usb, ( USB_CLEAR_FEATURE | type ), feature, index, NULL, 0 ); } /** * Set feature * * @v usb USB device * @v type Request type * @v feature Feature selector * @v index Target index * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_set_feature ( struct usb_device *usb, unsigned int type, unsigned int feature, unsigned int index ) { return usb_control ( usb, ( USB_SET_FEATURE | type ), feature, index, NULL, 0 ); } /** * Set address * * @v usb USB device * @v address Device address * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_set_address ( struct usb_device *usb, unsigned int address ) { return usb_control ( usb, USB_SET_ADDRESS, address, 0, NULL, 0 ); } /** * Get USB descriptor * * @v usb USB device * @v type Request type * @v desc Descriptor type * @v index Descriptor index * @v language Language ID (for string descriptors) * @v data Descriptor to fill in * @v len Maximum length of descriptor * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_get_descriptor ( struct usb_device *usb, unsigned int type, unsigned int desc, unsigned int index, unsigned int language, struct usb_descriptor_header *data, size_t len ) { return usb_control ( usb, ( USB_GET_DESCRIPTOR | type ), ( ( desc << 8 ) | index ), language, data, len ); } /** * Get first part of USB device descriptor (up to and including MTU) * * @v usb USB device * @v data Device descriptor to (partially) fill in * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_get_mtu ( struct usb_device *usb, struct usb_device_descriptor *data ) { return usb_get_descriptor ( usb, 0, USB_DEVICE_DESCRIPTOR, 0, 0, &data->header, ( offsetof ( typeof ( *data ), mtu ) + sizeof ( data->mtu ) ) ); } /** * Get USB device descriptor * * @v usb USB device * @v data Device descriptor to fill in * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_get_device_descriptor ( struct usb_device *usb, struct usb_device_descriptor *data ) { return usb_get_descriptor ( usb, 0, USB_DEVICE_DESCRIPTOR, 0, 0, &data->header, sizeof ( *data ) ); } /** * Get USB configuration descriptor * * @v usb USB device * @v index Configuration index * @v data Configuration descriptor to fill in * @ret rc Return status code */ static inline __attribute (( always_inline )) int usb_get_config_descriptor ( struct usb_device *usb, unsigned int index, struct usb_configuration_descriptor *data, size_t len ) { return usb_get_descriptor ( usb, 0, USB_CONFIGURATION_DESCRIPTOR, index, 0, &data->header, len ); } /** * Set USB configuration * * @v usb USB device * @v index Configuration index * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_set_configuration ( struct usb_device *usb, unsigned int index ) { return usb_control ( usb, USB_SET_CONFIGURATION, index, 0, NULL, 0 ); } /** * Set USB interface alternate setting * * @v usb USB device * @v interface Interface number * @v alternate Alternate setting * @ret rc Return status code */ static inline __attribute__ (( always_inline )) int usb_set_interface ( struct usb_device *usb, unsigned int interface, unsigned int alternate ) { return usb_control ( usb, USB_SET_INTERFACE, alternate, interface, NULL, 0 ); } extern struct list_head usb_buses; extern struct usb_interface_descriptor * usb_interface_descriptor ( struct usb_configuration_descriptor *config, unsigned int interface, unsigned int alternate ); extern struct usb_endpoint_descriptor * usb_endpoint_descriptor ( struct usb_configuration_descriptor *config, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index ); extern struct usb_endpoint_companion_descriptor * usb_endpoint_companion_descriptor ( struct usb_configuration_descriptor *config, struct usb_endpoint_descriptor *desc ); extern struct usb_hub * alloc_usb_hub ( struct usb_bus *bus, struct usb_device *usb, unsigned int ports, struct usb_hub_driver_operations *op ); extern int register_usb_hub ( struct usb_hub *hub ); extern void unregister_usb_hub ( struct usb_hub *hub ); extern void free_usb_hub ( struct usb_hub *hub ); extern void usb_port_changed ( struct usb_port *port ); extern struct usb_bus * alloc_usb_bus ( struct device *dev, unsigned int ports, size_t mtu, struct usb_host_operations *op ); extern int register_usb_bus ( struct usb_bus *bus ); extern void unregister_usb_bus ( struct usb_bus *bus ); extern void free_usb_bus ( struct usb_bus *bus ); extern struct usb_bus * find_usb_bus_by_location ( unsigned int bus_type, unsigned int location ); extern int usb_alloc_address ( struct usb_bus *bus ); extern void usb_free_address ( struct usb_bus *bus, unsigned int address ); extern unsigned int usb_route_string ( struct usb_device *usb ); extern unsigned int usb_depth ( struct usb_device *usb ); extern struct usb_port * usb_root_hub_port ( struct usb_device *usb ); extern struct usb_port * usb_transaction_translator ( struct usb_device *usb ); /** Minimum reset time * * Section 7.1.7.5 of the USB2 specification states that root hub * ports should assert reset signalling for at least 50ms. */ #define USB_RESET_DELAY_MS 50 /** Reset recovery time * * Section 9.2.6.2 of the USB2 specification states that the * "recovery" interval after a port reset is 10ms. */ #define USB_RESET_RECOVER_DELAY_MS 10 /** Maximum time to wait for a control transaction to complete * * Section 9.2.6.1 of the USB2 specification states that the upper * limit for commands to be processed is 5 seconds. */ #define USB_CONTROL_MAX_WAIT_MS 5000 /** Set address recovery time * * Section 9.2.6.3 of the USB2 specification states that devices are * allowed a 2ms recovery interval after receiving a new address. */ #define USB_SET_ADDRESS_RECOVER_DELAY_MS 2 /** Time to wait for ports to stabilise * * Section 7.1.7.3 of the USB specification states that we must allow * 100ms for devices to signal attachment, and an additional 100ms for * connection debouncing. (This delay is parallelised across all * ports on a hub; we do not delay separately for each port.) */ #define USB_PORT_DELAY_MS 200 /** A USB device ID */ struct usb_device_id { /** Name */ const char *name; /** Vendor ID */ uint16_t vendor; /** Product ID */ uint16_t product; /** Class */ struct usb_class class; }; /** Match-anything ID */ #define USB_ANY_ID 0xffff /** A USB driver */ struct usb_driver { /** USB ID table */ struct usb_device_id *ids; /** Number of entries in ID table */ unsigned int id_count; /** * Probe device * * @v func USB function * @v config Configuration descriptor * @ret rc Return status code */ int ( * probe ) ( struct usb_function *func, struct usb_configuration_descriptor *config ); /** * Remove device * * @v func USB function */ void ( * remove ) ( struct usb_function *func ); }; /** USB driver table */ #define USB_DRIVERS __table ( struct usb_driver, "usb_drivers" ) /** Declare a USB driver */ #define __usb_driver __table_entry ( USB_DRIVERS, 01 ) #endif /* _IPXE_USB_H */