]> Git Repo - qemu.git/blob - hw/usb.c
ba720b48e0d333b828fe99475aced3cf1dcae597
[qemu.git] / hw / usb.c
1 /*
2  * QEMU USB emulation
3  *
4  * Copyright (c) 2005 Fabrice Bellard
5  *
6  * 2008 Generic packet handler rewrite by Max Krasnyansky
7  *
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  */
26 #include "qemu-common.h"
27 #include "usb.h"
28
29 void usb_attach(USBPort *port, USBDevice *dev)
30 {
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     }
57 }
58
59 /**********************/
60
61 /* generic USB device helpers (you are not forced to use them when
62    writing your USB device driver, but they help handling the
63    protocol)
64 */
65
66 #define SETUP_STATE_IDLE 0
67 #define SETUP_STATE_DATA 1
68 #define SETUP_STATE_ACK  2
69
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) {
87         ret = s->info->handle_control(s, request, value, index, 
88                                       s->setup_len, s->data_buf);
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)
111         return s->info->handle_data(s, p);
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;
121             ret = s->info->handle_control(s, request, value, index,
122                                           s->setup_len, s->data_buf);
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)
152 {
153     if (p->devep != 0)
154         return s->info->handle_data(s, p);
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;
165
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 {
194     switch(p->pid) {
195     case USB_MSG_ATTACH:
196         s->state = USB_STATE_ATTACHED;
197         return 0;
198
199     case USB_MSG_DETACH:
200         s->state = USB_STATE_NOTATTACHED;
201         return 0;
202
203     case USB_MSG_RESET:
204         s->remote_wakeup = 0;
205         s->addr = 0;
206         s->state = USB_STATE_DEFAULT;
207         s->info->handle_reset(s);
208         return 0;
209     }
210
211     /* Rest of the PIDs must match our address */
212     if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
213         return USB_RET_NODEV;
214
215     switch (p->pid) {
216     case USB_TOKEN_SETUP:
217         return do_token_setup(s, p);
218
219     case USB_TOKEN_IN:
220         return do_token_in(s, p);
221
222     case USB_TOKEN_OUT:
223         return do_token_out(s, p);
224  
225     default:
226         return USB_RET_STALL;
227     }
228 }
229
230 /* XXX: fix overflow */
231 int set_usb_string(uint8_t *buf, const char *str)
232 {
233     int len, i;
234     uint8_t *q;
235
236     q = buf;
237     len = strlen(str);
238     *q++ = 2 * len + 2;
239     *q++ = 3;
240     for(i = 0; i < len; i++) {
241         *q++ = str[i];
242         *q++ = 0;
243     }
244     return q - buf;
245 }
246
247 /* Send an internal message to a USB device.  */
248 void usb_send_msg(USBDevice *dev, int msg)
249 {
250     USBPacket p;
251     memset(&p, 0, sizeof(p));
252     p.pid = msg;
253     dev->info->handle_packet(dev, &p);
254
255     /* This _must_ be synchronous */
256 }
This page took 0.02831 seconds and 2 git commands to generate.