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