Rename RFCOMM_GetFrameDataLength() to RFCOMM_GetVariableFieldValue() as it is multi...
[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_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
77 {
78 const RFCOMM_Header_t* FrameHeader = (const RFCOMM_Header_t*)Data;
79 const uint8_t* FrameData = (const uint8_t*)Data + sizeof(RFCOMM_Header_t);
80 uint16_t FrameDataLen = RFCOMM_GetVariableFieldValue(&FrameData);
81
82 /* Decode the RFCOMM frame type from the header */
83 switch (FrameHeader->Control & ~FRAME_POLL_FINAL)
84 {
85 case RFCOMM_Frame_DM:
86 RFCOMM_ProcessDM(&FrameHeader->Address, Channel);
87 break;
88 case RFCOMM_Frame_DISC:
89 RFCOMM_ProcessDISC(&FrameHeader->Address, Channel);
90 break;
91 case RFCOMM_Frame_SABM:
92 RFCOMM_ProcessSABM(&FrameHeader->Address, Channel);
93 break;
94 case RFCOMM_Frame_UA:
95 RFCOMM_ProcessUA(&FrameHeader->Address, Channel);
96 break;
97 case RFCOMM_Frame_UIH:
98 RFCOMM_ProcessUIH(&FrameHeader->Address, FrameDataLen, FrameData, Channel);
99 break;
100 default:
101 BT_RFCOMM_DEBUG(1, "<< Unknown Frame Received");
102 break;
103 }
104 }
105
106 RFCOMM_Channel_t* RFCOMM_GetChannelData(const uint8_t DLCI)
107 {
108 /* Search through the RFCOMM channel list, looking for the specified channel */
109 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
110 {
111 RFCOMM_Channel_t* CurrRFCOMMChannel = &RFCOMM_Channels[i];
112
113 /* If the current non-closed channel's DLCI matches the search DLCI, return it to the caller */
114 if ((CurrRFCOMMChannel->DLCI == DLCI) && (CurrRFCOMMChannel->State != RFCOMM_Channel_Closed))
115 return CurrRFCOMMChannel;
116 }
117
118 /* Channel not found in the channel state table, return failure */
119 return NULL;
120 }
121
122 uint16_t RFCOMM_GetVariableFieldValue(const uint8_t** BufferPos)
123 {
124 uint8_t FirstOctet;
125 uint8_t SecondOctet = 0;
126
127 FirstOctet = **BufferPos;
128 (*BufferPos)++;
129
130 /* If the field size is more than a single byte, fetch the next byte in the variable length field */
131 if (!(FirstOctet & 0x01))
132 {
133 SecondOctet = **BufferPos;
134 (*BufferPos)++;
135
136 /* Discard any remaining bytes in the variable length field that won't fit in the return value */
137 while (!(**BufferPos & 0x01))
138 (*BufferPos)++;
139 }
140
141 /* Bitshift the bytes that comprise the variable length field so that they form a single integer */
142 return (((uint16_t)SecondOctet << 7) | FirstOctet >> 1);
143 }
144
145 void RFCOMM_SendFrame(const uint8_t DLCI, const bool CommandResponse, const uint8_t Control, const uint16_t DataLen,
146 const void* Data, Bluetooth_Channel_t* const Channel)
147 {
148 struct
149 {
150 RFCOMM_Header_t FrameHeader;
151 uint8_t Size[(DataLen < 128) ? 1 : 2];
152 uint8_t Data[DataLen];
153 uint8_t FCS;
154 } ResponsePacket;
155
156 /* Set the frame header values to the specified address and frame type */
157 ResponsePacket.FrameHeader.Control = Control;
158 ResponsePacket.FrameHeader.Address = (RFCOMM_Address_t)
159 {
160 .EA = true,
161 .CR = CommandResponse,
162 .DLCI = DLCI,
163 };
164
165 /* Set the lower 7 bits of the packet length */
166 ResponsePacket.Size[0] = (DataLen << 1);
167
168 /* Terminate the size field if size is 7 bits or lower, otherwise set the upper 8 bits of the length */
169 if (DataLen < 128)
170 ResponsePacket.Size[0] |= 0x01;
171 else
172 ResponsePacket.Size[1] = (DataLen >> 7);
173
174 /* Copy over the packet data from the source buffer to the response packet buffer */
175 memcpy(ResponsePacket.Data, Data, DataLen);
176
177 /* Determine the length of the frame which is to be used to calculate the CRC value */
178 uint8_t CRCLength = sizeof(ResponsePacket.FrameHeader);
179
180 /* UIH frames do not have the CRC calculated on the Size field in the response, all other frames do */
181 if ((Control & ~FRAME_POLL_FINAL) != RFCOMM_Frame_UIH)
182 CRCLength += sizeof(ResponsePacket.Size);
183
184 /* Calculate the frame checksum from the appropriate fields */
185 ResponsePacket.FCS = RFCOMM_GetFCSValue(&ResponsePacket, CRCLength);
186
187 /* Send the completed response packet to the sender */
188 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), Channel);
189 }
190
191 static uint8_t RFCOMM_GetFCSValue(const void* FrameStart, uint8_t Length)
192 {
193 uint8_t FCS = 0xFF;
194
195 for (uint8_t i = 0; i < Length; i++)
196 FCS = pgm_read_byte(&CRC8_Table[FCS ^ ((uint8_t*)FrameStart)[i]]);
197
198 return ~FCS;
199 }
200
201 static void RFCOMM_ProcessDM(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
202 {
203 BT_RFCOMM_DEBUG(1, "<< DM Received");
204 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
205 }
206
207 static void RFCOMM_ProcessDISC(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
208 {
209 BT_RFCOMM_DEBUG(1, "<< DISC Received");
210 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
211
212 RFCOMM_Channel_t* RFCOMMChannel = RFCOMM_GetChannelData(FrameAddress->DLCI);
213
214 /* If the requested channel is currently open, destroy it */
215 if (RFCOMMChannel != NULL)
216 RFCOMMChannel->DLCI = 0x00;
217
218 BT_RFCOMM_DEBUG(1, ">> UA Sent");
219 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, Channel);
220 }
221
222 static void RFCOMM_ProcessSABM(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
223 {
224 BT_RFCOMM_DEBUG(1, "<< SABM Received");
225 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
226
227 /* Find a free entry in the RFCOMM channel multiplexer state array */
228 for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
229 {
230 RFCOMM_Channel_t* CurrRFCOMMChannel = &RFCOMM_Channels[i];
231
232 /* If the channel's DLCI is zero, the channel state entry is free */
233 if (!(CurrRFCOMMChannel->DLCI))
234 {
235 CurrRFCOMMChannel->DLCI = FrameAddress->DLCI;
236 CurrRFCOMMChannel->State = RFCOMM_Channel_Open;
237 CurrRFCOMMChannel->Priority = 7 + (CurrRFCOMMChannel->DLCI >> 3) + ((CurrRFCOMMChannel->DLCI >> 3) * 7);
238 CurrRFCOMMChannel->UseUIFrames = false;
239 CurrRFCOMMChannel->MTU = 0xFFFF;
240 CurrRFCOMMChannel->Signals = 0;
241 CurrRFCOMMChannel->BreakSignals = 0;
242
243 BT_RFCOMM_DEBUG(1, ">> UA Sent");
244 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, Channel);
245 return;
246 }
247 }
248
249 BT_RFCOMM_DEBUG(1, ">> DM Sent");
250
251 /* No free channel in the multiplexer - decline the SABM by sending a DM frame */
252 RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_DM | FRAME_POLL_FINAL), 0, NULL, Channel);
253 }
254
255 static void RFCOMM_ProcessUA(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
256 {
257 BT_RFCOMM_DEBUG(1, "<< UA Received");
258 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
259 }
260
261 static void RFCOMM_ProcessUIH(const RFCOMM_Address_t* const FrameAddress, const uint16_t FrameLength,
262 const uint8_t* FrameData, Bluetooth_Channel_t* const Channel)
263 {
264 if (FrameAddress->DLCI == RFCOMM_CONTROL_DLCI)
265 {
266 RFCOMM_ProcessControlCommand(FrameData, Channel);
267 return;
268 }
269
270 BT_RFCOMM_DEBUG(1, "<< UIH Received");
271 BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
272 BT_RFCOMM_DEBUG(2, "-- Length 0x%02X", FrameLength);
273
274 puts("RFCOMM Data: ");
275
276 for (uint8_t i = 0; i < FrameLength; i++)
277 printf("0x%02X (%c) ", FrameData[i], FrameData[i]);
278
279 printf("\r\n");
280 }