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

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

unix.superglobalmegacorp.com

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