diff --git a/_b_t_h_i_d_8cpp_source.html b/_b_t_h_i_d_8cpp_source.html index 1596ae37..7d26fd4c 100644 --- a/_b_t_h_i_d_8cpp_source.html +++ b/_b_t_h_i_d_8cpp_source.html @@ -86,7 +86,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
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 
23 BTHID::BTHID(BTD *p, bool pair, const char *pin) :
24 BluetoothService(p), // Pointer to USB class instance - mandatory
25 protocolMode(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 
43 void BTHID::Reset() {
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 
53 void 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 
63 void 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) {
67  pBtd->sdpConnectionClaimed = true;
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
191  pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid);
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);
307  uint16_t uuid;
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]);
312  D_PrintHex<uint16_t > (uuid, 0x80);
313 
314  Notify(PSTR("\r\nLength: "), 0x80);
315  uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
316  D_PrintHex<uint16_t > (length, 0x80);
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_THDR_DATA_INPUT
340  uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
341  ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]);
342 
343  switch(l2capinbuf[9]) {
344  case 0x01: // Keyboard or Joystick events
345  if(pRptParser[KEYBOARD_PARSER_ID])
346  pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
347  break;
348 
349  case 0x02: // Mouse events
350  if(pRptParser[MOUSE_PARSER_ID])
351  pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
352  break;
353 #ifdef EXTRADEBUG
354  default:
355  Notify(PSTR("\r\nUnknown Report type: "), 0x80);
356  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
357  break;
358 #endif
359  }
360  }
361  } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control
362 #ifdef PRINTREPORT
363  Notify(PSTR("\r\nL2CAP Control: "), 0x80);
364  for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
365  D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
366  Notify(PSTR(" "), 0x80);
367  }
368 #endif
369  }
370 #ifdef EXTRADEBUG
371  else {
372  Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
373  D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
374  Notify(PSTR(" "), 0x80);
375  D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
376 
377  Notify(PSTR("\r\nData: "), 0x80);
378  Notify(PSTR("\r\n"), 0x80);
379  for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
380  D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
381  Notify(PSTR(" "), 0x80);
382  }
383  }
384 #endif
385  SDP_task();
386  L2CAP_task();
387  }
388 }
389 
390 void BTHID::SDP_task() {
391  switch(l2cap_sdp_state) {
392  case L2CAP_SDP_WAIT:
395 #ifdef DEBUG_USB_HOST
396  Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
397 #endif
399  delay(1);
401  identifier++;
402  delay(1);
407  SDPConnected = false;
408 #ifdef DEBUG_USB_HOST
409  Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80);
410 #endif
412  }
413  break;
414  case L2CAP_SDP_SUCCESS:
417 #ifdef DEBUG_USB_HOST
418  Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
419 #endif
420  SDPConnected = true;
422  }
423  break;
424 
425  case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
427 #ifdef DEBUG_USB_HOST
428  Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
429 #endif
431  hci_handle = -1; // Reset handle
432  Reset();
433  }
434  break;
435  }
436 }
437 
438 void BTHID::L2CAP_task() {
439  switch(l2cap_state) {
440  /* These states are used if the HID device is the host */
443 #ifdef DEBUG_USB_HOST
444  Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
445 #endif
446  setProtocol(); // Set protocol before establishing HID interrupt channel
447  l2cap_state = L2CAP_INTERRUPT_SETUP;
448  }
449  break;
450 
453 #ifdef DEBUG_USB_HOST
454  Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
455 #endif
457  delay(1);
459  identifier++;
460  delay(1);
462 
463  l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
464  }
465  break;
466 
467  /* These states are used if the Arduino is the host */
470 #ifdef DEBUG_USB_HOST
471  Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
472 #endif
473  identifier++;
475  l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
476  }
477  break;
478 
481  setProtocol(); // Set protocol before establishing HID interrupt channel
482  delay(1); // Short delay between commands - just to be sure
483 #ifdef DEBUG_USB_HOST
484  Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
485 #endif
486  identifier++;
488  l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;
489  }
490  break;
491 
494 #ifdef DEBUG_USB_HOST
495  Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
496 #endif
497  identifier++;
499  l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
500  }
501  break;
502 
504  if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
505 #ifdef DEBUG_USB_HOST
506  Notify(PSTR("\r\nHID Channels Established"), 0x80);
507 #endif
508  pBtd->connectToHIDDevice = false;
509  pBtd->pairWithHIDDevice = false;
510  connected = true;
511  onInit();
512  l2cap_state = L2CAP_DONE;
513  }
514  break;
515 
516  case L2CAP_DONE:
517  break;
518 
521 #ifdef DEBUG_USB_HOST
522  Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
523 #endif
524  identifier++;
526  l2cap_state = L2CAP_CONTROL_DISCONNECT;
527  }
528  break;
529 
532 #ifdef DEBUG_USB_HOST
533  Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
534 #endif
536  hci_handle = -1; // Reset handle
537  l2cap_event_flag = 0; // Reset flags
538  l2cap_state = L2CAP_WAIT;
539  }
540  break;
541  }
542 }
543 
544 void BTHID::Run() {
545  switch(l2cap_state) {
546  case L2CAP_WAIT:
547  if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) {
549  activeConnection = true;
550 #ifdef DEBUG_USB_HOST
551  Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
552 #endif
553  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
554  l2cap_event_flag = 0; // Reset flags
555  identifier = 0;
557  l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
559 #ifdef DEBUG_USB_HOST
560  Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
561 #endif
563  delay(1);
565  identifier++;
566  delay(1);
568  l2cap_state = L2CAP_CONTROL_SUCCESS;
569  }
570  break;
571  }
572 }
573 
574 void BTHID::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
575  pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]);
576 }
577 
578 void BTHID::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
579  l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE;
580  l2capoutbuf[1] = transactionIDHigh;
581  l2capoutbuf[2] = transactionIDLow;
582  l2capoutbuf[3] = 0x00; // MSB Parameter Length
583  l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
584  l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
585  l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2
586 
587  /* Attribute ID/Value Sequence: */
588  l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte
589  l2capoutbuf[8] = 0x00; // Length = 0
590  l2capoutbuf[9] = 0x00; // No continuation state
591 
592  SDP_Command(l2capoutbuf, 10);
593 }
594 
595 /************************************************************/
596 /* HID Commands */
597 
598 /************************************************************/
599 void BTHID::setProtocol() {
600 #ifdef DEBUG_USB_HOST
601  Notify(PSTR("\r\nSet protocol mode: "), 0x80);
602  D_PrintHex<uint8_t > (protocolMode, 0x80);
603 #endif
604  if (protocolMode != USB_HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {
605 #ifdef DEBUG_USB_HOST
606  Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80);
607 #endif
608  protocolMode = USB_HID_BOOT_PROTOCOL; // Use Boot Protocol by default
609  }
610  uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33
611  pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]);
612 }
613 
614 void BTHID::setLeds(uint8_t data) {
615  uint8_t buf[3];
616  buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
617  buf[1] = 0x01; // Report ID
618  buf[2] = data;
620 }
#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE
Definition: BTD.h:149
+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 
23 BTHID::BTHID(BTD *p, bool pair, const char *pin) :
24 BluetoothService(p), // Pointer to USB class instance - mandatory
25 protocolMode(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 
43 void BTHID::Reset() {
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 
53 void 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 
63 void 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) {
67  pBtd->sdpConnectionClaimed = true;
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
191  pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid);
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);
307  uint16_t uuid;
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]);
312  D_PrintHex<uint16_t > (uuid, 0x80);
313 
314  Notify(PSTR("\r\nLength: "), 0x80);
315  uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
316  D_PrintHex<uint16_t > (length, 0x80);
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_THDR_DATA_INPUT
340  uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
341  ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]);
342 
343  switch(l2capinbuf[9]) {
344  case 0x01: // Keyboard or Joystick events
345  if(pRptParser[KEYBOARD_PARSER_ID])
346  pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
347  break;
348 
349  case 0x02: // Mouse events
350  if(pRptParser[MOUSE_PARSER_ID])
351  pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
352  break;
353 #ifdef EXTRADEBUG
354  default:
355  Notify(PSTR("\r\nUnknown Report type: "), 0x80);
356  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
357  break;
358 #endif
359  }
360  }
361  } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control
362 #ifdef PRINTREPORT
363  Notify(PSTR("\r\nL2CAP Control: "), 0x80);
364  for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
365  D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
366  Notify(PSTR(" "), 0x80);
367  }
368 #endif
369  if(l2capinbuf[8] == 0xA3) {
370  uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
371  ParseBTHIDControlData((uint8_t)(length - 1), &l2capinbuf[9]);
372  }
373  }
374 #ifdef EXTRADEBUG
375  else {
376  Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
377  D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
378  Notify(PSTR(" "), 0x80);
379  D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
380 
381  Notify(PSTR("\r\nData: "), 0x80);
382  Notify(PSTR("\r\n"), 0x80);
383  for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
384  D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
385  Notify(PSTR(" "), 0x80);
386  }
387  }
388 #endif
389  SDP_task();
390  L2CAP_task();
391  }
392 }
393 
394 void BTHID::SDP_task() {
395  switch(l2cap_sdp_state) {
396  case L2CAP_SDP_WAIT:
399 #ifdef DEBUG_USB_HOST
400  Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
401 #endif
403  delay(1);
405  identifier++;
406  delay(1);
411  SDPConnected = false;
412 #ifdef DEBUG_USB_HOST
413  Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80);
414 #endif
416  }
417  break;
418  case L2CAP_SDP_SUCCESS:
421 #ifdef DEBUG_USB_HOST
422  Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
423 #endif
424  SDPConnected = true;
426  }
427  break;
428 
429  case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
431 #ifdef DEBUG_USB_HOST
432  Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
433 #endif
435  hci_handle = -1; // Reset handle
436  Reset();
437  }
438  break;
439  }
440 }
441 
442 void BTHID::L2CAP_task() {
443  switch(l2cap_state) {
444  /* These states are used if the HID device is the host */
447 #ifdef DEBUG_USB_HOST
448  Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
449 #endif
450  setProtocol(); // Set protocol before establishing HID interrupt channel
451  l2cap_state = L2CAP_INTERRUPT_SETUP;
452  }
453  break;
454 
457 #ifdef DEBUG_USB_HOST
458  Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
459 #endif
461  delay(1);
463  identifier++;
464  delay(1);
466 
467  l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
468  }
469  break;
470 
471  /* These states are used if the Arduino is the host */
474 #ifdef DEBUG_USB_HOST
475  Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
476 #endif
477  identifier++;
479  l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
480  }
481  break;
482 
485  setProtocol(); // Set protocol before establishing HID interrupt channel
486  delay(1); // Short delay between commands - just to be sure
487 #ifdef DEBUG_USB_HOST
488  Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
489 #endif
490  identifier++;
492  l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;
493  }
494  break;
495 
498 #ifdef DEBUG_USB_HOST
499  Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
500 #endif
501  identifier++;
503  l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
504  }
505  break;
506 
508  if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
509 #ifdef DEBUG_USB_HOST
510  Notify(PSTR("\r\nHID Channels Established"), 0x80);
511 #endif
512  pBtd->connectToHIDDevice = false;
513  pBtd->pairWithHIDDevice = false;
514  connected = true;
515  onInit();
516  l2cap_state = L2CAP_DONE;
517  }
518  break;
519 
520  case L2CAP_DONE:
521  break;
522 
525 #ifdef DEBUG_USB_HOST
526  Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
527 #endif
528  identifier++;
530  l2cap_state = L2CAP_CONTROL_DISCONNECT;
531  }
532  break;
533 
536 #ifdef DEBUG_USB_HOST
537  Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
538 #endif
540  hci_handle = -1; // Reset handle
541  l2cap_event_flag = 0; // Reset flags
542  l2cap_state = L2CAP_WAIT;
543  }
544  break;
545  }
546 }
547 
548 void BTHID::Run() {
549  switch(l2cap_state) {
550  case L2CAP_WAIT:
551  if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) {
553  activeConnection = true;
554 #ifdef DEBUG_USB_HOST
555  Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
556 #endif
557  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
558  l2cap_event_flag = 0; // Reset flags
559  identifier = 0;
561  l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
563 #ifdef DEBUG_USB_HOST
564  Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
565 #endif
567  delay(1);
569  identifier++;
570  delay(1);
572  l2cap_state = L2CAP_CONTROL_SUCCESS;
573  }
574  break;
575  }
576 }
577 
578 void BTHID::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
579  pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]);
580 }
581 
582 void BTHID::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
583  l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE;
584  l2capoutbuf[1] = transactionIDHigh;
585  l2capoutbuf[2] = transactionIDLow;
586  l2capoutbuf[3] = 0x00; // MSB Parameter Length
587  l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
588  l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
589  l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2
590 
591  /* Attribute ID/Value Sequence: */
592  l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte
593  l2capoutbuf[8] = 0x00; // Length = 0
594  l2capoutbuf[9] = 0x00; // No continuation state
595 
596  SDP_Command(l2capoutbuf, 10);
597 }
598 
599 /************************************************************/
600 /* HID Commands */
601 
602 /************************************************************/
603 void BTHID::setProtocol() {
604 #ifdef DEBUG_USB_HOST
605  Notify(PSTR("\r\nSet protocol mode: "), 0x80);
606  D_PrintHex<uint8_t > (protocolMode, 0x80);
607 #endif
608  if (protocolMode != USB_HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {
609 #ifdef DEBUG_USB_HOST
610  Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80);
611 #endif
612  protocolMode = USB_HID_BOOT_PROTOCOL; // Use Boot Protocol by default
613  }
614  uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33
615  pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]);
616 }
617 
618 void BTHID::setLeds(uint8_t data) {
619  uint8_t buf[3];
620  buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
621  buf[1] = 0x01; // Report ID
622  buf[2] = data;
624 }
#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE
Definition: BTD.h:149
#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS
Definition: BTD.h:153
#define L2CAP_INTERRUPT_CONFIG_REQUEST
Definition: BTD.h:125
#define L2CAP_INTERRUPT_SETUP
Definition: BTD.h:123
@@ -98,26 +98,26 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
bool sdpConnectionClaimed
Definition: BTD.h:472
Definition: BTD.h:221
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1541
-
uint8_t interrupt_scid[2]
Definition: BTHID.h:142
+
uint8_t interrupt_scid[2]
Definition: BTHID.h:149
uint8_t identifier
Definition: BTD.h:655
#define L2CAP_FLAG_CONFIG_SDP_SUCCESS
Definition: BTD.h:159
#define SDP_SERVICE_ATTRIBUTE_REQUEST
Definition: BTD.h:198
bool connected
Definition: BTHID.h:88
#define L2CAP_SDP_SUCCESS
Definition: BTD.h:130
-
void Run()
Definition: BTHID.cpp:544
+
void Run()
Definition: BTHID.cpp:548
const char * btdPin
Definition: BTD.h:479
#define L2CAP_DONE
Definition: BTD.h:114
#define L2CAP_CONTROL_SUCCESS
Definition: BTD.h:119
#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST
Definition: BTD.h:200
#define L2CAP_WAIT
Definition: BTD.h:113
-
virtual void ResetBTHID()
Definition: BTHID.h:133
+
virtual void ResetBTHID()
Definition: BTHID.h:140
#define L2CAP_CMD_INFORMATION_REQUEST
Definition: BTD.h:182
void Reset()
Definition: BTHID.cpp:43
#define SDP_SERVICE_SEARCH_RESPONSE
Definition: BTD.h:197
#define L2CAP_CONTROL_CONFIG_REQUEST
Definition: BTD.h:118
#define SDP_PSM
Definition: BTD.h:190
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1554
-
uint8_t control_scid[2]
Definition: BTHID.h:139
+
uint8_t control_scid[2]
Definition: BTHID.h:146
#define Notify(...)
Definition: message.h:51
bool connectToHIDDevice
Definition: BTD.h:517
#define L2CAP_CONTROL_CONNECT_REQUEST
Definition: BTD.h:117
@@ -125,6 +125,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
bool incomingHIDDevice
Definition: BTD.h:521
bool pairWithHIDDevice
Definition: BTD.h:523
#define MOUSE_PARSER_ID
Definition: BTHID.h:25
+
virtual void ParseBTHIDControlData(uint8_t len, uint8_t *buf)
Definition: BTHID.h:132
uint16_t hci_handle
Definition: BTD.h:484
#define SDP_SERVICE_SEARCH_REQUEST
Definition: BTD.h:196
@@ -153,7 +154,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE
Definition: BTD.h:201
void setLeds(struct KBDLEDS data)
Definition: BTHID.h:81
uint16_t hci_handle
Definition: BTD.h:649
-
uint8_t sdp_scid[2]
Definition: BTHID.h:145
+
uint8_t sdp_scid[2]
Definition: BTHID.h:152
#define NUM_PARSERS
Definition: BTHID.h:26
#define KEYBOARD_PARSER_ID
Definition: BTHID.h:24
#define L2CAP_FLAG_CONNECTION_SDP_REQUEST
Definition: BTD.h:158
@@ -172,7 +173,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
#define L2CAP_CMD_CONNECTION_REQUEST
Definition: BTD.h:176
virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)=0
BTHID(BTD *p, bool pair=false, const char *pin="0000")
Definition: BTHID.cpp:23
-
uint8_t l2cap_sdp_state
Definition: BTHID.h:144
+
uint8_t l2cap_sdp_state
Definition: BTHID.h:151
bool checkHciHandle(uint8_t *buf, uint16_t handle)
Definition: BTD.h:638
#define L2CAP_INTERRUPT_CONNECT_REQUEST
Definition: BTD.h:124
#define HID_RPT_PROTOCOL
Definition: usbhid.h:83
diff --git a/_b_t_h_i_d_8h_source.html b/_b_t_h_i_d_8h_source.html index c05d80c1..f352c142 100644 --- a/_b_t_h_i_d_8h_source.html +++ b/_b_t_h_i_d_8h_source.html @@ -86,17 +86,18 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
BTHID.h
-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 #ifndef _bthid_h_
19 #define _bthid_h_
20 
21 #include "BTD.h"
22 #include "hidboot.h"
23 
24 #define KEYBOARD_PARSER_ID 0
25 #define MOUSE_PARSER_ID 1
26 #define NUM_PARSERS 2
27 
29 class BTHID : public BluetoothService {
30 public:
37  BTHID(BTD *p, bool pair = false, const char *pin = "0000");
38 
41  void disconnect();
50  if (id >= NUM_PARSERS)
51  return NULL;
52  return pRptParser[id];
53  };
54 
61  bool SetReportParser(uint8_t id, HIDReportParser *prs) {
62  if (id >= NUM_PARSERS)
63  return false;
64  pRptParser[id] = prs;
65  return true;
66  };
67 
72  void setProtocolMode(uint8_t mode) {
73  protocolMode = mode;
74  };
75 
81  void setLeds(struct KBDLEDS data) {
82  setLeds(*((uint8_t*)&data));
83  };
84  void setLeds(uint8_t data);
88  bool connected;
89 
91  void pair(void) {
92  if(pBtd)
93  pBtd->pairWithHID();
94  };
95 
96 protected:
102  void ACLData(uint8_t* ACLData);
104  void Run();
106  void Reset();
112  void onInit() {
113  if(pFuncOnInit)
114  pFuncOnInit(); // Call the user function
115  OnInitBTHID();
116  };
125  virtual void ParseBTHIDData(uint8_t len __attribute__((unused)), uint8_t *buf __attribute__((unused))) {
126  return;
127  };
129  virtual void OnInitBTHID() {
130  return;
131  };
133  virtual void ResetBTHID() {
134  return;
135  }
139  uint8_t control_scid[2];
140 
142  uint8_t interrupt_scid[2];
143 
145  uint8_t sdp_scid[2]; // L2CAP source CID for SDP
146 
147 private:
148  HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers.
149 
150  uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
151  void SDP_Command(uint8_t* data, uint8_t nbytes);
152  void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
153 
155  void setProtocol();
156  uint8_t protocolMode;
157 
158  void SDP_task();
159  void L2CAP_task(); // L2CAP state machine
160 
161  bool activeConnection; // Used to indicate if it already has established a connection
162  bool SDPConnected;
163 
164  /* Variables used for L2CAP communication */
165  uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070
166  uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071
167  uint8_t sdp_dcid[2];
168  uint8_t l2cap_state;
169 };
170 #endif
+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 #ifndef _bthid_h_
19 #define _bthid_h_
20 
21 #include "BTD.h"
22 #include "hidboot.h"
23 
24 #define KEYBOARD_PARSER_ID 0
25 #define MOUSE_PARSER_ID 1
26 #define NUM_PARSERS 2
27 
29 class BTHID : public BluetoothService {
30 public:
37  BTHID(BTD *p, bool pair = false, const char *pin = "0000");
38 
41  void disconnect();
50  if (id >= NUM_PARSERS)
51  return NULL;
52  return pRptParser[id];
53  };
54 
61  bool SetReportParser(uint8_t id, HIDReportParser *prs) {
62  if (id >= NUM_PARSERS)
63  return false;
64  pRptParser[id] = prs;
65  return true;
66  };
67 
72  void setProtocolMode(uint8_t mode) {
73  protocolMode = mode;
74  };
75 
81  void setLeds(struct KBDLEDS data) {
82  setLeds(*((uint8_t*)&data));
83  };
84  void setLeds(uint8_t data);
88  bool connected;
89 
91  void pair(void) {
92  if(pBtd)
93  pBtd->pairWithHID();
94  };
95 
96 protected:
102  void ACLData(uint8_t* ACLData);
104  void Run();
106  void Reset();
112  void onInit() {
113  if(pFuncOnInit)
114  pFuncOnInit(); // Call the user function
115  OnInitBTHID();
116  };
125  virtual void ParseBTHIDData(uint8_t len __attribute__((unused)), uint8_t *buf __attribute__((unused))) {
126  return;
127  };
132  virtual void ParseBTHIDControlData(uint8_t len __attribute__((unused)), uint8_t *buf __attribute__((unused))) {
133  return;
134  }
136  virtual void OnInitBTHID() {
137  return;
138  };
140  virtual void ResetBTHID() {
141  return;
142  }
146  uint8_t control_scid[2];
147 
149  uint8_t interrupt_scid[2];
150 
152  uint8_t sdp_scid[2]; // L2CAP source CID for SDP
153 
154 private:
155  HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers.
156 
157  uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
158  void SDP_Command(uint8_t* data, uint8_t nbytes);
159  void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
160 
162  void setProtocol();
163  uint8_t protocolMode;
164 
165  void SDP_task();
166  void L2CAP_task(); // L2CAP state machine
167 
168  bool activeConnection; // Used to indicate if it already has established a connection
169  bool SDPConnected;
170 
171  /* Variables used for L2CAP communication */
172  uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070
173  uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071
174  uint8_t sdp_dcid[2];
175  uint8_t l2cap_state;
176 };
177 #endif
-
virtual void OnInitBTHID()
Definition: BTHID.h:129
+
virtual void OnInitBTHID()
Definition: BTHID.h:136
void ACLData(uint8_t *ACLData)
Definition: BTHID.cpp:63
Definition: BTD.h:221
-
uint8_t interrupt_scid[2]
Definition: BTHID.h:142
+
uint8_t interrupt_scid[2]
Definition: BTHID.h:149
bool connected
Definition: BTHID.h:88
-
void Run()
Definition: BTHID.cpp:544
-
virtual void ResetBTHID()
Definition: BTHID.h:133
+
void Run()
Definition: BTHID.cpp:548
+
virtual void ResetBTHID()
Definition: BTHID.h:140
void Reset()
Definition: BTHID.cpp:43
-
uint8_t control_scid[2]
Definition: BTHID.h:139
+
uint8_t control_scid[2]
Definition: BTHID.h:146
+
virtual void ParseBTHIDControlData(uint8_t len, uint8_t *buf)
Definition: BTHID.h:132
void pairWithHID()
Definition: BTD.h:513
void disconnect()
Definition: BTHID.cpp:53
@@ -106,7 +107,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
BTD * pBtd
Definition: BTD.h:646
#define BULK_MAXPKTSIZE
Definition: BTD.h:37
void setLeds(struct KBDLEDS data)
Definition: BTHID.h:81
-
uint8_t sdp_scid[2]
Definition: BTHID.h:145
+
uint8_t sdp_scid[2]
Definition: BTHID.h:152
#define NUM_PARSERS
Definition: BTHID.h:26
void onInit()
Definition: BTHID.h:112
@@ -114,7 +115,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
void setProtocolMode(uint8_t mode)
Definition: BTHID.h:72
BTHID(BTD *p, bool pair=false, const char *pin="0000")
Definition: BTHID.cpp:23
-
uint8_t l2cap_sdp_state
Definition: BTHID.h:144
+
uint8_t l2cap_sdp_state
Definition: BTHID.h:151
void pair(void)
Definition: BTHID.h:91
bool SetReportParser(uint8_t id, HIDReportParser *prs)
Definition: BTHID.h:61
diff --git a/_p_s4_b_t_8h_source.html b/_p_s4_b_t_8h_source.html index a0e17d8d..645ab860 100644 --- a/_p_s4_b_t_8h_source.html +++ b/_p_s4_b_t_8h_source.html @@ -94,7 +94,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
bool connected
Definition: BTHID.h:88
uint8_t flashOn
Definition: PS4Parser.h:119
-
uint8_t control_scid[2]
Definition: BTHID.h:139
+
uint8_t control_scid[2]
Definition: BTHID.h:146
uint8_t g
Definition: PS4Parser.h:118
bool reportChanged
Definition: PS4Parser.h:120
void Parse(uint8_t len, uint8_t *buf)
Definition: PS4Parser.cpp:76
diff --git a/_x_b_o_x_o_n_e_s_b_t_8h_source.html b/_x_b_o_x_o_n_e_s_b_t_8h_source.html index 9695c63a..484fb8e2 100644 --- a/_x_b_o_x_o_n_e_s_b_t_8h_source.html +++ b/_x_b_o_x_o_n_e_s_b_t_8h_source.html @@ -93,7 +93,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
virtual void ParseBTHIDData(uint8_t len, uint8_t *buf)
Definition: XBOXONESBT.h:56
bool connected
Definition: BTHID.h:88
virtual void ResetBTHID()
Definition: XBOXONESBT.h:72
-
uint8_t control_scid[2]
Definition: BTHID.h:139
+
uint8_t control_scid[2]
Definition: BTHID.h:146
#define Notify(...)
Definition: message.h:51
void Parse(uint8_t len, uint8_t *buf)
diff --git a/class_b_t_h_i_d-members.html b/class_b_t_h_i_d-members.html index bd5387f4..ead8e4c5 100644 --- a/class_b_t_h_i_d-members.html +++ b/class_b_t_h_i_d-members.html @@ -108,17 +108,18 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); onInit()BTHIDinlineprotectedvirtual OnInitBTHID()BTHIDinlineprotectedvirtual pair(void)BTHIDinline - ParseBTHIDData(uint8_t len, uint8_t *buf)BTHIDinlineprotectedvirtual - pBtdBluetoothServiceprotected - pFuncOnInitBluetoothServiceprotected - Reset()BTHIDprotectedvirtual - ResetBTHID()BTHIDinlineprotectedvirtual - Run()BTHIDprotectedvirtual - sdp_scidBTHIDprotected - setLeds(struct KBDLEDS data)BTHIDinline - setLeds(uint8_t data)BTHID - setProtocolMode(uint8_t mode)BTHIDinline - SetReportParser(uint8_t id, HIDReportParser *prs)BTHIDinline + ParseBTHIDControlData(uint8_t len, uint8_t *buf)BTHIDinlineprotectedvirtual + ParseBTHIDData(uint8_t len, uint8_t *buf)BTHIDinlineprotectedvirtual + pBtdBluetoothServiceprotected + pFuncOnInitBluetoothServiceprotected + Reset()BTHIDprotectedvirtual + ResetBTHID()BTHIDinlineprotectedvirtual + Run()BTHIDprotectedvirtual + sdp_scidBTHIDprotected + setLeds(struct KBDLEDS data)BTHIDinline + setLeds(uint8_t data)BTHID + setProtocolMode(uint8_t mode)BTHIDinline + SetReportParser(uint8_t id, HIDReportParser *prs)BTHIDinline
@@ -522,7 +524,7 @@ BluetoothService implementation

Implements BluetoothService.

-

Definition at line 544 of file BTHID.cpp.

+

Definition at line 548 of file BTHID.cpp.

@@ -625,6 +627,43 @@ BluetoothService implementation

Definition at line 125 of file BTHID.h.

+ + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
virtual void BTHID::ParseBTHIDControlData (uint8_t len,
uint8_t * buf 
)
+
+inlineprotectedvirtual
+
+

Same as ParseBTHIDData for reports that are sent through the interrupt pipe (in response to a GET_REPORT).

+ +

Definition at line 132 of file BTHID.h.

+
@@ -651,7 +690,7 @@ BluetoothService implementation

Reimplemented in PS4BT, and XBOXONESBT.

-

Definition at line 129 of file BTHID.h.

+

Definition at line 136 of file BTHID.h.

@@ -679,7 +718,7 @@ BluetoothService implementation

Reimplemented in PS4BT, and XBOXONESBT.

-

Definition at line 133 of file BTHID.h.

+

Definition at line 140 of file BTHID.h.

@@ -718,7 +757,7 @@ BluetoothService implementation

L2CAP source CID for HID_Control

-

Definition at line 139 of file BTHID.h.

+

Definition at line 146 of file BTHID.h.

@@ -741,7 +780,7 @@ BluetoothService implementation

L2CAP source CID for HID_Interrupt

-

Definition at line 142 of file BTHID.h.

+

Definition at line 149 of file BTHID.h.

@@ -763,7 +802,7 @@ BluetoothService implementation
-

Definition at line 144 of file BTHID.h.

+

Definition at line 151 of file BTHID.h.

@@ -785,7 +824,7 @@ BluetoothService implementation
-

Definition at line 145 of file BTHID.h.

+

Definition at line 152 of file BTHID.h.

diff --git a/class_p_s4_b_t-members.html b/class_p_s4_b_t-members.html index e3554180..2af13e41 100644 --- a/class_p_s4_b_t-members.html +++ b/class_p_s4_b_t-members.html @@ -124,29 +124,30 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); OnInitBTHID()PS4BTinlineprotectedvirtual pair(void)BTHIDinline Parse(uint8_t len, uint8_t *buf)PS4Parserprotected - ParseBTHIDData(uint8_t len, uint8_t *buf)PS4BTinlineprotectedvirtual - pBtdBluetoothServiceprotected - pFuncOnInitBluetoothServiceprotected - PS4BT(BTD *p, bool pair=false, const char *pin="0000")PS4BTinline - PS4Parser()PS4Parserinline - BTHID::Reset()BTHIDprotectedvirtual - PS4Parser::Reset()PS4Parserprotected - ResetBTHID()PS4BTinlineprotectedvirtual - Run()BTHIDprotectedvirtual - sdp_scidBTHIDprotected - sendOutputReport(PS4Output *output)PS4BTinlineprotectedvirtual - setAllOff()PS4Parserinline - setLed(uint8_t r, uint8_t g, uint8_t b)PS4Parserinline - setLed(ColorsEnum color)PS4Parserinline - setLedFlash(uint8_t flashOn, uint8_t flashOff)PS4Parserinline - setLedOff()PS4Parserinline - setLeds(struct KBDLEDS data)BTHIDinline - setLeds(uint8_t data)BTHID - setProtocolMode(uint8_t mode)BTHIDinline - SetReportParser(uint8_t id, HIDReportParser *prs)BTHIDinline - setRumbleOff()PS4Parserinline - setRumbleOn(RumbleEnum mode)PS4Parserinline - setRumbleOn(uint8_t bigRumble, uint8_t smallRumble)PS4Parserinline + ParseBTHIDControlData(uint8_t len, uint8_t *buf)BTHIDinlineprotectedvirtual + ParseBTHIDData(uint8_t len, uint8_t *buf)PS4BTinlineprotectedvirtual + pBtdBluetoothServiceprotected + pFuncOnInitBluetoothServiceprotected + PS4BT(BTD *p, bool pair=false, const char *pin="0000")PS4BTinline + PS4Parser()PS4Parserinline + BTHID::Reset()BTHIDprotectedvirtual + PS4Parser::Reset()PS4Parserprotected + ResetBTHID()PS4BTinlineprotectedvirtual + Run()BTHIDprotectedvirtual + sdp_scidBTHIDprotected + sendOutputReport(PS4Output *output)PS4BTinlineprotectedvirtual + setAllOff()PS4Parserinline + setLed(uint8_t r, uint8_t g, uint8_t b)PS4Parserinline + setLed(ColorsEnum color)PS4Parserinline + setLedFlash(uint8_t flashOn, uint8_t flashOff)PS4Parserinline + setLedOff()PS4Parserinline + setLeds(struct KBDLEDS data)BTHIDinline + setLeds(uint8_t data)BTHID + setProtocolMode(uint8_t mode)BTHIDinline + SetReportParser(uint8_t id, HIDReportParser *prs)BTHIDinline + setRumbleOff()PS4Parserinline + setRumbleOn(RumbleEnum mode)PS4Parserinline + setRumbleOn(uint8_t bigRumble, uint8_t smallRumble)PS4Parserinline