xref: /qemu/hw/usb/core.c (revision 19f3322379c25a235eb1ec6335676549109fa625)
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 > sizeof(s->data_buf)) {
97             fprintf(stderr,
98                 "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
99                 s->setup_len, sizeof(s->data_buf));
100             return USB_RET_STALL;
101         }
102         if (s->setup_len == 0)
103             s->setup_state = SETUP_STATE_ACK;
104         else
105             s->setup_state = SETUP_STATE_DATA;
106     }
107 
108     return ret;
109 }
110 
111 static int do_token_in(USBDevice *s, USBPacket *p)
112 {
113     int request, value, index;
114     int ret = 0;
115 
116     if (p->devep != 0)
117         return s->info->handle_data(s, p);
118 
119     request = (s->setup_buf[0] << 8) | s->setup_buf[1];
120     value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
121     index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
122 
123     switch(s->setup_state) {
124     case SETUP_STATE_ACK:
125         if (!(s->setup_buf[0] & USB_DIR_IN)) {
126             s->setup_state = SETUP_STATE_IDLE;
127             ret = s->info->handle_control(s, request, value, index,
128                                           s->setup_len, s->data_buf);
129             if (ret > 0)
130                 return 0;
131             return ret;
132         }
133 
134         /* return 0 byte */
135         return 0;
136 
137     case SETUP_STATE_DATA:
138         if (s->setup_buf[0] & USB_DIR_IN) {
139             int len = s->setup_len - s->setup_index;
140             if (len > p->len)
141                 len = p->len;
142             memcpy(p->data, s->data_buf + s->setup_index, len);
143             s->setup_index += len;
144             if (s->setup_index >= s->setup_len)
145                 s->setup_state = SETUP_STATE_ACK;
146             return len;
147         }
148 
149         s->setup_state = SETUP_STATE_IDLE;
150         return USB_RET_STALL;
151 
152     default:
153         return USB_RET_STALL;
154     }
155 }
156 
157 static int do_token_out(USBDevice *s, USBPacket *p)
158 {
159     if (p->devep != 0)
160         return s->info->handle_data(s, p);
161 
162     switch(s->setup_state) {
163     case SETUP_STATE_ACK:
164         if (s->setup_buf[0] & USB_DIR_IN) {
165             s->setup_state = SETUP_STATE_IDLE;
166             /* transfer OK */
167         } else {
168             /* ignore additional output */
169         }
170         return 0;
171 
172     case SETUP_STATE_DATA:
173         if (!(s->setup_buf[0] & USB_DIR_IN)) {
174             int len = s->setup_len - s->setup_index;
175             if (len > p->len)
176                 len = p->len;
177             memcpy(s->data_buf + s->setup_index, p->data, len);
178             s->setup_index += len;
179             if (s->setup_index >= s->setup_len)
180                 s->setup_state = SETUP_STATE_ACK;
181             return len;
182         }
183 
184         s->setup_state = SETUP_STATE_IDLE;
185         return USB_RET_STALL;
186 
187     default:
188         return USB_RET_STALL;
189     }
190 }
191 
192 /*
193  * Generic packet handler.
194  * Called by the HC (host controller).
195  *
196  * Returns length of the transaction or one of the USB_RET_XXX codes.
197  */
198 int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
199 {
200     switch(p->pid) {
201     case USB_MSG_ATTACH:
202         s->state = USB_STATE_ATTACHED;
203         if (s->info->handle_attach) {
204             s->info->handle_attach(s);
205         }
206         return 0;
207 
208     case USB_MSG_DETACH:
209         s->state = USB_STATE_NOTATTACHED;
210         return 0;
211 
212     case USB_MSG_RESET:
213         s->remote_wakeup = 0;
214         s->addr = 0;
215         s->state = USB_STATE_DEFAULT;
216         if (s->info->handle_reset) {
217             s->info->handle_reset(s);
218         }
219         return 0;
220     }
221 
222     /* Rest of the PIDs must match our address */
223     if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
224         return USB_RET_NODEV;
225 
226     switch (p->pid) {
227     case USB_TOKEN_SETUP:
228         return do_token_setup(s, p);
229 
230     case USB_TOKEN_IN:
231         return do_token_in(s, p);
232 
233     case USB_TOKEN_OUT:
234         return do_token_out(s, p);
235 
236     default:
237         return USB_RET_STALL;
238     }
239 }
240 
241 /* XXX: fix overflow */
242 int set_usb_string(uint8_t *buf, const char *str)
243 {
244     int len, i;
245     uint8_t *q;
246 
247     q = buf;
248     len = strlen(str);
249     *q++ = 2 * len + 2;
250     *q++ = 3;
251     for(i = 0; i < len; i++) {
252         *q++ = str[i];
253         *q++ = 0;
254     }
255     return q - buf;
256 }
257 
258 /* Send an internal message to a USB device.  */
259 void usb_send_msg(USBDevice *dev, int msg)
260 {
261     USBPacket p;
262     memset(&p, 0, sizeof(p));
263     p.pid = msg;
264     dev->info->handle_packet(dev, &p);
265 
266     /* This _must_ be synchronous */
267 }
268