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 /** Initializes 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 confiured RFCOMM channels */ 
  72         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
  73           RFCOMM_Channels
[i
].State 
= RFCOMM_Channel_Closed
; 
  76 void RFCOMM_ServiceChannels(Bluetooth_Channel_t
* const BluetoothChannel
) 
  78         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
  80                 RFCOMM_Channel_t
* RFCOMMChannel 
= &RFCOMM_Channels
[i
]; 
  82                 if (RFCOMMChannel
->State 
== RFCOMM_Channel_Configure
) 
  84                         /* Check if the local signals have not yet been sent on the current channel */ 
  85                         if (!(RFCOMMChannel
->ConfigFlags 
& RFCOMM_CONFIG_LOCALSIGNALSSENT
)) 
  87                                 /* Indicate that the local signals have been sent, transmit them to the remote device */ 
  88                                 RFCOMMChannel
->ConfigFlags 
|= RFCOMM_CONFIG_LOCALSIGNALSSENT
; 
  89                                 RFCOMM_SendChannelSignals(RFCOMMChannel
, BluetoothChannel
); 
  92                         /* If signals have been configured in both directions, progress to the open state */ 
  93                         if ((RFCOMMChannel
->ConfigFlags 
& (RFCOMM_CONFIG_REMOTESIGNALS 
| RFCOMM_CONFIG_LOCALSIGNALS
)) == 
  94                                                           (RFCOMM_CONFIG_REMOTESIGNALS 
| RFCOMM_CONFIG_LOCALSIGNALS
)) 
  96                                 RFCOMMChannel
->State 
= RFCOMM_Channel_Open
; 
  97                                 RFCOMM_ChannelOpened(RFCOMMChannel
); 
 103 void RFCOMM_ProcessPacket(void* Data
, Bluetooth_Channel_t
* const Channel
) 
 105         const RFCOMM_Header_t
* FrameHeader  
= (const RFCOMM_Header_t
*)Data
; 
 106         const uint8_t*         FrameData    
= (const uint8_t*)Data 
+ sizeof(RFCOMM_Header_t
); 
 107         uint16_t               FrameDataLen 
= RFCOMM_GetVariableFieldValue(&FrameData
); 
 109         /* Decode the RFCOMM frame type from the header */ 
 110         switch (FrameHeader
->Control 
& ~FRAME_POLL_FINAL
) 
 112                 case RFCOMM_Frame_DM
: 
 113                         RFCOMM_ProcessDM(&FrameHeader
->Address
, Channel
); 
 115                 case RFCOMM_Frame_DISC
: 
 116                         RFCOMM_ProcessDISC(&FrameHeader
->Address
, Channel
); 
 118                 case RFCOMM_Frame_SABM
: 
 119                         RFCOMM_ProcessSABM(&FrameHeader
->Address
, Channel
); 
 121                 case RFCOMM_Frame_UA
: 
 122                         RFCOMM_ProcessUA(&FrameHeader
->Address
, Channel
); 
 124                 case RFCOMM_Frame_UIH
: 
 125                         RFCOMM_ProcessUIH(&FrameHeader
->Address
, FrameDataLen
, FrameData
, Channel
); 
 128                         BT_RFCOMM_DEBUG(1, "<< Unknown Frame Received"); 
 133 void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t
* const RFCOMMChannel
, Bluetooth_Channel_t
* const BluetoothChannel
) 
 135         BT_RFCOMM_DEBUG(1, ">> MSC Command"); 
 136         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel
->DLCI
); 
 140                 RFCOMM_Command_t        CommandHeader
; 
 142                 RFCOMM_MSC_Parameters_t Params
; 
 145         MSCommand
.CommandHeader      
= (RFCOMM_Command_t
){.Command 
= RFCOMM_Control_ModemStatus
, .EA 
= true, .CR 
= true}; 
 146         MSCommand
.Length             
= (sizeof(MSCommand
.Params
) << 1) | 0x01; 
 147         MSCommand
.Params
.Channel     
= (RFCOMM_Address_t
){.DLCI 
= RFCOMMChannel
->DLCI
, .EA 
= true, .CR 
= true}; 
 148         MSCommand
.Params
.Signals     
= RFCOMMChannel
->Local
.Signals
; 
 149         MSCommand
.Params
.BreakSignal 
= RFCOMMChannel
->Local
.BreakSignal
; 
 151         /* Send the MSC command to the remote device */ 
 152         RFCOMM_SendFrame(RFCOMM_CONTROL_DLCI
, true, RFCOMM_Frame_UIH
, sizeof(MSCommand
), &MSCommand
, BluetoothChannel
);  
 155 void RFCOMM_SendData(const uint16_t DataLen
, const uint8_t* Data
, const RFCOMM_Channel_t
* const RFCOMMChannel
, 
 156                      Bluetooth_Channel_t
* const BluetoothChannel
) 
 158         if (RFCOMMChannel
->State 
!= RFCOMM_Channel_Open
) 
 161         BT_RFCOMM_DEBUG(1, ">> UIH Frame"); 
 162         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel
->DLCI
); 
 164         /* Send the MSC command to the remote device */ 
 165         RFCOMM_SendFrame(RFCOMMChannel
->DLCI
, false, RFCOMM_Frame_UIH
, DataLen
, Data
, BluetoothChannel
);                 
 168 RFCOMM_Channel_t
* RFCOMM_GetFreeChannelEntry(const uint8_t DLCI
) 
 170         /* Find a free entry in the RFCOMM channel multiplexer state array */ 
 171         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
 173                 RFCOMM_Channel_t
* RFCOMMChannel 
= &RFCOMM_Channels
[i
]; 
 175                 /* If the channel's state is closed, the channel state entry is free */ 
 176                 if (RFCOMMChannel
->State 
== RFCOMM_Channel_Closed
) 
 178                         RFCOMMChannel
->DLCI               
= DLCI
; 
 179                         RFCOMMChannel
->State              
= RFCOMM_Channel_Configure
; 
 180                         RFCOMMChannel
->Priority           
= 7 + (RFCOMMChannel
->DLCI 
& 0xF8); 
 181                         RFCOMMChannel
->MTU                
= 0xFFFF; 
 182                         RFCOMMChannel
->Remote
.Signals     
= 0 | (1 << 0); 
 183                         RFCOMMChannel
->Remote
.BreakSignal 
= 0 | (1 << 0); 
 184                         RFCOMMChannel
->Local
.Signals      
= RFCOMM_SIGNAL_RTC 
| RFCOMM_SIGNAL_RTR 
| RFCOMM_SIGNAL_DV 
| (1 << 0); 
 185                         RFCOMMChannel
->Local
.BreakSignal  
= 0 | (1 << 0); 
 186                         RFCOMMChannel
->ConfigFlags        
= 0; 
 188                         return RFCOMMChannel
; 
 195 RFCOMM_Channel_t
* RFCOMM_GetChannelData(const uint8_t DLCI
) 
 197         /* Search through the RFCOMM channel list, looking for the specified channel */ 
 198         for (uint8_t i 
= 0; i 
< RFCOMM_MAX_OPEN_CHANNELS
; i
++) 
 200                 RFCOMM_Channel_t
* CurrRFCOMMChannel 
= &RFCOMM_Channels
[i
]; 
 202                 /* If the current non-closed channel's DLCI matches the search DLCI, return it to the caller */ 
 203                 if ((CurrRFCOMMChannel
->State 
!= RFCOMM_Channel_Closed
) && (CurrRFCOMMChannel
->DLCI 
== DLCI
)) 
 204                   return CurrRFCOMMChannel
; 
 207         /* Channel not found in the channel state table, return failure */ 
 211 uint16_t RFCOMM_GetVariableFieldValue(const uint8_t** BufferPos
) 
 214         uint8_t SecondOctet 
= 0; 
 216         FirstOctet 
= **BufferPos
; 
 219         /* If the field size is more than a single byte, fetch the next byte in the variable length field */ 
 220         if (!(FirstOctet 
& 0x01)) 
 222                 SecondOctet 
= **BufferPos
; 
 225                 /* Discard any remaining bytes in the variable length field that won't fit in the return value */ 
 226                 while (!(**BufferPos 
& 0x01)) 
 230         /* Bitshift the bytes that comprise the variable length field so that they form a single integer */ 
 231         return (((uint16_t)SecondOctet 
<< 7) | FirstOctet 
>> 1); 
 234 void RFCOMM_SendFrame(const uint8_t DLCI
, const bool CommandResponse
, const uint8_t Control
, const uint16_t DataLen
, 
 235                       const void* Data
, Bluetooth_Channel_t
* const Channel
) 
 239                 RFCOMM_Header_t FrameHeader
; 
 240                 uint8_t         Size
[(DataLen 
< 128) ? 
1 : 2]; 
 241                 uint8_t         Data
[DataLen
]; 
 245         /* Set the frame header values to the specified address and frame type */ 
 246         ResponsePacket
.FrameHeader
.Control 
= Control
; 
 247         ResponsePacket
.FrameHeader
.Address 
= (RFCOMM_Address_t
){.DLCI 
= DLCI
, .EA   
= true, .CR 
= CommandResponse
}; 
 249         /* Set the lower 7 bits of the packet length */ 
 250         ResponsePacket
.Size
[0] = (DataLen 
<< 1); 
 252         /* Terminate the size field if size is 7 bits or lower, otherwise set the upper 8 bits of the length */ 
 254           ResponsePacket
.Size
[0] |= 0x01; 
 256           ResponsePacket
.Size
[1]  = (DataLen 
>> 7); 
 258         /* Copy over the packet data from the source buffer to the response packet buffer */ 
 259         memcpy(ResponsePacket
.Data
, Data
, DataLen
); 
 261         /* Determine the length of the frame which is to be used to calculate the CRC value */ 
 262         uint8_t CRCLength 
= sizeof(ResponsePacket
.FrameHeader
); 
 264         /* UIH frames do not have the CRC calculated on the Size field in the response, all other frames do */ 
 265         if ((Control 
& ~FRAME_POLL_FINAL
) != RFCOMM_Frame_UIH
) 
 266           CRCLength 
+= sizeof(ResponsePacket
.Size
); 
 268         /* Calculate the frame checksum from the appropriate fields */ 
 269         ResponsePacket
.FCS 
= RFCOMM_GetFCSValue(&ResponsePacket
, CRCLength
); 
 271         /* Send the completed response packet to the sender */ 
 272         Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), Channel
); 
 275 static uint8_t RFCOMM_GetFCSValue(const void* FrameStart
, uint8_t Length
) 
 279         /* Calculate new Frame CRC value via the given data bytes and the CRC table */ 
 280         for (uint8_t i 
= 0; i 
< Length
; i
++) 
 281           FCS 
= pgm_read_byte(&CRC8_Table
[FCS 
^ ((uint8_t*)FrameStart
)[i
]]); 
 286 static void RFCOMM_ProcessDM(const RFCOMM_Address_t
* const FrameAddress
, Bluetooth_Channel_t
* const Channel
) 
 288         BT_RFCOMM_DEBUG(1, "<< DM Received"); 
 289         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 292 static void RFCOMM_ProcessDISC(const RFCOMM_Address_t
* const FrameAddress
, Bluetooth_Channel_t
* const Channel
) 
 294         BT_RFCOMM_DEBUG(1, "<< DISC Received"); 
 295         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 297         RFCOMM_Channel_t
* RFCOMMChannel 
= RFCOMM_GetChannelData(FrameAddress
->DLCI
); 
 299         /* If the requested channel is currently open, destroy it */ 
 300         if (RFCOMMChannel 
!= NULL
) 
 301           RFCOMMChannel
->State 
= RFCOMM_Channel_Closed
; 
 303         BT_RFCOMM_DEBUG(1, ">> UA Sent"); 
 304         RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_UA 
| FRAME_POLL_FINAL
), 0, NULL
, Channel
); 
 307 static void RFCOMM_ProcessSABM(const RFCOMM_Address_t
* const FrameAddress
, Bluetooth_Channel_t
* const Channel
) 
 309         BT_RFCOMM_DEBUG(1, "<< SABM Received"); 
 310         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 312         if (FrameAddress
->DLCI 
== RFCOMM_CONTROL_DLCI
) 
 314                 BT_RFCOMM_DEBUG(1, ">> UA Sent"); 
 316                 /* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */ 
 317                 RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_UA 
| FRAME_POLL_FINAL
), 0, NULL
, Channel
); 
 322         /* Find the existing channel's entry in the channel table */ 
 323         RFCOMM_Channel_t
* RFCOMMChannel 
= RFCOMM_GetChannelData(FrameAddress
->DLCI
); 
 325         /* Existing entry not found, create a new entry for the channel */ 
 326         if (RFCOMMChannel 
== NULL
) 
 327           RFCOMMChannel 
= RFCOMM_GetFreeChannelEntry(FrameAddress
->DLCI
); 
 329         /* If space was found in the channel table for the new channel, ACK the request */ 
 330         if (RFCOMMChannel 
!= NULL
) 
 332                 BT_RFCOMM_DEBUG(1, ">> UA Sent"); 
 334                 /* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */ 
 335                 RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_UA 
| FRAME_POLL_FINAL
), 0, NULL
, Channel
); 
 339                 BT_RFCOMM_DEBUG(1, ">> DM Sent"); 
 341                 /* No free channel in the multiplexer - decline the SABM by sending a DM frame */ 
 342                 RFCOMM_SendFrame(FrameAddress
->DLCI
, true, (RFCOMM_Frame_DM 
| FRAME_POLL_FINAL
), 0, NULL
, Channel
); 
 346 static void RFCOMM_ProcessUA(const RFCOMM_Address_t
* const FrameAddress
, Bluetooth_Channel_t
* const Channel
) 
 348         BT_RFCOMM_DEBUG(1, "<< UA Received"); 
 349         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 352 static void RFCOMM_ProcessUIH(const RFCOMM_Address_t
* const FrameAddress
, const uint16_t FrameLength
,  
 353                               const uint8_t* FrameData
, Bluetooth_Channel_t
* const Channel
) 
 355         if (FrameAddress
->DLCI 
== RFCOMM_CONTROL_DLCI
) 
 357                 RFCOMM_ProcessControlCommand(FrameData
, Channel
); 
 361         BT_RFCOMM_DEBUG(1, "<< UIH Received"); 
 362         BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress
->DLCI
); 
 363         BT_RFCOMM_DEBUG(2, "-- Length 0x%02X", FrameLength
); 
 365         RFCOMM_Channel_t
* RFCOMMChannel 
= RFCOMM_GetChannelData(FrameAddress
->DLCI
); 
 367         if (RFCOMMChannel 
!= NULL
) 
 368           RFCOMM_DataReceived(RFCOMMChannel
, FrameLength
, FrameData
);