2013-11-24 21:55:15 +01:00
/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 ( GPL2 ) as published by the Free Software
Foundation and appearing in the file GPL2 . TXT included in the packaging of
this file . Please note that GPL2 Section 2 [ b ] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ( " Copyleft " ) .
Contact information
- - - - - - - - - - - - - - - - - - -
Kristian Lauszus , TKJ Electronics
Web : http : //www.tkjelectronics.com
e - mail : kristianl @ tkjelectronics . com
*/
# include "BTHID.h"
// To enable serial debugging see "settings.h"
//#define EXTRADEBUG // Uncomment to get even more debugging data
2013-11-24 23:51:45 +01:00
//#define PRINTREPORT // Uncomment to print the report send by the HID device
2013-11-24 21:55:15 +01:00
BTHID : : BTHID ( BTD * p , bool pair , const char * pin ) :
2016-01-19 16:34:45 +01:00
BluetoothService ( p ) , // Pointer to BTD class instance - mandatory
2016-01-16 20:01:11 +01:00
protocolMode ( USB_HID_BOOT_PROTOCOL ) {
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < NUM_PARSERS ; i + + )
2013-11-24 23:51:45 +01:00
pRptParser [ i ] = NULL ;
2013-11-24 21:55:15 +01:00
pBtd - > pairWithHIDDevice = pair ;
2013-12-25 11:09:57 +01:00
pBtd - > btdPin = pin ;
2013-11-24 21:55:15 +01:00
/* Set device cid for the control and intterrupt channelse - LSB */
control_dcid [ 0 ] = 0x70 ; // 0x0070
control_dcid [ 1 ] = 0x00 ;
interrupt_dcid [ 0 ] = 0x71 ; // 0x0071
interrupt_dcid [ 1 ] = 0x00 ;
Reset ( ) ;
}
void BTHID : : Reset ( ) {
connected = false ;
activeConnection = false ;
l2cap_event_flag = 0 ; // Reset flags
l2cap_state = L2CAP_WAIT ;
2014-01-18 22:36:01 +01:00
ResetBTHID ( ) ;
2013-11-24 21:55:15 +01:00
}
2013-12-30 16:11:19 +01:00
void BTHID : : disconnect ( ) { // Use this void to disconnect the device
2013-11-24 21:55:15 +01:00
// First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
2013-12-13 10:38:41 +01:00
pBtd - > l2cap_disconnection_request ( hci_handle , + + identifier , interrupt_scid , interrupt_dcid ) ;
2013-11-24 21:55:15 +01:00
Reset ( ) ;
l2cap_state = L2CAP_INTERRUPT_DISCONNECT ;
}
void BTHID : : ACLData ( uint8_t * l2capinbuf ) {
2013-12-25 11:09:57 +01:00
if ( ! pBtd - > l2capConnectionClaimed & & pBtd - > incomingHIDDevice & & ! connected & & ! activeConnection ) {
if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_REQUEST ) {
if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = HID_CTRL_PSM ) {
2013-11-24 21:55:15 +01:00
pBtd - > incomingHIDDevice = false ;
pBtd - > l2capConnectionClaimed = true ; // Claim that the incoming connection belongs to this service
activeConnection = true ;
hci_handle = pBtd - > hci_handle ; // Store the HCI Handle for the connection
l2cap_state = L2CAP_WAIT ;
}
}
}
2014-09-10 01:38:42 +02:00
if ( checkHciHandle ( l2capinbuf , hci_handle ) ) { // acl_handle_ok
2013-12-25 11:09:57 +01:00
if ( ( l2capinbuf [ 6 ] | ( l2capinbuf [ 7 ] < < 8 ) ) = = 0x0001U ) { // l2cap_control - Channel ID for ACL-U
if ( l2capinbuf [ 8 ] = = L2CAP_CMD_COMMAND_REJECT ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n L2CAP Command Rejected - Reason: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 17 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 16 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 15 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
# endif
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_RESPONSE ) {
if ( ( ( l2capinbuf [ 16 ] | ( l2capinbuf [ 17 ] < < 8 ) ) = = 0x0000 ) & & ( ( l2capinbuf [ 18 ] | ( l2capinbuf [ 19 ] < < 8 ) ) = = SUCCESSFUL ) ) { // Success
if ( l2capinbuf [ 14 ] = = control_dcid [ 0 ] & & l2capinbuf [ 15 ] = = control_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
identifier = l2capinbuf [ 9 ] ;
control_scid [ 0 ] = l2capinbuf [ 12 ] ;
control_scid [ 1 ] = l2capinbuf [ 13 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONTROL_CONNECTED ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 14 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 15 ] = = interrupt_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
identifier = l2capinbuf [ 9 ] ;
interrupt_scid [ 0 ] = l2capinbuf [ 12 ] ;
interrupt_scid [ 1 ] = l2capinbuf [ 13 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_INTERRUPT_CONNECTED ) ;
2013-11-24 21:55:15 +01:00
}
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_REQUEST ) {
2013-11-24 21:55:15 +01:00
# ifdef EXTRADEBUG
Notify ( PSTR ( " \r \n L2CAP Connection Request - PSM: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
Notify ( PSTR ( " SCID: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 15 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
Notify ( PSTR ( " Identifier: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 9 ] , 0x80 ) ;
# endif
2013-12-25 11:09:57 +01:00
if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = HID_CTRL_PSM ) {
2013-11-24 21:55:15 +01:00
identifier = l2capinbuf [ 9 ] ;
control_scid [ 0 ] = l2capinbuf [ 14 ] ;
control_scid [ 1 ] = l2capinbuf [ 15 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONNECTION_CONTROL_REQUEST ) ;
2013-12-25 11:09:57 +01:00
} else if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = HID_INTR_PSM ) {
2013-11-24 21:55:15 +01:00
identifier = l2capinbuf [ 9 ] ;
interrupt_scid [ 0 ] = l2capinbuf [ 14 ] ;
interrupt_scid [ 1 ] = l2capinbuf [ 15 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST ) ;
2013-11-24 21:55:15 +01:00
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONFIG_RESPONSE ) {
if ( ( l2capinbuf [ 16 ] | ( l2capinbuf [ 17 ] < < 8 ) ) = = 0x0000 ) { // Success
if ( l2capinbuf [ 12 ] = = control_dcid [ 0 ] & & l2capinbuf [ 13 ] = = control_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONFIG_CONTROL_SUCCESS ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS ) ;
2013-11-24 21:55:15 +01:00
}
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONFIG_REQUEST ) {
if ( l2capinbuf [ 12 ] = = control_dcid [ 0 ] & & l2capinbuf [ 13 ] = = control_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
pBtd - > l2cap_config_response ( hci_handle , l2capinbuf [ 9 ] , control_scid ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
pBtd - > l2cap_config_response ( hci_handle , l2capinbuf [ 9 ] , interrupt_scid ) ;
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_DISCONNECT_REQUEST ) {
if ( l2capinbuf [ 12 ] = = control_dcid [ 0 ] & & l2capinbuf [ 13 ] = = control_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Disconnect Request: Control Channel " ) , 0x80 ) ;
# endif
identifier = l2capinbuf [ 9 ] ;
pBtd - > l2cap_disconnection_response ( hci_handle , identifier , control_dcid , control_scid ) ;
Reset ( ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_dcid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Disconnect Request: Interrupt Channel " ) , 0x80 ) ;
# endif
identifier = l2capinbuf [ 9 ] ;
pBtd - > l2cap_disconnection_response ( hci_handle , identifier , interrupt_dcid , interrupt_scid ) ;
Reset ( ) ;
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_DISCONNECT_RESPONSE ) {
if ( l2capinbuf [ 12 ] = = control_scid [ 0 ] & & l2capinbuf [ 13 ] = = control_scid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = interrupt_scid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_scid [ 1 ] ) {
2013-11-24 21:55:15 +01:00
//Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE ) ;
2013-11-24 21:55:15 +01:00
}
}
# ifdef EXTRADEBUG
else {
identifier = l2capinbuf [ 9 ] ;
Notify ( PSTR ( " \r \n L2CAP Unknown Signaling Command: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 8 ] , 0x80 ) ;
}
# endif
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 6 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 7 ] = = interrupt_dcid [ 1 ] ) { // l2cap_interrupt
2013-11-24 21:55:15 +01:00
# ifdef PRINTREPORT
2013-11-25 02:58:33 +01:00
Notify ( PSTR ( " \r \n L2CAP Interrupt: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( uint16_t i = 0 ; i < ( ( uint16_t ) l2capinbuf [ 5 ] < < 8 | l2capinbuf [ 4 ] ) ; i + + ) {
2013-11-24 21:55:15 +01:00
D_PrintHex < uint8_t > ( l2capinbuf [ i + 8 ] , 0x80 ) ;
2013-11-25 18:46:10 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
}
# endif
2013-12-25 11:09:57 +01:00
if ( l2capinbuf [ 8 ] = = 0xA1 ) { // HID_THDR_DATA_INPUT
2014-01-18 22:36:01 +01:00
uint16_t length = ( ( uint16_t ) l2capinbuf [ 5 ] < < 8 | l2capinbuf [ 4 ] ) ;
2014-02-03 23:06:27 +01:00
ParseBTHIDData ( ( uint8_t ) ( length - 1 ) , & l2capinbuf [ 9 ] ) ;
2014-01-18 22:36:01 +01:00
2013-12-25 11:09:57 +01:00
switch ( l2capinbuf [ 9 ] ) {
2014-01-18 22:36:01 +01:00
case 0x01 : // Keyboard or Joystick events
if ( pRptParser [ KEYBOARD_PARSER_ID ] )
2016-01-16 20:01:11 +01:00
pRptParser [ KEYBOARD_PARSER_ID ] - > Parse ( reinterpret_cast < USBHID * > ( this ) , 0 , ( uint8_t ) ( length - 2 ) , & l2capinbuf [ 10 ] ) ; // Use reinterpret_cast again to extract the instance
2013-11-24 21:55:15 +01:00
break ;
case 0x02 : // Mouse events
2014-01-18 22:36:01 +01:00
if ( pRptParser [ MOUSE_PARSER_ID ] )
2016-01-16 20:01:11 +01:00
pRptParser [ MOUSE_PARSER_ID ] - > Parse ( reinterpret_cast < USBHID * > ( this ) , 0 , ( uint8_t ) ( length - 2 ) , & l2capinbuf [ 10 ] ) ; // Use reinterpret_cast again to extract the instance
2013-11-24 21:55:15 +01:00
break ;
2014-01-22 05:13:49 +01:00
# ifdef EXTRADEBUG
2013-11-24 21:55:15 +01:00
default :
Notify ( PSTR ( " \r \n Unknown Report type: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 9 ] , 0x80 ) ;
break ;
# endif
}
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 6 ] = = control_dcid [ 0 ] & & l2capinbuf [ 7 ] = = control_dcid [ 1 ] ) { // l2cap_control
2013-11-25 02:58:33 +01:00
# ifdef PRINTREPORT
Notify ( PSTR ( " \r \n L2CAP Control: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( uint16_t i = 0 ; i < ( ( uint16_t ) l2capinbuf [ 5 ] < < 8 | l2capinbuf [ 4 ] ) ; i + + ) {
2013-11-25 02:58:33 +01:00
D_PrintHex < uint8_t > ( l2capinbuf [ i + 8 ] , 0x80 ) ;
2013-11-25 18:46:10 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-11-25 02:58:33 +01:00
}
# endif
2013-11-24 21:55:15 +01:00
}
# ifdef EXTRADEBUG
else {
Notify ( PSTR ( " \r \n Unsupported L2CAP Data - Channel ID: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 7 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 6 ] , 0x80 ) ;
Notify ( PSTR ( " \r \n Data: " ) , 0x80 ) ;
Notify ( PSTR ( " \r \n " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( uint16_t i = 0 ; i < ( ( uint16_t ) l2capinbuf [ 5 ] < < 8 | l2capinbuf [ 4 ] ) ; i + + ) {
2013-11-24 21:55:15 +01:00
D_PrintHex < uint8_t > ( l2capinbuf [ i + 8 ] , 0x80 ) ;
2013-11-27 00:07:58 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
}
}
# endif
L2CAP_task ( ) ;
}
}
void BTHID : : L2CAP_task ( ) {
2013-12-25 11:09:57 +01:00
switch ( l2cap_state ) {
2013-11-24 23:51:45 +01:00
/* These states are used if the HID device is the host */
2013-11-24 21:55:15 +01:00
case L2CAP_CONTROL_SUCCESS :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONFIG_CONTROL_SUCCESS ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n HID Control Successfully Configured " ) , 0x80 ) ;
# endif
2013-11-25 19:01:20 +01:00
setProtocol ( ) ; // Set protocol before establishing HID interrupt channel
2013-11-24 21:55:15 +01:00
l2cap_state = L2CAP_INTERRUPT_SETUP ;
}
break ;
case L2CAP_INTERRUPT_SETUP :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n HID Interrupt Incoming Connection Request " ) , 0x80 ) ;
# endif
pBtd - > l2cap_connection_response ( hci_handle , identifier , interrupt_dcid , interrupt_scid , PENDING ) ;
delay ( 1 ) ;
pBtd - > l2cap_connection_response ( hci_handle , identifier , interrupt_dcid , interrupt_scid , SUCCESSFUL ) ;
identifier + + ;
delay ( 1 ) ;
pBtd - > l2cap_config_request ( hci_handle , identifier , interrupt_scid ) ;
l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST ;
}
break ;
/* These states are used if the Arduino is the host */
case L2CAP_CONTROL_CONNECT_REQUEST :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONTROL_CONNECTED ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Send HID Control Config Request " ) , 0x80 ) ;
# endif
identifier + + ;
pBtd - > l2cap_config_request ( hci_handle , identifier , control_scid ) ;
l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST ;
}
break ;
case L2CAP_CONTROL_CONFIG_REQUEST :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONFIG_CONTROL_SUCCESS ) ) {
2013-11-25 19:01:20 +01:00
setProtocol ( ) ; // Set protocol before establishing HID interrupt channel
delay ( 1 ) ; // Short delay between commands - just to be sure
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
2013-11-25 19:01:20 +01:00
Notify ( PSTR ( " \r \n Send HID Interrupt Connection Request " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
# endif
2013-11-25 19:01:20 +01:00
identifier + + ;
pBtd - > l2cap_connection_request ( hci_handle , identifier , interrupt_dcid , HID_INTR_PSM ) ;
l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST ;
}
2013-11-24 21:55:15 +01:00
break ;
case L2CAP_INTERRUPT_CONNECT_REQUEST :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_INTERRUPT_CONNECTED ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Send HID Interrupt Config Request " ) , 0x80 ) ;
# endif
identifier + + ;
pBtd - > l2cap_config_request ( hci_handle , identifier , interrupt_scid ) ;
l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST ;
}
break ;
case L2CAP_INTERRUPT_CONFIG_REQUEST :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS ) ) { // Now the HID channels is established
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n HID Channels Established " ) , 0x80 ) ;
# endif
pBtd - > connectToHIDDevice = false ;
pBtd - > pairWithHIDDevice = false ;
connected = true ;
onInit ( ) ;
l2cap_state = L2CAP_DONE ;
}
break ;
case L2CAP_DONE :
break ;
case L2CAP_INTERRUPT_DISCONNECT :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Disconnected Interrupt Channel " ) , 0x80 ) ;
# endif
identifier + + ;
pBtd - > l2cap_disconnection_request ( hci_handle , identifier , control_scid , control_dcid ) ;
l2cap_state = L2CAP_CONTROL_DISCONNECT ;
}
break ;
case L2CAP_CONTROL_DISCONNECT :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Disconnected Control Channel " ) , 0x80 ) ;
# endif
pBtd - > hci_disconnect ( hci_handle ) ;
hci_handle = - 1 ; // Reset handle
l2cap_event_flag = 0 ; // Reset flags
l2cap_state = L2CAP_WAIT ;
}
break ;
}
}
void BTHID : : Run ( ) {
2013-12-25 11:09:57 +01:00
switch ( l2cap_state ) {
2013-11-24 21:55:15 +01:00
case L2CAP_WAIT :
2013-12-25 11:09:57 +01:00
if ( pBtd - > connectToHIDDevice & & ! pBtd - > l2capConnectionClaimed & & ! connected & & ! activeConnection ) {
2013-11-24 21:55:15 +01:00
pBtd - > l2capConnectionClaimed = true ;
activeConnection = true ;
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Send HID Control Connection Request " ) , 0x80 ) ;
# endif
hci_handle = pBtd - > hci_handle ; // Store the HCI Handle for the connection
l2cap_event_flag = 0 ; // Reset flags
identifier = 0 ;
pBtd - > l2cap_connection_request ( hci_handle , identifier , control_dcid , HID_CTRL_PSM ) ;
l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST ;
2013-12-25 11:09:57 +01:00
} else if ( l2cap_check_flag ( L2CAP_FLAG_CONNECTION_CONTROL_REQUEST ) ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n HID Control Incoming Connection Request " ) , 0x80 ) ;
# endif
pBtd - > l2cap_connection_response ( hci_handle , identifier , control_dcid , control_scid , PENDING ) ;
delay ( 1 ) ;
pBtd - > l2cap_connection_response ( hci_handle , identifier , control_dcid , control_scid , SUCCESSFUL ) ;
identifier + + ;
delay ( 1 ) ;
pBtd - > l2cap_config_request ( hci_handle , identifier , control_scid ) ;
l2cap_state = L2CAP_CONTROL_SUCCESS ;
}
break ;
}
}
/************************************************************/
/* HID Commands */
2013-12-25 11:09:57 +01:00
2013-11-24 21:55:15 +01:00
/************************************************************/
void BTHID : : setProtocol ( ) {
2013-11-25 02:15:33 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Set protocol mode: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( protocolMode , 0x80 ) ;
# endif
2016-01-16 20:01:11 +01:00
if ( protocolMode ! = USB_HID_BOOT_PROTOCOL & & protocolMode ! = HID_RPT_PROTOCOL ) {
2013-12-30 16:11:19 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Not a valid protocol mode. Using Boot protocol instead. " ) , 0x80 ) ;
# endif
2016-01-16 20:01:11 +01:00
protocolMode = USB_HID_BOOT_PROTOCOL ; // Use Boot Protocol by default
2013-12-30 16:11:19 +01:00
}
uint8_t command = 0x70 | protocolMode ; // Set Protocol, see Bluetooth HID specs page 33
2013-11-24 21:55:15 +01:00
pBtd - > L2CAP_Command ( hci_handle , & command , 1 , control_scid [ 0 ] , control_scid [ 1 ] ) ;
2013-11-25 01:45:24 +01:00
}
void BTHID : : setLeds ( uint8_t data ) {
uint8_t buf [ 3 ] ;
buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
buf [ 1 ] = 0x01 ; // Report ID
buf [ 2 ] = data ;
pBtd - > L2CAP_Command ( hci_handle , buf , 3 , interrupt_scid [ 0 ] , interrupt_scid [ 1 ] ) ;
2013-12-25 11:09:57 +01:00
}