4602d9e06e843fb8f50ea187c107ee49036051e5
[qemu] / hw / bt-hid.c
1 /*
2  * QEMU Bluetooth HID Profile wrapper for USB HID.
3  *
4  * Copyright (C) 2007-2008 OpenMoko, Inc.
5  * Written by Andrzej Zaborowski <andrew@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
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 "bt.h"
26
27 enum hid_transaction_req {
28     BT_HANDSHAKE                        = 0x0,
29     BT_HID_CONTROL                      = 0x1,
30     BT_GET_REPORT                       = 0x4,
31     BT_SET_REPORT                       = 0x5,
32     BT_GET_PROTOCOL                     = 0x6,
33     BT_SET_PROTOCOL                     = 0x7,
34     BT_GET_IDLE                         = 0x8,
35     BT_SET_IDLE                         = 0x9,
36     BT_DATA                             = 0xa,
37     BT_DATC                             = 0xb,
38 };
39
40 enum hid_transaction_handshake {
41     BT_HS_SUCCESSFUL                    = 0x0,
42     BT_HS_NOT_READY                     = 0x1,
43     BT_HS_ERR_INVALID_REPORT_ID         = 0x2,
44     BT_HS_ERR_UNSUPPORTED_REQUEST       = 0x3,
45     BT_HS_ERR_INVALID_PARAMETER         = 0x4,
46     BT_HS_ERR_UNKNOWN                   = 0xe,
47     BT_HS_ERR_FATAL                     = 0xf,
48 };
49
50 enum hid_transaction_control {
51     BT_HC_NOP                           = 0x0,
52     BT_HC_HARD_RESET                    = 0x1,
53     BT_HC_SOFT_RESET                    = 0x2,
54     BT_HC_SUSPEND                       = 0x3,
55     BT_HC_EXIT_SUSPEND                  = 0x4,
56     BT_HC_VIRTUAL_CABLE_UNPLUG          = 0x5,
57 };
58
59 enum hid_protocol {
60     BT_HID_PROTO_BOOT                   = 0,
61     BT_HID_PROTO_REPORT                 = 1,
62 };
63
64 enum hid_boot_reportid {
65     BT_HID_BOOT_INVALID                 = 0,
66     BT_HID_BOOT_KEYBOARD,
67     BT_HID_BOOT_MOUSE,
68 };
69
70 enum hid_data_pkt {
71     BT_DATA_OTHER                       = 0,
72     BT_DATA_INPUT,
73     BT_DATA_OUTPUT,
74     BT_DATA_FEATURE,
75 };
76
77 #define BT_HID_MTU                      48
78
79 /* HID interface requests */
80 #define GET_REPORT                      0xa101
81 #define GET_IDLE                        0xa102
82 #define GET_PROTOCOL                    0xa103
83 #define SET_REPORT                      0x2109
84 #define SET_IDLE                        0x210a
85 #define SET_PROTOCOL                    0x210b
86
87 struct bt_hid_device_s {
88     struct bt_l2cap_device_s btdev;
89     struct bt_l2cap_conn_params_s *control;
90     struct bt_l2cap_conn_params_s *interrupt;
91     USBDevice *usbdev;
92
93     int proto;
94     int connected;
95     int data_type;
96     int intr_state;
97     struct {
98         int len;
99         uint8_t buffer[1024];
100     } dataother, datain, dataout, feature, intrdataout;
101     enum {
102         bt_state_ready,
103         bt_state_transaction,
104         bt_state_suspend,
105     } state;
106 };
107
108 static void bt_hid_reset(struct bt_hid_device_s *s)
109 {
110     struct bt_scatternet_s *net = s->btdev.device.net;
111
112     /* Go as far as... */
113     bt_l2cap_device_done(&s->btdev);
114     bt_l2cap_device_init(&s->btdev, net);
115
116     s->usbdev->handle_reset(s->usbdev);
117     s->proto = BT_HID_PROTO_REPORT;
118     s->state = bt_state_ready;
119     s->dataother.len = 0;
120     s->datain.len = 0;
121     s->dataout.len = 0;
122     s->feature.len = 0;
123     s->intrdataout.len = 0;
124     s->intr_state = 0;
125 }
126
127 static int bt_hid_out(struct bt_hid_device_s *s)
128 {
129     USBPacket p;
130
131     if (s->data_type == BT_DATA_OUTPUT) {
132         p.pid = USB_TOKEN_OUT;
133         p.devep = 1;
134         p.data = s->dataout.buffer;
135         p.len = s->dataout.len;
136         s->dataout.len = s->usbdev->handle_data(s->usbdev, &p);
137
138         return s->dataout.len;
139     }
140
141     if (s->data_type == BT_DATA_FEATURE) {
142         /* XXX:
143          * does this send a USB_REQ_CLEAR_FEATURE/USB_REQ_SET_FEATURE
144          * or a SET_REPORT? */
145         p.devep = 0;
146     }
147
148     return -1;
149 }
150
151 static int bt_hid_in(struct bt_hid_device_s *s)
152 {
153     USBPacket p;
154
155     p.pid = USB_TOKEN_IN;
156     p.devep = 1;
157     p.data = s->datain.buffer;
158     p.len = sizeof(s->datain.buffer);
159     s->datain.len = s->usbdev->handle_data(s->usbdev, &p);
160
161     return s->datain.len;
162 }
163
164 static void bt_hid_send_handshake(struct bt_hid_device_s *s, int result)
165 {
166     *s->control->sdu_out(s->control, 1) =
167             (BT_HANDSHAKE << 4) | result;
168     s->control->sdu_submit(s->control);
169 }
170
171 static void bt_hid_send_control(struct bt_hid_device_s *s, int operation)
172 {
173     *s->control->sdu_out(s->control, 1) =
174             (BT_HID_CONTROL << 4) | operation;
175     s->control->sdu_submit(s->control);
176 }
177
178 static void bt_hid_disconnect(struct bt_hid_device_s *s)
179 {
180     /* Disconnect s->control and s->interrupt */
181 }
182
183 static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
184                 const uint8_t *data, int len)
185 {
186     uint8_t *pkt, hdr = (BT_DATA << 4) | type;
187     int plen;
188
189     do {
190         plen = MIN(len, ch->remote_mtu - 1);
191         pkt = ch->sdu_out(ch, plen + 1);
192
193         pkt[0] = hdr;
194         if (plen)
195             memcpy(pkt + 1, data, plen);
196         ch->sdu_submit(ch);
197
198         len -= plen;
199         data += plen;
200         hdr = (BT_DATC << 4) | type;
201     } while (plen == ch->remote_mtu - 1);
202 }
203
204 static void bt_hid_control_transaction(struct bt_hid_device_s *s,
205                 const uint8_t *data, int len)
206 {
207     uint8_t type, parameter;
208     int rlen, ret = -1;
209     if (len < 1)
210         return;
211
212     type = data[0] >> 4;
213     parameter = data[0] & 0xf;
214
215     switch (type) {
216     case BT_HANDSHAKE:
217     case BT_DATA:
218         switch (parameter) {
219         default:
220             /* These are not expected to be sent this direction.  */
221             ret = BT_HS_ERR_INVALID_PARAMETER;
222         }
223         break;
224
225     case BT_HID_CONTROL:
226         if (len != 1 || (parameter != BT_HC_VIRTUAL_CABLE_UNPLUG &&
227                                 s->state == bt_state_transaction)) {
228             ret = BT_HS_ERR_INVALID_PARAMETER;
229             break;
230         }
231         switch (parameter) {
232         case BT_HC_NOP:
233             break;
234         case BT_HC_HARD_RESET:
235         case BT_HC_SOFT_RESET:
236             bt_hid_reset(s);
237             break;
238         case BT_HC_SUSPEND:
239             if (s->state == bt_state_ready)
240                 s->state = bt_state_suspend;
241             else
242                 ret = BT_HS_ERR_INVALID_PARAMETER;
243             break;
244         case BT_HC_EXIT_SUSPEND:
245             if (s->state == bt_state_suspend)
246                 s->state = bt_state_ready;
247             else
248                 ret = BT_HS_ERR_INVALID_PARAMETER;
249             break;
250         case BT_HC_VIRTUAL_CABLE_UNPLUG:
251             bt_hid_disconnect(s);
252             break;
253         default:
254             ret = BT_HS_ERR_INVALID_PARAMETER;
255         }
256         break;
257
258     case BT_GET_REPORT:
259         /* No ReportIDs declared.  */
260         if (((parameter & 8) && len != 3) ||
261                         (!(parameter & 8) && len != 1) ||
262                         s->state != bt_state_ready) {
263             ret = BT_HS_ERR_INVALID_PARAMETER;
264             break;
265         }
266         if (parameter & 8)
267             rlen = data[2] | (data[3] << 8);
268         else
269             rlen = INT_MAX;
270         switch (parameter & 3) {
271         case BT_DATA_OTHER:
272             ret = BT_HS_ERR_INVALID_PARAMETER;
273             break;
274         case BT_DATA_INPUT:
275             /* Here we can as well poll s->usbdev */
276             bt_hid_send_data(s->control, BT_DATA_INPUT,
277                             s->datain.buffer, MIN(rlen, s->datain.len));
278             break;
279         case BT_DATA_OUTPUT:
280             bt_hid_send_data(s->control, BT_DATA_OUTPUT,
281                             s->dataout.buffer, MIN(rlen, s->dataout.len));
282             break;
283         case BT_DATA_FEATURE:
284             bt_hid_send_data(s->control, BT_DATA_FEATURE,
285                             s->feature.buffer, MIN(rlen, s->feature.len));
286             break;
287         }
288         break;
289
290     case BT_SET_REPORT:
291         if (len < 2 || len > BT_HID_MTU || s->state != bt_state_ready ||
292                         (parameter & 3) == BT_DATA_OTHER ||
293                         (parameter & 3) == BT_DATA_INPUT) {
294             ret = BT_HS_ERR_INVALID_PARAMETER;
295             break;
296         }
297         s->data_type = parameter & 3;
298         if (s->data_type == BT_DATA_OUTPUT) {
299             s->dataout.len = len - 1;
300             memcpy(s->dataout.buffer, data + 1, s->dataout.len);
301         } else {
302             s->feature.len = len - 1;
303             memcpy(s->feature.buffer, data + 1, s->feature.len);
304         }
305         if (len == BT_HID_MTU)
306             s->state = bt_state_transaction;
307         else
308             bt_hid_out(s);
309         break;
310
311     case BT_GET_PROTOCOL:
312         if (len != 1 || s->state == bt_state_transaction) {
313             ret = BT_HS_ERR_INVALID_PARAMETER;
314             break;
315         }
316         *s->control->sdu_out(s->control, 1) = s->proto;
317         s->control->sdu_submit(s->control);
318         break;
319
320     case BT_SET_PROTOCOL:
321         if (len != 1 || s->state == bt_state_transaction ||
322                         (parameter != BT_HID_PROTO_BOOT &&
323                          parameter != BT_HID_PROTO_REPORT)) {
324             ret = BT_HS_ERR_INVALID_PARAMETER;
325             break;
326         }
327         s->proto = parameter;
328         s->usbdev->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0, 0);
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, 0) ?
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     return 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 = 0;
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 = 0;
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 }