aboutsummaryrefslogtreecommitdiff
path: root/protocol/iwrap/iwrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocol/iwrap/iwrap.c')
-rw-r--r--protocol/iwrap/iwrap.c467
1 files changed, 467 insertions, 0 deletions
diff --git a/protocol/iwrap/iwrap.c b/protocol/iwrap/iwrap.c
new file mode 100644
index 000000000..9c68761bf
--- /dev/null
+++ b/protocol/iwrap/iwrap.c
@@ -0,0 +1,467 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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 "usb_keycodes.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
51static uint8_t connected = 0;
52//static uint8_t channel = 1;
53
54/* iWRAP buffer */
55#define MUX_BUF_SIZE 64
56static char buf[MUX_BUF_SIZE];
57static uint8_t snd_pos = 0;
58
59#define MUX_RCV_BUF_SIZE 256
60static char rcv_buf[MUX_RCV_BUF_SIZE];
61static uint8_t rcv_head = 0;
62static uint8_t rcv_tail = 0;
63
64
65/* receive buffer */
66static 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
75static 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/*
86static char rcv_peek(void)
87{
88 if (rcv_head == rcv_tail)
89 return 0;
90 return rcv_buf[rcv_tail];
91}
92*/
93
94static void rcv_clear(void)
95{
96 rcv_tail = rcv_head = 0;
97}
98
99/* iWRAP response */
100ISR(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 *------------------------------------------------------------------*/
139void 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
150void 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
158void iwrap_send(const char *s)
159{
160 while (*s)
161 xmit(*s++);
162}
163
164/* send buffer */
165void 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
172void iwrap_buf_del(void)
173{
174 if (snd_pos)
175 snd_pos--;
176}
177
178void iwrap_buf_send(void)
179{
180 buf[snd_pos] = '\0';
181 snd_pos = 0;
182 iwrap_mux_send(buf);
183}
184
185void 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
227void 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
252void 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
265void iwrap_sleep(void)
266{
267 iwrap_mux_send("SLEEP");
268}
269
270void iwrap_sniff(void)
271{
272}
273
274void iwrap_subrate(void)
275{
276}
277
278bool iwrap_failed(void)
279{
280 if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
281 return true;
282 else
283 return false;
284}
285
286uint8_t iwrap_connected(void)
287{
288 return connected;
289}
290
291uint8_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 *------------------------------------------------------------------*/
307static uint8_t keyboard_leds(void);
308static void send_keyboard(report_keyboard_t *report);
309static void send_mouse(report_mouse_t *report);
310static void send_system(uint16_t data);
311static void send_consumer(uint16_t data);
312
313static host_driver_t driver = {
314 keyboard_leds,
315 send_keyboard,
316 send_mouse,
317 send_system,
318 send_consumer
319};
320
321host_driver_t *iwrap_driver(void)
322{
323 return &driver;
324}
325
326static uint8_t keyboard_leds(void) {
327 return 0;
328}
329
330static 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); // keyboard report
338 xmit(0x01);
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
350static void send_mouse(report_mouse_t *report)
351{
352#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
353 if (!iwrap_connected() && !iwrap_check_connection()) return;
354 MUX_HEADER(0x01, 0x07);
355 // HID raw mode header
356 xmit(0x9f);
357 xmit(0x05); // Length
358 xmit(0xa1); // mouse report
359 xmit(0x02);
360 xmit(report->buttons);
361 xmit(report->x);
362 xmit(report->y);
363 MUX_FOOTER(0x01);
364#endif
365}
366
367static void send_system(uint16_t data)
368{
369 /* not supported */
370}
371
372static void send_consumer(uint16_t data)
373{
374#ifdef EXTRAKEY_ENABLE
375 static uint16_t last_data = 0;
376 uint8_t bits1 = 0;
377 uint8_t bits2 = 0;
378 uint8_t bits3 = 0;
379
380 if (!iwrap_connected() && !iwrap_check_connection()) return;
381 if (data == last_data) return;
382 last_data = data;
383
384 // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
385 switch (data) {
386 case AUDIO_VOL_UP:
387 bits1 = 0x01;
388 break;
389 case AUDIO_VOL_DOWN:
390 bits1 = 0x02;
391 break;
392 case AUDIO_MUTE:
393 bits1 = 0x04;
394 break;
395 case TRANSPORT_PLAY_PAUSE:
396 bits1 = 0x08;
397 break;
398 case TRANSPORT_NEXT_TRACK:
399 bits1 = 0x10;
400 break;
401 case TRANSPORT_PREV_TRACK:
402 bits1 = 0x20;
403 break;
404 case TRANSPORT_STOP:
405 bits1 = 0x40;
406 break;
407 case TRANSPORT_EJECT:
408 bits1 = 0x80;
409 break;
410 case AL_EMAIL:
411 bits2 = 0x01;
412 break;
413 case AC_SEARCH:
414 bits2 = 0x02;
415 break;
416 case AC_BOOKMARKS:
417 bits2 = 0x04;
418 break;
419 case AC_HOME:
420 bits2 = 0x08;
421 break;
422 case AC_BACK:
423 bits2 = 0x10;
424 break;
425 case AC_FORWARD:
426 bits2 = 0x20;
427 break;
428 case AC_STOP:
429 bits2 = 0x40;
430 break;
431 case AC_REFRESH:
432 bits2 = 0x80;
433 break;
434 case AL_CC_CONFIG:
435 bits3 = 0x01;
436 break;
437 case AL_CALCULATOR:
438 bits3 = 0x04;
439 break;
440 case AL_LOCK:
441 bits3 = 0x08;
442 break;
443 case AL_LOCAL_BROWSER:
444 bits3 = 0x10;
445 break;
446 case AC_MINIMIZE:
447 bits3 = 0x20;
448 break;
449 case TRANSPORT_RECORD:
450 bits3 = 0x40;
451 break;
452 case TRANSPORT_REWIND:
453 bits3 = 0x80;
454 break;
455 }
456
457 MUX_HEADER(0x01, 0x07);
458 xmit(0x9f);
459 xmit(0x05); // Length
460 xmit(0xa1); // consumer report
461 xmit(0x03);
462 xmit(bits1);
463 xmit(bits2);
464 xmit(bits3);
465 MUX_FOOTER(0x01);
466#endif
467}