|
|
1.1 root 1: /*
2: * QEMU USB emulation
3: *
4: * Copyright (c) 2005 Fabrice Bellard
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24: #include "vl.h"
25:
26: void usb_attach(USBPort *port, USBDevice *dev)
27: {
28: port->attach(port, dev);
29: }
30:
31: /**********************/
32: /* generic USB device helpers (you are not forced to use them when
33: writing your USB device driver, but they help handling the
34: protocol)
35: */
36:
37: #define SETUP_STATE_IDLE 0
38: #define SETUP_STATE_DATA 1
39: #define SETUP_STATE_ACK 2
40:
1.1.1.3 ! root 41: int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
1.1 root 42: {
43: int l, ret = 0;
1.1.1.3 ! root 44: int len = p->len;
! 45: uint8_t *data = p->data;
1.1 root 46:
1.1.1.3 ! root 47: switch(p->pid) {
1.1 root 48: case USB_MSG_ATTACH:
49: s->state = USB_STATE_ATTACHED;
50: break;
51: case USB_MSG_DETACH:
52: s->state = USB_STATE_NOTATTACHED;
53: break;
54: case USB_MSG_RESET:
55: s->remote_wakeup = 0;
56: s->addr = 0;
57: s->state = USB_STATE_DEFAULT;
58: s->handle_reset(s);
59: break;
60: case USB_TOKEN_SETUP:
1.1.1.3 ! root 61: if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
1.1 root 62: return USB_RET_NODEV;
63: if (len != 8)
64: goto fail;
65: memcpy(s->setup_buf, data, 8);
66: s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
67: s->setup_index = 0;
68: if (s->setup_buf[0] & USB_DIR_IN) {
69: ret = s->handle_control(s,
70: (s->setup_buf[0] << 8) | s->setup_buf[1],
71: (s->setup_buf[3] << 8) | s->setup_buf[2],
72: (s->setup_buf[5] << 8) | s->setup_buf[4],
73: s->setup_len,
74: s->data_buf);
75: if (ret < 0)
76: return ret;
77: if (ret < s->setup_len)
78: s->setup_len = ret;
79: s->setup_state = SETUP_STATE_DATA;
80: } else {
81: if (s->setup_len == 0)
82: s->setup_state = SETUP_STATE_ACK;
83: else
84: s->setup_state = SETUP_STATE_DATA;
85: }
86: break;
87: case USB_TOKEN_IN:
1.1.1.3 ! root 88: if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
1.1 root 89: return USB_RET_NODEV;
1.1.1.3 ! root 90: switch(p->devep) {
1.1 root 91: case 0:
92: switch(s->setup_state) {
93: case SETUP_STATE_ACK:
94: if (!(s->setup_buf[0] & USB_DIR_IN)) {
1.1.1.2 root 95: s->setup_state = SETUP_STATE_IDLE;
1.1 root 96: ret = s->handle_control(s,
97: (s->setup_buf[0] << 8) | s->setup_buf[1],
98: (s->setup_buf[3] << 8) | s->setup_buf[2],
99: (s->setup_buf[5] << 8) | s->setup_buf[4],
100: s->setup_len,
101: s->data_buf);
102: if (ret > 0)
103: ret = 0;
104: } else {
1.1.1.2 root 105: /* return 0 byte */
1.1 root 106: }
107: break;
108: case SETUP_STATE_DATA:
109: if (s->setup_buf[0] & USB_DIR_IN) {
110: l = s->setup_len - s->setup_index;
111: if (l > len)
112: l = len;
113: memcpy(data, s->data_buf + s->setup_index, l);
114: s->setup_index += l;
115: if (s->setup_index >= s->setup_len)
116: s->setup_state = SETUP_STATE_ACK;
117: ret = l;
118: } else {
119: s->setup_state = SETUP_STATE_IDLE;
120: goto fail;
121: }
122: break;
123: default:
124: goto fail;
125: }
126: break;
127: default:
1.1.1.3 ! root 128: ret = s->handle_data(s, p);
1.1 root 129: break;
130: }
131: break;
132: case USB_TOKEN_OUT:
1.1.1.3 ! root 133: if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
1.1 root 134: return USB_RET_NODEV;
1.1.1.3 ! root 135: switch(p->devep) {
1.1 root 136: case 0:
137: switch(s->setup_state) {
138: case SETUP_STATE_ACK:
139: if (s->setup_buf[0] & USB_DIR_IN) {
1.1.1.2 root 140: s->setup_state = SETUP_STATE_IDLE;
1.1 root 141: /* transfer OK */
142: } else {
1.1.1.2 root 143: /* ignore additionnal output */
1.1 root 144: }
145: break;
146: case SETUP_STATE_DATA:
147: if (!(s->setup_buf[0] & USB_DIR_IN)) {
148: l = s->setup_len - s->setup_index;
149: if (l > len)
150: l = len;
151: memcpy(s->data_buf + s->setup_index, data, l);
152: s->setup_index += l;
153: if (s->setup_index >= s->setup_len)
154: s->setup_state = SETUP_STATE_ACK;
155: ret = l;
156: } else {
157: s->setup_state = SETUP_STATE_IDLE;
158: goto fail;
159: }
160: break;
161: default:
162: goto fail;
163: }
164: break;
165: default:
1.1.1.3 ! root 166: ret = s->handle_data(s, p);
1.1 root 167: break;
168: }
169: break;
170: default:
171: fail:
172: ret = USB_RET_STALL;
173: break;
174: }
175: return ret;
176: }
177:
178: /* XXX: fix overflow */
179: int set_usb_string(uint8_t *buf, const char *str)
180: {
181: int len, i;
182: uint8_t *q;
183:
184: q = buf;
185: len = strlen(str);
1.1.1.2 root 186: *q++ = 2 * len + 2;
1.1 root 187: *q++ = 3;
188: for(i = 0; i < len; i++) {
189: *q++ = str[i];
190: *q++ = 0;
191: }
192: return q - buf;
193: }
1.1.1.3 ! root 194:
! 195: /* Send an internal message to a USB device. */
! 196: void usb_send_msg(USBDevice *dev, int msg)
! 197: {
! 198: USBPacket p;
! 199: memset(&p, 0, sizeof(p));
! 200: p.pid = msg;
! 201: dev->handle_packet(dev, &p);
! 202: }
! 203:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.