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

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;
        !            43:         port->ops->detach(port);
        !            44:         if (dev) {
        !            45:             usb_send_msg(dev, USB_MSG_DETACH);
        !            46:             dev->port = NULL;
        !            47:             port->dev = NULL;
        !            48:         }
        !            49:     }
        !            50: }
        !            51: 
        !            52: void usb_wakeup(USBDevice *dev)
        !            53: {
        !            54:     if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
        !            55:         dev->port->ops->wakeup(dev);
        !            56:     }
1.1       root       57: }
                     58: 
                     59: /**********************/
1.1.1.5   root       60: 
1.1       root       61: /* generic USB device helpers (you are not forced to use them when
                     62:    writing your USB device driver, but they help handling the
1.1.1.4   root       63:    protocol)
1.1       root       64: */
                     65: 
                     66: #define SETUP_STATE_IDLE 0
                     67: #define SETUP_STATE_DATA 1
                     68: #define SETUP_STATE_ACK  2
                     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];
                     85:  
                     86:     if (s->setup_buf[0] & USB_DIR_IN) {
1.1.1.6   root       87:         ret = s->info->handle_control(s, request, value, index, 
                     88:                                       s->setup_len, s->data_buf);
1.1.1.5   root       89:         if (ret < 0)
                     90:             return ret;
                     91: 
                     92:         if (ret < s->setup_len)
                     93:             s->setup_len = ret;
                     94:         s->setup_state = SETUP_STATE_DATA;
                     95:     } else {
                     96:         if (s->setup_len == 0)
                     97:             s->setup_state = SETUP_STATE_ACK;
                     98:         else
                     99:             s->setup_state = SETUP_STATE_DATA;
                    100:     }
                    101: 
                    102:     return ret;
                    103: }
                    104: 
                    105: static int do_token_in(USBDevice *s, USBPacket *p)
                    106: {
                    107:     int request, value, index;
                    108:     int ret = 0;
                    109: 
                    110:     if (p->devep != 0)
1.1.1.6   root      111:         return s->info->handle_data(s, p);
1.1.1.5   root      112: 
                    113:     request = (s->setup_buf[0] << 8) | s->setup_buf[1];
                    114:     value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
                    115:     index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
                    116:  
                    117:     switch(s->setup_state) {
                    118:     case SETUP_STATE_ACK:
                    119:         if (!(s->setup_buf[0] & USB_DIR_IN)) {
                    120:             s->setup_state = SETUP_STATE_IDLE;
1.1.1.6   root      121:             ret = s->info->handle_control(s, request, value, index,
                    122:                                           s->setup_len, s->data_buf);
1.1.1.5   root      123:             if (ret > 0)
                    124:                 return 0;
                    125:             return ret;
                    126:         }
                    127: 
                    128:         /* return 0 byte */
                    129:         return 0;
                    130: 
                    131:     case SETUP_STATE_DATA:
                    132:         if (s->setup_buf[0] & USB_DIR_IN) {
                    133:             int len = s->setup_len - s->setup_index;
                    134:             if (len > p->len)
                    135:                 len = p->len;
                    136:             memcpy(p->data, s->data_buf + s->setup_index, len);
                    137:             s->setup_index += len;
                    138:             if (s->setup_index >= s->setup_len)
                    139:                 s->setup_state = SETUP_STATE_ACK;
                    140:             return len;
                    141:         }
                    142: 
                    143:         s->setup_state = SETUP_STATE_IDLE;
                    144:         return USB_RET_STALL;
                    145: 
                    146:     default:
                    147:         return USB_RET_STALL;
                    148:     }
                    149: }
                    150: 
                    151: static int do_token_out(USBDevice *s, USBPacket *p)
1.1       root      152: {
1.1.1.5   root      153:     if (p->devep != 0)
1.1.1.6   root      154:         return s->info->handle_data(s, p);
1.1.1.5   root      155: 
                    156:     switch(s->setup_state) {
                    157:     case SETUP_STATE_ACK:
                    158:         if (s->setup_buf[0] & USB_DIR_IN) {
                    159:             s->setup_state = SETUP_STATE_IDLE;
                    160:             /* transfer OK */
                    161:         } else {
                    162:             /* ignore additional output */
                    163:         }
                    164:         return 0;
1.1       root      165: 
1.1.1.5   root      166:     case SETUP_STATE_DATA:
                    167:         if (!(s->setup_buf[0] & USB_DIR_IN)) {
                    168:             int len = s->setup_len - s->setup_index;
                    169:             if (len > p->len)
                    170:                 len = p->len;
                    171:             memcpy(s->data_buf + s->setup_index, p->data, len);
                    172:             s->setup_index += len;
                    173:             if (s->setup_index >= s->setup_len)
                    174:                 s->setup_state = SETUP_STATE_ACK;
                    175:             return len;
                    176:         }
                    177: 
                    178:         s->setup_state = SETUP_STATE_IDLE;
                    179:         return USB_RET_STALL;
                    180: 
                    181:     default:
                    182:         return USB_RET_STALL;
                    183:     }
                    184: }
                    185: 
                    186: /*
                    187:  * Generic packet handler.
                    188:  * Called by the HC (host controller).
                    189:  *
                    190:  * Returns length of the transaction or one of the USB_RET_XXX codes.
                    191:  */
                    192: int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
                    193: {
1.1.1.3   root      194:     switch(p->pid) {
1.1       root      195:     case USB_MSG_ATTACH:
                    196:         s->state = USB_STATE_ATTACHED;
1.1.1.7 ! root      197:         if (s->info->handle_attach) {
        !           198:             s->info->handle_attach(s);
        !           199:         }
1.1.1.5   root      200:         return 0;
                    201: 
1.1       root      202:     case USB_MSG_DETACH:
                    203:         s->state = USB_STATE_NOTATTACHED;
1.1.1.5   root      204:         return 0;
                    205: 
1.1       root      206:     case USB_MSG_RESET:
                    207:         s->remote_wakeup = 0;
                    208:         s->addr = 0;
                    209:         s->state = USB_STATE_DEFAULT;
1.1.1.7 ! root      210:         if (s->info->handle_reset) {
        !           211:             s->info->handle_reset(s);
        !           212:         }
1.1.1.5   root      213:         return 0;
                    214:     }
                    215: 
                    216:     /* Rest of the PIDs must match our address */
                    217:     if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
                    218:         return USB_RET_NODEV;
                    219: 
                    220:     switch (p->pid) {
1.1       root      221:     case USB_TOKEN_SETUP:
1.1.1.5   root      222:         return do_token_setup(s, p);
                    223: 
1.1       root      224:     case USB_TOKEN_IN:
1.1.1.5   root      225:         return do_token_in(s, p);
                    226: 
1.1       root      227:     case USB_TOKEN_OUT:
1.1.1.5   root      228:         return do_token_out(s, p);
                    229:  
1.1       root      230:     default:
1.1.1.5   root      231:         return USB_RET_STALL;
1.1       root      232:     }
                    233: }
                    234: 
                    235: /* XXX: fix overflow */
                    236: int set_usb_string(uint8_t *buf, const char *str)
                    237: {
                    238:     int len, i;
                    239:     uint8_t *q;
                    240: 
                    241:     q = buf;
                    242:     len = strlen(str);
1.1.1.2   root      243:     *q++ = 2 * len + 2;
1.1       root      244:     *q++ = 3;
                    245:     for(i = 0; i < len; i++) {
                    246:         *q++ = str[i];
                    247:         *q++ = 0;
                    248:     }
                    249:     return q - buf;
                    250: }
1.1.1.3   root      251: 
                    252: /* Send an internal message to a USB device.  */
                    253: void usb_send_msg(USBDevice *dev, int msg)
                    254: {
                    255:     USBPacket p;
                    256:     memset(&p, 0, sizeof(p));
                    257:     p.pid = msg;
1.1.1.6   root      258:     dev->info->handle_packet(dev, &p);
1.1.1.3   root      259: 
1.1.1.5   root      260:     /* This _must_ be synchronous */
                    261: }

unix.superglobalmegacorp.com

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