bt-hid.c 15 KB

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