|
1 /* |
|
2 * QEMU Bluetooth HCI USB Transport Layer v1.0 |
|
3 * |
|
4 * Copyright (C) 2007 OpenMoko, Inc. |
|
5 * Copyright (C) 2008 Andrzej Zaborowski <balrog@zabor.org> |
|
6 * |
|
7 * This program is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU General Public License as |
|
9 * published by the Free Software Foundation; either version 2 or |
|
10 * (at your option) version 3 of the License. |
|
11 * |
|
12 * This program is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 * GNU General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License |
|
18 * along with this program; if not, write to the Free Software |
|
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
|
20 * MA 02111-1307 USA |
|
21 */ |
|
22 |
|
23 #include "qemu-common.h" |
|
24 #include "usb.h" |
|
25 #include "net.h" |
|
26 #include "bt.h" |
|
27 |
|
28 struct USBBtState { |
|
29 USBDevice dev; |
|
30 struct HCIInfo *hci; |
|
31 |
|
32 int altsetting; |
|
33 int config; |
|
34 |
|
35 #define CFIFO_LEN_MASK 255 |
|
36 #define DFIFO_LEN_MASK 4095 |
|
37 struct usb_hci_in_fifo_s { |
|
38 uint8_t data[(DFIFO_LEN_MASK + 1) * 2]; |
|
39 struct { |
|
40 uint8_t *data; |
|
41 int len; |
|
42 } fifo[CFIFO_LEN_MASK + 1]; |
|
43 int dstart, dlen, dsize, start, len; |
|
44 } evt, acl, sco; |
|
45 |
|
46 struct usb_hci_out_fifo_s { |
|
47 uint8_t data[4096]; |
|
48 int len; |
|
49 } outcmd, outacl, outsco; |
|
50 }; |
|
51 |
|
52 #define USB_EVT_EP 1 |
|
53 #define USB_ACL_EP 2 |
|
54 #define USB_SCO_EP 3 |
|
55 |
|
56 static const uint8_t qemu_bt_dev_descriptor[] = { |
|
57 0x12, /* u8 bLength; */ |
|
58 USB_DT_DEVICE, /* u8 bDescriptorType; Device */ |
|
59 0x10, 0x01, /* u16 bcdUSB; v1.10 */ |
|
60 |
|
61 0xe0, /* u8 bDeviceClass; Wireless */ |
|
62 0x01, /* u8 bDeviceSubClass; Radio Frequency */ |
|
63 0x01, /* u8 bDeviceProtocol; Bluetooth */ |
|
64 0x40, /* u8 bMaxPacketSize0; 64 Bytes */ |
|
65 |
|
66 0x12, 0x0a, /* u16 idVendor; */ |
|
67 0x01, 0x00, /* u16 idProduct; Bluetooth Dongle (HCI mode) */ |
|
68 0x58, 0x19, /* u16 bcdDevice; (some devices have 0x48, 0x02) */ |
|
69 |
|
70 0x00, /* u8 iManufacturer; */ |
|
71 0x00, /* u8 iProduct; */ |
|
72 0x00, /* u8 iSerialNumber; */ |
|
73 0x01, /* u8 bNumConfigurations; */ |
|
74 }; |
|
75 |
|
76 static const uint8_t qemu_bt_config_descriptor[] = { |
|
77 /* one configuration */ |
|
78 0x09, /* u8 bLength; */ |
|
79 USB_DT_CONFIG, /* u8 bDescriptorType; */ |
|
80 0xb1, 0x00, /* u16 wTotalLength; */ |
|
81 0x02, /* u8 bNumInterfaces; (2) */ |
|
82 0x01, /* u8 bConfigurationValue; */ |
|
83 0x00, /* u8 iConfiguration; */ |
|
84 0xc0, /* u8 bmAttributes; |
|
85 Bit 7: must be set, |
|
86 6: Self-powered, |
|
87 5: Remote wakeup, |
|
88 4..0: resvd */ |
|
89 0x00, /* u8 MaxPower; */ |
|
90 |
|
91 /* USB 1.1: |
|
92 * USB 2.0, single TT organization (mandatory): |
|
93 * one interface, protocol 0 |
|
94 * |
|
95 * USB 2.0, multiple TT organization (optional): |
|
96 * two interfaces, protocols 1 (like single TT) |
|
97 * and 2 (multiple TT mode) ... config is |
|
98 * sometimes settable |
|
99 * NOT IMPLEMENTED |
|
100 */ |
|
101 |
|
102 /* interface one */ |
|
103 0x09, /* u8 if_bLength; */ |
|
104 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
105 0x00, /* u8 if_bInterfaceNumber; */ |
|
106 0x00, /* u8 if_bAlternateSetting; */ |
|
107 0x03, /* u8 if_bNumEndpoints; */ |
|
108 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
109 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
110 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
111 0x00, /* u8 if_iInterface; */ |
|
112 |
|
113 /* endpoint one */ |
|
114 0x07, /* u8 ep_bLength; */ |
|
115 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
116 USB_DIR_IN | USB_EVT_EP, /* u8 ep_bEndpointAddress; */ |
|
117 0x03, /* u8 ep_bmAttributes; Interrupt */ |
|
118 0x10, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
119 0x02, /* u8 ep_bInterval; */ |
|
120 |
|
121 /* endpoint two */ |
|
122 0x07, /* u8 ep_bLength; */ |
|
123 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
124 USB_DIR_OUT | USB_ACL_EP, /* u8 ep_bEndpointAddress; */ |
|
125 0x02, /* u8 ep_bmAttributes; Bulk */ |
|
126 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
127 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
128 |
|
129 /* endpoint three */ |
|
130 0x07, /* u8 ep_bLength; */ |
|
131 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
132 USB_DIR_IN | USB_ACL_EP, /* u8 ep_bEndpointAddress; */ |
|
133 0x02, /* u8 ep_bmAttributes; Bulk */ |
|
134 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
135 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
136 |
|
137 /* interface two setting one */ |
|
138 0x09, /* u8 if_bLength; */ |
|
139 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
140 0x01, /* u8 if_bInterfaceNumber; */ |
|
141 0x00, /* u8 if_bAlternateSetting; */ |
|
142 0x02, /* u8 if_bNumEndpoints; */ |
|
143 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
144 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
145 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
146 0x00, /* u8 if_iInterface; */ |
|
147 |
|
148 /* endpoint one */ |
|
149 0x07, /* u8 ep_bLength; */ |
|
150 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
151 USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
152 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
153 0x00, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
154 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
155 |
|
156 /* endpoint two */ |
|
157 0x07, /* u8 ep_bLength; */ |
|
158 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
159 USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
160 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
161 0x00, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
162 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
163 |
|
164 /* interface two setting two */ |
|
165 0x09, /* u8 if_bLength; */ |
|
166 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
167 0x01, /* u8 if_bInterfaceNumber; */ |
|
168 0x01, /* u8 if_bAlternateSetting; */ |
|
169 0x02, /* u8 if_bNumEndpoints; */ |
|
170 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
171 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
172 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
173 0x00, /* u8 if_iInterface; */ |
|
174 |
|
175 /* endpoint one */ |
|
176 0x07, /* u8 ep_bLength; */ |
|
177 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
178 USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
179 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
180 0x09, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
181 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
182 |
|
183 /* endpoint two */ |
|
184 0x07, /* u8 ep_bLength; */ |
|
185 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
186 USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
187 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
188 0x09, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
189 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
190 |
|
191 /* interface two setting three */ |
|
192 0x09, /* u8 if_bLength; */ |
|
193 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
194 0x01, /* u8 if_bInterfaceNumber; */ |
|
195 0x02, /* u8 if_bAlternateSetting; */ |
|
196 0x02, /* u8 if_bNumEndpoints; */ |
|
197 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
198 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
199 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
200 0x00, /* u8 if_iInterface; */ |
|
201 |
|
202 /* endpoint one */ |
|
203 0x07, /* u8 ep_bLength; */ |
|
204 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
205 USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
206 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
207 0x11, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
208 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
209 |
|
210 /* endpoint two */ |
|
211 0x07, /* u8 ep_bLength; */ |
|
212 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
213 USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
214 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
215 0x11, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
216 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
217 |
|
218 /* interface two setting four */ |
|
219 0x09, /* u8 if_bLength; */ |
|
220 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
221 0x01, /* u8 if_bInterfaceNumber; */ |
|
222 0x03, /* u8 if_bAlternateSetting; */ |
|
223 0x02, /* u8 if_bNumEndpoints; */ |
|
224 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
225 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
226 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
227 0x00, /* u8 if_iInterface; */ |
|
228 |
|
229 /* endpoint one */ |
|
230 0x07, /* u8 ep_bLength; */ |
|
231 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
232 USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
233 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
234 0x19, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
235 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
236 |
|
237 /* endpoint two */ |
|
238 0x07, /* u8 ep_bLength; */ |
|
239 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
240 USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
241 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
242 0x19, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
243 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
244 |
|
245 /* interface two setting five */ |
|
246 0x09, /* u8 if_bLength; */ |
|
247 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
248 0x01, /* u8 if_bInterfaceNumber; */ |
|
249 0x04, /* u8 if_bAlternateSetting; */ |
|
250 0x02, /* u8 if_bNumEndpoints; */ |
|
251 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
252 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
253 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
254 0x00, /* u8 if_iInterface; */ |
|
255 |
|
256 /* endpoint one */ |
|
257 0x07, /* u8 ep_bLength; */ |
|
258 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
259 USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
260 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
261 0x21, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
262 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
263 |
|
264 /* endpoint two */ |
|
265 0x07, /* u8 ep_bLength; */ |
|
266 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
267 USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
268 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
269 0x21, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
270 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
271 |
|
272 /* interface two setting six */ |
|
273 0x09, /* u8 if_bLength; */ |
|
274 USB_DT_INTERFACE, /* u8 if_bDescriptorType; */ |
|
275 0x01, /* u8 if_bInterfaceNumber; */ |
|
276 0x05, /* u8 if_bAlternateSetting; */ |
|
277 0x02, /* u8 if_bNumEndpoints; */ |
|
278 0xe0, /* u8 if_bInterfaceClass; Wireless */ |
|
279 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */ |
|
280 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */ |
|
281 0x00, /* u8 if_iInterface; */ |
|
282 |
|
283 /* endpoint one */ |
|
284 0x07, /* u8 ep_bLength; */ |
|
285 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
286 USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
287 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
288 0x31, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
289 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
290 |
|
291 /* endpoint two */ |
|
292 0x07, /* u8 ep_bLength; */ |
|
293 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */ |
|
294 USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */ |
|
295 0x01, /* u8 ep_bmAttributes; Isochronous */ |
|
296 0x31, 0x00, /* u16 ep_wMaxPacketSize; */ |
|
297 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ |
|
298 |
|
299 /* If implemented, the DFU interface descriptor goes here with no |
|
300 * endpoints or alternative settings. */ |
|
301 }; |
|
302 |
|
303 static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo) |
|
304 { |
|
305 fifo->dstart = 0; |
|
306 fifo->dlen = 0; |
|
307 fifo->dsize = DFIFO_LEN_MASK + 1; |
|
308 fifo->start = 0; |
|
309 fifo->len = 0; |
|
310 } |
|
311 |
|
312 static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo, |
|
313 const uint8_t *data, int len) |
|
314 { |
|
315 int off = fifo->dstart + fifo->dlen; |
|
316 uint8_t *buf; |
|
317 |
|
318 fifo->dlen += len; |
|
319 if (off <= DFIFO_LEN_MASK) { |
|
320 if (off + len > DFIFO_LEN_MASK + 1 && |
|
321 (fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) { |
|
322 fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len); |
|
323 exit(-1); |
|
324 } |
|
325 buf = fifo->data + off; |
|
326 } else { |
|
327 if (fifo->dlen > fifo->dsize) { |
|
328 fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len); |
|
329 exit(-1); |
|
330 } |
|
331 buf = fifo->data + off - fifo->dsize; |
|
332 } |
|
333 |
|
334 off = (fifo->start + fifo->len ++) & CFIFO_LEN_MASK; |
|
335 fifo->fifo[off].data = memcpy(buf, data, len); |
|
336 fifo->fifo[off].len = len; |
|
337 } |
|
338 |
|
339 static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo, |
|
340 USBPacket *p) |
|
341 { |
|
342 int len; |
|
343 |
|
344 if (likely(!fifo->len)) |
|
345 return USB_RET_STALL; |
|
346 |
|
347 len = MIN(p->len, fifo->fifo[fifo->start].len); |
|
348 memcpy(p->data, fifo->fifo[fifo->start].data, len); |
|
349 if (len == p->len) { |
|
350 fifo->fifo[fifo->start].len -= len; |
|
351 fifo->fifo[fifo->start].data += len; |
|
352 } else { |
|
353 fifo->start ++; |
|
354 fifo->start &= CFIFO_LEN_MASK; |
|
355 fifo->len --; |
|
356 } |
|
357 |
|
358 fifo->dstart += len; |
|
359 fifo->dlen -= len; |
|
360 if (fifo->dstart >= fifo->dsize) { |
|
361 fifo->dstart = 0; |
|
362 fifo->dsize = DFIFO_LEN_MASK + 1; |
|
363 } |
|
364 |
|
365 return len; |
|
366 } |
|
367 |
|
368 static void inline usb_bt_fifo_out_enqueue(struct USBBtState *s, |
|
369 struct usb_hci_out_fifo_s *fifo, |
|
370 void (*send)(struct HCIInfo *, const uint8_t *, int), |
|
371 int (*complete)(const uint8_t *, int), |
|
372 const uint8_t *data, int len) |
|
373 { |
|
374 if (fifo->len) { |
|
375 memcpy(fifo->data + fifo->len, data, len); |
|
376 fifo->len += len; |
|
377 if (complete(fifo->data, fifo->len)) { |
|
378 send(s->hci, fifo->data, fifo->len); |
|
379 fifo->len = 0; |
|
380 } |
|
381 } else if (complete(data, len)) |
|
382 send(s->hci, data, len); |
|
383 else { |
|
384 memcpy(fifo->data, data, len); |
|
385 fifo->len = len; |
|
386 } |
|
387 |
|
388 /* TODO: do we need to loop? */ |
|
389 } |
|
390 |
|
391 static int usb_bt_hci_cmd_complete(const uint8_t *data, int len) |
|
392 { |
|
393 len -= HCI_COMMAND_HDR_SIZE; |
|
394 return len >= 0 && |
|
395 len >= ((struct hci_command_hdr *) data)->plen; |
|
396 } |
|
397 |
|
398 static int usb_bt_hci_acl_complete(const uint8_t *data, int len) |
|
399 { |
|
400 len -= HCI_ACL_HDR_SIZE; |
|
401 return len >= 0 && |
|
402 len >= le16_to_cpu(((struct hci_acl_hdr *) data)->dlen); |
|
403 } |
|
404 |
|
405 static int usb_bt_hci_sco_complete(const uint8_t *data, int len) |
|
406 { |
|
407 len -= HCI_SCO_HDR_SIZE; |
|
408 return len >= 0 && |
|
409 len >= ((struct hci_sco_hdr *) data)->dlen; |
|
410 } |
|
411 |
|
412 static void usb_bt_handle_reset(USBDevice *dev) |
|
413 { |
|
414 struct USBBtState *s = (struct USBBtState *) dev->opaque; |
|
415 |
|
416 usb_bt_fifo_reset(&s->evt); |
|
417 usb_bt_fifo_reset(&s->acl); |
|
418 usb_bt_fifo_reset(&s->sco); |
|
419 s->outcmd.len = 0; |
|
420 s->outacl.len = 0; |
|
421 s->outsco.len = 0; |
|
422 s->altsetting = 0; |
|
423 } |
|
424 |
|
425 static int usb_bt_handle_control(USBDevice *dev, int request, int value, |
|
426 int index, int length, uint8_t *data) |
|
427 { |
|
428 struct USBBtState *s = (struct USBBtState *) dev->opaque; |
|
429 int ret = 0; |
|
430 |
|
431 switch (request) { |
|
432 case DeviceRequest | USB_REQ_GET_STATUS: |
|
433 case InterfaceRequest | USB_REQ_GET_STATUS: |
|
434 case EndpointRequest | USB_REQ_GET_STATUS: |
|
435 data[0] = (1 << USB_DEVICE_SELF_POWERED) | |
|
436 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); |
|
437 data[1] = 0x00; |
|
438 ret = 2; |
|
439 break; |
|
440 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: |
|
441 case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE: |
|
442 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: |
|
443 if (value == USB_DEVICE_REMOTE_WAKEUP) { |
|
444 dev->remote_wakeup = 0; |
|
445 } else { |
|
446 goto fail; |
|
447 } |
|
448 ret = 0; |
|
449 break; |
|
450 case DeviceOutRequest | USB_REQ_SET_FEATURE: |
|
451 case InterfaceOutRequest | USB_REQ_SET_FEATURE: |
|
452 case EndpointOutRequest | USB_REQ_SET_FEATURE: |
|
453 if (value == USB_DEVICE_REMOTE_WAKEUP) { |
|
454 dev->remote_wakeup = 1; |
|
455 } else { |
|
456 goto fail; |
|
457 } |
|
458 ret = 0; |
|
459 break; |
|
460 case DeviceOutRequest | USB_REQ_SET_ADDRESS: |
|
461 dev->addr = value; |
|
462 ret = 0; |
|
463 break; |
|
464 case DeviceRequest | USB_REQ_GET_DESCRIPTOR: |
|
465 switch (value >> 8) { |
|
466 case USB_DT_DEVICE: |
|
467 ret = sizeof(qemu_bt_dev_descriptor); |
|
468 memcpy(data, qemu_bt_dev_descriptor, ret); |
|
469 break; |
|
470 case USB_DT_CONFIG: |
|
471 ret = sizeof(qemu_bt_config_descriptor); |
|
472 memcpy(data, qemu_bt_config_descriptor, ret); |
|
473 break; |
|
474 case USB_DT_STRING: |
|
475 switch(value & 0xff) { |
|
476 case 0: |
|
477 /* language ids */ |
|
478 data[0] = 4; |
|
479 data[1] = 3; |
|
480 data[2] = 0x09; |
|
481 data[3] = 0x04; |
|
482 ret = 4; |
|
483 break; |
|
484 default: |
|
485 goto fail; |
|
486 } |
|
487 break; |
|
488 default: |
|
489 goto fail; |
|
490 } |
|
491 break; |
|
492 case DeviceRequest | USB_REQ_GET_CONFIGURATION: |
|
493 data[0] = qemu_bt_config_descriptor[0x5]; |
|
494 ret = 1; |
|
495 s->config = 0; |
|
496 break; |
|
497 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: |
|
498 ret = 0; |
|
499 if (value != qemu_bt_config_descriptor[0x5] && value != 0) { |
|
500 printf("%s: Wrong SET_CONFIGURATION request (%i)\n", |
|
501 __FUNCTION__, value); |
|
502 goto fail; |
|
503 } |
|
504 s->config = 1; |
|
505 usb_bt_fifo_reset(&s->evt); |
|
506 usb_bt_fifo_reset(&s->acl); |
|
507 usb_bt_fifo_reset(&s->sco); |
|
508 break; |
|
509 case InterfaceRequest | USB_REQ_GET_INTERFACE: |
|
510 if (value != 0 || (index & ~1) || length != 1) |
|
511 goto fail; |
|
512 if (index == 1) |
|
513 data[0] = s->altsetting; |
|
514 else |
|
515 data[0] = 0; |
|
516 ret = 1; |
|
517 break; |
|
518 case InterfaceOutRequest | USB_REQ_SET_INTERFACE: |
|
519 if ((index & ~1) || length != 0 || |
|
520 (index == 1 && (value < 0 || value > 4)) || |
|
521 (index == 0 && value != 0)) { |
|
522 printf("%s: Wrong SET_INTERFACE request (%i, %i)\n", |
|
523 __FUNCTION__, index, value); |
|
524 goto fail; |
|
525 } |
|
526 s->altsetting = value; |
|
527 ret = 0; |
|
528 break; |
|
529 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8): |
|
530 if (s->config) |
|
531 usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send, |
|
532 usb_bt_hci_cmd_complete, data, length); |
|
533 break; |
|
534 default: |
|
535 fail: |
|
536 ret = USB_RET_STALL; |
|
537 break; |
|
538 } |
|
539 return ret; |
|
540 } |
|
541 |
|
542 static int usb_bt_handle_data(USBDevice *dev, USBPacket *p) |
|
543 { |
|
544 struct USBBtState *s = (struct USBBtState *) dev->opaque; |
|
545 int ret = 0; |
|
546 |
|
547 if (!s->config) |
|
548 goto fail; |
|
549 |
|
550 switch (p->pid) { |
|
551 case USB_TOKEN_IN: |
|
552 switch (p->devep & 0xf) { |
|
553 case USB_EVT_EP: |
|
554 ret = usb_bt_fifo_dequeue(&s->evt, p); |
|
555 break; |
|
556 |
|
557 case USB_ACL_EP: |
|
558 ret = usb_bt_fifo_dequeue(&s->acl, p); |
|
559 break; |
|
560 |
|
561 case USB_SCO_EP: |
|
562 ret = usb_bt_fifo_dequeue(&s->sco, p); |
|
563 break; |
|
564 |
|
565 default: |
|
566 goto fail; |
|
567 } |
|
568 break; |
|
569 |
|
570 case USB_TOKEN_OUT: |
|
571 switch (p->devep & 0xf) { |
|
572 case USB_ACL_EP: |
|
573 usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send, |
|
574 usb_bt_hci_acl_complete, p->data, p->len); |
|
575 break; |
|
576 |
|
577 case USB_SCO_EP: |
|
578 usb_bt_fifo_out_enqueue(s, &s->outsco, s->hci->sco_send, |
|
579 usb_bt_hci_sco_complete, p->data, p->len); |
|
580 break; |
|
581 |
|
582 default: |
|
583 goto fail; |
|
584 } |
|
585 break; |
|
586 |
|
587 default: |
|
588 fail: |
|
589 ret = USB_RET_STALL; |
|
590 break; |
|
591 } |
|
592 |
|
593 return ret; |
|
594 } |
|
595 |
|
596 static void usb_bt_out_hci_packet_event(void *opaque, |
|
597 const uint8_t *data, int len) |
|
598 { |
|
599 struct USBBtState *s = (struct USBBtState *) opaque; |
|
600 |
|
601 usb_bt_fifo_enqueue(&s->evt, data, len); |
|
602 } |
|
603 |
|
604 static void usb_bt_out_hci_packet_acl(void *opaque, |
|
605 const uint8_t *data, int len) |
|
606 { |
|
607 struct USBBtState *s = (struct USBBtState *) opaque; |
|
608 |
|
609 usb_bt_fifo_enqueue(&s->acl, data, len); |
|
610 } |
|
611 |
|
612 static void usb_bt_handle_destroy(USBDevice *dev) |
|
613 { |
|
614 struct USBBtState *s = (struct USBBtState *) dev->opaque; |
|
615 |
|
616 s->hci->opaque = 0; |
|
617 s->hci->evt_recv = 0; |
|
618 s->hci->acl_recv = 0; |
|
619 qemu_free(s); |
|
620 } |
|
621 |
|
622 USBDevice *usb_bt_init(HCIInfo *hci) |
|
623 { |
|
624 struct USBBtState *s; |
|
625 |
|
626 if (!hci) |
|
627 return NULL; |
|
628 s = qemu_mallocz(sizeof(struct USBBtState)); |
|
629 if (!s) |
|
630 return NULL; |
|
631 s->dev.opaque = s; |
|
632 s->dev.speed = USB_SPEED_HIGH; |
|
633 s->dev.handle_packet = usb_generic_handle_packet; |
|
634 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU BT dongle"); |
|
635 |
|
636 s->dev.handle_reset = usb_bt_handle_reset; |
|
637 s->dev.handle_control = usb_bt_handle_control; |
|
638 s->dev.handle_data = usb_bt_handle_data; |
|
639 s->dev.handle_destroy = usb_bt_handle_destroy; |
|
640 |
|
641 s->hci = hci; |
|
642 s->hci->opaque = s; |
|
643 s->hci->evt_recv = usb_bt_out_hci_packet_event; |
|
644 s->hci->acl_recv = usb_bt_out_hci_packet_acl; |
|
645 |
|
646 usb_bt_handle_reset(&s->dev); |
|
647 |
|
648 return &s->dev; |
|
649 } |