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
*/
2014-04-21 18:41:39 +02:00
# include "SPPServer.h"
2013-11-11 11:48:09 +01:00
// To enable serial debugging see "settings.h"
2012-08-04 12:20:47 +02:00
//#define EXTRADEBUG // Uncomment to get even more debugging data
//#define PRINTREPORT // Uncomment to print the report sent to the Arduino
2014-04-21 18:41:39 +02:00
SPPServer : : SPPServer ( BTD * p , const char * name , const char * pin , bool pair , uint8_t * addr ) :
2014-04-21 18:27:04 +02:00
SPPBase ( p )
2012-08-04 12:20:47 +02:00
{
2013-12-25 11:09:57 +01:00
if ( pBtd )
2013-03-28 09:46:43 +01:00
pBtd - > registerServiceClass ( this ) ; // Register it as a Bluetooth service
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
pBtd - > btdName = name ;
pBtd - > btdPin = pin ;
2013-03-28 09:37:09 +01:00
2014-04-21 18:27:04 +02:00
if ( addr ) // Make sure address is set
pBtd - > pairWithOtherDevice = pair ;
for ( uint8_t i = 0 ; i < 6 ; i + + )
pBtd - > remote_bdaddr [ i ] = addr [ i ] ;
2013-03-28 09:46:43 +01:00
/* Set device cid for the SDP and RFCOMM channelse */
sdp_dcid [ 0 ] = 0x50 ; // 0x0050
sdp_dcid [ 1 ] = 0x00 ;
2014-04-21 18:27:04 +02:00
2013-03-28 09:46:43 +01:00
rfcomm_dcid [ 0 ] = 0x51 ; // 0x0051
rfcomm_dcid [ 1 ] = 0x00 ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
Reset ( ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : Reset ( ) {
2013-03-28 09:46:43 +01:00
connected = false ;
RFCOMMConnected = false ;
SDPConnected = false ;
2013-09-27 11:07:05 +02:00
waitForLastCommand = false ;
2013-03-28 09:46:43 +01:00
l2cap_sdp_state = L2CAP_SDP_WAIT ;
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT ;
l2cap_event_flag = 0 ;
2013-05-07 00:06:49 +02:00
sppIndex = 0 ;
2013-03-28 09:46:43 +01:00
}
2014-04-21 18:41:39 +02:00
void SPPServer : : ACLData ( uint8_t * l2capinbuf ) {
2013-12-25 11:09:57 +01:00
if ( ! connected ) {
if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_REQUEST ) {
if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = SDP_PSM & & ! pBtd - > sdpConnectionClaimed ) {
2013-03-28 09:46:43 +01:00
pBtd - > sdpConnectionClaimed = true ;
hci_handle = pBtd - > hci_handle ; // Store the HCI Handle for the connection
l2cap_sdp_state = L2CAP_SDP_WAIT ; // Reset state
2013-12-25 11:09:57 +01:00
} else if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = RFCOMM_PSM & & ! pBtd - > rfcommConnectionClaimed ) {
2013-03-28 09:46:43 +01:00
pBtd - > rfcommConnectionClaimed = true ;
hci_handle = pBtd - > hci_handle ; // Store the HCI Handle for the connection
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT ; // Reset state
}
}
2012-08-04 12:20:47 +02:00
}
2013-12-30 05:53:24 +01:00
//if((l2capinbuf[0] | (uint16_t)l2capinbuf[1] << 8) == (hci_handle | 0x2000U)) { // acl_handle_ok
if ( UHS_ACL_HANDLE_OK ( l2capinbuf , hci_handle ) ) { // acl_handle_ok
2014-04-21 18:27:04 +02:00
if ( ( l2capinbuf [ 6 ] | ( l2capinbuf [ 7 ] < < 8 ) ) = = 0x0001U ) { // l2cap_control - Channel ID for ACL-U
2013-12-25 11:09:57 +01:00
if ( l2capinbuf [ 8 ] = = L2CAP_CMD_COMMAND_REJECT ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n L2CAP Command Rejected - Reason: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " Data: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 17 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 16 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 15 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
# endif
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_REQUEST ) {
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n L2CAP Connection Request - PSM: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " SCID: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 15 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " Identifier: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 9 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
# endif
2013-12-25 11:09:57 +01:00
if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = SDP_PSM ) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
sdp_scid [ 0 ] = l2capinbuf [ 14 ] ;
sdp_scid [ 1 ] = l2capinbuf [ 15 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONNECTION_SDP_REQUEST ) ;
2013-12-25 11:09:57 +01:00
} else if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = RFCOMM_PSM ) { // ----- || -----
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
rfcomm_scid [ 0 ] = l2capinbuf [ 14 ] ;
rfcomm_scid [ 1 ] = l2capinbuf [ 15 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST ) ;
2013-03-28 09:46:43 +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 ] = = sdp_dcid [ 0 ] & & l2capinbuf [ 13 ] = = sdp_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONFIG_SDP_SUCCESS ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = rfcomm_dcid [ 0 ] & & l2capinbuf [ 13 ] = = rfcomm_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80);
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS ) ;
2013-03-28 09:46:43 +01:00
}
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONFIG_REQUEST ) {
if ( l2capinbuf [ 12 ] = = sdp_dcid [ 0 ] & & l2capinbuf [ 13 ] = = sdp_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
2013-12-13 10:35:27 +01:00
pBtd - > l2cap_config_response ( hci_handle , l2capinbuf [ 9 ] , sdp_scid ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = rfcomm_dcid [ 0 ] & & l2capinbuf [ 13 ] = = rfcomm_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
2013-12-13 10:35:27 +01:00
pBtd - > l2cap_config_response ( hci_handle , l2capinbuf [ 9 ] , rfcomm_scid ) ;
2013-03-28 09:46:43 +01:00
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_DISCONNECT_REQUEST ) {
if ( l2capinbuf [ 12 ] = = sdp_dcid [ 0 ] & & l2capinbuf [ 13 ] = = sdp_dcid [ 1 ] ) {
2013-03-28 09:46:43 +01:00
//Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80);
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_DISCONNECT_SDP_REQUEST ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = rfcomm_dcid [ 0 ] & & l2capinbuf [ 13 ] = = rfcomm_dcid [ 1 ] ) {
2013-03-28 09:46:43 +01:00
//Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80);
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST ) ;
2013-03-28 09:46:43 +01:00
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_DISCONNECT_RESPONSE ) {
if ( l2capinbuf [ 12 ] = = sdp_scid [ 0 ] & & l2capinbuf [ 13 ] = = sdp_scid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_DISCONNECT_RESPONSE ) ;
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 12 ] = = rfcomm_scid [ 0 ] & & l2capinbuf [ 13 ] = = rfcomm_scid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
2013-12-11 09:59:58 +01:00
l2cap_set_flag ( L2CAP_FLAG_DISCONNECT_RESPONSE ) ;
2013-03-28 09:46:43 +01:00
}
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_INFORMATION_REQUEST ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Information request " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
pBtd - > l2cap_information_response ( hci_handle , identifier , l2capinbuf [ 12 ] , l2capinbuf [ 13 ] ) ;
}
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
else {
Notify ( PSTR ( " \r \n L2CAP Unknown Signaling Command: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 8 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
}
# endif
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 6 ] = = sdp_dcid [ 0 ] & & l2capinbuf [ 7 ] = = sdp_dcid [ 1 ] ) { // SDP
if ( l2capinbuf [ 8 ] = = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU ) {
if ( ( ( l2capinbuf [ 16 ] < < 8 | l2capinbuf [ 17 ] ) = = SERIALPORT_UUID ) | | ( ( l2capinbuf [ 16 ] < < 8 | l2capinbuf [ 17 ] ) = = 0x0000 & & ( l2capinbuf [ 18 ] < < 8 | l2capinbuf [ 19 ] ) = = SERIALPORT_UUID ) ) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes
if ( firstMessage ) {
2013-03-28 09:46:43 +01:00
serialPortResponse1 ( l2capinbuf [ 9 ] , l2capinbuf [ 10 ] ) ;
firstMessage = false ;
} else {
serialPortResponse2 ( l2capinbuf [ 9 ] , l2capinbuf [ 10 ] ) ; // Serialport continuation state
firstMessage = true ;
}
2013-12-25 11:09:57 +01:00
} else if ( ( ( l2capinbuf [ 16 ] < < 8 | l2capinbuf [ 17 ] ) = = L2CAP_UUID ) | | ( ( l2capinbuf [ 16 ] < < 8 | l2capinbuf [ 17 ] ) = = 0x0000 & & ( l2capinbuf [ 18 ] < < 8 | l2capinbuf [ 19 ] ) = = L2CAP_UUID ) ) {
if ( firstMessage ) {
2013-03-28 09:46:43 +01:00
l2capResponse1 ( l2capinbuf [ 9 ] , l2capinbuf [ 10 ] ) ;
firstMessage = false ;
} else {
l2capResponse2 ( l2capinbuf [ 9 ] , l2capinbuf [ 10 ] ) ; // L2CAP continuation state
firstMessage = true ;
}
2013-04-08 00:22:15 +02:00
} else
serviceNotSupported ( l2capinbuf [ 9 ] , l2capinbuf [ 10 ] ) ; // The service is not supported
2013-04-01 03:09:23 +02:00
# ifdef EXTRADEBUG
2013-04-08 00:23:52 +02:00
Notify ( PSTR ( " \r \n UUID: " ) , 0x80 ) ;
uint16_t uuid ;
if ( ( l2capinbuf [ 16 ] < < 8 | l2capinbuf [ 17 ] ) = = 0x0000 ) // Check if it's sending the UUID as a 128-bit UUID
uuid = ( l2capinbuf [ 18 ] < < 8 | l2capinbuf [ 19 ] ) ;
else // Short UUID
uuid = ( l2capinbuf [ 16 ] < < 8 | l2capinbuf [ 17 ] ) ;
2013-12-25 11:09:57 +01:00
D_PrintHex < uint16_t > ( uuid , 0x80 ) ;
2013-04-03 17:52:12 +02:00
2013-04-08 00:23:52 +02:00
Notify ( PSTR ( " \r \n Length: " ) , 0x80 ) ;
uint16_t length = l2capinbuf [ 11 ] < < 8 | l2capinbuf [ 12 ] ;
2013-12-25 11:09:57 +01:00
D_PrintHex < uint16_t > ( length , 0x80 ) ;
2013-04-08 00:23:52 +02:00
Notify ( PSTR ( " \r \n Data: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < length ; i + + ) {
D_PrintHex < uint8_t > ( l2capinbuf [ 13 + i ] , 0x80 ) ;
2013-04-08 00:23:52 +02:00
Notify ( PSTR ( " " ) , 0x80 ) ;
}
2013-04-01 03:09:23 +02:00
# endif
2013-03-28 09:46:43 +01:00
}
2013-06-15 17:47:48 +02:00
# ifdef EXTRADEBUG
else {
2013-07-04 15:37:29 +02:00
Notify ( PSTR ( " \r \n Unknown PDU: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 8 ] , 0x80 ) ;
2013-06-15 17:47:48 +02:00
}
# endif
2013-12-25 11:09:57 +01:00
} else if ( l2capinbuf [ 6 ] = = rfcomm_dcid [ 0 ] & & l2capinbuf [ 7 ] = = rfcomm_dcid [ 1 ] ) { // RFCOMM
2013-03-28 09:46:43 +01:00
rfcommChannel = l2capinbuf [ 8 ] & 0xF8 ;
rfcommDirection = l2capinbuf [ 8 ] & 0x04 ;
rfcommCommandResponse = l2capinbuf [ 8 ] & 0x02 ;
rfcommChannelType = l2capinbuf [ 9 ] & 0xEF ;
rfcommPfBit = l2capinbuf [ 9 ] & 0x10 ;
2013-12-25 11:09:57 +01:00
if ( rfcommChannel > > 3 ! = 0x00 )
2013-03-28 09:46:43 +01:00
rfcommChannelConnection = rfcommChannel ;
2013-03-28 09:37:09 +01:00
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n RFCOMM Channel: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommChannel > > 3 , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " Direction: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommDirection > > 2 , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " CommandResponse: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommCommandResponse > > 1 , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " ChannelType: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommChannelType , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " PF_BIT: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommPfBit , 0x80 ) ;
2013-03-28 09:46:43 +01:00
# endif
2013-12-25 11:09:57 +01:00
if ( rfcommChannelType = = RFCOMM_DISC ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Received Disconnect RFCOMM Command on channel: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommChannel > > 3 , 0x80 ) ;
2013-03-28 09:46:43 +01:00
# endif
connected = false ;
sendRfcomm ( rfcommChannel , rfcommDirection , rfcommCommandResponse , RFCOMM_UA , rfcommPfBit , rfcommbuf , 0x00 ) ; // UA Command
}
2013-12-25 11:09:57 +01:00
if ( connected ) {
2013-03-28 09:46:43 +01:00
/* Read the incoming message */
2013-12-25 11:09:57 +01:00
if ( rfcommChannelType = = RFCOMM_UIH & & rfcommChannel = = rfcommChannelConnection ) {
2013-03-28 09:46:43 +01:00
uint8_t length = l2capinbuf [ 10 ] > > 1 ; // Get length
2013-08-03 02:12:55 +02:00
uint8_t offset = l2capinbuf [ 4 ] - length - 4 ; // Check if there is credit
2013-12-25 11:09:57 +01:00
if ( checkFcs ( & l2capinbuf [ 8 ] , l2capinbuf [ 11 + length + offset ] ) ) {
2013-08-03 02:12:55 +02:00
uint8_t i = 0 ;
2013-12-25 11:09:57 +01:00
for ( ; i < length ; i + + ) {
if ( rfcommAvailable + i > = sizeof ( rfcommDataBuffer ) ) {
2013-08-03 02:12:55 +02:00
# ifdef DEBUG_USB_HOST
Notify ( PSTR ( " \r \n Warning: Buffer is full! " ) , 0x80 ) ;
# endif
break ;
}
2013-03-28 09:46:43 +01:00
rfcommDataBuffer [ rfcommAvailable + i ] = l2capinbuf [ 11 + i + offset ] ;
2013-08-03 02:12:55 +02:00
}
rfcommAvailable + = i ;
2012-08-04 12:20:47 +02:00
# ifdef EXTRADEBUG
2013-08-03 02:12:55 +02:00
Notify ( PSTR ( " \r \n RFCOMM Data Available: " ) , 0x80 ) ;
Notify ( rfcommAvailable , 0x80 ) ;
2013-12-25 11:09:57 +01:00
if ( offset ) {
2013-08-03 02:12:55 +02:00
Notify ( PSTR ( " - Credit: 0x " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 11 ] , 0x80 ) ;
}
# endif
2013-03-28 09:46:43 +01:00
}
2013-08-03 02:12:55 +02:00
# ifdef DEBUG_USB_HOST
else
Notify ( PSTR ( " \r \n Error in FCS checksum! " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
# ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < length ; i + + )
2013-04-26 23:50:39 +02:00
Notifyc ( l2capinbuf [ i + 11 + offset ] , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 11 ] = = BT_RFCOMM_RPN_CMD ) { // UIH Remote Port Negotiation Command
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Received UIH Remote Port Negotiation Command " ) , 0x80 ) ;
# endif
rfcommbuf [ 0 ] = BT_RFCOMM_RPN_RSP ; // Command
rfcommbuf [ 1 ] = l2capinbuf [ 12 ] ; // Length and shiftet like so: length << 1 | 1
rfcommbuf [ 2 ] = l2capinbuf [ 13 ] ; // Channel: channel << 1 | 1
rfcommbuf [ 3 ] = l2capinbuf [ 14 ] ; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
rfcommbuf [ 4 ] = l2capinbuf [ 15 ] ; // Priority
rfcommbuf [ 5 ] = l2capinbuf [ 16 ] ; // Timer
rfcommbuf [ 6 ] = l2capinbuf [ 17 ] ; // Max Fram Size LSB
rfcommbuf [ 7 ] = l2capinbuf [ 18 ] ; // Max Fram Size MSB
rfcommbuf [ 8 ] = l2capinbuf [ 19 ] ; // MaxRatransm.
rfcommbuf [ 9 ] = l2capinbuf [ 20 ] ; // Number of Frames
sendRfcomm ( rfcommChannel , rfcommDirection , 0 , RFCOMM_UIH , rfcommPfBit , rfcommbuf , 0x0A ) ; // UIH Remote Port Negotiation Response
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 11 ] = = BT_RFCOMM_MSC_CMD ) { // UIH Modem Status Command
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send UIH Modem Status Response " ) , 0x80 ) ;
# endif
rfcommbuf [ 0 ] = BT_RFCOMM_MSC_RSP ; // UIH Modem Status Response
rfcommbuf [ 1 ] = 2 < < 1 | 1 ; // Length and shiftet like so: length << 1 | 1
rfcommbuf [ 2 ] = l2capinbuf [ 13 ] ; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
rfcommbuf [ 3 ] = l2capinbuf [ 14 ] ;
sendRfcomm ( rfcommChannel , rfcommDirection , 0 , RFCOMM_UIH , rfcommPfBit , rfcommbuf , 0x04 ) ;
}
} else {
2013-12-25 11:09:57 +01:00
if ( rfcommChannelType = = RFCOMM_SABM ) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Received SABM Command " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2013-03-28 09:46:43 +01:00
sendRfcomm ( rfcommChannel , rfcommDirection , rfcommCommandResponse , RFCOMM_UA , rfcommPfBit , rfcommbuf , 0x00 ) ; // UA Command
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 11 ] = = BT_RFCOMM_PN_CMD ) { // UIH Parameter Negotiation Command
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Received UIH Parameter Negotiation Command " ) , 0x80 ) ;
# endif
rfcommbuf [ 0 ] = BT_RFCOMM_PN_RSP ; // UIH Parameter Negotiation Response
rfcommbuf [ 1 ] = l2capinbuf [ 12 ] ; // Length and shiftet like so: length << 1 | 1
rfcommbuf [ 2 ] = l2capinbuf [ 13 ] ; // Channel: channel << 1 | 1
rfcommbuf [ 3 ] = 0xE0 ; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
rfcommbuf [ 4 ] = 0x00 ; // Priority
rfcommbuf [ 5 ] = 0x00 ; // Timer
rfcommbuf [ 6 ] = BULK_MAXPKTSIZE - 14 ; // Max Fram Size LSB - set to the size of received data (50)
rfcommbuf [ 7 ] = 0x00 ; // Max Fram Size MSB
rfcommbuf [ 8 ] = 0x00 ; // MaxRatransm.
rfcommbuf [ 9 ] = 0x00 ; // Number of Frames
sendRfcomm ( rfcommChannel , rfcommDirection , 0 , RFCOMM_UIH , rfcommPfBit , rfcommbuf , 0x0A ) ;
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 11 ] = = BT_RFCOMM_MSC_CMD ) { // UIH Modem Status Command
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send UIH Modem Status Response " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:46:43 +01:00
rfcommbuf [ 0 ] = BT_RFCOMM_MSC_RSP ; // UIH Modem Status Response
rfcommbuf [ 1 ] = 2 < < 1 | 1 ; // Length and shiftet like so: length << 1 | 1
rfcommbuf [ 2 ] = l2capinbuf [ 13 ] ; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
rfcommbuf [ 3 ] = l2capinbuf [ 14 ] ;
sendRfcomm ( rfcommChannel , rfcommDirection , 0 , RFCOMM_UIH , rfcommPfBit , rfcommbuf , 0x04 ) ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
delay ( 1 ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send UIH Modem Status Command " ) , 0x80 ) ;
2012-08-04 12:20:47 +02:00
# endif
2013-03-28 09:46:43 +01:00
rfcommbuf [ 0 ] = BT_RFCOMM_MSC_CMD ; // UIH Modem Status Command
rfcommbuf [ 1 ] = 2 < < 1 | 1 ; // Length and shiftet like so: length << 1 | 1
rfcommbuf [ 2 ] = l2capinbuf [ 13 ] ; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
rfcommbuf [ 3 ] = 0x8D ; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
sendRfcomm ( rfcommChannel , rfcommDirection , 0 , RFCOMM_UIH , rfcommPfBit , rfcommbuf , 0x04 ) ;
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 11 ] = = BT_RFCOMM_MSC_RSP ) { // UIH Modem Status Response
if ( ! creditSent ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send UIH Command with credit " ) , 0x80 ) ;
# endif
sendRfcommCredit ( rfcommChannelConnection , rfcommDirection , 0 , RFCOMM_UIH , 0x10 , sizeof ( rfcommDataBuffer ) ) ; // Send credit
creditSent = true ;
timer = millis ( ) ;
waitForLastCommand = true ;
}
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 10 ] = = 0x01 ) { // UIH Command with credit
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Received UIH Command with credit " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2013-12-25 11:09:57 +01:00
} else if ( rfcommChannelType = = RFCOMM_UIH & & l2capinbuf [ 11 ] = = BT_RFCOMM_RPN_CMD ) { // UIH Remote Port Negotiation Command
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Received UIH Remote Port Negotiation Command " ) , 0x80 ) ;
# endif
rfcommbuf [ 0 ] = BT_RFCOMM_RPN_RSP ; // Command
rfcommbuf [ 1 ] = l2capinbuf [ 12 ] ; // Length and shiftet like so: length << 1 | 1
rfcommbuf [ 2 ] = l2capinbuf [ 13 ] ; // Channel: channel << 1 | 1
rfcommbuf [ 3 ] = l2capinbuf [ 14 ] ; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
rfcommbuf [ 4 ] = l2capinbuf [ 15 ] ; // Priority
rfcommbuf [ 5 ] = l2capinbuf [ 16 ] ; // Timer
rfcommbuf [ 6 ] = l2capinbuf [ 17 ] ; // Max Fram Size LSB
rfcommbuf [ 7 ] = l2capinbuf [ 18 ] ; // Max Fram Size MSB
rfcommbuf [ 8 ] = l2capinbuf [ 19 ] ; // MaxRatransm.
rfcommbuf [ 9 ] = l2capinbuf [ 20 ] ; // Number of Frames
sendRfcomm ( rfcommChannel , rfcommDirection , 0 , RFCOMM_UIH , rfcommPfBit , rfcommbuf , 0x0A ) ; // UIH Remote Port Negotiation Response
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n RFCOMM Connection is now established \r \n " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2013-03-28 09:46:43 +01:00
waitForLastCommand = false ;
creditSent = false ;
connected = true ; // The RFCOMM channel is now established
2013-05-07 00:06:49 +02:00
sppIndex = 0 ;
2013-03-28 09:46:43 +01:00
}
2013-12-13 10:35:27 +01:00
# ifdef EXTRADEBUG
2013-12-25 11:09:57 +01:00
else if ( rfcommChannelType ! = RFCOMM_DISC ) {
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Unsupported RFCOMM Data - ChannelType: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rfcommChannelType , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " Command: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 11 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
}
# endif
}
2012-08-04 12:20:47 +02:00
}
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
else {
Notify ( PSTR ( " \r \n Unsupported L2CAP Data - Channel ID: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 7 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 6 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
}
2012-08-09 21:22:55 +02:00
# endif
2013-03-28 09:46:43 +01:00
SDP_task ( ) ;
RFCOMM_task ( ) ;
}
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : Run ( ) {
2013-12-25 11:09:57 +01:00
if ( waitForLastCommand & & ( millis ( ) - timer ) > 100 ) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n RFCOMM Connection is now established - Automatic \r \n " ) , 0x80 ) ;
2012-08-05 01:14:39 +02:00
# endif
2013-03-28 09:46:43 +01:00
creditSent = false ;
waitForLastCommand = false ;
connected = true ; // The RFCOMM channel is now established
2013-05-07 00:06:49 +02:00
sppIndex = 0 ;
2013-03-28 09:46:43 +01:00
}
2013-05-07 00:06:49 +02:00
send ( ) ; // Send all bytes currently in the buffer
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : SDP_task ( ) {
2013-12-25 11:09:57 +01:00
switch ( l2cap_sdp_state ) {
2013-03-28 09:46:43 +01:00
case L2CAP_SDP_WAIT :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONNECTION_SDP_REQUEST ) ) {
2013-12-11 09:59:58 +01:00
l2cap_clear_flag ( L2CAP_FLAG_CONNECTION_SDP_REQUEST ) ; // Clear flag
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n SDP Incoming Connection Request " ) , 0x80 ) ;
# endif
pBtd - > l2cap_connection_response ( hci_handle , identifier , sdp_dcid , sdp_scid , PENDING ) ;
delay ( 1 ) ;
pBtd - > l2cap_connection_response ( hci_handle , identifier , sdp_dcid , sdp_scid , SUCCESSFUL ) ;
identifier + + ;
delay ( 1 ) ;
pBtd - > l2cap_config_request ( hci_handle , identifier , sdp_scid ) ;
l2cap_sdp_state = L2CAP_SDP_SUCCESS ;
2013-12-25 11:09:57 +01:00
} else if ( l2cap_check_flag ( L2CAP_FLAG_DISCONNECT_SDP_REQUEST ) ) {
2013-12-13 10:41:12 +01:00
l2cap_clear_flag ( L2CAP_FLAG_DISCONNECT_SDP_REQUEST ) ; // Clear flag
SDPConnected = false ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-13 10:41:12 +01:00
Notify ( PSTR ( " \r \n Disconnected SDP Channel " ) , 0x80 ) ;
2013-03-28 09:46:43 +01:00
# endif
2013-12-13 10:41:12 +01:00
pBtd - > l2cap_disconnection_response ( hci_handle , identifier , sdp_dcid , sdp_scid ) ;
2013-03-28 09:46:43 +01:00
}
break ;
case L2CAP_SDP_SUCCESS :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONFIG_SDP_SUCCESS ) ) {
2013-12-11 09:59:58 +01:00
l2cap_clear_flag ( L2CAP_FLAG_CONFIG_SDP_SUCCESS ) ; // Clear flag
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n SDP Successfully Configured " ) , 0x80 ) ;
# endif
firstMessage = true ; // Reset bool
SDPConnected = true ;
l2cap_sdp_state = L2CAP_SDP_WAIT ;
2013-12-13 10:41:12 +01:00
}
2013-03-28 09:46:43 +01:00
break ;
2013-12-13 10:41:12 +01:00
2013-03-28 09:46:43 +01:00
case L2CAP_DISCONNECT_RESPONSE : // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_DISCONNECT_RESPONSE ) ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Disconnected L2CAP Connection " ) , 0x80 ) ;
# endif
pBtd - > hci_disconnect ( hci_handle ) ;
hci_handle = - 1 ; // Reset handle
2013-12-13 10:41:12 +01:00
Reset ( ) ;
2013-03-28 09:46:43 +01:00
}
break ;
}
}
2014-04-21 18:41:39 +02:00
void SPPServer : : RFCOMM_task ( ) {
2013-12-25 11:09:57 +01:00
switch ( l2cap_rfcomm_state ) {
2013-03-28 09:46:43 +01:00
case L2CAP_RFCOMM_WAIT :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST ) ) {
2013-12-11 09:59:58 +01:00
l2cap_clear_flag ( L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST ) ; // Clear flag
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n RFCOMM Incoming Connection Request " ) , 0x80 ) ;
# endif
pBtd - > l2cap_connection_response ( hci_handle , identifier , rfcomm_dcid , rfcomm_scid , PENDING ) ;
delay ( 1 ) ;
pBtd - > l2cap_connection_response ( hci_handle , identifier , rfcomm_dcid , rfcomm_scid , SUCCESSFUL ) ;
identifier + + ;
delay ( 1 ) ;
pBtd - > l2cap_config_request ( hci_handle , identifier , rfcomm_scid ) ;
l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS ;
2013-12-25 11:09:57 +01:00
} else if ( l2cap_check_flag ( L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST ) ) {
2013-12-13 10:41:12 +01:00
l2cap_clear_flag ( L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST ) ; // Clear flag
RFCOMMConnected = false ;
connected = false ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-13 10:41:12 +01:00
Notify ( PSTR ( " \r \n Disconnected RFCOMM Channel " ) , 0x80 ) ;
2013-03-28 09:46:43 +01:00
# endif
2013-12-13 10:41:12 +01:00
pBtd - > l2cap_disconnection_response ( hci_handle , identifier , rfcomm_dcid , rfcomm_scid ) ;
2013-03-28 09:46:43 +01:00
}
break ;
case L2CAP_RFCOMM_SUCCESS :
2013-12-25 11:09:57 +01:00
if ( l2cap_check_flag ( L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS ) ) {
2013-12-11 09:59:58 +01:00
l2cap_clear_flag ( L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS ) ; // Clear flag
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n RFCOMM Successfully Configured " ) , 0x80 ) ;
# endif
rfcommAvailable = 0 ; // Reset number of bytes available
bytesRead = 0 ; // Reset number of bytes received
RFCOMMConnected = true ;
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT ;
2013-12-13 10:41:12 +01:00
}
2013-03-28 09:46:43 +01:00
break ;
}
2012-08-04 12:20:47 +02:00
}
/************************************************************/
/* SDP Commands */
/************************************************************/
2014-04-21 18:41:39 +02:00
void SPPServer : : SDP_Command ( uint8_t * data , uint8_t nbytes ) { // See page 223 in the Bluetooth specs
2013-03-28 09:46:43 +01:00
pBtd - > L2CAP_Command ( hci_handle , data , nbytes , sdp_scid [ 0 ] , sdp_scid [ 1 ] ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : serviceNotSupported ( uint8_t transactionIDHigh , uint8_t transactionIDLow ) { // See page 235 in the Bluetooth specs
2013-03-28 09:46:43 +01:00
l2capoutbuf [ 0 ] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU ;
l2capoutbuf [ 1 ] = transactionIDHigh ;
l2capoutbuf [ 2 ] = transactionIDLow ;
l2capoutbuf [ 3 ] = 0x00 ; // Parameter Length
l2capoutbuf [ 4 ] = 0x05 ; // Parameter Length
l2capoutbuf [ 5 ] = 0x00 ; // AttributeListsByteCount
l2capoutbuf [ 6 ] = 0x02 ; // AttributeListsByteCount
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
/* Attribute ID/Value Sequence: */
l2capoutbuf [ 7 ] = 0x35 ;
l2capoutbuf [ 8 ] = 0x00 ;
l2capoutbuf [ 9 ] = 0x00 ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
SDP_Command ( l2capoutbuf , 10 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : serialPortResponse1 ( uint8_t transactionIDHigh , uint8_t transactionIDLow ) {
2013-03-28 09:46:43 +01:00
l2capoutbuf [ 0 ] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU ;
l2capoutbuf [ 1 ] = transactionIDHigh ;
l2capoutbuf [ 2 ] = transactionIDLow ;
l2capoutbuf [ 3 ] = 0x00 ; // Parameter Length
l2capoutbuf [ 4 ] = 0x2B ; // Parameter Length
l2capoutbuf [ 5 ] = 0x00 ; // AttributeListsByteCount
l2capoutbuf [ 6 ] = 0x26 ; // AttributeListsByteCount
/* Attribute ID/Value Sequence: */
l2capoutbuf [ 7 ] = 0x36 ;
l2capoutbuf [ 8 ] = 0x00 ;
l2capoutbuf [ 9 ] = 0x3C ;
l2capoutbuf [ 10 ] = 0x36 ;
l2capoutbuf [ 11 ] = 0x00 ;
l2capoutbuf [ 12 ] = 0x39 ;
l2capoutbuf [ 13 ] = 0x09 ;
l2capoutbuf [ 14 ] = 0x00 ;
l2capoutbuf [ 15 ] = 0x00 ;
l2capoutbuf [ 16 ] = 0x0A ;
l2capoutbuf [ 17 ] = 0x00 ;
l2capoutbuf [ 18 ] = 0x01 ;
l2capoutbuf [ 19 ] = 0x00 ;
l2capoutbuf [ 20 ] = 0x06 ;
l2capoutbuf [ 21 ] = 0x09 ;
l2capoutbuf [ 22 ] = 0x00 ;
l2capoutbuf [ 23 ] = 0x01 ;
l2capoutbuf [ 24 ] = 0x35 ;
l2capoutbuf [ 25 ] = 0x03 ;
l2capoutbuf [ 26 ] = 0x19 ;
l2capoutbuf [ 27 ] = 0x11 ;
l2capoutbuf [ 28 ] = 0x01 ;
l2capoutbuf [ 29 ] = 0x09 ;
l2capoutbuf [ 30 ] = 0x00 ;
l2capoutbuf [ 31 ] = 0x04 ;
l2capoutbuf [ 32 ] = 0x35 ;
l2capoutbuf [ 33 ] = 0x0C ;
l2capoutbuf [ 34 ] = 0x35 ;
l2capoutbuf [ 35 ] = 0x03 ;
l2capoutbuf [ 36 ] = 0x19 ;
l2capoutbuf [ 37 ] = 0x01 ;
l2capoutbuf [ 38 ] = 0x00 ;
l2capoutbuf [ 39 ] = 0x35 ;
l2capoutbuf [ 40 ] = 0x05 ;
l2capoutbuf [ 41 ] = 0x19 ;
l2capoutbuf [ 42 ] = 0x00 ;
l2capoutbuf [ 43 ] = 0x03 ;
l2capoutbuf [ 44 ] = 0x08 ;
l2capoutbuf [ 45 ] = 0x02 ; // Two extra bytes
l2capoutbuf [ 46 ] = 0x00 ; // 25 (0x19) more bytes to come
l2capoutbuf [ 47 ] = 0x19 ;
SDP_Command ( l2capoutbuf , 48 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : serialPortResponse2 ( uint8_t transactionIDHigh , uint8_t transactionIDLow ) {
2013-03-28 09:46:43 +01:00
l2capoutbuf [ 0 ] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU ;
l2capoutbuf [ 1 ] = transactionIDHigh ;
l2capoutbuf [ 2 ] = transactionIDLow ;
l2capoutbuf [ 3 ] = 0x00 ; // Parameter Length
l2capoutbuf [ 4 ] = 0x1C ; // Parameter Length
l2capoutbuf [ 5 ] = 0x00 ; // AttributeListsByteCount
l2capoutbuf [ 6 ] = 0x19 ; // AttributeListsByteCount
/* Attribute ID/Value Sequence: */
l2capoutbuf [ 7 ] = 0x01 ;
l2capoutbuf [ 8 ] = 0x09 ;
l2capoutbuf [ 9 ] = 0x00 ;
l2capoutbuf [ 10 ] = 0x06 ;
l2capoutbuf [ 11 ] = 0x35 ;
l2capoutbuf [ 12 ] = 0x09 ;
l2capoutbuf [ 13 ] = 0x09 ;
l2capoutbuf [ 14 ] = 0x65 ;
l2capoutbuf [ 15 ] = 0x6E ;
l2capoutbuf [ 16 ] = 0x09 ;
l2capoutbuf [ 17 ] = 0x00 ;
l2capoutbuf [ 18 ] = 0x6A ;
l2capoutbuf [ 19 ] = 0x09 ;
l2capoutbuf [ 20 ] = 0x01 ;
l2capoutbuf [ 21 ] = 0x00 ;
l2capoutbuf [ 22 ] = 0x09 ;
l2capoutbuf [ 23 ] = 0x01 ;
l2capoutbuf [ 24 ] = 0x00 ;
l2capoutbuf [ 25 ] = 0x25 ;
l2capoutbuf [ 26 ] = 0x05 ; // Name length
l2capoutbuf [ 27 ] = ' T ' ;
l2capoutbuf [ 28 ] = ' K ' ;
l2capoutbuf [ 29 ] = ' J ' ;
l2capoutbuf [ 30 ] = ' S ' ;
l2capoutbuf [ 31 ] = ' P ' ;
l2capoutbuf [ 32 ] = 0x00 ; // No more data
SDP_Command ( l2capoutbuf , 33 ) ;
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : l2capResponse1 ( uint8_t transactionIDHigh , uint8_t transactionIDLow ) {
2013-03-28 09:46:43 +01:00
serialPortResponse1 ( transactionIDHigh , transactionIDLow ) ; // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again
2012-08-04 12:20:47 +02:00
}
2013-03-28 09:46:43 +01:00
2014-04-21 18:41:39 +02:00
void SPPServer : : l2capResponse2 ( uint8_t transactionIDHigh , uint8_t transactionIDLow ) {
2013-03-28 09:46:43 +01:00
serialPortResponse2 ( transactionIDHigh , transactionIDLow ) ; // Same data as serialPortResponse2
2012-08-04 12:20:47 +02:00
}
/************************************************************/
/* RFCOMM Commands */
/************************************************************/
2014-04-21 18:41:39 +02:00
void SPPServer : : RFCOMM_Command ( uint8_t * data , uint8_t nbytes ) {
2013-03-28 09:46:43 +01:00
pBtd - > L2CAP_Command ( hci_handle , data , nbytes , rfcomm_scid [ 0 ] , rfcomm_scid [ 1 ] ) ;
2012-08-04 12:20:47 +02:00
}