bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 1 | /* |
| 2 | * QEMU USB API |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 4 | * Copyright (c) 2005 Fabrice Bellard |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 5 | * |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | * of this software and associated documentation files (the "Software"), to deal |
| 8 | * in the Software without restriction, including without limitation the rights |
| 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | * copies of the Software, and to permit persons to whom the Software is |
| 11 | * furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | * all copies or substantial portions of the Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | * THE SOFTWARE. |
| 23 | */ |
aliguori | c0f4ce7 | 2009-03-05 23:01:01 +0000 | [diff] [blame] | 24 | |
| 25 | #include "block.h" |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 26 | #include "qdev.h" |
Blue Swirl | 72cf2d4 | 2009-09-12 07:36:22 +0000 | [diff] [blame] | 27 | #include "qemu-queue.h" |
aliguori | c0f4ce7 | 2009-03-05 23:01:01 +0000 | [diff] [blame] | 28 | |
Brad Hards | 8e25781 | 2011-06-02 11:18:46 +1000 | [diff] [blame] | 29 | /* Constants related to the USB / PCI interaction */ |
| 30 | #define USB_SBRN 0x60 /* Serial Bus Release Number Register */ |
| 31 | #define USB_RELEASE_1 0x10 /* USB 1.0 */ |
| 32 | #define USB_RELEASE_2 0x20 /* USB 2.0 */ |
| 33 | #define USB_RELEASE_3 0x30 /* USB 3.0 */ |
| 34 | |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 35 | #define USB_TOKEN_SETUP 0x2d |
| 36 | #define USB_TOKEN_IN 0x69 /* device -> host */ |
| 37 | #define USB_TOKEN_OUT 0xe1 /* host -> device */ |
| 38 | |
| 39 | /* specific usb messages, also sent in the 'pid' parameter */ |
| 40 | #define USB_MSG_ATTACH 0x100 |
| 41 | #define USB_MSG_DETACH 0x101 |
| 42 | #define USB_MSG_RESET 0x102 |
| 43 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 44 | #define USB_RET_NODEV (-1) |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 45 | #define USB_RET_NAK (-2) |
| 46 | #define USB_RET_STALL (-3) |
| 47 | #define USB_RET_BABBLE (-4) |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 48 | #define USB_RET_ASYNC (-5) |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 49 | |
| 50 | #define USB_SPEED_LOW 0 |
| 51 | #define USB_SPEED_FULL 1 |
| 52 | #define USB_SPEED_HIGH 2 |
Gerd Hoffmann | 843d4e0 | 2010-12-03 17:30:13 +0100 | [diff] [blame] | 53 | #define USB_SPEED_SUPER 3 |
| 54 | |
| 55 | #define USB_SPEED_MASK_LOW (1 << USB_SPEED_LOW) |
| 56 | #define USB_SPEED_MASK_FULL (1 << USB_SPEED_FULL) |
| 57 | #define USB_SPEED_MASK_HIGH (1 << USB_SPEED_HIGH) |
| 58 | #define USB_SPEED_MASK_SUPER (1 << USB_SPEED_SUPER) |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 59 | |
| 60 | #define USB_STATE_NOTATTACHED 0 |
| 61 | #define USB_STATE_ATTACHED 1 |
| 62 | //#define USB_STATE_POWERED 2 |
| 63 | #define USB_STATE_DEFAULT 3 |
| 64 | //#define USB_STATE_ADDRESS 4 |
| 65 | //#define USB_STATE_CONFIGURED 5 |
| 66 | #define USB_STATE_SUSPENDED 6 |
| 67 | |
bellard | a594cfb | 2005-11-06 16:13:29 +0000 | [diff] [blame] | 68 | #define USB_CLASS_AUDIO 1 |
| 69 | #define USB_CLASS_COMM 2 |
| 70 | #define USB_CLASS_HID 3 |
| 71 | #define USB_CLASS_PHYSICAL 5 |
| 72 | #define USB_CLASS_STILL_IMAGE 6 |
| 73 | #define USB_CLASS_PRINTER 7 |
| 74 | #define USB_CLASS_MASS_STORAGE 8 |
| 75 | #define USB_CLASS_HUB 9 |
| 76 | #define USB_CLASS_CDC_DATA 0x0a |
| 77 | #define USB_CLASS_CSCID 0x0b |
| 78 | #define USB_CLASS_CONTENT_SEC 0x0d |
| 79 | #define USB_CLASS_APP_SPEC 0xfe |
| 80 | #define USB_CLASS_VENDOR_SPEC 0xff |
| 81 | |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 82 | #define USB_DIR_OUT 0 |
| 83 | #define USB_DIR_IN 0x80 |
| 84 | |
| 85 | #define USB_TYPE_MASK (0x03 << 5) |
| 86 | #define USB_TYPE_STANDARD (0x00 << 5) |
| 87 | #define USB_TYPE_CLASS (0x01 << 5) |
| 88 | #define USB_TYPE_VENDOR (0x02 << 5) |
| 89 | #define USB_TYPE_RESERVED (0x03 << 5) |
| 90 | |
| 91 | #define USB_RECIP_MASK 0x1f |
| 92 | #define USB_RECIP_DEVICE 0x00 |
| 93 | #define USB_RECIP_INTERFACE 0x01 |
| 94 | #define USB_RECIP_ENDPOINT 0x02 |
| 95 | #define USB_RECIP_OTHER 0x03 |
| 96 | |
| 97 | #define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) |
| 98 | #define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) |
bellard | 59ae540 | 2005-11-05 16:57:08 +0000 | [diff] [blame] | 99 | #define InterfaceRequest \ |
| 100 | ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) |
| 101 | #define InterfaceOutRequest \ |
| 102 | ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) |
| 103 | #define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) |
| 104 | #define EndpointOutRequest \ |
| 105 | ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) |
Max Reitz | f3571b1 | 2010-03-14 12:19:03 +0100 | [diff] [blame] | 106 | #define ClassInterfaceRequest \ |
| 107 | ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) |
| 108 | #define ClassInterfaceOutRequest \ |
| 109 | ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 110 | |
| 111 | #define USB_REQ_GET_STATUS 0x00 |
| 112 | #define USB_REQ_CLEAR_FEATURE 0x01 |
| 113 | #define USB_REQ_SET_FEATURE 0x03 |
| 114 | #define USB_REQ_SET_ADDRESS 0x05 |
| 115 | #define USB_REQ_GET_DESCRIPTOR 0x06 |
| 116 | #define USB_REQ_SET_DESCRIPTOR 0x07 |
| 117 | #define USB_REQ_GET_CONFIGURATION 0x08 |
| 118 | #define USB_REQ_SET_CONFIGURATION 0x09 |
| 119 | #define USB_REQ_GET_INTERFACE 0x0A |
| 120 | #define USB_REQ_SET_INTERFACE 0x0B |
| 121 | #define USB_REQ_SYNCH_FRAME 0x0C |
| 122 | |
| 123 | #define USB_DEVICE_SELF_POWERED 0 |
| 124 | #define USB_DEVICE_REMOTE_WAKEUP 1 |
| 125 | |
| 126 | #define USB_DT_DEVICE 0x01 |
| 127 | #define USB_DT_CONFIG 0x02 |
| 128 | #define USB_DT_STRING 0x03 |
| 129 | #define USB_DT_INTERFACE 0x04 |
| 130 | #define USB_DT_ENDPOINT 0x05 |
Gerd Hoffmann | 25620cb | 2010-12-08 17:35:22 +0100 | [diff] [blame] | 131 | #define USB_DT_DEVICE_QUALIFIER 0x06 |
| 132 | #define USB_DT_OTHER_SPEED_CONFIG 0x07 |
Gerd Hoffmann | a7fb71d | 2011-06-23 17:15:43 +0200 | [diff] [blame] | 133 | #define USB_DT_DEBUG 0x0A |
Brad Hards | c6d3ad0 | 2011-04-03 15:33:18 +1000 | [diff] [blame] | 134 | #define USB_DT_INTERFACE_ASSOC 0x0B |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 135 | |
balrog | 942ac05 | 2008-04-22 03:15:10 +0000 | [diff] [blame] | 136 | #define USB_ENDPOINT_XFER_CONTROL 0 |
| 137 | #define USB_ENDPOINT_XFER_ISOC 1 |
| 138 | #define USB_ENDPOINT_XFER_BULK 2 |
| 139 | #define USB_ENDPOINT_XFER_INT 3 |
| 140 | |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 141 | typedef struct USBBus USBBus; |
Gerd Hoffmann | 07771f6 | 2011-05-23 17:37:12 +0200 | [diff] [blame] | 142 | typedef struct USBBusOps USBBusOps; |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 143 | typedef struct USBPort USBPort; |
| 144 | typedef struct USBDevice USBDevice; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 145 | typedef struct USBDeviceInfo USBDeviceInfo; |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 146 | typedef struct USBPacket USBPacket; |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 147 | |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 148 | typedef struct USBDesc USBDesc; |
| 149 | typedef struct USBDescID USBDescID; |
| 150 | typedef struct USBDescDevice USBDescDevice; |
| 151 | typedef struct USBDescConfig USBDescConfig; |
Brad Hards | 6e625fc | 2011-04-03 15:33:21 +1000 | [diff] [blame] | 152 | typedef struct USBDescIfaceAssoc USBDescIfaceAssoc; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 153 | typedef struct USBDescIface USBDescIface; |
| 154 | typedef struct USBDescEndpoint USBDescEndpoint; |
| 155 | typedef struct USBDescOther USBDescOther; |
Gerd Hoffmann | 132a3f5 | 2010-11-26 12:25:32 +0100 | [diff] [blame] | 156 | typedef struct USBDescString USBDescString; |
| 157 | |
| 158 | struct USBDescString { |
| 159 | uint8_t index; |
| 160 | char *str; |
| 161 | QLIST_ENTRY(USBDescString) next; |
| 162 | }; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 163 | |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 164 | /* definition of a USB device */ |
| 165 | struct USBDevice { |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 166 | DeviceState qdev; |
| 167 | USBDeviceInfo *info; |
Gerd Hoffmann | 618c169 | 2010-12-01 11:27:05 +0100 | [diff] [blame] | 168 | USBPort *port; |
Gerd Hoffmann | 5f69076 | 2010-12-10 11:43:35 +0100 | [diff] [blame] | 169 | char *port_path; |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 170 | void *opaque; |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 171 | |
Hans de Goede | ba3f9bf | 2011-05-27 14:27:18 +0200 | [diff] [blame] | 172 | /* Actual connected speed */ |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 173 | int speed; |
Hans de Goede | ba3f9bf | 2011-05-27 14:27:18 +0200 | [diff] [blame] | 174 | /* Supported speeds, not in info because it may be variable (hostdevs) */ |
| 175 | int speedmask; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 176 | uint8_t addr; |
Markus Armbruster | 0fe6d12 | 2009-12-09 17:07:51 +0100 | [diff] [blame] | 177 | char product_desc[32]; |
Gerd Hoffmann | 61e094c | 2009-10-26 15:56:48 +0100 | [diff] [blame] | 178 | int auto_attach; |
Gerd Hoffmann | a5d2f72 | 2009-08-31 14:24:00 +0200 | [diff] [blame] | 179 | int attached; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 180 | |
Gerd Hoffmann | c1ecb40 | 2010-12-10 14:20:46 +0100 | [diff] [blame] | 181 | int32_t state; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 182 | uint8_t setup_buf[8]; |
Hans de Goede | 19f3322 | 2011-02-02 17:46:00 +0100 | [diff] [blame] | 183 | uint8_t data_buf[4096]; |
Gerd Hoffmann | c1ecb40 | 2010-12-10 14:20:46 +0100 | [diff] [blame] | 184 | int32_t remote_wakeup; |
| 185 | int32_t setup_state; |
| 186 | int32_t setup_len; |
| 187 | int32_t setup_index; |
Gerd Hoffmann | 132a3f5 | 2010-11-26 12:25:32 +0100 | [diff] [blame] | 188 | |
| 189 | QLIST_HEAD(, USBDescString) strings; |
Gerd Hoffmann | a980a06 | 2010-11-26 20:20:41 +0100 | [diff] [blame] | 190 | const USBDescDevice *device; |
| 191 | const USBDescConfig *config; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 192 | }; |
| 193 | |
| 194 | struct USBDeviceInfo { |
| 195 | DeviceInfo qdev; |
| 196 | int (*init)(USBDevice *dev); |
| 197 | |
| 198 | /* |
| 199 | * Process USB packet. |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 200 | * Called by the HC (Host Controller). |
| 201 | * |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 202 | * Returns length of the transaction |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 203 | * or one of the USB_RET_XXX codes. |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 204 | */ |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 205 | int (*handle_packet)(USBDevice *dev, USBPacket *p); |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 206 | |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 207 | /* |
Gerd Hoffmann | eb5e680 | 2011-05-16 10:34:53 +0200 | [diff] [blame] | 208 | * Called when a packet is canceled. |
| 209 | */ |
| 210 | void (*cancel_packet)(USBDevice *dev, USBPacket *p); |
| 211 | |
| 212 | /* |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 213 | * Called when device is destroyed. |
| 214 | */ |
bellard | 059809e | 2006-07-19 18:06:15 +0000 | [diff] [blame] | 215 | void (*handle_destroy)(USBDevice *dev); |
| 216 | |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 217 | /* |
Gerd Hoffmann | b6f77fb | 2010-12-03 17:59:36 +0100 | [diff] [blame] | 218 | * Attach the device |
| 219 | */ |
| 220 | void (*handle_attach)(USBDevice *dev); |
| 221 | |
| 222 | /* |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 223 | * Reset the device |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 224 | */ |
bellard | 059809e | 2006-07-19 18:06:15 +0000 | [diff] [blame] | 225 | void (*handle_reset)(USBDevice *dev); |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 226 | |
| 227 | /* |
| 228 | * Process control request. |
| 229 | * Called from handle_packet(). |
| 230 | * |
| 231 | * Returns length or one of the USB_RET_ codes. |
| 232 | */ |
Hans de Goede | 007fd62 | 2011-02-02 16:33:13 +0100 | [diff] [blame] | 233 | int (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value, |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 234 | int index, int length, uint8_t *data); |
aliguori | 89b9b79 | 2008-08-21 19:29:38 +0000 | [diff] [blame] | 235 | |
| 236 | /* |
| 237 | * Process data transfers (both BULK and ISOC). |
| 238 | * Called from handle_packet(). |
| 239 | * |
| 240 | * Returns length or one of the USB_RET_ codes. |
| 241 | */ |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 242 | int (*handle_data)(USBDevice *dev, USBPacket *p); |
Gerd Hoffmann | 0958b4c | 2009-10-26 15:56:45 +0100 | [diff] [blame] | 243 | |
Markus Armbruster | 0638469 | 2009-12-09 17:07:52 +0100 | [diff] [blame] | 244 | const char *product_desc; |
Gerd Hoffmann | 37fb59d | 2010-11-17 11:03:53 +0100 | [diff] [blame] | 245 | const USBDesc *usb_desc; |
Markus Armbruster | 0638469 | 2009-12-09 17:07:52 +0100 | [diff] [blame] | 246 | |
Gerd Hoffmann | 0958b4c | 2009-10-26 15:56:45 +0100 | [diff] [blame] | 247 | /* handle legacy -usbdevice command line options */ |
| 248 | const char *usbdevice_name; |
| 249 | USBDevice *(*usbdevice_init)(const char *params); |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 250 | }; |
| 251 | |
Gerd Hoffmann | 0d86d2b | 2010-12-01 11:08:44 +0100 | [diff] [blame] | 252 | typedef struct USBPortOps { |
Gerd Hoffmann | 618c169 | 2010-12-01 11:27:05 +0100 | [diff] [blame] | 253 | void (*attach)(USBPort *port); |
| 254 | void (*detach)(USBPort *port); |
Hans de Goede | 4706ab6 | 2011-06-24 12:31:11 +0200 | [diff] [blame] | 255 | /* |
| 256 | * This gets called when a device downstream from the device attached to |
| 257 | * the port (iow attached through a hub) gets detached. |
| 258 | */ |
| 259 | void (*child_detach)(USBPort *port, USBDevice *child); |
Hans de Goede | d47e59b | 2011-06-21 11:52:28 +0200 | [diff] [blame] | 260 | void (*wakeup)(USBPort *port); |
| 261 | /* |
| 262 | * Note that port->dev will be different then the device from which |
| 263 | * the packet originated when a hub is involved, if you want the orginating |
| 264 | * device use p->owner |
| 265 | */ |
| 266 | void (*complete)(USBPort *port, USBPacket *p); |
Gerd Hoffmann | 0d86d2b | 2010-12-01 11:08:44 +0100 | [diff] [blame] | 267 | } USBPortOps; |
pbrook | 0d92ed3 | 2006-05-21 16:30:15 +0000 | [diff] [blame] | 268 | |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 269 | /* USB port on which a device can be connected */ |
| 270 | struct USBPort { |
bellard | a594cfb | 2005-11-06 16:13:29 +0000 | [diff] [blame] | 271 | USBDevice *dev; |
Gerd Hoffmann | 843d4e0 | 2010-12-03 17:30:13 +0100 | [diff] [blame] | 272 | int speedmask; |
Gerd Hoffmann | c7a2196 | 2010-12-10 11:37:45 +0100 | [diff] [blame] | 273 | char path[16]; |
Gerd Hoffmann | 0d86d2b | 2010-12-01 11:08:44 +0100 | [diff] [blame] | 274 | USBPortOps *ops; |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 275 | void *opaque; |
| 276 | int index; /* internal port index, may be used with the opaque */ |
Blue Swirl | 72cf2d4 | 2009-09-12 07:36:22 +0000 | [diff] [blame] | 277 | QTAILQ_ENTRY(USBPort) next; |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 278 | }; |
| 279 | |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 280 | typedef void USBCallback(USBPacket * packet, void *opaque); |
| 281 | |
| 282 | /* Structure used to hold information about an active USB packet. */ |
| 283 | struct USBPacket { |
| 284 | /* Data fields for use by the driver. */ |
| 285 | int pid; |
| 286 | uint8_t devaddr; |
| 287 | uint8_t devep; |
Gerd Hoffmann | 4f4321c | 2011-07-12 15:22:25 +0200 | [diff] [blame] | 288 | QEMUIOVector iov; |
| 289 | int result; /* transfer length or USB_RET_* status code */ |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 290 | /* Internal use by the USB layer. */ |
Gerd Hoffmann | 4ff658f | 2011-05-12 13:48:13 +0200 | [diff] [blame] | 291 | USBDevice *owner; |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 292 | }; |
| 293 | |
Gerd Hoffmann | 4f4321c | 2011-07-12 15:22:25 +0200 | [diff] [blame] | 294 | void usb_packet_init(USBPacket *p); |
| 295 | void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep); |
| 296 | void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len); |
| 297 | int usb_packet_map(USBPacket *p, QEMUSGList *sgl); |
| 298 | void usb_packet_unmap(USBPacket *p); |
| 299 | void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes); |
| 300 | void usb_packet_skip(USBPacket *p, size_t bytes); |
| 301 | void usb_packet_cleanup(USBPacket *p); |
| 302 | |
Gerd Hoffmann | 53aa8c0 | 2011-05-12 13:20:39 +0200 | [diff] [blame] | 303 | int usb_handle_packet(USBDevice *dev, USBPacket *p); |
Gerd Hoffmann | 4ff658f | 2011-05-12 13:48:13 +0200 | [diff] [blame] | 304 | void usb_packet_complete(USBDevice *dev, USBPacket *p); |
| 305 | void usb_cancel_packet(USBPacket * p); |
Gerd Hoffmann | 53aa8c0 | 2011-05-12 13:20:39 +0200 | [diff] [blame] | 306 | |
Gerd Hoffmann | 891fb2c | 2011-09-01 13:56:37 +0200 | [diff] [blame] | 307 | void usb_attach(USBPort *port); |
| 308 | void usb_detach(USBPort *port); |
Gerd Hoffmann | e0b8e72 | 2011-09-15 12:10:21 +0200 | [diff] [blame] | 309 | void usb_reset(USBPort *port); |
Gerd Hoffmann | 01eacab | 2010-12-01 11:32:45 +0100 | [diff] [blame] | 310 | void usb_wakeup(USBDevice *dev); |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 311 | int usb_generic_handle_packet(USBDevice *s, USBPacket *p); |
Hans de Goede | 50b7963 | 2011-02-02 17:36:29 +0100 | [diff] [blame] | 312 | void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p); |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 313 | int set_usb_string(uint8_t *buf, const char *str); |
pbrook | 4d611c9 | 2006-08-12 01:04:27 +0000 | [diff] [blame] | 314 | void usb_send_msg(USBDevice *dev, int msg); |
| 315 | |
bellard | bb36d47 | 2005-11-05 14:22:28 +0000 | [diff] [blame] | 316 | /* usb-linux.c */ |
bellard | a594cfb | 2005-11-06 16:13:29 +0000 | [diff] [blame] | 317 | USBDevice *usb_host_device_open(const char *devname); |
aliguori | 5d0c575 | 2008-09-14 01:07:41 +0000 | [diff] [blame] | 318 | int usb_host_device_close(const char *devname); |
aliguori | 376253e | 2009-03-05 23:01:23 +0000 | [diff] [blame] | 319 | void usb_host_info(Monitor *mon); |
bellard | 59ae540 | 2005-11-05 16:57:08 +0000 | [diff] [blame] | 320 | |
balrog | e6a6d5a | 2008-09-29 00:40:44 +0000 | [diff] [blame] | 321 | /* usb-bt.c */ |
| 322 | USBDevice *usb_bt_init(HCIInfo *hci); |
| 323 | |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 324 | /* usb ports of the VM */ |
| 325 | |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 326 | #define VM_USB_HUB_SIZE 8 |
| 327 | |
balrog | 942ac05 | 2008-04-22 03:15:10 +0000 | [diff] [blame] | 328 | /* usb-musb.c */ |
| 329 | enum musb_irq_source_e { |
| 330 | musb_irq_suspend = 0, |
| 331 | musb_irq_resume, |
| 332 | musb_irq_rst_babble, |
| 333 | musb_irq_sof, |
| 334 | musb_irq_connect, |
| 335 | musb_irq_disconnect, |
| 336 | musb_irq_vbus_request, |
| 337 | musb_irq_vbus_error, |
| 338 | musb_irq_rx, |
| 339 | musb_irq_tx, |
| 340 | musb_set_vbus, |
| 341 | musb_set_session, |
Peter Maydell | 9147b75 | 2011-08-31 21:49:39 +0100 | [diff] [blame] | 342 | /* Add new interrupts here */ |
| 343 | musb_irq_max, /* total number of interrupts defined */ |
balrog | 942ac05 | 2008-04-22 03:15:10 +0000 | [diff] [blame] | 344 | }; |
| 345 | |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 346 | typedef struct MUSBState MUSBState; |
Peter Maydell | 406c207 | 2011-08-31 21:49:40 +0100 | [diff] [blame] | 347 | MUSBState *musb_init(DeviceState *parent_device, int gpio_base); |
Juha Riihimäki | 5b1cdb4 | 2011-08-31 21:49:41 +0100 | [diff] [blame] | 348 | void musb_reset(MUSBState *s); |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 349 | uint32_t musb_core_intr_get(MUSBState *s); |
| 350 | void musb_core_intr_clear(MUSBState *s, uint32_t mask); |
| 351 | void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 352 | |
| 353 | /* usb-bus.c */ |
| 354 | |
| 355 | struct USBBus { |
| 356 | BusState qbus; |
Gerd Hoffmann | 07771f6 | 2011-05-23 17:37:12 +0200 | [diff] [blame] | 357 | USBBusOps *ops; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 358 | int busnr; |
| 359 | int nfree; |
| 360 | int nused; |
Blue Swirl | 72cf2d4 | 2009-09-12 07:36:22 +0000 | [diff] [blame] | 361 | QTAILQ_HEAD(, USBPort) free; |
| 362 | QTAILQ_HEAD(, USBPort) used; |
| 363 | QTAILQ_ENTRY(USBBus) next; |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 364 | }; |
| 365 | |
Gerd Hoffmann | 07771f6 | 2011-05-23 17:37:12 +0200 | [diff] [blame] | 366 | struct USBBusOps { |
Hans de Goede | ae60fea | 2011-06-24 11:29:56 +0200 | [diff] [blame] | 367 | int (*register_companion)(USBBus *bus, USBPort *ports[], |
| 368 | uint32_t portcount, uint32_t firstport); |
Gerd Hoffmann | 07771f6 | 2011-05-23 17:37:12 +0200 | [diff] [blame] | 369 | }; |
| 370 | |
| 371 | void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host); |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 372 | USBBus *usb_bus_find(int busnr); |
| 373 | void usb_qdev_register(USBDeviceInfo *info); |
| 374 | void usb_qdev_register_many(USBDeviceInfo *info); |
Gerd Hoffmann | a5d2f72 | 2009-08-31 14:24:00 +0200 | [diff] [blame] | 375 | USBDevice *usb_create(USBBus *bus, const char *name); |
Gerd Hoffmann | 806b602 | 2009-08-31 14:23:59 +0200 | [diff] [blame] | 376 | USBDevice *usb_create_simple(USBBus *bus, const char *name); |
Gerd Hoffmann | 0958b4c | 2009-10-26 15:56:45 +0100 | [diff] [blame] | 377 | USBDevice *usbdevice_create(const char *cmdline); |
Gerd Hoffmann | a5d2f72 | 2009-08-31 14:24:00 +0200 | [diff] [blame] | 378 | void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, |
Gerd Hoffmann | ace1318 | 2011-01-12 11:34:50 +0100 | [diff] [blame] | 379 | USBPortOps *ops, int speedmask); |
Hans de Goede | ae60fea | 2011-06-24 11:29:56 +0200 | [diff] [blame] | 380 | int usb_register_companion(const char *masterbus, USBPort *ports[], |
| 381 | uint32_t portcount, uint32_t firstport, |
| 382 | void *opaque, USBPortOps *ops, int speedmask); |
Gerd Hoffmann | c7a2196 | 2010-12-10 11:37:45 +0100 | [diff] [blame] | 383 | void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr); |
Gerd Hoffmann | a8e662b | 2009-09-25 21:42:39 +0200 | [diff] [blame] | 384 | void usb_unregister_port(USBBus *bus, USBPort *port); |
Gerd Hoffmann | 891fb2c | 2011-09-01 13:56:37 +0200 | [diff] [blame] | 385 | int usb_claim_port(USBDevice *dev); |
| 386 | void usb_release_port(USBDevice *dev); |
Gerd Hoffmann | a5d2f72 | 2009-08-31 14:24:00 +0200 | [diff] [blame] | 387 | int usb_device_attach(USBDevice *dev); |
Gerd Hoffmann | a8e662b | 2009-09-25 21:42:39 +0200 | [diff] [blame] | 388 | int usb_device_detach(USBDevice *dev); |
Gerd Hoffmann | a5d2f72 | 2009-08-31 14:24:00 +0200 | [diff] [blame] | 389 | int usb_device_delete_addr(int busnr, int addr); |
| 390 | |
| 391 | static inline USBBus *usb_bus_from_device(USBDevice *d) |
| 392 | { |
| 393 | return DO_UPCAST(USBBus, qbus, d->qdev.parent_bus); |
| 394 | } |