qemu/hw/bt/hci-csr.c
<<
>>
Prefs
   1/*
   2 * Bluetooth serial HCI transport.
   3 * CSR41814 HCI with H4p vendor extensions.
   4 *
   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/osdep.h"
  22#include "qemu-common.h"
  23#include "sysemu/char.h"
  24#include "qemu/timer.h"
  25#include "qemu/bswap.h"
  26#include "hw/irq.h"
  27#include "sysemu/bt.h"
  28#include "hw/bt.h"
  29#include "qapi/error.h"
  30
  31struct csrhci_s {
  32    Chardev parent;
  33    int enable;
  34    qemu_irq *pins;
  35    int pin_state;
  36    int modem_state;
  37#define FIFO_LEN        4096
  38    int out_start;
  39    int out_len;
  40    int out_size;
  41    uint8_t outfifo[FIFO_LEN * 2];
  42    uint8_t inpkt[FIFO_LEN];
  43    enum {
  44        CSR_HDR_LEN,
  45        CSR_DATA_LEN,
  46        CSR_DATA
  47    } in_state;
  48    int in_len;
  49    int in_hdr;
  50    int in_needed;
  51    QEMUTimer *out_tm;
  52    int64_t baud_delay;
  53
  54    bdaddr_t bd_addr;
  55    struct HCIInfo *hci;
  56};
  57
  58#define TYPE_CHARDEV_HCI "chardev-hci"
  59#define HCI_CHARDEV(obj) OBJECT_CHECK(struct csrhci_s, (obj), TYPE_CHARDEV_HCI)
  60
  61/* H4+ packet types */
  62enum {
  63    H4_CMD_PKT   = 1,
  64    H4_ACL_PKT   = 2,
  65    H4_SCO_PKT   = 3,
  66    H4_EVT_PKT   = 4,
  67    H4_NEG_PKT   = 6,
  68    H4_ALIVE_PKT = 7,
  69};
  70
  71/* CSR41814 negotiation start magic packet */
  72static const uint8_t csrhci_neg_packet[] = {
  73    H4_NEG_PKT, 10,
  74    0x00, 0xa0, 0x01, 0x00, 0x00,
  75    0x4c, 0x00, 0x96, 0x00, 0x00,
  76};
  77
  78/* CSR41814 vendor-specific command OCFs */
  79enum {
  80    OCF_CSR_SEND_FIRMWARE = 0x000,
  81};
  82
  83static inline void csrhci_fifo_wake(struct csrhci_s *s)
  84{
  85    Chardev *chr = (Chardev *)s;
  86    CharBackend *be = chr->be;
  87
  88    if (!s->enable || !s->out_len)
  89        return;
  90
  91    /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */
  92    if (be && be->chr_can_read && be->chr_can_read(be->opaque) &&
  93        be->chr_read) {
  94        be->chr_read(be->opaque,
  95                     s->outfifo + s->out_start++, 1);
  96        s->out_len--;
  97        if (s->out_start >= s->out_size) {
  98            s->out_start = 0;
  99            s->out_size = FIFO_LEN;
 100        }
 101    }
 102
 103    if (s->out_len)
 104        timer_mod(s->out_tm, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->baud_delay);
 105}
 106
 107#define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
 108static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
 109{
 110    int off = s->out_start + s->out_len;
 111
 112    /* TODO: do the padding here, i.e. align len */
 113    s->out_len += len;
 114
 115    if (off < FIFO_LEN) {
 116        if (off + len > FIFO_LEN && (s->out_size = off + len) > FIFO_LEN * 2) {
 117            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
 118            exit(-1);
 119        }
 120        return s->outfifo + off;
 121    }
 122
 123    if (s->out_len > s->out_size) {
 124        fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
 125        exit(-1);
 126    }
 127
 128    return s->outfifo + off - s->out_size;
 129}
 130
 131static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
 132                int type, int len)
 133{
 134    uint8_t *ret = csrhci_out_packetz(s, len + 2);
 135
 136    *ret ++ = type;
 137    *ret ++ = len;
 138
 139    return ret;
 140}
 141
 142static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
 143                int evt, int len)
 144{
 145    uint8_t *ret = csrhci_out_packetz(s,
 146                    len + 1 + sizeof(struct hci_event_hdr));
 147
 148    *ret ++ = H4_EVT_PKT;
 149    ((struct hci_event_hdr *) ret)->evt = evt;
 150    ((struct hci_event_hdr *) ret)->plen = len;
 151
 152    return ret + sizeof(struct hci_event_hdr);
 153}
 154
 155static void csrhci_in_packet_vendor(struct csrhci_s *s, int ocf,
 156                uint8_t *data, int len)
 157{
 158    int offset;
 159    uint8_t *rpkt;
 160
 161    switch (ocf) {
 162    case OCF_CSR_SEND_FIRMWARE:
 163        /* Check if this is the bd_address packet */
 164        if (len >= 18 + 8 && data[12] == 0x01 && data[13] == 0x00) {
 165            offset = 18;
 166            s->bd_addr.b[0] = data[offset + 7]; /* Beyond cmd packet end(!?) */
 167            s->bd_addr.b[1] = data[offset + 6];
 168            s->bd_addr.b[2] = data[offset + 4];
 169            s->bd_addr.b[3] = data[offset + 0];
 170            s->bd_addr.b[4] = data[offset + 3];
 171            s->bd_addr.b[5] = data[offset + 2];
 172
 173            s->hci->bdaddr_set(s->hci, s->bd_addr.b);
 174            fprintf(stderr, "%s: bd_address loaded from firmware: "
 175                            "%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,
 176                            s->bd_addr.b[0], s->bd_addr.b[1], s->bd_addr.b[2],
 177                            s->bd_addr.b[3], s->bd_addr.b[4], s->bd_addr.b[5]);
 178        }
 179
 180        rpkt = csrhci_out_packet_event(s, EVT_VENDOR, 11);
 181        /* Status bytes: no error */
 182        rpkt[9] = 0x00;
 183        rpkt[10] = 0x00;
 184        break;
 185
 186    default:
 187        fprintf(stderr, "%s: got a bad CMD packet\n", __FUNCTION__);
 188        return;
 189    }
 190
 191    csrhci_fifo_wake(s);
 192}
 193
 194static void csrhci_in_packet(struct csrhci_s *s, uint8_t *pkt)
 195{
 196    uint8_t *rpkt;
 197    int opc;
 198
 199    switch (*pkt ++) {
 200    case H4_CMD_PKT:
 201        opc = le16_to_cpu(((struct hci_command_hdr *) pkt)->opcode);
 202        if (cmd_opcode_ogf(opc) == OGF_VENDOR_CMD) {
 203            csrhci_in_packet_vendor(s, cmd_opcode_ocf(opc),
 204                            pkt + sizeof(struct hci_command_hdr),
 205                            s->in_len - sizeof(struct hci_command_hdr) - 1);
 206            return;
 207        }
 208
 209        /* TODO: if the command is OCF_READ_LOCAL_COMMANDS or the likes,
 210         * we need to send it to the HCI layer and then add our supported
 211         * commands to the returned mask (such as OGF_VENDOR_CMD).  With
 212         * bt-hci.c we could just have hooks for this kind of commands but
 213         * we can't with bt-host.c.  */
 214
 215        s->hci->cmd_send(s->hci, pkt, s->in_len - 1);
 216        break;
 217
 218    case H4_EVT_PKT:
 219        goto bad_pkt;
 220
 221    case H4_ACL_PKT:
 222        s->hci->acl_send(s->hci, pkt, s->in_len - 1);
 223        break;
 224
 225    case H4_SCO_PKT:
 226        s->hci->sco_send(s->hci, pkt, s->in_len - 1);
 227        break;
 228
 229    case H4_NEG_PKT:
 230        if (s->in_hdr != sizeof(csrhci_neg_packet) ||
 231                        memcmp(pkt - 1, csrhci_neg_packet, s->in_hdr)) {
 232            fprintf(stderr, "%s: got a bad NEG packet\n", __FUNCTION__);
 233            return;
 234        }
 235        pkt += 2;
 236
 237        rpkt = csrhci_out_packet_csr(s, H4_NEG_PKT, 10);
 238
 239        *rpkt ++ = 0x20;        /* Operational settings negotiation Ok */
 240        memcpy(rpkt, pkt, 7); rpkt += 7;
 241        *rpkt ++ = 0xff;
 242        *rpkt = 0xff;
 243        break;
 244
 245    case H4_ALIVE_PKT:
 246        if (s->in_hdr != 4 || pkt[1] != 0x55 || pkt[2] != 0x00) {
 247            fprintf(stderr, "%s: got a bad ALIVE packet\n", __FUNCTION__);
 248            return;
 249        }
 250
 251        rpkt = csrhci_out_packet_csr(s, H4_ALIVE_PKT, 2);
 252
 253        *rpkt ++ = 0xcc;
 254        *rpkt = 0x00;
 255        break;
 256
 257    default:
 258    bad_pkt:
 259        /* TODO: error out */
 260        fprintf(stderr, "%s: got a bad packet\n", __FUNCTION__);
 261        break;
 262    }
 263
 264    csrhci_fifo_wake(s);
 265}
 266
 267static int csrhci_header_len(const uint8_t *pkt)
 268{
 269    switch (pkt[0]) {
 270    case H4_CMD_PKT:
 271        return HCI_COMMAND_HDR_SIZE;
 272    case H4_EVT_PKT:
 273        return HCI_EVENT_HDR_SIZE;
 274    case H4_ACL_PKT:
 275        return HCI_ACL_HDR_SIZE;
 276    case H4_SCO_PKT:
 277        return HCI_SCO_HDR_SIZE;
 278    case H4_NEG_PKT:
 279        return pkt[1] + 1;
 280    case H4_ALIVE_PKT:
 281        return 3;
 282    }
 283
 284    exit(-1);
 285}
 286
 287static int csrhci_data_len(const uint8_t *pkt)
 288{
 289    switch (*pkt ++) {
 290    case H4_CMD_PKT:
 291        /* It seems that vendor-specific command packets for H4+ are all
 292         * one byte longer than indicated in the standard header.  */
 293        if (le16_to_cpu(((struct hci_command_hdr *) pkt)->opcode) == 0xfc00)
 294            return (((struct hci_command_hdr *) pkt)->plen + 1) & ~1;
 295
 296        return ((struct hci_command_hdr *) pkt)->plen;
 297    case H4_EVT_PKT:
 298        return ((struct hci_event_hdr *) pkt)->plen;
 299    case H4_ACL_PKT:
 300        return le16_to_cpu(((struct hci_acl_hdr *) pkt)->dlen);
 301    case H4_SCO_PKT:
 302        return ((struct hci_sco_hdr *) pkt)->dlen;
 303    case H4_NEG_PKT:
 304    case H4_ALIVE_PKT:
 305        return 0;
 306    }
 307
 308    exit(-1);
 309}
 310
 311static void csrhci_ready_for_next_inpkt(struct csrhci_s *s)
 312{
 313    s->in_state = CSR_HDR_LEN;
 314    s->in_len = 0;
 315    s->in_needed = 2;
 316    s->in_hdr = INT_MAX;
 317}
 318
 319static int csrhci_write(struct Chardev *chr,
 320                const uint8_t *buf, int len)
 321{
 322    struct csrhci_s *s = (struct csrhci_s *)chr;
 323    int total = 0;
 324
 325    if (!s->enable)
 326        return 0;
 327
 328    for (;;) {
 329        int cnt = MIN(len, s->in_needed - s->in_len);
 330        if (cnt) {
 331            memcpy(s->inpkt + s->in_len, buf, cnt);
 332            s->in_len += cnt;
 333            buf += cnt;
 334            len -= cnt;
 335            total += cnt;
 336        }
 337
 338        if (s->in_len < s->in_needed) {
 339            break;
 340        }
 341
 342        if (s->in_state == CSR_HDR_LEN) {
 343            s->in_hdr = csrhci_header_len(s->inpkt) + 1;
 344            assert(s->in_hdr >= s->in_needed);
 345            s->in_needed = s->in_hdr;
 346            s->in_state = CSR_DATA_LEN;
 347            continue;
 348        }
 349
 350        if (s->in_state == CSR_DATA_LEN) {
 351            s->in_needed += csrhci_data_len(s->inpkt);
 352            /* hci_acl_hdr could specify more than 4096 bytes, so assert.  */
 353            assert(s->in_needed <= sizeof(s->inpkt));
 354            s->in_state = CSR_DATA;
 355            continue;
 356        }
 357
 358        if (s->in_state == CSR_DATA) {
 359            csrhci_in_packet(s, s->inpkt);
 360            csrhci_ready_for_next_inpkt(s);
 361        }
 362    }
 363
 364    return total;
 365}
 366
 367static void csrhci_out_hci_packet_event(void *opaque,
 368                const uint8_t *data, int len)
 369{
 370    struct csrhci_s *s = (struct csrhci_s *) opaque;
 371    uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1);        /* Align */
 372
 373    *pkt ++ = H4_EVT_PKT;
 374    memcpy(pkt, data, len);
 375
 376    csrhci_fifo_wake(s);
 377}
 378
 379static void csrhci_out_hci_packet_acl(void *opaque,
 380                const uint8_t *data, int len)
 381{
 382    struct csrhci_s *s = (struct csrhci_s *) opaque;
 383    uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1);        /* Align */
 384
 385    *pkt ++ = H4_ACL_PKT;
 386    pkt[len & ~1] = 0;
 387    memcpy(pkt, data, len);
 388
 389    csrhci_fifo_wake(s);
 390}
 391
 392static int csrhci_ioctl(struct Chardev *chr, int cmd, void *arg)
 393{
 394    QEMUSerialSetParams *ssp;
 395    struct csrhci_s *s = (struct csrhci_s *) chr;
 396    int prev_state = s->modem_state;
 397
 398    switch (cmd) {
 399    case CHR_IOCTL_SERIAL_SET_PARAMS:
 400        ssp = (QEMUSerialSetParams *) arg;
 401        s->baud_delay = NANOSECONDS_PER_SECOND / ssp->speed;
 402        /* Moments later... (but shorter than 100ms) */
 403        s->modem_state |= CHR_TIOCM_CTS;
 404        break;
 405
 406    case CHR_IOCTL_SERIAL_GET_TIOCM:
 407        *(int *) arg = s->modem_state;
 408        break;
 409
 410    case CHR_IOCTL_SERIAL_SET_TIOCM:
 411        s->modem_state = *(int *) arg;
 412        if (~s->modem_state & prev_state & CHR_TIOCM_RTS)
 413            s->modem_state &= ~CHR_TIOCM_CTS;
 414        break;
 415
 416    default:
 417        return -ENOTSUP;
 418    }
 419    return 0;
 420}
 421
 422static void csrhci_reset(struct csrhci_s *s)
 423{
 424    s->out_len = 0;
 425    s->out_size = FIFO_LEN;
 426    csrhci_ready_for_next_inpkt(s);
 427    s->baud_delay = NANOSECONDS_PER_SECOND;
 428    s->enable = 0;
 429
 430    s->modem_state = 0;
 431    /* After a while... (but sooner than 10ms) */
 432    s->modem_state |= CHR_TIOCM_CTS;
 433
 434    memset(&s->bd_addr, 0, sizeof(bdaddr_t));
 435}
 436
 437static void csrhci_out_tick(void *opaque)
 438{
 439    csrhci_fifo_wake((struct csrhci_s *) opaque);
 440}
 441
 442static void csrhci_pins(void *opaque, int line, int level)
 443{
 444    struct csrhci_s *s = (struct csrhci_s *) opaque;
 445    int state = s->pin_state;
 446
 447    s->pin_state &= ~(1 << line);
 448    s->pin_state |= (!!level) << line;
 449
 450    if ((state & ~s->pin_state) & (1 << csrhci_pin_reset)) {
 451        /* TODO: Disappear from lower layers */
 452        csrhci_reset(s);
 453    }
 454
 455    if (s->pin_state == 3 && state != 3) {
 456        s->enable = 1;
 457        /* TODO: Wake lower layers up */
 458    }
 459}
 460
 461qemu_irq *csrhci_pins_get(Chardev *chr)
 462{
 463    struct csrhci_s *s = (struct csrhci_s *) chr;
 464
 465    return s->pins;
 466}
 467
 468static void csrhci_open(Chardev *chr,
 469                        ChardevBackend *backend,
 470                        bool *be_opened,
 471                        Error **errp)
 472{
 473    struct csrhci_s *s = HCI_CHARDEV(chr);
 474
 475    s->hci = qemu_next_hci();
 476    s->hci->opaque = s;
 477    s->hci->evt_recv = csrhci_out_hci_packet_event;
 478    s->hci->acl_recv = csrhci_out_hci_packet_acl;
 479
 480    s->out_tm = timer_new_ns(QEMU_CLOCK_VIRTUAL, csrhci_out_tick, s);
 481    s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins);
 482    csrhci_reset(s);
 483    *be_opened = false;
 484}
 485
 486static void char_hci_class_init(ObjectClass *oc, void *data)
 487{
 488    ChardevClass *cc = CHARDEV_CLASS(oc);
 489
 490    cc->internal = true;
 491    cc->open = csrhci_open;
 492    cc->chr_write = csrhci_write;
 493    cc->chr_ioctl = csrhci_ioctl;
 494}
 495
 496static const TypeInfo char_hci_type_info = {
 497    .name = TYPE_CHARDEV_HCI,
 498    .parent = TYPE_CHARDEV,
 499    .instance_size = sizeof(struct csrhci_s),
 500    .class_init = char_hci_class_init,
 501};
 502
 503Chardev *uart_hci_init(void)
 504{
 505    return qemu_chardev_new(NULL, TYPE_CHARDEV_HCI,
 506                            NULL, &error_abort);
 507}
 508
 509static void register_types(void)
 510{
 511    type_register_static(&char_hci_type_info);
 512}
 513
 514type_init(register_types);
 515