Correct misspellings in the Bluetooth demo code.
[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 configured 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 /** 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
79 * device.
80 *
81 * \param[in] ACLChannel ACL channel which has been previously opened to handle RFCOMM traffic between devices
82 */
83 void RFCOMM_ServiceChannels(Bluetooth_Channel_t* const ACLChannel)
84 {
85 /* Abort if the RFCOMM ACL channel is not currently open */
86 if ((ACLChannel == NULL) || (ACLChannel->State != BT_Channel_Open))
87 return;
88
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++)
91 {
92 RFCOMM_Channel_t* RFCOMMChannel = &RFCOMM_Channels[i];
93
94 if (RFCOMMChannel->State == RFCOMM_Channel_Configure)
95 {
96 /* Check if the local signals have not yet been sent on the current channel */
97 if (!(RFCOMMChannel->ConfigFlags & RFCOMM_CONFIG_LOCALSIGNALSSENT))
98 {
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);
102 }
103
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))
107 {
108 RFCOMMChannel->State = RFCOMM_Channel_Open;
109 RFCOMM_ChannelOpened(RFCOMMChannel);
110 }
111 }
112 }
113 }
114
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.
117 *
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
120 */
121 void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const ACLChannel)
122 {
123 const RFCOMM_Header_t* FrameHeader = (const RFCOMM_Header_t*)Data;
124 const uint8_t* FrameData = (const uint8_t*)Data + sizeof(RFCOMM_Header_t);
125 uint16_t FrameDataLen = RFCOMM_GetVariableFieldValue(&FrameData);
126
127 /* Decode the RFCOMM frame type from the header */
128 switch (FrameHeader->Control & ~FRAME_POLL_FINAL)
129 {
130 case RFCOMM_Frame_DM:
131 RFCOMM_ProcessDM(&FrameHeader->Address, ACLChannel);
132 break;
133 case RFCOMM_Frame_DISC:
134 RFCOMM_ProcessDISC(&FrameHeader->Address, ACLChannel);
135 break;
136 case RFCOMM_Frame_SABM:
137 RFCOMM_ProcessSABM(&FrameHeader->Address, ACLChannel);
138 break;
139 case RFCOMM_Frame_UA:
140 RFCOMM_ProcessUA(&FrameHeader->Address, ACLChannel);
141 break;
142 case RFCOMM_Frame_UIH:
143 RFCOMM_ProcessUIH(&FrameHeader->Address, FrameDataLen, FrameData, ACLChannel);
144 break;
145 default:
146 BT_RFCOMM_DEBUG(1, "<< Unknown Frame Received");
147 break;
148 }
149 }
150
151 /** Sends an RFCOMM notification to the remote device that the local terminal control signals (located in the
152 * "Local" structure of the RFCOMM channel) have changed, pushing the new signals to the remote device.
153 *
154 * \param[in] RFCOMMChannel RFCOMM logical channel whose local terminal signals have changed
155 * \param[in] ACLChannel ACL channel which has been opened to carry RFCOMM traffic between devices
156 */
157 void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t* const RFCOMMChannel, Bluetooth_Channel_t* const ACLChannel)
158 {
159 BT_RFCOMM_DEBUG(1, ">> MSC Command");
160 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel->DLCI);
161
162 struct
163 {
164 RFCOMM_Command_t CommandHeader;
165 uint8_t Length;
166 RFCOMM_MSC_Parameters_t Params;
167 } MSCommand;
168
169 MSCommand.CommandHeader = (RFCOMM_Command_t){.Command = RFCOMM_Control_ModemStatus, .EA = true, .CR = true};
170 MSCommand.Length = (sizeof(MSCommand.Params) << 1) | 0x01;
171 MSCommand.Params.Channel = (RFCOMM_Address_t){.DLCI = RFCOMMChannel->DLCI, .EA = true, .CR = true};
172 MSCommand.Params.Signals = RFCOMMChannel->Local.Signals;
173 MSCommand.Params.BreakSignal = RFCOMMChannel->Local.BreakSignal;
174
175 /* Send the MSC command to the remote device */
176 RFCOMM_SendFrame(RFCOMM_CONTROL_DLCI, true, RFCOMM_Frame_UIH, sizeof(MSCommand), &MSCommand, ACLChannel);
177 }
178
179 /** Sends new data through an open logical RFCOMM channel. This should be used to transmit data through a
180 * RFCOMM channel once it has been opened.
181 *
182 * \param[in] DataLen Length of the RFCOMM data to send, in bytes
183 * \param[in] Data Pointer to a buffer where the data to send is located
184 * \param[in] RFCOMMChannel RFCOMM logical channel which is to be transmitted to
185 * \param[in] ACLChannel ACL channel which has been opened to carry RFCOMM traffic between devices
186 */
187 void RFCOMM_SendData(const uint16_t DataLen, const uint8_t* Data, const RFCOMM_Channel_t* const RFCOMMChannel,
188 Bluetooth_Channel_t* const ACLChannel)
189 {
190 if (RFCOMMChannel->State != RFCOMM_Channel_Open)
191 return;
192
193 BT_RFCOMM_DEBUG(1, ">> UIH Frame");
194 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel->DLCI);
195
196 /* Send the MSC command to the remote device */
197 RFCOMM_SendFrame(RFCOMMChannel->DLCI, false, RFCOMM_Frame_UIH, DataLen, Data, ACLChannel);
198 }
199
200 RFCOMM_Channel_t* RFCOMM_GetFreeChannelEntry(const uint8_t DLCI)
201 {
202 /* Find a free entry in the RFCOMM channel multiplexer state array */
203 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
204 {
205 RFCOMM_Channel_t* RFCOMMChannel = &RFCOMM_Channels[i];
206
207 /* If the channel's state is closed, the channel state entry is free */
208 if (RFCOMMChannel->State == RFCOMM_Channel_Closed)
209 {
210 RFCOMMChannel->DLCI = DLCI;
211 RFCOMMChannel->State = RFCOMM_Channel_Configure;
212 RFCOMMChannel->Priority = 7 + (RFCOMMChannel->DLCI & 0xF8);
213 RFCOMMChannel->MTU = 0xFFFF;
214 RFCOMMChannel->Remote.Signals = 0 | (1 << 0);
215 RFCOMMChannel->Remote.BreakSignal = 0 | (1 << 0);
216 RFCOMMChannel->Local.Signals = RFCOMM_SIGNAL_RTC | RFCOMM_SIGNAL_RTR | RFCOMM_SIGNAL_DV | (1 << 0);
217 RFCOMMChannel->Local.BreakSignal = 0 | (1 << 0);
218 RFCOMMChannel->ConfigFlags = 0;
219
220 return RFCOMMChannel;
221 }
222 }
223
224 return NULL;
225 }
226
227 RFCOMM_Channel_t* RFCOMM_GetChannelData(const uint8_t DLCI)
228 {
229 /* Search through the RFCOMM channel list, looking for the specified channel */
230 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
231 {
232 RFCOMM_Channel_t* CurrRFCOMMChannel = &RFCOMM_Channels[i];
233
234 /* If the current non-closed channel's DLCI matches the search DLCI, return it to the caller */
235 if ((CurrRFCOMMChannel->State != RFCOMM_Channel_Closed) && (CurrRFCOMMChannel->DLCI == DLCI))
236 return CurrRFCOMMChannel;
237 }
238
239 /* Channel not found in the channel state table, return failure */
240 return NULL;
241 }
242
243 uint16_t RFCOMM_GetVariableFieldValue(const uint8_t** BufferPos)
244 {
245 uint8_t FirstOctet;
246 uint8_t SecondOctet = 0;
247
248 FirstOctet = **BufferPos;
249 (*BufferPos)++;
250
251 /* If the field size is more than a single byte, fetch the next byte in the variable length field */
252 if (!(FirstOctet & 0x01))
253 {
254 SecondOctet = **BufferPos;
255 (*BufferPos)++;
256
257 /* Discard any remaining bytes in the variable length field that won't fit in the return value */
258 while (!(**BufferPos & 0x01))
259 (*BufferPos)++;
260 }
261
262 /* Bitshift the bytes that comprise the variable length field so that they form a single integer */
263 return (((uint16_t)SecondOctet << 7) | FirstOctet >> 1);
264 }
265
266 void RFCOMM_SendFrame(const uint8_t DLCI, const bool CommandResponse, const uint8_t Control, const uint16_t DataLen,
267 const void* Data, Bluetooth_Channel_t* const ACLChannel)
268 {
269 struct
270 {
271 RFCOMM_Header_t FrameHeader;
272 uint8_t Size[(DataLen < 128) ? 1 : 2];
273 uint8_t Data[DataLen];
274 uint8_t FCS;
275 } ResponsePacket;
276
277 /* Set the frame header values to the specified address and frame type */
278 ResponsePacket.FrameHeader.Control = Control;
279 ResponsePacket.FrameHeader.Address = (RFCOMM_Address_t){.DLCI = DLCI, .EA = true, .CR = CommandResponse};
280
281 /* Set the lower 7 bits of the packet length */
282 ResponsePacket.Size[0] = (DataLen << 1);
283
284 /* Terminate the size field if size is 7 bits or lower, otherwise set the upper 8 bits of the length */
285 if (DataLen < 128)
286 ResponsePacket.Size[0] |= 0x01;
287 else
288 ResponsePacket.Size[1] = (DataLen >> 7);
289
290 /* Copy over the packet data from the source buffer to the response packet buffer */
291 memcpy(ResponsePacket.Data, Data, DataLen);
292
293 /* Determine the length of the frame which is to be used to calculate the CRC value */
294 uint8_t CRCLength = sizeof(ResponsePacket.FrameHeader);
295
296 /* UIH frames do not have the CRC calculated on the Size field in the response, all other frames do */
297 if ((Control & ~FRAME_POLL_FINAL) != RFCOMM_Frame_UIH)
298 CRCLength += sizeof(ResponsePacket.Size);
299
300 /* Calculate the frame checksum from the appropriate fields */
301 ResponsePacket.FCS = RFCOMM_GetFCSValue(&ResponsePacket, CRCLength);
302
303 /* Send the completed response packet to the sender */
304 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), ACLChannel);
305 }
306
307 static uint8_t RFCOMM_GetFCSValue(const void* FrameStart, uint8_t Length)
308 {
309 uint8_t FCS = 0xFF;
310
311 /* Calculate new Frame CRC value via the given data bytes and the CRC table */
312 for (uint8_t i = 0; i < Length; i++)
313 FCS = pgm_read_byte(&CRC8_Table[FCS ^ ((const uint8_t*)FrameStart)[i]]);
314
315 return ~FCS;
316 }
317
318 static void RFCOMM_ProcessDM(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const ACLChannel)
319 {
320 BT_RFCOMM_DEBUG(1, "<< DM Received");
321 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
322 }
323
324 static void RFCOMM_ProcessDISC(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const ACLChannel)
325 {
326 BT_RFCOMM_DEBUG(1, "<< DISC Received");
327 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
328
329 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
330
331 /* If the requested channel is currently open, destroy it */
332 if (RFCOMMChannel != NULL)
333 RFCOMMChannel->State = RFCOMM_Channel_Closed;
334
335 BT_RFCOMM_DEBUG(1, ">> UA Sent");
336 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, ACLChannel);
337 }
338
339 static void RFCOMM_ProcessSABM(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const ACLChannel)
340 {
341 BT_RFCOMM_DEBUG(1, "<< SABM Received");
342 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
343
344 if (FrameAddress->DLCI == RFCOMM_CONTROL_DLCI)
345 {
346 BT_RFCOMM_DEBUG(1, ">> UA Sent");
347
348 /* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */
349 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, ACLChannel);
350
351 return;
352 }
353
354 /* Find the existing channel's entry in the channel table */
355 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
356
357 /* Existing entry not found, create a new entry for the channel */
358 if (RFCOMMChannel == NULL)
359 RFCOMMChannel = RFCOMM_GetFreeChannelEntry(FrameAddress->DLCI);
360
361 /* If space was found in the channel table for the new channel, ACK the request */
362 if (RFCOMMChannel != NULL)
363 {
364 BT_RFCOMM_DEBUG(1, ">> UA Sent");
365
366 /* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */
367 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, ACLChannel);
368 }
369 else
370 {
371 BT_RFCOMM_DEBUG(1, ">> DM Sent");
372
373 /* No free channel in the multiplexer - decline the SABM by sending a DM frame */
374 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_DM | FRAME_POLL_FINAL), 0, NULL, ACLChannel);
375 }
376 }
377
378 static void RFCOMM_ProcessUA(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const ACLChannel)
379 {
380 BT_RFCOMM_DEBUG(1, "<< UA Received");
381 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
382 }
383
384 static void RFCOMM_ProcessUIH(const RFCOMM_Address_t* const FrameAddress, const uint16_t FrameLength,
385 const uint8_t* FrameData, Bluetooth_Channel_t* const ACLChannel)
386 {
387 if (FrameAddress->DLCI == RFCOMM_CONTROL_DLCI)
388 {
389 RFCOMM_ProcessControlCommand(FrameData, ACLChannel);
390 return;
391 }
392
393 BT_RFCOMM_DEBUG(1, "<< UIH Received");
394 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
395 BT_RFCOMM_DEBUG(2, "-- Length 0x%02X", FrameLength);
396
397 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
398
399 if (RFCOMMChannel != NULL)
400 RFCOMM_DataReceived(RFCOMMChannel, FrameLength, FrameData);
401 }