USB Host Shield 2.0
Loading...
Searching...
No Matches
BTHID.cpp
Go to the documentation of this file.
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
23BTHID::BTHID(BTD *p, bool pair, const char *pin) :
24BluetoothService(p), // Pointer to USB class instance - mandatory
25protocolMode(USB_HID_BOOT_PROTOCOL) {
26 for(uint8_t i = 0; i < NUM_PARSERS; i++)
27 pRptParser[i] = NULL;
28
30 pBtd->btdPin = pin;
31
32 /* Set device cid for the control and intterrupt channelse - LSB */
33 sdp_dcid[0] = 0x50; // 0x0050
34 sdp_dcid[1] = 0x00;
35 control_dcid[0] = 0x70; // 0x0070
36 control_dcid[1] = 0x00;
37 interrupt_dcid[0] = 0x71; // 0x0071
38 interrupt_dcid[1] = 0x00;
39
40 Reset();
41}
42
44 connected = false;
45 activeConnection = false;
46 SDPConnected = false;
47 l2cap_event_flag = 0; // Reset flags
49 l2cap_state = L2CAP_WAIT;
50 ResetBTHID();
51}
52
53void BTHID::disconnect() { // Use this void to disconnect the device
54 if(SDPConnected)
56 // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
58 Reset();
60 l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
61}
62
63void BTHID::ACLData(uint8_t* l2capinbuf) {
64 if(!connected) {
65 if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
66 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {
68 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
69 l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state
70 }
71 }
72 }
73
74 if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) {
75 if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
76 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
77 pBtd->incomingHIDDevice = false;
78 pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
79 activeConnection = true;
80 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
81 l2cap_state = L2CAP_WAIT;
82 }
83 }
84 }
85
86 if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
87 if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
88 if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
89#ifdef DEBUG_USB_HOST
90 Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
91 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
92 Notify(PSTR(" "), 0x80);
93 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
94 Notify(PSTR(" "), 0x80);
95 D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
96 Notify(PSTR(" "), 0x80);
97 D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
98 Notify(PSTR(" "), 0x80);
99 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
100 Notify(PSTR(" "), 0x80);
101 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
102#endif
103 } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
104 if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
105 if(l2capinbuf[14] == sdp_dcid[0] && l2capinbuf[15] == sdp_dcid[1]) {
106#ifdef EXTRADEBUG
107 Notify(PSTR("\r\nSDP Connection Complete"), 0x80);
108#endif
109 identifier = l2capinbuf[9];
110 sdp_scid[0] = l2capinbuf[12];
111 sdp_scid[1] = l2capinbuf[13];
112#ifdef DEBUG_USB_HOST
113 Notify(PSTR("\r\nSend SDP Config Request"), 0x80);
114#endif
115 identifier++;
117 } else if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
118#ifdef EXTRADEBUG
119 Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
120#endif
121 identifier = l2capinbuf[9];
122 control_scid[0] = l2capinbuf[12];
123 control_scid[1] = l2capinbuf[13];
125 } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
126#ifdef EXTRADEBUG
127 Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
128#endif
129 identifier = l2capinbuf[9];
130 interrupt_scid[0] = l2capinbuf[12];
131 interrupt_scid[1] = l2capinbuf[13];
133 }
134 }
135 } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
136#ifdef EXTRADEBUG
137 Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
138 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
139 Notify(PSTR(" "), 0x80);
140 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
141 Notify(PSTR(" SCID: "), 0x80);
142 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
143 Notify(PSTR(" "), 0x80);
144 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
145 Notify(PSTR(" Identifier: "), 0x80);
146 D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
147#endif
148 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) {
149 identifier = l2capinbuf[9];
150 sdp_scid[0] = l2capinbuf[14];
151 sdp_scid[1] = l2capinbuf[15];
153 } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
154 identifier = l2capinbuf[9];
155 control_scid[0] = l2capinbuf[14];
156 control_scid[1] = l2capinbuf[15];
158 } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
159 identifier = l2capinbuf[9];
160 interrupt_scid[0] = l2capinbuf[14];
161 interrupt_scid[1] = l2capinbuf[15];
163 }
164 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
165 if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
166 if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
167#ifdef EXTRADEBUG
168 Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
169#endif
170 identifier = l2capinbuf[9];
172 } else if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
173#ifdef EXTRADEBUG
174 Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
175#endif
176 identifier = l2capinbuf[9];
178 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
179#ifdef EXTRADEBUG
180 Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
181#endif
182 identifier = l2capinbuf[9];
184 }
185 }
186 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
187 if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
188#ifdef EXTRADEBUG
189 Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
190#endif
192 } else if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
193#ifdef EXTRADEBUG
194 Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
195#endif
197 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
198#ifdef EXTRADEBUG
199 Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
200#endif
202 }
203 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
204 if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
205#ifdef DEBUG_USB_HOST
206 Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80);
207#endif
208 identifier = l2capinbuf[9];
210 } else if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
211#ifdef DEBUG_USB_HOST
212 Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
213#endif
214 identifier = l2capinbuf[9];
216 Reset();
217 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
218#ifdef DEBUG_USB_HOST
219 Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
220#endif
221 identifier = l2capinbuf[9];
223 Reset();
224 }
225 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
226 if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
227#ifdef EXTRADEBUG
228 Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
229#endif
230 identifier = l2capinbuf[9];
232 } else if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
233#ifdef EXTRADEBUG
234 Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
235#endif
236 identifier = l2capinbuf[9];
238 } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
239#ifdef EXTRADEBUG
240 Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
241#endif
242 identifier = l2capinbuf[9];
244 }
245 } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {
246#ifdef DEBUG_USB_HOST
247 Notify(PSTR("\r\nInformation request"), 0x80);
248#endif
249 identifier = l2capinbuf[9];
250 pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]);
251 }
252#ifdef EXTRADEBUG
253 else {
254 identifier = l2capinbuf[9];
255 Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
256 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
257 }
258#endif
259 } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP
260 if(l2capinbuf[8] == SDP_SERVICE_SEARCH_REQUEST) {
261#ifdef EXTRADEBUG
262 Notify(PSTR("\r\nSDP_SERVICE_SEARCH_REQUEST"), 0x80);
263#endif
264 // Send response
265 l2capoutbuf[0] = SDP_SERVICE_SEARCH_RESPONSE;
266 l2capoutbuf[1] = l2capinbuf[9];//transactionIDHigh;
267 l2capoutbuf[2] = l2capinbuf[10];//transactionIDLow;
268
269 l2capoutbuf[3] = 0x00; // MSB Parameter Length
270 l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
271
272 l2capoutbuf[5] = 0x00; // MSB TotalServiceRecordCount
273 l2capoutbuf[6] = 0x00; // LSB TotalServiceRecordCount = 0
274
275 l2capoutbuf[7] = 0x00; // MSB CurrentServiceRecordCount
276 l2capoutbuf[8] = 0x00; // LSB CurrentServiceRecordCount = 0
277
278 l2capoutbuf[9] = 0x00; // No continuation state
279
280 SDP_Command(l2capoutbuf, 10);
281 } else if(l2capinbuf[8] == SDP_SERVICE_ATTRIBUTE_REQUEST) {
282#ifdef EXTRADEBUG
283 Notify(PSTR("\r\nSDP_SERVICE_ATTRIBUTE_REQUEST"), 0x80);
284#endif
285 // Send response
286 l2capoutbuf[0] = SDP_SERVICE_ATTRIBUTE_RESPONSE;
287 l2capoutbuf[1] = l2capinbuf[9];//transactionIDHigh;
288 l2capoutbuf[2] = l2capinbuf[10];//transactionIDLow;
289
290 l2capoutbuf[3] = 0x00; // MSB Parameter Length
291 l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
292
293 l2capoutbuf[5] = 0x00; // MSB AttributeListByteCount
294 l2capoutbuf[6] = 0x02; // LSB AttributeListByteCount = 2
295
296 // TODO: What to send?
297 l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte
298 l2capoutbuf[8] = 0x00; // Length = 0
299
300 l2capoutbuf[9] = 0x00; // No continuation state
301
302 SDP_Command(l2capoutbuf, 10);
303 } else if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST) {
304#ifdef EXTRADEBUG
305 Notify(PSTR("\r\nSDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST"), 0x80);
306 Notify(PSTR("\r\nUUID: "), 0x80);
308 if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID
309 uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]);
310 else // Short UUID
311 uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]);
313
314 Notify(PSTR("\r\nLength: "), 0x80);
315 uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
317 Notify(PSTR("\r\nData: "), 0x80);
318 for(uint8_t i = 0; i < length; i++) {
319 D_PrintHex<uint8_t > (l2capinbuf[13 + i], 0x80);
320 Notify(PSTR(" "), 0x80);
321 }
322#endif
323 serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported
324 }
325#ifdef EXTRADEBUG
326 else {
327 Notify(PSTR("\r\nUnknown PDU: "), 0x80);
328 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
329 }
330#endif
331 } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
332#ifdef PRINTREPORT
333 Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80);
334 for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
335 D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
336 Notify(PSTR(" "), 0x80);
337 }
338#endif
339 if(l2capinbuf[8] == 0xA1) { // HID BT DATA (0xA0) | Report Type (Input 0x01)
340 lastBtDataInputIntMillis = (uint32_t)millis(); // Store the timestamp of the report
341
342 uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
343 ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]); // First byte will be the report ID
344
345 switch(l2capinbuf[9]) { // Report ID
346 case 0x01: // Keyboard or Joystick events
347 if(pRptParser[KEYBOARD_PARSER_ID])
348 pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
349 break;
350
351 case 0x02: // Mouse events
352 if(pRptParser[MOUSE_PARSER_ID])
353 pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
354 break;
355#ifdef EXTRADEBUG
356 default:
357 Notify(PSTR("\r\nUnknown Report type: "), 0x80);
358 D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
359 break;
360#endif
361 }
362 } else {
363#ifdef EXTRADEBUG
364 Notify(PSTR("\r\nUnhandled L2CAP interrupt report: "), 0x80);
365 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
366#endif
367 }
368 } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control
369#ifdef PRINTREPORT
370 Notify(PSTR("\r\nL2CAP Control: "), 0x80);
371 for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
372 D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
373 Notify(PSTR(" "), 0x80);
374 }
375#endif
376 if(l2capinbuf[8] == 0xA3) { // HID BT DATA (0xA0) | Report Type (Feature 0x03)
377 uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
378 ParseBTHIDControlData((uint8_t)(length - 1), &l2capinbuf[9]); // First byte will be the report ID
379 } else {
380#ifdef EXTRADEBUG
381 Notify(PSTR("\r\nUnhandled L2CAP control report: "), 0x80);
382 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
383#endif
384 }
385 }
386#ifdef EXTRADEBUG
387 else {
388 Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
389 D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
390 Notify(PSTR(" "), 0x80);
391 D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
392
393 Notify(PSTR("\r\nData: "), 0x80);
394 Notify(PSTR("\r\n"), 0x80);
395 for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
396 D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
397 Notify(PSTR(" "), 0x80);
398 }
399 }
400#endif
401 SDP_task();
402 L2CAP_task();
403 }
404}
405
406void BTHID::SDP_task() {
407 switch(l2cap_sdp_state) {
408 case L2CAP_SDP_WAIT:
411#ifdef DEBUG_USB_HOST
412 Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
413#endif
415 delay(1);
417 identifier++;
418 delay(1);
423 SDPConnected = false;
424#ifdef DEBUG_USB_HOST
425 Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80);
426#endif
428 }
429 break;
433#ifdef DEBUG_USB_HOST
434 Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
435#endif
436 SDPConnected = true;
438 }
439 break;
440
441 case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
443#ifdef DEBUG_USB_HOST
444 Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
445#endif
447 hci_handle = -1; // Reset handle
448 Reset();
449 }
450 break;
451 }
452}
453
454void BTHID::L2CAP_task() {
455 switch(l2cap_state) {
456 /* These states are used if the HID device is the host */
459#ifdef DEBUG_USB_HOST
460 Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
461#endif
462 setProtocol(); // Set protocol before establishing HID interrupt channel
463 l2cap_state = L2CAP_INTERRUPT_SETUP;
464 }
465 break;
466
469#ifdef DEBUG_USB_HOST
470 Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
471#endif
473 delay(1);
475 identifier++;
476 delay(1);
478
479 l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
480 }
481 break;
482
483 /* These states are used if the Arduino is the host */
486#ifdef DEBUG_USB_HOST
487 Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
488#endif
489 identifier++;
491 l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
492 }
493 break;
494
497 setProtocol(); // Set protocol before establishing HID interrupt channel
498 delay(1); // Short delay between commands - just to be sure
499#ifdef DEBUG_USB_HOST
500 Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
501#endif
502 identifier++;
505 }
506 break;
507
510#ifdef DEBUG_USB_HOST
511 Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
512#endif
513 identifier++;
515 l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
516 }
517 break;
518
520 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
521#ifdef DEBUG_USB_HOST
522 Notify(PSTR("\r\nHID Channels Established"), 0x80);
523#endif
524 pBtd->connectToHIDDevice = false;
525 pBtd->pairWithHIDDevice = false;
526 connected = true;
527 onInit();
528 l2cap_state = L2CAP_DONE;
529 }
530 break;
531
532 case L2CAP_DONE:
533 break;
534
537#ifdef DEBUG_USB_HOST
538 Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
539#endif
540 identifier++;
542 l2cap_state = L2CAP_CONTROL_DISCONNECT;
543 }
544 break;
545
548#ifdef DEBUG_USB_HOST
549 Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
550#endif
552 hci_handle = -1; // Reset handle
553 l2cap_event_flag = 0; // Reset flags
554 l2cap_state = L2CAP_WAIT;
555 }
556 break;
557 }
558}
559
561 switch(l2cap_state) {
562 case L2CAP_WAIT:
563 if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) {
565 activeConnection = true;
566#ifdef DEBUG_USB_HOST
567 Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
568#endif
569 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
570 l2cap_event_flag = 0; // Reset flags
571 identifier = 0;
573 l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
575#ifdef DEBUG_USB_HOST
576 Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
577#endif
579 delay(1);
581 identifier++;
582 delay(1);
584 l2cap_state = L2CAP_CONTROL_SUCCESS;
585 }
586 break;
587 }
588}
589
590void BTHID::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
592}
593
594void BTHID::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
596 l2capoutbuf[1] = transactionIDHigh;
597 l2capoutbuf[2] = transactionIDLow;
598 l2capoutbuf[3] = 0x00; // MSB Parameter Length
599 l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
600 l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
601 l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2
602
603 /* Attribute ID/Value Sequence: */
604 l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte
605 l2capoutbuf[8] = 0x00; // Length = 0
606 l2capoutbuf[9] = 0x00; // No continuation state
607
608 SDP_Command(l2capoutbuf, 10);
609}
610
611/************************************************************/
612/* HID Commands */
613
614/************************************************************/
615void BTHID::setProtocol() {
616#ifdef DEBUG_USB_HOST
617 Notify(PSTR("\r\nSet protocol mode: "), 0x80);
618 D_PrintHex<uint8_t > (protocolMode, 0x80);
619#endif
620 if (protocolMode != USB_HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {
621#ifdef DEBUG_USB_HOST
622 Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80);
623#endif
624 protocolMode = USB_HID_BOOT_PROTOCOL; // Use Boot Protocol by default
625 }
626 uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33
628}
629
631 uint8_t buf[3];
632 buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
633 buf[1] = 0x01; // Report ID
634 buf[2] = data;
636}
#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST
Definition BTD.h:153
#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS
Definition BTD.h:148
#define L2CAP_FLAG_CONNECTION_SDP_REQUEST
Definition BTD.h:159
#define HID_CTRL_PSM
Definition BTD.h:193
#define L2CAP_WAIT
Definition BTD.h:114
#define L2CAP_SDP_SUCCESS
Definition BTD.h:131
#define SUCCESSFUL
Definition BTD.h:188
#define SDP_SERVICE_ATTRIBUTE_RESPONSE
Definition BTD.h:200
#define L2CAP_CMD_INFORMATION_REQUEST
Definition BTD.h:183
#define SDP_PSM
Definition BTD.h:191
#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE
Definition BTD.h:150
#define SDP_SERVICE_ATTRIBUTE_REQUEST
Definition BTD.h:199
#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS
Definition BTD.h:154
#define L2CAP_FLAG_CONTROL_CONNECTED
Definition BTD.h:149
#define L2CAP_CMD_DISCONNECT_REQUEST
Definition BTD.h:181
#define L2CAP_CMD_CONFIG_REQUEST
Definition BTD.h:179
#define HID_INTR_PSM
Definition BTD.h:194
#define L2CAP_CMD_DISCONNECT_RESPONSE
Definition BTD.h:182
#define l2cap_check_flag(flag)
Definition BTD.h:171
#define l2cap_set_flag(flag)
Definition BTD.h:172
#define SDP_SERVICE_SEARCH_REQUEST
Definition BTD.h:197
#define L2CAP_CONTROL_CONNECT_REQUEST
Definition BTD.h:118
#define L2CAP_CMD_COMMAND_REJECT
Definition BTD.h:176
#define L2CAP_SDP_WAIT
Definition BTD.h:130
#define L2CAP_INTERRUPT_CONFIG_REQUEST
Definition BTD.h:126
#define L2CAP_FLAG_CONFIG_SDP_SUCCESS
Definition BTD.h:160
#define L2CAP_CMD_CONFIG_RESPONSE
Definition BTD.h:180
#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST
Definition BTD.h:201
#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST
Definition BTD.h:147
#define PENDING
Definition BTD.h:187
#define L2CAP_CONTROL_DISCONNECT
Definition BTD.h:121
#define L2CAP_CONTROL_CONFIG_REQUEST
Definition BTD.h:119
#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST
Definition BTD.h:161
#define L2CAP_FLAG_INTERRUPT_CONNECTED
Definition BTD.h:155
#define L2CAP_INTERRUPT_DISCONNECT
Definition BTD.h:127
#define l2cap_clear_flag(flag)
Definition BTD.h:173
#define L2CAP_CONTROL_SUCCESS
Definition BTD.h:120
#define L2CAP_CMD_CONNECTION_REQUEST
Definition BTD.h:177
#define L2CAP_INTERRUPT_SETUP
Definition BTD.h:124
#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE
Definition BTD.h:156
#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE
Definition BTD.h:202
#define L2CAP_DISCONNECT_RESPONSE
Definition BTD.h:137
#define L2CAP_FLAG_DISCONNECT_RESPONSE
Definition BTD.h:168
#define L2CAP_DONE
Definition BTD.h:115
#define SDP_SERVICE_SEARCH_RESPONSE
Definition BTD.h:198
#define L2CAP_CMD_CONNECTION_RESPONSE
Definition BTD.h:178
#define L2CAP_INTERRUPT_CONNECT_REQUEST
Definition BTD.h:125
#define MOUSE_PARSER_ID
Definition BTHID.h:25
#define KEYBOARD_PARSER_ID
Definition BTHID.h:24
#define NUM_PARSERS
Definition BTHID.h:26
Definition BTD.h:222
bool l2capConnectionClaimed
Definition BTD.h:471
void hci_disconnect(uint16_t handle)
Definition BTD.cpp:1404
const char * btdPin
Definition BTD.h:480
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition BTD.cpp:1559
bool pairWithHIDDevice
Definition BTD.h:524
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t *scid, uint16_t psm)
Definition BTD.cpp:1480
bool incomingHIDDevice
Definition BTD.h:522
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t *scid)
Definition BTD.cpp:1527
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid, uint8_t result)
Definition BTD.cpp:1493
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh)
Definition BTD.cpp:1572
uint16_t hci_handle
Definition BTD.h:485
void L2CAP_Command(uint16_t handle, uint8_t *data, uint8_t nbytes, uint8_t channelLow=0x01, uint8_t channelHigh=0x00)
Definition BTD.cpp:1452
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t *dcid)
Definition BTD.cpp:1510
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition BTD.cpp:1546
bool connectToHIDDevice
Definition BTD.h:520
bool sdpConnectionClaimed
Definition BTD.h:473
uint8_t sdp_scid[2]
Definition BTHID.h:161
uint8_t interrupt_scid[2]
Definition BTHID.h:158
virtual void ParseBTHIDData(uint8_t len, uint8_t *buf)
Definition BTHID.h:134
BTHID(BTD *p, bool pair=false, const char *pin="0000")
Definition BTHID.cpp:23
void ACLData(uint8_t *ACLData)
Definition BTHID.cpp:63
void Run()
Definition BTHID.cpp:560
void onInit()
Definition BTHID.h:121
bool connected
Definition BTHID.h:88
virtual void ResetBTHID()
Definition BTHID.h:149
uint8_t control_scid[2]
Definition BTHID.h:155
virtual void ParseBTHIDControlData(uint8_t len, uint8_t *buf)
Definition BTHID.h:141
void setLeds(struct KBDLEDS data)
Definition BTHID.h:81
void disconnect()
Definition BTHID.cpp:53
uint8_t l2cap_sdp_state
Definition BTHID.h:160
void Reset()
Definition BTHID.cpp:43
void pair(void)
Definition BTHID.h:91
bool checkHciHandle(uint8_t *buf, uint16_t handle)
Definition BTD.h:639
uint16_t hci_handle
Definition BTD.h:650
uint32_t l2cap_event_flag
Definition BTD.h:653
BTD * pBtd
Definition BTD.h:647
uint8_t identifier
Definition BTD.h:656
virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)=0
#define Notify(...)
Definition message.h:51
#define HID_RPT_PROTOCOL
Definition usbhid.h:83
#define USB_HID_BOOT_PROTOCOL
Definition usbhid.h:82
#define PSTR(str)