]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/bluefruit/bluefruit.c
bluetooth
[qmk_firmware.git] / protocol / bluefruit / bluefruit.c
1 /*
2 Bluefruit Protocol for TMK firmware
3 Author: Benjamin Gould, 2013
4 Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
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 You should have received a copy of the GNU General Public License
14 along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <stdint.h>
18 #include "host.h"
19 #include "report.h"
20 #include "print.h"
21 #include "debug.h"
22 #include "host_driver.h"
23 #include "serial.h"
24 #include "bluefruit.h"
25
26 #define BLUEFRUIT_TRACE_SERIAL 1
27
28 static uint8_t bluefruit_keyboard_leds = 0;
29
30 static void bluefruit_serial_send(uint8_t);
31
32 void bluefruit_keyboard_print_report(report_keyboard_t *report)
33 {
34     if (!debug_keyboard) return;
35     dprintf("keys: "); for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); }
36     dprintf(" mods: "); debug_hex8(report->mods);
37     dprintf(" reserved: "); debug_hex8(report->reserved); 
38     dprintf("\n");
39 }
40
41 #ifdef BLUEFRUIT_TRACE_SERIAL
42 static void bluefruit_trace_header()
43 {
44     dprintf("+------------------------------------+\n");
45     dprintf("| HID report to Bluefruit via serial |\n");
46     dprintf("+------------------------------------+\n|");
47 }
48
49 static void bluefruit_trace_footer()
50 {
51     dprintf("|\n+------------------------------------+\n\n");
52 }
53 #endif
54
55 static void bluefruit_serial_send(uint8_t data)
56 {
57 #ifdef BLUEFRUIT_TRACE_SERIAL
58     dprintf(" ");
59     debug_hex8(data);
60     dprintf(" ");
61 #endif
62     serial_send(data);
63 }
64
65 /*------------------------------------------------------------------*
66  * Host driver
67  *------------------------------------------------------------------*/
68
69 static uint8_t keyboard_leds(void);
70 static void send_keyboard(report_keyboard_t *report);
71 static void send_mouse(report_mouse_t *report);
72 static void send_system(uint16_t data);
73 static void send_consumer(uint16_t data);
74
75
76 void sendString(char string[], int length) {
77     for(int i = 0; i < length; i++) {
78         serial_send(string[i]);
79     }
80 }
81
82 static host_driver_t driver = {
83         keyboard_leds,
84         send_keyboard,
85         send_mouse,
86         send_system,
87         send_consumer
88 };
89
90 host_driver_t *bluefruit_driver(void)
91 {
92     return &driver;
93 }
94
95 static uint8_t keyboard_leds(void) {
96     return bluefruit_keyboard_leds;
97 }
98
99 static void send_keyboard(report_keyboard_t *report)
100 {
101 #ifdef BLUEFRUIT_TRACE_SERIAL   
102     bluefruit_trace_header();
103 #endif
104     bluefruit_serial_send(0xFD);
105     for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
106
107         bluefruit_serial_send(report->raw[i]);
108     }
109 #ifdef BLUEFRUIT_TRACE_SERIAL   
110     bluefruit_trace_footer();   
111 #endif
112 }
113
114 static void send_mouse(report_mouse_t *report)
115 {
116 #ifdef BLUEFRUIT_TRACE_SERIAL   
117     bluefruit_trace_header();
118 #endif
119     bluefruit_serial_send(0xFD);
120     bluefruit_serial_send(0x00);
121     bluefruit_serial_send(0x03);
122     bluefruit_serial_send(report->buttons);
123     bluefruit_serial_send(report->x);
124     bluefruit_serial_send(report->y);
125     bluefruit_serial_send(report->v); // should try sending the wheel v here
126     bluefruit_serial_send(report->h); // should try sending the wheel h here
127     bluefruit_serial_send(0x00);
128 #ifdef BLUEFRUIT_TRACE_SERIAL
129     bluefruit_trace_footer();
130 #endif
131 }
132
133 static void send_system(uint16_t data)
134 {
135 }
136
137 /*
138 +-----------------+-------------------+-------+
139 | Consumer Key    | Bit Map           | Hex   |
140 +-----------------+-------------------+-------+
141 | Home            | 00000001 00000000 | 01 00 |
142 | KeyboardLayout  | 00000010 00000000 | 02 00 |
143 | Search          | 00000100 00000000 | 04 00 |
144 | Snapshot        | 00001000 00000000 | 08 00 |
145 | VolumeUp        | 00010000 00000000 | 10 00 |
146 | VolumeDown      | 00100000 00000000 | 20 00 |
147 | Play/Pause      | 01000000 00000000 | 40 00 |
148 | Fast Forward    | 10000000 00000000 | 80 00 |
149 | Rewind          | 00000000 00000001 | 00 01 |
150 | Scan Next Track | 00000000 00000010 | 00 02 |
151 | Scan Prev Track | 00000000 00000100 | 00 04 |
152 | Random Play     | 00000000 00001000 | 00 08 |
153 | Stop            | 00000000 00010000 | 00 10 |
154 +-------------------------------------+-------+
155 */
156 #define CONSUMER2BLUEFRUIT(usage) \
157     (usage == AUDIO_MUTE           ? 0x0000  : \
158     (usage == AUDIO_VOL_UP         ? 0x1000  : \
159     (usage == AUDIO_VOL_DOWN       ? 0x2000  : \
160     (usage == TRANSPORT_NEXT_TRACK ? 0x0002  : \
161     (usage == TRANSPORT_PREV_TRACK ? 0x0004  : \
162     (usage == TRANSPORT_STOP       ? 0x0010  : \
163     (usage == TRANSPORT_STOP_EJECT ? 0x0000  : \
164     (usage == TRANSPORT_PLAY_PAUSE ? 0x4000  : \
165     (usage == AL_CC_CONFIG         ? 0x0000  : \
166     (usage == AL_EMAIL             ? 0x0000  : \
167     (usage == AL_CALCULATOR        ? 0x0000  : \
168     (usage == AL_LOCAL_BROWSER     ? 0x0000  : \
169     (usage == AC_SEARCH            ? 0x0400  : \
170     (usage == AC_HOME              ? 0x0100  : \
171     (usage == AC_BACK              ? 0x0000  : \
172     (usage == AC_FORWARD           ? 0x0000  : \
173     (usage == AC_STOP              ? 0x0000  : \
174     (usage == AC_REFRESH           ? 0x0000  : \
175     (usage == AC_BOOKMARKS         ? 0x0000  : 0)))))))))))))))))))
176
177 static void send_consumer(uint16_t data)
178 {
179     static uint16_t last_data = 0;
180     if (data == last_data) return;
181     last_data = data;
182     
183     uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
184     
185 #ifdef BLUEFRUIT_TRACE_SERIAL   
186     dprintf("\nData: "); 
187     debug_hex16(data); 
188     dprintf("; bitmap: "); 
189     debug_hex16(bitmap); 
190     dprintf("\n");
191     bluefruit_trace_header();
192 #endif
193     bluefruit_serial_send(0xFD);
194     bluefruit_serial_send(0x00);
195     bluefruit_serial_send(0x02);
196     bluefruit_serial_send((bitmap>>8)&0xFF);
197     bluefruit_serial_send(bitmap&0xFF); 
198     bluefruit_serial_send(0x00);
199     bluefruit_serial_send(0x00);
200     bluefruit_serial_send(0x00);
201     bluefruit_serial_send(0x00);
202 #ifdef BLUEFRUIT_TRACE_SERIAL
203     bluefruit_trace_footer();
204 #endif
205 }