1f1ae32a1SGerd Hoffmann /* 2f1ae32a1SGerd Hoffmann * QEMU USB emulation 3f1ae32a1SGerd Hoffmann * 4f1ae32a1SGerd Hoffmann * Copyright (c) 2005 Fabrice Bellard 5f1ae32a1SGerd Hoffmann * 6f1ae32a1SGerd Hoffmann * 2008 Generic packet handler rewrite by Max Krasnyansky 7f1ae32a1SGerd Hoffmann * 8f1ae32a1SGerd Hoffmann * Permission is hereby granted, free of charge, to any person obtaining a copy 9f1ae32a1SGerd Hoffmann * of this software and associated documentation files (the "Software"), to deal 10f1ae32a1SGerd Hoffmann * in the Software without restriction, including without limitation the rights 11f1ae32a1SGerd Hoffmann * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12f1ae32a1SGerd Hoffmann * copies of the Software, and to permit persons to whom the Software is 13f1ae32a1SGerd Hoffmann * furnished to do so, subject to the following conditions: 14f1ae32a1SGerd Hoffmann * 15f1ae32a1SGerd Hoffmann * The above copyright notice and this permission notice shall be included in 16f1ae32a1SGerd Hoffmann * all copies or substantial portions of the Software. 17f1ae32a1SGerd Hoffmann * 18f1ae32a1SGerd Hoffmann * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19f1ae32a1SGerd Hoffmann * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20f1ae32a1SGerd Hoffmann * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21f1ae32a1SGerd Hoffmann * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22f1ae32a1SGerd Hoffmann * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23f1ae32a1SGerd Hoffmann * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24f1ae32a1SGerd Hoffmann * THE SOFTWARE. 25f1ae32a1SGerd Hoffmann */ 26f1ae32a1SGerd Hoffmann #include "qemu-common.h" 27f1ae32a1SGerd Hoffmann #include "hw/usb.h" 28f1ae32a1SGerd Hoffmann #include "iov.h" 29f1ae32a1SGerd Hoffmann #include "trace.h" 30f1ae32a1SGerd Hoffmann 31f1ae32a1SGerd Hoffmann void usb_attach(USBPort *port) 32f1ae32a1SGerd Hoffmann { 33f1ae32a1SGerd Hoffmann USBDevice *dev = port->dev; 34f1ae32a1SGerd Hoffmann 35f1ae32a1SGerd Hoffmann assert(dev != NULL); 36f1ae32a1SGerd Hoffmann assert(dev->attached); 37f1ae32a1SGerd Hoffmann assert(dev->state == USB_STATE_NOTATTACHED); 38f1ae32a1SGerd Hoffmann port->ops->attach(port); 39f1ae32a1SGerd Hoffmann dev->state = USB_STATE_ATTACHED; 40f1ae32a1SGerd Hoffmann usb_device_handle_attach(dev); 41f1ae32a1SGerd Hoffmann } 42f1ae32a1SGerd Hoffmann 43f1ae32a1SGerd Hoffmann void usb_detach(USBPort *port) 44f1ae32a1SGerd Hoffmann { 45f1ae32a1SGerd Hoffmann USBDevice *dev = port->dev; 46f1ae32a1SGerd Hoffmann 47f1ae32a1SGerd Hoffmann assert(dev != NULL); 48f1ae32a1SGerd Hoffmann assert(dev->state != USB_STATE_NOTATTACHED); 49f1ae32a1SGerd Hoffmann port->ops->detach(port); 50f1ae32a1SGerd Hoffmann dev->state = USB_STATE_NOTATTACHED; 51f1ae32a1SGerd Hoffmann } 52f1ae32a1SGerd Hoffmann 53f1ae32a1SGerd Hoffmann void usb_port_reset(USBPort *port) 54f1ae32a1SGerd Hoffmann { 55f1ae32a1SGerd Hoffmann USBDevice *dev = port->dev; 56f1ae32a1SGerd Hoffmann 57f1ae32a1SGerd Hoffmann assert(dev != NULL); 58f1ae32a1SGerd Hoffmann usb_detach(port); 59f1ae32a1SGerd Hoffmann usb_attach(port); 60f1ae32a1SGerd Hoffmann usb_device_reset(dev); 61f1ae32a1SGerd Hoffmann } 62f1ae32a1SGerd Hoffmann 63f1ae32a1SGerd Hoffmann void usb_device_reset(USBDevice *dev) 64f1ae32a1SGerd Hoffmann { 65f1ae32a1SGerd Hoffmann if (dev == NULL || !dev->attached) { 66f1ae32a1SGerd Hoffmann return; 67f1ae32a1SGerd Hoffmann } 68f1ae32a1SGerd Hoffmann dev->remote_wakeup = 0; 69f1ae32a1SGerd Hoffmann dev->addr = 0; 70f1ae32a1SGerd Hoffmann dev->state = USB_STATE_DEFAULT; 71f1ae32a1SGerd Hoffmann usb_device_handle_reset(dev); 72f1ae32a1SGerd Hoffmann } 73f1ae32a1SGerd Hoffmann 74f1ae32a1SGerd Hoffmann void usb_wakeup(USBEndpoint *ep) 75f1ae32a1SGerd Hoffmann { 76f1ae32a1SGerd Hoffmann USBDevice *dev = ep->dev; 77f1ae32a1SGerd Hoffmann USBBus *bus = usb_bus_from_device(dev); 78f1ae32a1SGerd Hoffmann 79f1ae32a1SGerd Hoffmann if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) { 80f1ae32a1SGerd Hoffmann dev->port->ops->wakeup(dev->port); 81f1ae32a1SGerd Hoffmann } 82f1ae32a1SGerd Hoffmann if (bus->ops->wakeup_endpoint) { 83f1ae32a1SGerd Hoffmann bus->ops->wakeup_endpoint(bus, ep); 84f1ae32a1SGerd Hoffmann } 85f1ae32a1SGerd Hoffmann } 86f1ae32a1SGerd Hoffmann 87f1ae32a1SGerd Hoffmann /**********************/ 88f1ae32a1SGerd Hoffmann 89f1ae32a1SGerd Hoffmann /* generic USB device helpers (you are not forced to use them when 90f1ae32a1SGerd Hoffmann writing your USB device driver, but they help handling the 91f1ae32a1SGerd Hoffmann protocol) 92f1ae32a1SGerd Hoffmann */ 93f1ae32a1SGerd Hoffmann 94f1ae32a1SGerd Hoffmann #define SETUP_STATE_IDLE 0 95f1ae32a1SGerd Hoffmann #define SETUP_STATE_SETUP 1 96f1ae32a1SGerd Hoffmann #define SETUP_STATE_DATA 2 97f1ae32a1SGerd Hoffmann #define SETUP_STATE_ACK 3 98f1ae32a1SGerd Hoffmann #define SETUP_STATE_PARAM 4 99f1ae32a1SGerd Hoffmann 100f1ae32a1SGerd Hoffmann static int do_token_setup(USBDevice *s, USBPacket *p) 101f1ae32a1SGerd Hoffmann { 102f1ae32a1SGerd Hoffmann int request, value, index; 103f1ae32a1SGerd Hoffmann int ret = 0; 104f1ae32a1SGerd Hoffmann 105f1ae32a1SGerd Hoffmann if (p->iov.size != 8) { 106f1ae32a1SGerd Hoffmann return USB_RET_STALL; 107f1ae32a1SGerd Hoffmann } 108f1ae32a1SGerd Hoffmann 109f1ae32a1SGerd Hoffmann usb_packet_copy(p, s->setup_buf, p->iov.size); 110f1ae32a1SGerd Hoffmann s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; 111f1ae32a1SGerd Hoffmann s->setup_index = 0; 112f1ae32a1SGerd Hoffmann 113f1ae32a1SGerd Hoffmann request = (s->setup_buf[0] << 8) | s->setup_buf[1]; 114f1ae32a1SGerd Hoffmann value = (s->setup_buf[3] << 8) | s->setup_buf[2]; 115f1ae32a1SGerd Hoffmann index = (s->setup_buf[5] << 8) | s->setup_buf[4]; 116f1ae32a1SGerd Hoffmann 117f1ae32a1SGerd Hoffmann if (s->setup_buf[0] & USB_DIR_IN) { 118f1ae32a1SGerd Hoffmann ret = usb_device_handle_control(s, p, request, value, index, 119f1ae32a1SGerd Hoffmann s->setup_len, s->data_buf); 120f1ae32a1SGerd Hoffmann if (ret == USB_RET_ASYNC) { 121f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_SETUP; 122f1ae32a1SGerd Hoffmann return USB_RET_ASYNC; 123f1ae32a1SGerd Hoffmann } 124f1ae32a1SGerd Hoffmann if (ret < 0) 125f1ae32a1SGerd Hoffmann return ret; 126f1ae32a1SGerd Hoffmann 127f1ae32a1SGerd Hoffmann if (ret < s->setup_len) 128f1ae32a1SGerd Hoffmann s->setup_len = ret; 129f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_DATA; 130f1ae32a1SGerd Hoffmann } else { 131f1ae32a1SGerd Hoffmann if (s->setup_len > sizeof(s->data_buf)) { 132f1ae32a1SGerd Hoffmann fprintf(stderr, 133f1ae32a1SGerd Hoffmann "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", 134f1ae32a1SGerd Hoffmann s->setup_len, sizeof(s->data_buf)); 135f1ae32a1SGerd Hoffmann return USB_RET_STALL; 136f1ae32a1SGerd Hoffmann } 137f1ae32a1SGerd Hoffmann if (s->setup_len == 0) 138f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_ACK; 139f1ae32a1SGerd Hoffmann else 140f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_DATA; 141f1ae32a1SGerd Hoffmann } 142f1ae32a1SGerd Hoffmann 143f1ae32a1SGerd Hoffmann return ret; 144f1ae32a1SGerd Hoffmann } 145f1ae32a1SGerd Hoffmann 146f1ae32a1SGerd Hoffmann static int do_token_in(USBDevice *s, USBPacket *p) 147f1ae32a1SGerd Hoffmann { 148f1ae32a1SGerd Hoffmann int request, value, index; 149f1ae32a1SGerd Hoffmann int ret = 0; 150f1ae32a1SGerd Hoffmann 151f1ae32a1SGerd Hoffmann assert(p->ep->nr == 0); 152f1ae32a1SGerd Hoffmann 153f1ae32a1SGerd Hoffmann request = (s->setup_buf[0] << 8) | s->setup_buf[1]; 154f1ae32a1SGerd Hoffmann value = (s->setup_buf[3] << 8) | s->setup_buf[2]; 155f1ae32a1SGerd Hoffmann index = (s->setup_buf[5] << 8) | s->setup_buf[4]; 156f1ae32a1SGerd Hoffmann 157f1ae32a1SGerd Hoffmann switch(s->setup_state) { 158f1ae32a1SGerd Hoffmann case SETUP_STATE_ACK: 159f1ae32a1SGerd Hoffmann if (!(s->setup_buf[0] & USB_DIR_IN)) { 160f1ae32a1SGerd Hoffmann ret = usb_device_handle_control(s, p, request, value, index, 161f1ae32a1SGerd Hoffmann s->setup_len, s->data_buf); 162f1ae32a1SGerd Hoffmann if (ret == USB_RET_ASYNC) { 163f1ae32a1SGerd Hoffmann return USB_RET_ASYNC; 164f1ae32a1SGerd Hoffmann } 165f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_IDLE; 166f1ae32a1SGerd Hoffmann if (ret > 0) 167f1ae32a1SGerd Hoffmann return 0; 168f1ae32a1SGerd Hoffmann return ret; 169f1ae32a1SGerd Hoffmann } 170f1ae32a1SGerd Hoffmann 171f1ae32a1SGerd Hoffmann /* return 0 byte */ 172f1ae32a1SGerd Hoffmann return 0; 173f1ae32a1SGerd Hoffmann 174f1ae32a1SGerd Hoffmann case SETUP_STATE_DATA: 175f1ae32a1SGerd Hoffmann if (s->setup_buf[0] & USB_DIR_IN) { 176f1ae32a1SGerd Hoffmann int len = s->setup_len - s->setup_index; 177f1ae32a1SGerd Hoffmann if (len > p->iov.size) { 178f1ae32a1SGerd Hoffmann len = p->iov.size; 179f1ae32a1SGerd Hoffmann } 180f1ae32a1SGerd Hoffmann usb_packet_copy(p, s->data_buf + s->setup_index, len); 181f1ae32a1SGerd Hoffmann s->setup_index += len; 182f1ae32a1SGerd Hoffmann if (s->setup_index >= s->setup_len) 183f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_ACK; 184f1ae32a1SGerd Hoffmann return len; 185f1ae32a1SGerd Hoffmann } 186f1ae32a1SGerd Hoffmann 187f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_IDLE; 188f1ae32a1SGerd Hoffmann return USB_RET_STALL; 189f1ae32a1SGerd Hoffmann 190f1ae32a1SGerd Hoffmann default: 191f1ae32a1SGerd Hoffmann return USB_RET_STALL; 192f1ae32a1SGerd Hoffmann } 193f1ae32a1SGerd Hoffmann } 194f1ae32a1SGerd Hoffmann 195f1ae32a1SGerd Hoffmann static int do_token_out(USBDevice *s, USBPacket *p) 196f1ae32a1SGerd Hoffmann { 197f1ae32a1SGerd Hoffmann assert(p->ep->nr == 0); 198f1ae32a1SGerd Hoffmann 199f1ae32a1SGerd Hoffmann switch(s->setup_state) { 200f1ae32a1SGerd Hoffmann case SETUP_STATE_ACK: 201f1ae32a1SGerd Hoffmann if (s->setup_buf[0] & USB_DIR_IN) { 202f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_IDLE; 203f1ae32a1SGerd Hoffmann /* transfer OK */ 204f1ae32a1SGerd Hoffmann } else { 205f1ae32a1SGerd Hoffmann /* ignore additional output */ 206f1ae32a1SGerd Hoffmann } 207f1ae32a1SGerd Hoffmann return 0; 208f1ae32a1SGerd Hoffmann 209f1ae32a1SGerd Hoffmann case SETUP_STATE_DATA: 210f1ae32a1SGerd Hoffmann if (!(s->setup_buf[0] & USB_DIR_IN)) { 211f1ae32a1SGerd Hoffmann int len = s->setup_len - s->setup_index; 212f1ae32a1SGerd Hoffmann if (len > p->iov.size) { 213f1ae32a1SGerd Hoffmann len = p->iov.size; 214f1ae32a1SGerd Hoffmann } 215f1ae32a1SGerd Hoffmann usb_packet_copy(p, s->data_buf + s->setup_index, len); 216f1ae32a1SGerd Hoffmann s->setup_index += len; 217f1ae32a1SGerd Hoffmann if (s->setup_index >= s->setup_len) 218f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_ACK; 219f1ae32a1SGerd Hoffmann return len; 220f1ae32a1SGerd Hoffmann } 221f1ae32a1SGerd Hoffmann 222f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_IDLE; 223f1ae32a1SGerd Hoffmann return USB_RET_STALL; 224f1ae32a1SGerd Hoffmann 225f1ae32a1SGerd Hoffmann default: 226f1ae32a1SGerd Hoffmann return USB_RET_STALL; 227f1ae32a1SGerd Hoffmann } 228f1ae32a1SGerd Hoffmann } 229f1ae32a1SGerd Hoffmann 230f1ae32a1SGerd Hoffmann static int do_parameter(USBDevice *s, USBPacket *p) 231f1ae32a1SGerd Hoffmann { 232f1ae32a1SGerd Hoffmann int request, value, index; 233f1ae32a1SGerd Hoffmann int i, ret = 0; 234f1ae32a1SGerd Hoffmann 235f1ae32a1SGerd Hoffmann for (i = 0; i < 8; i++) { 236f1ae32a1SGerd Hoffmann s->setup_buf[i] = p->parameter >> (i*8); 237f1ae32a1SGerd Hoffmann } 238f1ae32a1SGerd Hoffmann 239f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_PARAM; 240f1ae32a1SGerd Hoffmann s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; 241f1ae32a1SGerd Hoffmann s->setup_index = 0; 242f1ae32a1SGerd Hoffmann 243f1ae32a1SGerd Hoffmann request = (s->setup_buf[0] << 8) | s->setup_buf[1]; 244f1ae32a1SGerd Hoffmann value = (s->setup_buf[3] << 8) | s->setup_buf[2]; 245f1ae32a1SGerd Hoffmann index = (s->setup_buf[5] << 8) | s->setup_buf[4]; 246f1ae32a1SGerd Hoffmann 247f1ae32a1SGerd Hoffmann if (s->setup_len > sizeof(s->data_buf)) { 248f1ae32a1SGerd Hoffmann fprintf(stderr, 249f1ae32a1SGerd Hoffmann "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", 250f1ae32a1SGerd Hoffmann s->setup_len, sizeof(s->data_buf)); 251f1ae32a1SGerd Hoffmann return USB_RET_STALL; 252f1ae32a1SGerd Hoffmann } 253f1ae32a1SGerd Hoffmann 254f1ae32a1SGerd Hoffmann if (p->pid == USB_TOKEN_OUT) { 255f1ae32a1SGerd Hoffmann usb_packet_copy(p, s->data_buf, s->setup_len); 256f1ae32a1SGerd Hoffmann } 257f1ae32a1SGerd Hoffmann 258f1ae32a1SGerd Hoffmann ret = usb_device_handle_control(s, p, request, value, index, 259f1ae32a1SGerd Hoffmann s->setup_len, s->data_buf); 260f1ae32a1SGerd Hoffmann if (ret < 0) { 261f1ae32a1SGerd Hoffmann return ret; 262f1ae32a1SGerd Hoffmann } 263f1ae32a1SGerd Hoffmann 264f1ae32a1SGerd Hoffmann if (ret < s->setup_len) { 265f1ae32a1SGerd Hoffmann s->setup_len = ret; 266f1ae32a1SGerd Hoffmann } 267f1ae32a1SGerd Hoffmann if (p->pid == USB_TOKEN_IN) { 268f1ae32a1SGerd Hoffmann usb_packet_copy(p, s->data_buf, s->setup_len); 269f1ae32a1SGerd Hoffmann } 270f1ae32a1SGerd Hoffmann 271f1ae32a1SGerd Hoffmann return ret; 272f1ae32a1SGerd Hoffmann } 273f1ae32a1SGerd Hoffmann 274f1ae32a1SGerd Hoffmann /* ctrl complete function for devices which use usb_generic_handle_packet and 275f1ae32a1SGerd Hoffmann may return USB_RET_ASYNC from their handle_control callback. Device code 276f1ae32a1SGerd Hoffmann which does this *must* call this function instead of the normal 277f1ae32a1SGerd Hoffmann usb_packet_complete to complete their async control packets. */ 278f1ae32a1SGerd Hoffmann void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p) 279f1ae32a1SGerd Hoffmann { 280f1ae32a1SGerd Hoffmann if (p->result < 0) { 281f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_IDLE; 282f1ae32a1SGerd Hoffmann } 283f1ae32a1SGerd Hoffmann 284f1ae32a1SGerd Hoffmann switch (s->setup_state) { 285f1ae32a1SGerd Hoffmann case SETUP_STATE_SETUP: 286f1ae32a1SGerd Hoffmann if (p->result < s->setup_len) { 287f1ae32a1SGerd Hoffmann s->setup_len = p->result; 288f1ae32a1SGerd Hoffmann } 289f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_DATA; 290f1ae32a1SGerd Hoffmann p->result = 8; 291f1ae32a1SGerd Hoffmann break; 292f1ae32a1SGerd Hoffmann 293f1ae32a1SGerd Hoffmann case SETUP_STATE_ACK: 294f1ae32a1SGerd Hoffmann s->setup_state = SETUP_STATE_IDLE; 295f1ae32a1SGerd Hoffmann p->result = 0; 296f1ae32a1SGerd Hoffmann break; 297f1ae32a1SGerd Hoffmann 298f1ae32a1SGerd Hoffmann case SETUP_STATE_PARAM: 299f1ae32a1SGerd Hoffmann if (p->result < s->setup_len) { 300f1ae32a1SGerd Hoffmann s->setup_len = p->result; 301f1ae32a1SGerd Hoffmann } 302f1ae32a1SGerd Hoffmann if (p->pid == USB_TOKEN_IN) { 303f1ae32a1SGerd Hoffmann p->result = 0; 304f1ae32a1SGerd Hoffmann usb_packet_copy(p, s->data_buf, s->setup_len); 305f1ae32a1SGerd Hoffmann } 306f1ae32a1SGerd Hoffmann break; 307f1ae32a1SGerd Hoffmann 308f1ae32a1SGerd Hoffmann default: 309f1ae32a1SGerd Hoffmann break; 310f1ae32a1SGerd Hoffmann } 311f1ae32a1SGerd Hoffmann usb_packet_complete(s, p); 312f1ae32a1SGerd Hoffmann } 313f1ae32a1SGerd Hoffmann 314f1ae32a1SGerd Hoffmann /* XXX: fix overflow */ 315f1ae32a1SGerd Hoffmann int set_usb_string(uint8_t *buf, const char *str) 316f1ae32a1SGerd Hoffmann { 317f1ae32a1SGerd Hoffmann int len, i; 318f1ae32a1SGerd Hoffmann uint8_t *q; 319f1ae32a1SGerd Hoffmann 320f1ae32a1SGerd Hoffmann q = buf; 321f1ae32a1SGerd Hoffmann len = strlen(str); 322f1ae32a1SGerd Hoffmann *q++ = 2 * len + 2; 323f1ae32a1SGerd Hoffmann *q++ = 3; 324f1ae32a1SGerd Hoffmann for(i = 0; i < len; i++) { 325f1ae32a1SGerd Hoffmann *q++ = str[i]; 326f1ae32a1SGerd Hoffmann *q++ = 0; 327f1ae32a1SGerd Hoffmann } 328f1ae32a1SGerd Hoffmann return q - buf; 329f1ae32a1SGerd Hoffmann } 330f1ae32a1SGerd Hoffmann 331f1ae32a1SGerd Hoffmann USBDevice *usb_find_device(USBPort *port, uint8_t addr) 332f1ae32a1SGerd Hoffmann { 333f1ae32a1SGerd Hoffmann USBDevice *dev = port->dev; 334f1ae32a1SGerd Hoffmann 335f1ae32a1SGerd Hoffmann if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) { 336f1ae32a1SGerd Hoffmann return NULL; 337f1ae32a1SGerd Hoffmann } 338f1ae32a1SGerd Hoffmann if (dev->addr == addr) { 339f1ae32a1SGerd Hoffmann return dev; 340f1ae32a1SGerd Hoffmann } 341f1ae32a1SGerd Hoffmann return usb_device_find_device(dev, addr); 342f1ae32a1SGerd Hoffmann } 343f1ae32a1SGerd Hoffmann 344f1ae32a1SGerd Hoffmann static int usb_process_one(USBPacket *p) 345f1ae32a1SGerd Hoffmann { 346f1ae32a1SGerd Hoffmann USBDevice *dev = p->ep->dev; 347f1ae32a1SGerd Hoffmann 348f1ae32a1SGerd Hoffmann if (p->ep->nr == 0) { 349f1ae32a1SGerd Hoffmann /* control pipe */ 350f1ae32a1SGerd Hoffmann if (p->parameter) { 351f1ae32a1SGerd Hoffmann return do_parameter(dev, p); 352f1ae32a1SGerd Hoffmann } 353f1ae32a1SGerd Hoffmann switch (p->pid) { 354f1ae32a1SGerd Hoffmann case USB_TOKEN_SETUP: 355f1ae32a1SGerd Hoffmann return do_token_setup(dev, p); 356f1ae32a1SGerd Hoffmann case USB_TOKEN_IN: 357f1ae32a1SGerd Hoffmann return do_token_in(dev, p); 358f1ae32a1SGerd Hoffmann case USB_TOKEN_OUT: 359f1ae32a1SGerd Hoffmann return do_token_out(dev, p); 360f1ae32a1SGerd Hoffmann default: 361f1ae32a1SGerd Hoffmann return USB_RET_STALL; 362f1ae32a1SGerd Hoffmann } 363f1ae32a1SGerd Hoffmann } else { 364f1ae32a1SGerd Hoffmann /* data pipe */ 365f1ae32a1SGerd Hoffmann return usb_device_handle_data(dev, p); 366f1ae32a1SGerd Hoffmann } 367f1ae32a1SGerd Hoffmann } 368f1ae32a1SGerd Hoffmann 369f1ae32a1SGerd Hoffmann /* Hand over a packet to a device for processing. Return value 370f1ae32a1SGerd Hoffmann USB_RET_ASYNC indicates the processing isn't finished yet, the 371f1ae32a1SGerd Hoffmann driver will call usb_packet_complete() when done processing it. */ 372f1ae32a1SGerd Hoffmann int usb_handle_packet(USBDevice *dev, USBPacket *p) 373f1ae32a1SGerd Hoffmann { 374f1ae32a1SGerd Hoffmann int ret; 375f1ae32a1SGerd Hoffmann 376f1ae32a1SGerd Hoffmann if (dev == NULL) { 377f1ae32a1SGerd Hoffmann return USB_RET_NODEV; 378f1ae32a1SGerd Hoffmann } 379f1ae32a1SGerd Hoffmann assert(dev == p->ep->dev); 380f1ae32a1SGerd Hoffmann assert(dev->state == USB_STATE_DEFAULT); 3815ac2731cSGerd Hoffmann usb_packet_check_state(p, USB_PACKET_SETUP); 382f1ae32a1SGerd Hoffmann assert(p->ep != NULL); 383f1ae32a1SGerd Hoffmann 384f1ae32a1SGerd Hoffmann if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { 385f1ae32a1SGerd Hoffmann ret = usb_process_one(p); 386f1ae32a1SGerd Hoffmann if (ret == USB_RET_ASYNC) { 387f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_ASYNC); 388f1ae32a1SGerd Hoffmann QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); 389f1ae32a1SGerd Hoffmann } else { 390f1ae32a1SGerd Hoffmann p->result = ret; 391f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_COMPLETE); 392f1ae32a1SGerd Hoffmann } 393f1ae32a1SGerd Hoffmann } else { 394f1ae32a1SGerd Hoffmann ret = USB_RET_ASYNC; 395f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_QUEUED); 396f1ae32a1SGerd Hoffmann QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); 397f1ae32a1SGerd Hoffmann } 398f1ae32a1SGerd Hoffmann return ret; 399f1ae32a1SGerd Hoffmann } 400f1ae32a1SGerd Hoffmann 401f1ae32a1SGerd Hoffmann /* Notify the controller that an async packet is complete. This should only 402f1ae32a1SGerd Hoffmann be called for packets previously deferred by returning USB_RET_ASYNC from 403f1ae32a1SGerd Hoffmann handle_packet. */ 404f1ae32a1SGerd Hoffmann void usb_packet_complete(USBDevice *dev, USBPacket *p) 405f1ae32a1SGerd Hoffmann { 406f1ae32a1SGerd Hoffmann USBEndpoint *ep = p->ep; 407f1ae32a1SGerd Hoffmann int ret; 408f1ae32a1SGerd Hoffmann 4095ac2731cSGerd Hoffmann usb_packet_check_state(p, USB_PACKET_ASYNC); 410f1ae32a1SGerd Hoffmann assert(QTAILQ_FIRST(&ep->queue) == p); 411f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_COMPLETE); 412f1ae32a1SGerd Hoffmann QTAILQ_REMOVE(&ep->queue, p, queue); 413f1ae32a1SGerd Hoffmann dev->port->ops->complete(dev->port, p); 414f1ae32a1SGerd Hoffmann 415f1ae32a1SGerd Hoffmann while (!QTAILQ_EMPTY(&ep->queue)) { 416f1ae32a1SGerd Hoffmann p = QTAILQ_FIRST(&ep->queue); 417f1ae32a1SGerd Hoffmann if (p->state == USB_PACKET_ASYNC) { 418f1ae32a1SGerd Hoffmann break; 419f1ae32a1SGerd Hoffmann } 4205ac2731cSGerd Hoffmann usb_packet_check_state(p, USB_PACKET_QUEUED); 421f1ae32a1SGerd Hoffmann ret = usb_process_one(p); 422f1ae32a1SGerd Hoffmann if (ret == USB_RET_ASYNC) { 423f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_ASYNC); 424f1ae32a1SGerd Hoffmann break; 425f1ae32a1SGerd Hoffmann } 426f1ae32a1SGerd Hoffmann p->result = ret; 427f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_COMPLETE); 428f1ae32a1SGerd Hoffmann QTAILQ_REMOVE(&ep->queue, p, queue); 429f1ae32a1SGerd Hoffmann dev->port->ops->complete(dev->port, p); 430f1ae32a1SGerd Hoffmann } 431f1ae32a1SGerd Hoffmann } 432f1ae32a1SGerd Hoffmann 433f1ae32a1SGerd Hoffmann /* Cancel an active packet. The packed must have been deferred by 434f1ae32a1SGerd Hoffmann returning USB_RET_ASYNC from handle_packet, and not yet 435f1ae32a1SGerd Hoffmann completed. */ 436f1ae32a1SGerd Hoffmann void usb_cancel_packet(USBPacket * p) 437f1ae32a1SGerd Hoffmann { 438f1ae32a1SGerd Hoffmann bool callback = (p->state == USB_PACKET_ASYNC); 439f1ae32a1SGerd Hoffmann assert(usb_packet_is_inflight(p)); 440f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_CANCELED); 441f1ae32a1SGerd Hoffmann QTAILQ_REMOVE(&p->ep->queue, p, queue); 442f1ae32a1SGerd Hoffmann if (callback) { 443f1ae32a1SGerd Hoffmann usb_device_cancel_packet(p->ep->dev, p); 444f1ae32a1SGerd Hoffmann } 445f1ae32a1SGerd Hoffmann } 446f1ae32a1SGerd Hoffmann 447f1ae32a1SGerd Hoffmann 448f1ae32a1SGerd Hoffmann void usb_packet_init(USBPacket *p) 449f1ae32a1SGerd Hoffmann { 450f1ae32a1SGerd Hoffmann qemu_iovec_init(&p->iov, 1); 451f1ae32a1SGerd Hoffmann } 452f1ae32a1SGerd Hoffmann 4535ac2731cSGerd Hoffmann static const char *usb_packet_state_name(USBPacketState state) 454f1ae32a1SGerd Hoffmann { 455f1ae32a1SGerd Hoffmann static const char *name[] = { 456f1ae32a1SGerd Hoffmann [USB_PACKET_UNDEFINED] = "undef", 457f1ae32a1SGerd Hoffmann [USB_PACKET_SETUP] = "setup", 458f1ae32a1SGerd Hoffmann [USB_PACKET_QUEUED] = "queued", 459f1ae32a1SGerd Hoffmann [USB_PACKET_ASYNC] = "async", 460f1ae32a1SGerd Hoffmann [USB_PACKET_COMPLETE] = "complete", 461f1ae32a1SGerd Hoffmann [USB_PACKET_CANCELED] = "canceled", 462f1ae32a1SGerd Hoffmann }; 4635ac2731cSGerd Hoffmann if (state < ARRAY_SIZE(name)) { 4645ac2731cSGerd Hoffmann return name[state]; 4655ac2731cSGerd Hoffmann } 4665ac2731cSGerd Hoffmann return "INVALID"; 4675ac2731cSGerd Hoffmann } 4685ac2731cSGerd Hoffmann 4695ac2731cSGerd Hoffmann void usb_packet_check_state(USBPacket *p, USBPacketState expected) 4705ac2731cSGerd Hoffmann { 4715ac2731cSGerd Hoffmann USBDevice *dev; 4725ac2731cSGerd Hoffmann USBBus *bus; 4735ac2731cSGerd Hoffmann 4745ac2731cSGerd Hoffmann if (p->state == expected) { 4755ac2731cSGerd Hoffmann return; 4765ac2731cSGerd Hoffmann } 4775ac2731cSGerd Hoffmann dev = p->ep->dev; 4785ac2731cSGerd Hoffmann bus = usb_bus_from_device(dev); 4795ac2731cSGerd Hoffmann trace_usb_packet_state_fault(bus->busnr, dev->port->path, p->ep->nr, p, 4805ac2731cSGerd Hoffmann usb_packet_state_name(p->state), 4815ac2731cSGerd Hoffmann usb_packet_state_name(expected)); 4825ac2731cSGerd Hoffmann assert(!"usb packet state check failed"); 4835ac2731cSGerd Hoffmann } 4845ac2731cSGerd Hoffmann 4855ac2731cSGerd Hoffmann void usb_packet_set_state(USBPacket *p, USBPacketState state) 4865ac2731cSGerd Hoffmann { 487*f5bf14bfSGerd Hoffmann if (p->ep) { 488f1ae32a1SGerd Hoffmann USBDevice *dev = p->ep->dev; 489f1ae32a1SGerd Hoffmann USBBus *bus = usb_bus_from_device(dev); 4905ac2731cSGerd Hoffmann trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, p, 4915ac2731cSGerd Hoffmann usb_packet_state_name(p->state), 4925ac2731cSGerd Hoffmann usb_packet_state_name(state)); 493*f5bf14bfSGerd Hoffmann } else { 494*f5bf14bfSGerd Hoffmann trace_usb_packet_state_change(-1, "", -1, p, 495*f5bf14bfSGerd Hoffmann usb_packet_state_name(p->state), 496*f5bf14bfSGerd Hoffmann usb_packet_state_name(state)); 497*f5bf14bfSGerd Hoffmann } 498f1ae32a1SGerd Hoffmann p->state = state; 499f1ae32a1SGerd Hoffmann } 500f1ae32a1SGerd Hoffmann 501f1ae32a1SGerd Hoffmann void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep) 502f1ae32a1SGerd Hoffmann { 503f1ae32a1SGerd Hoffmann assert(!usb_packet_is_inflight(p)); 504f1ae32a1SGerd Hoffmann p->pid = pid; 505f1ae32a1SGerd Hoffmann p->ep = ep; 506f1ae32a1SGerd Hoffmann p->result = 0; 507f1ae32a1SGerd Hoffmann p->parameter = 0; 508f1ae32a1SGerd Hoffmann qemu_iovec_reset(&p->iov); 509f1ae32a1SGerd Hoffmann usb_packet_set_state(p, USB_PACKET_SETUP); 510f1ae32a1SGerd Hoffmann } 511f1ae32a1SGerd Hoffmann 512f1ae32a1SGerd Hoffmann void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len) 513f1ae32a1SGerd Hoffmann { 514f1ae32a1SGerd Hoffmann qemu_iovec_add(&p->iov, ptr, len); 515f1ae32a1SGerd Hoffmann } 516f1ae32a1SGerd Hoffmann 517f1ae32a1SGerd Hoffmann void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes) 518f1ae32a1SGerd Hoffmann { 519f1ae32a1SGerd Hoffmann assert(p->result >= 0); 520f1ae32a1SGerd Hoffmann assert(p->result + bytes <= p->iov.size); 521f1ae32a1SGerd Hoffmann switch (p->pid) { 522f1ae32a1SGerd Hoffmann case USB_TOKEN_SETUP: 523f1ae32a1SGerd Hoffmann case USB_TOKEN_OUT: 524f1ae32a1SGerd Hoffmann iov_to_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes); 525f1ae32a1SGerd Hoffmann break; 526f1ae32a1SGerd Hoffmann case USB_TOKEN_IN: 527f1ae32a1SGerd Hoffmann iov_from_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes); 528f1ae32a1SGerd Hoffmann break; 529f1ae32a1SGerd Hoffmann default: 530f1ae32a1SGerd Hoffmann fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid); 531f1ae32a1SGerd Hoffmann abort(); 532f1ae32a1SGerd Hoffmann } 533f1ae32a1SGerd Hoffmann p->result += bytes; 534f1ae32a1SGerd Hoffmann } 535f1ae32a1SGerd Hoffmann 536f1ae32a1SGerd Hoffmann void usb_packet_skip(USBPacket *p, size_t bytes) 537f1ae32a1SGerd Hoffmann { 538f1ae32a1SGerd Hoffmann assert(p->result >= 0); 539f1ae32a1SGerd Hoffmann assert(p->result + bytes <= p->iov.size); 540f1ae32a1SGerd Hoffmann if (p->pid == USB_TOKEN_IN) { 541f1ae32a1SGerd Hoffmann iov_clear(p->iov.iov, p->iov.niov, p->result, bytes); 542f1ae32a1SGerd Hoffmann } 543f1ae32a1SGerd Hoffmann p->result += bytes; 544f1ae32a1SGerd Hoffmann } 545f1ae32a1SGerd Hoffmann 546f1ae32a1SGerd Hoffmann void usb_packet_cleanup(USBPacket *p) 547f1ae32a1SGerd Hoffmann { 548f1ae32a1SGerd Hoffmann assert(!usb_packet_is_inflight(p)); 549f1ae32a1SGerd Hoffmann qemu_iovec_destroy(&p->iov); 550f1ae32a1SGerd Hoffmann } 551f1ae32a1SGerd Hoffmann 552f1ae32a1SGerd Hoffmann void usb_ep_init(USBDevice *dev) 553f1ae32a1SGerd Hoffmann { 554f1ae32a1SGerd Hoffmann int ep; 555f1ae32a1SGerd Hoffmann 556f1ae32a1SGerd Hoffmann dev->ep_ctl.nr = 0; 557f1ae32a1SGerd Hoffmann dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL; 558f1ae32a1SGerd Hoffmann dev->ep_ctl.ifnum = 0; 559f1ae32a1SGerd Hoffmann dev->ep_ctl.dev = dev; 560f1ae32a1SGerd Hoffmann dev->ep_ctl.pipeline = false; 561f1ae32a1SGerd Hoffmann QTAILQ_INIT(&dev->ep_ctl.queue); 562f1ae32a1SGerd Hoffmann for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { 563f1ae32a1SGerd Hoffmann dev->ep_in[ep].nr = ep + 1; 564f1ae32a1SGerd Hoffmann dev->ep_out[ep].nr = ep + 1; 565f1ae32a1SGerd Hoffmann dev->ep_in[ep].pid = USB_TOKEN_IN; 566f1ae32a1SGerd Hoffmann dev->ep_out[ep].pid = USB_TOKEN_OUT; 567f1ae32a1SGerd Hoffmann dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID; 568f1ae32a1SGerd Hoffmann dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID; 569f1ae32a1SGerd Hoffmann dev->ep_in[ep].ifnum = 0; 570f1ae32a1SGerd Hoffmann dev->ep_out[ep].ifnum = 0; 571f1ae32a1SGerd Hoffmann dev->ep_in[ep].dev = dev; 572f1ae32a1SGerd Hoffmann dev->ep_out[ep].dev = dev; 573f1ae32a1SGerd Hoffmann dev->ep_in[ep].pipeline = false; 574f1ae32a1SGerd Hoffmann dev->ep_out[ep].pipeline = false; 575f1ae32a1SGerd Hoffmann QTAILQ_INIT(&dev->ep_in[ep].queue); 576f1ae32a1SGerd Hoffmann QTAILQ_INIT(&dev->ep_out[ep].queue); 577f1ae32a1SGerd Hoffmann } 578f1ae32a1SGerd Hoffmann } 579f1ae32a1SGerd Hoffmann 580f1ae32a1SGerd Hoffmann void usb_ep_dump(USBDevice *dev) 581f1ae32a1SGerd Hoffmann { 582f1ae32a1SGerd Hoffmann static const char *tname[] = { 583f1ae32a1SGerd Hoffmann [USB_ENDPOINT_XFER_CONTROL] = "control", 584f1ae32a1SGerd Hoffmann [USB_ENDPOINT_XFER_ISOC] = "isoc", 585f1ae32a1SGerd Hoffmann [USB_ENDPOINT_XFER_BULK] = "bulk", 586f1ae32a1SGerd Hoffmann [USB_ENDPOINT_XFER_INT] = "int", 587f1ae32a1SGerd Hoffmann }; 588f1ae32a1SGerd Hoffmann int ifnum, ep, first; 589f1ae32a1SGerd Hoffmann 590f1ae32a1SGerd Hoffmann fprintf(stderr, "Device \"%s\", config %d\n", 591f1ae32a1SGerd Hoffmann dev->product_desc, dev->configuration); 592f1ae32a1SGerd Hoffmann for (ifnum = 0; ifnum < 16; ifnum++) { 593f1ae32a1SGerd Hoffmann first = 1; 594f1ae32a1SGerd Hoffmann for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { 595f1ae32a1SGerd Hoffmann if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID && 596f1ae32a1SGerd Hoffmann dev->ep_in[ep].ifnum == ifnum) { 597f1ae32a1SGerd Hoffmann if (first) { 598f1ae32a1SGerd Hoffmann first = 0; 599f1ae32a1SGerd Hoffmann fprintf(stderr, " Interface %d, alternative %d\n", 600f1ae32a1SGerd Hoffmann ifnum, dev->altsetting[ifnum]); 601f1ae32a1SGerd Hoffmann } 602f1ae32a1SGerd Hoffmann fprintf(stderr, " Endpoint %d, IN, %s, %d max\n", ep, 603f1ae32a1SGerd Hoffmann tname[dev->ep_in[ep].type], 604f1ae32a1SGerd Hoffmann dev->ep_in[ep].max_packet_size); 605f1ae32a1SGerd Hoffmann } 606f1ae32a1SGerd Hoffmann if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID && 607f1ae32a1SGerd Hoffmann dev->ep_out[ep].ifnum == ifnum) { 608f1ae32a1SGerd Hoffmann if (first) { 609f1ae32a1SGerd Hoffmann first = 0; 610f1ae32a1SGerd Hoffmann fprintf(stderr, " Interface %d, alternative %d\n", 611f1ae32a1SGerd Hoffmann ifnum, dev->altsetting[ifnum]); 612f1ae32a1SGerd Hoffmann } 613f1ae32a1SGerd Hoffmann fprintf(stderr, " Endpoint %d, OUT, %s, %d max\n", ep, 614f1ae32a1SGerd Hoffmann tname[dev->ep_out[ep].type], 615f1ae32a1SGerd Hoffmann dev->ep_out[ep].max_packet_size); 616f1ae32a1SGerd Hoffmann } 617f1ae32a1SGerd Hoffmann } 618f1ae32a1SGerd Hoffmann } 619f1ae32a1SGerd Hoffmann fprintf(stderr, "--\n"); 620f1ae32a1SGerd Hoffmann } 621f1ae32a1SGerd Hoffmann 622f1ae32a1SGerd Hoffmann struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep) 623f1ae32a1SGerd Hoffmann { 624f1ae32a1SGerd Hoffmann struct USBEndpoint *eps; 625f1ae32a1SGerd Hoffmann 626f1ae32a1SGerd Hoffmann if (dev == NULL) { 627f1ae32a1SGerd Hoffmann return NULL; 628f1ae32a1SGerd Hoffmann } 629f1ae32a1SGerd Hoffmann eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out; 630f1ae32a1SGerd Hoffmann if (ep == 0) { 631f1ae32a1SGerd Hoffmann return &dev->ep_ctl; 632f1ae32a1SGerd Hoffmann } 633f1ae32a1SGerd Hoffmann assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT); 634f1ae32a1SGerd Hoffmann assert(ep > 0 && ep <= USB_MAX_ENDPOINTS); 635f1ae32a1SGerd Hoffmann return eps + ep - 1; 636f1ae32a1SGerd Hoffmann } 637f1ae32a1SGerd Hoffmann 638f1ae32a1SGerd Hoffmann uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep) 639f1ae32a1SGerd Hoffmann { 640f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 641f1ae32a1SGerd Hoffmann return uep->type; 642f1ae32a1SGerd Hoffmann } 643f1ae32a1SGerd Hoffmann 644f1ae32a1SGerd Hoffmann void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type) 645f1ae32a1SGerd Hoffmann { 646f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 647f1ae32a1SGerd Hoffmann uep->type = type; 648f1ae32a1SGerd Hoffmann } 649f1ae32a1SGerd Hoffmann 650f1ae32a1SGerd Hoffmann uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep) 651f1ae32a1SGerd Hoffmann { 652f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 653f1ae32a1SGerd Hoffmann return uep->ifnum; 654f1ae32a1SGerd Hoffmann } 655f1ae32a1SGerd Hoffmann 656f1ae32a1SGerd Hoffmann void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum) 657f1ae32a1SGerd Hoffmann { 658f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 659f1ae32a1SGerd Hoffmann uep->ifnum = ifnum; 660f1ae32a1SGerd Hoffmann } 661f1ae32a1SGerd Hoffmann 662f1ae32a1SGerd Hoffmann void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep, 663f1ae32a1SGerd Hoffmann uint16_t raw) 664f1ae32a1SGerd Hoffmann { 665f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 666f1ae32a1SGerd Hoffmann int size, microframes; 667f1ae32a1SGerd Hoffmann 668f1ae32a1SGerd Hoffmann size = raw & 0x7ff; 669f1ae32a1SGerd Hoffmann switch ((raw >> 11) & 3) { 670f1ae32a1SGerd Hoffmann case 1: 671f1ae32a1SGerd Hoffmann microframes = 2; 672f1ae32a1SGerd Hoffmann break; 673f1ae32a1SGerd Hoffmann case 2: 674f1ae32a1SGerd Hoffmann microframes = 3; 675f1ae32a1SGerd Hoffmann break; 676f1ae32a1SGerd Hoffmann default: 677f1ae32a1SGerd Hoffmann microframes = 1; 678f1ae32a1SGerd Hoffmann break; 679f1ae32a1SGerd Hoffmann } 680f1ae32a1SGerd Hoffmann uep->max_packet_size = size * microframes; 681f1ae32a1SGerd Hoffmann } 682f1ae32a1SGerd Hoffmann 683f1ae32a1SGerd Hoffmann int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep) 684f1ae32a1SGerd Hoffmann { 685f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 686f1ae32a1SGerd Hoffmann return uep->max_packet_size; 687f1ae32a1SGerd Hoffmann } 688f1ae32a1SGerd Hoffmann 689f1ae32a1SGerd Hoffmann void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled) 690f1ae32a1SGerd Hoffmann { 691f1ae32a1SGerd Hoffmann struct USBEndpoint *uep = usb_ep_get(dev, pid, ep); 692f1ae32a1SGerd Hoffmann uep->pipeline = enabled; 693f1ae32a1SGerd Hoffmann } 694