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