Add a new RFCOMM_ChannelOpened() callback event for when logical RFCOMM channels...
[pub/USBasp.git] / Demos / Host / Incomplete / BluetoothHost / Lib / RFCOMM.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 /** \file
32 *
33 * RFCOMM layer module. This module manages the RFCOMM layer of the
34 * stack, providing virtual serial port channels on top of the lower
35 * L2CAP layer.
36 */
37
38 #define INCLUDE_FROM_RFCOMM_C
39 #include "RFCOMM.h"
40
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.
43 */
44 const uint8_t CRC8_Table[256] PROGMEM =
45 {
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
62 };
63
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];
66
67
68 /** Initializes the RFCOMM service, ready for new connections from a SDP client. */
69 void RFCOMM_Initialize(void)
70 {
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;
74 }
75
76 void RFCOMM_ServiceChannels(Bluetooth_Channel_t* const BluetoothChannel)
77 {
78 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
79 {
80 RFCOMM_Channel_t* RFCOMMChannel = &RFCOMM_Channels[i];
81
82 if (RFCOMMChannel->State == RFCOMM_Channel_Configure)
83 {
84 /* Check if the local signals have not yet been sent on the current channel */
85 if (!(RFCOMMChannel->ConfigFlags & RFCOMM_CONFIG_LOCALSIGNALSSENT))
86 {
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);
90 }
91
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))
95 {
96 RFCOMMChannel->State = RFCOMM_Channel_Open;
97 RFCOMM_ChannelOpened(RFCOMMChannel);
98 }
99 }
100 }
101 }
102
103 void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
104 {
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);
108
109 /* Decode the RFCOMM frame type from the header */
110 switch (FrameHeader->Control & ~FRAME_POLL_FINAL)
111 {
112 case RFCOMM_Frame_DM:
113 RFCOMM_ProcessDM(&FrameHeader->Address, Channel);
114 break;
115 case RFCOMM_Frame_DISC:
116 RFCOMM_ProcessDISC(&FrameHeader->Address, Channel);
117 break;
118 case RFCOMM_Frame_SABM:
119 RFCOMM_ProcessSABM(&FrameHeader->Address, Channel);
120 break;
121 case RFCOMM_Frame_UA:
122 RFCOMM_ProcessUA(&FrameHeader->Address, Channel);
123 break;
124 case RFCOMM_Frame_UIH:
125 RFCOMM_ProcessUIH(&FrameHeader->Address, FrameDataLen, FrameData, Channel);
126 break;
127 default:
128 BT_RFCOMM_DEBUG(1, "<< Unknown Frame Received");
129 break;
130 }
131 }
132
133 void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t* const RFCOMMChannel, Bluetooth_Channel_t* const BluetoothChannel)
134 {
135 BT_RFCOMM_DEBUG(1, ">> MSC Command");
136 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel->DLCI);
137
138 struct
139 {
140 RFCOMM_Command_t CommandHeader;
141 uint8_t Length;
142 RFCOMM_MSC_Parameters_t Params;
143 } MSCommand;
144
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;
150
151 /* Send the MSC command to the remote device */
152 RFCOMM_SendFrame(RFCOMM_CONTROL_DLCI, true, RFCOMM_Frame_UIH, sizeof(MSCommand), &MSCommand, BluetoothChannel);
153 }
154
155 void RFCOMM_SendData(const uint16_t DataLen, const uint8_t* Data, const RFCOMM_Channel_t* const RFCOMMChannel,
156 Bluetooth_Channel_t* const BluetoothChannel)
157 {
158 if (RFCOMMChannel->State != RFCOMM_Channel_Open)
159 return;
160
161 BT_RFCOMM_DEBUG(1, ">> UIH Frame");
162 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel->DLCI);
163
164 /* Send the MSC command to the remote device */
165 RFCOMM_SendFrame(RFCOMMChannel->DLCI, false, RFCOMM_Frame_UIH, DataLen, Data, BluetoothChannel);
166 }
167
168 RFCOMM_Channel_t* RFCOMM_GetFreeChannelEntry(const uint8_t DLCI)
169 {
170 /* Find a free entry in the RFCOMM channel multiplexer state array */
171 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
172 {
173 RFCOMM_Channel_t* RFCOMMChannel = &RFCOMM_Channels[i];
174
175 /* If the channel's state is closed, the channel state entry is free */
176 if (RFCOMMChannel->State == RFCOMM_Channel_Closed)
177 {
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;
187
188 return RFCOMMChannel;
189 }
190 }
191
192 return NULL;
193 }
194
195 RFCOMM_Channel_t* RFCOMM_GetChannelData(const uint8_t DLCI)
196 {
197 /* Search through the RFCOMM channel list, looking for the specified channel */
198 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
199 {
200 RFCOMM_Channel_t* CurrRFCOMMChannel = &RFCOMM_Channels[i];
201
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;
205 }
206
207 /* Channel not found in the channel state table, return failure */
208 return NULL;
209 }
210
211 uint16_t RFCOMM_GetVariableFieldValue(const uint8_t** BufferPos)
212 {
213 uint8_t FirstOctet;
214 uint8_t SecondOctet = 0;
215
216 FirstOctet = **BufferPos;
217 (*BufferPos)++;
218
219 /* If the field size is more than a single byte, fetch the next byte in the variable length field */
220 if (!(FirstOctet & 0x01))
221 {
222 SecondOctet = **BufferPos;
223 (*BufferPos)++;
224
225 /* Discard any remaining bytes in the variable length field that won't fit in the return value */
226 while (!(**BufferPos & 0x01))
227 (*BufferPos)++;
228 }
229
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);
232 }
233
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)
236 {
237 struct
238 {
239 RFCOMM_Header_t FrameHeader;
240 uint8_t Size[(DataLen < 128) ? 1 : 2];
241 uint8_t Data[DataLen];
242 uint8_t FCS;
243 } ResponsePacket;
244
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};
248
249 /* Set the lower 7 bits of the packet length */
250 ResponsePacket.Size[0] = (DataLen << 1);
251
252 /* Terminate the size field if size is 7 bits or lower, otherwise set the upper 8 bits of the length */
253 if (DataLen < 128)
254 ResponsePacket.Size[0] |= 0x01;
255 else
256 ResponsePacket.Size[1] = (DataLen >> 7);
257
258 /* Copy over the packet data from the source buffer to the response packet buffer */
259 memcpy(ResponsePacket.Data, Data, DataLen);
260
261 /* Determine the length of the frame which is to be used to calculate the CRC value */
262 uint8_t CRCLength = sizeof(ResponsePacket.FrameHeader);
263
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);
267
268 /* Calculate the frame checksum from the appropriate fields */
269 ResponsePacket.FCS = RFCOMM_GetFCSValue(&ResponsePacket, CRCLength);
270
271 /* Send the completed response packet to the sender */
272 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), Channel);
273 }
274
275 static uint8_t RFCOMM_GetFCSValue(const void* FrameStart, uint8_t Length)
276 {
277 uint8_t FCS = 0xFF;
278
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]]);
282
283 return ~FCS;
284 }
285
286 static void RFCOMM_ProcessDM(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
287 {
288 BT_RFCOMM_DEBUG(1, "<< DM Received");
289 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
290 }
291
292 static void RFCOMM_ProcessDISC(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
293 {
294 BT_RFCOMM_DEBUG(1, "<< DISC Received");
295 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
296
297 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
298
299 /* If the requested channel is currently open, destroy it */
300 if (RFCOMMChannel != NULL)
301 RFCOMMChannel->State = RFCOMM_Channel_Closed;
302
303 BT_RFCOMM_DEBUG(1, ">> UA Sent");
304 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, Channel);
305 }
306
307 static void RFCOMM_ProcessSABM(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
308 {
309 BT_RFCOMM_DEBUG(1, "<< SABM Received");
310 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
311
312 if (FrameAddress->DLCI == RFCOMM_CONTROL_DLCI)
313 {
314 BT_RFCOMM_DEBUG(1, ">> UA Sent");
315
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);
318
319 return;
320 }
321
322 /* Find the existing channel's entry in the channel table */
323 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
324
325 /* Existing entry not found, create a new entry for the channel */
326 if (RFCOMMChannel == NULL)
327 RFCOMMChannel = RFCOMM_GetFreeChannelEntry(FrameAddress->DLCI);
328
329 /* If space was found in the channel table for the new channel, ACK the request */
330 if (RFCOMMChannel != NULL)
331 {
332 BT_RFCOMM_DEBUG(1, ">> UA Sent");
333
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);
336 }
337 else
338 {
339 BT_RFCOMM_DEBUG(1, ">> DM Sent");
340
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);
343 }
344 }
345
346 static void RFCOMM_ProcessUA(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
347 {
348 BT_RFCOMM_DEBUG(1, "<< UA Received");
349 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
350 }
351
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)
354 {
355 if (FrameAddress->DLCI == RFCOMM_CONTROL_DLCI)
356 {
357 RFCOMM_ProcessControlCommand(FrameData, Channel);
358 return;
359 }
360
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);
364
365 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
366
367 if (RFCOMMChannel != NULL)
368 RFCOMM_DataReceived(RFCOMMChannel, FrameLength, FrameData);
369 }