Statistics
| Branch: | Revision:

root / hw / usb.c @ ac791b88

History | View | Annotate | Download (10.9 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 87ecb68b pbrook
#include "usb.h"
28 4f4321c1 Gerd Hoffmann
#include "iov.h"
29 bb36d470 bellard
30 891fb2cd Gerd Hoffmann
void usb_attach(USBPort *port)
31 bb36d470 bellard
{
32 891fb2cd Gerd Hoffmann
    USBDevice *dev = port->dev;
33 891fb2cd Gerd Hoffmann
34 891fb2cd Gerd Hoffmann
    assert(dev != NULL);
35 891fb2cd Gerd Hoffmann
    assert(dev->attached);
36 e0b8e72d Gerd Hoffmann
    assert(dev->state == USB_STATE_NOTATTACHED);
37 891fb2cd Gerd Hoffmann
    port->ops->attach(port);
38 891fb2cd Gerd Hoffmann
    usb_send_msg(dev, USB_MSG_ATTACH);
39 891fb2cd Gerd Hoffmann
}
40 891fb2cd Gerd Hoffmann
41 891fb2cd Gerd Hoffmann
void usb_detach(USBPort *port)
42 891fb2cd Gerd Hoffmann
{
43 891fb2cd Gerd Hoffmann
    USBDevice *dev = port->dev;
44 891fb2cd Gerd Hoffmann
45 891fb2cd Gerd Hoffmann
    assert(dev != NULL);
46 e0b8e72d Gerd Hoffmann
    assert(dev->state != USB_STATE_NOTATTACHED);
47 891fb2cd Gerd Hoffmann
    port->ops->detach(port);
48 891fb2cd Gerd Hoffmann
    usb_send_msg(dev, USB_MSG_DETACH);
49 bb36d470 bellard
}
50 bb36d470 bellard
51 e0b8e72d Gerd Hoffmann
void usb_reset(USBPort *port)
52 e0b8e72d Gerd Hoffmann
{
53 e0b8e72d Gerd Hoffmann
    USBDevice *dev = port->dev;
54 e0b8e72d Gerd Hoffmann
55 e0b8e72d Gerd Hoffmann
    assert(dev != NULL);
56 e0b8e72d Gerd Hoffmann
    usb_detach(port);
57 e0b8e72d Gerd Hoffmann
    usb_attach(port);
58 e0b8e72d Gerd Hoffmann
    usb_send_msg(dev, USB_MSG_RESET);
59 e0b8e72d Gerd Hoffmann
}
60 e0b8e72d Gerd Hoffmann
61 01eacab6 Gerd Hoffmann
void usb_wakeup(USBDevice *dev)
62 01eacab6 Gerd Hoffmann
{
63 01eacab6 Gerd Hoffmann
    if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
64 d47e59b8 Hans de Goede
        dev->port->ops->wakeup(dev->port);
65 01eacab6 Gerd Hoffmann
    }
66 01eacab6 Gerd Hoffmann
}
67 01eacab6 Gerd Hoffmann
68 bb36d470 bellard
/**********************/
69 89b9b79f aliguori
70 bb36d470 bellard
/* generic USB device helpers (you are not forced to use them when
71 bb36d470 bellard
   writing your USB device driver, but they help handling the
72 5fafdf24 ths
   protocol)
73 bb36d470 bellard
*/
74 bb36d470 bellard
75 50b7963e Hans de Goede
#define SETUP_STATE_IDLE  0
76 50b7963e Hans de Goede
#define SETUP_STATE_SETUP 1
77 50b7963e Hans de Goede
#define SETUP_STATE_DATA  2
78 50b7963e Hans de Goede
#define SETUP_STATE_ACK   3
79 bb36d470 bellard
80 89b9b79f aliguori
static int do_token_setup(USBDevice *s, USBPacket *p)
81 89b9b79f aliguori
{
82 89b9b79f aliguori
    int request, value, index;
83 89b9b79f aliguori
    int ret = 0;
84 89b9b79f aliguori
85 4f4321c1 Gerd Hoffmann
    if (p->iov.size != 8) {
86 89b9b79f aliguori
        return USB_RET_STALL;
87 4f4321c1 Gerd Hoffmann
    }
88 4f4321c1 Gerd Hoffmann
89 4f4321c1 Gerd Hoffmann
    usb_packet_copy(p, s->setup_buf, p->iov.size);
90 89b9b79f aliguori
    s->setup_len   = (s->setup_buf[7] << 8) | s->setup_buf[6];
91 89b9b79f aliguori
    s->setup_index = 0;
92 89b9b79f aliguori
93 89b9b79f aliguori
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
94 89b9b79f aliguori
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
95 89b9b79f aliguori
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
96 007fd62f Hans de Goede
97 89b9b79f aliguori
    if (s->setup_buf[0] & USB_DIR_IN) {
98 007fd62f Hans de Goede
        ret = s->info->handle_control(s, p, request, value, index,
99 806b6024 Gerd Hoffmann
                                      s->setup_len, s->data_buf);
100 50b7963e Hans de Goede
        if (ret == USB_RET_ASYNC) {
101 50b7963e Hans de Goede
             s->setup_state = SETUP_STATE_SETUP;
102 50b7963e Hans de Goede
             return USB_RET_ASYNC;
103 50b7963e Hans de Goede
        }
104 89b9b79f aliguori
        if (ret < 0)
105 89b9b79f aliguori
            return ret;
106 89b9b79f aliguori
107 89b9b79f aliguori
        if (ret < s->setup_len)
108 89b9b79f aliguori
            s->setup_len = ret;
109 89b9b79f aliguori
        s->setup_state = SETUP_STATE_DATA;
110 89b9b79f aliguori
    } else {
111 19f33223 Hans de Goede
        if (s->setup_len > sizeof(s->data_buf)) {
112 19f33223 Hans de Goede
            fprintf(stderr,
113 19f33223 Hans de Goede
                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
114 19f33223 Hans de Goede
                s->setup_len, sizeof(s->data_buf));
115 19f33223 Hans de Goede
            return USB_RET_STALL;
116 19f33223 Hans de Goede
        }
117 89b9b79f aliguori
        if (s->setup_len == 0)
118 89b9b79f aliguori
            s->setup_state = SETUP_STATE_ACK;
119 89b9b79f aliguori
        else
120 89b9b79f aliguori
            s->setup_state = SETUP_STATE_DATA;
121 89b9b79f aliguori
    }
122 89b9b79f aliguori
123 89b9b79f aliguori
    return ret;
124 89b9b79f aliguori
}
125 89b9b79f aliguori
126 89b9b79f aliguori
static int do_token_in(USBDevice *s, USBPacket *p)
127 bb36d470 bellard
{
128 89b9b79f aliguori
    int request, value, index;
129 89b9b79f aliguori
    int ret = 0;
130 89b9b79f aliguori
131 89b9b79f aliguori
    if (p->devep != 0)
132 806b6024 Gerd Hoffmann
        return s->info->handle_data(s, p);
133 89b9b79f aliguori
134 89b9b79f aliguori
    request = (s->setup_buf[0] << 8) | s->setup_buf[1];
135 89b9b79f aliguori
    value   = (s->setup_buf[3] << 8) | s->setup_buf[2];
136 89b9b79f aliguori
    index   = (s->setup_buf[5] << 8) | s->setup_buf[4];
137 89b9b79f aliguori
 
138 89b9b79f aliguori
    switch(s->setup_state) {
139 89b9b79f aliguori
    case SETUP_STATE_ACK:
140 89b9b79f aliguori
        if (!(s->setup_buf[0] & USB_DIR_IN)) {
141 007fd62f Hans de Goede
            ret = s->info->handle_control(s, p, request, value, index,
142 806b6024 Gerd Hoffmann
                                          s->setup_len, s->data_buf);
143 007fd62f Hans de Goede
            if (ret == USB_RET_ASYNC) {
144 007fd62f Hans de Goede
                return USB_RET_ASYNC;
145 007fd62f Hans de Goede
            }
146 007fd62f Hans de Goede
            s->setup_state = SETUP_STATE_IDLE;
147 89b9b79f aliguori
            if (ret > 0)
148 89b9b79f aliguori
                return 0;
149 89b9b79f aliguori
            return ret;
150 89b9b79f aliguori
        }
151 89b9b79f aliguori
152 89b9b79f aliguori
        /* return 0 byte */
153 89b9b79f aliguori
        return 0;
154 89b9b79f aliguori
155 89b9b79f aliguori
    case SETUP_STATE_DATA:
156 89b9b79f aliguori
        if (s->setup_buf[0] & USB_DIR_IN) {
157 89b9b79f aliguori
            int len = s->setup_len - s->setup_index;
158 4f4321c1 Gerd Hoffmann
            if (len > p->iov.size) {
159 4f4321c1 Gerd Hoffmann
                len = p->iov.size;
160 4f4321c1 Gerd Hoffmann
            }
161 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf + s->setup_index, len);
162 89b9b79f aliguori
            s->setup_index += len;
163 89b9b79f aliguori
            if (s->setup_index >= s->setup_len)
164 89b9b79f aliguori
                s->setup_state = SETUP_STATE_ACK;
165 89b9b79f aliguori
            return len;
166 89b9b79f aliguori
        }
167 89b9b79f aliguori
168 89b9b79f aliguori
        s->setup_state = SETUP_STATE_IDLE;
169 89b9b79f aliguori
        return USB_RET_STALL;
170 89b9b79f aliguori
171 89b9b79f aliguori
    default:
172 89b9b79f aliguori
        return USB_RET_STALL;
173 89b9b79f aliguori
    }
174 89b9b79f aliguori
}
175 89b9b79f aliguori
176 89b9b79f aliguori
static int do_token_out(USBDevice *s, USBPacket *p)
177 89b9b79f aliguori
{
178 89b9b79f aliguori
    if (p->devep != 0)
179 806b6024 Gerd Hoffmann
        return s->info->handle_data(s, p);
180 89b9b79f aliguori
181 89b9b79f aliguori
    switch(s->setup_state) {
182 89b9b79f aliguori
    case SETUP_STATE_ACK:
183 89b9b79f aliguori
        if (s->setup_buf[0] & USB_DIR_IN) {
184 89b9b79f aliguori
            s->setup_state = SETUP_STATE_IDLE;
185 89b9b79f aliguori
            /* transfer OK */
186 89b9b79f aliguori
        } else {
187 89b9b79f aliguori
            /* ignore additional output */
188 89b9b79f aliguori
        }
189 89b9b79f aliguori
        return 0;
190 89b9b79f aliguori
191 89b9b79f aliguori
    case SETUP_STATE_DATA:
192 89b9b79f aliguori
        if (!(s->setup_buf[0] & USB_DIR_IN)) {
193 89b9b79f aliguori
            int len = s->setup_len - s->setup_index;
194 4f4321c1 Gerd Hoffmann
            if (len > p->iov.size) {
195 4f4321c1 Gerd Hoffmann
                len = p->iov.size;
196 4f4321c1 Gerd Hoffmann
            }
197 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, s->data_buf + s->setup_index, len);
198 89b9b79f aliguori
            s->setup_index += len;
199 89b9b79f aliguori
            if (s->setup_index >= s->setup_len)
200 89b9b79f aliguori
                s->setup_state = SETUP_STATE_ACK;
201 89b9b79f aliguori
            return len;
202 89b9b79f aliguori
        }
203 89b9b79f aliguori
204 89b9b79f aliguori
        s->setup_state = SETUP_STATE_IDLE;
205 89b9b79f aliguori
        return USB_RET_STALL;
206 89b9b79f aliguori
207 89b9b79f aliguori
    default:
208 89b9b79f aliguori
        return USB_RET_STALL;
209 89b9b79f aliguori
    }
210 89b9b79f aliguori
}
211 bb36d470 bellard
212 89b9b79f aliguori
/*
213 89b9b79f aliguori
 * Generic packet handler.
214 89b9b79f aliguori
 * Called by the HC (host controller).
215 89b9b79f aliguori
 *
216 89b9b79f aliguori
 * Returns length of the transaction or one of the USB_RET_XXX codes.
217 89b9b79f aliguori
 */
218 89b9b79f aliguori
int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
219 89b9b79f aliguori
{
220 4d611c9a pbrook
    switch(p->pid) {
221 bb36d470 bellard
    case USB_MSG_ATTACH:
222 bb36d470 bellard
        s->state = USB_STATE_ATTACHED;
223 b6f77fbe Gerd Hoffmann
        if (s->info->handle_attach) {
224 b6f77fbe Gerd Hoffmann
            s->info->handle_attach(s);
225 b6f77fbe Gerd Hoffmann
        }
226 89b9b79f aliguori
        return 0;
227 89b9b79f aliguori
228 bb36d470 bellard
    case USB_MSG_DETACH:
229 bb36d470 bellard
        s->state = USB_STATE_NOTATTACHED;
230 89b9b79f aliguori
        return 0;
231 89b9b79f aliguori
232 bb36d470 bellard
    case USB_MSG_RESET:
233 bb36d470 bellard
        s->remote_wakeup = 0;
234 bb36d470 bellard
        s->addr = 0;
235 bb36d470 bellard
        s->state = USB_STATE_DEFAULT;
236 b6f77fbe Gerd Hoffmann
        if (s->info->handle_reset) {
237 b6f77fbe Gerd Hoffmann
            s->info->handle_reset(s);
238 b6f77fbe Gerd Hoffmann
        }
239 89b9b79f aliguori
        return 0;
240 89b9b79f aliguori
    }
241 89b9b79f aliguori
242 89b9b79f aliguori
    /* Rest of the PIDs must match our address */
243 89b9b79f aliguori
    if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
244 89b9b79f aliguori
        return USB_RET_NODEV;
245 89b9b79f aliguori
246 89b9b79f aliguori
    switch (p->pid) {
247 bb36d470 bellard
    case USB_TOKEN_SETUP:
248 89b9b79f aliguori
        return do_token_setup(s, p);
249 89b9b79f aliguori
250 bb36d470 bellard
    case USB_TOKEN_IN:
251 89b9b79f aliguori
        return do_token_in(s, p);
252 89b9b79f aliguori
253 bb36d470 bellard
    case USB_TOKEN_OUT:
254 89b9b79f aliguori
        return do_token_out(s, p);
255 89b9b79f aliguori
 
256 bb36d470 bellard
    default:
257 89b9b79f aliguori
        return USB_RET_STALL;
258 bb36d470 bellard
    }
259 bb36d470 bellard
}
260 bb36d470 bellard
261 50b7963e Hans de Goede
/* ctrl complete function for devices which use usb_generic_handle_packet and
262 50b7963e Hans de Goede
   may return USB_RET_ASYNC from their handle_control callback. Device code
263 50b7963e Hans de Goede
   which does this *must* call this function instead of the normal
264 50b7963e Hans de Goede
   usb_packet_complete to complete their async control packets. */
265 50b7963e Hans de Goede
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
266 50b7963e Hans de Goede
{
267 4f4321c1 Gerd Hoffmann
    if (p->result < 0) {
268 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_IDLE;
269 50b7963e Hans de Goede
    }
270 50b7963e Hans de Goede
271 50b7963e Hans de Goede
    switch (s->setup_state) {
272 50b7963e Hans de Goede
    case SETUP_STATE_SETUP:
273 4f4321c1 Gerd Hoffmann
        if (p->result < s->setup_len) {
274 4f4321c1 Gerd Hoffmann
            s->setup_len = p->result;
275 50b7963e Hans de Goede
        }
276 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_DATA;
277 4f4321c1 Gerd Hoffmann
        p->result = 8;
278 50b7963e Hans de Goede
        break;
279 50b7963e Hans de Goede
280 50b7963e Hans de Goede
    case SETUP_STATE_ACK:
281 50b7963e Hans de Goede
        s->setup_state = SETUP_STATE_IDLE;
282 4f4321c1 Gerd Hoffmann
        p->result = 0;
283 50b7963e Hans de Goede
        break;
284 50b7963e Hans de Goede
285 50b7963e Hans de Goede
    default:
286 50b7963e Hans de Goede
        break;
287 50b7963e Hans de Goede
    }
288 50b7963e Hans de Goede
    usb_packet_complete(s, p);
289 50b7963e Hans de Goede
}
290 50b7963e Hans de Goede
291 bb36d470 bellard
/* XXX: fix overflow */
292 bb36d470 bellard
int set_usb_string(uint8_t *buf, const char *str)
293 bb36d470 bellard
{
294 bb36d470 bellard
    int len, i;
295 bb36d470 bellard
    uint8_t *q;
296 bb36d470 bellard
297 bb36d470 bellard
    q = buf;
298 bb36d470 bellard
    len = strlen(str);
299 ce5c37c2 pbrook
    *q++ = 2 * len + 2;
300 bb36d470 bellard
    *q++ = 3;
301 bb36d470 bellard
    for(i = 0; i < len; i++) {
302 bb36d470 bellard
        *q++ = str[i];
303 bb36d470 bellard
        *q++ = 0;
304 bb36d470 bellard
    }
305 bb36d470 bellard
    return q - buf;
306 bb36d470 bellard
}
307 4d611c9a pbrook
308 4d611c9a pbrook
/* Send an internal message to a USB device.  */
309 4d611c9a pbrook
void usb_send_msg(USBDevice *dev, int msg)
310 4d611c9a pbrook
{
311 4d611c9a pbrook
    USBPacket p;
312 53aa8c0e Gerd Hoffmann
    int ret;
313 53aa8c0e Gerd Hoffmann
314 4d611c9a pbrook
    memset(&p, 0, sizeof(p));
315 4d611c9a pbrook
    p.pid = msg;
316 53aa8c0e Gerd Hoffmann
    ret = usb_handle_packet(dev, &p);
317 89b9b79f aliguori
    /* This _must_ be synchronous */
318 53aa8c0e Gerd Hoffmann
    assert(ret != USB_RET_ASYNC);
319 53aa8c0e Gerd Hoffmann
}
320 53aa8c0e Gerd Hoffmann
321 53aa8c0e Gerd Hoffmann
/* Hand over a packet to a device for processing.  Return value
322 53aa8c0e Gerd Hoffmann
   USB_RET_ASYNC indicates the processing isn't finished yet, the
323 53aa8c0e Gerd Hoffmann
   driver will call usb_packet_complete() when done processing it. */
324 53aa8c0e Gerd Hoffmann
int usb_handle_packet(USBDevice *dev, USBPacket *p)
325 53aa8c0e Gerd Hoffmann
{
326 53aa8c0e Gerd Hoffmann
    int ret;
327 53aa8c0e Gerd Hoffmann
328 4ff658fb Gerd Hoffmann
    assert(p->owner == NULL);
329 53aa8c0e Gerd Hoffmann
    ret = dev->info->handle_packet(dev, p);
330 4ff658fb Gerd Hoffmann
    if (ret == USB_RET_ASYNC) {
331 4ff658fb Gerd Hoffmann
        if (p->owner == NULL) {
332 4ff658fb Gerd Hoffmann
            p->owner = dev;
333 4ff658fb Gerd Hoffmann
        } else {
334 4ff658fb Gerd Hoffmann
            /* We'll end up here when usb_handle_packet is called
335 4ff658fb Gerd Hoffmann
             * recursively due to a hub being in the chain.  Nothing
336 4ff658fb Gerd Hoffmann
             * to do.  Leave p->owner pointing to the device, not the
337 4ff658fb Gerd Hoffmann
             * hub. */;
338 4ff658fb Gerd Hoffmann
        }
339 4ff658fb Gerd Hoffmann
    }
340 53aa8c0e Gerd Hoffmann
    return ret;
341 89b9b79f aliguori
}
342 4ff658fb Gerd Hoffmann
343 4ff658fb Gerd Hoffmann
/* Notify the controller that an async packet is complete.  This should only
344 4ff658fb Gerd Hoffmann
   be called for packets previously deferred by returning USB_RET_ASYNC from
345 4ff658fb Gerd Hoffmann
   handle_packet. */
346 4ff658fb Gerd Hoffmann
void usb_packet_complete(USBDevice *dev, USBPacket *p)
347 4ff658fb Gerd Hoffmann
{
348 4ff658fb Gerd Hoffmann
    /* Note: p->owner != dev is possible in case dev is a hub */
349 4ff658fb Gerd Hoffmann
    assert(p->owner != NULL);
350 4ff658fb Gerd Hoffmann
    p->owner = NULL;
351 4d8debba Gerd Hoffmann
    dev->port->ops->complete(dev->port, p);
352 4ff658fb Gerd Hoffmann
}
353 4ff658fb Gerd Hoffmann
354 4ff658fb Gerd Hoffmann
/* Cancel an active packet.  The packed must have been deferred by
355 4ff658fb Gerd Hoffmann
   returning USB_RET_ASYNC from handle_packet, and not yet
356 4ff658fb Gerd Hoffmann
   completed.  */
357 4ff658fb Gerd Hoffmann
void usb_cancel_packet(USBPacket * p)
358 4ff658fb Gerd Hoffmann
{
359 4ff658fb Gerd Hoffmann
    assert(p->owner != NULL);
360 eb5e680a Gerd Hoffmann
    p->owner->info->cancel_packet(p->owner, p);
361 4ff658fb Gerd Hoffmann
    p->owner = NULL;
362 4ff658fb Gerd Hoffmann
}
363 4f4321c1 Gerd Hoffmann
364 4f4321c1 Gerd Hoffmann
365 4f4321c1 Gerd Hoffmann
void usb_packet_init(USBPacket *p)
366 4f4321c1 Gerd Hoffmann
{
367 4f4321c1 Gerd Hoffmann
    qemu_iovec_init(&p->iov, 1);
368 4f4321c1 Gerd Hoffmann
}
369 4f4321c1 Gerd Hoffmann
370 4f4321c1 Gerd Hoffmann
void usb_packet_setup(USBPacket *p, int pid, uint8_t addr, uint8_t ep)
371 4f4321c1 Gerd Hoffmann
{
372 4f4321c1 Gerd Hoffmann
    p->pid = pid;
373 4f4321c1 Gerd Hoffmann
    p->devaddr = addr;
374 4f4321c1 Gerd Hoffmann
    p->devep = ep;
375 4f4321c1 Gerd Hoffmann
    p->result = 0;
376 4f4321c1 Gerd Hoffmann
    qemu_iovec_reset(&p->iov);
377 4f4321c1 Gerd Hoffmann
}
378 4f4321c1 Gerd Hoffmann
379 4f4321c1 Gerd Hoffmann
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
380 4f4321c1 Gerd Hoffmann
{
381 4f4321c1 Gerd Hoffmann
    qemu_iovec_add(&p->iov, ptr, len);
382 4f4321c1 Gerd Hoffmann
}
383 4f4321c1 Gerd Hoffmann
384 4f4321c1 Gerd Hoffmann
void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
385 4f4321c1 Gerd Hoffmann
{
386 4f4321c1 Gerd Hoffmann
    assert(p->result >= 0);
387 4f4321c1 Gerd Hoffmann
    assert(p->result + bytes <= p->iov.size);
388 4f4321c1 Gerd Hoffmann
    switch (p->pid) {
389 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_SETUP:
390 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_OUT:
391 4f4321c1 Gerd Hoffmann
        iov_to_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
392 4f4321c1 Gerd Hoffmann
        break;
393 4f4321c1 Gerd Hoffmann
    case USB_TOKEN_IN:
394 4f4321c1 Gerd Hoffmann
        iov_from_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes);
395 4f4321c1 Gerd Hoffmann
        break;
396 4f4321c1 Gerd Hoffmann
    default:
397 4f4321c1 Gerd Hoffmann
        fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
398 4f4321c1 Gerd Hoffmann
        abort();
399 4f4321c1 Gerd Hoffmann
    }
400 4f4321c1 Gerd Hoffmann
    p->result += bytes;
401 4f4321c1 Gerd Hoffmann
}
402 4f4321c1 Gerd Hoffmann
403 4f4321c1 Gerd Hoffmann
void usb_packet_skip(USBPacket *p, size_t bytes)
404 4f4321c1 Gerd Hoffmann
{
405 4f4321c1 Gerd Hoffmann
    assert(p->result >= 0);
406 4f4321c1 Gerd Hoffmann
    assert(p->result + bytes <= p->iov.size);
407 4f4321c1 Gerd Hoffmann
    if (p->pid == USB_TOKEN_IN) {
408 4f4321c1 Gerd Hoffmann
        iov_clear(p->iov.iov, p->iov.niov, p->result, bytes);
409 4f4321c1 Gerd Hoffmann
    }
410 4f4321c1 Gerd Hoffmann
    p->result += bytes;
411 4f4321c1 Gerd Hoffmann
}
412 4f4321c1 Gerd Hoffmann
413 4f4321c1 Gerd Hoffmann
void usb_packet_cleanup(USBPacket *p)
414 4f4321c1 Gerd Hoffmann
{
415 4f4321c1 Gerd Hoffmann
    qemu_iovec_destroy(&p->iov);
416 4f4321c1 Gerd Hoffmann
}