|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.