| #ifndef QEMU_HW_USB_DESC_H |
| #define QEMU_HW_USB_DESC_H |
| |
| #include <inttypes.h> |
| #include <wchar.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; |
| struct { |
| uint8_t bMaxBurst; |
| uint8_t bmAttributes; |
| uint8_t wBytesPerInterval_lo; |
| uint8_t wBytesPerInterval_hi; |
| } super_endpoint; |
| struct { |
| uint8_t wTotalLength_lo; |
| uint8_t wTotalLength_hi; |
| uint8_t bNumDeviceCaps; |
| } bos; |
| struct { |
| uint8_t bDevCapabilityType; |
| union { |
| struct { |
| uint8_t bmAttributes_1; |
| uint8_t bmAttributes_2; |
| uint8_t bmAttributes_3; |
| uint8_t bmAttributes_4; |
| } usb2_ext; |
| struct { |
| uint8_t bmAttributes; |
| uint8_t wSpeedsSupported_lo; |
| uint8_t wSpeedsSupported_hi; |
| uint8_t bFunctionalitySupport; |
| uint8_t bU1DevExitLat; |
| uint8_t wU2DevExitLat_lo; |
| uint8_t wU2DevExitLat_hi; |
| } super; |
| } u; |
| } cap; |
| } 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; |
| |
| /* superspeed endpoint companion */ |
| uint8_t bMaxBurst; |
| uint8_t bmAttributes_super; |
| uint16_t wBytesPerInterval; |
| }; |
| |
| struct USBDescOther { |
| uint8_t length; |
| const uint8_t *data; |
| }; |
| |
| struct USBDescMSOS { |
| const wchar_t *Label; |
| bool SelectiveSuspendEnabled; |
| }; |
| |
| typedef const char *USBDescStrings[256]; |
| |
| struct USBDesc { |
| USBDescID id; |
| const USBDescDevice *full; |
| const USBDescDevice *high; |
| const USBDescDevice *super; |
| const char* const *str; |
| const USBDescMSOS *msos; |
| }; |
| |
| #define USB_DESC_FLAG_SUPER (1 << 1) |
| |
| /* little helpers */ |
| static inline uint8_t usb_lo(uint16_t val) |
| { |
| return val & 0xff; |
| } |
| |
| static inline uint8_t usb_hi(uint16_t val) |
| { |
| return (val >> 8) & 0xff; |
| } |
| |
| /* generate usb packages from structs */ |
| int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, |
| bool msos, 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, int flags, |
| uint8_t *dest, size_t len); |
| int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags, |
| uint8_t *dest, size_t len); |
| int usb_desc_iface(const USBDescIface *iface, int flags, |
| uint8_t *dest, size_t len); |
| int usb_desc_endpoint(const USBDescEndpoint *ep, int flags, |
| uint8_t *dest, size_t len); |
| int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); |
| int usb_desc_msos(const USBDesc *desc, USBPacket *p, |
| int index, 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, USBPacket *p, |
| 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 */ |