Annotation of qemu/hw/usb.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  * QEMU USB emulation
                      3:  *
                      4:  * Copyright (c) 2005 Fabrice Bellard
1.1.1.4   root        5:  *
1.1.1.5   root        6:  * 2008 Generic packet handler rewrite by Max Krasnyansky
                      7:  *
1.1       root        8:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      9:  * of this software and associated documentation files (the "Software"), to deal
                     10:  * in the Software without restriction, including without limitation the rights
                     11:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     12:  * copies of the Software, and to permit persons to whom the Software is
                     13:  * furnished to do so, subject to the following conditions:
                     14:  *
                     15:  * The above copyright notice and this permission notice shall be included in
                     16:  * all copies or substantial portions of the Software.
                     17:  *
                     18:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     19:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     20:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     21:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     22:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     23:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     24:  * THE SOFTWARE.
                     25:  */
1.1.1.4   root       26: #include "qemu-common.h"
                     27: #include "usb.h"
1.1       root       28: 
                     29: void usb_attach(USBPort *port, USBDevice *dev)
                     30: {
1.1.1.7   root       31:     if (dev != NULL) {
                     32:         /* attach */
                     33:         if (port->dev) {
                     34:             usb_attach(port, NULL);
                     35:         }
                     36:         dev->port = port;
                     37:         port->dev = dev;
                     38:         port->ops->attach(port);
                     39:         usb_send_msg(dev, USB_MSG_ATTACH);
                     40:     } else {
                     41:         /* detach */
                     42:         dev = port->dev;
1.1.1.8 ! root       43:         assert(dev);
1.1.1.7   root       44:         port->ops->detach(port);
1.1.1.8 ! root       45:         usb_send_msg(dev, USB_MSG_DETACH);
        !            46:         dev->port = NULL;
        !            47:         port->dev = NULL;
1.1.1.7   root       48:     }
                     49: }
                     50: 
                     51: void usb_wakeup(USBDevice *dev)
                     52: {
                     53:     if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
1.1.1.8 ! root       54:         dev->port->ops->wakeup(dev->port);
1.1.1.7   root       55:     }
1.1       root       56: }
                     57: 
                     58: /**********************/
1.1.1.5   root       59: 
1.1       root       60: /* generic USB device helpers (you are not forced to use them when
                     61:    writing your USB device driver, but they help handling the
1.1.1.4   root       62:    protocol)
1.1       root       63: */
                     64: 
1.1.1.8 ! root       65: #define SETUP_STATE_IDLE  0
        !            66: #define SETUP_STATE_SETUP 1
        !            67: #define SETUP_STATE_DATA  2
        !            68: #define SETUP_STATE_ACK   3
1.1       root       69: 
1.1.1.5   root       70: static int do_token_setup(USBDevice *s, USBPacket *p)
                     71: {
                     72:     int request, value, index;
                     73:     int ret = 0;
                     74: 
                     75:     if (p->len != 8)
                     76:         return USB_RET_STALL;
                     77:  
                     78:     memcpy(s->setup_buf, p->data, 8);
                     79:     s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
                     80:     s->setup_index = 0;
                     81: 
                     82:     request = (s->setup_buf[0] << 8) | s->setup_buf[1];
                     83:     value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
                     84:     index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
1.1.1.8 ! root       85: 
1.1.1.5   root       86:     if (s->setup_buf[0] & USB_DIR_IN) {
1.1.1.8 ! root       87:         ret = s->info->handle_control(s, p, request, value, index,
1.1.1.6   root       88:                                       s->setup_len, s->data_buf);
1.1.1.8 ! root       89:         if (ret == USB_RET_ASYNC) {
        !            90:              s->setup_state = SETUP_STATE_SETUP;
        !            91:              return USB_RET_ASYNC;
        !            92:         }
1.1.1.5   root       93:         if (ret < 0)
                     94:             return ret;
                     95: 
                     96:         if (ret < s->setup_len)
                     97:             s->setup_len = ret;
                     98:         s->setup_state = SETUP_STATE_DATA;
                     99:     } else {
1.1.1.8 ! root      100:         if (s->setup_len > sizeof(s->data_buf)) {
        !           101:             fprintf(stderr,
        !           102:                 "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
        !           103:                 s->setup_len, sizeof(s->data_buf));
        !           104:             return USB_RET_STALL;
        !           105:         }
1.1.1.5   root      106:         if (s->setup_len == 0)
                    107:             s->setup_state = SETUP_STATE_ACK;
                    108:         else
                    109:             s->setup_state = SETUP_STATE_DATA;
                    110:     }
                    111: 
                    112:     return ret;
                    113: }
                    114: 
                    115: static int do_token_in(USBDevice *s, USBPacket *p)
                    116: {
                    117:     int request, value, index;
                    118:     int ret = 0;
                    119: 
                    120:     if (p->devep != 0)
1.1.1.6   root      121:         return s->info->handle_data(s, p);
1.1.1.5   root      122: 
                    123:     request = (s->setup_buf[0] << 8) | s->setup_buf[1];
                    124:     value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
                    125:     index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
                    126:  
                    127:     switch(s->setup_state) {
                    128:     case SETUP_STATE_ACK:
                    129:         if (!(s->setup_buf[0] & USB_DIR_IN)) {
1.1.1.8 ! root      130:             ret = s->info->handle_control(s, p, request, value, index,
1.1.1.6   root      131:                                           s->setup_len, s->data_buf);
1.1.1.8 ! root      132:             if (ret == USB_RET_ASYNC) {
        !           133:                 return USB_RET_ASYNC;
        !           134:             }
        !           135:             s->setup_state = SETUP_STATE_IDLE;
1.1.1.5   root      136:             if (ret > 0)
                    137:                 return 0;
                    138:             return ret;
                    139:         }
                    140: 
                    141:         /* return 0 byte */
                    142:         return 0;
                    143: 
                    144:     case SETUP_STATE_DATA:
                    145:         if (s->setup_buf[0] & USB_DIR_IN) {
                    146:             int len = s->setup_len - s->setup_index;
                    147:             if (len > p->len)
                    148:                 len = p->len;
                    149:             memcpy(p->data, s->data_buf + s->setup_index, len);
                    150:             s->setup_index += len;
                    151:             if (s->setup_index >= s->setup_len)
                    152:                 s->setup_state = SETUP_STATE_ACK;
                    153:             return len;
                    154:         }
                    155: 
                    156:         s->setup_state = SETUP_STATE_IDLE;
                    157:         return USB_RET_STALL;
                    158: 
                    159:     default:
                    160:         return USB_RET_STALL;
                    161:     }
                    162: }
                    163: 
                    164: static int do_token_out(USBDevice *s, USBPacket *p)
1.1       root      165: {
1.1.1.5   root      166:     if (p->devep != 0)
1.1.1.6   root      167:         return s->info->handle_data(s, p);
1.1.1.5   root      168: 
                    169:     switch(s->setup_state) {
                    170:     case SETUP_STATE_ACK:
                    171:         if (s->setup_buf[0] & USB_DIR_IN) {
                    172:             s->setup_state = SETUP_STATE_IDLE;
                    173:             /* transfer OK */
                    174:         } else {
                    175:             /* ignore additional output */
                    176:         }
                    177:         return 0;
1.1       root      178: 
1.1.1.5   root      179:     case SETUP_STATE_DATA:
                    180:         if (!(s->setup_buf[0] & USB_DIR_IN)) {
                    181:             int len = s->setup_len - s->setup_index;
                    182:             if (len > p->len)
                    183:                 len = p->len;
                    184:             memcpy(s->data_buf + s->setup_index, p->data, len);
                    185:             s->setup_index += len;
                    186:             if (s->setup_index >= s->setup_len)
                    187:                 s->setup_state = SETUP_STATE_ACK;
                    188:             return len;
                    189:         }
                    190: 
                    191:         s->setup_state = SETUP_STATE_IDLE;
                    192:         return USB_RET_STALL;
                    193: 
                    194:     default:
                    195:         return USB_RET_STALL;
                    196:     }
                    197: }
                    198: 
                    199: /*
                    200:  * Generic packet handler.
                    201:  * Called by the HC (host controller).
                    202:  *
                    203:  * Returns length of the transaction or one of the USB_RET_XXX codes.
                    204:  */
                    205: int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
                    206: {
1.1.1.3   root      207:     switch(p->pid) {
1.1       root      208:     case USB_MSG_ATTACH:
                    209:         s->state = USB_STATE_ATTACHED;
1.1.1.7   root      210:         if (s->info->handle_attach) {
                    211:             s->info->handle_attach(s);
                    212:         }
1.1.1.5   root      213:         return 0;
                    214: 
1.1       root      215:     case USB_MSG_DETACH:
                    216:         s->state = USB_STATE_NOTATTACHED;
1.1.1.5   root      217:         return 0;
                    218: 
1.1       root      219:     case USB_MSG_RESET:
                    220:         s->remote_wakeup = 0;
                    221:         s->addr = 0;
                    222:         s->state = USB_STATE_DEFAULT;
1.1.1.7   root      223:         if (s->info->handle_reset) {
                    224:             s->info->handle_reset(s);
                    225:         }
1.1.1.5   root      226:         return 0;
                    227:     }
                    228: 
                    229:     /* Rest of the PIDs must match our address */
                    230:     if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
                    231:         return USB_RET_NODEV;
                    232: 
                    233:     switch (p->pid) {
1.1       root      234:     case USB_TOKEN_SETUP:
1.1.1.5   root      235:         return do_token_setup(s, p);
                    236: 
1.1       root      237:     case USB_TOKEN_IN:
1.1.1.5   root      238:         return do_token_in(s, p);
                    239: 
1.1       root      240:     case USB_TOKEN_OUT:
1.1.1.5   root      241:         return do_token_out(s, p);
                    242:  
1.1       root      243:     default:
1.1.1.5   root      244:         return USB_RET_STALL;
1.1       root      245:     }
                    246: }
                    247: 
1.1.1.8 ! root      248: /* ctrl complete function for devices which use usb_generic_handle_packet and
        !           249:    may return USB_RET_ASYNC from their handle_control callback. Device code
        !           250:    which does this *must* call this function instead of the normal
        !           251:    usb_packet_complete to complete their async control packets. */
        !           252: void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
        !           253: {
        !           254:     if (p->len < 0) {
        !           255:         s->setup_state = SETUP_STATE_IDLE;
        !           256:     }
        !           257: 
        !           258:     switch (s->setup_state) {
        !           259:     case SETUP_STATE_SETUP:
        !           260:         if (p->len < s->setup_len) {
        !           261:             s->setup_len = p->len;
        !           262:         }
        !           263:         s->setup_state = SETUP_STATE_DATA;
        !           264:         p->len = 8;
        !           265:         break;
        !           266: 
        !           267:     case SETUP_STATE_ACK:
        !           268:         s->setup_state = SETUP_STATE_IDLE;
        !           269:         p->len = 0;
        !           270:         break;
        !           271: 
        !           272:     default:
        !           273:         break;
        !           274:     }
        !           275:     usb_packet_complete(s, p);
        !           276: }
        !           277: 
1.1       root      278: /* XXX: fix overflow */
                    279: int set_usb_string(uint8_t *buf, const char *str)
                    280: {
                    281:     int len, i;
                    282:     uint8_t *q;
                    283: 
                    284:     q = buf;
                    285:     len = strlen(str);
1.1.1.2   root      286:     *q++ = 2 * len + 2;
1.1       root      287:     *q++ = 3;
                    288:     for(i = 0; i < len; i++) {
                    289:         *q++ = str[i];
                    290:         *q++ = 0;
                    291:     }
                    292:     return q - buf;
                    293: }
1.1.1.3   root      294: 
                    295: /* Send an internal message to a USB device.  */
                    296: void usb_send_msg(USBDevice *dev, int msg)
                    297: {
                    298:     USBPacket p;
1.1.1.8 ! root      299:     int ret;
        !           300: 
1.1.1.3   root      301:     memset(&p, 0, sizeof(p));
                    302:     p.pid = msg;
1.1.1.8 ! root      303:     ret = usb_handle_packet(dev, &p);
1.1.1.5   root      304:     /* This _must_ be synchronous */
1.1.1.8 ! root      305:     assert(ret != USB_RET_ASYNC);
        !           306: }
        !           307: 
        !           308: /* Hand over a packet to a device for processing.  Return value
        !           309:    USB_RET_ASYNC indicates the processing isn't finished yet, the
        !           310:    driver will call usb_packet_complete() when done processing it. */
        !           311: int usb_handle_packet(USBDevice *dev, USBPacket *p)
        !           312: {
        !           313:     int ret;
        !           314: 
        !           315:     assert(p->owner == NULL);
        !           316:     ret = dev->info->handle_packet(dev, p);
        !           317:     if (ret == USB_RET_ASYNC) {
        !           318:         if (p->owner == NULL) {
        !           319:             p->owner = dev;
        !           320:         } else {
        !           321:             /* We'll end up here when usb_handle_packet is called
        !           322:              * recursively due to a hub being in the chain.  Nothing
        !           323:              * to do.  Leave p->owner pointing to the device, not the
        !           324:              * hub. */;
        !           325:         }
        !           326:     }
        !           327:     return ret;
        !           328: }
        !           329: 
        !           330: /* Notify the controller that an async packet is complete.  This should only
        !           331:    be called for packets previously deferred by returning USB_RET_ASYNC from
        !           332:    handle_packet. */
        !           333: void usb_packet_complete(USBDevice *dev, USBPacket *p)
        !           334: {
        !           335:     /* Note: p->owner != dev is possible in case dev is a hub */
        !           336:     assert(p->owner != NULL);
        !           337:     dev->port->ops->complete(dev->port, p);
        !           338:     p->owner = NULL;
        !           339: }
        !           340: 
        !           341: /* Cancel an active packet.  The packed must have been deferred by
        !           342:    returning USB_RET_ASYNC from handle_packet, and not yet
        !           343:    completed.  */
        !           344: void usb_cancel_packet(USBPacket * p)
        !           345: {
        !           346:     assert(p->owner != NULL);
        !           347:     p->owner->info->cancel_packet(p->owner, p);
        !           348:     p->owner = NULL;
1.1.1.5   root      349: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.