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.

420 lines
10 KiB

  1. /*
  2. Copyright 2011 Jun Wako <wakojun@gmail.com>
  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) \
  36. do { \
  37. xmit(0xbf); /* SOF */ \
  38. xmit(LINK); /* Link */ \
  39. xmit(0x00); /* Flags */ \
  40. xmit(LENGTH); /* Length */ \
  41. } while (0)
  42. #define MUX_FOOTER(LINK) xmit(LINK ^ 0xff)
  43. static uint8_t connected = 0;
  44. // static uint8_t channel = 1;
  45. /* iWRAP buffer */
  46. #define MUX_BUF_SIZE 64
  47. static char buf[MUX_BUF_SIZE];
  48. static uint8_t snd_pos = 0;
  49. #define MUX_RCV_BUF_SIZE 256
  50. static char rcv_buf[MUX_RCV_BUF_SIZE];
  51. static uint8_t rcv_head = 0;
  52. static uint8_t rcv_tail = 0;
  53. /* receive buffer */
  54. static void rcv_enq(char c) {
  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. char c = 0;
  63. if (rcv_head != rcv_tail) {
  64. c = rcv_buf[rcv_tail++];
  65. rcv_tail %= MUX_RCV_BUF_SIZE;
  66. }
  67. return c;
  68. }
  69. /*
  70. static char rcv_peek(void)
  71. {
  72. if (rcv_head == rcv_tail)
  73. return 0;
  74. return rcv_buf[rcv_tail];
  75. }
  76. */
  77. static void rcv_clear(void) { rcv_tail = rcv_head = 0; }
  78. /* iWRAP response */
  79. ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK
  80. {
  81. if ((SUART_IN_PIN & (1 << SUART_IN_BIT))) return;
  82. static volatile uint8_t mux_state = 0xff;
  83. static volatile uint8_t mux_link = 0xff;
  84. uint8_t c = recv();
  85. switch (mux_state) {
  86. case 0xff: // SOF
  87. if (c == 0xbf) mux_state--;
  88. break;
  89. case 0xfe: // Link
  90. mux_state--;
  91. mux_link = c;
  92. break;
  93. case 0xfd: // Flags
  94. mux_state--;
  95. break;
  96. case 0xfc: // Length
  97. mux_state = c;
  98. break;
  99. case 0x00:
  100. mux_state = 0xff;
  101. mux_link = 0xff;
  102. break;
  103. default:
  104. if (mux_state--) {
  105. uart_putchar(c);
  106. rcv_enq(c);
  107. }
  108. }
  109. }
  110. /*------------------------------------------------------------------*
  111. * iWRAP communication
  112. *------------------------------------------------------------------*/
  113. void iwrap_init(void) {
  114. // reset iWRAP if in already MUX mode after AVR software-reset
  115. iwrap_send("RESET");
  116. iwrap_mux_send("RESET");
  117. _delay_ms(3000);
  118. iwrap_send("\r\nSET CONTROL MUX 1\r\n");
  119. _delay_ms(500);
  120. iwrap_check_connection();
  121. }
  122. void iwrap_mux_send(const char *s) {
  123. rcv_clear();
  124. MUX_HEADER(0xff, strlen((char *)s));
  125. iwrap_send(s);
  126. MUX_FOOTER(0xff);
  127. }
  128. void iwrap_send(const char *s) {
  129. while (*s) xmit(*s++);
  130. }
  131. /* send buffer */
  132. void iwrap_buf_add(uint8_t c) {
  133. // need space for '\0'
  134. if (snd_pos < MUX_BUF_SIZE - 1) buf[snd_pos++] = c;
  135. }
  136. void iwrap_buf_del(void) {
  137. if (snd_pos) snd_pos--;
  138. }
  139. void iwrap_buf_send(void) {
  140. buf[snd_pos] = '\0';
  141. snd_pos = 0;
  142. iwrap_mux_send(buf);
  143. }
  144. void iwrap_call(void) {
  145. char *p;
  146. iwrap_mux_send("SET BT PAIR");
  147. _delay_ms(500);
  148. p = rcv_buf + rcv_tail;
  149. while (!strncmp(p, "SET BT PAIR", 11)) {
  150. p += 7;
  151. strncpy(p, "CALL", 4);
  152. strncpy(p + 22, " 11 HID\n\0", 9);
  153. print_S(p);
  154. iwrap_mux_send(p);
  155. // TODO: skip to next line
  156. p += 57;
  157. DEBUG_LED_CONFIG;
  158. DEBUG_LED_ON;
  159. _delay_ms(500);
  160. DEBUG_LED_OFF;
  161. _delay_ms(500);
  162. DEBUG_LED_ON;
  163. _delay_ms(500);
  164. DEBUG_LED_OFF;
  165. _delay_ms(500);
  166. DEBUG_LED_ON;
  167. _delay_ms(500);
  168. DEBUG_LED_OFF;
  169. _delay_ms(500);
  170. DEBUG_LED_ON;
  171. _delay_ms(500);
  172. DEBUG_LED_OFF;
  173. _delay_ms(500);
  174. DEBUG_LED_ON;
  175. _delay_ms(500);
  176. DEBUG_LED_OFF;
  177. _delay_ms(500);
  178. }
  179. iwrap_check_connection();
  180. }
  181. void iwrap_kill(void) {
  182. char c;
  183. iwrap_mux_send("LIST");
  184. _delay_ms(500);
  185. while ((c = rcv_deq()) && c != '\n')
  186. ;
  187. if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) {
  188. print("no connection to kill.\n");
  189. return;
  190. }
  191. // skip 10 'space' chars
  192. for (uint8_t i = 10; i; i--)
  193. while ((c = rcv_deq()) && c != ' ')
  194. ;
  195. char *p = rcv_buf + rcv_tail - 5;
  196. strncpy(p, "KILL ", 5);
  197. strncpy(p + 22, "\n\0", 2);
  198. print_S(p);
  199. iwrap_mux_send(p);
  200. _delay_ms(500);
  201. iwrap_check_connection();
  202. }
  203. void iwrap_unpair(void) {
  204. iwrap_mux_send("SET BT PAIR");
  205. _delay_ms(500);
  206. char *p = rcv_buf + rcv_tail;
  207. if (!strncmp(p, "SET BT PAIR", 11)) {
  208. strncpy(p + 29, "\n\0", 2);
  209. print_S(p);
  210. iwrap_mux_send(p);
  211. }
  212. }
  213. void iwrap_sleep(void) { iwrap_mux_send("SLEEP"); }
  214. void iwrap_sniff(void) {}
  215. void iwrap_subrate(void) {}
  216. bool iwrap_failed(void) {
  217. if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
  218. return true;
  219. else
  220. return false;
  221. }
  222. uint8_t iwrap_connected(void) { return connected; }
  223. uint8_t iwrap_check_connection(void) {
  224. iwrap_mux_send("LIST");
  225. _delay_ms(100);
  226. if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6))
  227. connected = 0;
  228. else
  229. connected = 1;
  230. return connected;
  231. }
  232. /*------------------------------------------------------------------*
  233. * Host driver
  234. *------------------------------------------------------------------*/
  235. static uint8_t keyboard_leds(void);
  236. static void send_keyboard(report_keyboard_t *report);
  237. static void send_mouse(report_mouse_t *report);
  238. static void send_system(uint16_t data);
  239. static void send_consumer(uint16_t data);
  240. static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
  241. host_driver_t *iwrap_driver(void) { return &driver; }
  242. static uint8_t keyboard_leds(void) { return 0; }
  243. static void send_keyboard(report_keyboard_t *report) {
  244. if (!iwrap_connected() && !iwrap_check_connection()) return;
  245. MUX_HEADER(0x01, 0x0c);
  246. // HID raw mode header
  247. xmit(0x9f);
  248. xmit(0x0a); // Length
  249. xmit(0xa1); // DATA(Input)
  250. xmit(0x01); // Report ID
  251. xmit(report->mods);
  252. xmit(0x00); // reserved byte(always 0)
  253. xmit(report->keys[0]);
  254. xmit(report->keys[1]);
  255. xmit(report->keys[2]);
  256. xmit(report->keys[3]);
  257. xmit(report->keys[4]);
  258. xmit(report->keys[5]);
  259. MUX_FOOTER(0x01);
  260. }
  261. static void send_mouse(report_mouse_t *report) {
  262. #if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) || defined(POINTING_DEVICE_ENABLE)
  263. if (!iwrap_connected() && !iwrap_check_connection()) return;
  264. MUX_HEADER(0x01, 0x09);
  265. // HID raw mode header
  266. xmit(0x9f);
  267. xmit(0x07); // Length
  268. xmit(0xa1); // DATA(Input)
  269. xmit(0x02); // Report ID
  270. xmit(report->buttons);
  271. xmit(report->x);
  272. xmit(report->y);
  273. xmit(report->v);
  274. xmit(report->h);
  275. MUX_FOOTER(0x01);
  276. #endif
  277. }
  278. static void send_system(uint16_t data) { /* not supported */
  279. }
  280. static void send_consumer(uint16_t data) {
  281. #ifdef EXTRAKEY_ENABLE
  282. static uint16_t last_data = 0;
  283. uint8_t bits1 = 0;
  284. uint8_t bits2 = 0;
  285. uint8_t bits3 = 0;
  286. if (!iwrap_connected() && !iwrap_check_connection()) return;
  287. if (data == last_data) return;
  288. last_data = data;
  289. // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
  290. switch (data) {
  291. case AUDIO_VOL_UP:
  292. bits1 = 0x01;
  293. break;
  294. case AUDIO_VOL_DOWN:
  295. bits1 = 0x02;
  296. break;
  297. case AUDIO_MUTE:
  298. bits1 = 0x04;
  299. break;
  300. case TRANSPORT_PLAY_PAUSE:
  301. bits1 = 0x08;
  302. break;
  303. case TRANSPORT_NEXT_TRACK:
  304. bits1 = 0x10;
  305. break;
  306. case TRANSPORT_PREV_TRACK:
  307. bits1 = 0x20;
  308. break;
  309. case TRANSPORT_STOP:
  310. bits1 = 0x40;
  311. break;
  312. case TRANSPORT_EJECT:
  313. bits1 = 0x80;
  314. break;
  315. case AL_EMAIL:
  316. bits2 = 0x01;
  317. break;
  318. case AC_SEARCH:
  319. bits2 = 0x02;
  320. break;
  321. case AC_BOOKMARKS:
  322. bits2 = 0x04;
  323. break;
  324. case AC_HOME:
  325. bits2 = 0x08;
  326. break;
  327. case AC_BACK:
  328. bits2 = 0x10;
  329. break;
  330. case AC_FORWARD:
  331. bits2 = 0x20;
  332. break;
  333. case AC_STOP:
  334. bits2 = 0x40;
  335. break;
  336. case AC_REFRESH:
  337. bits2 = 0x80;
  338. break;
  339. case AL_CC_CONFIG:
  340. bits3 = 0x01;
  341. break;
  342. case AL_CALCULATOR:
  343. bits3 = 0x04;
  344. break;
  345. case AL_LOCK:
  346. bits3 = 0x08;
  347. break;
  348. case AL_LOCAL_BROWSER:
  349. bits3 = 0x10;
  350. break;
  351. case AC_MINIMIZE:
  352. bits3 = 0x20;
  353. break;
  354. case TRANSPORT_RECORD:
  355. bits3 = 0x40;
  356. break;
  357. case TRANSPORT_REWIND:
  358. bits3 = 0x80;
  359. break;
  360. }
  361. MUX_HEADER(0x01, 0x07);
  362. xmit(0x9f);
  363. xmit(0x05); // Length
  364. xmit(0xa1); // DATA(Input)
  365. xmit(0x03); // Report ID
  366. xmit(bits1);
  367. xmit(bits2);
  368. xmit(bits3);
  369. MUX_FOOTER(0x01);
  370. #endif
  371. }