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