qemu/hw/usb/dev-bluetooth.c
<<
>>
Prefs
   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 "qemu/error-report.h"
  23#include "hw/usb.h"
  24#include "hw/usb/desc.h"
  25#include "sysemu/bt.h"
  26#include "hw/bt.h"
  27
  28struct USBBtState {
  29    USBDevice dev;
  30    struct HCIInfo *hci;
  31    USBEndpoint *intr;
  32
  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
  56enum {
  57    STR_MANUFACTURER = 1,
  58    STR_SERIALNUMBER,
  59};
  60
  61static const USBDescStrings desc_strings = {
  62    [STR_MANUFACTURER]     = "QEMU",
  63    [STR_SERIALNUMBER]     = "1",
  64};
  65
  66static const USBDescIface desc_iface_bluetooth[] = {
  67    {
  68        .bInterfaceNumber              = 0,
  69        .bNumEndpoints                 = 3,
  70        .bInterfaceClass               = 0xe0, /* Wireless */
  71        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
  72        .bInterfaceProtocol            = 0x01, /* Bluetooth */
  73        .eps = (USBDescEndpoint[]) {
  74            {
  75                .bEndpointAddress      = USB_DIR_IN | USB_EVT_EP,
  76                .bmAttributes          = USB_ENDPOINT_XFER_INT,
  77                .wMaxPacketSize        = 0x10,
  78                .bInterval             = 0x02,
  79            },
  80            {
  81                .bEndpointAddress      = USB_DIR_OUT | USB_ACL_EP,
  82                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
  83                .wMaxPacketSize        = 0x40,
  84                .bInterval             = 0x0a,
  85            },
  86            {
  87                .bEndpointAddress      = USB_DIR_IN | USB_ACL_EP,
  88                .bmAttributes          = USB_ENDPOINT_XFER_BULK,
  89                .wMaxPacketSize        = 0x40,
  90                .bInterval             = 0x0a,
  91            },
  92        },
  93    },{
  94        .bInterfaceNumber              = 1,
  95        .bAlternateSetting             = 0,
  96        .bNumEndpoints                 = 2,
  97        .bInterfaceClass               = 0xe0, /* Wireless */
  98        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
  99        .bInterfaceProtocol            = 0x01, /* Bluetooth */
 100        .eps = (USBDescEndpoint[]) {
 101            {
 102                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
 103                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 104                .wMaxPacketSize        = 0,
 105                .bInterval             = 0x01,
 106            },
 107            {
 108                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
 109                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 110                .wMaxPacketSize        = 0,
 111                .bInterval             = 0x01,
 112            },
 113        },
 114    },{
 115        .bInterfaceNumber              = 1,
 116        .bAlternateSetting             = 1,
 117        .bNumEndpoints                 = 2,
 118        .bInterfaceClass               = 0xe0, /* Wireless */
 119        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
 120        .bInterfaceProtocol            = 0x01, /* Bluetooth */
 121        .eps = (USBDescEndpoint[]) {
 122            {
 123                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
 124                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 125                .wMaxPacketSize        = 0x09,
 126                .bInterval             = 0x01,
 127            },
 128            {
 129                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
 130                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 131                .wMaxPacketSize        = 0x09,
 132                .bInterval             = 0x01,
 133            },
 134        },
 135    },{
 136        .bInterfaceNumber              = 1,
 137        .bAlternateSetting             = 2,
 138        .bNumEndpoints                 = 2,
 139        .bInterfaceClass               = 0xe0, /* Wireless */
 140        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
 141        .bInterfaceProtocol            = 0x01, /* Bluetooth */
 142        .eps = (USBDescEndpoint[]) {
 143            {
 144                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
 145                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 146                .wMaxPacketSize        = 0x11,
 147                .bInterval             = 0x01,
 148            },
 149            {
 150                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
 151                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 152                .wMaxPacketSize        = 0x11,
 153                .bInterval             = 0x01,
 154            },
 155        },
 156    },{
 157        .bInterfaceNumber              = 1,
 158        .bAlternateSetting             = 3,
 159        .bNumEndpoints                 = 2,
 160        .bInterfaceClass               = 0xe0, /* Wireless */
 161        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
 162        .bInterfaceProtocol            = 0x01, /* Bluetooth */
 163        .eps = (USBDescEndpoint[]) {
 164            {
 165                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
 166                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 167                .wMaxPacketSize        = 0x19,
 168                .bInterval             = 0x01,
 169            },
 170            {
 171                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
 172                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 173                .wMaxPacketSize        = 0x19,
 174                .bInterval             = 0x01,
 175            },
 176        },
 177    },{
 178        .bInterfaceNumber              = 1,
 179        .bAlternateSetting             = 4,
 180        .bNumEndpoints                 = 2,
 181        .bInterfaceClass               = 0xe0, /* Wireless */
 182        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
 183        .bInterfaceProtocol            = 0x01, /* Bluetooth */
 184        .eps = (USBDescEndpoint[]) {
 185            {
 186                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
 187                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 188                .wMaxPacketSize        = 0x21,
 189                .bInterval             = 0x01,
 190            },
 191            {
 192                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
 193                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 194                .wMaxPacketSize        = 0x21,
 195                .bInterval             = 0x01,
 196            },
 197        },
 198    },{
 199        .bInterfaceNumber              = 1,
 200        .bAlternateSetting             = 5,
 201        .bNumEndpoints                 = 2,
 202        .bInterfaceClass               = 0xe0, /* Wireless */
 203        .bInterfaceSubClass            = 0x01, /* Radio Frequency */
 204        .bInterfaceProtocol            = 0x01, /* Bluetooth */
 205        .eps = (USBDescEndpoint[]) {
 206            {
 207                .bEndpointAddress      = USB_DIR_OUT | USB_SCO_EP,
 208                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 209                .wMaxPacketSize        = 0x31,
 210                .bInterval             = 0x01,
 211            },
 212            {
 213                .bEndpointAddress      = USB_DIR_IN | USB_SCO_EP,
 214                .bmAttributes          = USB_ENDPOINT_XFER_ISOC,
 215                .wMaxPacketSize        = 0x31,
 216                .bInterval             = 0x01,
 217            },
 218        },
 219    }
 220};
 221
 222static const USBDescDevice desc_device_bluetooth = {
 223    .bcdUSB                        = 0x0110,
 224    .bDeviceClass                  = 0xe0, /* Wireless */
 225    .bDeviceSubClass               = 0x01, /* Radio Frequency */
 226    .bDeviceProtocol               = 0x01, /* Bluetooth */
 227    .bMaxPacketSize0               = 64,
 228    .bNumConfigurations            = 1,
 229    .confs = (USBDescConfig[]) {
 230        {
 231            .bNumInterfaces        = 2,
 232            .bConfigurationValue   = 1,
 233            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER,
 234            .bMaxPower             = 0,
 235            .nif = ARRAY_SIZE(desc_iface_bluetooth),
 236            .ifs = desc_iface_bluetooth,
 237        },
 238    },
 239};
 240
 241static const USBDesc desc_bluetooth = {
 242    .id = {
 243        .idVendor          = 0x0a12,
 244        .idProduct         = 0x0001,
 245        .bcdDevice         = 0x1958,
 246        .iManufacturer     = STR_MANUFACTURER,
 247        .iProduct          = 0,
 248        .iSerialNumber     = STR_SERIALNUMBER,
 249    },
 250    .full = &desc_device_bluetooth,
 251    .str  = desc_strings,
 252};
 253
 254static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
 255{
 256    fifo->dstart = 0;
 257    fifo->dlen = 0;
 258    fifo->dsize = DFIFO_LEN_MASK + 1;
 259    fifo->start = 0;
 260    fifo->len = 0;
 261}
 262
 263static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
 264                const uint8_t *data, int len)
 265{
 266    int off = fifo->dstart + fifo->dlen;
 267    uint8_t *buf;
 268
 269    fifo->dlen += len;
 270    if (off <= DFIFO_LEN_MASK) {
 271        if (off + len > DFIFO_LEN_MASK + 1 &&
 272                        (fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) {
 273            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
 274            exit(-1);
 275        }
 276        buf = fifo->data + off;
 277    } else {
 278        if (fifo->dlen > fifo->dsize) {
 279            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
 280            exit(-1);
 281        }
 282        buf = fifo->data + off - fifo->dsize;
 283    }
 284
 285    off = (fifo->start + fifo->len ++) & CFIFO_LEN_MASK;
 286    fifo->fifo[off].data = memcpy(buf, data, len);
 287    fifo->fifo[off].len = len;
 288}
 289
 290static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
 291                USBPacket *p)
 292{
 293    int len;
 294
 295    assert(fifo->len != 0);
 296
 297    len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
 298    usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
 299    if (len == p->iov.size) {
 300        fifo->fifo[fifo->start].len -= len;
 301        fifo->fifo[fifo->start].data += len;
 302    } else {
 303        fifo->start ++;
 304        fifo->start &= CFIFO_LEN_MASK;
 305        fifo->len --;
 306    }
 307
 308    fifo->dstart += len;
 309    fifo->dlen -= len;
 310    if (fifo->dstart >= fifo->dsize) {
 311        fifo->dstart = 0;
 312        fifo->dsize = DFIFO_LEN_MASK + 1;
 313    }
 314}
 315
 316static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
 317                struct usb_hci_out_fifo_s *fifo,
 318                void (*send)(struct HCIInfo *, const uint8_t *, int),
 319                int (*complete)(const uint8_t *, int),
 320                USBPacket *p)
 321{
 322    usb_packet_copy(p, fifo->data + fifo->len, p->iov.size);
 323    fifo->len += p->iov.size;
 324    if (complete(fifo->data, fifo->len)) {
 325        send(s->hci, fifo->data, fifo->len);
 326        fifo->len = 0;
 327    }
 328
 329    /* TODO: do we need to loop? */
 330}
 331
 332static int usb_bt_hci_cmd_complete(const uint8_t *data, int len)
 333{
 334    len -= HCI_COMMAND_HDR_SIZE;
 335    return len >= 0 &&
 336            len >= ((struct hci_command_hdr *) data)->plen;
 337}
 338
 339static int usb_bt_hci_acl_complete(const uint8_t *data, int len)
 340{
 341    len -= HCI_ACL_HDR_SIZE;
 342    return len >= 0 &&
 343            len >= le16_to_cpu(((struct hci_acl_hdr *) data)->dlen);
 344}
 345
 346static int usb_bt_hci_sco_complete(const uint8_t *data, int len)
 347{
 348    len -= HCI_SCO_HDR_SIZE;
 349    return len >= 0 &&
 350            len >= ((struct hci_sco_hdr *) data)->dlen;
 351}
 352
 353static void usb_bt_handle_reset(USBDevice *dev)
 354{
 355    struct USBBtState *s = (struct USBBtState *) dev->opaque;
 356
 357    usb_bt_fifo_reset(&s->evt);
 358    usb_bt_fifo_reset(&s->acl);
 359    usb_bt_fifo_reset(&s->sco);
 360    s->outcmd.len = 0;
 361    s->outacl.len = 0;
 362    s->outsco.len = 0;
 363}
 364
 365static void usb_bt_handle_control(USBDevice *dev, USBPacket *p,
 366               int request, int value, int index, int length, uint8_t *data)
 367{
 368    struct USBBtState *s = (struct USBBtState *) dev->opaque;
 369    int ret;
 370
 371    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
 372    if (ret >= 0) {
 373        switch (request) {
 374        case DeviceRequest | USB_REQ_GET_CONFIGURATION:
 375            s->config = 0;
 376            break;
 377        case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
 378            s->config = 1;
 379            usb_bt_fifo_reset(&s->evt);
 380            usb_bt_fifo_reset(&s->acl);
 381            usb_bt_fifo_reset(&s->sco);
 382            break;
 383        }
 384        return;
 385    }
 386
 387    switch (request) {
 388    case InterfaceRequest | USB_REQ_GET_STATUS:
 389    case EndpointRequest | USB_REQ_GET_STATUS:
 390        data[0] = 0x00;
 391        data[1] = 0x00;
 392        p->actual_length = 2;
 393        break;
 394    case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
 395    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 396        goto fail;
 397    case InterfaceOutRequest | USB_REQ_SET_FEATURE:
 398    case EndpointOutRequest | USB_REQ_SET_FEATURE:
 399        goto fail;
 400        break;
 401    case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
 402        if (s->config)
 403            usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
 404                            usb_bt_hci_cmd_complete, p);
 405        break;
 406    default:
 407    fail:
 408        p->status = USB_RET_STALL;
 409        break;
 410    }
 411}
 412
 413static void usb_bt_handle_data(USBDevice *dev, USBPacket *p)
 414{
 415    struct USBBtState *s = (struct USBBtState *) dev->opaque;
 416
 417    if (!s->config)
 418        goto fail;
 419
 420    switch (p->pid) {
 421    case USB_TOKEN_IN:
 422        switch (p->ep->nr) {
 423        case USB_EVT_EP:
 424            if (s->evt.len == 0) {
 425                p->status = USB_RET_NAK;
 426                break;
 427            }
 428            usb_bt_fifo_dequeue(&s->evt, p);
 429            break;
 430
 431        case USB_ACL_EP:
 432            if (s->evt.len == 0) {
 433                p->status = USB_RET_STALL;
 434                break;
 435            }
 436            usb_bt_fifo_dequeue(&s->acl, p);
 437            break;
 438
 439        case USB_SCO_EP:
 440            if (s->evt.len == 0) {
 441                p->status = USB_RET_STALL;
 442                break;
 443            }
 444            usb_bt_fifo_dequeue(&s->sco, p);
 445            break;
 446
 447        default:
 448            goto fail;
 449        }
 450        break;
 451
 452    case USB_TOKEN_OUT:
 453        switch (p->ep->nr) {
 454        case USB_ACL_EP:
 455            usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
 456                            usb_bt_hci_acl_complete, p);
 457            break;
 458
 459        case USB_SCO_EP:
 460            usb_bt_fifo_out_enqueue(s, &s->outsco, s->hci->sco_send,
 461                            usb_bt_hci_sco_complete, p);
 462            break;
 463
 464        default:
 465            goto fail;
 466        }
 467        break;
 468
 469    default:
 470    fail:
 471        p->status = USB_RET_STALL;
 472        break;
 473    }
 474}
 475
 476static void usb_bt_out_hci_packet_event(void *opaque,
 477                const uint8_t *data, int len)
 478{
 479    struct USBBtState *s = (struct USBBtState *) opaque;
 480
 481    if (s->evt.len == 0) {
 482        usb_wakeup(s->intr, 0);
 483    }
 484    usb_bt_fifo_enqueue(&s->evt, data, len);
 485}
 486
 487static void usb_bt_out_hci_packet_acl(void *opaque,
 488                const uint8_t *data, int len)
 489{
 490    struct USBBtState *s = (struct USBBtState *) opaque;
 491
 492    usb_bt_fifo_enqueue(&s->acl, data, len);
 493}
 494
 495static void usb_bt_handle_destroy(USBDevice *dev)
 496{
 497    struct USBBtState *s = (struct USBBtState *) dev->opaque;
 498
 499    s->hci->opaque = NULL;
 500    s->hci->evt_recv = NULL;
 501    s->hci->acl_recv = NULL;
 502}
 503
 504static void usb_bt_realize(USBDevice *dev, Error **errp)
 505{
 506    struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
 507
 508    usb_desc_create_serial(dev);
 509    usb_desc_init(dev);
 510    s->dev.opaque = s;
 511    if (!s->hci) {
 512        s->hci = bt_new_hci(qemu_find_bt_vlan(0));
 513    }
 514    s->hci->opaque = s;
 515    s->hci->evt_recv = usb_bt_out_hci_packet_event;
 516    s->hci->acl_recv = usb_bt_out_hci_packet_acl;
 517    usb_bt_handle_reset(&s->dev);
 518    s->intr = usb_ep_get(dev, USB_TOKEN_IN, USB_EVT_EP);
 519}
 520
 521static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
 522{
 523    USBDevice *dev;
 524    struct USBBtState *s;
 525    HCIInfo *hci;
 526    const char *name = "usb-bt-dongle";
 527
 528    if (*cmdline) {
 529        hci = hci_init(cmdline);
 530    } else {
 531        hci = bt_new_hci(qemu_find_bt_vlan(0));
 532    }
 533
 534    if (!hci)
 535        return NULL;
 536    dev = usb_create(bus, name);
 537    if (!dev) {
 538        error_report("Failed to create USB device '%s'", name);
 539        return NULL;
 540    }
 541    s = DO_UPCAST(struct USBBtState, dev, dev);
 542    s->hci = hci;
 543    if (qdev_init(&dev->qdev) < 0) {
 544        error_report("Failed to initialize USB device '%s'", name);
 545        return NULL;
 546    }
 547
 548    return dev;
 549}
 550
 551static const VMStateDescription vmstate_usb_bt = {
 552    .name = "usb-bt",
 553    .unmigratable = 1,
 554};
 555
 556static void usb_bt_class_initfn(ObjectClass *klass, void *data)
 557{
 558    DeviceClass *dc = DEVICE_CLASS(klass);
 559    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 560
 561    uc->realize        = usb_bt_realize;
 562    uc->product_desc   = "QEMU BT dongle";
 563    uc->usb_desc       = &desc_bluetooth;
 564    uc->handle_reset   = usb_bt_handle_reset;
 565    uc->handle_control = usb_bt_handle_control;
 566    uc->handle_data    = usb_bt_handle_data;
 567    uc->handle_destroy = usb_bt_handle_destroy;
 568    dc->vmsd = &vmstate_usb_bt;
 569    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 570}
 571
 572static const TypeInfo bt_info = {
 573    .name          = "usb-bt-dongle",
 574    .parent        = TYPE_USB_DEVICE,
 575    .instance_size = sizeof(struct USBBtState),
 576    .class_init    = usb_bt_class_initfn,
 577};
 578
 579static void usb_bt_register_types(void)
 580{
 581    type_register_static(&bt_info);
 582    usb_legacy_register("usb-bt-dongle", "bt", usb_bt_init);
 583}
 584
 585type_init(usb_bt_register_types)
 586