Statistics
| Branch: | Revision:

root / hw / usb / core.c @ ef5b2344

History | View | Annotate | Download (20.3 kB)

1 bb36d470 bellard
/*
2 bb36d470 bellard
 * QEMU USB emulation
3 bb36d470 bellard
 *
4 bb36d470 bellard
 * Copyright (c) 2005 Fabrice Bellard
5 5fafdf24 ths
 *
6 89b9b79f aliguori
 * 2008 Generic packet handler rewrite by Max Krasnyansky
7 89b9b79f aliguori
 *
8 bb36d470 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 bb36d470 bellard
 * of this software and associated documentation files (the "Software"), to deal
10 bb36d470 bellard
 * in the Software without restriction, including without limitation the rights
11 bb36d470 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 bb36d470 bellard
 * copies of the Software, and to permit persons to whom the Software is
13 bb36d470 bellard
 * furnished to do so, subject to the following conditions:
14 bb36d470 bellard
 *
15 bb36d470 bellard
 * The above copyright notice and this permission notice shall be included in
16 bb36d470 bellard
 * all copies or substantial portions of the Software.
17 bb36d470 bellard
 *
18 bb36d470 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 bb36d470 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 bb36d470 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 bb36d470 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 bb36d470 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 bb36d470 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 bb36d470 bellard
 * THE SOFTWARE.
25 bb36d470 bellard
 */
26 87ecb68b pbrook
#include "qemu-common.h"
27 f1ae32a1 Gerd Hoffmann
#include "hw/usb.h"
28 4f4321c1 Gerd Hoffmann
#include "iov.h"
29 808aeb98 Gerd Hoffmann
#include "trace.h"
30 bb36d470 bellard
31 891fb2cd Gerd Hoffmann
void usb_attach(USBPort *port)
32 bb36d470 bellard
{
33 891fb2cd Gerd Hoffmann
    USBDevice *dev = port->dev;
34 891fb2cd Gerd Hoffmann
35 891fb2cd Gerd Hoffmann
    assert(dev != NULL);
36 891fb2cd Gerd Hoffmann
    assert(dev->attached);
37 e0b8e72d Gerd Hoffmann
    assert(dev->state == USB_STATE_NOTATTACHED);
38 891fb2cd Gerd Hoffmann
    port->ops->attach(port);
39 d1f8b536 Gerd Hoffmann
    dev->state = USB_STATE_ATTACHED;
40 d1f8b536 Gerd Hoffmann
    usb_device_handle_attach(dev);
41 891fb2cd Gerd Hoffmann
}
42 891fb2cd Gerd Hoffmann
43 891fb2cd Gerd Hoffmann
void usb_detach(USBPort *port)
44 891fb2cd Gerd Hoffmann
{
45 891fb2cd Gerd Hoffmann
    USBDevice *dev = port->dev;
46 891fb2cd Gerd Hoffmann
47 891fb2cd Gerd Hoffmann
    assert(dev != NULL);
48 e0b8e72d Gerd Hoffmann
    assert(dev->state != USB_STATE_NOTATTACHED);
49 891fb2cd Gerd Hoffmann
    port->ops->detach(port);
50 d1f8b536 Gerd Hoffmann
    dev->state = USB_STATE_NOTATTACHED;
51 bb36d470 bellard
}
52 bb36d470 bellard
53 d28f4e2d Gerd Hoffmann
void usb_port_reset(USBPort *port)
54 e0b8e72d Gerd Hoffmann
{
55 e0b8e72d Gerd Hoffmann
    USBDevice *dev = port->dev;
56 e0b8e72d Gerd Hoffmann
57 e0b8e72d Gerd Hoffmann
    assert(dev != NULL);
58 e0b8e72d Gerd Hoffmann
    usb_detach(port);
59 e0b8e72d Gerd Hoffmann
    usb_attach(port);
60 d28f4e2d Gerd Hoffmann
    usb_device_reset(dev);
61 d28f4e2d Gerd Hoffmann
}
62 d28f4e2d Gerd Hoffmann
63 d28f4e2d Gerd Hoffmann
void usb_device_reset(USBDevice *dev)
64 d28f4e2d Gerd Hoffmann
{
65 d28f4e2d Gerd Hoffmann
    if (dev == NULL || !dev->attached) {
66 d28f4e2d Gerd Hoffmann
        return;
67 d28f4e2d Gerd Hoffmann
    }
68 d28f4e2d Gerd Hoffmann
    dev->remote_wakeup = 0;
69 d28f4e2d Gerd Hoffmann
    dev->addr = 0;
70 d28f4e2d Gerd Hoffmann
    dev->state = USB_STATE_DEFAULT;
71 d28f4e2d Gerd Hoffmann
    usb_device_handle_reset(dev);
72 e0b8e72d Gerd Hoffmann
}
73 e0b8e72d Gerd Hoffmann
74 7567b51f Gerd Hoffmann
void usb_wakeup(USBEndpoint *ep)
75 01eacab6 Gerd Hoffmann
{
76 7567b51f Gerd Hoffmann
    USBDevice *dev = ep->dev;
77 37f32f0f Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
78 7567b51f Gerd Hoffmann
79 01eacab6 Gerd Hoffmann
    if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
80 d47e59b8 Hans de Goede
        dev->port->ops->wakeup(dev->port);
81 01eacab6 Gerd Hoffmann
    }
82 37f32f0f Gerd Hoffmann
    if (bus->ops->wakeup_endpoint) {
83 37f32f0f Gerd Hoffmann
        bus->ops->wakeup_endpoint(bus, ep);
84 37f32f0f Gerd Hoffmann
    }
85 01eacab6 Gerd Hoffmann
}
86 01eacab6 Gerd Hoffmann
87 bb36d470 bellard
/**********************/
88 89b9b79f aliguori
89 bb36d470 bellard
/* generic USB device helpers (you are not forced to use them when
90 bb36d470 bellard
   writing your USB device driver, but they help handling the
91 5fafdf24 ths
   protocol)
92 bb36d470 bellard
*/
93 bb36d470 bellard
94 50b7963e Hans de Goede
#define SETUP_STATE_IDLE  0
95 50b7963e Hans de Goede
#define SETUP_STATE_SETUP 1
96 50b7963e Hans de Goede
#define SETUP_STATE_DATA  2
97 50b7963e Hans de Goede
#define SETUP_STATE_ACK   3
98 1b4b29a1 Gerd Hoffmann
#define SETUP_STATE_PARAM 4
99 bb36d470 bellard
100 89b9b79f aliguori
static int do_token_setup(USBDevice *s, USBPacket *p)
101 89b9b79f aliguori
{
102 89b9b79f aliguori
    int request, value, index;
103 89b9b79f aliguori
    int ret = 0;
104 89b9b79f aliguori
105 4f4321c1 Gerd Hoffmann
    if (p->iov.size != 8) {
106 89b9b79f aliguori
        return USB_RET_STALL;
107 4f4321c1 Gerd Hoffmann
    }
108 4f4321c1 Gerd Hoffmann
109 4f4321c1 Gerd Hoffmann
    usb_packet_copy(p, s->setup_buf, p->iov.size);
110 c19537a1 Gerd Hoffmann
    p->result = 0;
111 89b9b79f aliguori
    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
112 89b9b79f aliguori
    s->setup_index = 0;
113 89b9b79f aliguori
114 89b9b79f aliguori
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
115 89b9b79f aliguori
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
116 89b9b79f aliguori
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
117 007fd62f Hans de Goede
118 89b9b79f aliguori
    if (s->setup_buf[0] & USB_DIR_IN) {
119 62aed765 Anthony Liguori
        ret = usb_device_handle_control(s, p, request, value, index,
120 62aed765 Anthony Liguori
                                        s->setup_len, s->data_buf);
121 50b7963e Hans de Goede
        if (ret == USB_RET_ASYNC) {
122 50b7963e Hans de Goede
             s->setup_state = SETUP_STATE_SETUP;
123 50b7963e Hans de Goede
             return USB_RET_ASYNC;
124 50b7963e Hans de Goede
        }
125 89b9b79f aliguori
        if (ret < 0)
126 89b9b79f aliguori
            return ret;
127 89b9b79f aliguori
128 89b9b79f aliguori
        if (ret < s->setup_len)
129 89b9b79f aliguori
            s->setup_len = ret;
130 89b9b79f aliguori
        s->setup_state = SETUP_STATE_DATA;
131 89b9b79f aliguori
    } else {
132 19f33223 Hans de Goede
        if (s->setup_len > sizeof(s->data_buf)) {
133 19f33223 Hans de Goede
            fprintf(stderr,
134 19f33223 Hans de Goede
                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
135 19f33223 Hans de Goede
                s->setup_len, sizeof(s->data_buf));
136 19f33223 Hans de Goede
            return USB_RET_STALL;
137 19f33223 Hans de Goede
        }
138 89b9b79f aliguori
        if (s->setup_len == 0)
139 89b9b79f aliguori
            s->setup_state = SETUP_STATE_ACK;
140 89b9b79f aliguori
        else
141 89b9b79f aliguori
            s->setup_state = SETUP_STATE_DATA;
142 89b9b79f aliguori
    }
143 89b9b79f aliguori
144 89b9b79f aliguori
    return ret;
145 89b9b79f aliguori
}
146 89b9b79f aliguori
147 89b9b79f aliguori
static int do_token_in(USBDevice *s, USBPacket *p)
148 bb36d470 bellard
{
149 89b9b79f aliguori
    int request, value, index;
150 89b9b79f aliguori
    int ret = 0;
151 89b9b79f aliguori
152 079d0b7f Gerd Hoffmann
    assert(p->ep->nr == 0);
153 89b9b79f aliguori
154 89b9b79f aliguori
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
155 89b9b79f aliguori
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
156 89b9b79f aliguori
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
157 89b9b79f aliguori
 
158 89b9b79f aliguori
    switch(s->setup_state) {
159 89b9b79f aliguori
    case SETUP_STATE_ACK:
160 89b9b79f aliguori
        if (!(s->setup_buf[0] & USB_DIR_IN)) {
161 62aed765 Anthony Liguori
            ret = usb_device_handle_control(s, p, request, value, index,
162 62aed765 Anthony Liguori
                                            s->setup_len, s->data_buf);
163 007fd62f Hans de Goede
            if (ret == USB_RET_ASYNC) {
164 007fd62f Hans de Goede
                return USB_RET_ASYNC;
165 007fd62f Hans de Goede
            }
166 007fd62f Hans de Goede
            s->setup_state = SETUP_STATE_IDLE;
167 89b9b79f aliguori
            if (ret > 0)
168 89b9b79f aliguori
                return 0;
169 89b9b79f aliguori
            return ret;
170 89b9b79f aliguori
        }
171 89b9b79f aliguori
172 89b9b79f aliguori
        /* return 0 byte */
173 89b9b79f aliguori
        return 0;
174 89b9b79f aliguori
175 89b9b79f aliguori
    case SETUP_STATE_DATA:
176 89b9b79f aliguori
        if (s->setup_buf[0] & USB_DIR_IN) {
177 89b9b79f aliguori
            int len = s->setup_len - s->setup_index;
178 4f4321c1 Gerd Hoffmann
            if (len > p->iov.size) {
179 4f4321c1 Gerd Hoffmann
                len = p->iov.size;
180 4f4321c1 Gerd Hoffmann
            }
181 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf + s->setup_index, len);
182 89b9b79f aliguori
            s->setup_index += len;
183 89b9b79f aliguori
            if (s->setup_index >= s->setup_len)
184 89b9b79f aliguori
                s->setup_state = SETUP_STATE_ACK;
185 89b9b79f aliguori
            return len;
186 89b9b79f aliguori
        }
187 89b9b79f aliguori
188 89b9b79f aliguori
        s->setup_state = SETUP_STATE_IDLE;
189 89b9b79f aliguori
        return USB_RET_STALL;
190 89b9b79f aliguori
191 89b9b79f aliguori
    default:
192 89b9b79f aliguori
        return USB_RET_STALL;
193 89b9b79f aliguori
    }
194 89b9b79f aliguori
}
195 89b9b79f aliguori
196 89b9b79f aliguori
static int do_token_out(USBDevice *s, USBPacket *p)
197 89b9b79f aliguori
{
198 079d0b7f Gerd Hoffmann
    assert(p->ep->nr == 0);
199 89b9b79f aliguori
200 89b9b79f aliguori
    switch(s->setup_state) {
201 89b9b79f aliguori
    case SETUP_STATE_ACK:
202 89b9b79f aliguori
        if (s->setup_buf[0] & USB_DIR_IN) {
203 89b9b79f aliguori
            s->setup_state = SETUP_STATE_IDLE;
204 89b9b79f aliguori
            /* transfer OK */
205 89b9b79f aliguori
        } else {
206 89b9b79f aliguori
            /* ignore additional output */
207 89b9b79f aliguori
        }
208 89b9b79f aliguori
        return 0;
209 89b9b79f aliguori
210 89b9b79f aliguori
    case SETUP_STATE_DATA:
211 89b9b79f aliguori
        if (!(s->setup_buf[0] & USB_DIR_IN)) {
212 89b9b79f aliguori
            int len = s->setup_len - s->setup_index;
213 4f4321c1 Gerd Hoffmann
            if (len > p->iov.size) {
214 4f4321c1 Gerd Hoffmann
                len = p->iov.size;
215 4f4321c1 Gerd Hoffmann
            }
216 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf + s->setup_index, len);
217 89b9b79f aliguori
            s->setup_index += len;
218 89b9b79f aliguori
            if (s->setup_index >= s->setup_len)
219 89b9b79f aliguori
                s->setup_state = SETUP_STATE_ACK;
220 89b9b79f aliguori
            return len;
221 89b9b79f aliguori
        }
222 89b9b79f aliguori
223 89b9b79f aliguori
        s->setup_state = SETUP_STATE_IDLE;
224 89b9b79f aliguori
        return USB_RET_STALL;
225 89b9b79f aliguori
226 89b9b79f aliguori
    default:
227 89b9b79f aliguori
        return USB_RET_STALL;
228 89b9b79f aliguori
    }
229 89b9b79f aliguori
}
230 bb36d470 bellard
231 1b4b29a1 Gerd Hoffmann
static int do_parameter(USBDevice *s, USBPacket *p)
232 1b4b29a1 Gerd Hoffmann
{
233 1b4b29a1 Gerd Hoffmann
    int request, value, index;
234 1b4b29a1 Gerd Hoffmann
    int i, ret = 0;
235 1b4b29a1 Gerd Hoffmann
236 1b4b29a1 Gerd Hoffmann
    for (i = 0; i < 8; i++) {
237 1b4b29a1 Gerd Hoffmann
        s->setup_buf[i] = p->parameter >> (i*8);
238 1b4b29a1 Gerd Hoffmann
    }
239 1b4b29a1 Gerd Hoffmann
240 1b4b29a1 Gerd Hoffmann
    s->setup_state = SETUP_STATE_PARAM;
241 1b4b29a1 Gerd Hoffmann
    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
242 1b4b29a1 Gerd Hoffmann
    s->setup_index = 0;
243 1b4b29a1 Gerd Hoffmann
244 1b4b29a1 Gerd Hoffmann
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
245 1b4b29a1 Gerd Hoffmann
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
246 1b4b29a1 Gerd Hoffmann
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
247 1b4b29a1 Gerd Hoffmann
248 1b4b29a1 Gerd Hoffmann
    if (s->setup_len > sizeof(s->data_buf)) {
249 1b4b29a1 Gerd Hoffmann
        fprintf(stderr,
250 1b4b29a1 Gerd Hoffmann
                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
251 1b4b29a1 Gerd Hoffmann
                s->setup_len, sizeof(s->data_buf));
252 1b4b29a1 Gerd Hoffmann
        return USB_RET_STALL;
253 1b4b29a1 Gerd Hoffmann
    }
254 1b4b29a1 Gerd Hoffmann
255 1b4b29a1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_OUT) {
256 1b4b29a1 Gerd Hoffmann
        usb_packet_copy(p, s->data_buf, s->setup_len);
257 1b4b29a1 Gerd Hoffmann
    }
258 1b4b29a1 Gerd Hoffmann
259 1b4b29a1 Gerd Hoffmann
    ret = usb_device_handle_control(s, p, request, value, index,
260 1b4b29a1 Gerd Hoffmann
                                    s->setup_len, s->data_buf);
261 1b4b29a1 Gerd Hoffmann
    if (ret < 0) {
262 1b4b29a1 Gerd Hoffmann
        return ret;
263 1b4b29a1 Gerd Hoffmann
    }
264 1b4b29a1 Gerd Hoffmann
265 1b4b29a1 Gerd Hoffmann
    if (ret < s->setup_len) {
266 1b4b29a1 Gerd Hoffmann
        s->setup_len = ret;
267 1b4b29a1 Gerd Hoffmann
    }
268 1b4b29a1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_IN) {
269 1b4b29a1 Gerd Hoffmann
        usb_packet_copy(p, s->data_buf, s->setup_len);
270 1b4b29a1 Gerd Hoffmann
    }
271 1b4b29a1 Gerd Hoffmann
272 1b4b29a1 Gerd Hoffmann
    return ret;
273 1b4b29a1 Gerd Hoffmann
}
274 1b4b29a1 Gerd Hoffmann
275 50b7963e Hans de Goede
/* ctrl complete function for devices which use usb_generic_handle_packet and
276 50b7963e Hans de Goede
   may return USB_RET_ASYNC from their handle_control callback. Device code
277 50b7963e Hans de Goede
   which does this *must* call this function instead of the normal
278 50b7963e Hans de Goede
   usb_packet_complete to complete their async control packets. */
279 50b7963e Hans de Goede
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
280 50b7963e Hans de Goede
{
281 4f4321c1 Gerd Hoffmann
    if (p->result < 0) {
282 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_IDLE;
283 50b7963e Hans de Goede
    }
284 50b7963e Hans de Goede
285 50b7963e Hans de Goede
    switch (s->setup_state) {
286 50b7963e Hans de Goede
    case SETUP_STATE_SETUP:
287 4f4321c1 Gerd Hoffmann
        if (p->result < s->setup_len) {
288 4f4321c1 Gerd Hoffmann
            s->setup_len = p->result;
289 50b7963e Hans de Goede
        }
290 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_DATA;
291 4f4321c1 Gerd Hoffmann
        p->result = 8;
292 50b7963e Hans de Goede
        break;
293 50b7963e Hans de Goede
294 50b7963e Hans de Goede
    case SETUP_STATE_ACK:
295 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_IDLE;
296 4f4321c1 Gerd Hoffmann
        p->result = 0;
297 50b7963e Hans de Goede
        break;
298 50b7963e Hans de Goede
299 1b4b29a1 Gerd Hoffmann
    case SETUP_STATE_PARAM:
300 1b4b29a1 Gerd Hoffmann
        if (p->result < s->setup_len) {
301 1b4b29a1 Gerd Hoffmann
            s->setup_len = p->result;
302 1b4b29a1 Gerd Hoffmann
        }
303 1b4b29a1 Gerd Hoffmann
        if (p->pid == USB_TOKEN_IN) {
304 1b4b29a1 Gerd Hoffmann
            p->result = 0;
305 1b4b29a1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf, s->setup_len);
306 1b4b29a1 Gerd Hoffmann
        }
307 1b4b29a1 Gerd Hoffmann
        break;
308 1b4b29a1 Gerd Hoffmann
309 50b7963e Hans de Goede
    default:
310 50b7963e Hans de Goede
        break;
311 50b7963e Hans de Goede
    }
312 50b7963e Hans de Goede
    usb_packet_complete(s, p);
313 50b7963e Hans de Goede
}
314 50b7963e Hans de Goede
315 bb36d470 bellard
/* XXX: fix overflow */
316 bb36d470 bellard
int set_usb_string(uint8_t *buf, const char *str)
317 bb36d470 bellard
{
318 bb36d470 bellard
    int len, i;
319 bb36d470 bellard
    uint8_t *q;
320 bb36d470 bellard
321 bb36d470 bellard
    q = buf;
322 bb36d470 bellard
    len = strlen(str);
323 ce5c37c2 pbrook
    *q++ = 2 * len + 2;
324 bb36d470 bellard
    *q++ = 3;
325 bb36d470 bellard
    for(i = 0; i < len; i++) {
326 bb36d470 bellard
        *q++ = str[i];
327 bb36d470 bellard
        *q++ = 0;
328 bb36d470 bellard
    }
329 bb36d470 bellard
    return q - buf;
330 bb36d470 bellard
}
331 4d611c9a pbrook
332 73796fe6 Gerd Hoffmann
USBDevice *usb_find_device(USBPort *port, uint8_t addr)
333 73796fe6 Gerd Hoffmann
{
334 73796fe6 Gerd Hoffmann
    USBDevice *dev = port->dev;
335 73796fe6 Gerd Hoffmann
336 73796fe6 Gerd Hoffmann
    if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
337 73796fe6 Gerd Hoffmann
        return NULL;
338 73796fe6 Gerd Hoffmann
    }
339 73796fe6 Gerd Hoffmann
    if (dev->addr == addr) {
340 73796fe6 Gerd Hoffmann
        return dev;
341 73796fe6 Gerd Hoffmann
    }
342 73796fe6 Gerd Hoffmann
    return usb_device_find_device(dev, addr);
343 73796fe6 Gerd Hoffmann
}
344 73796fe6 Gerd Hoffmann
345 db4be873 Gerd Hoffmann
static int usb_process_one(USBPacket *p)
346 db4be873 Gerd Hoffmann
{
347 db4be873 Gerd Hoffmann
    USBDevice *dev = p->ep->dev;
348 db4be873 Gerd Hoffmann
349 db4be873 Gerd Hoffmann
    if (p->ep->nr == 0) {
350 db4be873 Gerd Hoffmann
        /* control pipe */
351 1b4b29a1 Gerd Hoffmann
        if (p->parameter) {
352 1b4b29a1 Gerd Hoffmann
            return do_parameter(dev, p);
353 1b4b29a1 Gerd Hoffmann
        }
354 db4be873 Gerd Hoffmann
        switch (p->pid) {
355 db4be873 Gerd Hoffmann
        case USB_TOKEN_SETUP:
356 db4be873 Gerd Hoffmann
            return do_token_setup(dev, p);
357 db4be873 Gerd Hoffmann
        case USB_TOKEN_IN:
358 db4be873 Gerd Hoffmann
            return do_token_in(dev, p);
359 db4be873 Gerd Hoffmann
        case USB_TOKEN_OUT:
360 db4be873 Gerd Hoffmann
            return do_token_out(dev, p);
361 db4be873 Gerd Hoffmann
        default:
362 db4be873 Gerd Hoffmann
            return USB_RET_STALL;
363 db4be873 Gerd Hoffmann
        }
364 db4be873 Gerd Hoffmann
    } else {
365 db4be873 Gerd Hoffmann
        /* data pipe */
366 db4be873 Gerd Hoffmann
        return usb_device_handle_data(dev, p);
367 db4be873 Gerd Hoffmann
    }
368 db4be873 Gerd Hoffmann
}
369 db4be873 Gerd Hoffmann
370 53aa8c0e Gerd Hoffmann
/* Hand over a packet to a device for processing.  Return value
371 53aa8c0e Gerd Hoffmann
   USB_RET_ASYNC indicates the processing isn't finished yet, the
372 53aa8c0e Gerd Hoffmann
   driver will call usb_packet_complete() when done processing it. */
373 53aa8c0e Gerd Hoffmann
int usb_handle_packet(USBDevice *dev, USBPacket *p)
374 53aa8c0e Gerd Hoffmann
{
375 53aa8c0e Gerd Hoffmann
    int ret;
376 53aa8c0e Gerd Hoffmann
377 98861f51 Gerd Hoffmann
    if (dev == NULL) {
378 98861f51 Gerd Hoffmann
        return USB_RET_NODEV;
379 98861f51 Gerd Hoffmann
    }
380 079d0b7f Gerd Hoffmann
    assert(dev == p->ep->dev);
381 1977f93d Gerd Hoffmann
    assert(dev->state == USB_STATE_DEFAULT);
382 5ac2731c Gerd Hoffmann
    usb_packet_check_state(p, USB_PACKET_SETUP);
383 db4be873 Gerd Hoffmann
    assert(p->ep != NULL);
384 1977f93d Gerd Hoffmann
385 0132b4b6 Hans de Goede
    /* Submitting a new packet clears halt */
386 0132b4b6 Hans de Goede
    if (p->ep->halted) {
387 0132b4b6 Hans de Goede
        assert(QTAILQ_EMPTY(&p->ep->queue));
388 0132b4b6 Hans de Goede
        p->ep->halted = false;
389 0132b4b6 Hans de Goede
    }
390 0132b4b6 Hans de Goede
391 7936e0f0 Gerd Hoffmann
    if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
392 db4be873 Gerd Hoffmann
        ret = usb_process_one(p);
393 db4be873 Gerd Hoffmann
        if (ret == USB_RET_ASYNC) {
394 db4be873 Gerd Hoffmann
            usb_packet_set_state(p, USB_PACKET_ASYNC);
395 db4be873 Gerd Hoffmann
            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
396 db4be873 Gerd Hoffmann
        } else {
397 0132b4b6 Hans de Goede
            /*
398 0132b4b6 Hans de Goede
             * When pipelining is enabled usb-devices must always return async,
399 0132b4b6 Hans de Goede
             * otherwise packets can complete out of order!
400 0132b4b6 Hans de Goede
             */
401 9c1f6765 Hans de Goede
            assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
402 cc409974 Hans de Goede
            if (ret != USB_RET_NAK) {
403 cc409974 Hans de Goede
                p->result = ret;
404 cc409974 Hans de Goede
                usb_packet_set_state(p, USB_PACKET_COMPLETE);
405 cc409974 Hans de Goede
            }
406 1977f93d Gerd Hoffmann
        }
407 1977f93d Gerd Hoffmann
    } else {
408 db4be873 Gerd Hoffmann
        ret = USB_RET_ASYNC;
409 db4be873 Gerd Hoffmann
        usb_packet_set_state(p, USB_PACKET_QUEUED);
410 db4be873 Gerd Hoffmann
        QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
411 4ff658fb Gerd Hoffmann
    }
412 53aa8c0e Gerd Hoffmann
    return ret;
413 89b9b79f aliguori
}
414 4ff658fb Gerd Hoffmann
415 0132b4b6 Hans de Goede
static void __usb_packet_complete(USBDevice *dev, USBPacket *p)
416 0132b4b6 Hans de Goede
{
417 0132b4b6 Hans de Goede
    USBEndpoint *ep = p->ep;
418 0132b4b6 Hans de Goede
419 0132b4b6 Hans de Goede
    assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK);
420 0132b4b6 Hans de Goede
421 0132b4b6 Hans de Goede
    if (p->result < 0) {
422 0132b4b6 Hans de Goede
        ep->halted = true;
423 0132b4b6 Hans de Goede
    }
424 0132b4b6 Hans de Goede
    usb_packet_set_state(p, USB_PACKET_COMPLETE);
425 0132b4b6 Hans de Goede
    QTAILQ_REMOVE(&ep->queue, p, queue);
426 0132b4b6 Hans de Goede
    dev->port->ops->complete(dev->port, p);
427 0132b4b6 Hans de Goede
}
428 0132b4b6 Hans de Goede
429 4ff658fb Gerd Hoffmann
/* Notify the controller that an async packet is complete.  This should only
430 4ff658fb Gerd Hoffmann
   be called for packets previously deferred by returning USB_RET_ASYNC from
431 4ff658fb Gerd Hoffmann
   handle_packet. */
432 4ff658fb Gerd Hoffmann
void usb_packet_complete(USBDevice *dev, USBPacket *p)
433 4ff658fb Gerd Hoffmann
{
434 db4be873 Gerd Hoffmann
    USBEndpoint *ep = p->ep;
435 db4be873 Gerd Hoffmann
    int ret;
436 db4be873 Gerd Hoffmann
437 5ac2731c Gerd Hoffmann
    usb_packet_check_state(p, USB_PACKET_ASYNC);
438 db4be873 Gerd Hoffmann
    assert(QTAILQ_FIRST(&ep->queue) == p);
439 0132b4b6 Hans de Goede
    __usb_packet_complete(dev, p);
440 db4be873 Gerd Hoffmann
441 0132b4b6 Hans de Goede
    while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) {
442 db4be873 Gerd Hoffmann
        p = QTAILQ_FIRST(&ep->queue);
443 eb9d4673 Gerd Hoffmann
        if (p->state == USB_PACKET_ASYNC) {
444 eb9d4673 Gerd Hoffmann
            break;
445 eb9d4673 Gerd Hoffmann
        }
446 5ac2731c Gerd Hoffmann
        usb_packet_check_state(p, USB_PACKET_QUEUED);
447 db4be873 Gerd Hoffmann
        ret = usb_process_one(p);
448 db4be873 Gerd Hoffmann
        if (ret == USB_RET_ASYNC) {
449 db4be873 Gerd Hoffmann
            usb_packet_set_state(p, USB_PACKET_ASYNC);
450 db4be873 Gerd Hoffmann
            break;
451 db4be873 Gerd Hoffmann
        }
452 db4be873 Gerd Hoffmann
        p->result = ret;
453 0132b4b6 Hans de Goede
        __usb_packet_complete(ep->dev, p);
454 db4be873 Gerd Hoffmann
    }
455 4ff658fb Gerd Hoffmann
}
456 4ff658fb Gerd Hoffmann
457 4ff658fb Gerd Hoffmann
/* Cancel an active packet.  The packed must have been deferred by
458 4ff658fb Gerd Hoffmann
   returning USB_RET_ASYNC from handle_packet, and not yet
459 4ff658fb Gerd Hoffmann
   completed.  */
460 4ff658fb Gerd Hoffmann
void usb_cancel_packet(USBPacket * p)
461 4ff658fb Gerd Hoffmann
{
462 db4be873 Gerd Hoffmann
    bool callback = (p->state == USB_PACKET_ASYNC);
463 db4be873 Gerd Hoffmann
    assert(usb_packet_is_inflight(p));
464 db4be873 Gerd Hoffmann
    usb_packet_set_state(p, USB_PACKET_CANCELED);
465 db4be873 Gerd Hoffmann
    QTAILQ_REMOVE(&p->ep->queue, p, queue);
466 db4be873 Gerd Hoffmann
    if (callback) {
467 db4be873 Gerd Hoffmann
        usb_device_cancel_packet(p->ep->dev, p);
468 db4be873 Gerd Hoffmann
    }
469 4ff658fb Gerd Hoffmann
}
470 4f4321c1 Gerd Hoffmann
471 4f4321c1 Gerd Hoffmann
472 4f4321c1 Gerd Hoffmann
void usb_packet_init(USBPacket *p)
473 4f4321c1 Gerd Hoffmann
{
474 4f4321c1 Gerd Hoffmann
    qemu_iovec_init(&p->iov, 1);
475 4f4321c1 Gerd Hoffmann
}
476 4f4321c1 Gerd Hoffmann
477 5ac2731c Gerd Hoffmann
static const char *usb_packet_state_name(USBPacketState state)
478 db4be873 Gerd Hoffmann
{
479 db4be873 Gerd Hoffmann
    static const char *name[] = {
480 db4be873 Gerd Hoffmann
        [USB_PACKET_UNDEFINED] = "undef",
481 db4be873 Gerd Hoffmann
        [USB_PACKET_SETUP]     = "setup",
482 db4be873 Gerd Hoffmann
        [USB_PACKET_QUEUED]    = "queued",
483 db4be873 Gerd Hoffmann
        [USB_PACKET_ASYNC]     = "async",
484 db4be873 Gerd Hoffmann
        [USB_PACKET_COMPLETE]  = "complete",
485 db4be873 Gerd Hoffmann
        [USB_PACKET_CANCELED]  = "canceled",
486 db4be873 Gerd Hoffmann
    };
487 5ac2731c Gerd Hoffmann
    if (state < ARRAY_SIZE(name)) {
488 5ac2731c Gerd Hoffmann
        return name[state];
489 5ac2731c Gerd Hoffmann
    }
490 5ac2731c Gerd Hoffmann
    return "INVALID";
491 5ac2731c Gerd Hoffmann
}
492 5ac2731c Gerd Hoffmann
493 5ac2731c Gerd Hoffmann
void usb_packet_check_state(USBPacket *p, USBPacketState expected)
494 5ac2731c Gerd Hoffmann
{
495 5ac2731c Gerd Hoffmann
    USBDevice *dev;
496 5ac2731c Gerd Hoffmann
    USBBus *bus;
497 5ac2731c Gerd Hoffmann
498 5ac2731c Gerd Hoffmann
    if (p->state == expected) {
499 5ac2731c Gerd Hoffmann
        return;
500 5ac2731c Gerd Hoffmann
    }
501 5ac2731c Gerd Hoffmann
    dev = p->ep->dev;
502 5ac2731c Gerd Hoffmann
    bus = usb_bus_from_device(dev);
503 5ac2731c Gerd Hoffmann
    trace_usb_packet_state_fault(bus->busnr, dev->port->path, p->ep->nr, p,
504 5ac2731c Gerd Hoffmann
                                 usb_packet_state_name(p->state),
505 5ac2731c Gerd Hoffmann
                                 usb_packet_state_name(expected));
506 5ac2731c Gerd Hoffmann
    assert(!"usb packet state check failed");
507 5ac2731c Gerd Hoffmann
}
508 5ac2731c Gerd Hoffmann
509 5ac2731c Gerd Hoffmann
void usb_packet_set_state(USBPacket *p, USBPacketState state)
510 5ac2731c Gerd Hoffmann
{
511 f5bf14bf Gerd Hoffmann
    if (p->ep) {
512 f5bf14bf Gerd Hoffmann
        USBDevice *dev = p->ep->dev;
513 f5bf14bf Gerd Hoffmann
        USBBus *bus = usb_bus_from_device(dev);
514 f5bf14bf Gerd Hoffmann
        trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, p,
515 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(p->state),
516 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(state));
517 f5bf14bf Gerd Hoffmann
    } else {
518 f5bf14bf Gerd Hoffmann
        trace_usb_packet_state_change(-1, "", -1, p,
519 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(p->state),
520 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(state));
521 f5bf14bf Gerd Hoffmann
    }
522 db4be873 Gerd Hoffmann
    p->state = state;
523 db4be873 Gerd Hoffmann
}
524 db4be873 Gerd Hoffmann
525 e983395d Gerd Hoffmann
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id)
526 4f4321c1 Gerd Hoffmann
{
527 f53c398a Gerd Hoffmann
    assert(!usb_packet_is_inflight(p));
528 0cc6a0f1 Gerd Hoffmann
    assert(p->iov.iov != NULL);
529 e983395d Gerd Hoffmann
    p->id = id;
530 4f4321c1 Gerd Hoffmann
    p->pid = pid;
531 079d0b7f Gerd Hoffmann
    p->ep = ep;
532 4f4321c1 Gerd Hoffmann
    p->result = 0;
533 1b4b29a1 Gerd Hoffmann
    p->parameter = 0;
534 4f4321c1 Gerd Hoffmann
    qemu_iovec_reset(&p->iov);
535 db4be873 Gerd Hoffmann
    usb_packet_set_state(p, USB_PACKET_SETUP);
536 4f4321c1 Gerd Hoffmann
}
537 4f4321c1 Gerd Hoffmann
538 4f4321c1 Gerd Hoffmann
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
539 4f4321c1 Gerd Hoffmann
{
540 4f4321c1 Gerd Hoffmann
    qemu_iovec_add(&p->iov, ptr, len);
541 4f4321c1 Gerd Hoffmann
}
542 4f4321c1 Gerd Hoffmann
543 4f4321c1 Gerd Hoffmann
void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
544 4f4321c1 Gerd Hoffmann
{
545 4f4321c1 Gerd Hoffmann
    assert(p->result >= 0);
546 4f4321c1 Gerd Hoffmann
    assert(p->result + bytes <= p->iov.size);
547 4f4321c1 Gerd Hoffmann
    switch (p->pid) {
548 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_SETUP:
549 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_OUT:
550 dcf6f5e1 Michael Tokarev
        iov_to_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes);
551 4f4321c1 Gerd Hoffmann
        break;
552 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_IN:
553 dcf6f5e1 Michael Tokarev
        iov_from_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes);
554 4f4321c1 Gerd Hoffmann
        break;
555 4f4321c1 Gerd Hoffmann
    default:
556 4f4321c1 Gerd Hoffmann
        fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
557 4f4321c1 Gerd Hoffmann
        abort();
558 4f4321c1 Gerd Hoffmann
    }
559 4f4321c1 Gerd Hoffmann
    p->result += bytes;
560 4f4321c1 Gerd Hoffmann
}
561 4f4321c1 Gerd Hoffmann
562 4f4321c1 Gerd Hoffmann
void usb_packet_skip(USBPacket *p, size_t bytes)
563 4f4321c1 Gerd Hoffmann
{
564 4f4321c1 Gerd Hoffmann
    assert(p->result >= 0);
565 4f4321c1 Gerd Hoffmann
    assert(p->result + bytes <= p->iov.size);
566 4f4321c1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_IN) {
567 dcf6f5e1 Michael Tokarev
        iov_memset(p->iov.iov, p->iov.niov, p->result, 0, bytes);
568 4f4321c1 Gerd Hoffmann
    }
569 4f4321c1 Gerd Hoffmann
    p->result += bytes;
570 4f4321c1 Gerd Hoffmann
}
571 4f4321c1 Gerd Hoffmann
572 4f4321c1 Gerd Hoffmann
void usb_packet_cleanup(USBPacket *p)
573 4f4321c1 Gerd Hoffmann
{
574 f53c398a Gerd Hoffmann
    assert(!usb_packet_is_inflight(p));
575 4f4321c1 Gerd Hoffmann
    qemu_iovec_destroy(&p->iov);
576 4f4321c1 Gerd Hoffmann
}
577 d8e17efd Gerd Hoffmann
578 19deaa08 Gerd Hoffmann
void usb_ep_reset(USBDevice *dev)
579 d8e17efd Gerd Hoffmann
{
580 d8e17efd Gerd Hoffmann
    int ep;
581 d8e17efd Gerd Hoffmann
582 63095ab5 Gerd Hoffmann
    dev->ep_ctl.nr = 0;
583 25d5de7d Gerd Hoffmann
    dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
584 25d5de7d Gerd Hoffmann
    dev->ep_ctl.ifnum = 0;
585 25d5de7d Gerd Hoffmann
    dev->ep_ctl.dev = dev;
586 7936e0f0 Gerd Hoffmann
    dev->ep_ctl.pipeline = false;
587 d8e17efd Gerd Hoffmann
    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
588 63095ab5 Gerd Hoffmann
        dev->ep_in[ep].nr = ep + 1;
589 63095ab5 Gerd Hoffmann
        dev->ep_out[ep].nr = ep + 1;
590 63095ab5 Gerd Hoffmann
        dev->ep_in[ep].pid = USB_TOKEN_IN;
591 63095ab5 Gerd Hoffmann
        dev->ep_out[ep].pid = USB_TOKEN_OUT;
592 d8e17efd Gerd Hoffmann
        dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
593 d8e17efd Gerd Hoffmann
        dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
594 7c37e6a4 Gerd Hoffmann
        dev->ep_in[ep].ifnum = USB_INTERFACE_INVALID;
595 7c37e6a4 Gerd Hoffmann
        dev->ep_out[ep].ifnum = USB_INTERFACE_INVALID;
596 25d5de7d Gerd Hoffmann
        dev->ep_in[ep].dev = dev;
597 25d5de7d Gerd Hoffmann
        dev->ep_out[ep].dev = dev;
598 7936e0f0 Gerd Hoffmann
        dev->ep_in[ep].pipeline = false;
599 7936e0f0 Gerd Hoffmann
        dev->ep_out[ep].pipeline = false;
600 19deaa08 Gerd Hoffmann
    }
601 19deaa08 Gerd Hoffmann
}
602 19deaa08 Gerd Hoffmann
603 19deaa08 Gerd Hoffmann
void usb_ep_init(USBDevice *dev)
604 19deaa08 Gerd Hoffmann
{
605 19deaa08 Gerd Hoffmann
    int ep;
606 19deaa08 Gerd Hoffmann
607 19deaa08 Gerd Hoffmann
    usb_ep_reset(dev);
608 19deaa08 Gerd Hoffmann
    QTAILQ_INIT(&dev->ep_ctl.queue);
609 19deaa08 Gerd Hoffmann
    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
610 db4be873 Gerd Hoffmann
        QTAILQ_INIT(&dev->ep_in[ep].queue);
611 db4be873 Gerd Hoffmann
        QTAILQ_INIT(&dev->ep_out[ep].queue);
612 d8e17efd Gerd Hoffmann
    }
613 d8e17efd Gerd Hoffmann
}
614 d8e17efd Gerd Hoffmann
615 5b6780d0 Gerd Hoffmann
void usb_ep_dump(USBDevice *dev)
616 5b6780d0 Gerd Hoffmann
{
617 5b6780d0 Gerd Hoffmann
    static const char *tname[] = {
618 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_CONTROL] = "control",
619 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_ISOC]    = "isoc",
620 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_BULK]    = "bulk",
621 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_INT]     = "int",
622 5b6780d0 Gerd Hoffmann
    };
623 5b6780d0 Gerd Hoffmann
    int ifnum, ep, first;
624 5b6780d0 Gerd Hoffmann
625 5b6780d0 Gerd Hoffmann
    fprintf(stderr, "Device \"%s\", config %d\n",
626 5b6780d0 Gerd Hoffmann
            dev->product_desc, dev->configuration);
627 5b6780d0 Gerd Hoffmann
    for (ifnum = 0; ifnum < 16; ifnum++) {
628 5b6780d0 Gerd Hoffmann
        first = 1;
629 5b6780d0 Gerd Hoffmann
        for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
630 5b6780d0 Gerd Hoffmann
            if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
631 5b6780d0 Gerd Hoffmann
                dev->ep_in[ep].ifnum == ifnum) {
632 5b6780d0 Gerd Hoffmann
                if (first) {
633 5b6780d0 Gerd Hoffmann
                    first = 0;
634 5b6780d0 Gerd Hoffmann
                    fprintf(stderr, "  Interface %d, alternative %d\n",
635 5b6780d0 Gerd Hoffmann
                            ifnum, dev->altsetting[ifnum]);
636 5b6780d0 Gerd Hoffmann
                }
637 f003397c Gerd Hoffmann
                fprintf(stderr, "    Endpoint %d, IN, %s, %d max\n", ep,
638 f003397c Gerd Hoffmann
                        tname[dev->ep_in[ep].type],
639 f003397c Gerd Hoffmann
                        dev->ep_in[ep].max_packet_size);
640 5b6780d0 Gerd Hoffmann
            }
641 5b6780d0 Gerd Hoffmann
            if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
642 5b6780d0 Gerd Hoffmann
                dev->ep_out[ep].ifnum == ifnum) {
643 5b6780d0 Gerd Hoffmann
                if (first) {
644 5b6780d0 Gerd Hoffmann
                    first = 0;
645 5b6780d0 Gerd Hoffmann
                    fprintf(stderr, "  Interface %d, alternative %d\n",
646 5b6780d0 Gerd Hoffmann
                            ifnum, dev->altsetting[ifnum]);
647 5b6780d0 Gerd Hoffmann
                }
648 f003397c Gerd Hoffmann
                fprintf(stderr, "    Endpoint %d, OUT, %s, %d max\n", ep,
649 f003397c Gerd Hoffmann
                        tname[dev->ep_out[ep].type],
650 f003397c Gerd Hoffmann
                        dev->ep_out[ep].max_packet_size);
651 5b6780d0 Gerd Hoffmann
            }
652 5b6780d0 Gerd Hoffmann
        }
653 5b6780d0 Gerd Hoffmann
    }
654 5b6780d0 Gerd Hoffmann
    fprintf(stderr, "--\n");
655 5b6780d0 Gerd Hoffmann
}
656 5b6780d0 Gerd Hoffmann
657 d8e17efd Gerd Hoffmann
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
658 d8e17efd Gerd Hoffmann
{
659 079d0b7f Gerd Hoffmann
    struct USBEndpoint *eps;
660 079d0b7f Gerd Hoffmann
661 079d0b7f Gerd Hoffmann
    if (dev == NULL) {
662 079d0b7f Gerd Hoffmann
        return NULL;
663 079d0b7f Gerd Hoffmann
    }
664 079d0b7f Gerd Hoffmann
    eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
665 25d5de7d Gerd Hoffmann
    if (ep == 0) {
666 25d5de7d Gerd Hoffmann
        return &dev->ep_ctl;
667 25d5de7d Gerd Hoffmann
    }
668 d8e17efd Gerd Hoffmann
    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
669 d8e17efd Gerd Hoffmann
    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
670 d8e17efd Gerd Hoffmann
    return eps + ep - 1;
671 d8e17efd Gerd Hoffmann
}
672 d8e17efd Gerd Hoffmann
673 d8e17efd Gerd Hoffmann
uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
674 d8e17efd Gerd Hoffmann
{
675 d8e17efd Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
676 d8e17efd Gerd Hoffmann
    return uep->type;
677 d8e17efd Gerd Hoffmann
}
678 d8e17efd Gerd Hoffmann
679 d8e17efd Gerd Hoffmann
void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
680 d8e17efd Gerd Hoffmann
{
681 d8e17efd Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
682 d8e17efd Gerd Hoffmann
    uep->type = type;
683 d8e17efd Gerd Hoffmann
}
684 82f02fe9 Gerd Hoffmann
685 82f02fe9 Gerd Hoffmann
uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
686 82f02fe9 Gerd Hoffmann
{
687 82f02fe9 Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
688 82f02fe9 Gerd Hoffmann
    return uep->ifnum;
689 82f02fe9 Gerd Hoffmann
}
690 82f02fe9 Gerd Hoffmann
691 82f02fe9 Gerd Hoffmann
void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
692 82f02fe9 Gerd Hoffmann
{
693 82f02fe9 Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
694 82f02fe9 Gerd Hoffmann
    uep->ifnum = ifnum;
695 82f02fe9 Gerd Hoffmann
}
696 f003397c Gerd Hoffmann
697 f003397c Gerd Hoffmann
void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
698 f003397c Gerd Hoffmann
                                uint16_t raw)
699 f003397c Gerd Hoffmann
{
700 f003397c Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
701 f003397c Gerd Hoffmann
    int size, microframes;
702 f003397c Gerd Hoffmann
703 f003397c Gerd Hoffmann
    size = raw & 0x7ff;
704 f003397c Gerd Hoffmann
    switch ((raw >> 11) & 3) {
705 f003397c Gerd Hoffmann
    case 1:
706 f003397c Gerd Hoffmann
        microframes = 2;
707 f003397c Gerd Hoffmann
        break;
708 f003397c Gerd Hoffmann
    case 2:
709 f003397c Gerd Hoffmann
        microframes = 3;
710 f003397c Gerd Hoffmann
        break;
711 f003397c Gerd Hoffmann
    default:
712 f003397c Gerd Hoffmann
        microframes = 1;
713 f003397c Gerd Hoffmann
        break;
714 f003397c Gerd Hoffmann
    }
715 f003397c Gerd Hoffmann
    uep->max_packet_size = size * microframes;
716 f003397c Gerd Hoffmann
}
717 f003397c Gerd Hoffmann
718 f003397c Gerd Hoffmann
int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
719 f003397c Gerd Hoffmann
{
720 f003397c Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
721 f003397c Gerd Hoffmann
    return uep->max_packet_size;
722 f003397c Gerd Hoffmann
}
723 7936e0f0 Gerd Hoffmann
724 7936e0f0 Gerd Hoffmann
void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
725 7936e0f0 Gerd Hoffmann
{
726 7936e0f0 Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
727 7936e0f0 Gerd Hoffmann
    uep->pipeline = enabled;
728 7936e0f0 Gerd Hoffmann
}
729 c13a9e61 Hans de Goede
730 c13a9e61 Hans de Goede
USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
731 c13a9e61 Hans de Goede
                                    uint64_t id)
732 c13a9e61 Hans de Goede
{
733 c13a9e61 Hans de Goede
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
734 c13a9e61 Hans de Goede
    USBPacket *p;
735 c13a9e61 Hans de Goede
736 c13a9e61 Hans de Goede
    while ((p = QTAILQ_FIRST(&uep->queue)) != NULL) {
737 c13a9e61 Hans de Goede
        if (p->id == id) {
738 c13a9e61 Hans de Goede
            return p;
739 c13a9e61 Hans de Goede
        }
740 c13a9e61 Hans de Goede
    }
741 c13a9e61 Hans de Goede
742 c13a9e61 Hans de Goede
    return NULL;
743 c13a9e61 Hans de Goede
}