diff options
Diffstat (limited to 'lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp')
-rw-r--r-- | lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp b/lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp new file mode 100644 index 000000000..bfa9202c3 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/BTHID.cpp | |||
@@ -0,0 +1,399 @@ | |||
1 | /* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved. | ||
2 | |||
3 | This software may be distributed and modified under the terms of the GNU | ||
4 | General Public License version 2 (GPL2) as published by the Free Software | ||
5 | Foundation and appearing in the file GPL2.TXT included in the packaging of | ||
6 | this file. Please note that GPL2 Section 2[b] requires that all works based | ||
7 | on this software must also be made publicly available under the terms of | ||
8 | the GPL2 ("Copyleft"). | ||
9 | |||
10 | Contact information | ||
11 | ------------------- | ||
12 | |||
13 | Kristian Lauszus, TKJ Electronics | ||
14 | Web : http://www.tkjelectronics.com | ||
15 | e-mail : kristianl@tkjelectronics.com | ||
16 | */ | ||
17 | |||
18 | #include "BTHID.h" | ||
19 | // To enable serial debugging see "settings.h" | ||
20 | //#define EXTRADEBUG // Uncomment to get even more debugging data | ||
21 | //#define PRINTREPORT // Uncomment to print the report send by the HID device | ||
22 | |||
23 | BTHID::BTHID(BTD *p, bool pair, const char *pin) : | ||
24 | BluetoothService(p), // Pointer to USB class instance - mandatory | ||
25 | protocolMode(HID_BOOT_PROTOCOL) { | ||
26 | for(uint8_t i = 0; i < NUM_PARSERS; i++) | ||
27 | pRptParser[i] = NULL; | ||
28 | |||
29 | pBtd->pairWithHIDDevice = pair; | ||
30 | pBtd->btdPin = pin; | ||
31 | |||
32 | /* Set device cid for the control and intterrupt channelse - LSB */ | ||
33 | control_dcid[0] = 0x70; // 0x0070 | ||
34 | control_dcid[1] = 0x00; | ||
35 | interrupt_dcid[0] = 0x71; // 0x0071 | ||
36 | interrupt_dcid[1] = 0x00; | ||
37 | |||
38 | Reset(); | ||
39 | } | ||
40 | |||
41 | void BTHID::Reset() { | ||
42 | connected = false; | ||
43 | activeConnection = false; | ||
44 | l2cap_event_flag = 0; // Reset flags | ||
45 | l2cap_state = L2CAP_WAIT; | ||
46 | ResetBTHID(); | ||
47 | } | ||
48 | |||
49 | void BTHID::disconnect() { // Use this void to disconnect the device | ||
50 | // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection | ||
51 | pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid); | ||
52 | Reset(); | ||
53 | l2cap_state = L2CAP_INTERRUPT_DISCONNECT; | ||
54 | } | ||
55 | |||
56 | void BTHID::ACLData(uint8_t* l2capinbuf) { | ||
57 | if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) { | ||
58 | if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { | ||
59 | if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { | ||
60 | pBtd->incomingHIDDevice = false; | ||
61 | pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service | ||
62 | activeConnection = true; | ||
63 | hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection | ||
64 | l2cap_state = L2CAP_WAIT; | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | |||
69 | if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok | ||
70 | if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U | ||
71 | if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) { | ||
72 | #ifdef DEBUG_USB_HOST | ||
73 | Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); | ||
74 | D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); | ||
75 | Notify(PSTR(" "), 0x80); | ||
76 | D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); | ||
77 | Notify(PSTR(" "), 0x80); | ||
78 | D_PrintHex<uint8_t > (l2capinbuf[17], 0x80); | ||
79 | Notify(PSTR(" "), 0x80); | ||
80 | D_PrintHex<uint8_t > (l2capinbuf[16], 0x80); | ||
81 | Notify(PSTR(" "), 0x80); | ||
82 | D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); | ||
83 | Notify(PSTR(" "), 0x80); | ||
84 | D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); | ||
85 | #endif | ||
86 | } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { | ||
87 | if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success | ||
88 | if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { | ||
89 | //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80); | ||
90 | identifier = l2capinbuf[9]; | ||
91 | control_scid[0] = l2capinbuf[12]; | ||
92 | control_scid[1] = l2capinbuf[13]; | ||
93 | l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED); | ||
94 | } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { | ||
95 | //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80); | ||
96 | identifier = l2capinbuf[9]; | ||
97 | interrupt_scid[0] = l2capinbuf[12]; | ||
98 | interrupt_scid[1] = l2capinbuf[13]; | ||
99 | l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED); | ||
100 | } | ||
101 | } | ||
102 | } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { | ||
103 | #ifdef EXTRADEBUG | ||
104 | Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80); | ||
105 | D_PrintHex<uint8_t > (l2capinbuf[13], 0x80); | ||
106 | Notify(PSTR(" "), 0x80); | ||
107 | D_PrintHex<uint8_t > (l2capinbuf[12], 0x80); | ||
108 | Notify(PSTR(" SCID: "), 0x80); | ||
109 | D_PrintHex<uint8_t > (l2capinbuf[15], 0x80); | ||
110 | Notify(PSTR(" "), 0x80); | ||
111 | D_PrintHex<uint8_t > (l2capinbuf[14], 0x80); | ||
112 | Notify(PSTR(" Identifier: "), 0x80); | ||
113 | D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); | ||
114 | #endif | ||
115 | if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) { | ||
116 | identifier = l2capinbuf[9]; | ||
117 | control_scid[0] = l2capinbuf[14]; | ||
118 | control_scid[1] = l2capinbuf[15]; | ||
119 | l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST); | ||
120 | } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) { | ||
121 | identifier = l2capinbuf[9]; | ||
122 | interrupt_scid[0] = l2capinbuf[14]; | ||
123 | interrupt_scid[1] = l2capinbuf[15]; | ||
124 | l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST); | ||
125 | } | ||
126 | } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { | ||
127 | if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success | ||
128 | if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { | ||
129 | //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80); | ||
130 | identifier = l2capinbuf[9]; | ||
131 | l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS); | ||
132 | } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { | ||
133 | //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80); | ||
134 | identifier = l2capinbuf[9]; | ||
135 | l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS); | ||
136 | } | ||
137 | } | ||
138 | } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { | ||
139 | if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { | ||
140 | //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80); | ||
141 | pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); | ||
142 | } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { | ||
143 | //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80); | ||
144 | pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); | ||
145 | } | ||
146 | } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { | ||
147 | if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { | ||
148 | #ifdef DEBUG_USB_HOST | ||
149 | Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80); | ||
150 | #endif | ||
151 | identifier = l2capinbuf[9]; | ||
152 | pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid); | ||
153 | Reset(); | ||
154 | } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { | ||
155 | #ifdef DEBUG_USB_HOST | ||
156 | Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80); | ||
157 | #endif | ||
158 | identifier = l2capinbuf[9]; | ||
159 | pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid); | ||
160 | Reset(); | ||
161 | } | ||
162 | } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { | ||
163 | if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { | ||
164 | //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80); | ||
165 | identifier = l2capinbuf[9]; | ||
166 | l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE); | ||
167 | } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { | ||
168 | //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80); | ||
169 | identifier = l2capinbuf[9]; | ||
170 | l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE); | ||
171 | } | ||
172 | } | ||
173 | #ifdef EXTRADEBUG | ||
174 | else { | ||
175 | identifier = l2capinbuf[9]; | ||
176 | Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80); | ||
177 | D_PrintHex<uint8_t > (l2capinbuf[8], 0x80); | ||
178 | } | ||
179 | #endif | ||
180 | } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt | ||
181 | #ifdef PRINTREPORT | ||
182 | Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80); | ||
183 | for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { | ||
184 | D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); | ||
185 | Notify(PSTR(" "), 0x80); | ||
186 | } | ||
187 | #endif | ||
188 | if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT | ||
189 | uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); | ||
190 | ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]); | ||
191 | |||
192 | switch(l2capinbuf[9]) { | ||
193 | case 0x01: // Keyboard or Joystick events | ||
194 | if(pRptParser[KEYBOARD_PARSER_ID]) | ||
195 | pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance | ||
196 | break; | ||
197 | |||
198 | case 0x02: // Mouse events | ||
199 | if(pRptParser[MOUSE_PARSER_ID]) | ||
200 | pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance | ||
201 | break; | ||
202 | #ifdef EXTRADEBUG | ||
203 | default: | ||
204 | Notify(PSTR("\r\nUnknown Report type: "), 0x80); | ||
205 | D_PrintHex<uint8_t > (l2capinbuf[9], 0x80); | ||
206 | break; | ||
207 | #endif | ||
208 | } | ||
209 | } | ||
210 | } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control | ||
211 | #ifdef PRINTREPORT | ||
212 | Notify(PSTR("\r\nL2CAP Control: "), 0x80); | ||
213 | for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { | ||
214 | D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); | ||
215 | Notify(PSTR(" "), 0x80); | ||
216 | } | ||
217 | #endif | ||
218 | } | ||
219 | #ifdef EXTRADEBUG | ||
220 | else { | ||
221 | Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80); | ||
222 | D_PrintHex<uint8_t > (l2capinbuf[7], 0x80); | ||
223 | Notify(PSTR(" "), 0x80); | ||
224 | D_PrintHex<uint8_t > (l2capinbuf[6], 0x80); | ||
225 | |||
226 | Notify(PSTR("\r\nData: "), 0x80); | ||
227 | Notify(PSTR("\r\n"), 0x80); | ||
228 | for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) { | ||
229 | D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80); | ||
230 | Notify(PSTR(" "), 0x80); | ||
231 | } | ||
232 | } | ||
233 | #endif | ||
234 | L2CAP_task(); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | void BTHID::L2CAP_task() { | ||
239 | switch(l2cap_state) { | ||
240 | /* These states are used if the HID device is the host */ | ||
241 | case L2CAP_CONTROL_SUCCESS: | ||
242 | if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { | ||
243 | #ifdef DEBUG_USB_HOST | ||
244 | Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80); | ||
245 | #endif | ||
246 | setProtocol(); // Set protocol before establishing HID interrupt channel | ||
247 | l2cap_state = L2CAP_INTERRUPT_SETUP; | ||
248 | } | ||
249 | break; | ||
250 | |||
251 | case L2CAP_INTERRUPT_SETUP: | ||
252 | if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) { | ||
253 | #ifdef DEBUG_USB_HOST | ||
254 | Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80); | ||
255 | #endif | ||
256 | pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING); | ||
257 | delay(1); | ||
258 | pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL); | ||
259 | identifier++; | ||
260 | delay(1); | ||
261 | pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); | ||
262 | |||
263 | l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; | ||
264 | } | ||
265 | break; | ||
266 | |||
267 | /* These states are used if the Arduino is the host */ | ||
268 | case L2CAP_CONTROL_CONNECT_REQUEST: | ||
269 | if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) { | ||
270 | #ifdef DEBUG_USB_HOST | ||
271 | Notify(PSTR("\r\nSend HID Control Config Request"), 0x80); | ||
272 | #endif | ||
273 | identifier++; | ||
274 | pBtd->l2cap_config_request(hci_handle, identifier, control_scid); | ||
275 | l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST; | ||
276 | } | ||
277 | break; | ||
278 | |||
279 | case L2CAP_CONTROL_CONFIG_REQUEST: | ||
280 | if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) { | ||
281 | setProtocol(); // Set protocol before establishing HID interrupt channel | ||
282 | delay(1); // Short delay between commands - just to be sure | ||
283 | #ifdef DEBUG_USB_HOST | ||
284 | Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80); | ||
285 | #endif | ||
286 | identifier++; | ||
287 | pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM); | ||
288 | l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST; | ||
289 | } | ||
290 | break; | ||
291 | |||
292 | case L2CAP_INTERRUPT_CONNECT_REQUEST: | ||
293 | if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) { | ||
294 | #ifdef DEBUG_USB_HOST | ||
295 | Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80); | ||
296 | #endif | ||
297 | identifier++; | ||
298 | pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid); | ||
299 | l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST; | ||
300 | } | ||
301 | break; | ||
302 | |||
303 | case L2CAP_INTERRUPT_CONFIG_REQUEST: | ||
304 | if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established | ||
305 | #ifdef DEBUG_USB_HOST | ||
306 | Notify(PSTR("\r\nHID Channels Established"), 0x80); | ||
307 | #endif | ||
308 | pBtd->connectToHIDDevice = false; | ||
309 | pBtd->pairWithHIDDevice = false; | ||
310 | connected = true; | ||
311 | onInit(); | ||
312 | l2cap_state = L2CAP_DONE; | ||
313 | } | ||
314 | break; | ||
315 | |||
316 | case L2CAP_DONE: | ||
317 | break; | ||
318 | |||
319 | case L2CAP_INTERRUPT_DISCONNECT: | ||
320 | if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) { | ||
321 | #ifdef DEBUG_USB_HOST | ||
322 | Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80); | ||
323 | #endif | ||
324 | identifier++; | ||
325 | pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid); | ||
326 | l2cap_state = L2CAP_CONTROL_DISCONNECT; | ||
327 | } | ||
328 | break; | ||
329 | |||
330 | case L2CAP_CONTROL_DISCONNECT: | ||
331 | if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) { | ||
332 | #ifdef DEBUG_USB_HOST | ||
333 | Notify(PSTR("\r\nDisconnected Control Channel"), 0x80); | ||
334 | #endif | ||
335 | pBtd->hci_disconnect(hci_handle); | ||
336 | hci_handle = -1; // Reset handle | ||
337 | l2cap_event_flag = 0; // Reset flags | ||
338 | l2cap_state = L2CAP_WAIT; | ||
339 | } | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | void BTHID::Run() { | ||
345 | switch(l2cap_state) { | ||
346 | case L2CAP_WAIT: | ||
347 | if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) { | ||
348 | pBtd->l2capConnectionClaimed = true; | ||
349 | activeConnection = true; | ||
350 | #ifdef DEBUG_USB_HOST | ||
351 | Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80); | ||
352 | #endif | ||
353 | hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection | ||
354 | l2cap_event_flag = 0; // Reset flags | ||
355 | identifier = 0; | ||
356 | pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM); | ||
357 | l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST; | ||
358 | } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) { | ||
359 | #ifdef DEBUG_USB_HOST | ||
360 | Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80); | ||
361 | #endif | ||
362 | pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING); | ||
363 | delay(1); | ||
364 | pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL); | ||
365 | identifier++; | ||
366 | delay(1); | ||
367 | pBtd->l2cap_config_request(hci_handle, identifier, control_scid); | ||
368 | l2cap_state = L2CAP_CONTROL_SUCCESS; | ||
369 | } | ||
370 | break; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /************************************************************/ | ||
375 | /* HID Commands */ | ||
376 | |||
377 | /************************************************************/ | ||
378 | void BTHID::setProtocol() { | ||
379 | #ifdef DEBUG_USB_HOST | ||
380 | Notify(PSTR("\r\nSet protocol mode: "), 0x80); | ||
381 | D_PrintHex<uint8_t > (protocolMode, 0x80); | ||
382 | #endif | ||
383 | if (protocolMode != HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) { | ||
384 | #ifdef DEBUG_USB_HOST | ||
385 | Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80); | ||
386 | #endif | ||
387 | protocolMode = HID_BOOT_PROTOCOL; // Use Boot Protocol by default | ||
388 | } | ||
389 | uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33 | ||
390 | pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]); | ||
391 | } | ||
392 | |||
393 | void BTHID::setLeds(uint8_t data) { | ||
394 | uint8_t buf[3]; | ||
395 | buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) | ||
396 | buf[1] = 0x01; // Report ID | ||
397 | buf[2] = data; | ||
398 | pBtd->L2CAP_Command(hci_handle, buf, 3, interrupt_scid[0], interrupt_scid[1]); | ||
399 | } | ||