Statistics
| Branch: | Revision:

root / hw / usb / core.c @ afd347ab

History | View | Annotate | Download (21.6 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 1de7afc9 Paolo Bonzini
#include "qemu/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 9a77a0f5 Hans de Goede
static void do_token_setup(USBDevice *s, USBPacket *p)
101 89b9b79f aliguori
{
102 89b9b79f aliguori
    int request, value, index;
103 89b9b79f aliguori
104 4f4321c1 Gerd Hoffmann
    if (p->iov.size != 8) {
105 9a77a0f5 Hans de Goede
        p->status = USB_RET_STALL;
106 9a77a0f5 Hans de Goede
        return;
107 4f4321c1 Gerd Hoffmann
    }
108 4f4321c1 Gerd Hoffmann
109 4f4321c1 Gerd Hoffmann
    usb_packet_copy(p, s->setup_buf, p->iov.size);
110 9a77a0f5 Hans de Goede
    p->actual_length = 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 9a77a0f5 Hans de Goede
        usb_device_handle_control(s, p, request, value, index,
120 9a77a0f5 Hans de Goede
                                  s->setup_len, s->data_buf);
121 9a77a0f5 Hans de Goede
        if (p->status == USB_RET_ASYNC) {
122 9a77a0f5 Hans de Goede
            s->setup_state = SETUP_STATE_SETUP;
123 9a77a0f5 Hans de Goede
        }
124 9a77a0f5 Hans de Goede
        if (p->status != USB_RET_SUCCESS) {
125 9a77a0f5 Hans de Goede
            return;
126 50b7963e Hans de Goede
        }
127 89b9b79f aliguori
128 9a77a0f5 Hans de Goede
        if (p->actual_length < s->setup_len) {
129 9a77a0f5 Hans de Goede
            s->setup_len = p->actual_length;
130 9a77a0f5 Hans de Goede
        }
131 89b9b79f aliguori
        s->setup_state = SETUP_STATE_DATA;
132 89b9b79f aliguori
    } else {
133 19f33223 Hans de Goede
        if (s->setup_len > sizeof(s->data_buf)) {
134 19f33223 Hans de Goede
            fprintf(stderr,
135 19f33223 Hans de Goede
                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
136 19f33223 Hans de Goede
                s->setup_len, sizeof(s->data_buf));
137 9a77a0f5 Hans de Goede
            p->status = USB_RET_STALL;
138 9a77a0f5 Hans de Goede
            return;
139 19f33223 Hans de Goede
        }
140 89b9b79f aliguori
        if (s->setup_len == 0)
141 89b9b79f aliguori
            s->setup_state = SETUP_STATE_ACK;
142 89b9b79f aliguori
        else
143 89b9b79f aliguori
            s->setup_state = SETUP_STATE_DATA;
144 89b9b79f aliguori
    }
145 89b9b79f aliguori
146 9a77a0f5 Hans de Goede
    p->actual_length = 8;
147 89b9b79f aliguori
}
148 89b9b79f aliguori
149 9a77a0f5 Hans de Goede
static void do_token_in(USBDevice *s, USBPacket *p)
150 bb36d470 bellard
{
151 89b9b79f aliguori
    int request, value, index;
152 89b9b79f aliguori
153 079d0b7f Gerd Hoffmann
    assert(p->ep->nr == 0);
154 89b9b79f aliguori
155 89b9b79f aliguori
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
156 89b9b79f aliguori
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
157 89b9b79f aliguori
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
158 89b9b79f aliguori
 
159 89b9b79f aliguori
    switch(s->setup_state) {
160 89b9b79f aliguori
    case SETUP_STATE_ACK:
161 89b9b79f aliguori
        if (!(s->setup_buf[0] & USB_DIR_IN)) {
162 9a77a0f5 Hans de Goede
            usb_device_handle_control(s, p, request, value, index,
163 9a77a0f5 Hans de Goede
                                      s->setup_len, s->data_buf);
164 9a77a0f5 Hans de Goede
            if (p->status == USB_RET_ASYNC) {
165 9a77a0f5 Hans de Goede
                return;
166 007fd62f Hans de Goede
            }
167 007fd62f Hans de Goede
            s->setup_state = SETUP_STATE_IDLE;
168 9a77a0f5 Hans de Goede
            p->actual_length = 0;
169 89b9b79f aliguori
        }
170 9a77a0f5 Hans de Goede
        break;
171 89b9b79f aliguori
172 89b9b79f aliguori
    case SETUP_STATE_DATA:
173 89b9b79f aliguori
        if (s->setup_buf[0] & USB_DIR_IN) {
174 89b9b79f aliguori
            int len = s->setup_len - s->setup_index;
175 4f4321c1 Gerd Hoffmann
            if (len > p->iov.size) {
176 4f4321c1 Gerd Hoffmann
                len = p->iov.size;
177 4f4321c1 Gerd Hoffmann
            }
178 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf + s->setup_index, len);
179 89b9b79f aliguori
            s->setup_index += len;
180 9a77a0f5 Hans de Goede
            if (s->setup_index >= s->setup_len) {
181 89b9b79f aliguori
                s->setup_state = SETUP_STATE_ACK;
182 9a77a0f5 Hans de Goede
            }
183 9a77a0f5 Hans de Goede
            return;
184 89b9b79f aliguori
        }
185 89b9b79f aliguori
        s->setup_state = SETUP_STATE_IDLE;
186 9a77a0f5 Hans de Goede
        p->status = USB_RET_STALL;
187 9a77a0f5 Hans de Goede
        break;
188 89b9b79f aliguori
189 89b9b79f aliguori
    default:
190 9a77a0f5 Hans de Goede
        p->status = USB_RET_STALL;
191 89b9b79f aliguori
    }
192 89b9b79f aliguori
}
193 89b9b79f aliguori
194 9a77a0f5 Hans de Goede
static void do_token_out(USBDevice *s, USBPacket *p)
195 89b9b79f aliguori
{
196 079d0b7f Gerd Hoffmann
    assert(p->ep->nr == 0);
197 89b9b79f aliguori
198 89b9b79f aliguori
    switch(s->setup_state) {
199 89b9b79f aliguori
    case SETUP_STATE_ACK:
200 89b9b79f aliguori
        if (s->setup_buf[0] & USB_DIR_IN) {
201 89b9b79f aliguori
            s->setup_state = SETUP_STATE_IDLE;
202 89b9b79f aliguori
            /* transfer OK */
203 89b9b79f aliguori
        } else {
204 89b9b79f aliguori
            /* ignore additional output */
205 89b9b79f aliguori
        }
206 9a77a0f5 Hans de Goede
        break;
207 89b9b79f aliguori
208 89b9b79f aliguori
    case SETUP_STATE_DATA:
209 89b9b79f aliguori
        if (!(s->setup_buf[0] & USB_DIR_IN)) {
210 89b9b79f aliguori
            int len = s->setup_len - s->setup_index;
211 4f4321c1 Gerd Hoffmann
            if (len > p->iov.size) {
212 4f4321c1 Gerd Hoffmann
                len = p->iov.size;
213 4f4321c1 Gerd Hoffmann
            }
214 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf + s->setup_index, len);
215 89b9b79f aliguori
            s->setup_index += len;
216 9a77a0f5 Hans de Goede
            if (s->setup_index >= s->setup_len) {
217 89b9b79f aliguori
                s->setup_state = SETUP_STATE_ACK;
218 9a77a0f5 Hans de Goede
            }
219 9a77a0f5 Hans de Goede
            return;
220 89b9b79f aliguori
        }
221 89b9b79f aliguori
        s->setup_state = SETUP_STATE_IDLE;
222 9a77a0f5 Hans de Goede
        p->status = USB_RET_STALL;
223 9a77a0f5 Hans de Goede
        break;
224 89b9b79f aliguori
225 89b9b79f aliguori
    default:
226 9a77a0f5 Hans de Goede
        p->status = USB_RET_STALL;
227 89b9b79f aliguori
    }
228 89b9b79f aliguori
}
229 bb36d470 bellard
230 9a77a0f5 Hans de Goede
static void do_parameter(USBDevice *s, USBPacket *p)
231 1b4b29a1 Gerd Hoffmann
{
232 9a77a0f5 Hans de Goede
    int i, request, value, index;
233 1b4b29a1 Gerd Hoffmann
234 1b4b29a1 Gerd Hoffmann
    for (i = 0; i < 8; i++) {
235 1b4b29a1 Gerd Hoffmann
        s->setup_buf[i] = p->parameter >> (i*8);
236 1b4b29a1 Gerd Hoffmann
    }
237 1b4b29a1 Gerd Hoffmann
238 1b4b29a1 Gerd Hoffmann
    s->setup_state = SETUP_STATE_PARAM;
239 1b4b29a1 Gerd Hoffmann
    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
240 1b4b29a1 Gerd Hoffmann
    s->setup_index = 0;
241 1b4b29a1 Gerd Hoffmann
242 1b4b29a1 Gerd Hoffmann
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
243 1b4b29a1 Gerd Hoffmann
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
244 1b4b29a1 Gerd Hoffmann
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
245 1b4b29a1 Gerd Hoffmann
246 1b4b29a1 Gerd Hoffmann
    if (s->setup_len > sizeof(s->data_buf)) {
247 1b4b29a1 Gerd Hoffmann
        fprintf(stderr,
248 1b4b29a1 Gerd Hoffmann
                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
249 1b4b29a1 Gerd Hoffmann
                s->setup_len, sizeof(s->data_buf));
250 9a77a0f5 Hans de Goede
        p->status = USB_RET_STALL;
251 9a77a0f5 Hans de Goede
        return;
252 1b4b29a1 Gerd Hoffmann
    }
253 1b4b29a1 Gerd Hoffmann
254 1b4b29a1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_OUT) {
255 1b4b29a1 Gerd Hoffmann
        usb_packet_copy(p, s->data_buf, s->setup_len);
256 1b4b29a1 Gerd Hoffmann
    }
257 1b4b29a1 Gerd Hoffmann
258 9a77a0f5 Hans de Goede
    usb_device_handle_control(s, p, request, value, index,
259 9a77a0f5 Hans de Goede
                              s->setup_len, s->data_buf);
260 9a77a0f5 Hans de Goede
    if (p->status == USB_RET_ASYNC) {
261 9a77a0f5 Hans de Goede
        return;
262 1b4b29a1 Gerd Hoffmann
    }
263 1b4b29a1 Gerd Hoffmann
264 9a77a0f5 Hans de Goede
    if (p->actual_length < s->setup_len) {
265 9a77a0f5 Hans de Goede
        s->setup_len = p->actual_length;
266 1b4b29a1 Gerd Hoffmann
    }
267 1b4b29a1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_IN) {
268 9a77a0f5 Hans de Goede
        p->actual_length = 0;
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
273 50b7963e Hans de Goede
/* ctrl complete function for devices which use usb_generic_handle_packet and
274 50b7963e Hans de Goede
   may return USB_RET_ASYNC from their handle_control callback. Device code
275 50b7963e Hans de Goede
   which does this *must* call this function instead of the normal
276 50b7963e Hans de Goede
   usb_packet_complete to complete their async control packets. */
277 50b7963e Hans de Goede
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
278 50b7963e Hans de Goede
{
279 9a77a0f5 Hans de Goede
    if (p->status < 0) {
280 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_IDLE;
281 50b7963e Hans de Goede
    }
282 50b7963e Hans de Goede
283 50b7963e Hans de Goede
    switch (s->setup_state) {
284 50b7963e Hans de Goede
    case SETUP_STATE_SETUP:
285 9a77a0f5 Hans de Goede
        if (p->actual_length < s->setup_len) {
286 9a77a0f5 Hans de Goede
            s->setup_len = p->actual_length;
287 50b7963e Hans de Goede
        }
288 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_DATA;
289 9a77a0f5 Hans de Goede
        p->actual_length = 8;
290 50b7963e Hans de Goede
        break;
291 50b7963e Hans de Goede
292 50b7963e Hans de Goede
    case SETUP_STATE_ACK:
293 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_IDLE;
294 9a77a0f5 Hans de Goede
        p->actual_length = 0;
295 50b7963e Hans de Goede
        break;
296 50b7963e Hans de Goede
297 1b4b29a1 Gerd Hoffmann
    case SETUP_STATE_PARAM:
298 9a77a0f5 Hans de Goede
        if (p->actual_length < s->setup_len) {
299 9a77a0f5 Hans de Goede
            s->setup_len = p->actual_length;
300 1b4b29a1 Gerd Hoffmann
        }
301 1b4b29a1 Gerd Hoffmann
        if (p->pid == USB_TOKEN_IN) {
302 9a77a0f5 Hans de Goede
            p->actual_length = 0;
303 1b4b29a1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf, s->setup_len);
304 1b4b29a1 Gerd Hoffmann
        }
305 1b4b29a1 Gerd Hoffmann
        break;
306 1b4b29a1 Gerd Hoffmann
307 50b7963e Hans de Goede
    default:
308 50b7963e Hans de Goede
        break;
309 50b7963e Hans de Goede
    }
310 50b7963e Hans de Goede
    usb_packet_complete(s, p);
311 50b7963e Hans de Goede
}
312 50b7963e Hans de Goede
313 bb36d470 bellard
/* XXX: fix overflow */
314 bb36d470 bellard
int set_usb_string(uint8_t *buf, const char *str)
315 bb36d470 bellard
{
316 bb36d470 bellard
    int len, i;
317 bb36d470 bellard
    uint8_t *q;
318 bb36d470 bellard
319 bb36d470 bellard
    q = buf;
320 bb36d470 bellard
    len = strlen(str);
321 ce5c37c2 pbrook
    *q++ = 2 * len + 2;
322 bb36d470 bellard
    *q++ = 3;
323 bb36d470 bellard
    for(i = 0; i < len; i++) {
324 bb36d470 bellard
        *q++ = str[i];
325 bb36d470 bellard
        *q++ = 0;
326 bb36d470 bellard
    }
327 bb36d470 bellard
    return q - buf;
328 bb36d470 bellard
}
329 4d611c9a pbrook
330 73796fe6 Gerd Hoffmann
USBDevice *usb_find_device(USBPort *port, uint8_t addr)
331 73796fe6 Gerd Hoffmann
{
332 73796fe6 Gerd Hoffmann
    USBDevice *dev = port->dev;
333 73796fe6 Gerd Hoffmann
334 73796fe6 Gerd Hoffmann
    if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
335 73796fe6 Gerd Hoffmann
        return NULL;
336 73796fe6 Gerd Hoffmann
    }
337 73796fe6 Gerd Hoffmann
    if (dev->addr == addr) {
338 73796fe6 Gerd Hoffmann
        return dev;
339 73796fe6 Gerd Hoffmann
    }
340 73796fe6 Gerd Hoffmann
    return usb_device_find_device(dev, addr);
341 73796fe6 Gerd Hoffmann
}
342 73796fe6 Gerd Hoffmann
343 9a77a0f5 Hans de Goede
static void usb_process_one(USBPacket *p)
344 db4be873 Gerd Hoffmann
{
345 db4be873 Gerd Hoffmann
    USBDevice *dev = p->ep->dev;
346 db4be873 Gerd Hoffmann
347 9a77a0f5 Hans de Goede
    /*
348 9a77a0f5 Hans de Goede
     * Handlers expect status to be initialized to USB_RET_SUCCESS, but it
349 9a77a0f5 Hans de Goede
     * can be USB_RET_NAK here from a previous usb_process_one() call,
350 9a77a0f5 Hans de Goede
     * or USB_RET_ASYNC from going through usb_queue_one().
351 9a77a0f5 Hans de Goede
     */
352 9a77a0f5 Hans de Goede
    p->status = USB_RET_SUCCESS;
353 9a77a0f5 Hans de Goede
354 db4be873 Gerd Hoffmann
    if (p->ep->nr == 0) {
355 db4be873 Gerd Hoffmann
        /* control pipe */
356 1b4b29a1 Gerd Hoffmann
        if (p->parameter) {
357 9a77a0f5 Hans de Goede
            do_parameter(dev, p);
358 9a77a0f5 Hans de Goede
            return;
359 1b4b29a1 Gerd Hoffmann
        }
360 db4be873 Gerd Hoffmann
        switch (p->pid) {
361 db4be873 Gerd Hoffmann
        case USB_TOKEN_SETUP:
362 9a77a0f5 Hans de Goede
            do_token_setup(dev, p);
363 9a77a0f5 Hans de Goede
            break;
364 db4be873 Gerd Hoffmann
        case USB_TOKEN_IN:
365 9a77a0f5 Hans de Goede
            do_token_in(dev, p);
366 9a77a0f5 Hans de Goede
            break;
367 db4be873 Gerd Hoffmann
        case USB_TOKEN_OUT:
368 9a77a0f5 Hans de Goede
            do_token_out(dev, p);
369 9a77a0f5 Hans de Goede
            break;
370 db4be873 Gerd Hoffmann
        default:
371 9a77a0f5 Hans de Goede
            p->status = USB_RET_STALL;
372 db4be873 Gerd Hoffmann
        }
373 db4be873 Gerd Hoffmann
    } else {
374 db4be873 Gerd Hoffmann
        /* data pipe */
375 9a77a0f5 Hans de Goede
        usb_device_handle_data(dev, p);
376 db4be873 Gerd Hoffmann
    }
377 db4be873 Gerd Hoffmann
}
378 db4be873 Gerd Hoffmann
379 9a77a0f5 Hans de Goede
static void usb_queue_one(USBPacket *p)
380 9a77a0f5 Hans de Goede
{
381 9a77a0f5 Hans de Goede
    usb_packet_set_state(p, USB_PACKET_QUEUED);
382 9a77a0f5 Hans de Goede
    QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
383 9a77a0f5 Hans de Goede
    p->status = USB_RET_ASYNC;
384 9a77a0f5 Hans de Goede
}
385 9a77a0f5 Hans de Goede
386 9a77a0f5 Hans de Goede
/* Hand over a packet to a device for processing.  p->status ==
387 53aa8c0e Gerd Hoffmann
   USB_RET_ASYNC indicates the processing isn't finished yet, the
388 53aa8c0e Gerd Hoffmann
   driver will call usb_packet_complete() when done processing it. */
389 9a77a0f5 Hans de Goede
void usb_handle_packet(USBDevice *dev, USBPacket *p)
390 53aa8c0e Gerd Hoffmann
{
391 98861f51 Gerd Hoffmann
    if (dev == NULL) {
392 9a77a0f5 Hans de Goede
        p->status = USB_RET_NODEV;
393 9a77a0f5 Hans de Goede
        return;
394 98861f51 Gerd Hoffmann
    }
395 079d0b7f Gerd Hoffmann
    assert(dev == p->ep->dev);
396 1977f93d Gerd Hoffmann
    assert(dev->state == USB_STATE_DEFAULT);
397 5ac2731c Gerd Hoffmann
    usb_packet_check_state(p, USB_PACKET_SETUP);
398 db4be873 Gerd Hoffmann
    assert(p->ep != NULL);
399 1977f93d Gerd Hoffmann
400 0132b4b6 Hans de Goede
    /* Submitting a new packet clears halt */
401 0132b4b6 Hans de Goede
    if (p->ep->halted) {
402 0132b4b6 Hans de Goede
        assert(QTAILQ_EMPTY(&p->ep->queue));
403 0132b4b6 Hans de Goede
        p->ep->halted = false;
404 0132b4b6 Hans de Goede
    }
405 0132b4b6 Hans de Goede
406 7936e0f0 Gerd Hoffmann
    if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
407 9a77a0f5 Hans de Goede
        usb_process_one(p);
408 9a77a0f5 Hans de Goede
        if (p->status == USB_RET_ASYNC) {
409 be41efde Hans de Goede
            /* hcd drivers cannot handle async for isoc */
410 aaac7434 Hans de Goede
            assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
411 be41efde Hans de Goede
            /* using async for interrupt packets breaks migration */
412 be41efde Hans de Goede
            assert(p->ep->type != USB_ENDPOINT_XFER_INT ||
413 be41efde Hans de Goede
                   (dev->flags & USB_DEV_FLAG_IS_HOST));
414 db4be873 Gerd Hoffmann
            usb_packet_set_state(p, USB_PACKET_ASYNC);
415 db4be873 Gerd Hoffmann
            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
416 9a77a0f5 Hans de Goede
        } else if (p->status == USB_RET_ADD_TO_QUEUE) {
417 9a77a0f5 Hans de Goede
            usb_queue_one(p);
418 db4be873 Gerd Hoffmann
        } else {
419 0132b4b6 Hans de Goede
            /*
420 0132b4b6 Hans de Goede
             * When pipelining is enabled usb-devices must always return async,
421 0132b4b6 Hans de Goede
             * otherwise packets can complete out of order!
422 0132b4b6 Hans de Goede
             */
423 9c1f6765 Hans de Goede
            assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
424 9a77a0f5 Hans de Goede
            if (p->status != USB_RET_NAK) {
425 cc409974 Hans de Goede
                usb_packet_set_state(p, USB_PACKET_COMPLETE);
426 cc409974 Hans de Goede
            }
427 1977f93d Gerd Hoffmann
        }
428 1977f93d Gerd Hoffmann
    } else {
429 9a77a0f5 Hans de Goede
        usb_queue_one(p);
430 4ff658fb Gerd Hoffmann
    }
431 89b9b79f aliguori
}
432 4ff658fb Gerd Hoffmann
433 d0ff81b8 Hans de Goede
void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
434 0132b4b6 Hans de Goede
{
435 0132b4b6 Hans de Goede
    USBEndpoint *ep = p->ep;
436 0132b4b6 Hans de Goede
437 d0ff81b8 Hans de Goede
    assert(QTAILQ_FIRST(&ep->queue) == p);
438 9a77a0f5 Hans de Goede
    assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK);
439 0132b4b6 Hans de Goede
440 9a77a0f5 Hans de Goede
    if (p->status != USB_RET_SUCCESS ||
441 9a77a0f5 Hans de Goede
            (p->short_not_ok && (p->actual_length < p->iov.size))) {
442 0132b4b6 Hans de Goede
        ep->halted = true;
443 0132b4b6 Hans de Goede
    }
444 0132b4b6 Hans de Goede
    usb_packet_set_state(p, USB_PACKET_COMPLETE);
445 0132b4b6 Hans de Goede
    QTAILQ_REMOVE(&ep->queue, p, queue);
446 0132b4b6 Hans de Goede
    dev->port->ops->complete(dev->port, p);
447 0132b4b6 Hans de Goede
}
448 0132b4b6 Hans de Goede
449 4ff658fb Gerd Hoffmann
/* Notify the controller that an async packet is complete.  This should only
450 4ff658fb Gerd Hoffmann
   be called for packets previously deferred by returning USB_RET_ASYNC from
451 4ff658fb Gerd Hoffmann
   handle_packet. */
452 4ff658fb Gerd Hoffmann
void usb_packet_complete(USBDevice *dev, USBPacket *p)
453 4ff658fb Gerd Hoffmann
{
454 db4be873 Gerd Hoffmann
    USBEndpoint *ep = p->ep;
455 db4be873 Gerd Hoffmann
456 5ac2731c Gerd Hoffmann
    usb_packet_check_state(p, USB_PACKET_ASYNC);
457 d0ff81b8 Hans de Goede
    usb_packet_complete_one(dev, p);
458 db4be873 Gerd Hoffmann
459 0cae7b1a Hans de Goede
    while (!QTAILQ_EMPTY(&ep->queue)) {
460 db4be873 Gerd Hoffmann
        p = QTAILQ_FIRST(&ep->queue);
461 0cae7b1a Hans de Goede
        if (ep->halted) {
462 0cae7b1a Hans de Goede
            /* Empty the queue on a halt */
463 9a77a0f5 Hans de Goede
            p->status = USB_RET_REMOVE_FROM_QUEUE;
464 0cae7b1a Hans de Goede
            dev->port->ops->complete(dev->port, p);
465 0cae7b1a Hans de Goede
            continue;
466 0cae7b1a Hans de Goede
        }
467 eb9d4673 Gerd Hoffmann
        if (p->state == USB_PACKET_ASYNC) {
468 eb9d4673 Gerd Hoffmann
            break;
469 eb9d4673 Gerd Hoffmann
        }
470 5ac2731c Gerd Hoffmann
        usb_packet_check_state(p, USB_PACKET_QUEUED);
471 9a77a0f5 Hans de Goede
        usb_process_one(p);
472 9a77a0f5 Hans de Goede
        if (p->status == USB_RET_ASYNC) {
473 db4be873 Gerd Hoffmann
            usb_packet_set_state(p, USB_PACKET_ASYNC);
474 db4be873 Gerd Hoffmann
            break;
475 db4be873 Gerd Hoffmann
        }
476 d0ff81b8 Hans de Goede
        usb_packet_complete_one(ep->dev, p);
477 db4be873 Gerd Hoffmann
    }
478 4ff658fb Gerd Hoffmann
}
479 4ff658fb Gerd Hoffmann
480 4ff658fb Gerd Hoffmann
/* Cancel an active packet.  The packed must have been deferred by
481 4ff658fb Gerd Hoffmann
   returning USB_RET_ASYNC from handle_packet, and not yet
482 4ff658fb Gerd Hoffmann
   completed.  */
483 4ff658fb Gerd Hoffmann
void usb_cancel_packet(USBPacket * p)
484 4ff658fb Gerd Hoffmann
{
485 db4be873 Gerd Hoffmann
    bool callback = (p->state == USB_PACKET_ASYNC);
486 db4be873 Gerd Hoffmann
    assert(usb_packet_is_inflight(p));
487 db4be873 Gerd Hoffmann
    usb_packet_set_state(p, USB_PACKET_CANCELED);
488 db4be873 Gerd Hoffmann
    QTAILQ_REMOVE(&p->ep->queue, p, queue);
489 db4be873 Gerd Hoffmann
    if (callback) {
490 db4be873 Gerd Hoffmann
        usb_device_cancel_packet(p->ep->dev, p);
491 db4be873 Gerd Hoffmann
    }
492 4ff658fb Gerd Hoffmann
}
493 4f4321c1 Gerd Hoffmann
494 4f4321c1 Gerd Hoffmann
495 4f4321c1 Gerd Hoffmann
void usb_packet_init(USBPacket *p)
496 4f4321c1 Gerd Hoffmann
{
497 4f4321c1 Gerd Hoffmann
    qemu_iovec_init(&p->iov, 1);
498 4f4321c1 Gerd Hoffmann
}
499 4f4321c1 Gerd Hoffmann
500 5ac2731c Gerd Hoffmann
static const char *usb_packet_state_name(USBPacketState state)
501 db4be873 Gerd Hoffmann
{
502 db4be873 Gerd Hoffmann
    static const char *name[] = {
503 db4be873 Gerd Hoffmann
        [USB_PACKET_UNDEFINED] = "undef",
504 db4be873 Gerd Hoffmann
        [USB_PACKET_SETUP]     = "setup",
505 db4be873 Gerd Hoffmann
        [USB_PACKET_QUEUED]    = "queued",
506 db4be873 Gerd Hoffmann
        [USB_PACKET_ASYNC]     = "async",
507 db4be873 Gerd Hoffmann
        [USB_PACKET_COMPLETE]  = "complete",
508 db4be873 Gerd Hoffmann
        [USB_PACKET_CANCELED]  = "canceled",
509 db4be873 Gerd Hoffmann
    };
510 5ac2731c Gerd Hoffmann
    if (state < ARRAY_SIZE(name)) {
511 5ac2731c Gerd Hoffmann
        return name[state];
512 5ac2731c Gerd Hoffmann
    }
513 5ac2731c Gerd Hoffmann
    return "INVALID";
514 5ac2731c Gerd Hoffmann
}
515 5ac2731c Gerd Hoffmann
516 5ac2731c Gerd Hoffmann
void usb_packet_check_state(USBPacket *p, USBPacketState expected)
517 5ac2731c Gerd Hoffmann
{
518 5ac2731c Gerd Hoffmann
    USBDevice *dev;
519 5ac2731c Gerd Hoffmann
    USBBus *bus;
520 5ac2731c Gerd Hoffmann
521 5ac2731c Gerd Hoffmann
    if (p->state == expected) {
522 5ac2731c Gerd Hoffmann
        return;
523 5ac2731c Gerd Hoffmann
    }
524 5ac2731c Gerd Hoffmann
    dev = p->ep->dev;
525 5ac2731c Gerd Hoffmann
    bus = usb_bus_from_device(dev);
526 5ac2731c Gerd Hoffmann
    trace_usb_packet_state_fault(bus->busnr, dev->port->path, p->ep->nr, p,
527 5ac2731c Gerd Hoffmann
                                 usb_packet_state_name(p->state),
528 5ac2731c Gerd Hoffmann
                                 usb_packet_state_name(expected));
529 5ac2731c Gerd Hoffmann
    assert(!"usb packet state check failed");
530 5ac2731c Gerd Hoffmann
}
531 5ac2731c Gerd Hoffmann
532 5ac2731c Gerd Hoffmann
void usb_packet_set_state(USBPacket *p, USBPacketState state)
533 5ac2731c Gerd Hoffmann
{
534 f5bf14bf Gerd Hoffmann
    if (p->ep) {
535 f5bf14bf Gerd Hoffmann
        USBDevice *dev = p->ep->dev;
536 f5bf14bf Gerd Hoffmann
        USBBus *bus = usb_bus_from_device(dev);
537 f5bf14bf Gerd Hoffmann
        trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, p,
538 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(p->state),
539 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(state));
540 f5bf14bf Gerd Hoffmann
    } else {
541 f5bf14bf Gerd Hoffmann
        trace_usb_packet_state_change(-1, "", -1, p,
542 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(p->state),
543 f5bf14bf Gerd Hoffmann
                                      usb_packet_state_name(state));
544 f5bf14bf Gerd Hoffmann
    }
545 db4be873 Gerd Hoffmann
    p->state = state;
546 db4be873 Gerd Hoffmann
}
547 db4be873 Gerd Hoffmann
548 6ba43f1f Hans de Goede
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id,
549 a6fb2ddb Hans de Goede
                      bool short_not_ok, bool int_req)
550 4f4321c1 Gerd Hoffmann
{
551 f53c398a Gerd Hoffmann
    assert(!usb_packet_is_inflight(p));
552 0cc6a0f1 Gerd Hoffmann
    assert(p->iov.iov != NULL);
553 e983395d Gerd Hoffmann
    p->id = id;
554 4f4321c1 Gerd Hoffmann
    p->pid = pid;
555 079d0b7f Gerd Hoffmann
    p->ep = ep;
556 9a77a0f5 Hans de Goede
    p->status = USB_RET_SUCCESS;
557 9a77a0f5 Hans de Goede
    p->actual_length = 0;
558 1b4b29a1 Gerd Hoffmann
    p->parameter = 0;
559 6ba43f1f Hans de Goede
    p->short_not_ok = short_not_ok;
560 a6fb2ddb Hans de Goede
    p->int_req = int_req;
561 a552a966 Hans de Goede
    p->combined = NULL;
562 4f4321c1 Gerd Hoffmann
    qemu_iovec_reset(&p->iov);
563 db4be873 Gerd Hoffmann
    usb_packet_set_state(p, USB_PACKET_SETUP);
564 4f4321c1 Gerd Hoffmann
}
565 4f4321c1 Gerd Hoffmann
566 4f4321c1 Gerd Hoffmann
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
567 4f4321c1 Gerd Hoffmann
{
568 4f4321c1 Gerd Hoffmann
    qemu_iovec_add(&p->iov, ptr, len);
569 4f4321c1 Gerd Hoffmann
}
570 4f4321c1 Gerd Hoffmann
571 4f4321c1 Gerd Hoffmann
void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
572 4f4321c1 Gerd Hoffmann
{
573 9a77a0f5 Hans de Goede
    assert(p->actual_length >= 0);
574 9a77a0f5 Hans de Goede
    assert(p->actual_length + bytes <= p->iov.size);
575 4f4321c1 Gerd Hoffmann
    switch (p->pid) {
576 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_SETUP:
577 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_OUT:
578 9a77a0f5 Hans de Goede
        iov_to_buf(p->iov.iov, p->iov.niov, p->actual_length, ptr, bytes);
579 4f4321c1 Gerd Hoffmann
        break;
580 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_IN:
581 9a77a0f5 Hans de Goede
        iov_from_buf(p->iov.iov, p->iov.niov, p->actual_length, ptr, bytes);
582 4f4321c1 Gerd Hoffmann
        break;
583 4f4321c1 Gerd Hoffmann
    default:
584 4f4321c1 Gerd Hoffmann
        fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
585 4f4321c1 Gerd Hoffmann
        abort();
586 4f4321c1 Gerd Hoffmann
    }
587 9a77a0f5 Hans de Goede
    p->actual_length += bytes;
588 4f4321c1 Gerd Hoffmann
}
589 4f4321c1 Gerd Hoffmann
590 4f4321c1 Gerd Hoffmann
void usb_packet_skip(USBPacket *p, size_t bytes)
591 4f4321c1 Gerd Hoffmann
{
592 9a77a0f5 Hans de Goede
    assert(p->actual_length >= 0);
593 9a77a0f5 Hans de Goede
    assert(p->actual_length + bytes <= p->iov.size);
594 4f4321c1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_IN) {
595 9a77a0f5 Hans de Goede
        iov_memset(p->iov.iov, p->iov.niov, p->actual_length, 0, bytes);
596 4f4321c1 Gerd Hoffmann
    }
597 9a77a0f5 Hans de Goede
    p->actual_length += bytes;
598 4f4321c1 Gerd Hoffmann
}
599 4f4321c1 Gerd Hoffmann
600 4f4321c1 Gerd Hoffmann
void usb_packet_cleanup(USBPacket *p)
601 4f4321c1 Gerd Hoffmann
{
602 f53c398a Gerd Hoffmann
    assert(!usb_packet_is_inflight(p));
603 4f4321c1 Gerd Hoffmann
    qemu_iovec_destroy(&p->iov);
604 4f4321c1 Gerd Hoffmann
}
605 d8e17efd Gerd Hoffmann
606 19deaa08 Gerd Hoffmann
void usb_ep_reset(USBDevice *dev)
607 d8e17efd Gerd Hoffmann
{
608 d8e17efd Gerd Hoffmann
    int ep;
609 d8e17efd Gerd Hoffmann
610 63095ab5 Gerd Hoffmann
    dev->ep_ctl.nr = 0;
611 25d5de7d Gerd Hoffmann
    dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
612 25d5de7d Gerd Hoffmann
    dev->ep_ctl.ifnum = 0;
613 25d5de7d Gerd Hoffmann
    dev->ep_ctl.dev = dev;
614 7936e0f0 Gerd Hoffmann
    dev->ep_ctl.pipeline = false;
615 d8e17efd Gerd Hoffmann
    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
616 63095ab5 Gerd Hoffmann
        dev->ep_in[ep].nr = ep + 1;
617 63095ab5 Gerd Hoffmann
        dev->ep_out[ep].nr = ep + 1;
618 63095ab5 Gerd Hoffmann
        dev->ep_in[ep].pid = USB_TOKEN_IN;
619 63095ab5 Gerd Hoffmann
        dev->ep_out[ep].pid = USB_TOKEN_OUT;
620 d8e17efd Gerd Hoffmann
        dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
621 d8e17efd Gerd Hoffmann
        dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
622 7c37e6a4 Gerd Hoffmann
        dev->ep_in[ep].ifnum = USB_INTERFACE_INVALID;
623 7c37e6a4 Gerd Hoffmann
        dev->ep_out[ep].ifnum = USB_INTERFACE_INVALID;
624 25d5de7d Gerd Hoffmann
        dev->ep_in[ep].dev = dev;
625 25d5de7d Gerd Hoffmann
        dev->ep_out[ep].dev = dev;
626 7936e0f0 Gerd Hoffmann
        dev->ep_in[ep].pipeline = false;
627 7936e0f0 Gerd Hoffmann
        dev->ep_out[ep].pipeline = false;
628 19deaa08 Gerd Hoffmann
    }
629 19deaa08 Gerd Hoffmann
}
630 19deaa08 Gerd Hoffmann
631 19deaa08 Gerd Hoffmann
void usb_ep_init(USBDevice *dev)
632 19deaa08 Gerd Hoffmann
{
633 19deaa08 Gerd Hoffmann
    int ep;
634 19deaa08 Gerd Hoffmann
635 19deaa08 Gerd Hoffmann
    usb_ep_reset(dev);
636 19deaa08 Gerd Hoffmann
    QTAILQ_INIT(&dev->ep_ctl.queue);
637 19deaa08 Gerd Hoffmann
    for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
638 db4be873 Gerd Hoffmann
        QTAILQ_INIT(&dev->ep_in[ep].queue);
639 db4be873 Gerd Hoffmann
        QTAILQ_INIT(&dev->ep_out[ep].queue);
640 d8e17efd Gerd Hoffmann
    }
641 d8e17efd Gerd Hoffmann
}
642 d8e17efd Gerd Hoffmann
643 5b6780d0 Gerd Hoffmann
void usb_ep_dump(USBDevice *dev)
644 5b6780d0 Gerd Hoffmann
{
645 5b6780d0 Gerd Hoffmann
    static const char *tname[] = {
646 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_CONTROL] = "control",
647 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_ISOC]    = "isoc",
648 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_BULK]    = "bulk",
649 5b6780d0 Gerd Hoffmann
        [USB_ENDPOINT_XFER_INT]     = "int",
650 5b6780d0 Gerd Hoffmann
    };
651 5b6780d0 Gerd Hoffmann
    int ifnum, ep, first;
652 5b6780d0 Gerd Hoffmann
653 5b6780d0 Gerd Hoffmann
    fprintf(stderr, "Device \"%s\", config %d\n",
654 5b6780d0 Gerd Hoffmann
            dev->product_desc, dev->configuration);
655 5b6780d0 Gerd Hoffmann
    for (ifnum = 0; ifnum < 16; ifnum++) {
656 5b6780d0 Gerd Hoffmann
        first = 1;
657 5b6780d0 Gerd Hoffmann
        for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
658 5b6780d0 Gerd Hoffmann
            if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
659 5b6780d0 Gerd Hoffmann
                dev->ep_in[ep].ifnum == ifnum) {
660 5b6780d0 Gerd Hoffmann
                if (first) {
661 5b6780d0 Gerd Hoffmann
                    first = 0;
662 5b6780d0 Gerd Hoffmann
                    fprintf(stderr, "  Interface %d, alternative %d\n",
663 5b6780d0 Gerd Hoffmann
                            ifnum, dev->altsetting[ifnum]);
664 5b6780d0 Gerd Hoffmann
                }
665 f003397c Gerd Hoffmann
                fprintf(stderr, "    Endpoint %d, IN, %s, %d max\n", ep,
666 f003397c Gerd Hoffmann
                        tname[dev->ep_in[ep].type],
667 f003397c Gerd Hoffmann
                        dev->ep_in[ep].max_packet_size);
668 5b6780d0 Gerd Hoffmann
            }
669 5b6780d0 Gerd Hoffmann
            if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
670 5b6780d0 Gerd Hoffmann
                dev->ep_out[ep].ifnum == ifnum) {
671 5b6780d0 Gerd Hoffmann
                if (first) {
672 5b6780d0 Gerd Hoffmann
                    first = 0;
673 5b6780d0 Gerd Hoffmann
                    fprintf(stderr, "  Interface %d, alternative %d\n",
674 5b6780d0 Gerd Hoffmann
                            ifnum, dev->altsetting[ifnum]);
675 5b6780d0 Gerd Hoffmann
                }
676 f003397c Gerd Hoffmann
                fprintf(stderr, "    Endpoint %d, OUT, %s, %d max\n", ep,
677 f003397c Gerd Hoffmann
                        tname[dev->ep_out[ep].type],
678 f003397c Gerd Hoffmann
                        dev->ep_out[ep].max_packet_size);
679 5b6780d0 Gerd Hoffmann
            }
680 5b6780d0 Gerd Hoffmann
        }
681 5b6780d0 Gerd Hoffmann
    }
682 5b6780d0 Gerd Hoffmann
    fprintf(stderr, "--\n");
683 5b6780d0 Gerd Hoffmann
}
684 5b6780d0 Gerd Hoffmann
685 d8e17efd Gerd Hoffmann
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
686 d8e17efd Gerd Hoffmann
{
687 079d0b7f Gerd Hoffmann
    struct USBEndpoint *eps;
688 079d0b7f Gerd Hoffmann
689 079d0b7f Gerd Hoffmann
    if (dev == NULL) {
690 079d0b7f Gerd Hoffmann
        return NULL;
691 079d0b7f Gerd Hoffmann
    }
692 079d0b7f Gerd Hoffmann
    eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
693 25d5de7d Gerd Hoffmann
    if (ep == 0) {
694 25d5de7d Gerd Hoffmann
        return &dev->ep_ctl;
695 25d5de7d Gerd Hoffmann
    }
696 d8e17efd Gerd Hoffmann
    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
697 d8e17efd Gerd Hoffmann
    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
698 d8e17efd Gerd Hoffmann
    return eps + ep - 1;
699 d8e17efd Gerd Hoffmann
}
700 d8e17efd Gerd Hoffmann
701 d8e17efd Gerd Hoffmann
uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
702 d8e17efd Gerd Hoffmann
{
703 d8e17efd Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
704 d8e17efd Gerd Hoffmann
    return uep->type;
705 d8e17efd Gerd Hoffmann
}
706 d8e17efd Gerd Hoffmann
707 d8e17efd Gerd Hoffmann
void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
708 d8e17efd Gerd Hoffmann
{
709 d8e17efd Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
710 d8e17efd Gerd Hoffmann
    uep->type = type;
711 d8e17efd Gerd Hoffmann
}
712 82f02fe9 Gerd Hoffmann
713 82f02fe9 Gerd Hoffmann
uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
714 82f02fe9 Gerd Hoffmann
{
715 82f02fe9 Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
716 82f02fe9 Gerd Hoffmann
    return uep->ifnum;
717 82f02fe9 Gerd Hoffmann
}
718 82f02fe9 Gerd Hoffmann
719 82f02fe9 Gerd Hoffmann
void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
720 82f02fe9 Gerd Hoffmann
{
721 82f02fe9 Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
722 82f02fe9 Gerd Hoffmann
    uep->ifnum = ifnum;
723 82f02fe9 Gerd Hoffmann
}
724 f003397c Gerd Hoffmann
725 f003397c Gerd Hoffmann
void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
726 f003397c Gerd Hoffmann
                                uint16_t raw)
727 f003397c Gerd Hoffmann
{
728 f003397c Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
729 f003397c Gerd Hoffmann
    int size, microframes;
730 f003397c Gerd Hoffmann
731 f003397c Gerd Hoffmann
    size = raw & 0x7ff;
732 f003397c Gerd Hoffmann
    switch ((raw >> 11) & 3) {
733 f003397c Gerd Hoffmann
    case 1:
734 f003397c Gerd Hoffmann
        microframes = 2;
735 f003397c Gerd Hoffmann
        break;
736 f003397c Gerd Hoffmann
    case 2:
737 f003397c Gerd Hoffmann
        microframes = 3;
738 f003397c Gerd Hoffmann
        break;
739 f003397c Gerd Hoffmann
    default:
740 f003397c Gerd Hoffmann
        microframes = 1;
741 f003397c Gerd Hoffmann
        break;
742 f003397c Gerd Hoffmann
    }
743 f003397c Gerd Hoffmann
    uep->max_packet_size = size * microframes;
744 f003397c Gerd Hoffmann
}
745 f003397c Gerd Hoffmann
746 f003397c Gerd Hoffmann
int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
747 f003397c Gerd Hoffmann
{
748 f003397c Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
749 f003397c Gerd Hoffmann
    return uep->max_packet_size;
750 f003397c Gerd Hoffmann
}
751 7936e0f0 Gerd Hoffmann
752 7936e0f0 Gerd Hoffmann
void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
753 7936e0f0 Gerd Hoffmann
{
754 7936e0f0 Gerd Hoffmann
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
755 7936e0f0 Gerd Hoffmann
    uep->pipeline = enabled;
756 7936e0f0 Gerd Hoffmann
}
757 c13a9e61 Hans de Goede
758 c13a9e61 Hans de Goede
USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
759 c13a9e61 Hans de Goede
                                    uint64_t id)
760 c13a9e61 Hans de Goede
{
761 c13a9e61 Hans de Goede
    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
762 c13a9e61 Hans de Goede
    USBPacket *p;
763 c13a9e61 Hans de Goede
764 6735d433 Hans de Goede
    QTAILQ_FOREACH(p, &uep->queue, queue) {
765 c13a9e61 Hans de Goede
        if (p->id == id) {
766 c13a9e61 Hans de Goede
            return p;
767 c13a9e61 Hans de Goede
        }
768 c13a9e61 Hans de Goede
    }
769 c13a9e61 Hans de Goede
770 c13a9e61 Hans de Goede
    return NULL;
771 c13a9e61 Hans de Goede
}