#ifndef _IPXE_USB_H #define _IPXE_USB_H /** @file * * Universal Serial Bus (USB) * */ FILE_LICENCE ( GPL2_OR_LATER ); #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 ), }; /** 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 ) /** 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 /** 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 endpoint (internal) type */ #define USB_INTERRUPT ( USB_ENDPOINT_ATTR_INTERRUPT | USB_DIR_IN ) /** 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; /** Endpoint is open */ int open; /** Current failure state (if any) */ int rc; /** Host controller operations */ struct usb_endpoint_host_operations *host; /** Host controller private data */ void *priv; /** Driver operations */ struct usb_endpoint_driver_operations *driver; }; /** 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 packet Setup packet * @v iobuf I/O buffer (if any) * @ret rc Return status code */ int ( * message ) ( struct usb_endpoint *ep, struct usb_setup_packet *setup, struct io_buffer *iobuf ); /** Enqueue stream transfer * * @v ep USB endpoint * @v iobuf I/O buffer * @ret rc Return status code */ int ( * stream ) ( struct usb_endpoint *ep, struct io_buffer *iobuf ); }; /** 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 /** 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 */ 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 ) { ep->address = address; ep->attributes = attributes; ep->mtu = mtu; ep->burst = burst; } /** * 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 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 ); extern void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf, int rc ); /** * 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; /** Currently attached device (if any) */ struct usb_device *usb; /** List of changed ports */ struct list_head list; }; /** 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; /** 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 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 ); }; /** * 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; /** Root hub */ struct usb_hub *hub; /** List of devices */ struct list_head devices; /** List of hubs */ struct list_head hubs; /** List of changed ports */ struct list_head changed; /** Process */ struct process process; /** 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; /** Root hub operations */ struct usb_hub_driver_operations hub; }; /** * 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 ); } /** * 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 ); } /** * 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 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, 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 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 ); /** Maximum time to wait for a control transaction to complete * * This is a policy decision. */ #define USB_CONTROL_MAX_WAIT_MS 100 /** Time to wait for ports to stabilise * * This is a policy decision. */ #define USB_PORT_DELAY_MS 100 /** 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 */