]>
Commit | Line | Data |
---|---|---|
1 | #include <avr/io.h> | |
2 | #include "host.h" | |
3 | #include "host_driver.h" | |
4 | #include "serial.h" | |
5 | #include "rn42.h" | |
6 | #include "print.h" | |
7 | #include "timer.h" | |
8 | #include "wait.h" | |
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 | ||
26 | ||
27 | void rn42_init(void) | |
28 | { | |
29 | // JTAG disable for PORT F. write JTD bit twice within four cycles. | |
30 | MCUCR |= (1<<JTD); | |
31 | MCUCR |= (1<<JTD); | |
32 | ||
33 | // PF7: BT connection control(high: connect, low: disconnect) | |
34 | rn42_autoconnect(); | |
35 | ||
36 | // PF6: linked(input without pull-up) | |
37 | DDRF &= ~(1<<6); | |
38 | PORTF |= (1<<6); | |
39 | ||
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) | |
45 | DDRD |= (1<<5); | |
46 | PORTD &= ~(1<<5); | |
47 | ||
48 | serial_init(); | |
49 | } | |
50 | ||
51 | int16_t rn42_getc(void) | |
52 | { | |
53 | return serial_recv2(); | |
54 | } | |
55 | ||
56 | const char *rn42_gets(uint16_t timeout) | |
57 | { | |
58 | static char s[24]; | |
59 | uint16_t t = timer_read(); | |
60 | uint8_t i = 0; | |
61 | int16_t c; | |
62 | while (i < 23 && timer_elapsed(t) < timeout) { | |
63 | if ((c = rn42_getc()) != -1) { | |
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 | ||
73 | void rn42_putc(uint8_t c) | |
74 | { | |
75 | serial_send(c); | |
76 | } | |
77 | ||
78 | void rn42_puts(char *s) | |
79 | { | |
80 | while (*s) | |
81 | serial_send(*s++); | |
82 | } | |
83 | ||
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 | ||
91 | void rn42_autoconnect(void) | |
92 | { | |
93 | // hi to auto connect | |
94 | DDRF |= (1<<7); | |
95 | PORTF |= (1<<7); | |
96 | } | |
97 | ||
98 | void rn42_disconnect(void) | |
99 | { | |
100 | // low to disconnect | |
101 | DDRF |= (1<<7); | |
102 | PORTF &= ~(1<<7); | |
103 | } | |
104 | ||
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) | |
112 | { | |
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); | |
121 | } | |
122 | ||
123 | bool rn42_linked(void) | |
124 | { | |
125 | // RN-42 GPIO2 | |
126 | // Hi-Z: Not powered | |
127 | // High: Linked | |
128 | // Low: Connecting | |
129 | return PINF&(1<<6); | |
130 | } | |
131 | ||
132 | ||
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; } | |
136 | ||
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 | ||
165 | static void send_keyboard(report_keyboard_t *report) | |
166 | { | |
167 | // wake from deep sleep | |
168 | /* | |
169 | PORTD |= (1<<5); // high | |
170 | wait_ms(5); | |
171 | PORTD &= ~(1<<5); // low | |
172 | */ | |
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]); | |
185 | } | |
186 | ||
187 | static void send_mouse(report_mouse_t *report) | |
188 | { | |
189 | // wake from deep sleep | |
190 | /* | |
191 | PORTD |= (1<<5); // high | |
192 | wait_ms(5); | |
193 | PORTD &= ~(1<<5); // low | |
194 | */ | |
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); | |
203 | } | |
204 | ||
205 | static void send_system(uint16_t data) | |
206 | { | |
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) { | |
215 | case APPCONTROL_HOME: return 0x01; | |
216 | case APPLAUNCH_EMAIL: return 0x02; | |
217 | case APPCONTROL_SEARCH: return 0x04; | |
218 | //case AL_KBD_LAYOUT: return 0x08; // Apple virtual keybaord toggle | |
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; | |
229 | //case return 0x4000; // Stop/eject | |
230 | //case return 0x8000; // Internet browser | |
231 | }; | |
232 | return 0; | |
233 | } | |
234 | ||
235 | static void send_consumer(uint16_t data) | |
236 | { | |
237 | uint16_t bits = usage2bits(data); | |
238 | serial_send(0xFD); // Raw report mode | |
239 | serial_send(3); // length | |
240 | serial_send(3); // descriptor type | |
241 | serial_send(bits&0xFF); | |
242 | serial_send((bits>>8)&0xFF); | |
243 | } | |
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 | ||
261 | static uint8_t config_keyboard_leds(void) { return leds; } | |
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) {} |