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
);