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 along
18  * with this program; if not, if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "qemu/osdep.h"
22 #include "qemu/timer.h"
23 #include "ui/console.h"
24 #include "hw/input/hid.h"
25 #include "hw/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     HIDState hid;
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 
bt_hid_reset(struct bt_hid_device_s * s)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     hid_reset(&s->hid);
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 
bt_hid_out(struct bt_hid_device_s * s)127 static int bt_hid_out(struct bt_hid_device_s *s)
128 {
129     if (s->data_type == BT_DATA_OUTPUT) {
130         /* nothing */
131         ;
132     }
133 
134     if (s->data_type == BT_DATA_FEATURE) {
135         /* XXX:
136          * does this send a USB_REQ_CLEAR_FEATURE/USB_REQ_SET_FEATURE
137          * or a SET_REPORT? */
138         ;
139     }
140 
141     return -1;
142 }
143 
bt_hid_in(struct bt_hid_device_s * s)144 static int bt_hid_in(struct bt_hid_device_s *s)
145 {
146     s->datain.len = hid_keyboard_poll(&s->hid, s->datain.buffer,
147                                       sizeof(s->datain.buffer));
148     return s->datain.len;
149 }
150 
bt_hid_send_handshake(struct bt_hid_device_s * s,int result)151 static void bt_hid_send_handshake(struct bt_hid_device_s *s, int result)
152 {
153     *s->control->sdu_out(s->control, 1) =
154             (BT_HANDSHAKE << 4) | result;
155     s->control->sdu_submit(s->control);
156 }
157 
bt_hid_send_control(struct bt_hid_device_s * s,int operation)158 static void bt_hid_send_control(struct bt_hid_device_s *s, int operation)
159 {
160     *s->control->sdu_out(s->control, 1) =
161             (BT_HID_CONTROL << 4) | operation;
162     s->control->sdu_submit(s->control);
163 }
164 
bt_hid_disconnect(struct bt_hid_device_s * s)165 static void bt_hid_disconnect(struct bt_hid_device_s *s)
166 {
167     /* Disconnect s->control and s->interrupt */
168 }
169 
bt_hid_send_data(struct bt_l2cap_conn_params_s * ch,int type,const uint8_t * data,int len)170 static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
171                 const uint8_t *data, int len)
172 {
173     uint8_t *pkt, hdr = (BT_DATA << 4) | type;
174     int plen;
175 
176     do {
177         plen = MIN(len, ch->remote_mtu - 1);
178         pkt = ch->sdu_out(ch, plen + 1);
179 
180         pkt[0] = hdr;
181         if (plen)
182             memcpy(pkt + 1, data, plen);
183         ch->sdu_submit(ch);
184 
185         len -= plen;
186         data += plen;
187         hdr = (BT_DATC << 4) | type;
188     } while (plen == ch->remote_mtu - 1);
189 }
190 
bt_hid_control_transaction(struct bt_hid_device_s * s,const uint8_t * data,int len)191 static void bt_hid_control_transaction(struct bt_hid_device_s *s,
192                 const uint8_t *data, int len)
193 {
194     uint8_t type, parameter;
195     int rlen, ret = -1;
196     if (len < 1)
197         return;
198 
199     type = data[0] >> 4;
200     parameter = data[0] & 0xf;
201 
202     switch (type) {
203     case BT_HANDSHAKE:
204     case BT_DATA:
205         switch (parameter) {
206         default:
207             /* These are not expected to be sent this direction.  */
208             ret = BT_HS_ERR_INVALID_PARAMETER;
209         }
210         break;
211 
212     case BT_HID_CONTROL:
213         if (len != 1 || (parameter != BT_HC_VIRTUAL_CABLE_UNPLUG &&
214                                 s->state == bt_state_transaction)) {
215             ret = BT_HS_ERR_INVALID_PARAMETER;
216             break;
217         }
218         switch (parameter) {
219         case BT_HC_NOP:
220             break;
221         case BT_HC_HARD_RESET:
222         case BT_HC_SOFT_RESET:
223             bt_hid_reset(s);
224             break;
225         case BT_HC_SUSPEND:
226             if (s->state == bt_state_ready)
227                 s->state = bt_state_suspend;
228             else
229                 ret = BT_HS_ERR_INVALID_PARAMETER;
230             break;
231         case BT_HC_EXIT_SUSPEND:
232             if (s->state == bt_state_suspend)
233                 s->state = bt_state_ready;
234             else
235                 ret = BT_HS_ERR_INVALID_PARAMETER;
236             break;
237         case BT_HC_VIRTUAL_CABLE_UNPLUG:
238             bt_hid_disconnect(s);
239             break;
240         default:
241             ret = BT_HS_ERR_INVALID_PARAMETER;
242         }
243         break;
244 
245     case BT_GET_REPORT:
246         /* No ReportIDs declared.  */
247         if (((parameter & 8) && len != 3) ||
248                         (!(parameter & 8) && len != 1) ||
249                         s->state != bt_state_ready) {
250             ret = BT_HS_ERR_INVALID_PARAMETER;
251             break;
252         }
253         if (parameter & 8)
254             rlen = data[2] | (data[3] << 8);
255         else
256             rlen = INT_MAX;
257         switch (parameter & 3) {
258         case BT_DATA_OTHER:
259             ret = BT_HS_ERR_INVALID_PARAMETER;
260             break;
261         case BT_DATA_INPUT:
262             /* Here we can as well poll s->usbdev */
263             bt_hid_send_data(s->control, BT_DATA_INPUT,
264                             s->datain.buffer, MIN(rlen, s->datain.len));
265             break;
266         case BT_DATA_OUTPUT:
267             bt_hid_send_data(s->control, BT_DATA_OUTPUT,
268                             s->dataout.buffer, MIN(rlen, s->dataout.len));
269             break;
270         case BT_DATA_FEATURE:
271             bt_hid_send_data(s->control, BT_DATA_FEATURE,
272                             s->feature.buffer, MIN(rlen, s->feature.len));
273             break;
274         }
275         break;
276 
277     case BT_SET_REPORT:
278         if (len < 2 || len > BT_HID_MTU || s->state != bt_state_ready ||
279                         (parameter & 3) == BT_DATA_OTHER ||
280                         (parameter & 3) == BT_DATA_INPUT) {
281             ret = BT_HS_ERR_INVALID_PARAMETER;
282             break;
283         }
284         s->data_type = parameter & 3;
285         if (s->data_type == BT_DATA_OUTPUT) {
286             s->dataout.len = len - 1;
287             memcpy(s->dataout.buffer, data + 1, s->dataout.len);
288         } else {
289             s->feature.len = len - 1;
290             memcpy(s->feature.buffer, data + 1, s->feature.len);
291         }
292         if (len == BT_HID_MTU)
293             s->state = bt_state_transaction;
294         else
295             bt_hid_out(s);
296         break;
297 
298     case BT_GET_PROTOCOL:
299         if (len != 1 || s->state == bt_state_transaction) {
300             ret = BT_HS_ERR_INVALID_PARAMETER;
301             break;
302         }
303         *s->control->sdu_out(s->control, 1) = s->proto;
304         s->control->sdu_submit(s->control);
305         break;
306 
307     case BT_SET_PROTOCOL:
308         if (len != 1 || s->state == bt_state_transaction ||
309                         (parameter != BT_HID_PROTO_BOOT &&
310                          parameter != BT_HID_PROTO_REPORT)) {
311             ret = BT_HS_ERR_INVALID_PARAMETER;
312             break;
313         }
314         s->proto = parameter;
315         s->hid.protocol = parameter;
316         ret = BT_HS_SUCCESSFUL;
317         break;
318 
319     case BT_GET_IDLE:
320         if (len != 1 || s->state == bt_state_transaction) {
321             ret = BT_HS_ERR_INVALID_PARAMETER;
322             break;
323         }
324         *s->control->sdu_out(s->control, 1) = s->hid.idle;
325         s->control->sdu_submit(s->control);
326         break;
327 
328     case BT_SET_IDLE:
329         if (len != 2 || s->state == bt_state_transaction) {
330             ret = BT_HS_ERR_INVALID_PARAMETER;
331             break;
332         }
333 
334         s->hid.idle = data[1];
335         /* XXX: Does this generate a handshake? */
336         break;
337 
338     case BT_DATC:
339         if (len > BT_HID_MTU || s->state != bt_state_transaction) {
340             ret = BT_HS_ERR_INVALID_PARAMETER;
341             break;
342         }
343         if (s->data_type == BT_DATA_OUTPUT) {
344             memcpy(s->dataout.buffer + s->dataout.len, data + 1, len - 1);
345             s->dataout.len += len - 1;
346         } else {
347             memcpy(s->feature.buffer + s->feature.len, data + 1, len - 1);
348             s->feature.len += len - 1;
349         }
350         if (len < BT_HID_MTU) {
351             bt_hid_out(s);
352             s->state = bt_state_ready;
353         }
354         break;
355 
356     default:
357         ret = BT_HS_ERR_UNSUPPORTED_REQUEST;
358     }
359 
360     if (ret != -1)
361         bt_hid_send_handshake(s, ret);
362 }
363 
bt_hid_control_sdu(void * opaque,const uint8_t * data,int len)364 static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
365 {
366     struct bt_hid_device_s *hid = opaque;
367 
368     bt_hid_control_transaction(hid, data, len);
369 }
370 
bt_hid_datain(HIDState * hs)371 static void bt_hid_datain(HIDState *hs)
372 {
373     struct bt_hid_device_s *hid =
374         container_of(hs, struct bt_hid_device_s, hid);
375 
376     /* If suspended, wake-up and send a wake-up event first.  We might
377      * want to also inspect the input report and ignore event like
378      * mouse movements until a button event occurs.  */
379     if (hid->state == bt_state_suspend) {
380         hid->state = bt_state_ready;
381     }
382 
383     if (bt_hid_in(hid) > 0)
384         /* TODO: when in boot-mode precede any Input reports with the ReportID
385          * byte, here and in GetReport/SetReport on the Control channel.  */
386         bt_hid_send_data(hid->interrupt, BT_DATA_INPUT,
387                         hid->datain.buffer, hid->datain.len);
388 }
389 
bt_hid_interrupt_sdu(void * opaque,const uint8_t * data,int len)390 static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, int len)
391 {
392     struct bt_hid_device_s *hid = opaque;
393 
394     if (len > BT_HID_MTU || len < 1)
395         goto bad;
396     if ((data[0] & 3) != BT_DATA_OUTPUT)
397         goto bad;
398     if ((data[0] >> 4) == BT_DATA) {
399         if (hid->intr_state)
400             goto bad;
401 
402         hid->data_type = BT_DATA_OUTPUT;
403         hid->intrdataout.len = 0;
404     } else if ((data[0] >> 4) == BT_DATC) {
405         if (!hid->intr_state)
406             goto bad;
407     } else
408         goto bad;
409 
410     memcpy(hid->intrdataout.buffer + hid->intrdataout.len, data + 1, len - 1);
411     hid->intrdataout.len += len - 1;
412     hid->intr_state = (len == BT_HID_MTU);
413     if (!hid->intr_state) {
414         memcpy(hid->dataout.buffer, hid->intrdataout.buffer,
415                         hid->dataout.len = hid->intrdataout.len);
416         bt_hid_out(hid);
417     }
418 
419     return;
420 bad:
421     error_report("%s: bad transaction on Interrupt channel.",
422                     __func__);
423 }
424 
425 /* "Virtual cable" plug/unplug event.  */
bt_hid_connected_update(struct bt_hid_device_s * hid)426 static void bt_hid_connected_update(struct bt_hid_device_s *hid)
427 {
428     int prev = hid->connected;
429 
430     hid->connected = hid->control && hid->interrupt;
431 
432     /* Stop page-/inquiry-scanning when a host is connected.  */
433     hid->btdev.device.page_scan = !hid->connected;
434     hid->btdev.device.inquiry_scan = !hid->connected;
435 
436     if (hid->connected && !prev) {
437         hid_reset(&hid->hid);
438         hid->proto = BT_HID_PROTO_REPORT;
439     }
440 
441     /* Should set HIDVirtualCable in SDP (possibly need to check that SDP
442      * isn't destroyed yet, in case we're being called from handle_destroy) */
443 }
444 
bt_hid_close_control(void * opaque)445 static void bt_hid_close_control(void *opaque)
446 {
447     struct bt_hid_device_s *hid = opaque;
448 
449     hid->control = NULL;
450     bt_hid_connected_update(hid);
451 }
452 
bt_hid_close_interrupt(void * opaque)453 static void bt_hid_close_interrupt(void *opaque)
454 {
455     struct bt_hid_device_s *hid = opaque;
456 
457     hid->interrupt = NULL;
458     bt_hid_connected_update(hid);
459 }
460 
bt_hid_new_control_ch(struct bt_l2cap_device_s * dev,struct bt_l2cap_conn_params_s * params)461 static int bt_hid_new_control_ch(struct bt_l2cap_device_s *dev,
462                 struct bt_l2cap_conn_params_s *params)
463 {
464     struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
465 
466     if (hid->control)
467         return 1;
468 
469     hid->control = params;
470     hid->control->opaque = hid;
471     hid->control->close = bt_hid_close_control;
472     hid->control->sdu_in = bt_hid_control_sdu;
473 
474     bt_hid_connected_update(hid);
475 
476     return 0;
477 }
478 
bt_hid_new_interrupt_ch(struct bt_l2cap_device_s * dev,struct bt_l2cap_conn_params_s * params)479 static int bt_hid_new_interrupt_ch(struct bt_l2cap_device_s *dev,
480                 struct bt_l2cap_conn_params_s *params)
481 {
482     struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
483 
484     if (hid->interrupt)
485         return 1;
486 
487     hid->interrupt = params;
488     hid->interrupt->opaque = hid;
489     hid->interrupt->close = bt_hid_close_interrupt;
490     hid->interrupt->sdu_in = bt_hid_interrupt_sdu;
491 
492     bt_hid_connected_update(hid);
493 
494     return 0;
495 }
496 
bt_hid_destroy(struct bt_device_s * dev)497 static void bt_hid_destroy(struct bt_device_s *dev)
498 {
499     struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
500 
501     if (hid->connected)
502         bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG);
503     bt_l2cap_device_done(&hid->btdev);
504 
505     hid_free(&hid->hid);
506 
507     g_free(hid);
508 }
509 
510 enum peripheral_minor_class {
511     class_other		= 0 << 4,
512     class_keyboard	= 1 << 4,
513     class_pointing	= 2 << 4,
514     class_combo		= 3 << 4,
515 };
516 
bt_hid_init(struct bt_scatternet_s * net,enum peripheral_minor_class minor)517 static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
518                                        enum peripheral_minor_class minor)
519 {
520     struct bt_hid_device_s *s = g_malloc0(sizeof(*s));
521     uint32_t class =
522             /* Format type */
523             (0 << 0) |
524             /* Device class */
525             (minor << 2) |
526             (5 << 8) |  /* "Peripheral" */
527             /* Service classes */
528             (1 << 13) | /* Limited discoverable mode */
529             (1 << 19);  /* Capturing device (?) */
530 
531     bt_l2cap_device_init(&s->btdev, net);
532     bt_l2cap_sdp_init(&s->btdev);
533     bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_CTRL,
534                     BT_HID_MTU, bt_hid_new_control_ch);
535     bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_INTR,
536                     BT_HID_MTU, bt_hid_new_interrupt_ch);
537 
538     hid_init(&s->hid, HID_KEYBOARD, bt_hid_datain);
539     s->btdev.device.lmp_name = "BT Keyboard";
540 
541     s->btdev.device.handle_destroy = bt_hid_destroy;
542 
543     s->btdev.device.class[0] = (class >>  0) & 0xff;
544     s->btdev.device.class[1] = (class >>  8) & 0xff;
545     s->btdev.device.class[2] = (class >> 16) & 0xff;
546 
547     return &s->btdev.device;
548 }
549 
bt_keyboard_init(struct bt_scatternet_s * net)550 struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
551 {
552     return bt_hid_init(net, class_keyboard);
553 }
554