]>
Commit | Line | Data |
---|---|---|
b4e4f599 | 1 | #include <avr/io.h> |
4069776c | 2 | #include "host.h" |
3 | #include "host_driver.h" | |
31a298f9 | 4 | #include "serial.h" |
4069776c | 5 | #include "rn42.h" |
31a298f9 | 6 | #include "print.h" |
4f121de7 | 7 | #include "timer.h" |
31a298f9 | 8 | #include "wait.h" |
4069776c | 9 | |
10 | ||
11 | /* Host driver */ | |
12 | static uint8_t keyboard_leds(void); | |
13 | static void send_keyboard(report_keyboard_t *report); | |
14 | static void send_mouse(report_mouse_t *report); | |
15 | static void send_system(uint16_t data); | |
16 | static void send_consumer(uint16_t data); | |
17 | ||
18 | host_driver_t rn42_driver = { | |
19 | keyboard_leds, | |
20 | send_keyboard, | |
21 | send_mouse, | |
22 | send_system, | |
23 | send_consumer | |
24 | }; | |
25 | ||
31a298f9 | 26 | |
27 | void rn42_init(void) | |
28 | { | |
31a298f9 | 29 | // JTAG disable for PORT F. write JTD bit twice within four cycles. |
30 | MCUCR |= (1<<JTD); | |
31 | MCUCR |= (1<<JTD); | |
f441ad07 | 32 | |
33 | // PF7: BT connection control(high: connect, low: disconnect) | |
31a298f9 | 34 | rn42_autoconnect(); |
35 | ||
f441ad07 | 36 | // PF6: linked(input without pull-up) |
37 | DDRF &= ~(1<<6); | |
807ed33a | 38 | PORTF |= (1<<6); |
f441ad07 | 39 | |
fa545c87 | 40 | // PF1: RTS(low: allowed to send, high: not allowed) |
41 | DDRF &= ~(1<<1); | |
42 | PORTF &= ~(1<<1); | |
43 | ||
44 | // PD5: CTS(low: allow to send, high:not allow) | |
31a298f9 | 45 | DDRD |= (1<<5); |
46 | PORTD &= ~(1<<5); | |
47 | ||
48 | serial_init(); | |
49 | } | |
50 | ||
4f121de7 | 51 | int16_t rn42_getc(void) |
52 | { | |
53 | return serial_recv2(); | |
54 | } | |
55 | ||
3b3af3ba | 56 | const char *rn42_gets(uint16_t timeout) |
4f121de7 | 57 | { |
3b3af3ba | 58 | static char s[24]; |
4f121de7 | 59 | uint16_t t = timer_read(); |
60 | uint8_t i = 0; | |
61 | int16_t c; | |
3b3af3ba | 62 | while (i < 23 && timer_elapsed(t) < timeout) { |
63 | if ((c = rn42_getc()) != -1) { | |
4f121de7 | 64 | if ((char)c == '\r') continue; |
65 | if ((char)c == '\n') break; | |
66 | s[i++] = c; | |
67 | } | |
68 | } | |
69 | s[i] = '\0'; | |
70 | return s; | |
71 | } | |
72 | ||
31a298f9 | 73 | void rn42_putc(uint8_t c) |
74 | { | |
75 | serial_send(c); | |
76 | } | |
77 | ||
4f121de7 | 78 | void rn42_puts(char *s) |
79 | { | |
80 | while (*s) | |
81 | serial_send(*s++); | |
82 | } | |
83 | ||
fa545c87 | 84 | bool rn42_autoconnecting(void) |
85 | { | |
86 | // GPIO6 for control connection(high: auto connect, low: disconnect) | |
87 | // Note that this needs config: SM,4(Auto-Connect DTR Mode) | |
88 | return (PORTF & (1<<7) ? true : false); | |
89 | } | |
90 | ||
31a298f9 | 91 | void rn42_autoconnect(void) |
92 | { | |
fa545c87 | 93 | // hi to auto connect |
94 | DDRF |= (1<<7); | |
95 | PORTF |= (1<<7); | |
31a298f9 | 96 | } |
97 | ||
98 | void rn42_disconnect(void) | |
99 | { | |
fa545c87 | 100 | // low to disconnect |
31a298f9 | 101 | DDRF |= (1<<7); |
102 | PORTF &= ~(1<<7); | |
103 | } | |
104 | ||
fa545c87 | 105 | bool rn42_rts(void) |
106 | { | |
107 | // low when RN-42 is powered and ready to receive | |
108 | return PINF&(1<<1); | |
109 | } | |
110 | ||
111 | void rn42_cts_hi(void) | |
31a298f9 | 112 | { |
fa545c87 | 113 | // not allow to send |
114 | PORTD |= (1<<5); | |
115 | } | |
116 | ||
117 | void rn42_cts_lo(void) | |
118 | { | |
119 | // allow to send | |
120 | PORTD &= ~(1<<5); | |
31a298f9 | 121 | } |
122 | ||
4b2b32a1 | 123 | bool rn42_linked(void) |
124 | { | |
807ed33a | 125 | // RN-42 GPIO2 |
126 | // Hi-Z: Not powered | |
127 | // High: Linked | |
128 | // Low: Connecting | |
3b3af3ba | 129 | return PINF&(1<<6); |
4b2b32a1 | 130 | } |
131 | ||
31a298f9 | 132 | |
bfd2d969 | 133 | static uint8_t leds = 0; |
134 | static uint8_t keyboard_leds(void) { return leds; } | |
135 | void rn42_set_leds(uint8_t l) { leds = l; } | |
4069776c | 136 | |
2e464737 | 137 | |
138 | void rn42_send_str(const char *str) | |
139 | { | |
140 | uint8_t c; | |
141 | while ((c = pgm_read_byte(str++))) | |
142 | rn42_putc(c); | |
143 | } | |
144 | ||
145 | const char *rn42_send_command(const char *cmd) | |
146 | { | |
147 | static const char *s; | |
148 | rn42_send_str(cmd); | |
149 | wait_ms(500); | |
150 | s = rn42_gets(100); | |
151 | xprintf("%s\r\n", s); | |
152 | rn42_print_response(); | |
153 | return s; | |
154 | } | |
155 | ||
156 | void rn42_print_response(void) | |
157 | { | |
158 | int16_t c; | |
159 | while ((c = rn42_getc()) != -1) { | |
160 | xprintf("%c", c); | |
161 | } | |
162 | } | |
163 | ||
164 | ||
4069776c | 165 | static void send_keyboard(report_keyboard_t *report) |
166 | { | |
31a298f9 | 167 | // wake from deep sleep |
862f519e | 168 | /* |
31a298f9 | 169 | PORTD |= (1<<5); // high |
170 | wait_ms(5); | |
171 | PORTD &= ~(1<<5); // low | |
862f519e | 172 | */ |
31a298f9 | 173 | |
174 | serial_send(0xFD); // Raw report mode | |
175 | serial_send(9); // length | |
176 | serial_send(1); // descriptor type | |
177 | serial_send(report->mods); | |
178 | serial_send(0x00); | |
179 | serial_send(report->keys[0]); | |
180 | serial_send(report->keys[1]); | |
181 | serial_send(report->keys[2]); | |
182 | serial_send(report->keys[3]); | |
183 | serial_send(report->keys[4]); | |
184 | serial_send(report->keys[5]); | |
4069776c | 185 | } |
186 | ||
187 | static void send_mouse(report_mouse_t *report) | |
188 | { | |
31a298f9 | 189 | // wake from deep sleep |
862f519e | 190 | /* |
31a298f9 | 191 | PORTD |= (1<<5); // high |
192 | wait_ms(5); | |
193 | PORTD &= ~(1<<5); // low | |
862f519e | 194 | */ |
31a298f9 | 195 | |
196 | serial_send(0xFD); // Raw report mode | |
197 | serial_send(5); // length | |
198 | serial_send(2); // descriptor type | |
199 | serial_send(report->buttons); | |
200 | serial_send(report->x); | |
201 | serial_send(report->y); | |
202 | serial_send(report->v); | |
4069776c | 203 | } |
204 | ||
205 | static void send_system(uint16_t data) | |
206 | { | |
31a298f9 | 207 | // Table 5-6 of RN-BT-DATA-UB |
208 | // 81,82,83 scan codes can be used? | |
209 | } | |
210 | ||
211 | ||
212 | static uint16_t usage2bits(uint16_t usage) | |
213 | { | |
214 | switch (usage) { | |
1414ea35 | 215 | case APPCONTROL_HOME: return 0x01; |
216 | case APPLAUNCH_EMAIL: return 0x02; | |
217 | case APPCONTROL_SEARCH: return 0x04; | |
31a298f9 | 218 | //case AL_KBD_LAYOUT: return 0x08; // Apple virtual keybaord toggle |
e19d574b RR |
219 | case AUDIO_VOL_UP: return 0x10; |
220 | case AUDIO_VOL_DOWN: return 0x20; | |
221 | case AUDIO_MUTE: return 0x40; | |
222 | case TRANSPORT_PLAY_PAUSE: return 0x80; | |
223 | case TRANSPORT_NEXT_TRACK: return 0x100; | |
224 | case TRANSPORT_PREV_TRACK: return 0x200; | |
225 | case TRANSPORT_STOP: return 0x400; | |
226 | case TRANSPORT_STOP_EJECT: return 0x800; | |
227 | case TRANSPORT_FAST_FORWARD: return 0x1000; | |
228 | case TRANSPORT_REWIND: return 0x2000; | |
31a298f9 | 229 | //case return 0x4000; // Stop/eject |
230 | //case return 0x8000; // Internet browser | |
231 | }; | |
232 | return 0; | |
4069776c | 233 | } |
234 | ||
235 | static void send_consumer(uint16_t data) | |
236 | { | |
31a298f9 | 237 | uint16_t bits = usage2bits(data); |
238 | serial_send(0xFD); // Raw report mode | |
239 | serial_send(3); // length | |
240 | serial_send(3); // descriptor type | |
31a298f9 | 241 | serial_send(bits&0xFF); |
cd861043 | 242 | serial_send((bits>>8)&0xFF); |
4069776c | 243 | } |
31a298f9 | 244 | |
245 | ||
246 | /* Null driver for config_mode */ | |
247 | static uint8_t config_keyboard_leds(void); | |
248 | static void config_send_keyboard(report_keyboard_t *report); | |
249 | static void config_send_mouse(report_mouse_t *report); | |
250 | static void config_send_system(uint16_t data); | |
251 | static void config_send_consumer(uint16_t data); | |
252 | ||
253 | host_driver_t rn42_config_driver = { | |
254 | config_keyboard_leds, | |
255 | config_send_keyboard, | |
256 | config_send_mouse, | |
257 | config_send_system, | |
258 | config_send_consumer | |
259 | }; | |
260 | ||
bfd2d969 | 261 | static uint8_t config_keyboard_leds(void) { return leds; } |
31a298f9 | 262 | static void config_send_keyboard(report_keyboard_t *report) {} |
263 | static void config_send_mouse(report_mouse_t *report) {} | |
264 | static void config_send_system(uint16_t data) {} | |
265 | static void config_send_consumer(uint16_t data) {} |