diff options
Diffstat (limited to 'hw/usb/desc.h')
-rw-r--r-- | hw/usb/desc.h | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/hw/usb/desc.h b/hw/usb/desc.h new file mode 100644 index 000000000..7cf544294 --- /dev/null +++ b/hw/usb/desc.h @@ -0,0 +1,181 @@ +#ifndef QEMU_HW_USB_DESC_H +#define QEMU_HW_USB_DESC_H + +#include <inttypes.h> + +/* binary representation */ +typedef struct USBDescriptor { + uint8_t bLength; + uint8_t bDescriptorType; + union { + struct { + uint8_t bcdUSB_lo; + uint8_t bcdUSB_hi; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t idVendor_lo; + uint8_t idVendor_hi; + uint8_t idProduct_lo; + uint8_t idProduct_hi; + uint8_t bcdDevice_lo; + uint8_t bcdDevice_hi; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; + } device; + struct { + uint8_t bcdUSB_lo; + uint8_t bcdUSB_hi; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bReserved; + } device_qualifier; + struct { + uint8_t wTotalLength_lo; + uint8_t wTotalLength_hi; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; + } config; + struct { + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + } interface; + struct { + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint8_t wMaxPacketSize_lo; + uint8_t wMaxPacketSize_hi; + uint8_t bInterval; + uint8_t bRefresh; /* only audio ep */ + uint8_t bSynchAddress; /* only audio ep */ + } endpoint; + } u; +} QEMU_PACKED USBDescriptor; + +struct USBDescID { + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; +}; + +struct USBDescDevice { + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + + const USBDescConfig *confs; +}; + +struct USBDescConfig { + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; + + /* grouped interfaces */ + uint8_t nif_groups; + const USBDescIfaceAssoc *if_groups; + + /* "normal" interfaces */ + uint8_t nif; + const USBDescIface *ifs; +}; + +/* conceptually an Interface Association Descriptor, and releated interfaces */ +struct USBDescIfaceAssoc { + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; + + uint8_t nif; + const USBDescIface *ifs; +}; + +struct USBDescIface { + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + + uint8_t ndesc; + USBDescOther *descs; + USBDescEndpoint *eps; +}; + +struct USBDescEndpoint { + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + uint8_t bRefresh; + uint8_t bSynchAddress; + + uint8_t is_audio; /* has bRefresh + bSynchAddress */ + uint8_t *extra; +}; + +struct USBDescOther { + uint8_t length; + const uint8_t *data; +}; + +typedef const char *USBDescStrings[256]; + +struct USBDesc { + USBDescID id; + const USBDescDevice *full; + const USBDescDevice *high; + const char* const *str; +}; + +/* generate usb packages from structs */ +int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, + uint8_t *dest, size_t len); +int usb_desc_device_qualifier(const USBDescDevice *dev, + uint8_t *dest, size_t len); +int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len); +int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest, + size_t len); +int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len); +int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len); +int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); + +/* control message emulation helpers */ +void usb_desc_init(USBDevice *dev); +void usb_desc_attach(USBDevice *dev); +void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str); +void usb_desc_create_serial(USBDevice *dev); +const char *usb_desc_get_string(USBDevice *dev, uint8_t index); +int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len); +int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len); +int usb_desc_handle_control(USBDevice *dev, USBPacket *p, + int request, int value, int index, int length, uint8_t *data); + +#endif /* QEMU_HW_USB_DESC_H */ |