2012-08-04 12:20:47 +02:00
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
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 " ) .
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
Contact information
- - - - - - - - - - - - - - - - - - -
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
Kristian Lauszus , TKJ Electronics
Web : http : //www.tkjelectronics.com
e - mail : kristianl @ tkjelectronics . com
*/
# include "BTD.h"
2013-11-11 11:48:09 +01:00
// To enable serial debugging see "settings.h"
2020-11-15 17:29:54 +01:00
//#define EXTRADEBUG // Uncomment to get even more debugging data
2012-08-04 12:20:47 +02:00
2013-02-05 19:51:45 +01:00
const uint8_t BTD : : BTD_CONTROL_PIPE = 0 ;
2013-03-28 09:37:09 +01:00
const uint8_t BTD : : BTD_EVENT_PIPE = 1 ;
2012-08-04 12:20:47 +02:00
const uint8_t BTD : : BTD_DATAIN_PIPE = 2 ;
const uint8_t BTD : : BTD_DATAOUT_PIPE = 3 ;
2013-03-28 09:37:09 +01:00
BTD : : BTD ( USB * p ) :
2013-09-27 11:07:05 +02:00
connectToWii ( false ) ,
pairWithWii ( false ) ,
2013-11-24 21:55:15 +01:00
connectToHIDDevice ( false ) ,
pairWithHIDDevice ( false ) ,
2020-11-15 19:02:54 +01:00
useSimplePairing ( false ) ,
2012-08-04 12:20:47 +02:00
pUsb ( p ) , // Pointer to USB class instance - mandatory
bAddress ( 0 ) , // Device address - mandatory
bNumEP ( 1 ) , // If config descriptor needs to be parsed
qNextPollTime ( 0 ) , // Reset NextPollTime
2013-09-27 11:07:05 +02:00
pollInterval ( 0 ) ,
2019-07-03 00:30:18 +02:00
simple_pairing_supported ( false ) ,
2012-08-04 12:20:47 +02:00
bPollEnable ( false ) // Don't start polling before dongle is connected
{
2014-01-12 16:31:47 +01:00
for ( uint8_t i = 0 ; i < BTD_NUM_SERVICES ; i + + )
2013-09-27 21:39:38 +02:00
btService [ i ] = NULL ;
2013-09-27 11:07:05 +02:00
2013-12-01 16:02:23 +01:00
Initialize ( ) ; // Set all variables, endpoint structs etc. to default values
2013-10-07 00:47:53 +02:00
2013-12-25 11:09:57 +01:00
if ( pUsb ) // Register in USB subsystem
2013-10-07 00:47:53 +02:00
pUsb - > RegisterDeviceClass ( this ) ; // Set devConfig[] entry
2012-08-04 12:20:47 +02:00
}
2013-10-07 00:47:53 +02:00
uint8_t BTD : : ConfigureDevice ( uint8_t parent , uint8_t port , bool lowspeed ) {
const uint8_t constBufSize = sizeof ( USB_DEVICE_DESCRIPTOR ) ;
uint8_t buf [ constBufSize ] ;
2013-12-05 00:40:23 +01:00
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast < USB_DEVICE_DESCRIPTOR * > ( buf ) ;
2013-03-28 09:37:09 +01:00
uint8_t rcode ;
UsbDevice * p = NULL ;
EpInfo * oldep_ptr = NULL ;
2013-12-01 16:02:23 +01:00
Initialize ( ) ; // Set all variables, endpoint structs etc. to default values
2013-10-07 00:47:53 +02:00
AddressPool & addrPool = pUsb - > GetAddressPool ( ) ; // Get memory address of USB device address pool
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-10-07 00:47:53 +02:00
Notify ( PSTR ( " \r \n BTD ConfigureDevice " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-10-07 00:47:53 +02:00
2013-12-25 11:09:57 +01:00
if ( bAddress ) { // Check if address has already been assigned to an instance
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Address in use " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE ;
}
2013-10-07 00:47:53 +02:00
p = addrPool . GetUsbDevicePtr ( 0 ) ; // Get pointer to pseudo device with address 0 assigned
2013-12-25 11:09:57 +01:00
if ( ! p ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Address not found " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL ;
}
2013-12-25 11:09:57 +01:00
if ( ! p - > epinfo ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n epinfo is null " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
return USB_ERROR_EPINFO_IS_NULL ;
}
2013-10-07 00:47:53 +02:00
oldep_ptr = p - > epinfo ; // Save old pointer to EP_RECORD of address 0
p - > epinfo = epInfo ; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
2013-03-28 09:37:09 +01:00
p - > lowspeed = lowspeed ;
2013-10-07 00:47:53 +02:00
rcode = pUsb - > getDevDescr ( 0 , 0 , constBufSize , ( uint8_t * ) buf ) ; // Get device descriptor - addr, ep, nbytes, data
2013-03-28 09:37:09 +01:00
2013-10-07 00:47:53 +02:00
p - > epinfo = oldep_ptr ; // Restore p->epinfo
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-28 09:37:09 +01:00
goto FailGetDevDescr ;
2013-10-07 00:47:53 +02:00
bAddress = addrPool . AllocAddress ( parent , false , port ) ; // Allocate new address according to device class
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( ! bAddress ) {
2013-10-07 00:47:53 +02:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Out of address space " ) , 0x80 ) ;
# endif
2013-03-28 09:37:09 +01:00
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL ;
2013-10-07 00:47:53 +02:00
}
2015-12-06 18:35:16 +01:00
if ( udd - > bDeviceClass = = 0x09 ) // Some dongles have an USB hub inside
goto FailHub ;
2013-12-05 00:40:23 +01:00
epInfo [ 0 ] . maxPktSize = udd - > bMaxPacketSize0 ; // Extract Max Packet Size from device descriptor
epInfo [ 1 ] . epAddr = udd - > bNumConfigurations ; // Steal and abuse from epInfo structure to save memory
2013-10-07 00:47:53 +02:00
2013-12-05 00:40:23 +01:00
VID = udd - > idVendor ;
PID = udd - > idProduct ;
2013-10-07 01:45:21 +02:00
2013-10-07 00:47:53 +02:00
return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET ;
2015-12-06 18:35:16 +01:00
FailHub :
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Please create a hub instance in your code: \" USBHub Hub1(&Usb); \" " ) , 0x80 ) ;
# endif
pUsb - > setAddr ( bAddress , 0 , 0 ) ; // Reset address
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED ;
Release ( ) ;
return rcode ;
2013-10-07 00:47:53 +02:00
FailGetDevDescr :
# ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr ( rcode ) ;
# endif
2013-12-25 11:09:57 +01:00
if ( rcode ! = hrJERR )
2013-10-08 19:51:20 +02:00
rcode = USB_ERROR_FailGetDevDescr ;
2013-10-07 00:47:53 +02:00
Release ( ) ;
return rcode ;
} ;
2017-12-01 16:43:31 +01:00
uint8_t BTD : : Init ( uint8_t parent __attribute__ ( ( unused ) ) , uint8_t port __attribute__ ( ( unused ) ) , bool lowspeed ) {
2013-10-07 00:47:53 +02:00
uint8_t rcode ;
uint8_t num_of_conf = epInfo [ 1 ] . epAddr ; // Number of configurations
epInfo [ 1 ] . epAddr = 0 ;
2013-03-28 09:37:09 +01:00
2013-10-07 00:47:53 +02:00
AddressPool & addrPool = pUsb - > GetAddressPool ( ) ;
# ifdef EXTRADEBUG
Notify ( PSTR ( " \r \n BTD Init " ) , 0x80 ) ;
# endif
UsbDevice * p = addrPool . GetUsbDevicePtr ( bAddress ) ; // Get pointer to assigned address record
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( ! p ) {
2013-10-07 00:47:53 +02:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Address not found " ) , 0x80 ) ;
# endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL ;
}
delay ( 300 ) ; // Assign new address to the device
rcode = pUsb - > setAddr ( 0 , 0 , bAddress ) ; // Assign new address to the device
2013-12-25 11:09:57 +01:00
if ( rcode ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n setAddr: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rcode , 0x80 ) ;
2013-07-15 19:34:56 +02:00
# endif
2013-10-07 00:47:53 +02:00
p - > lowspeed = false ;
2013-09-06 00:22:00 +02:00
goto Fail ;
2013-03-28 09:37:09 +01:00
}
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Addr: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( bAddress , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-07-15 19:34:56 +02:00
2013-03-28 09:37:09 +01:00
p - > lowspeed = false ;
2013-10-07 00:47:53 +02:00
p = addrPool . GetUsbDevicePtr ( bAddress ) ; // Get pointer to assigned address record
2013-12-25 11:09:57 +01:00
if ( ! p ) {
2013-10-07 00:47:53 +02:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Address not found " ) , 0x80 ) ;
# endif
2013-03-28 09:37:09 +01:00
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL ;
2013-10-07 00:47:53 +02:00
}
2013-03-28 09:37:09 +01:00
p - > lowspeed = lowspeed ;
2013-10-07 00:47:53 +02:00
rcode = pUsb - > setEpInfoEntry ( bAddress , 1 , epInfo ) ; // Assign epInfo to epinfo pointer - only EP0 is known
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-28 09:37:09 +01:00
goto FailSetDevTblEntry ;
2013-10-07 00:47:53 +02:00
2013-12-25 11:09:57 +01:00
if ( VID = = PS3_VID & & ( PID = = PS3_PID | | PID = = PS3NAVIGATION_PID | | PID = = PS3MOVE_PID ) ) {
2013-10-21 17:36:42 +02:00
delay ( 100 ) ;
2013-10-07 00:47:53 +02:00
rcode = pUsb - > setConf ( bAddress , epInfo [ BTD_CONTROL_PIPE ] . epAddr , 1 ) ; // We only need the Control endpoint, so we don't have to initialize the other endpoints of device
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-30 15:29:16 +01:00
goto FailSetConfDescr ;
2013-03-28 09:37:09 +01:00
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( PID = = PS3_PID | | PID = = PS3NAVIGATION_PID ) {
if ( PID = = PS3_PID )
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Dualshock 3 Controller Connected " ) , 0x80 ) ;
2013-05-14 00:47:05 +02:00
else // It must be a navigation controller
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Navigation Controller Connected " ) , 0x80 ) ;
2013-05-14 00:47:05 +02:00
} else // It must be a Motion controller
Notify ( PSTR ( " \r \n Motion Controller Connected " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-05-14 00:47:05 +02:00
2013-12-25 11:09:57 +01:00
if ( my_bdaddr [ 0 ] = = 0x00 & & my_bdaddr [ 1 ] = = 0x00 & & my_bdaddr [ 2 ] = = 0x00 & & my_bdaddr [ 3 ] = = 0x00 & & my_bdaddr [ 4 ] = = 0x00 & & my_bdaddr [ 5 ] = = 0x00 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-09-12 22:24:48 +02:00
Notify ( PSTR ( " \r \n Please plug in the dongle before trying to pair with the PS3 Controller \r \n or set the Bluetooth address in the constructor of the PS3BT class " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-05-14 00:47:05 +02:00
} else {
2013-12-25 11:09:57 +01:00
if ( PID = = PS3_PID | | PID = = PS3NAVIGATION_PID )
2013-05-14 00:47:05 +02:00
setBdaddr ( my_bdaddr ) ; // Set internal Bluetooth address
else
setMoveBdaddr ( my_bdaddr ) ; // Set internal Bluetooth address
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-05-14 00:47:05 +02:00
Notify ( PSTR ( " \r \n Bluetooth Address was set to: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( int8_t i = 5 ; i > 0 ; i - - ) {
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( my_bdaddr [ i ] , 0x80 ) ;
2013-05-14 00:47:05 +02:00
Notify ( PSTR ( " : " ) , 0x80 ) ;
}
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( my_bdaddr [ 0 ] , 0x80 ) ;
2013-04-02 00:10:02 +02:00
# endif
2013-05-14 00:47:05 +02:00
}
2013-09-06 00:22:00 +02:00
pUsb - > setConf ( bAddress , epInfo [ BTD_CONTROL_PIPE ] . epAddr , 0 ) ; // Reset configuration value
2013-09-12 22:12:13 +02:00
pUsb - > setAddr ( bAddress , 0 , 0 ) ; // Reset address
Release ( ) ; // Release device
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED ; // Return
2013-03-28 09:37:09 +01:00
} else {
2013-05-14 00:47:05 +02:00
// Check if attached device is a Bluetooth dongle and fill endpoint data structure
// First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
// And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < num_of_conf ; i + + ) {
2017-12-08 17:34:26 +01:00
if ( ( VID = = IOGEAR_GBU521_VID & & PID = = IOGEAR_GBU521_PID ) | | ( VID = = BELKIN_F8T065BF_VID & & PID = = BELKIN_F8T065BF_PID ) ) {
ConfigDescParser < USB_CLASS_VENDOR_SPECIFIC , WI_SUBCLASS_RF , WI_PROTOCOL_BT , CP_MASK_COMPARE_ALL > confDescrParser ( this ) ; // Workaround issue with some dongles
2013-08-14 00:43:15 +02:00
rcode = pUsb - > getConfDescr ( bAddress , 0 , i , & confDescrParser ) ;
} else {
2017-12-08 17:34:26 +01:00
ConfigDescParser < USB_CLASS_WIRELESS_CTRL , WI_SUBCLASS_RF , WI_PROTOCOL_BT , CP_MASK_COMPARE_ALL > confDescrParser ( this ) ; // Set class id according to the specification
2013-08-14 00:43:15 +02:00
rcode = pUsb - > getConfDescr ( bAddress , 0 , i , & confDescrParser ) ;
}
2013-12-25 11:09:57 +01:00
if ( rcode ) // Check error code
2013-03-28 09:37:09 +01:00
goto FailGetConfDescr ;
2013-12-25 11:09:57 +01:00
if ( bNumEP > = BTD_MAX_ENDPOINTS ) // All endpoints extracted
2013-03-28 09:37:09 +01:00
break ;
}
2013-12-25 11:09:57 +01:00
if ( bNumEP < BTD_MAX_ENDPOINTS )
2013-08-14 00:43:15 +02:00
goto FailUnknownDevice ;
2013-03-28 09:37:09 +01:00
// Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb - > setEpInfoEntry ( bAddress , bNumEP , epInfo ) ;
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-28 09:37:09 +01:00
goto FailSetDevTblEntry ;
// Set Configuration Value
rcode = pUsb - > setConf ( bAddress , epInfo [ BTD_CONTROL_PIPE ] . epAddr , bConfNum ) ;
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-30 15:29:16 +01:00
goto FailSetConfDescr ;
2013-03-28 09:37:09 +01:00
hci_num_reset_loops = 100 ; // only loop 100 times before trying to send the hci reset command
hci_counter = 0 ;
hci_state = HCI_INIT_STATE ;
2017-02-07 15:27:00 +01:00
waitingForConnection = false ;
2013-03-28 09:37:09 +01:00
bPollEnable = true ;
2012-08-04 12:20:47 +02:00
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Bluetooth Dongle Initialized " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
}
return 0 ; // Successful configuration
2013-12-06 22:59:12 +01:00
/* Diagnostic messages */
2012-08-04 12:20:47 +02:00
FailSetDevTblEntry :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-30 15:29:16 +01:00
NotifyFailSetDevTblEntry ( ) ;
2013-03-28 09:37:09 +01:00
goto Fail ;
2013-05-16 22:43:51 +02:00
# endif
2013-03-30 15:29:16 +01:00
2012-08-04 12:20:47 +02:00
FailGetConfDescr :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-30 15:29:16 +01:00
NotifyFailGetConfDescr ( ) ;
2013-03-28 09:37:09 +01:00
goto Fail ;
2013-05-16 22:43:51 +02:00
# endif
2013-03-30 15:29:16 +01:00
FailSetConfDescr :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-30 15:29:16 +01:00
NotifyFailSetConfDescr ( ) ;
2013-05-16 22:43:51 +02:00
# endif
2013-03-28 09:37:09 +01:00
goto Fail ;
2013-03-30 15:29:16 +01:00
2013-04-01 03:06:49 +02:00
FailUnknownDevice :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-05-16 22:43:51 +02:00
NotifyFailUnknownDevice ( VID , PID ) ;
# endif
2013-03-28 09:37:09 +01:00
pUsb - > setAddr ( bAddress , 0 , 0 ) ; // Reset address
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED ;
2012-08-04 12:20:47 +02:00
Fail :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n BTD Init Failed, error code: " ) , 0x80 ) ;
2013-03-30 15:29:16 +01:00
NotifyFail ( rcode ) ;
2013-05-16 22:43:51 +02:00
# endif
2013-03-28 09:37:09 +01:00
Release ( ) ;
return rcode ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2013-12-01 16:02:23 +01:00
void BTD : : Initialize ( ) {
2013-10-07 00:47:53 +02:00
uint8_t i ;
2013-12-25 11:09:57 +01:00
for ( i = 0 ; i < BTD_MAX_ENDPOINTS ; i + + ) {
2013-10-07 00:47:53 +02:00
epInfo [ i ] . epAddr = 0 ;
epInfo [ i ] . maxPktSize = ( i ) ? 0 : 8 ;
2015-11-18 00:11:33 +01:00
epInfo [ i ] . bmSndToggle = 0 ;
epInfo [ i ] . bmRcvToggle = 0 ;
2013-10-07 00:47:53 +02:00
epInfo [ i ] . bmNakPower = ( i ) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER ;
}
2014-01-12 16:31:47 +01:00
for ( i = 0 ; i < BTD_NUM_SERVICES ; i + + ) {
2013-12-25 11:09:57 +01:00
if ( btService [ i ] )
2013-10-07 00:47:53 +02:00
btService [ i ] - > Reset ( ) ; // Reset all Bluetooth services
}
connectToWii = false ;
2013-10-08 18:52:37 +02:00
incomingWii = false ;
2013-11-24 21:55:15 +01:00
connectToHIDDevice = false ;
incomingHIDDevice = false ;
2021-01-17 23:34:31 +01:00
incomingPSController = false ;
2013-10-07 00:47:53 +02:00
bAddress = 0 ; // Clear device address
bNumEP = 1 ; // Must have to be reset to 1
qNextPollTime = 0 ; // Reset next poll time
pollInterval = 0 ;
bPollEnable = false ; // Don't start polling before dongle is connected
2019-07-03 00:30:18 +02:00
simple_pairing_supported = false ;
2013-10-07 00:47:53 +02:00
}
2012-08-04 12:20:47 +02:00
/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */
2017-12-01 16:43:31 +01:00
void BTD : : EndpointXtract ( uint8_t conf , uint8_t iface __attribute__ ( ( unused ) ) , uint8_t alt , uint8_t proto __attribute__ ( ( unused ) ) , const USB_ENDPOINT_DESCRIPTOR * pep ) {
2013-03-28 09:37:09 +01:00
//ErrorMessage<uint8_t>(PSTR("Conf.Val"),conf);
//ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
//ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt);
2013-12-25 11:09:57 +01:00
if ( alt ) // Wrong interface - by BT spec, no alt setting
2013-03-28 09:37:09 +01:00
return ;
bConfNum = conf ;
uint8_t index ;
2017-09-05 05:37:32 +02:00
if ( ( pep - > bmAttributes & bmUSB_TRANSFER_TYPE ) = = USB_TRANSFER_TYPE_INTERRUPT & & ( pep - > bEndpointAddress & 0x80 ) = = 0x80 ) { // Interrupt In endpoint found
2013-03-28 09:37:09 +01:00
index = BTD_EVENT_PIPE ;
2013-06-12 05:11:43 +02:00
epInfo [ index ] . bmNakPower = USB_NAK_NOWAIT ;
2017-09-05 05:37:32 +02:00
} else if ( ( pep - > bmAttributes & bmUSB_TRANSFER_TYPE ) = = USB_TRANSFER_TYPE_BULK ) // Bulk endpoint found
index = ( ( pep - > bEndpointAddress & 0x80 ) = = 0x80 ) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE ;
else
return ;
2013-03-28 09:37:09 +01:00
// Fill the rest of endpoint data structure
epInfo [ index ] . epAddr = ( pep - > bEndpointAddress & 0x0F ) ;
epInfo [ index ] . maxPktSize = ( uint8_t ) pep - > wMaxPacketSize ;
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:37:09 +01:00
PrintEndpointDescriptor ( pep ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-12-25 11:09:57 +01:00
if ( pollInterval < pep - > bInterval ) // Set the polling interval as the largest polling interval obtained from endpoints
2013-03-28 09:37:09 +01:00
pollInterval = pep - > bInterval ;
bNumEP + + ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2017-12-01 16:43:31 +01:00
void BTD : : PrintEndpointDescriptor ( const USB_ENDPOINT_DESCRIPTOR * ep_ptr __attribute__ ( ( unused ) ) ) {
2013-01-19 15:43:28 +01:00
# ifdef EXTRADEBUG
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Endpoint descriptor: " ) , 0x80 ) ;
Notify ( PSTR ( " \r \n Length: \t \t " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( ep_ptr - > bLength , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Type: \t \t " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( ep_ptr - > bDescriptorType , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Address: \t " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( ep_ptr - > bEndpointAddress , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Attributes: \t " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( ep_ptr - > bmAttributes , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n MaxPktSize: \t " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint16_t > ( ep_ptr - > wMaxPacketSize , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Poll Intrv: \t " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( ep_ptr - > bInterval , 0x80 ) ;
2013-01-19 15:43:28 +01:00
# endif
2012-08-04 12:20:47 +02:00
}
/* Performs a cleanup after failed Init() attempt */
uint8_t BTD : : Release ( ) {
2013-12-01 16:02:23 +01:00
Initialize ( ) ; // Set all variables, endpoint structs etc. to default values
2013-03-28 09:37:09 +01:00
pUsb - > GetAddressPool ( ) . FreeAddress ( bAddress ) ;
return 0 ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
uint8_t BTD : : Poll ( ) {
2013-12-25 11:09:57 +01:00
if ( ! bPollEnable )
2013-03-28 09:37:09 +01:00
return 0 ;
2017-02-12 16:58:14 +01:00
if ( ( int32_t ) ( ( uint32_t ) millis ( ) - qNextPollTime ) > = 0L ) { // Don't poll if shorter than polling interval
qNextPollTime = ( uint32_t ) millis ( ) + pollInterval ; // Set new poll time
2013-12-11 11:56:05 +01:00
HCI_event_task ( ) ; // Poll the HCI event pipe
HCI_task ( ) ; // HCI state machine
ACL_event_task ( ) ; // Poll the ACL input pipe too
2013-03-28 09:37:09 +01:00
}
return 0 ;
2012-08-04 12:20:47 +02:00
}
2014-09-10 01:32:46 +02:00
void BTD : : disconnect ( ) {
for ( uint8_t i = 0 ; i < BTD_NUM_SERVICES ; i + + )
if ( btService [ i ] )
btService [ i ] - > disconnect ( ) ;
} ;
2012-08-04 12:20:47 +02:00
void BTD : : HCI_event_task ( ) {
2013-12-11 11:56:05 +01:00
uint16_t length = BULK_MAXPKTSIZE ; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
2015-07-12 19:17:12 +02:00
uint8_t rcode = pUsb - > inTransfer ( bAddress , epInfo [ BTD_EVENT_PIPE ] . epAddr , & length , hcibuf , pollInterval ) ; // Input on endpoint 1
2013-12-11 11:56:05 +01:00
2013-12-25 11:09:57 +01:00
if ( ! rcode | | rcode = = hrNAK ) { // Check for errors
switch ( hcibuf [ 0 ] ) { // Switch on event type
2013-03-28 09:37:09 +01:00
case EV_COMMAND_COMPLETE :
2013-12-25 11:09:57 +01:00
if ( ! hcibuf [ 5 ] ) { // Check if command succeeded
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_CMD_COMPLETE ) ; // Set command complete flag
2013-12-25 11:09:57 +01:00
if ( ( hcibuf [ 3 ] = = 0x01 ) & & ( hcibuf [ 4 ] = = 0x10 ) ) { // Parameters from read local version information
2013-03-28 09:37:09 +01:00
hci_version = hcibuf [ 6 ] ; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm
2019-06-30 20:44:12 +02:00
# ifdef EXTRADEBUG
if ( ! hci_check_flag ( HCI_FLAG_READ_VERSION ) ) {
Notify ( PSTR ( " \r \n HCI version: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hci_version , 0x80 ) ;
}
# endif
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_READ_VERSION ) ;
2019-06-30 20:44:12 +02:00
} else if ( ( hcibuf [ 3 ] = = 0x04 ) & & ( hcibuf [ 4 ] = = 0x10 ) ) { // Parameters from read local extended features
if ( ! hci_check_flag ( HCI_FLAG_LOCAL_EXTENDED_FEATURES ) ) {
# ifdef EXTRADEBUG
Notify ( PSTR ( " \r \n Page number: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 6 ] , 0x80 ) ;
Notify ( PSTR ( " \r \n Maximum page number: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 7 ] , 0x80 ) ;
Notify ( PSTR ( " \r \n Extended LMP features: " ) , 0x80 ) ;
for ( uint8_t i = 0 ; i < 8 ; i + + ) {
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 8 + i ] , 0x80 ) ;
}
# endif
if ( hcibuf [ 6 ] = = 0 ) { // Page 0
2019-08-31 18:22:21 +02:00
# ifdef DEBUG_USB_HOST
2019-07-02 20:30:33 +02:00
Notify ( PSTR ( " \r \n Dongle " ) , 0x80 ) ;
2019-08-31 18:22:21 +02:00
# endif
2019-07-03 00:30:18 +02:00
if ( hcibuf [ 8 + 6 ] & ( 1U < < 3 ) ) {
simple_pairing_supported = true ;
2019-08-31 18:22:21 +02:00
# ifdef DEBUG_USB_HOST
2019-06-30 20:44:12 +02:00
Notify ( PSTR ( " supports " ) , 0x80 ) ;
2019-08-31 18:22:21 +02:00
# endif
2019-07-03 00:30:18 +02:00
} else {
simple_pairing_supported = false ;
2019-08-31 18:22:21 +02:00
# ifdef DEBUG_USB_HOST
2019-06-30 20:44:12 +02:00
Notify ( PSTR ( " does NOT support " ) , 0x80 ) ;
2019-08-31 18:22:21 +02:00
# endif
2019-07-03 00:30:18 +02:00
}
2019-08-31 18:22:21 +02:00
# ifdef DEBUG_USB_HOST
2019-07-02 20:30:33 +02:00
Notify ( PSTR ( " secure simple pairing (controller support) " ) , 0x80 ) ;
2019-08-31 18:22:21 +02:00
# endif
2019-06-30 20:44:12 +02:00
} else if ( hcibuf [ 6 ] = = 1 ) { // Page 1
2019-08-31 18:22:21 +02:00
# ifdef DEBUG_USB_HOST
2019-07-02 20:30:33 +02:00
Notify ( PSTR ( " \r \n Dongle " ) , 0x80 ) ;
2019-06-30 20:44:12 +02:00
if ( hcibuf [ 8 + 0 ] & ( 1U < < 0 ) )
Notify ( PSTR ( " supports " ) , 0x80 ) ;
else
Notify ( PSTR ( " does NOT support " ) , 0x80 ) ;
2019-07-02 20:30:33 +02:00
Notify ( PSTR ( " secure simple pairing (host support) " ) , 0x80 ) ;
2019-06-30 20:44:12 +02:00
# endif
2019-08-31 18:22:21 +02:00
}
2019-06-30 20:44:12 +02:00
}
hci_set_flag ( HCI_FLAG_LOCAL_EXTENDED_FEATURES ) ;
2013-12-25 11:09:57 +01:00
} else if ( ( hcibuf [ 3 ] = = 0x09 ) & & ( hcibuf [ 4 ] = = 0x10 ) ) { // Parameters from read local bluetooth address
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-03-28 09:37:09 +01:00
my_bdaddr [ i ] = hcibuf [ 6 + i ] ;
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_READ_BDADDR ) ;
2013-03-28 09:37:09 +01:00
}
}
break ;
case EV_COMMAND_STATUS :
2013-12-25 11:09:57 +01:00
if ( hcibuf [ 2 ] ) { // Show status on serial if not OK
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n HCI Command Failed: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( hcibuf [ 2 ] , 0x80 ) ;
2019-07-03 00:54:27 +02:00
Notify ( PSTR ( " \r \n Num HCI Command Packets: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 3 ] , 0x80 ) ;
Notify ( PSTR ( " \r \n Command Opcode: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 4 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 5 ] , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
}
break ;
case EV_INQUIRY_COMPLETE :
2013-12-25 11:09:57 +01:00
if ( inquiry_counter > = 5 & & ( pairWithWii | | pairWithHIDDevice ) ) {
2013-03-28 09:37:09 +01:00
inquiry_counter = 0 ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Couldn't find Wiimote " ) , 0x80 ) ;
else
Notify ( PSTR ( " \r \n Couldn't find HID device " ) , 0x80 ) ;
2012-10-08 15:32:42 +02:00
# endif
2013-03-28 09:37:09 +01:00
connectToWii = false ;
pairWithWii = false ;
2013-11-24 21:55:15 +01:00
connectToHIDDevice = false ;
pairWithHIDDevice = false ;
2013-03-28 09:37:09 +01:00
hci_state = HCI_SCANNING_STATE ;
}
inquiry_counter + + ;
break ;
case EV_INQUIRY_RESULT :
2021-12-19 18:41:04 +01:00
case EV_EXTENDED_INQUIRY_RESULT :
2013-12-25 11:09:57 +01:00
if ( hcibuf [ 2 ] ) { // Check that there is more than zero responses
2019-07-03 00:30:18 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Number of responses: " ) , 0x80 ) ;
2021-12-19 18:41:04 +01:00
Notify ( hcibuf [ 2 ] , 0x80 ) ; // This will always be 1 for an extended inquiry result
2012-08-21 14:31:11 +02:00
# endif
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < hcibuf [ 2 ] ; i + + ) {
2021-12-19 18:41:04 +01:00
uint8_t classOfDevice_offset ;
if ( hcibuf [ 0 ] = = EV_INQUIRY_RESULT )
classOfDevice_offset = 9 * hcibuf [ 2 ] ; // 6-byte bd_addr, 1 byte page_scan_repetition_mode, 2 byte reserved
else
classOfDevice_offset = 8 * hcibuf [ 2 ] ; // 6-byte bd_addr, 1 byte page_scan_repetition_mode, 1 byte reserved
2013-11-24 21:55:15 +01:00
2013-12-25 11:09:57 +01:00
for ( uint8_t j = 0 ; j < 3 ; j + + )
2021-12-19 18:41:04 +01:00
classOfDevice [ j ] = hcibuf [ 3 + classOfDevice_offset + 3 * i + j ] ;
2013-11-24 21:55:15 +01:00
2019-07-03 00:30:18 +02:00
# ifdef EXTRADEBUG
2015-04-16 01:57:00 +02:00
Notify ( PSTR ( " \r \n Class of device: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( classOfDevice [ 2 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( classOfDevice [ 1 ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( classOfDevice [ 0 ] , 0x80 ) ;
# endif
2021-10-08 18:18:16 +02:00
if ( pairWithWii & & ( classOfDevice [ 2 ] = = 0x00 ) & & ( ( classOfDevice [ 1 ] & 0x0F ) = = 0x05 ) & & ( classOfDevice [ 0 ] & 0x0C ) ) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
2015-04-16 01:57:00 +02:00
checkRemoteName = true ; // Check remote name to distinguish between the different controllers
2013-11-24 21:55:15 +01:00
2013-12-25 11:09:57 +01:00
for ( uint8_t j = 0 ; j < 6 ; j + + )
2021-12-19 18:41:04 +01:00
disc_bdaddr [ j ] = hcibuf [ 3 + 6 * i + j ] ;
2013-11-24 21:55:15 +01:00
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_DEVICE_FOUND ) ;
2013-03-28 09:37:09 +01:00
break ;
2021-10-08 17:41:48 +02:00
} else if ( pairWithHIDDevice & & ( ( classOfDevice [ 1 ] & 0x0F ) = = 0x05 ) & & ( classOfDevice [ 0 ] & 0xC8 ) ) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
2019-06-30 20:44:12 +02:00
checkRemoteName = true ; // Used to print name in the serial monitor if serial debugging is enabled
2013-12-25 11:09:57 +01:00
if ( classOfDevice [ 0 ] & 0x80 )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Mouse found " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
if ( classOfDevice [ 0 ] & 0x40 )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Keyboard found " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
if ( classOfDevice [ 0 ] & 0x08 )
Notify ( PSTR ( " \r \n Gamepad found " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
# endif
2013-12-25 11:09:57 +01:00
for ( uint8_t j = 0 ; j < 6 ; j + + )
2021-12-19 18:41:04 +01:00
disc_bdaddr [ j ] = hcibuf [ 3 + 6 * i + j ] ;
2013-11-24 21:55:15 +01:00
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_DEVICE_FOUND ) ;
2014-07-01 13:22:44 +02:00
break ;
2013-03-28 09:37:09 +01:00
}
}
}
break ;
case EV_CONNECT_COMPLETE :
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_CONNECT_EVENT ) ;
2013-12-25 11:09:57 +01:00
if ( ! hcibuf [ 2 ] ) { // Check if connected OK
2013-11-15 23:31:05 +01:00
# ifdef EXTRADEBUG
Notify ( PSTR ( " \r \n Connection established " ) , 0x80 ) ;
# endif
2013-12-11 10:06:40 +01:00
hci_handle = hcibuf [ 3 ] | ( ( hcibuf [ 4 ] & 0x0F ) < < 8 ) ; // Store the handle for the ACL connection
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_CONNECT_COMPLETE ) ; // Set connection complete flag
2013-11-12 19:38:18 +01:00
} else {
2013-11-24 21:55:15 +01:00
hci_state = HCI_CHECK_DEVICE_SERVICE ;
2013-11-12 19:38:18 +01:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Connection Failed: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 2 ] , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-11-12 19:38:18 +01:00
}
2013-03-28 09:37:09 +01:00
break ;
case EV_DISCONNECT_COMPLETE :
2013-12-25 11:09:57 +01:00
if ( ! hcibuf [ 2 ] ) { // Check if disconnected OK
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_DISCONNECT_COMPLETE ) ; // Set disconnect command complete flag
hci_clear_flag ( HCI_FLAG_CONNECT_COMPLETE ) ; // Clear connection complete flag
2013-03-28 09:37:09 +01:00
}
break ;
case EV_REMOTE_NAME_COMPLETE :
2013-12-25 11:09:57 +01:00
if ( ! hcibuf [ 2 ] ) { // Check if reading is OK
for ( uint8_t i = 0 ; i < min ( sizeof ( remote_name ) , sizeof ( hcibuf ) - 9 ) ; i + + ) {
2013-04-01 03:06:49 +02:00
remote_name [ i ] = hcibuf [ 9 + i ] ;
2013-12-25 11:09:57 +01:00
if ( remote_name [ i ] = = ' \0 ' ) // End of string
2013-12-11 10:10:12 +01:00
break ;
}
2019-06-30 20:44:12 +02:00
// TODO: Always set '\0' in remote name!
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_REMOTE_NAME_COMPLETE ) ;
2013-03-28 09:37:09 +01:00
}
break ;
case EV_INCOMING_CONNECT :
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-11-24 21:55:15 +01:00
disc_bdaddr [ i ] = hcibuf [ i + 2 ] ;
2014-01-10 17:44:51 +01:00
for ( uint8_t i = 0 ; i < 3 ; i + + )
classOfDevice [ i ] = hcibuf [ i + 8 ] ;
2021-10-08 17:41:48 +02:00
if ( ( ( classOfDevice [ 1 ] & 0x0F ) = = 0x05 ) & & ( classOfDevice [ 0 ] & 0xC8 ) ) { // Check if it is a mouse, keyboard or a gamepad
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
2014-01-10 17:44:51 +01:00
if ( classOfDevice [ 0 ] & 0x80 )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Mouse is connecting " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
if ( classOfDevice [ 0 ] & 0x40 )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Keyboard is connecting " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
if ( classOfDevice [ 0 ] & 0x08 )
Notify ( PSTR ( " \r \n Gamepad is connecting " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
# endif
incomingHIDDevice = true ;
}
2013-04-01 03:06:49 +02:00
# ifdef EXTRADEBUG
Notify ( PSTR ( " \r \n Class of device: " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
D_PrintHex < uint8_t > ( classOfDevice [ 2 ] , 0x80 ) ;
2013-04-01 03:06:49 +02:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
D_PrintHex < uint8_t > ( classOfDevice [ 1 ] , 0x80 ) ;
2013-04-01 03:06:49 +02:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
D_PrintHex < uint8_t > ( classOfDevice [ 0 ] , 0x80 ) ;
2013-04-01 03:06:49 +02:00
# endif
2013-12-11 10:37:18 +01:00
hci_set_flag ( HCI_FLAG_INCOMING_REQUEST ) ;
2013-03-28 09:37:09 +01:00
break ;
case EV_PIN_CODE_REQUEST :
2013-12-25 11:09:57 +01:00
if ( pairWithWii ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2015-04-16 01:57:00 +02:00
Notify ( PSTR ( " \r \n Pairing with Wiimote " ) , 0x80 ) ;
2012-10-07 14:50:51 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_pin_code_request_reply ( ) ;
2013-12-25 11:09:57 +01:00
} else if ( btdPin ! = NULL ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Bluetooth pin is set too: " ) , 0x80 ) ;
2013-04-26 23:50:39 +02:00
NotifyStr ( btdPin , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_pin_code_request_reply ( ) ;
} else {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n No pin was set " ) , 0x80 ) ;
2012-08-09 20:22:11 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_pin_code_negative_request_reply ( ) ;
}
break ;
case EV_LINK_KEY_REQUEST :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Received Key Request " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_link_key_request_negative_reply ( ) ;
break ;
case EV_AUTHENTICATION_COMPLETE :
2016-04-19 11:48:51 +02:00
if ( ! hcibuf [ 2 ] ) { // Check if pairing was successful
2016-02-09 12:10:12 +01:00
if ( pairWithWii & & ! connectToWii ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2016-02-09 12:10:12 +01:00
Notify ( PSTR ( " \r \n Pairing successful with Wiimote " ) , 0x80 ) ;
2012-10-07 14:50:51 +02:00
# endif
2016-02-09 12:10:12 +01:00
connectToWii = true ; // Used to indicate to the Wii service, that it should connect to this device
} else if ( pairWithHIDDevice & & ! connectToHIDDevice ) {
2013-11-24 21:55:15 +01:00
# ifdef DEBUG_USB_HOST
2016-02-09 12:10:12 +01:00
Notify ( PSTR ( " \r \n Pairing successful with HID device " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
# endif
2016-02-09 12:10:12 +01:00
connectToHIDDevice = true ; // Used to indicate to the BTHID service, that it should connect to this device
2019-08-31 18:22:21 +02:00
} else {
2020-11-15 19:02:54 +01:00
# ifdef EXTRADEBUG
2019-08-31 18:22:21 +02:00
Notify ( PSTR ( " \r \n Pairing was successful " ) , 0x80 ) ;
# endif
2016-02-09 12:10:12 +01:00
}
} else {
# ifdef DEBUG_USB_HOST
2016-04-19 11:48:51 +02:00
Notify ( PSTR ( " \r \n Pairing Failed: " ) , 0x80 ) ;
2016-02-09 12:10:12 +01:00
D_PrintHex < uint8_t > ( hcibuf [ 2 ] , 0x80 ) ;
# endif
hci_disconnect ( hci_handle ) ;
hci_state = HCI_DISCONNECT_STATE ;
2013-03-28 09:37:09 +01:00
}
break ;
2019-06-30 20:44:12 +02:00
2020-11-15 17:29:54 +01:00
case EV_IO_CAPABILITY_REQUEST :
2019-06-30 20:44:12 +02:00
# ifdef DEBUG_USB_HOST
2020-11-15 17:29:54 +01:00
Notify ( PSTR ( " \r \n Received IO Capability Request " ) , 0x80 ) ;
2019-06-30 20:44:12 +02:00
# endif
2020-11-15 17:29:54 +01:00
hci_io_capability_request_reply ( ) ;
break ;
case EV_IO_CAPABILITY_RESPONSE :
# ifdef EXTRADEBUG
Notify ( PSTR ( " \r \n Received IO Capability Response: " ) , 0x80 ) ;
Notify ( PSTR ( " \r \n IO capability: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 8 ] , 0x80 ) ;
Notify ( PSTR ( " \r \n OOB data present: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 9 ] , 0x80 ) ;
Notify ( PSTR ( " \r \n Authentication request: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 10 ] , 0x80 ) ;
2019-06-30 20:44:12 +02:00
# endif
break ;
case EV_USER_CONFIRMATION_REQUEST :
# ifdef DEBUG_USB_HOST
2020-11-15 17:29:54 +01:00
Notify ( PSTR ( " \r \n User confirmation Request " ) , 0x80 ) ;
2019-06-30 20:44:12 +02:00
# ifdef EXTRADEBUG
2020-11-15 17:29:54 +01:00
Notify ( PSTR ( " : \r \n Numeric value: " ) , 0x80 ) ;
2019-06-30 20:44:12 +02:00
for ( uint8_t i = 0 ; i < 4 ; i + + ) {
Notify ( PSTR ( " " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 8 + i ] , 0x80 ) ;
}
# endif
2020-11-15 17:29:54 +01:00
# endif
// Simply confirm the connection, as the host has no "NoInputNoOutput" capabilities
2019-06-30 20:44:12 +02:00
hci_user_confirmation_request_reply ( ) ;
2020-11-15 17:29:54 +01:00
break ;
case EV_SIMPLE_PAIRING_COMPLETE :
# ifdef EXTRADEBUG
if ( ! hcibuf [ 2 ] ) { // Check if connected OK
Notify ( PSTR ( " \r \n Simple Pairing succeeded " ) , 0x80 ) ;
} else {
Notify ( PSTR ( " \r \n Simple Pairing failed: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 2 ] , 0x80 ) ;
}
# endif
2019-06-30 20:44:12 +02:00
break ;
2013-03-28 09:37:09 +01:00
/* We will just ignore the following events */
2019-06-30 20:44:12 +02:00
case EV_MAX_SLOTS_CHANGE :
2013-03-28 09:37:09 +01:00
case EV_NUM_COMPLETE_PKT :
2019-07-03 00:30:18 +02:00
break ;
2013-03-28 09:37:09 +01:00
case EV_ROLE_CHANGED :
case EV_PAGE_SCAN_REP_MODE :
case EV_LOOPBACK_COMMAND :
case EV_DATA_BUFFER_OVERFLOW :
case EV_CHANGE_CONNECTION_LINK :
case EV_QOS_SETUP_COMPLETE :
case EV_LINK_KEY_NOTIFICATION :
case EV_ENCRYPTION_CHANGE :
case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE :
2019-06-30 20:44:12 +02:00
# ifdef EXTRADEBUG
if ( hcibuf [ 0 ] ! = 0x00 ) {
Notify ( PSTR ( " \r \n Ignore HCI Event: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( hcibuf [ 0 ] , 0x80 ) ;
}
# endif
2013-03-28 09:37:09 +01:00
break ;
2012-10-07 15:22:29 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:37:09 +01:00
default :
2013-12-25 11:09:57 +01:00
if ( hcibuf [ 0 ] ! = 0x00 ) {
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Unmanaged HCI Event: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( hcibuf [ 0 ] , 0x80 ) ;
2019-08-31 18:22:21 +02:00
Notify ( PSTR ( " , data: " ) , 0x80 ) ;
for ( uint16_t i = 0 ; i < hcibuf [ 1 ] ; i + + ) {
D_PrintHex < uint8_t > ( hcibuf [ 2 + i ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
}
2013-03-28 09:37:09 +01:00
}
break ;
2012-08-04 12:20:47 +02:00
# endif
2013-12-11 10:06:40 +01:00
} // Switch
2013-03-28 09:37:09 +01:00
}
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-08-02 14:24:06 +02:00
else {
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n HCI event error: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rcode , 0x80 ) ;
2013-03-28 09:37:09 +01:00
}
2012-08-09 21:22:55 +02:00
# endif
2012-08-04 12:20:47 +02:00
}
/* Poll Bluetooth and print result */
void BTD : : HCI_task ( ) {
2013-12-25 11:09:57 +01:00
switch ( hci_state ) {
2013-03-28 09:37:09 +01:00
case HCI_INIT_STATE :
hci_counter + + ;
2013-12-25 11:09:57 +01:00
if ( hci_counter > hci_num_reset_loops ) { // wait until we have looped x times to clear any old events
2013-03-28 09:37:09 +01:00
hci_reset ( ) ;
hci_state = HCI_RESET_STATE ;
hci_counter = 0 ;
}
break ;
case HCI_RESET_STATE :
hci_counter + + ;
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_CMD_COMPLETE ) ) {
2013-03-28 09:37:09 +01:00
hci_counter = 0 ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n HCI Reset complete " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_state = HCI_CLASS_STATE ;
hci_write_class_of_device ( ) ;
2013-12-25 11:09:57 +01:00
} else if ( hci_counter > hci_num_reset_loops ) {
2013-03-28 09:37:09 +01:00
hci_num_reset_loops * = 10 ;
2013-12-25 11:09:57 +01:00
if ( hci_num_reset_loops > 2000 )
2013-03-28 09:37:09 +01:00
hci_num_reset_loops = 2000 ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n No response to HCI Reset " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_state = HCI_INIT_STATE ;
hci_counter = 0 ;
}
break ;
2013-03-14 23:40:52 +01:00
2013-03-28 09:37:09 +01:00
case HCI_CLASS_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_CMD_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Write class of device " ) , 0x80 ) ;
2013-03-14 23:40:52 +01:00
# endif
2013-03-28 09:37:09 +01:00
hci_state = HCI_BDADDR_STATE ;
hci_read_bdaddr ( ) ;
}
break ;
case HCI_BDADDR_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_READ_BDADDR ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Local Bluetooth Address: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( int8_t i = 5 ; i > 0 ; i - - ) {
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( my_bdaddr [ i ] , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " : " ) , 0x80 ) ;
}
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( my_bdaddr [ 0 ] , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_read_local_version_information ( ) ;
hci_state = HCI_LOCAL_VERSION_STATE ;
}
break ;
case HCI_LOCAL_VERSION_STATE : // The local version is used by the PS3BT class
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_READ_VERSION ) ) {
2019-07-03 00:30:18 +02:00
if ( btdName ! = NULL ) {
hci_write_local_name ( btdName ) ;
hci_state = HCI_WRITE_NAME_STATE ;
2020-11-15 19:02:54 +01:00
} else if ( useSimplePairing ) {
2019-07-03 00:30:18 +02:00
hci_read_local_extended_features ( 0 ) ; // "Requests the normal LMP features as returned by Read_Local_Supported_Features"
//hci_read_local_extended_features(1); // Read page 1
hci_state = HCI_LOCAL_EXTENDED_FEATURES_STATE ;
2020-11-15 19:02:54 +01:00
} else
hci_state = HCI_CHECK_DEVICE_SERVICE ;
2019-07-03 00:30:18 +02:00
}
break ;
case HCI_WRITE_NAME_STATE :
if ( hci_check_flag ( HCI_FLAG_CMD_COMPLETE ) ) {
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n The name was set to: " ) , 0x80 ) ;
NotifyStr ( btdName , 0x80 ) ;
# endif
2020-11-15 19:02:54 +01:00
if ( useSimplePairing ) {
hci_read_local_extended_features ( 0 ) ; // "Requests the normal LMP features as returned by Read_Local_Supported_Features"
//hci_read_local_extended_features(1); // Read page 1
hci_state = HCI_LOCAL_EXTENDED_FEATURES_STATE ;
} else
hci_state = HCI_CHECK_DEVICE_SERVICE ;
2019-06-30 20:44:12 +02:00
}
break ;
case HCI_LOCAL_EXTENDED_FEATURES_STATE :
if ( hci_check_flag ( HCI_FLAG_LOCAL_EXTENDED_FEATURES ) ) {
2019-07-03 00:30:18 +02:00
if ( simple_pairing_supported ) {
hci_write_simple_pairing_mode ( true ) ;
hci_state = HCI_WRITE_SIMPLE_PAIRING_STATE ;
2013-03-28 09:37:09 +01:00
} else
2013-11-24 21:55:15 +01:00
hci_state = HCI_CHECK_DEVICE_SERVICE ;
2013-03-28 09:37:09 +01:00
}
break ;
2019-07-03 00:30:18 +02:00
case HCI_WRITE_SIMPLE_PAIRING_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_CMD_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2019-07-03 00:30:18 +02:00
Notify ( PSTR ( " \r \n Simple pairing was enabled " ) , 0x80 ) ;
2020-11-15 17:29:54 +01:00
# endif
hci_set_event_mask ( ) ;
hci_state = HCI_SET_EVENT_MASK_STATE ;
}
break ;
case HCI_SET_EVENT_MASK_STATE :
if ( hci_check_flag ( HCI_FLAG_CMD_COMPLETE ) ) {
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Set event mask completed " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-11-24 21:55:15 +01:00
hci_state = HCI_CHECK_DEVICE_SERVICE ;
2013-03-28 09:37:09 +01:00
}
break ;
2013-11-24 21:55:15 +01:00
case HCI_CHECK_DEVICE_SERVICE :
2013-12-25 11:09:57 +01:00
if ( pairWithHIDDevice | | pairWithWii ) { // Check if it should try to connect to a Wiimote
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2015-04-16 02:34:27 +02:00
Notify ( PSTR ( " \r \n Starting inquiry \r \n Press 1 & 2 on the Wiimote \r \n Or press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
else
Notify ( PSTR ( " \r \n Please enable discovery of your device " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
hci_inquiry ( ) ;
hci_state = HCI_INQUIRY_STATE ;
} else
hci_state = HCI_SCANNING_STATE ; // Don't try to connect to a Wiimote
break ;
case HCI_INQUIRY_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_DEVICE_FOUND ) ) {
2013-03-28 09:37:09 +01:00
hci_inquiry_cancel ( ) ; // Stop inquiry
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Wiimote found " ) , 0x80 ) ;
else
Notify ( PSTR ( " \r \n HID device found " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Now just create the instance like so: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n WII Wii(&Btd); " ) , 0x80 ) ;
else
2014-03-18 18:37:36 +01:00
Notify ( PSTR ( " \r \n BTHID bthid(&Btd); " ) , 0x80 ) ;
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n And then press any button on the " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " Wiimote " ) , 0x80 ) ;
else
Notify ( PSTR ( " device " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2015-04-16 01:57:00 +02:00
if ( checkRemoteName ) {
hci_remote_name ( ) ; // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board
2013-03-28 09:37:09 +01:00
hci_state = HCI_REMOTE_NAME_STATE ;
} else
2013-11-24 21:55:15 +01:00
hci_state = HCI_CONNECT_DEVICE_STATE ;
2013-03-28 09:37:09 +01:00
}
break ;
2013-11-24 21:55:15 +01:00
case HCI_CONNECT_DEVICE_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_CMD_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Connecting to Wiimote " ) , 0x80 ) ;
else
Notify ( PSTR ( " \r \n Connecting to HID device " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2015-04-16 01:57:00 +02:00
checkRemoteName = false ;
2013-03-28 09:37:09 +01:00
hci_connect ( ) ;
2013-11-24 21:55:15 +01:00
hci_state = HCI_CONNECTED_DEVICE_STATE ;
2013-03-28 09:37:09 +01:00
}
break ;
2013-11-24 21:55:15 +01:00
case HCI_CONNECTED_DEVICE_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_CONNECT_EVENT ) ) {
if ( hci_check_flag ( HCI_FLAG_CONNECT_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( pairWithWii )
2013-11-24 21:55:15 +01:00
Notify ( PSTR ( " \r \n Connected to Wiimote " ) , 0x80 ) ;
else
Notify ( PSTR ( " \r \n Connected to HID device " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2020-11-15 17:29:54 +01:00
hci_authentication_request ( ) ; // This will start the pairing with the device
hci_state = HCI_SCANNING_STATE ;
2013-03-28 09:37:09 +01:00
} else {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Trying to connect one more time... " ) , 0x80 ) ;
# endif
hci_connect ( ) ; // Try to connect one more time
}
}
break ;
case HCI_SCANNING_STATE :
2013-12-25 11:09:57 +01:00
if ( ! connectToWii & & ! pairWithWii & & ! connectToHIDDevice & & ! pairWithHIDDevice ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Wait For Incoming Connection Request " ) , 0x80 ) ;
# endif
hci_write_scan_enable ( ) ;
2017-02-07 15:27:00 +01:00
waitingForConnection = true ;
2013-03-28 09:37:09 +01:00
hci_state = HCI_CONNECT_IN_STATE ;
}
break ;
case HCI_CONNECT_IN_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_INCOMING_REQUEST ) ) {
2017-02-07 15:27:00 +01:00
waitingForConnection = false ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Incoming Connection Request " ) , 0x80 ) ;
# endif
hci_remote_name ( ) ;
hci_state = HCI_REMOTE_NAME_STATE ;
2013-12-25 11:09:57 +01:00
} else if ( hci_check_flag ( HCI_FLAG_DISCONNECT_COMPLETE ) )
2013-03-28 09:37:09 +01:00
hci_state = HCI_DISCONNECT_STATE ;
2012-08-04 12:20:47 +02:00
break ;
2013-03-28 09:37:09 +01:00
case HCI_REMOTE_NAME_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_REMOTE_NAME_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Remote Name: " ) , 0x80 ) ;
2014-01-16 18:56:42 +01:00
for ( uint8_t i = 0 ; i < strlen ( remote_name ) ; i + + )
2013-04-26 23:50:39 +02:00
Notifyc ( remote_name [ i ] , 0x80 ) ;
2013-02-02 22:14:01 +01:00
# endif
2013-12-25 11:09:57 +01:00
if ( strncmp ( ( const char * ) remote_name , " Nintendo " , 8 ) = = 0 ) {
2013-04-01 03:06:49 +02:00
incomingWii = true ;
2015-04-16 01:57:00 +02:00
motionPlusInside = false ;
wiiUProController = false ;
pairWiiUsingSync = false ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Wiimote is connecting " ) , 0x80 ) ;
2013-02-02 22:14:01 +01:00
# endif
2013-12-25 11:09:57 +01:00
if ( strncmp ( ( const char * ) remote_name , " Nintendo RVL-CNT-01-TR " , 22 ) = = 0 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " with Motion Plus Inside " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
motionPlusInside = true ;
2013-12-25 11:09:57 +01:00
} else if ( strncmp ( ( const char * ) remote_name , " Nintendo RVL-CNT-01-UC " , 22 ) = = 0 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " - Wii U Pro Controller " ) , 0x80 ) ;
2013-02-02 22:14:01 +01:00
# endif
2015-04-16 01:57:00 +02:00
wiiUProController = motionPlusInside = pairWiiUsingSync = true ;
} else if ( strncmp ( ( const char * ) remote_name , " Nintendo RVL-WBC-01 " , 19 ) = = 0 ) {
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " - Wii Balance Board " ) , 0x80 ) ;
# endif
pairWiiUsingSync = true ;
2013-03-28 09:37:09 +01:00
}
}
2014-01-10 17:44:51 +01:00
if ( classOfDevice [ 2 ] = = 0 & & classOfDevice [ 1 ] = = 0x25 & & classOfDevice [ 0 ] = = 0x08 & & strncmp ( ( const char * ) remote_name , " Wireless Controller " , 19 ) = = 0 ) {
# ifdef DEBUG_USB_HOST
2021-01-17 23:34:31 +01:00
Notify ( PSTR ( " \r \n PS4/PS5 controller is connecting " ) , 0x80 ) ;
2014-01-10 17:44:51 +01:00
# endif
2021-01-17 23:34:31 +01:00
incomingPSController = true ;
2014-01-10 17:44:51 +01:00
}
2019-06-30 20:44:12 +02:00
if ( ( pairWithWii | | pairWithHIDDevice ) & & checkRemoteName )
2013-11-24 21:55:15 +01:00
hci_state = HCI_CONNECT_DEVICE_STATE ;
2013-03-28 09:37:09 +01:00
else {
hci_accept_connection ( ) ;
hci_state = HCI_CONNECTED_STATE ;
}
}
break ;
case HCI_CONNECTED_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_CONNECT_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Connected to Device: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( int8_t i = 5 ; i > 0 ; i - - ) {
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( disc_bdaddr [ i ] , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " : " ) , 0x80 ) ;
}
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( disc_bdaddr [ 0 ] , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2021-01-17 23:34:31 +01:00
if ( incomingPSController )
connectToHIDDevice = true ; // We should always connect to the PS4/PS5 controller
2014-01-10 17:44:51 +01:00
2013-03-28 09:37:09 +01:00
// Clear these flags for a new connection
l2capConnectionClaimed = false ;
sdpConnectionClaimed = false ;
rfcommConnectionClaimed = false ;
hci_event_flag = 0 ;
hci_state = HCI_DONE_STATE ;
}
break ;
case HCI_DONE_STATE :
hci_counter + + ;
2013-12-25 11:09:57 +01:00
if ( hci_counter > 1000 ) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
2013-03-28 09:37:09 +01:00
hci_counter = 0 ;
hci_state = HCI_SCANNING_STATE ;
}
break ;
case HCI_DISCONNECT_STATE :
2013-12-25 11:09:57 +01:00
if ( hci_check_flag ( HCI_FLAG_DISCONNECT_COMPLETE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n HCI Disconnected from Device " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:37:09 +01:00
hci_event_flag = 0 ; // Clear all flags
// Reset all buffers
2013-12-11 10:06:40 +01:00
memset ( hcibuf , 0 , BULK_MAXPKTSIZE ) ;
memset ( l2capinbuf , 0 , BULK_MAXPKTSIZE ) ;
connectToWii = incomingWii = pairWithWii = false ;
2015-04-16 01:57:00 +02:00
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false ;
2021-01-17 23:34:31 +01:00
incomingPSController = false ;
2013-11-24 21:55:15 +01:00
2013-03-28 09:37:09 +01:00
hci_state = HCI_SCANNING_STATE ;
}
break ;
default :
break ;
}
2012-08-04 12:20:47 +02:00
}
void BTD : : ACL_event_task ( ) {
2013-12-11 11:56:05 +01:00
uint16_t length = BULK_MAXPKTSIZE ;
2015-07-12 19:17:12 +02:00
uint8_t rcode = pUsb - > inTransfer ( bAddress , epInfo [ BTD_DATAIN_PIPE ] . epAddr , & length , l2capinbuf , pollInterval ) ; // Input on endpoint 2
2013-12-11 11:56:05 +01:00
2013-12-25 11:09:57 +01:00
if ( ! rcode ) { // Check for errors
if ( length > 0 ) { // Check if any data was read
2014-01-12 16:31:47 +01:00
for ( uint8_t i = 0 ; i < BTD_NUM_SERVICES ; i + + ) {
2013-12-25 11:09:57 +01:00
if ( btService [ i ] )
2013-12-11 11:56:05 +01:00
btService [ i ] - > ACLData ( l2capinbuf ) ;
}
}
2013-03-28 09:37:09 +01:00
}
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-12-25 11:09:57 +01:00
else if ( rcode ! = hrNAK ) {
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n ACL data in error: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rcode , 0x80 ) ;
2013-03-28 09:37:09 +01:00
}
2012-08-09 21:22:55 +02:00
# endif
2014-01-12 16:31:47 +01:00
for ( uint8_t i = 0 ; i < BTD_NUM_SERVICES ; i + + )
2013-12-25 11:09:57 +01:00
if ( btService [ i ] )
2013-03-28 09:37:09 +01:00
btService [ i ] - > Run ( ) ;
2012-08-04 12:20:47 +02:00
}
/************************************************************/
/* HCI Commands */
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
/************************************************************/
void BTD : : HCI_Command ( uint8_t * data , uint16_t nbytes ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_CMD_COMPLETE ) ;
2013-03-28 09:37:09 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ BTD_CONTROL_PIPE ] . epAddr , bmREQ_HCI_OUT , 0x00 , 0x00 , 0x00 , 0x00 , nbytes , nbytes , data , NULL ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_reset ( ) {
2013-03-28 09:37:09 +01:00
hci_event_flag = 0 ; // Clear all the flags
hcibuf [ 0 ] = 0x03 ; // HCI OCF = 3
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = 0x00 ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 3 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_write_scan_enable ( ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_INCOMING_REQUEST ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x1A ; // HCI OCF = 1A
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = 0x01 ; // parameter length = 1
2013-12-25 11:09:57 +01:00
if ( btdName ! = NULL )
2013-03-28 09:37:09 +01:00
hcibuf [ 3 ] = 0x03 ; // Inquiry Scan enabled. Page Scan enabled.
else
hcibuf [ 3 ] = 0x02 ; // Inquiry Scan disabled. Page Scan enabled.
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 4 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_write_scan_disable ( ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x1A ; // HCI OCF = 1A
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = 0x01 ; // parameter length = 1
hcibuf [ 3 ] = 0x00 ; // Inquiry Scan disabled. Page Scan disabled.
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 4 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
void BTD : : hci_read_bdaddr ( ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_READ_BDADDR ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x09 ; // HCI OCF = 9
hcibuf [ 1 ] = 0x04 < < 2 ; // HCI OGF = 4
hcibuf [ 2 ] = 0x00 ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 3 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_read_local_version_information ( ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_READ_VERSION ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x01 ; // HCI OCF = 1
hcibuf [ 1 ] = 0x04 < < 2 ; // HCI OGF = 4
hcibuf [ 2 ] = 0x00 ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 3 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2019-06-30 20:44:12 +02:00
void BTD : : hci_read_local_extended_features ( uint8_t page_number ) {
hci_clear_flag ( HCI_FLAG_LOCAL_EXTENDED_FEATURES ) ;
hcibuf [ 0 ] = 0x04 ; // HCI OCF = 4
hcibuf [ 1 ] = 0x04 < < 2 ; // HCI OGF = 4
hcibuf [ 2 ] = 0x01 ; // parameter length = 1
hcibuf [ 3 ] = page_number ;
HCI_Command ( hcibuf , 4 ) ;
}
2012-08-04 12:20:47 +02:00
void BTD : : hci_accept_connection ( ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_CONNECT_COMPLETE ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x09 ; // HCI OCF = 9
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x07 ; // parameter length 7
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
2014-01-10 17:44:51 +01:00
hcibuf [ 9 ] = 0x00 ; // Switch role to master
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 10 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_remote_name ( ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_REMOTE_NAME_COMPLETE ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x19 ; // HCI OCF = 19
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x0A ; // parameter length = 10
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
2014-01-10 17:44:51 +01:00
hcibuf [ 9 ] = 0x01 ; // Page Scan Repetition Mode
hcibuf [ 10 ] = 0x00 ; // Reserved
hcibuf [ 11 ] = 0x00 ; // Clock offset - low byte
hcibuf [ 12 ] = 0x00 ; // Clock offset - high byte
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 13 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2019-07-02 20:30:33 +02:00
void BTD : : hci_write_local_name ( const char * name ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x13 ; // HCI OCF = 13
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = strlen ( name ) + 1 ; // parameter length = the length of the string + end byte
uint8_t i ;
2013-12-25 11:09:57 +01:00
for ( i = 0 ; i < strlen ( name ) ; i + + )
2013-03-28 09:37:09 +01:00
hcibuf [ i + 3 ] = name [ i ] ;
hcibuf [ i + 3 ] = 0x00 ; // End of string
HCI_Command ( hcibuf , 4 + strlen ( name ) ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2020-11-15 17:29:54 +01:00
void BTD : : hci_set_event_mask ( ) {
hcibuf [ 0 ] = 0x01 ; // HCI OCF = 01
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = 0x08 ;
// The first 6 bytes are the default of 1FFF FFFF FFFF
// However we need to set bits 48-55 for simple pairing to work
hcibuf [ 3 ] = 0xFF ;
hcibuf [ 4 ] = 0xFF ;
hcibuf [ 5 ] = 0xFF ;
hcibuf [ 6 ] = 0xFF ;
hcibuf [ 7 ] = 0xFF ;
hcibuf [ 8 ] = 0x1F ;
hcibuf [ 9 ] = 0xFF ; // Enable bits 48-55 used for simple pairing
hcibuf [ 10 ] = 0x00 ;
HCI_Command ( hcibuf , 11 ) ;
}
2019-07-02 20:30:33 +02:00
void BTD : : hci_write_simple_pairing_mode ( bool enable ) {
hcibuf [ 0 ] = 0x56 ; // HCI OCF = 56
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = 1 ; // parameter length = 1
hcibuf [ 3 ] = enable ? 1 : 0 ;
HCI_Command ( hcibuf , 4 ) ;
}
2012-08-21 14:31:11 +02:00
void BTD : : hci_inquiry ( ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_DEVICE_FOUND ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x01 ;
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x05 ; // Parameter Total Length = 5
hcibuf [ 3 ] = 0x33 ; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
hcibuf [ 4 ] = 0x8B ;
hcibuf [ 5 ] = 0x9E ;
hcibuf [ 6 ] = 0x30 ; // Inquiry time = 61.44 sec (maximum)
hcibuf [ 7 ] = 0x0A ; // 10 number of responses
HCI_Command ( hcibuf , 8 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-21 14:31:11 +02:00
void BTD : : hci_inquiry_cancel ( ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x02 ;
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
2013-04-03 18:30:46 +02:00
hcibuf [ 2 ] = 0x00 ; // Parameter Total Length = 0
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-21 14:31:11 +02:00
void BTD : : hci_connect ( ) {
2013-11-24 15:31:12 +01:00
hci_connect ( disc_bdaddr ) ; // Use last discovered device
}
void BTD : : hci_connect ( uint8_t * bdaddr ) {
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT ) ;
2019-08-31 18:22:21 +02:00
hcibuf [ 0 ] = 0x05 ; // HCI OCF = 5
2013-03-28 09:37:09 +01:00
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x0D ; // parameter Total Length = 13
2013-11-24 15:31:12 +01:00
hcibuf [ 3 ] = bdaddr [ 0 ] ; // 6 octet bdaddr (LSB)
hcibuf [ 4 ] = bdaddr [ 1 ] ;
hcibuf [ 5 ] = bdaddr [ 2 ] ;
hcibuf [ 6 ] = bdaddr [ 3 ] ;
hcibuf [ 7 ] = bdaddr [ 4 ] ;
hcibuf [ 8 ] = bdaddr [ 5 ] ;
2013-03-28 09:37:09 +01:00
hcibuf [ 9 ] = 0x18 ; // DM1 or DH1 may be used
hcibuf [ 10 ] = 0xCC ; // DM3, DH3, DM5, DH5 may be used
hcibuf [ 11 ] = 0x01 ; // Page repetition mode R1
hcibuf [ 12 ] = 0x00 ; // Reserved
hcibuf [ 13 ] = 0x00 ; // Clock offset
hcibuf [ 14 ] = 0x00 ; // Invalid clock offset
hcibuf [ 15 ] = 0x00 ; // Do not allow role switch
HCI_Command ( hcibuf , 16 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:37:09 +01:00
2012-10-07 14:50:51 +02:00
void BTD : : hci_pin_code_request_reply ( ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x0D ; // HCI OCF = 0D
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x17 ; // parameter length 23
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
2013-12-25 11:09:57 +01:00
if ( pairWithWii ) {
2013-04-03 18:30:24 +02:00
hcibuf [ 9 ] = 6 ; // Pin length is the length of the Bluetooth address
2015-04-16 01:57:00 +02:00
if ( pairWiiUsingSync ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2016-04-19 11:48:51 +02:00
Notify ( PSTR ( " \r \n Pairing with Wii controller via SYNC " ) , 0x80 ) ;
2013-02-02 22:14:01 +01:00
# endif
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-04-03 18:30:24 +02:00
hcibuf [ 10 + i ] = my_bdaddr [ i ] ; // The pin is the Bluetooth dongles Bluetooth address backwards
2013-05-16 22:43:51 +02:00
} else {
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-04-03 18:30:24 +02:00
hcibuf [ 10 + i ] = disc_bdaddr [ i ] ; // The pin is the Wiimote's Bluetooth address backwards
}
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 16 ; i < 26 ; i + + )
2013-03-28 09:37:09 +01:00
hcibuf [ i ] = 0x00 ; // The rest should be 0
} else {
hcibuf [ 9 ] = strlen ( btdPin ) ; // Length of pin
uint8_t i ;
2013-12-25 11:09:57 +01:00
for ( i = 0 ; i < strlen ( btdPin ) ; i + + ) // The maximum size of the pin is 16
2013-03-28 09:37:09 +01:00
hcibuf [ i + 10 ] = btdPin [ i ] ;
2013-12-25 11:09:57 +01:00
for ( ; i < 16 ; i + + )
2013-03-28 09:37:09 +01:00
hcibuf [ i + 10 ] = 0x00 ; // The rest should be 0
}
HCI_Command ( hcibuf , 26 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_pin_code_negative_request_reply ( ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x0E ; // HCI OCF = 0E
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x06 ; // parameter length 6
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
HCI_Command ( hcibuf , 9 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_link_key_request_negative_reply ( ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x0C ; // HCI OCF = 0C
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x06 ; // parameter length 6
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
HCI_Command ( hcibuf , 9 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2020-11-15 17:29:54 +01:00
void BTD : : hci_io_capability_request_reply ( ) {
hcibuf [ 0 ] = 0x2B ; // HCI OCF = 2B
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x09 ;
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
hcibuf [ 9 ] = 0x03 ; // NoInputNoOutput
hcibuf [ 10 ] = 0x00 ; // OOB authentication data not present
hcibuf [ 11 ] = 0x00 ; // MITM Protection Not Required – No Bonding. Numeric comparison with automatic accept allowed
HCI_Command ( hcibuf , 12 ) ;
}
2019-06-30 20:44:12 +02:00
void BTD : : hci_user_confirmation_request_reply ( ) {
hcibuf [ 0 ] = 0x2C ; // HCI OCF = 2C
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x06 ; // parameter length 6
hcibuf [ 3 ] = disc_bdaddr [ 0 ] ; // 6 octet bdaddr
hcibuf [ 4 ] = disc_bdaddr [ 1 ] ;
hcibuf [ 5 ] = disc_bdaddr [ 2 ] ;
hcibuf [ 6 ] = disc_bdaddr [ 3 ] ;
hcibuf [ 7 ] = disc_bdaddr [ 4 ] ;
hcibuf [ 8 ] = disc_bdaddr [ 5 ] ;
HCI_Command ( hcibuf , 9 ) ;
}
2012-10-07 14:50:51 +02:00
void BTD : : hci_authentication_request ( ) {
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x11 ; // HCI OCF = 11
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x02 ; // parameter length = 2
hcibuf [ 3 ] = ( uint8_t ) ( hci_handle & 0xFF ) ; //connection handle - low byte
hcibuf [ 4 ] = ( uint8_t ) ( ( hci_handle > > 8 ) & 0x0F ) ; //connection handle - high byte
HCI_Command ( hcibuf , 5 ) ;
2012-10-07 14:50:51 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : hci_disconnect ( uint16_t handle ) { // This is called by the different services
2013-12-11 10:37:18 +01:00
hci_clear_flag ( HCI_FLAG_DISCONNECT_COMPLETE ) ;
2013-03-28 09:37:09 +01:00
hcibuf [ 0 ] = 0x06 ; // HCI OCF = 6
hcibuf [ 1 ] = 0x01 < < 2 ; // HCI OGF = 1
hcibuf [ 2 ] = 0x03 ; // parameter length = 3
hcibuf [ 3 ] = ( uint8_t ) ( handle & 0xFF ) ; //connection handle - low byte
hcibuf [ 4 ] = ( uint8_t ) ( ( handle > > 8 ) & 0x0F ) ; //connection handle - high byte
hcibuf [ 5 ] = 0x13 ; // reason
HCI_Command ( hcibuf , 6 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2013-03-14 23:40:52 +01:00
void BTD : : hci_write_class_of_device ( ) { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
2013-11-12 19:38:18 +01:00
hcibuf [ 0 ] = 0x24 ; // HCI OCF = 24
2013-03-28 09:37:09 +01:00
hcibuf [ 1 ] = 0x03 < < 2 ; // HCI OGF = 3
hcibuf [ 2 ] = 0x03 ; // parameter length = 3
hcibuf [ 3 ] = 0x04 ; // Robot
hcibuf [ 4 ] = 0x08 ; // Toy
hcibuf [ 5 ] = 0x00 ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
HCI_Command ( hcibuf , 6 ) ;
2013-03-14 23:40:52 +01:00
}
2012-08-04 12:20:47 +02:00
/*******************************************************************
* *
* HCI ACL Data Packet *
* *
* buf [ 0 ] buf [ 1 ] buf [ 2 ] buf [ 3 ]
* 0 4 8 11 12 16 24 31 MSB
* . - + - + - + - + - + - + - + - | - + - + - + - | - + - | - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - .
* | HCI Handle | PB | BC | Data Total Length | HCI ACL Data Packet
* . - + - + - + - + - + - + - + - | - + - + - + - | - + - | - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - .
*
* buf [ 4 ] buf [ 5 ] buf [ 6 ] buf [ 7 ]
* 0 8 16 31 MSB
* . - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - .
* | Length | Channel ID | Basic L2CAP header
* . - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - .
*
* buf [ 8 ] buf [ 9 ] buf [ 10 ] buf [ 11 ]
* 0 8 16 31 MSB
* . - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - .
* | Code | Identifier | Length | Control frame ( C - frame )
* . - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - | - + - + - + - + - + - + - + - . ( signaling packet format )
*/
/************************************************************/
/* L2CAP Commands */
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
/************************************************************/
void BTD : : L2CAP_Command ( uint16_t handle , uint8_t * data , uint8_t nbytes , uint8_t channelLow , uint8_t channelHigh ) {
2013-03-28 09:37:09 +01:00
uint8_t buf [ 8 + nbytes ] ;
buf [ 0 ] = ( uint8_t ) ( handle & 0xff ) ; // HCI handle with PB,BC flag
buf [ 1 ] = ( uint8_t ) ( ( ( handle > > 8 ) & 0x0f ) | 0x20 ) ;
buf [ 2 ] = ( uint8_t ) ( ( 4 + nbytes ) & 0xff ) ; // HCI ACL total data length
buf [ 3 ] = ( uint8_t ) ( ( 4 + nbytes ) > > 8 ) ;
buf [ 4 ] = ( uint8_t ) ( nbytes & 0xff ) ; // L2CAP header: Length
buf [ 5 ] = ( uint8_t ) ( nbytes > > 8 ) ;
buf [ 6 ] = channelLow ;
buf [ 7 ] = channelHigh ;
2013-12-25 11:09:57 +01:00
for ( uint16_t i = 0 ; i < nbytes ; i + + ) // L2CAP C-frame
2013-03-28 09:37:09 +01:00
buf [ 8 + i ] = data [ i ] ;
uint8_t rcode = pUsb - > outTransfer ( bAddress , epInfo [ BTD_DATAOUT_PIPE ] . epAddr , ( 8 + nbytes ) , buf ) ;
2013-12-25 11:09:57 +01:00
if ( rcode ) {
2013-03-28 09:37:09 +01:00
delay ( 100 ) ; // This small delay prevents it from overflowing if it fails
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Error sending L2CAP message: 0x " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rcode , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " - Channel ID: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( channelHigh , 0x80 ) ;
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( channelLow , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
}
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-21 14:31:11 +02:00
void BTD : : l2cap_connection_request ( uint16_t handle , uint8_t rxid , uint8_t * scid , uint16_t psm ) {
2013-03-28 09:37:09 +01:00
l2capoutbuf [ 0 ] = L2CAP_CMD_CONNECTION_REQUEST ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x04 ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = ( uint8_t ) ( psm & 0xff ) ; // PSM
l2capoutbuf [ 5 ] = ( uint8_t ) ( psm > > 8 ) ;
l2capoutbuf [ 6 ] = scid [ 0 ] ; // Source CID
l2capoutbuf [ 7 ] = scid [ 1 ] ;
L2CAP_Command ( handle , l2capoutbuf , 8 ) ;
}
void BTD : : l2cap_connection_response ( uint16_t handle , uint8_t rxid , uint8_t * dcid , uint8_t * scid , uint8_t result ) {
l2capoutbuf [ 0 ] = L2CAP_CMD_CONNECTION_RESPONSE ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x08 ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = dcid [ 0 ] ; // Destination CID
l2capoutbuf [ 5 ] = dcid [ 1 ] ;
l2capoutbuf [ 6 ] = scid [ 0 ] ; // Source CID
l2capoutbuf [ 7 ] = scid [ 1 ] ;
l2capoutbuf [ 8 ] = result ; // Result: Pending or Success
l2capoutbuf [ 9 ] = 0x00 ;
l2capoutbuf [ 10 ] = 0x00 ; // No further information
l2capoutbuf [ 11 ] = 0x00 ;
L2CAP_Command ( handle , l2capoutbuf , 12 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : l2cap_config_request ( uint16_t handle , uint8_t rxid , uint8_t * dcid ) {
2013-03-28 09:37:09 +01:00
l2capoutbuf [ 0 ] = L2CAP_CMD_CONFIG_REQUEST ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x08 ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = dcid [ 0 ] ; // Destination CID
l2capoutbuf [ 5 ] = dcid [ 1 ] ;
l2capoutbuf [ 6 ] = 0x00 ; // Flags
l2capoutbuf [ 7 ] = 0x00 ;
l2capoutbuf [ 8 ] = 0x01 ; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint
l2capoutbuf [ 9 ] = 0x02 ; // Config Opt: length
l2capoutbuf [ 10 ] = 0xFF ; // MTU
l2capoutbuf [ 11 ] = 0xFF ;
L2CAP_Command ( handle , l2capoutbuf , 12 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
void BTD : : l2cap_config_response ( uint16_t handle , uint8_t rxid , uint8_t * scid ) {
l2capoutbuf [ 0 ] = L2CAP_CMD_CONFIG_RESPONSE ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x0A ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = scid [ 0 ] ; // Source CID
l2capoutbuf [ 5 ] = scid [ 1 ] ;
l2capoutbuf [ 6 ] = 0x00 ; // Flag
l2capoutbuf [ 7 ] = 0x00 ;
l2capoutbuf [ 8 ] = 0x00 ; // Result
l2capoutbuf [ 9 ] = 0x00 ;
l2capoutbuf [ 10 ] = 0x01 ; // Config
l2capoutbuf [ 11 ] = 0x02 ;
l2capoutbuf [ 12 ] = 0xA0 ;
l2capoutbuf [ 13 ] = 0x02 ;
L2CAP_Command ( handle , l2capoutbuf , 14 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : l2cap_disconnection_request ( uint16_t handle , uint8_t rxid , uint8_t * dcid , uint8_t * scid ) {
2013-03-28 09:37:09 +01:00
l2capoutbuf [ 0 ] = L2CAP_CMD_DISCONNECT_REQUEST ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x04 ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = dcid [ 0 ] ;
l2capoutbuf [ 5 ] = dcid [ 1 ] ;
l2capoutbuf [ 6 ] = scid [ 0 ] ;
l2capoutbuf [ 7 ] = scid [ 1 ] ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
L2CAP_Command ( handle , l2capoutbuf , 8 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : l2cap_disconnection_response ( uint16_t handle , uint8_t rxid , uint8_t * dcid , uint8_t * scid ) {
2013-03-28 09:37:09 +01:00
l2capoutbuf [ 0 ] = L2CAP_CMD_DISCONNECT_RESPONSE ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x04 ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = dcid [ 0 ] ;
l2capoutbuf [ 5 ] = dcid [ 1 ] ;
l2capoutbuf [ 6 ] = scid [ 0 ] ;
l2capoutbuf [ 7 ] = scid [ 1 ] ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
L2CAP_Command ( handle , l2capoutbuf , 8 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
void BTD : : l2cap_information_response ( uint16_t handle , uint8_t rxid , uint8_t infoTypeLow , uint8_t infoTypeHigh ) {
2013-03-28 09:37:09 +01:00
l2capoutbuf [ 0 ] = L2CAP_CMD_INFORMATION_RESPONSE ; // Code
l2capoutbuf [ 1 ] = rxid ; // Identifier
l2capoutbuf [ 2 ] = 0x08 ; // Length
l2capoutbuf [ 3 ] = 0x00 ;
l2capoutbuf [ 4 ] = infoTypeLow ;
l2capoutbuf [ 5 ] = infoTypeHigh ;
l2capoutbuf [ 6 ] = 0x00 ; // Result = success
l2capoutbuf [ 7 ] = 0x00 ; // Result = success
l2capoutbuf [ 8 ] = 0x00 ;
l2capoutbuf [ 9 ] = 0x00 ;
l2capoutbuf [ 10 ] = 0x00 ;
l2capoutbuf [ 11 ] = 0x00 ;
2013-04-03 18:30:46 +02:00
2013-03-28 09:37:09 +01:00
L2CAP_Command ( handle , l2capoutbuf , 12 ) ;
2012-08-04 12:20:47 +02:00
}
2013-04-02 00:10:02 +02:00
/* PS3 Commands - only set Bluetooth address is implemented in this library */
void BTD : : setBdaddr ( uint8_t * bdaddr ) {
/* Set the internal Bluetooth address */
2013-03-28 09:37:09 +01:00
uint8_t buf [ 8 ] ;
buf [ 0 ] = 0x01 ;
buf [ 1 ] = 0x00 ;
2013-04-02 00:10:02 +02:00
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-11-12 19:38:18 +01:00
buf [ i + 2 ] = bdaddr [ 5 - i ] ; // Copy into buffer, has to be written reversed, so it is MSB first
2013-03-28 09:37:09 +01:00
2013-11-12 19:38:18 +01:00
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
2015-03-19 18:11:22 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ BTD_CONTROL_PIPE ] . epAddr , bmREQ_HID_OUT , HID_REQUEST_SET_REPORT , 0xF5 , 0x03 , 0x00 , 8 , 8 , buf , NULL ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:37:09 +01:00
2013-04-02 00:10:02 +02:00
void BTD : : setMoveBdaddr ( uint8_t * bdaddr ) {
/* Set the internal Bluetooth address */
2013-03-28 09:37:09 +01:00
uint8_t buf [ 11 ] ;
buf [ 0 ] = 0x05 ;
buf [ 7 ] = 0x10 ;
buf [ 8 ] = 0x01 ;
buf [ 9 ] = 0x02 ;
buf [ 10 ] = 0x12 ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-04-02 00:10:02 +02:00
buf [ i + 1 ] = bdaddr [ i ] ;
2013-03-28 09:37:09 +01:00
2013-11-12 19:38:18 +01:00
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
2015-03-19 18:11:22 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ BTD_CONTROL_PIPE ] . epAddr , bmREQ_HID_OUT , HID_REQUEST_SET_REPORT , 0x05 , 0x03 , 0x00 , 11 , 11 , buf , NULL ) ;
2013-09-27 11:07:05 +02:00
}