Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 1 | #ifndef QEMU_HW_USB_DESC_H |
| 2 | #define QEMU_HW_USB_DESC_H |
| 3 | |
| 4 | #include <inttypes.h> |
Gerd Hoffmann | 5319dc7 | 2013-11-20 07:32:31 +0100 | [diff] [blame] | 5 | #include <wchar.h> |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 6 | |
Gerd Hoffmann | d3f904e | 2012-03-29 12:04:54 +0200 | [diff] [blame] | 7 | /* binary representation */ |
| 8 | typedef struct USBDescriptor { |
| 9 | uint8_t bLength; |
| 10 | uint8_t bDescriptorType; |
| 11 | union { |
| 12 | struct { |
| 13 | uint8_t bcdUSB_lo; |
| 14 | uint8_t bcdUSB_hi; |
| 15 | uint8_t bDeviceClass; |
| 16 | uint8_t bDeviceSubClass; |
| 17 | uint8_t bDeviceProtocol; |
| 18 | uint8_t bMaxPacketSize0; |
| 19 | uint8_t idVendor_lo; |
| 20 | uint8_t idVendor_hi; |
| 21 | uint8_t idProduct_lo; |
| 22 | uint8_t idProduct_hi; |
| 23 | uint8_t bcdDevice_lo; |
| 24 | uint8_t bcdDevice_hi; |
| 25 | uint8_t iManufacturer; |
| 26 | uint8_t iProduct; |
| 27 | uint8_t iSerialNumber; |
| 28 | uint8_t bNumConfigurations; |
| 29 | } device; |
Gerd Hoffmann | 3cfeee6 | 2012-03-29 12:15:01 +0200 | [diff] [blame] | 30 | struct { |
| 31 | uint8_t bcdUSB_lo; |
| 32 | uint8_t bcdUSB_hi; |
| 33 | uint8_t bDeviceClass; |
| 34 | uint8_t bDeviceSubClass; |
| 35 | uint8_t bDeviceProtocol; |
| 36 | uint8_t bMaxPacketSize0; |
| 37 | uint8_t bNumConfigurations; |
| 38 | uint8_t bReserved; |
| 39 | } device_qualifier; |
Gerd Hoffmann | 0a263db | 2012-03-29 12:24:08 +0200 | [diff] [blame] | 40 | struct { |
| 41 | uint8_t wTotalLength_lo; |
| 42 | uint8_t wTotalLength_hi; |
| 43 | uint8_t bNumInterfaces; |
| 44 | uint8_t bConfigurationValue; |
| 45 | uint8_t iConfiguration; |
| 46 | uint8_t bmAttributes; |
| 47 | uint8_t bMaxPower; |
| 48 | } config; |
Gerd Hoffmann | feafd79 | 2012-03-29 12:30:33 +0200 | [diff] [blame] | 49 | struct { |
| 50 | uint8_t bInterfaceNumber; |
| 51 | uint8_t bAlternateSetting; |
| 52 | uint8_t bNumEndpoints; |
| 53 | uint8_t bInterfaceClass; |
| 54 | uint8_t bInterfaceSubClass; |
| 55 | uint8_t bInterfaceProtocol; |
| 56 | uint8_t iInterface; |
| 57 | } interface; |
Gerd Hoffmann | e36a20d | 2012-03-29 16:01:21 +0200 | [diff] [blame] | 58 | struct { |
| 59 | uint8_t bEndpointAddress; |
| 60 | uint8_t bmAttributes; |
| 61 | uint8_t wMaxPacketSize_lo; |
| 62 | uint8_t wMaxPacketSize_hi; |
| 63 | uint8_t bInterval; |
| 64 | uint8_t bRefresh; /* only audio ep */ |
| 65 | uint8_t bSynchAddress; /* only audio ep */ |
| 66 | } endpoint; |
Gerd Hoffmann | b43a285 | 2012-08-28 17:28:03 +0200 | [diff] [blame] | 67 | struct { |
| 68 | uint8_t bMaxBurst; |
| 69 | uint8_t bmAttributes; |
| 70 | uint8_t wBytesPerInterval_lo; |
| 71 | uint8_t wBytesPerInterval_hi; |
| 72 | } super_endpoint; |
Gerd Hoffmann | 2077469 | 2012-08-28 17:46:29 +0200 | [diff] [blame] | 73 | struct { |
| 74 | uint8_t wTotalLength_lo; |
| 75 | uint8_t wTotalLength_hi; |
| 76 | uint8_t bNumDeviceCaps; |
| 77 | } bos; |
| 78 | struct { |
| 79 | uint8_t bDevCapabilityType; |
| 80 | union { |
| 81 | struct { |
| 82 | uint8_t bmAttributes_1; |
| 83 | uint8_t bmAttributes_2; |
| 84 | uint8_t bmAttributes_3; |
| 85 | uint8_t bmAttributes_4; |
| 86 | } usb2_ext; |
| 87 | struct { |
| 88 | uint8_t bmAttributes; |
| 89 | uint8_t wSpeedsSupported_lo; |
| 90 | uint8_t wSpeedsSupported_hi; |
| 91 | uint8_t bFunctionalitySupport; |
| 92 | uint8_t bU1DevExitLat; |
| 93 | uint8_t wU2DevExitLat_lo; |
| 94 | uint8_t wU2DevExitLat_hi; |
| 95 | } super; |
| 96 | } u; |
| 97 | } cap; |
Gerd Hoffmann | d3f904e | 2012-03-29 12:04:54 +0200 | [diff] [blame] | 98 | } u; |
| 99 | } QEMU_PACKED USBDescriptor; |
| 100 | |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 101 | struct USBDescID { |
| 102 | uint16_t idVendor; |
| 103 | uint16_t idProduct; |
| 104 | uint16_t bcdDevice; |
| 105 | uint8_t iManufacturer; |
| 106 | uint8_t iProduct; |
| 107 | uint8_t iSerialNumber; |
| 108 | }; |
| 109 | |
| 110 | struct USBDescDevice { |
| 111 | uint16_t bcdUSB; |
| 112 | uint8_t bDeviceClass; |
| 113 | uint8_t bDeviceSubClass; |
| 114 | uint8_t bDeviceProtocol; |
| 115 | uint8_t bMaxPacketSize0; |
| 116 | uint8_t bNumConfigurations; |
| 117 | |
| 118 | const USBDescConfig *confs; |
| 119 | }; |
| 120 | |
| 121 | struct USBDescConfig { |
| 122 | uint8_t bNumInterfaces; |
| 123 | uint8_t bConfigurationValue; |
| 124 | uint8_t iConfiguration; |
| 125 | uint8_t bmAttributes; |
| 126 | uint8_t bMaxPower; |
| 127 | |
Brad Hards | 6e625fc | 2011-04-03 15:33:21 +1000 | [diff] [blame] | 128 | /* grouped interfaces */ |
| 129 | uint8_t nif_groups; |
| 130 | const USBDescIfaceAssoc *if_groups; |
| 131 | |
| 132 | /* "normal" interfaces */ |
| 133 | uint8_t nif; |
| 134 | const USBDescIface *ifs; |
| 135 | }; |
| 136 | |
| 137 | /* conceptually an Interface Association Descriptor, and releated interfaces */ |
| 138 | struct USBDescIfaceAssoc { |
| 139 | uint8_t bFirstInterface; |
| 140 | uint8_t bInterfaceCount; |
| 141 | uint8_t bFunctionClass; |
| 142 | uint8_t bFunctionSubClass; |
| 143 | uint8_t bFunctionProtocol; |
| 144 | uint8_t iFunction; |
| 145 | |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 146 | uint8_t nif; |
| 147 | const USBDescIface *ifs; |
| 148 | }; |
| 149 | |
| 150 | struct USBDescIface { |
| 151 | uint8_t bInterfaceNumber; |
| 152 | uint8_t bAlternateSetting; |
| 153 | uint8_t bNumEndpoints; |
| 154 | uint8_t bInterfaceClass; |
| 155 | uint8_t bInterfaceSubClass; |
| 156 | uint8_t bInterfaceProtocol; |
| 157 | uint8_t iInterface; |
| 158 | |
| 159 | uint8_t ndesc; |
| 160 | USBDescOther *descs; |
| 161 | USBDescEndpoint *eps; |
| 162 | }; |
| 163 | |
| 164 | struct USBDescEndpoint { |
| 165 | uint8_t bEndpointAddress; |
| 166 | uint8_t bmAttributes; |
| 167 | uint16_t wMaxPacketSize; |
| 168 | uint8_t bInterval; |
Gerd Hoffmann | cc5f139 | 2011-08-10 14:10:04 +0200 | [diff] [blame] | 169 | uint8_t bRefresh; |
| 170 | uint8_t bSynchAddress; |
| 171 | |
| 172 | uint8_t is_audio; /* has bRefresh + bSynchAddress */ |
| 173 | uint8_t *extra; |
Gerd Hoffmann | b43a285 | 2012-08-28 17:28:03 +0200 | [diff] [blame] | 174 | |
| 175 | /* superspeed endpoint companion */ |
| 176 | uint8_t bMaxBurst; |
| 177 | uint8_t bmAttributes_super; |
| 178 | uint16_t wBytesPerInterval; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 179 | }; |
| 180 | |
| 181 | struct USBDescOther { |
| 182 | uint8_t length; |
Gerd Hoffmann | 97237e0 | 2011-08-30 11:49:05 +0200 | [diff] [blame] | 183 | const uint8_t *data; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 184 | }; |
| 185 | |
Gerd Hoffmann | 5319dc7 | 2013-11-20 07:32:31 +0100 | [diff] [blame] | 186 | struct USBDescMSOS { |
Gerd Hoffmann | 409951f | 2014-03-18 11:01:50 +0100 | [diff] [blame] | 187 | const char *CompatibleID; |
Gerd Hoffmann | 5319dc7 | 2013-11-20 07:32:31 +0100 | [diff] [blame] | 188 | const wchar_t *Label; |
| 189 | bool SelectiveSuspendEnabled; |
| 190 | }; |
| 191 | |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 192 | typedef const char *USBDescStrings[256]; |
| 193 | |
| 194 | struct USBDesc { |
| 195 | USBDescID id; |
| 196 | const USBDescDevice *full; |
| 197 | const USBDescDevice *high; |
Gerd Hoffmann | 6d51b2b | 2012-08-28 17:28:50 +0200 | [diff] [blame] | 198 | const USBDescDevice *super; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 199 | const char* const *str; |
Gerd Hoffmann | 5319dc7 | 2013-11-20 07:32:31 +0100 | [diff] [blame] | 200 | const USBDescMSOS *msos; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 201 | }; |
| 202 | |
Gerd Hoffmann | b43a285 | 2012-08-28 17:28:03 +0200 | [diff] [blame] | 203 | #define USB_DESC_FLAG_SUPER (1 << 1) |
| 204 | |
Gerd Hoffmann | 0b1fa34 | 2013-11-20 07:33:28 +0100 | [diff] [blame] | 205 | /* little helpers */ |
| 206 | static inline uint8_t usb_lo(uint16_t val) |
| 207 | { |
| 208 | return val & 0xff; |
| 209 | } |
| 210 | |
| 211 | static inline uint8_t usb_hi(uint16_t val) |
| 212 | { |
| 213 | return (val >> 8) & 0xff; |
| 214 | } |
| 215 | |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 216 | /* generate usb packages from structs */ |
| 217 | int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, |
Gerd Hoffmann | 5319dc7 | 2013-11-20 07:32:31 +0100 | [diff] [blame] | 218 | bool msos, uint8_t *dest, size_t len); |
Gerd Hoffmann | 25620cb | 2010-12-08 17:35:22 +0100 | [diff] [blame] | 219 | int usb_desc_device_qualifier(const USBDescDevice *dev, |
| 220 | uint8_t *dest, size_t len); |
Gerd Hoffmann | b43a285 | 2012-08-28 17:28:03 +0200 | [diff] [blame] | 221 | int usb_desc_config(const USBDescConfig *conf, int flags, |
| 222 | uint8_t *dest, size_t len); |
| 223 | int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags, |
| 224 | uint8_t *dest, size_t len); |
| 225 | int usb_desc_iface(const USBDescIface *iface, int flags, |
| 226 | uint8_t *dest, size_t len); |
| 227 | int usb_desc_endpoint(const USBDescEndpoint *ep, int flags, |
| 228 | uint8_t *dest, size_t len); |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 229 | int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); |
Gerd Hoffmann | 5319dc7 | 2013-11-20 07:32:31 +0100 | [diff] [blame] | 230 | int usb_desc_msos(const USBDesc *desc, USBPacket *p, |
| 231 | int index, uint8_t *dest, size_t len); |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 232 | |
| 233 | /* control message emulation helpers */ |
Gerd Hoffmann | a980a06 | 2010-11-26 20:20:41 +0100 | [diff] [blame] | 234 | void usb_desc_init(USBDevice *dev); |
Gerd Hoffmann | 32d4191 | 2010-12-03 18:07:20 +0100 | [diff] [blame] | 235 | void usb_desc_attach(USBDevice *dev); |
Gerd Hoffmann | 132a3f5 | 2010-11-26 12:25:32 +0100 | [diff] [blame] | 236 | void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str); |
Gerd Hoffmann | 9d55d1a | 2012-04-20 12:33:30 +0200 | [diff] [blame] | 237 | void usb_desc_create_serial(USBDevice *dev); |
Gerd Hoffmann | 132a3f5 | 2010-11-26 12:25:32 +0100 | [diff] [blame] | 238 | const char *usb_desc_get_string(USBDevice *dev, uint8_t index); |
| 239 | int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len); |
Hans de Goede | 9a77a0f | 2012-11-01 17:15:01 +0100 | [diff] [blame] | 240 | int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p, |
| 241 | int value, uint8_t *dest, size_t len); |
Hans de Goede | 007fd62 | 2011-02-02 16:33:13 +0100 | [diff] [blame] | 242 | int usb_desc_handle_control(USBDevice *dev, USBPacket *p, |
| 243 | int request, int value, int index, int length, uint8_t *data); |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 244 | |
| 245 | #endif /* QEMU_HW_USB_DESC_H */ |