Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

iwrap.c 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. Copyright 2011 Jun Wako <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /* host driver for Bulegiga iWRAP */
  15. /* Bluegiga BT12
  16. * Connections
  17. * Hardware UART Software UART BlueTooth
  18. * PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC
  19. *
  20. * - Hardware UART for Debug Console to communicate iWRAP
  21. * - Software UART for iWRAP control to send keyboard/mouse data
  22. */
  23. #include <stdint.h>
  24. #include <string.h>
  25. #include <avr/interrupt.h>
  26. #include <util/delay.h>
  27. #include "keycode.h"
  28. #include "suart.h"
  29. #include "uart.h"
  30. #include "report.h"
  31. #include "host_driver.h"
  32. #include "iwrap.h"
  33. #include "print.h"
  34. /* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */
  35. #define MUX_HEADER(LINK, LENGTH) do { \
  36. xmit(0xbf); /* SOF */ \
  37. xmit(LINK); /* Link */ \
  38. xmit(0x00); /* Flags */ \
  39. xmit(LENGTH); /* Length */ \
  40. } while (0)
  41. #define MUX_FOOTER(LINK) xmit(LINK^0xff)
  42. static uint8_t connected = 0;
  43. //static uint8_t channel = 1;
  44. /* iWRAP buffer */
  45. #define MUX_BUF_SIZE 64
  46. static char buf[MUX_BUF_SIZE];
  47. static uint8_t snd_pos = 0;
  48. #define MUX_RCV_BUF_SIZE 256
  49. static char rcv_buf[MUX_RCV_BUF_SIZE];
  50. static uint8_t rcv_head = 0;
  51. static uint8_t rcv_tail = 0;
  52. /* receive buffer */
  53. static void rcv_enq(char c)
  54. {
  55. uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE;
  56. if (next != rcv_tail) {
  57. rcv_buf[rcv_head] = c;
  58. rcv_head = next;
  59. }
  60. }
  61. static char rcv_deq(void)
  62. {
  63. char c = 0;
  64. if (rcv_head != rcv_tail) {
  65. c = rcv_buf[rcv_tail++];
  66. rcv_tail %= MUX_RCV_BUF_SIZE;
  67. }
  68. return c;
  69. }
  70. /*
  71. static char rcv_peek(void)
  72. {
  73. if (rcv_head == rcv_tail)
  74. return 0;
  75. return rcv_buf[rcv_tail];
  76. }
  77. */
  78. static void rcv_clear(void)
  79. {
  80. rcv_tail = rcv_head = 0;
  81. }
  82. /* iWRAP response */
  83. ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK
  84. {
  85. if ((SUART_IN_PIN & (1<<SUART_IN_BIT)))
  86. return;
  87. static volatile uint8_t mux_state = 0xff;
  88. static volatile uint8_t mux_link = 0xff;
  89. uint8_t c = recv();
  90. switch (mux_state) {
  91. case 0xff: // SOF
  92. if (c == 0xbf)
  93. mux_state--;
  94. break;
  95. case 0xfe: // Link
  96. mux_state--;
  97. mux_link = c;
  98. break;
  99. case 0xfd: // Flags
  100. mux_state--;
  101. break;
  102. case 0xfc: // Length
  103. mux_state = c;
  104. break;
  105. case 0x00:
  106. mux_state = 0xff;
  107. mux_link = 0xff;
  108. break;
  109. default:
  110. if (mux_state--) {
  111. uart_putchar(c);
  112. rcv_enq(c);
  113. }
  114. }
  115. }
  116. /*------------------------------------------------------------------*
  117. * iWRAP communication
  118. *------------------------------------------------------------------*/
  119. void iwrap_init(void)
  120. {
  121. // reset iWRAP if in already MUX mode after AVR software-reset
  122. iwrap_send("RESET");
  123. iwrap_mux_send("RESET");
  124. _delay_ms(3000);
  125. iwrap_send("\r\nSET CONTROL MUX 1\r\n");
  126. _delay_ms(500);
  127. iwrap_check_connection();
  128. }
  129. void iwrap_mux_send(const char *s)
  130. {
  131. rcv_clear();
  132. MUX_HEADER(0xff, strlen((char *)s));
  133. iwrap_send(s);
  134. MUX_FOOTER(0xff);
  135. }
  136. void iwrap_send(const char *s)
  137. {
  138. while (*s)
  139. xmit(*s++);
  140. }
  141. /* send buffer */
  142. void iwrap_buf_add(uint8_t c)
  143. {
  144. // need space for '\0'
  145. if (snd_pos < MUX_BUF_SIZE-1)
  146. buf[snd_pos++] = c;
  147. }
  148. void iwrap_buf_del(void)
  149. {
  150. if (snd_pos)
  151. snd_pos--;
  152. }
  153. void iwrap_buf_send(void)
  154. {
  155. buf[snd_pos] = '\0';
  156. snd_pos = 0;
  157. iwrap_mux_send(buf);
  158. }
  159. void iwrap_call(void)
  160. {
  161. char *p;
  162. iwrap_mux_send("SET BT PAIR");
  163. _delay_ms(500);
  164. p = rcv_buf + rcv_tail;
  165. while (!strncmp(p, "SET BT PAIR", 11)) {
  166. p += 7;
  167. strncpy(p, "CALL", 4);
  168. strncpy(p+22, " 11 HID\n\0", 9);
  169. print_S(p);
  170. iwrap_mux_send(p);
  171. // TODO: skip to next line
  172. p += 57;
  173. DEBUG_LED_CONFIG;
  174. DEBUG_LED_ON;
  175. _delay_ms(500);
  176. DEBUG_LED_OFF;
  177. _delay_ms(500);
  178. DEBUG_LED_ON;
  179. _delay_ms(500);
  180. DEBUG_LED_OFF;
  181. _delay_ms(500);
  182. DEBUG_LED_ON;
  183. _delay_ms(500);
  184. DEBUG_LED_OFF;
  185. _delay_ms(500);
  186. DEBUG_LED_ON;
  187. _delay_ms(500);
  188. DEBUG_LED_OFF;
  189. _delay_ms(500);
  190. DEBUG_LED_ON;
  191. _delay_ms(500);
  192. DEBUG_LED_OFF;
  193. _delay_ms(500);
  194. }
  195. iwrap_check_connection();
  196. }
  197. void iwrap_kill(void)
  198. {
  199. char c;
  200. iwrap_mux_send("LIST");
  201. _delay_ms(500);
  202. while ((c = rcv_deq()) && c != '\n') ;
  203. if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) {
  204. print("no connection to kill.\n");
  205. return;
  206. }
  207. // skip 10 'space' chars
  208. for (uint8_t i = 10; i; i--)
  209. while ((c = rcv_deq()) && c != ' ') ;
  210. char *p = rcv_buf + rcv_tail - 5;
  211. strncpy(p, "KILL ", 5);
  212. strncpy(p + 22, "\n\0", 2);
  213. print_S(p);
  214. iwrap_mux_send(p);
  215. _delay_ms(500);
  216. iwrap_check_connection();
  217. }
  218. void iwrap_unpair(void)
  219. {
  220. iwrap_mux_send("SET BT PAIR");
  221. _delay_ms(500);
  222. char *p = rcv_buf + rcv_tail;
  223. if (!strncmp(p, "SET BT PAIR", 11)) {
  224. strncpy(p+29, "\n\0", 2);
  225. print_S(p);
  226. iwrap_mux_send(p);
  227. }
  228. }
  229. void iwrap_sleep(void)
  230. {
  231. iwrap_mux_send("SLEEP");
  232. }
  233. void iwrap_sniff(void)
  234. {
  235. }
  236. void iwrap_subrate(void)
  237. {
  238. }
  239. bool iwrap_failed(void)
  240. {
  241. if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
  242. return true;
  243. else
  244. return false;
  245. }
  246. uint8_t iwrap_connected(void)
  247. {
  248. return connected;
  249. }
  250. uint8_t iwrap_check_connection(void)
  251. {
  252. iwrap_mux_send("LIST");
  253. _delay_ms(100);
  254. if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6))
  255. connected = 0;
  256. else
  257. connected = 1;
  258. return connected;
  259. }
  260. /*------------------------------------------------------------------*
  261. * Host driver
  262. *------------------------------------------------------------------*/
  263. static uint8_t keyboard_leds(void);
  264. static void send_keyboard(report_keyboard_t *report);
  265. static void send_mouse(report_mouse_t *report);
  266. static void send_system(uint16_t data);
  267. static void send_consumer(uint16_t data);
  268. static host_driver_t driver = {
  269. keyboard_leds,
  270. send_keyboard,
  271. send_mouse,
  272. send_system,
  273. send_consumer
  274. };
  275. host_driver_t *iwrap_driver(void)
  276. {
  277. return &driver;
  278. }
  279. static uint8_t keyboard_leds(void) {
  280. return 0;
  281. }
  282. static void send_keyboard(report_keyboard_t *report)
  283. {
  284. if (!iwrap_connected() && !iwrap_check_connection()) return;
  285. MUX_HEADER(0x01, 0x0c);
  286. // HID raw mode header
  287. xmit(0x9f);
  288. xmit(0x0a); // Length
  289. xmit(0xa1); // keyboard report
  290. xmit(0x01);
  291. xmit(report->mods);
  292. xmit(0x00); // reserved byte(always 0)
  293. xmit(report->keys[0]);
  294. xmit(report->keys[1]);
  295. xmit(report->keys[2]);
  296. xmit(report->keys[3]);
  297. xmit(report->keys[4]);
  298. xmit(report->keys[5]);
  299. MUX_FOOTER(0x01);
  300. }
  301. static void send_mouse(report_mouse_t *report)
  302. {
  303. #if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
  304. if (!iwrap_connected() && !iwrap_check_connection()) return;
  305. MUX_HEADER(0x01, 0x07);
  306. // HID raw mode header
  307. xmit(0x9f);
  308. xmit(0x05); // Length
  309. xmit(0xa1); // mouse report
  310. xmit(0x02);
  311. xmit(report->buttons);
  312. xmit(report->x);
  313. xmit(report->y);
  314. MUX_FOOTER(0x01);
  315. #endif
  316. }
  317. static void send_system(uint16_t data)
  318. {
  319. /* not supported */
  320. }
  321. static void send_consumer(uint16_t data)
  322. {
  323. #ifdef EXTRAKEY_ENABLE
  324. static uint16_t last_data = 0;
  325. uint8_t bits1 = 0;
  326. uint8_t bits2 = 0;
  327. uint8_t bits3 = 0;
  328. if (!iwrap_connected() && !iwrap_check_connection()) return;
  329. if (data == last_data) return;
  330. last_data = data;
  331. // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
  332. switch (data) {
  333. case AUDIO_VOL_UP:
  334. bits1 = 0x01;
  335. break;
  336. case AUDIO_VOL_DOWN:
  337. bits1 = 0x02;
  338. break;
  339. case AUDIO_MUTE:
  340. bits1 = 0x04;
  341. break;
  342. case TRANSPORT_PLAY_PAUSE:
  343. bits1 = 0x08;
  344. break;
  345. case TRANSPORT_NEXT_TRACK:
  346. bits1 = 0x10;
  347. break;
  348. case TRANSPORT_PREV_TRACK:
  349. bits1 = 0x20;
  350. break;
  351. case TRANSPORT_STOP:
  352. bits1 = 0x40;
  353. break;
  354. case TRANSPORT_EJECT:
  355. bits1 = 0x80;
  356. break;
  357. case AL_EMAIL:
  358. bits2 = 0x01;
  359. break;
  360. case AC_SEARCH:
  361. bits2 = 0x02;
  362. break;
  363. case AC_BOOKMARKS:
  364. bits2 = 0x04;
  365. break;
  366. case AC_HOME:
  367. bits2 = 0x08;
  368. break;
  369. case AC_BACK:
  370. bits2 = 0x10;
  371. break;
  372. case AC_FORWARD:
  373. bits2 = 0x20;
  374. break;
  375. case AC_STOP:
  376. bits2 = 0x40;
  377. break;
  378. case AC_REFRESH:
  379. bits2 = 0x80;
  380. break;
  381. case AL_CC_CONFIG:
  382. bits3 = 0x01;
  383. break;
  384. case AL_CALCULATOR:
  385. bits3 = 0x04;
  386. break;
  387. case AL_LOCK:
  388. bits3 = 0x08;
  389. break;
  390. case AL_LOCAL_BROWSER:
  391. bits3 = 0x10;
  392. break;
  393. case AC_MINIMIZE:
  394. bits3 = 0x20;
  395. break;
  396. case TRANSPORT_RECORD:
  397. bits3 = 0x40;
  398. break;
  399. case TRANSPORT_REWIND:
  400. bits3 = 0x80;
  401. break;
  402. }
  403. MUX_HEADER(0x01, 0x07);
  404. xmit(0x9f);
  405. xmit(0x05); // Length
  406. xmit(0xa1); // consumer report
  407. xmit(0x03);
  408. xmit(bits1);
  409. xmit(bits2);
  410. xmit(bits3);
  411. MUX_FOOTER(0x01);
  412. #endif
  413. }