~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/usb-bt.c

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

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