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