3      Copyright (C) Dean Camera, 2010. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, distribute, and sell this  
  13   software and its documentation for any purpose is hereby granted 
  14   without fee, provided that the above copyright notice appear in  
  15   all copies and that both that the copyright notice and this 
  16   permission notice and warranty disclaimer appear in supporting  
  17   documentation, and that the name of the author not be used in  
  18   advertising or publicity pertaining to distribution of the  
  19   software without specific, written prior permission. 
  21   The author disclaim all warranties with regard to this 
  22   software, including all implied warranties of merchantability 
  23   and fitness.  In no event shall the author be liable for any 
  24   special, indirect or consequential damages or any damages 
  25   whatsoever resulting from loss of use, data or profits, whether 
  26   in an action of contract, negligence or other tortious action, 
  27   arising out of or in connection with the use or performance of 
  33  *  RFCOMM layer module. This module manages the RFCOMM layer of the 
  34  *  stack, providing virtual serial port channels on top of the lower 
  38 #define  INCLUDE_FROM_RFCOMM_C 
  41 /** 8-Bit CRC table used by the FCS field of each RFCOMM encoded frame, sourced from the ETSI TS 101 369 V7.2.0 
  42  *  specification document, upon which the RFCOMM specification is based. 
  44 const uint8_t CRC8_Table
[256] PROGMEM 
= 
  46                 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 
  47                 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 
  48                 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 
  49                 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, 
  50                 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, 
  51                 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, 
  52                 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, 
  53                 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, 
  54                 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, 
  55                 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, 
  56                 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, 
  57                 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, 
  58                 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, 
  59                 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, 
  60                 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, 
  61                 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF 
  64 /** RFCOMM channel state structure, to retain information about each open channel in the RFCOMM multiplexer. */ 
  65 RFCOMM_Channel_t RFCOMM_Channels
[RFCOMM_MAX_OPEN_CHANNELS
]; 
  68 /** Initialises the RFCOMM service, ready for new connections from a SDP client. */ 
  69 void RFCOMM_Initialize(void) 
  71         /* Reset the RFCOMM channel structures, to invalidate any configured RFCOMM channels */ 
  72         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
  73           RFCOMM_Channels
[i
].State 
= RFCOMM_Channel_Closed
; 
  76 /** Services all the logical RFCOMM channels on the given ACL channel, sending any RFCOMM control requests to 
  77  *  the remote device as needed to establish new logical RFCOMM channels. This function should be called repeatedly 
  78  *  in the main program loop when an ACL channel with an RFCOMM PSM has been established between the local and remote 
  81  *  \param[in] ACLChannel  ACL channel which has been previously opened to handle RFCOMM traffic between devices 
  83 void RFCOMM_ServiceChannels(Bluetooth_Channel_t
* const ACLChannel
) 
  85         /* Abort if the RFCOMM ACL channel is not currently open */ 
  86         if ((ACLChannel 
== NULL
) || (ACLChannel
->State 
!= BT_Channel_Open
)) 
  89         /* Loop through each of the RFCOMM channels, send any required RFCOMM control commands */ 
  90         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
  92                 RFCOMM_Channel_t
* RFCOMMChannel 
= &RFCOMM_Channels
[i
]; 
  94                 if (RFCOMMChannel
->State 
== RFCOMM_Channel_Configure
) 
  96                         /* Check if the local signals have not yet been sent on the current channel */ 
  97                         if (!(RFCOMMChannel
->ConfigFlags 
& RFCOMM_CONFIG_LOCALSIGNALSSENT
)) 
  99                                 /* Indicate that the local signals have been sent, transmit them to the remote device */ 
 100                                 RFCOMMChannel
->ConfigFlags 
|= RFCOMM_CONFIG_LOCALSIGNALSSENT
; 
 101                                 RFCOMM_SendChannelSignals(RFCOMMChannel
, ACLChannel
); 
 104                         /* If signals have been configured in both directions, progress to the open state */ 
 105                         if ((RFCOMMChannel
->ConfigFlags 
& (RFCOMM_CONFIG_REMOTESIGNALS 
| RFCOMM_CONFIG_LOCALSIGNALS
)) == 
 106                                                           (RFCOMM_CONFIG_REMOTESIGNALS 
| RFCOMM_CONFIG_LOCALSIGNALS
)) 
 108                                 RFCOMMChannel
->State 
= RFCOMM_Channel_Open
; 
 109                                 RFCOMM_ChannelOpened(RFCOMMChannel
); 
 115 /** Processes an incoming RFCOMM packet on an ACL channel which has been previously opened between the local and 
 116  *  a remote device to handle RFCOMM traffic. 
 118  *  \param[in] Data        Incoming packet data containing the RFCOMM packet 
 119  *  \param[in] ACLChannel  ACL channel the request was issued to by the remote device 
 121 void RFCOMM_ProcessPacket(void* Data
, 
 122                           Bluetooth_Channel_t
* const ACLChannel
) 
 124         const RFCOMM_Header_t
* FrameHeader  
= (const RFCOMM_Header_t
*)Data
; 
 125         const uint8_t*         FrameData    
= (const uint8_t*)Data 
+ sizeof(RFCOMM_Header_t
); 
 126         uint16_t               FrameDataLen 
= RFCOMM_GetVariableFieldValue(&FrameData
); 
 128         /* Decode the RFCOMM frame type from the header */ 
 129         switch (FrameHeader
->Control 
& ~FRAME_POLL_FINAL
) 
 131                 case RFCOMM_Frame_DM
: 
 132                         RFCOMM_ProcessDM(&FrameHeader
->Address
, ACLChannel
); 
 134                 case RFCOMM_Frame_DISC
: 
 135                         RFCOMM_ProcessDISC(&FrameHeader
->Address
, ACLChannel
); 
 137                 case RFCOMM_Frame_SABM
: 
 138                         RFCOMM_ProcessSABM(&FrameHeader
->Address
, ACLChannel
); 
 140                 case RFCOMM_Frame_UA
: 
 141                         RFCOMM_ProcessUA(&FrameHeader
->Address
, ACLChannel
); 
 143                 case RFCOMM_Frame_UIH
: 
 144                         RFCOMM_ProcessUIH(&FrameHeader
->Address
, FrameDataLen
, FrameData
, ACLChannel
); 
 147                         BT_RFCOMM_DEBUG(1, "<< Unknown Frame Received"); 
 152 /** Sends an RFCOMM notification to the remote device that the local terminal control signals (located in the 
 153  *  "Local" structure of the RFCOMM channel) have changed, pushing the new signals to the remote device. 
 155  *  \param[in] RFCOMMChannel  RFCOMM logical channel whose local terminal signals have changed 
 156  *  \param[in] ACLChannel     ACL channel which has been opened to carry RFCOMM traffic between devices 
 158 void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t
* const RFCOMMChannel
, 
 159                                Bluetooth_Channel_t
* const ACLChannel
) 
 161         BT_RFCOMM_DEBUG(1, ">> MSC Command"); 
 162         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel
->DLCI
); 
 166                 RFCOMM_Command_t        CommandHeader
; 
 168                 RFCOMM_MSC_Parameters_t Params
; 
 171         MSCommand
.CommandHeader      
= (RFCOMM_Command_t
){.Command 
= RFCOMM_Control_ModemStatus
, .EA 
= true, .CR 
= true}; 
 172         MSCommand
.Length             
= (sizeof(MSCommand
.Params
) << 1) | 0x01; 
 173         MSCommand
.Params
.Channel     
= (RFCOMM_Address_t
){.DLCI 
= RFCOMMChannel
->DLCI
, .EA 
= true, .CR 
= true}; 
 174         MSCommand
.Params
.Signals     
= RFCOMMChannel
->Local
.Signals
; 
 175         MSCommand
.Params
.BreakSignal 
= RFCOMMChannel
->Local
.BreakSignal
; 
 177         /* Send the MSC command to the remote device */ 
 178         RFCOMM_SendFrame(RFCOMM_CONTROL_DLCI
, true, RFCOMM_Frame_UIH
, sizeof(MSCommand
), &MSCommand
, ACLChannel
);        
 181 /** Sends new data through an open logical RFCOMM channel. This should be used to transmit data through a 
 182  *  RFCOMM channel once it has been opened. 
 184  *  \param[in] DataLen        Length of the RFCOMM data to send, in bytes 
 185  *  \param[in] Data           Pointer to a buffer where the data to send is located 
 186  *  \param[in] RFCOMMChannel  RFCOMM logical channel which is to be transmitted to 
 187  *  \param[in] ACLChannel     ACL channel which has been opened to carry RFCOMM traffic between devices 
 189 void RFCOMM_SendData(const uint16_t DataLen
, 
 191                      const RFCOMM_Channel_t
* const RFCOMMChannel
, 
 192                      Bluetooth_Channel_t
* const ACLChannel
) 
 194         if (RFCOMMChannel
->State 
!= RFCOMM_Channel_Open
) 
 197         BT_RFCOMM_DEBUG(1, ">> UIH Frame"); 
 198         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel
->DLCI
); 
 200         /* Send the MSC command to the remote device */ 
 201         RFCOMM_SendFrame(RFCOMMChannel
->DLCI
, false, RFCOMM_Frame_UIH
, DataLen
, Data
, ACLChannel
);               
 204 RFCOMM_Channel_t
* RFCOMM_GetFreeChannelEntry(const uint8_t DLCI
) 
 206         /* Find a free entry in the RFCOMM channel multiplexer state array */ 
 207         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
 209                 RFCOMM_Channel_t
* RFCOMMChannel 
= &RFCOMM_Channels
[i
]; 
 211                 /* If the channel's state is closed, the channel state entry is free */ 
 212                 if (RFCOMMChannel
->State 
== RFCOMM_Channel_Closed
) 
 214                         RFCOMMChannel
->DLCI               
= DLCI
; 
 215                         RFCOMMChannel
->State              
= RFCOMM_Channel_Configure
; 
 216                         RFCOMMChannel
->Priority           
= 7 + (RFCOMMChannel
->DLCI 
& 0xF8); 
 217                         RFCOMMChannel
->MTU                
= 0xFFFF; 
 218                         RFCOMMChannel
->Remote
.Signals     
= 0 | (1 << 0); 
 219                         RFCOMMChannel
->Remote
.BreakSignal 
= 0 | (1 << 0); 
 220                         RFCOMMChannel
->Local
.Signals      
= RFCOMM_SIGNAL_RTC 
| RFCOMM_SIGNAL_RTR 
| RFCOMM_SIGNAL_DV 
| (1 << 0); 
 221                         RFCOMMChannel
->Local
.BreakSignal  
= 0 | (1 << 0); 
 222                         RFCOMMChannel
->ConfigFlags        
= 0; 
 224                         return RFCOMMChannel
; 
 231 RFCOMM_Channel_t
* RFCOMM_GetChannelData(const uint8_t DLCI
) 
 233         /* Search through the RFCOMM channel list, looking for the specified channel */ 
 234         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
 236                 RFCOMM_Channel_t
* CurrRFCOMMChannel 
= &RFCOMM_Channels
[i
]; 
 238                 /* If the current non-closed channel's DLCI matches the search DLCI, return it to the caller */ 
 239                 if ((CurrRFCOMMChannel
->State 
!= RFCOMM_Channel_Closed
) && (CurrRFCOMMChannel
->DLCI 
== DLCI
)) 
 240                   return CurrRFCOMMChannel
; 
 243         /* Channel not found in the channel state table, return failure */ 
 247 uint16_t RFCOMM_GetVariableFieldValue(const uint8_t** BufferPos
) 
 250         uint8_t SecondOctet 
= 0; 
 252         FirstOctet 
= **BufferPos
; 
 255         /* If the field size is more than a single byte, fetch the next byte in the variable length field */ 
 256         if (!(FirstOctet 
& 0x01)) 
 258                 SecondOctet 
= **BufferPos
; 
 261                 /* Discard any remaining bytes in the variable length field that won't fit in the return value */ 
 262                 while (!(**BufferPos 
& 0x01)) 
 266         /* Bit-shift the bytes that comprise the variable length field so that they form a single integer */ 
 267         return (((uint16_t)SecondOctet 
<< 7) | FirstOctet 
>> 1); 
 270 void RFCOMM_SendFrame(const uint8_t DLCI
, 
 271                       const bool CommandResponse
, 
 272                       const uint8_t Control
, 
 273                       const uint16_t DataLen
, 
 275                       Bluetooth_Channel_t
* const ACLChannel
) 
 279                 RFCOMM_Header_t FrameHeader
; 
 280                 uint8_t         Size
[(DataLen 
< 128) ? 
1 : 2]; 
 281                 uint8_t         Data
[DataLen
]; 
 285         /* Set the frame header values to the specified address and frame type */ 
 286         ResponsePacket
.FrameHeader
.Control 
= Control
; 
 287         ResponsePacket
.FrameHeader
.Address 
= (RFCOMM_Address_t
){.DLCI 
= DLCI
, .EA   
= true, .CR 
= CommandResponse
}; 
 289         /* Set the lower 7 bits of the packet length */ 
 290         ResponsePacket
.Size
[0] = (DataLen 
<< 1); 
 292         /* Terminate the size field if size is 7 bits or lower, otherwise set the upper 8 bits of the length */ 
 294           ResponsePacket
.Size
[0] |= 0x01; 
 296           ResponsePacket
.Size
[1]  = (DataLen 
>> 7); 
 298         /* Copy over the packet data from the source buffer to the response packet buffer */ 
 299         memcpy(ResponsePacket
.Data
, Data
, DataLen
); 
 301         /* Determine the length of the frame which is to be used to calculate the CRC value */ 
 302         uint8_t CRCLength 
= sizeof(ResponsePacket
.FrameHeader
); 
 304         /* UIH frames do not have the CRC calculated on the Size field in the response, all other frames do */ 
 305         if ((Control 
& ~FRAME_POLL_FINAL
) != RFCOMM_Frame_UIH
) 
 306           CRCLength 
+= sizeof(ResponsePacket
.Size
); 
 308         /* Calculate the frame checksum from the appropriate fields */ 
 309         ResponsePacket
.FCS 
= RFCOMM_GetFCSValue(&ResponsePacket
, CRCLength
); 
 311         /* Send the completed response packet to the sender */ 
 312         Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), ACLChannel
); 
 315 static uint8_t RFCOMM_GetFCSValue(const void* FrameStart
, 
 320         /* Calculate new Frame CRC value via the given data bytes and the CRC table */ 
 321         for (uint8_t i 
= 0; i 
< Length
; i
++) 
 322           FCS 
= pgm_read_byte(&CRC8_Table
[FCS 
^ ((const uint8_t*)FrameStart
)[i
]]); 
 327 static void RFCOMM_ProcessDM(const RFCOMM_Address_t
* const FrameAddress
, 
 328                              Bluetooth_Channel_t
* const ACLChannel
) 
 330         BT_RFCOMM_DEBUG(1, "<< DM Received"); 
 331         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 334 static void RFCOMM_ProcessDISC(const RFCOMM_Address_t
* const FrameAddress
, 
 335                                Bluetooth_Channel_t
* const ACLChannel
) 
 337         BT_RFCOMM_DEBUG(1, "<< DISC Received"); 
 338         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 340         RFCOMM_Channel_t
* RFCOMMChannel 
= RFCOMM_GetChannelData(FrameAddress
->DLCI
); 
 342         /* If the requested channel is currently open, destroy it */ 
 343         if (RFCOMMChannel 
!= NULL
) 
 344           RFCOMMChannel
->State 
= RFCOMM_Channel_Closed
; 
 346         BT_RFCOMM_DEBUG(1, ">> UA Sent"); 
 347         RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_UA 
| FRAME_POLL_FINAL
), 0, NULL
, ACLChannel
); 
 350 static void RFCOMM_ProcessSABM(const RFCOMM_Address_t
* const FrameAddress
, 
 351                                Bluetooth_Channel_t
* const ACLChannel
) 
 353         BT_RFCOMM_DEBUG(1, "<< SABM Received"); 
 354         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 356         if (FrameAddress
->DLCI 
== RFCOMM_CONTROL_DLCI
) 
 358                 BT_RFCOMM_DEBUG(1, ">> UA Sent"); 
 360                 /* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */ 
 361                 RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_UA 
| FRAME_POLL_FINAL
), 0, NULL
, ACLChannel
); 
 366         /* Find the existing channel's entry in the channel table */ 
 367         RFCOMM_Channel_t
* RFCOMMChannel 
= RFCOMM_GetChannelData(FrameAddress
->DLCI
); 
 369         /* Existing entry not found, create a new entry for the channel */ 
 370         if (RFCOMMChannel 
== NULL
) 
 371           RFCOMMChannel 
= RFCOMM_GetFreeChannelEntry(FrameAddress
->DLCI
); 
 373         /* If space was found in the channel table for the new channel, ACK the request */ 
 374         if (RFCOMMChannel 
!= NULL
) 
 376                 BT_RFCOMM_DEBUG(1, ">> UA Sent"); 
 378                 /* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */ 
 379                 RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_UA 
| FRAME_POLL_FINAL
), 0, NULL
, ACLChannel
); 
 383                 BT_RFCOMM_DEBUG(1, ">> DM Sent"); 
 385                 /* No free channel in the multiplexer - decline the SABM by sending a DM frame */ 
 386                 RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_DM 
| FRAME_POLL_FINAL
), 0, NULL
, ACLChannel
); 
 390 static void RFCOMM_ProcessUA(const RFCOMM_Address_t
* const FrameAddress
, 
 391                              Bluetooth_Channel_t
* const ACLChannel
) 
 393         BT_RFCOMM_DEBUG(1, "<< UA Received"); 
 394         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 397 static void RFCOMM_ProcessUIH(const RFCOMM_Address_t
* const FrameAddress
, 
 398                               const uint16_t FrameLength
,  
 399                               const uint8_t* FrameData
, 
 400                               Bluetooth_Channel_t
* const ACLChannel
) 
 402         if (FrameAddress
->DLCI 
== RFCOMM_CONTROL_DLCI
) 
 404                 RFCOMM_ProcessControlCommand(FrameData
, ACLChannel
); 
 408         BT_RFCOMM_DEBUG(1, "<< UIH Received"); 
 409         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 410         BT_RFCOMM_DEBUG(2, "-- Length 0x%02X", FrameLength
); 
 412         RFCOMM_Channel_t
* RFCOMMChannel 
= RFCOMM_GetChannelData(FrameAddress
->DLCI
); 
 414         if (RFCOMMChannel 
!= NULL
) 
 415           RFCOMM_DataReceived(RFCOMMChannel
, FrameLength
, FrameData
);