b8686893a98eceeae546d56ad9e167b29f28d97a
[pub/USBasp.git] / Demos / Host / Incomplete / BluetoothHost / Lib / BluetoothACLPackets.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 * Bluetooth L2CAP layer management code. This module managed the creation,
34 * configuration and teardown of L2CAP channels, and manages packet reception
35 * and sending to and from other Bluetooth devices.
36 */
37
38 /*
39 TODO: Make SendPacket respect receiver's MTU
40 TODO: Make ReceivePacket stitch together MTU fragments (?)
41 */
42
43 #define INCLUDE_FROM_BLUETOOTH_ACLPACKETS_C
44 #include "BluetoothACLPackets.h"
45
46 /** Bluetooth ACL processing task. This task should be called repeatedly the main Bluetooth
47 * stack task to manage the ACL processing state.
48 */
49 void Bluetooth_ACLTask(void)
50 {
51 /* Process incomming ACL packets, if any */
52 Bluetooth_ProcessIncommingACLPackets();
53
54 /* Check for any half-open channels, send configuration details to the remote device if found */
55 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
56 {
57 Bluetooth_Channel_t* ChannelData = &Bluetooth_Connection.Channels[i];
58
59 bool MustSendConfigReq = true;
60
61 /* Check if we are in a channel state which requires a configuration request to be sent */
62 switch (ChannelData->State)
63 {
64 case BT_Channel_Config_WaitConfig:
65 ChannelData->State = BT_Channel_Config_WaitReqResp;
66 break;
67 case BT_Channel_Config_WaitSendConfig:
68 ChannelData->State = BT_Channel_Config_WaitResp;
69 break;
70 default:
71 MustSendConfigReq = false;
72 break;
73 }
74
75 /* Only send a configuration request if it the channel was in a state which required it */
76 if (MustSendConfigReq)
77 {
78 struct
79 {
80 BT_Signal_Header_t SignalCommandHeader;
81 BT_Signal_ConfigurationReq_t ConfigurationRequest;
82
83 struct
84 {
85 BT_Config_Option_Header_t Header;
86 uint16_t Value;
87 } Option_LocalMTU;
88 } PacketData;
89
90 /* Fill out the Signal Command header in the response packet */
91 PacketData.SignalCommandHeader.Code = BT_SIGNAL_CONFIGURATION_REQUEST;
92 PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignallingIdentifier;
93 PacketData.SignalCommandHeader.Length = sizeof(PacketData.ConfigurationRequest) +
94 sizeof(PacketData.Option_LocalMTU);
95
96 /* Fill out the Configuration Request in the response packet, including local MTU information */
97 PacketData.ConfigurationRequest.DestinationChannel = ChannelData->RemoteNumber;
98 PacketData.ConfigurationRequest.Flags = 0;
99 PacketData.Option_LocalMTU.Header.Type = BT_CONFIG_OPTION_MTU;
100 PacketData.Option_LocalMTU.Header.Length = sizeof(PacketData.Option_LocalMTU.Value);
101 PacketData.Option_LocalMTU.Value = ChannelData->LocalMTU;
102
103 Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
104
105 BT_ACL_DEBUG(1, ">> L2CAP Configuration Request");
106 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData.ConfigurationRequest.DestinationChannel);
107 }
108 }
109 }
110
111 /** Incomming ACL packet processing task. This task is called by the main ACL processing task to read in and process
112 * any incomming ACL packets to the device, handling signal requests as they are received or passing along channel
113 * data to the user application.
114 */
115 static void Bluetooth_ProcessIncommingACLPackets(void)
116 {
117 BT_ACL_Header_t ACLPacketHeader;
118 BT_DataPacket_Header_t DataHeader;
119
120 Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE);
121 Pipe_Unfreeze();
122
123 if (!(Pipe_IsReadWriteAllowed()))
124 {
125 Pipe_Freeze();
126 return;
127 }
128
129 /* Read in the received ACL packet headers when it has been discovered that a packet has been received */
130 Pipe_Read_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
131 Pipe_Read_Stream_LE(&DataHeader, sizeof(DataHeader));
132
133 BT_ACL_DEBUG(2, "");
134 BT_ACL_DEBUG(2, "Packet Received");
135 BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader.ConnectionHandle & 0x0FFF));
136 BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader.DataLength);
137 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader.DestinationChannel);
138 BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader.PayloadLength);
139
140 /* Check the packet's destination channel - signalling channel should be processed by the stack internally */
141 if (DataHeader.DestinationChannel == BT_CHANNEL_SIGNALING)
142 {
143 /* Read in the Signal Command header of the incomming packet */
144 BT_Signal_Header_t SignalCommandHeader;
145 Pipe_Read_Stream_LE(&SignalCommandHeader, sizeof(SignalCommandHeader));
146
147 /* Dispatch to the appropriate handler function based on the Signal message code */
148 switch (SignalCommandHeader.Code)
149 {
150 case BT_SIGNAL_CONNECTION_REQUEST:
151 Bluetooth_Signal_ConnectionReq(&SignalCommandHeader);
152 break;
153 case BT_SIGNAL_CONNECTION_RESPONSE:
154 Bluetooth_Signal_ConnectionResp(&SignalCommandHeader);
155 break;
156 case BT_SIGNAL_CONFIGURATION_REQUEST:
157 Bluetooth_Signal_ConfigurationReq(&SignalCommandHeader);
158 break;
159 case BT_SIGNAL_CONFIGURATION_RESPONSE:
160 Bluetooth_Signal_ConfigurationResp(&SignalCommandHeader);
161 break;
162 case BT_SIGNAL_DISCONNECTION_REQUEST:
163 Bluetooth_Signal_DisconnectionReq(&SignalCommandHeader);
164 break;
165 case BT_SIGNAL_DISCONNECTION_RESPONSE:
166 Bluetooth_Signal_DisconnectionResp(&SignalCommandHeader);
167 break;
168 case BT_SIGNAL_ECHO_REQUEST:
169 Bluetooth_Signal_EchoReq(&SignalCommandHeader);
170 break;
171 case BT_SIGNAL_INFORMATION_REQUEST:
172 Bluetooth_Signal_InformationReq(&SignalCommandHeader);
173 break;
174 case BT_SIGNAL_COMMAND_REJECT:
175 BT_ACL_DEBUG(1, "<< Command Reject");
176
177 uint16_t RejectReason;
178 Pipe_Read_Stream_LE(&RejectReason, sizeof(RejectReason));
179 Pipe_Discard_Stream(ACLPacketHeader.DataLength - sizeof(RejectReason));
180 Pipe_ClearIN();
181 Pipe_Freeze();
182
183 BT_ACL_DEBUG(2, "-- Reason: %d", RejectReason);
184 break;
185 default:
186 BT_ACL_DEBUG(1, "<< Unknown Signaling Command 0x%02X", SignalCommandHeader.Code);
187
188 Pipe_Discard_Stream(ACLPacketHeader.DataLength);
189 Pipe_ClearIN();
190 Pipe_Freeze();
191 break;
192 }
193 }
194 else
195 {
196 /* Non-signalling packet received, read in the packet contents and pass to the user application */
197 uint8_t PacketData[DataHeader.PayloadLength];
198 Pipe_Read_Stream_LE(PacketData, DataHeader.PayloadLength);
199 Pipe_ClearIN();
200 Pipe_Freeze();
201
202 Bluetooth_PacketReceived(PacketData, DataHeader.PayloadLength,
203 Bluetooth_GetChannelData(DataHeader.DestinationChannel, CHANNEL_SEARCH_LOCALNUMBER));
204 }
205 }
206
207 /** Retrieves the channel information structure with the given local or remote channel number from the channel list.
208 *
209 * \param[in] SearchValue Value to search for in the channel structure list
210 * \param[in] SearchKey Key to search within the channel structure, a CHANNEL_SEARCH_* mask
211 *
212 * \return Pointer to the matching channel information structure in the channel table if found, NULL otherwise
213 */
214 Bluetooth_Channel_t* Bluetooth_GetChannelData(const uint16_t SearchValue, const uint8_t SearchKey)
215 {
216 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
217 {
218 Bluetooth_Channel_t* ChannelData = &Bluetooth_Connection.Channels[i];
219
220 /* Closed channels should be ignored as they are not considered valid data */
221 if (ChannelData->State == BT_Channel_Closed)
222 continue;
223
224 bool FoundMatch = false;
225
226 /* Search the current channel for the search key to see if it matches */
227 switch (SearchKey)
228 {
229 case CHANNEL_SEARCH_LOCALNUMBER:
230 FoundMatch = (SearchValue == ChannelData->LocalNumber);
231 break;
232 case CHANNEL_SEARCH_REMOTENUMBER:
233 FoundMatch = (SearchValue == ChannelData->RemoteNumber);
234 break;
235 case CHANNEL_SEARCH_PSM:
236 FoundMatch = (SearchValue == ChannelData->PSM);
237 break;
238 }
239
240 if (FoundMatch)
241 return ChannelData;
242 }
243
244 return NULL;
245 }
246
247 /** Sends a packet to the remote device on the specified channel.
248 *
249 * \param[in] Data Pointer to a buffer where the data is to be sourced from
250 * \param[in] DataLen Length of the data to send
251 * \param[in] Channel Channel information structure containing the destination channel's information, NULL to send
252 * to the remote device's signalling channel
253 *
254 * \return A value from the \ref BT_SendPacket_ErrorCodes_t enum
255 */
256 uint8_t Bluetooth_SendPacket(void* Data, const uint16_t DataLen, Bluetooth_Channel_t* const ACLChannel)
257 {
258 BT_ACL_Header_t ACLPacketHeader;
259 BT_DataPacket_Header_t DataHeader;
260
261 /* A remote device must be connected before a packet transmission is attempted */
262 if (!(Bluetooth_Connection.IsConnected))
263 return BT_SENDPACKET_NotConnected;
264
265 /* If the destination channel is not the signalling channel and it is not currently fully open, abort */
266 if ((ACLChannel == NULL) || (ACLChannel->State != BT_Channel_Open))
267 return BT_SENDPACKET_ChannelNotOpen;
268
269 /* Fill out the packet's header from the remote device connection information structure */
270 ACLPacketHeader.ConnectionHandle = (Bluetooth_Connection.ConnectionHandle | BT_ACL_FIRST_AUTOFLUSH);
271 ACLPacketHeader.DataLength = sizeof(DataHeader) + DataLen;
272 DataHeader.PayloadLength = DataLen;
273 DataHeader.DestinationChannel = (ACLChannel == NULL) ? BT_CHANNEL_SIGNALING : ACLChannel->RemoteNumber;
274
275 Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE);
276
277 Pipe_WaitUntilReady();
278 Pipe_Unfreeze();
279
280 /* Write the packet contents to the pipe so that it can be sent to the remote device */
281 Pipe_Write_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
282 Pipe_Write_Stream_LE(&DataHeader, sizeof(DataHeader));
283 Pipe_Write_Stream_LE(Data, DataLen);
284 Pipe_ClearOUT();
285
286 Pipe_Freeze();
287
288 BT_ACL_DEBUG(2, "");
289 BT_ACL_DEBUG(2, "Packet Sent");
290 BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader.ConnectionHandle & 0x0FFF));
291 BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader.DataLength);
292 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader.DestinationChannel);
293 BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader.PayloadLength);
294
295 return BT_SENDPACKET_NoError;
296 }
297
298 /** Opens a Bluetooth channel to the currently connected remote device, so that data can be exchanged.
299 *
300 * \note The channel is not immediately opened when this function returns - it must undergo a two way
301 * connection and configuration process first as the main Bluetooth stack processing task is
302 * repeatedly called. The returned channel is unusable by the user application until its State
303 * element has progressed to the Open state.
304 *
305 * \param[in] PSM PSM of the service that the channel is to be opened for
306 *
307 * \return Pointer to the channel information structure of the opened channel, or NULL if no free channels
308 */
309 Bluetooth_Channel_t* Bluetooth_OpenChannel(const uint16_t PSM)
310 {
311 Bluetooth_Channel_t* ChannelData = NULL;
312
313 /* Search through the channel information list for a free channel item */
314 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
315 {
316 if (Bluetooth_Connection.Channels[i].State == BT_Channel_Closed)
317 {
318 ChannelData = &Bluetooth_Connection.Channels[i];
319
320 /* Set the new channel structure's local channel number to a unique value within the connection orientated
321 channel address space */
322 ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);
323 break;
324 }
325 }
326
327 /* If no free channel item was found in the list, all channels are occupied - abort */
328 if (ChannelData == NULL)
329 return NULL;
330
331 /* Reset and fill out the allocated channel's information structure with defaults */
332 ChannelData->RemoteNumber = 0;
333 ChannelData->PSM = PSM;
334 ChannelData->LocalMTU = MAXIMUM_CHANNEL_MTU;
335 ChannelData->State = BT_Channel_WaitConnectRsp;
336
337 struct
338 {
339 BT_Signal_Header_t SignalCommandHeader;
340 BT_Signal_ConnectionReq_t ConnectionRequest;
341 } PacketData;
342
343 /* Fill out the Signal Command header in the response packet */
344 PacketData.SignalCommandHeader.Code = BT_SIGNAL_CONNECTION_REQUEST;
345 PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignallingIdentifier;
346 PacketData.SignalCommandHeader.Length = sizeof(PacketData.ConnectionRequest);
347
348 /* Fill out the Connection Request in the response packet */
349 PacketData.ConnectionRequest.PSM = PSM;
350 PacketData.ConnectionRequest.SourceChannel = ChannelData->LocalNumber;
351
352 Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
353
354 BT_ACL_DEBUG(1, ">> L2CAP Connection Request");
355 BT_ACL_DEBUG(2, "-- PSM 0x%04X", PacketData.ConnectionRequest.PSM);
356 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.ConnectionRequest.SourceChannel);
357
358 return ChannelData;
359 }
360
361 /** Closes a Bluetooth channel that is open to the currently connected remote device, so that no further data
362 * can be exchanged.
363 *
364 * \note The channel is not immediately closed when this function returns - it must undergo an asynchronous
365 * disconnection process first as the main Bluetooth stack processing task is repeatedly called. The
366 * returned channel is unusable by the user application upon return however the channel is not completely
367 * closed until its State element has progressed to the Closed state.
368 *
369 * \param[in,out] Channel Channel information structure of the channel to close
370 */
371 void Bluetooth_CloseChannel(Bluetooth_Channel_t* const ACLChannel)
372 {
373 /* Don't try to close a non-existing or already closed channel */
374 if ((ACLChannel == NULL) || (ACLChannel->State == BT_Channel_Closed))
375 return;
376
377 /* Set the channel's state to the start of the teardown process */
378 ACLChannel->State = BT_Channel_WaitDisconnect;
379
380 struct
381 {
382 BT_Signal_Header_t SignalCommandHeader;
383 BT_Signal_DisconnectionReq_t DisconnectionRequest;
384 } PacketData;
385
386 /* Fill out the Signal Command header in the response packet */
387 PacketData.SignalCommandHeader.Code = BT_SIGNAL_DISCONNECTION_REQUEST;
388 PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignallingIdentifier;
389 PacketData.SignalCommandHeader.Length = sizeof(PacketData.DisconnectionRequest);
390
391 /* Fill out the Disconnection Request in the response packet */
392 PacketData.DisconnectionRequest.DestinationChannel = ACLChannel->RemoteNumber;
393 PacketData.DisconnectionRequest.SourceChannel = ACLChannel->LocalNumber;
394
395 Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
396
397 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Request");
398 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData.DisconnectionRequest.DestinationChannel);
399 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.DisconnectionRequest.SourceChannel);
400 }
401
402 /** Internal Bluetooth stack Signal Command processing routine for a Connection Request command.
403 *
404 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
405 */
406 static inline void Bluetooth_Signal_ConnectionReq(const BT_Signal_Header_t* const SignalCommandHeader)
407 {
408 BT_Signal_ConnectionReq_t ConnectionRequest;
409
410 Pipe_Read_Stream_LE(&ConnectionRequest, sizeof(ConnectionRequest));
411
412 Pipe_ClearIN();
413 Pipe_Freeze();
414
415 BT_ACL_DEBUG(1, "<< L2CAP Connection Request");
416 BT_ACL_DEBUG(2, "-- PSM: 0x%04X", ConnectionRequest.PSM);
417 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionRequest.SourceChannel);
418
419 /* Try to retrieve the existing channel's information structure if it exists */
420 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConnectionRequest.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
421
422 /* If an existing channel item with the correct remote channel number was not found, find a free channel entry */
423 if (ChannelData == NULL)
424 {
425 /* Look through the channel information list for a free entry */
426 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
427 {
428 if (Bluetooth_Connection.Channels[i].State == BT_Channel_Closed)
429 {
430 ChannelData = &Bluetooth_Connection.Channels[i];
431
432 /* Set the new channel structure's local channel number to a unique value within the connection orientated
433 channel address space */
434 ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);
435 break;
436 }
437 }
438 }
439
440 uint8_t ChannelStatus = BT_CONNECTION_REFUSED_RESOURCES;
441
442 /* Reset the channel item contents only if a channel entry was found for it */
443 if (ChannelData != NULL)
444 {
445 /* Check if the user application will allow the connection based on its PSM */
446 if (Bluetooth_ChannelConnectionRequest(ConnectionRequest.PSM))
447 {
448 ChannelData->RemoteNumber = ConnectionRequest.SourceChannel;
449 ChannelData->PSM = ConnectionRequest.PSM;
450 ChannelData->LocalMTU = MAXIMUM_CHANNEL_MTU;
451 ChannelData->State = BT_Channel_Config_WaitConfig;
452
453 ChannelStatus = BT_CONNECTION_SUCCESSFUL;
454 }
455 else
456 {
457 ChannelStatus = BT_CONNECTION_REFUSED_PSM;
458 }
459 }
460
461 struct
462 {
463 BT_Signal_Header_t SignalCommandHeader;
464 BT_Signal_ConnectionResp_t ConnectionResponse;
465 } ResponsePacket;
466
467 /* Fill out the Signal Command header in the response packet */
468 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_CONNECTION_RESPONSE;
469 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
470 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.ConnectionResponse);
471
472 /* Fill out the Connection Response in the response packet */
473 ResponsePacket.ConnectionResponse.DestinationChannel = ChannelData->LocalNumber;
474 ResponsePacket.ConnectionResponse.SourceChannel = ChannelData->RemoteNumber;
475 ResponsePacket.ConnectionResponse.Result = ChannelStatus;
476 ResponsePacket.ConnectionResponse.Status = 0x00;
477
478 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
479
480 BT_ACL_DEBUG(1, ">> L2CAP Connection Response");
481 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.ConnectionResponse.Result);
482 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket.ConnectionResponse.DestinationChannel);
483 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.ConnectionResponse.SourceChannel);
484 }
485
486 /** Internal Bluetooth stack Signal Command processing routine for a Connection Response command.
487 *
488 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
489 */
490 static inline void Bluetooth_Signal_ConnectionResp(const BT_Signal_Header_t* const SignalCommandHeader)
491 {
492 BT_Signal_ConnectionResp_t ConnectionResponse;
493
494 Pipe_Read_Stream_LE(&ConnectionResponse, sizeof(ConnectionResponse));
495
496 Pipe_ClearIN();
497 Pipe_Freeze();
498
499 BT_ACL_DEBUG(1, "<< L2CAP Connection Response");
500 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConnectionResponse.Result);
501 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionResponse.SourceChannel);
502 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConnectionResponse.DestinationChannel);
503
504 /* Search for the referenced channel in the channel information list */
505 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConnectionResponse.SourceChannel, CHANNEL_SEARCH_LOCALNUMBER);
506
507 /* Only progress if the referenced channel data was found */
508 if (ChannelData != NULL)
509 {
510 /* Set the channel structure's remote channel number to the channel allocated on the remote device */
511 ChannelData->RemoteNumber = ConnectionResponse.SourceChannel;
512 ChannelData->State = (ConnectionResponse.Result == BT_CONNECTION_SUCCESSFUL) ?
513 BT_Channel_Config_WaitConfig : BT_Channel_Closed;
514 }
515 }
516
517 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Request command.
518 *
519 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
520 */
521 static inline void Bluetooth_Signal_ConfigurationReq(const BT_Signal_Header_t* const SignalCommandHeader)
522 {
523 BT_Signal_ConfigurationReq_t ConfigurationRequest;
524
525 /* Allocate a buffer large enough to hold the variable number of configuration options in the request */
526 uint8_t OptionsLen = (SignalCommandHeader->Length - sizeof(ConfigurationRequest));
527 uint8_t Options[OptionsLen];
528
529 Pipe_Read_Stream_LE(&ConfigurationRequest, sizeof(ConfigurationRequest));
530 Pipe_Read_Stream_LE(&Options, sizeof(Options));
531
532 Pipe_ClearIN();
533 Pipe_Freeze();
534
535 /* Search for the referenced channel in the channel information list */
536 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConfigurationRequest.DestinationChannel, CHANNEL_SEARCH_LOCALNUMBER);
537
538 BT_ACL_DEBUG(1, "<< L2CAP Configuration Request");
539 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConfigurationRequest.DestinationChannel);
540 BT_ACL_DEBUG(2, "-- Options Len: 0x%04X", OptionsLen);
541
542 /* Only look at the channel configuration options if a valid channel entry for the local channel number was found */
543 if (ChannelData != NULL)
544 {
545 /* Iterate through each option in the configuration request to look for ones which can be processed */
546 uint8_t OptionPos = 0;
547 while (OptionPos < OptionsLen)
548 {
549 BT_Config_Option_Header_t* OptionHeader = (BT_Config_Option_Header_t*)&Options[OptionPos];
550 void* OptionData = &Options[OptionPos + sizeof(BT_Config_Option_Header_t)];
551
552 BT_ACL_DEBUG(2, "-- Option Type: 0x%04X", OptionHeader->Type);
553 BT_ACL_DEBUG(2, "-- Option Length: 0x%04X", (sizeof(BT_Config_Option_Header_t) + OptionHeader->Length));
554
555 /* Store the remote MTU option's value if present */
556 if (OptionHeader->Type == BT_CONFIG_OPTION_MTU)
557 ChannelData->RemoteMTU = *((uint16_t*)OptionData);
558
559 /* Progress to the next option in the packet */
560 OptionPos += (sizeof(BT_Config_Option_Header_t) + OptionHeader->Length);
561 }
562 }
563
564 struct
565 {
566 BT_Signal_Header_t SignalCommandHeader;
567 BT_Signal_ConfigurationResp_t ConfigurationResponse;
568 } ResponsePacket;
569
570 /* Fill out the Signal Command header in the response packet */
571 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_CONFIGURATION_RESPONSE;
572 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
573 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.ConfigurationResponse);
574
575 /* Fill out the Configuration Response in the response packet */
576 ResponsePacket.ConfigurationResponse.SourceChannel = ChannelData->RemoteNumber;
577 ResponsePacket.ConfigurationResponse.Flags = 0x00;
578 ResponsePacket.ConfigurationResponse.Result = (ChannelData != NULL) ? BT_CONFIGURATION_SUCCESSFUL : BT_CONFIGURATION_REJECTED;
579
580 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
581
582 if (ChannelData != NULL)
583 {
584 switch (ChannelData->State)
585 {
586 case BT_Channel_Config_WaitConfig:
587 ChannelData->State = BT_Channel_Config_WaitSendConfig;
588 break;
589 case BT_Channel_Config_WaitReqResp:
590 ChannelData->State = BT_Channel_Config_WaitResp;
591 break;
592 case BT_Channel_Config_WaitReq:
593 ChannelData->State = BT_Channel_Open;
594 Bluetooth_ChannelOpened(ChannelData);
595 break;
596 }
597 }
598
599 BT_ACL_DEBUG(1, ">> L2CAP Configuration Response");
600 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.ConfigurationResponse.SourceChannel);
601 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.ConfigurationResponse.Result);
602 }
603
604 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Response command.
605 *
606 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
607 */
608 static inline void Bluetooth_Signal_ConfigurationResp(const BT_Signal_Header_t* const SignalCommandHeader)
609 {
610 BT_Signal_ConfigurationResp_t ConfigurationResponse;
611
612 Pipe_Read_Stream_LE(&ConfigurationResponse, sizeof(ConfigurationResponse));
613
614 Pipe_ClearIN();
615 Pipe_Freeze();
616
617 BT_ACL_DEBUG(1, "<< L2CAP Configuration Response");
618 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConfigurationResponse.SourceChannel);
619 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConfigurationResponse.Result);
620
621 /* Search for the referenced channel in the channel information list */
622 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConfigurationResponse.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
623
624 /* Only update the channel's state if it was found in the channel list */
625 if (ChannelData != NULL)
626 {
627 /* Check if the channel configuration completed successfuly */
628 if (ConfigurationResponse.Result == BT_CONFIGURATION_SUCCESSFUL)
629 {
630 switch (ChannelData->State)
631 {
632 case BT_Channel_Config_WaitReqResp:
633 ChannelData->State = BT_Channel_Config_WaitReq;
634 break;
635 case BT_Channel_Config_WaitResp:
636 ChannelData->State = BT_Channel_Open;
637 Bluetooth_ChannelOpened(ChannelData);
638 break;
639 }
640 }
641 else
642 {
643 /* Configuration failed - close the channel */
644 ChannelData->State = BT_Channel_Closed;
645 }
646 }
647 }
648
649 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Request command.
650 *
651 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
652 */
653 static inline void Bluetooth_Signal_DisconnectionReq(const BT_Signal_Header_t* const SignalCommandHeader)
654 {
655 BT_Signal_DisconnectionReq_t DisconnectionRequest;
656
657 Pipe_Read_Stream_LE(&DisconnectionRequest, sizeof(DisconnectionRequest));
658
659 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Request");
660 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionRequest.DestinationChannel);
661 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionRequest.SourceChannel);
662
663 Pipe_ClearIN();
664 Pipe_Freeze();
665
666 /* Search for the referenced channel in the channel information list */
667 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(DisconnectionRequest.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
668
669 struct
670 {
671 BT_Signal_Header_t SignalCommandHeader;
672 BT_Signal_DisconnectionResp_t DisconnectionResponse;
673 } ResponsePacket;
674
675 /* Fill out the Signal Command header in the response packet */
676 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_DISCONNECTION_RESPONSE;
677 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
678 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.DisconnectionResponse);
679
680 /* Fill out the Disconnection Response in the response packet */
681 ResponsePacket.DisconnectionResponse.DestinationChannel = ChannelData->RemoteNumber;
682 ResponsePacket.DisconnectionResponse.SourceChannel = ChannelData->LocalNumber;
683
684 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
685
686 /* If the channel was found in the channel list, close it */
687 if (ChannelData != NULL)
688 ChannelData->State = BT_Channel_Closed;
689
690 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Response");
691 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.DisconnectionResponse.SourceChannel);
692 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket.DisconnectionResponse.DestinationChannel);
693 }
694
695 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Response command.
696 *
697 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
698 */
699 static inline void Bluetooth_Signal_DisconnectionResp(const BT_Signal_Header_t* const SignalCommandHeader)
700 {
701 BT_Signal_DisconnectionResp_t DisconnectionResponse;
702
703 Pipe_Read_Stream_LE(&DisconnectionResponse, sizeof(DisconnectionResponse));
704
705 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Response");
706 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionResponse.DestinationChannel);
707 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionResponse.SourceChannel);
708
709 Pipe_ClearIN();
710 Pipe_Freeze();
711
712 /* Search for the referenced channel in the channel information list */
713 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(DisconnectionResponse.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
714
715 /* If the channel was found in the channel list, close it */
716 if (ChannelData != NULL)
717 ChannelData->State = BT_Channel_Closed;
718 }
719
720 /** Internal Bluetooth stack Signal Command processing routine for an Echo Request command.
721 *
722 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
723 */
724 static inline void Bluetooth_Signal_EchoReq(const BT_Signal_Header_t* const SignalCommandHeader)
725 {
726 BT_ACL_DEBUG(1, "<< L2CAP Echo Request");
727
728 Pipe_ClearIN();
729 Pipe_Freeze();
730
731 struct
732 {
733 BT_Signal_Header_t SignalCommandHeader;
734 } ResponsePacket;
735
736 /* Fill out the Signal Command header in the response packet */
737 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_ECHO_RESPONSE;
738 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
739 ResponsePacket.SignalCommandHeader.Length = 0;
740
741 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
742
743 BT_ACL_DEBUG(1, ">> L2CAP Echo Response");
744 }
745
746 /** Internal Bluetooth stack Signal Command processing routine for an Information Request command.
747 *
748 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
749 */
750 static inline void Bluetooth_Signal_InformationReq(const BT_Signal_Header_t* const SignalCommandHeader)
751 {
752 BT_Signal_InformationReq_t InformationRequest;
753
754 Pipe_Read_Stream_LE(&InformationRequest, sizeof(InformationRequest));
755
756 BT_ACL_DEBUG(1, "<< L2CAP Information Request");
757 BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest.InfoType);
758
759 Pipe_ClearIN();
760 Pipe_Freeze();
761
762 struct
763 {
764 BT_Signal_Header_t SignalCommandHeader;
765 BT_Signal_InformationResp_t InformationResponse;
766
767 uint8_t Data[4];
768 } ResponsePacket;
769
770 uint8_t DataLen = 0;
771
772 /* Retrieve the requested information and store it in the outgoing packet, if found */
773 switch (InformationRequest.InfoType)
774 {
775 case BT_INFOREQ_MTU:
776 ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
777 DataLen = 2;
778
779 *((uint16_t*)&ResponsePacket.Data) = MAXIMUM_CHANNEL_MTU;
780 break;
781 case BT_INFOREQ_EXTENDEDFEATURES:
782 ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
783 DataLen = 4;
784
785 *((uint32_t*)&ResponsePacket.Data) = 0;
786 break;
787 default:
788 ResponsePacket.InformationResponse.Result = BT_INFORMATION_NOTSUPPORTED;
789 DataLen = 0;
790 break;
791 }
792
793 /* Fill out the Signal Command header in the response packet */
794 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_INFORMATION_RESPONSE;
795 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
796 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.InformationResponse) + DataLen;
797
798 /* Fill out the Information Response in the response packet */
799 ResponsePacket.InformationResponse.InfoType = InformationRequest.InfoType;
800
801 Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket) - sizeof(ResponsePacket.Data) + DataLen), NULL);
802
803 BT_ACL_DEBUG(1, ">> L2CAP Information Response");
804 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.InformationResponse.Result);
805 }