Home | History | Annotate | Download | only in hw
      1 /*
      2  * QEMU Bluetooth HID Profile wrapper for USB HID.
      3  *
      4  * Copyright (C) 2007-2008 OpenMoko, Inc.
      5  * Written by Andrzej Zaborowski <andrew (at) openedhand.com>
      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, write to the Free Software Foundation, Inc.,
     19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     20  */
     21 
     22 #include "qemu-common.h"
     23 #include "usb.h"
     24 #include "bt.h"
     25 
     26 enum hid_transaction_req {
     27     BT_HANDSHAKE			= 0x0,
     28     BT_HID_CONTROL			= 0x1,
     29     BT_GET_REPORT			= 0x4,
     30     BT_SET_REPORT			= 0x5,
     31     BT_GET_PROTOCOL			= 0x6,
     32     BT_SET_PROTOCOL			= 0x7,
     33     BT_GET_IDLE				= 0x8,
     34     BT_SET_IDLE				= 0x9,
     35     BT_DATA				= 0xa,
     36     BT_DATC				= 0xb,
     37 };
     38 
     39 enum hid_transaction_handshake {
     40     BT_HS_SUCCESSFUL			= 0x0,
     41     BT_HS_NOT_READY			= 0x1,
     42     BT_HS_ERR_INVALID_REPORT_ID		= 0x2,
     43     BT_HS_ERR_UNSUPPORTED_REQUEST	= 0x3,
     44     BT_HS_ERR_INVALID_PARAMETER		= 0x4,
     45     BT_HS_ERR_UNKNOWN			= 0xe,
     46     BT_HS_ERR_FATAL			= 0xf,
     47 };
     48 
     49 enum hid_transaction_control {
     50     BT_HC_NOP				= 0x0,
     51     BT_HC_HARD_RESET			= 0x1,
     52     BT_HC_SOFT_RESET			= 0x2,
     53     BT_HC_SUSPEND			= 0x3,
     54     BT_HC_EXIT_SUSPEND			= 0x4,
     55     BT_HC_VIRTUAL_CABLE_UNPLUG		= 0x5,
     56 };
     57 
     58 enum hid_protocol {
     59     BT_HID_PROTO_BOOT			= 0,
     60     BT_HID_PROTO_REPORT			= 1,
     61 };
     62 
     63 enum hid_boot_reportid {
     64     BT_HID_BOOT_INVALID			= 0,
     65     BT_HID_BOOT_KEYBOARD,
     66     BT_HID_BOOT_MOUSE,
     67 };
     68 
     69 enum hid_data_pkt {
     70     BT_DATA_OTHER			= 0,
     71     BT_DATA_INPUT,
     72     BT_DATA_OUTPUT,
     73     BT_DATA_FEATURE,
     74 };
     75 
     76 #define BT_HID_MTU			48
     77 
     78 /* HID interface requests */
     79 #define GET_REPORT			0xa101
     80 #define GET_IDLE			0xa102
     81 #define GET_PROTOCOL			0xa103
     82 #define SET_REPORT			0x2109
     83 #define SET_IDLE			0x210a
     84 #define SET_PROTOCOL			0x210b
     85 
     86 struct bt_hid_device_s {
     87     struct bt_l2cap_device_s btdev;
     88     struct bt_l2cap_conn_params_s *control;
     89     struct bt_l2cap_conn_params_s *interrupt;
     90     USBDevice *usbdev;
     91 
     92     int proto;
     93     int connected;
     94     int data_type;
     95     int intr_state;
     96     struct {
     97         int len;
     98         uint8_t buffer[1024];
     99     } dataother, datain, dataout, feature, intrdataout;
    100     enum {
    101         bt_state_ready,
    102         bt_state_transaction,
    103         bt_state_suspend,
    104     } state;
    105 };
    106 
    107 static void bt_hid_reset(struct bt_hid_device_s *s)
    108 {
    109     struct bt_scatternet_s *net = s->btdev.device.net;
    110 
    111     /* Go as far as... */
    112     bt_l2cap_device_done(&s->btdev);
    113     bt_l2cap_device_init(&s->btdev, net);
    114 
    115     s->usbdev->handle_reset(s->usbdev);
    116     s->proto = BT_HID_PROTO_REPORT;
    117     s->state = bt_state_ready;
    118     s->dataother.len = 0;
    119     s->datain.len = 0;
    120     s->dataout.len = 0;
    121     s->feature.len = 0;
    122     s->intrdataout.len = 0;
    123     s->intr_state = 0;
    124 }
    125 
    126 static int bt_hid_out(struct bt_hid_device_s *s)
    127 {
    128     USBPacket p;
    129 
    130     if (s->data_type == BT_DATA_OUTPUT) {
    131         p.pid = USB_TOKEN_OUT;
    132         p.devep = 1;
    133         p.data = s->dataout.buffer;
    134         p.len = s->dataout.len;
    135         s->dataout.len = s->usbdev->handle_data(s->usbdev, &p);
    136 
    137         return s->dataout.len;
    138     }
    139 
    140     if (s->data_type == BT_DATA_FEATURE) {
    141         /* XXX:
    142          * does this send a USB_REQ_CLEAR_FEATURE/USB_REQ_SET_FEATURE
    143          * or a SET_REPORT? */
    144         p.devep = 0;
    145     }
    146 
    147     return -1;
    148 }
    149 
    150 static int bt_hid_in(struct bt_hid_device_s *s)
    151 {
    152     USBPacket p;
    153 
    154     p.pid = USB_TOKEN_IN;
    155     p.devep = 1;
    156     p.data = s->datain.buffer;
    157     p.len = sizeof(s->datain.buffer);
    158     s->datain.len = s->usbdev->handle_data(s->usbdev, &p);
    159 
    160     return s->datain.len;
    161 }
    162 
    163 static void bt_hid_send_handshake(struct bt_hid_device_s *s, int result)
    164 {
    165     *s->control->sdu_out(s->control, 1) =
    166             (BT_HANDSHAKE << 4) | result;
    167     s->control->sdu_submit(s->control);
    168 }
    169 
    170 static void bt_hid_send_control(struct bt_hid_device_s *s, int operation)
    171 {
    172     *s->control->sdu_out(s->control, 1) =
    173             (BT_HID_CONTROL << 4) | operation;
    174     s->control->sdu_submit(s->control);
    175 }
    176 
    177 static void bt_hid_disconnect(struct bt_hid_device_s *s)
    178 {
    179     /* Disconnect s->control and s->interrupt */
    180 }
    181 
    182 static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
    183                 const uint8_t *data, int len)
    184 {
    185     uint8_t *pkt, hdr = (BT_DATA << 4) | type;
    186     int plen;
    187 
    188     do {
    189         plen = MIN(len, ch->remote_mtu - 1);
    190         pkt = ch->sdu_out(ch, plen + 1);
    191 
    192         pkt[0] = hdr;
    193         if (plen)
    194             memcpy(pkt + 1, data, plen);
    195         ch->sdu_submit(ch);
    196 
    197         len -= plen;
    198         data += plen;
    199         hdr = (BT_DATC << 4) | type;
    200     } while (plen == ch->remote_mtu - 1);
    201 }
    202 
    203 static void bt_hid_control_transaction(struct bt_hid_device_s *s,
    204                 const uint8_t *data, int len)
    205 {
    206     uint8_t type, parameter;
    207     int rlen, ret = -1;
    208     if (len < 1)
    209         return;
    210 
    211     type = data[0] >> 4;
    212     parameter = data[0] & 0xf;
    213 
    214     switch (type) {
    215     case BT_HANDSHAKE:
    216     case BT_DATA:
    217         switch (parameter) {
    218         default:
    219             /* These are not expected to be sent this direction.  */
    220             ret = BT_HS_ERR_INVALID_PARAMETER;
    221         }
    222         break;
    223 
    224     case BT_HID_CONTROL:
    225         if (len != 1 || (parameter != BT_HC_VIRTUAL_CABLE_UNPLUG &&
    226                                 s->state == bt_state_transaction)) {
    227             ret = BT_HS_ERR_INVALID_PARAMETER;
    228             break;
    229         }
    230         switch (parameter) {
    231         case BT_HC_NOP:
    232             break;
    233         case BT_HC_HARD_RESET:
    234         case BT_HC_SOFT_RESET:
    235             bt_hid_reset(s);
    236             break;
    237         case BT_HC_SUSPEND:
    238             if (s->state == bt_state_ready)
    239                 s->state = bt_state_suspend;
    240             else
    241                 ret = BT_HS_ERR_INVALID_PARAMETER;
    242             break;
    243         case BT_HC_EXIT_SUSPEND:
    244             if (s->state == bt_state_suspend)
    245                 s->state = bt_state_ready;
    246             else
    247                 ret = BT_HS_ERR_INVALID_PARAMETER;
    248             break;
    249         case BT_HC_VIRTUAL_CABLE_UNPLUG:
    250             bt_hid_disconnect(s);
    251             break;
    252         default:
    253             ret = BT_HS_ERR_INVALID_PARAMETER;
    254         }
    255         break;
    256 
    257     case BT_GET_REPORT:
    258         /* No ReportIDs declared.  */
    259         if (((parameter & 8) && len != 3) ||
    260                         (!(parameter & 8) && len != 1) ||
    261                         s->state != bt_state_ready) {
    262             ret = BT_HS_ERR_INVALID_PARAMETER;
    263             break;
    264         }
    265         if (parameter & 8)
    266             rlen = data[2] | (data[3] << 8);
    267         else
    268             rlen = INT_MAX;
    269         switch (parameter & 3) {
    270         case BT_DATA_OTHER:
    271             ret = BT_HS_ERR_INVALID_PARAMETER;
    272             break;
    273         case BT_DATA_INPUT:
    274             /* Here we can as well poll s->usbdev */
    275             bt_hid_send_data(s->control, BT_DATA_INPUT,
    276                             s->datain.buffer, MIN(rlen, s->datain.len));
    277             break;
    278         case BT_DATA_OUTPUT:
    279             bt_hid_send_data(s->control, BT_DATA_OUTPUT,
    280                             s->dataout.buffer, MIN(rlen, s->dataout.len));
    281             break;
    282         case BT_DATA_FEATURE:
    283             bt_hid_send_data(s->control, BT_DATA_FEATURE,
    284                             s->feature.buffer, MIN(rlen, s->feature.len));
    285             break;
    286         }
    287         break;
    288 
    289     case BT_SET_REPORT:
    290         if (len < 2 || len > BT_HID_MTU || s->state != bt_state_ready ||
    291                         (parameter & 3) == BT_DATA_OTHER ||
    292                         (parameter & 3) == BT_DATA_INPUT) {
    293             ret = BT_HS_ERR_INVALID_PARAMETER;
    294             break;
    295         }
    296         s->data_type = parameter & 3;
    297         if (s->data_type == BT_DATA_OUTPUT) {
    298             s->dataout.len = len - 1;
    299             memcpy(s->dataout.buffer, data + 1, s->dataout.len);
    300         } else {
    301             s->feature.len = len - 1;
    302             memcpy(s->feature.buffer, data + 1, s->feature.len);
    303         }
    304         if (len == BT_HID_MTU)
    305             s->state = bt_state_transaction;
    306         else
    307             bt_hid_out(s);
    308         break;
    309 
    310     case BT_GET_PROTOCOL:
    311         if (len != 1 || s->state == bt_state_transaction) {
    312             ret = BT_HS_ERR_INVALID_PARAMETER;
    313             break;
    314         }
    315         *s->control->sdu_out(s->control, 1) = s->proto;
    316         s->control->sdu_submit(s->control);
    317         break;
    318 
    319     case BT_SET_PROTOCOL:
    320         if (len != 1 || s->state == bt_state_transaction ||
    321                         (parameter != BT_HID_PROTO_BOOT &&
    322                          parameter != BT_HID_PROTO_REPORT)) {
    323             ret = BT_HS_ERR_INVALID_PARAMETER;
    324             break;
    325         }
    326         s->proto = parameter;
    327         s->usbdev->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
    328                                   NULL);
    329         ret = BT_HS_SUCCESSFUL;
    330         break;
    331 
    332     case BT_GET_IDLE:
    333         if (len != 1 || s->state == bt_state_transaction) {
    334             ret = BT_HS_ERR_INVALID_PARAMETER;
    335             break;
    336         }
    337         s->usbdev->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
    338                         s->control->sdu_out(s->control, 1));
    339         s->control->sdu_submit(s->control);
    340         break;
    341 
    342     case BT_SET_IDLE:
    343         if (len != 2 || s->state == bt_state_transaction) {
    344             ret = BT_HS_ERR_INVALID_PARAMETER;
    345             break;
    346         }
    347 
    348         /* We don't need to know about the Idle Rate here really,
    349          * so just pass it on to the device.  */
    350         ret = s->usbdev->handle_control(s->usbdev,
    351                         SET_IDLE, data[1], 0, 0, NULL) ?
    352                 BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
    353         /* XXX: Does this generate a handshake? */
    354         break;
    355 
    356     case BT_DATC:
    357         if (len > BT_HID_MTU || s->state != bt_state_transaction) {
    358             ret = BT_HS_ERR_INVALID_PARAMETER;
    359             break;
    360         }
    361         if (s->data_type == BT_DATA_OUTPUT) {
    362             memcpy(s->dataout.buffer + s->dataout.len, data + 1, len - 1);
    363             s->dataout.len += len - 1;
    364         } else {
    365             memcpy(s->feature.buffer + s->feature.len, data + 1, len - 1);
    366             s->feature.len += len - 1;
    367         }
    368         if (len < BT_HID_MTU) {
    369             bt_hid_out(s);
    370             s->state = bt_state_ready;
    371         }
    372         break;
    373 
    374     default:
    375         ret = BT_HS_ERR_UNSUPPORTED_REQUEST;
    376     }
    377 
    378     if (ret != -1)
    379         bt_hid_send_handshake(s, ret);
    380 }
    381 
    382 static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
    383 {
    384     struct bt_hid_device_s *hid = opaque;
    385 
    386     bt_hid_control_transaction(hid, data, len);
    387 }
    388 
    389 static void bt_hid_datain(void *opaque)
    390 {
    391     struct bt_hid_device_s *hid = opaque;
    392 
    393     /* If suspended, wake-up and send a wake-up event first.  We might
    394      * want to also inspect the input report and ignore event like
    395      * mouse movements until a button event occurs.  */
    396     if (hid->state == bt_state_suspend) {
    397         hid->state = bt_state_ready;
    398     }
    399 
    400     if (bt_hid_in(hid) > 0)
    401         /* TODO: when in boot-mode precede any Input reports with the ReportID
    402          * byte, here and in GetReport/SetReport on the Control channel.  */
    403         bt_hid_send_data(hid->interrupt, BT_DATA_INPUT,
    404                         hid->datain.buffer, hid->datain.len);
    405 }
    406 
    407 static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, int len)
    408 {
    409     struct bt_hid_device_s *hid = opaque;
    410 
    411     if (len > BT_HID_MTU || len < 1)
    412         goto bad;
    413     if ((data[0] & 3) != BT_DATA_OUTPUT)
    414         goto bad;
    415     if ((data[0] >> 4) == BT_DATA) {
    416         if (hid->intr_state)
    417             goto bad;
    418 
    419         hid->data_type = BT_DATA_OUTPUT;
    420         hid->intrdataout.len = 0;
    421     } else if ((data[0] >> 4) == BT_DATC) {
    422         if (!hid->intr_state)
    423             goto bad;
    424     } else
    425         goto bad;
    426 
    427     memcpy(hid->intrdataout.buffer + hid->intrdataout.len, data + 1, len - 1);
    428     hid->intrdataout.len += len - 1;
    429     hid->intr_state = (len == BT_HID_MTU);
    430     if (!hid->intr_state) {
    431         memcpy(hid->dataout.buffer, hid->intrdataout.buffer,
    432                         hid->dataout.len = hid->intrdataout.len);
    433         bt_hid_out(hid);
    434     }
    435 
    436     return;
    437 bad:
    438     fprintf(stderr, "%s: bad transaction on Interrupt channel.\n",
    439                     __FUNCTION__);
    440 }
    441 
    442 /* "Virtual cable" plug/unplug event.  */
    443 static void bt_hid_connected_update(struct bt_hid_device_s *hid)
    444 {
    445     int prev = hid->connected;
    446 
    447     hid->connected = hid->control && hid->interrupt;
    448 
    449     /* Stop page-/inquiry-scanning when a host is connected.  */
    450     hid->btdev.device.page_scan = !hid->connected;
    451     hid->btdev.device.inquiry_scan = !hid->connected;
    452 
    453     if (hid->connected && !prev) {
    454         hid->usbdev->handle_reset(hid->usbdev);
    455         hid->proto = BT_HID_PROTO_REPORT;
    456     }
    457 
    458     /* Should set HIDVirtualCable in SDP (possibly need to check that SDP
    459      * isn't destroyed yet, in case we're being called from handle_destroy) */
    460 }
    461 
    462 static void bt_hid_close_control(void *opaque)
    463 {
    464     struct bt_hid_device_s *hid = opaque;
    465 
    466     hid->control = NULL;
    467     bt_hid_connected_update(hid);
    468 }
    469 
    470 static void bt_hid_close_interrupt(void *opaque)
    471 {
    472     struct bt_hid_device_s *hid = opaque;
    473 
    474     hid->interrupt = NULL;
    475     bt_hid_connected_update(hid);
    476 }
    477 
    478 static int bt_hid_new_control_ch(struct bt_l2cap_device_s *dev,
    479                 struct bt_l2cap_conn_params_s *params)
    480 {
    481     struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
    482 
    483     if (hid->control)
    484         return 1;
    485 
    486     hid->control = params;
    487     hid->control->opaque = hid;
    488     hid->control->close = bt_hid_close_control;
    489     hid->control->sdu_in = bt_hid_control_sdu;
    490 
    491     bt_hid_connected_update(hid);
    492 
    493     return 0;
    494 }
    495 
    496 static int bt_hid_new_interrupt_ch(struct bt_l2cap_device_s *dev,
    497                 struct bt_l2cap_conn_params_s *params)
    498 {
    499     struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
    500 
    501     if (hid->interrupt)
    502         return 1;
    503 
    504     hid->interrupt = params;
    505     hid->interrupt->opaque = hid;
    506     hid->interrupt->close = bt_hid_close_interrupt;
    507     hid->interrupt->sdu_in = bt_hid_interrupt_sdu;
    508 
    509     bt_hid_connected_update(hid);
    510 
    511     return 0;
    512 }
    513 
    514 static void bt_hid_destroy(struct bt_device_s *dev)
    515 {
    516     struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
    517 
    518     if (hid->connected)
    519         bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG);
    520     bt_l2cap_device_done(&hid->btdev);
    521 
    522     hid->usbdev->handle_destroy(hid->usbdev);
    523 
    524     qemu_free(hid);
    525 }
    526 
    527 enum peripheral_minor_class {
    528     class_other		= 0 << 4,
    529     class_keyboard	= 1 << 4,
    530     class_pointing	= 2 << 4,
    531     class_combo		= 3 << 4,
    532 };
    533 
    534 static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
    535                 USBDevice *dev, enum peripheral_minor_class minor)
    536 {
    537     struct bt_hid_device_s *s = qemu_mallocz(sizeof(*s));
    538     uint32_t class =
    539             /* Format type */
    540             (0 << 0) |
    541             /* Device class */
    542             (minor << 2) |
    543             (5 << 8) |  /* "Peripheral" */
    544             /* Service classes */
    545             (1 << 13) | /* Limited discoverable mode */
    546             (1 << 19);  /* Capturing device (?) */
    547 
    548     bt_l2cap_device_init(&s->btdev, net);
    549     bt_l2cap_sdp_init(&s->btdev);
    550     bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_CTRL,
    551                     BT_HID_MTU, bt_hid_new_control_ch);
    552     bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_INTR,
    553                     BT_HID_MTU, bt_hid_new_interrupt_ch);
    554 
    555     s->usbdev = dev;
    556     s->btdev.device.lmp_name = s->usbdev->devname;
    557     usb_hid_datain_cb(s->usbdev, s, bt_hid_datain);
    558 
    559     s->btdev.device.handle_destroy = bt_hid_destroy;
    560 
    561     s->btdev.device.class[0] = (class >>  0) & 0xff;
    562     s->btdev.device.class[1] = (class >>  8) & 0xff;
    563     s->btdev.device.class[2] = (class >> 16) & 0xff;
    564 
    565     return &s->btdev.device;
    566 }
    567 
    568 struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
    569 {
    570     return bt_hid_init(net, usb_keyboard_init(), class_keyboard);
    571 }
    572