Update copyright year on all source files.
[pub/USBasp.git] / Demos / Host / Incomplete / BluetoothHost / Lib / BluetoothACLPackets.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 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 incoming ACL packets, if any */
52 Bluetooth_ProcessIncomingACLPackets();
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.SignalingIdentifier;
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 /** Incoming ACL packet processing task. This task is called by the main ACL processing task to read in and process
112 * any incoming 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_ProcessIncomingACLPackets(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 - signaling 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 incoming 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-signaling 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,
215 const uint8_t SearchKey)
216 {
217 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
218 {
219 Bluetooth_Channel_t* ChannelData = &Bluetooth_Connection.Channels[i];
220
221 /* Closed channels should be ignored as they are not considered valid data */
222 if (ChannelData->State == BT_Channel_Closed)
223 continue;
224
225 bool FoundMatch = false;
226
227 /* Search the current channel for the search key to see if it matches */
228 switch (SearchKey)
229 {
230 case CHANNEL_SEARCH_LOCALNUMBER:
231 FoundMatch = (SearchValue == ChannelData->LocalNumber);
232 break;
233 case CHANNEL_SEARCH_REMOTENUMBER:
234 FoundMatch = (SearchValue == ChannelData->RemoteNumber);
235 break;
236 case CHANNEL_SEARCH_PSM:
237 FoundMatch = (SearchValue == ChannelData->PSM);
238 break;
239 }
240
241 if (FoundMatch)
242 return ChannelData;
243 }
244
245 return NULL;
246 }
247
248 /** Sends a packet to the remote device on the specified channel.
249 *
250 * \param[in] Data Pointer to a buffer where the data is to be sourced from
251 * \param[in] DataLen Length of the data to send
252 * \param[in] ACLChannel ACL channel information structure containing the destination channel's information, NULL
253 * to send to the remote device's signaling channel
254 *
255 * \return A value from the \ref BT_SendPacket_ErrorCodes_t enum
256 */
257 uint8_t Bluetooth_SendPacket(void* Data,
258 const uint16_t DataLen,
259 Bluetooth_Channel_t* const ACLChannel)
260 {
261 BT_ACL_Header_t ACLPacketHeader;
262 BT_DataPacket_Header_t DataHeader;
263
264 /* A remote device must be connected before a packet transmission is attempted */
265 if (!(Bluetooth_Connection.IsConnected))
266 return BT_SENDPACKET_NotConnected;
267
268 /* If the destination channel is not the signaling channel and it is not currently fully open, abort */
269 if ((ACLChannel != NULL) && (ACLChannel->State != BT_Channel_Open))
270 return BT_SENDPACKET_ChannelNotOpen;
271
272 /* Fill out the packet's header from the remote device connection information structure */
273 ACLPacketHeader.ConnectionHandle = (Bluetooth_Connection.ConnectionHandle | BT_ACL_FIRST_AUTOFLUSH);
274 ACLPacketHeader.DataLength = sizeof(DataHeader) + DataLen;
275 DataHeader.PayloadLength = DataLen;
276 DataHeader.DestinationChannel = (ACLChannel == NULL) ? BT_CHANNEL_SIGNALING : ACLChannel->RemoteNumber;
277
278 Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE);
279
280 Pipe_WaitUntilReady();
281 Pipe_Unfreeze();
282
283 /* Write the packet contents to the pipe so that it can be sent to the remote device */
284 Pipe_Write_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
285 Pipe_Write_Stream_LE(&DataHeader, sizeof(DataHeader));
286 Pipe_Write_Stream_LE(Data, DataLen);
287 Pipe_ClearOUT();
288
289 Pipe_Freeze();
290
291 BT_ACL_DEBUG(2, "");
292 BT_ACL_DEBUG(2, "Packet Sent");
293 BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader.ConnectionHandle & 0x0FFF));
294 BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader.DataLength);
295 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader.DestinationChannel);
296 BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader.PayloadLength);
297
298 return BT_SENDPACKET_NoError;
299 }
300
301 /** Opens a Bluetooth channel to the currently connected remote device, so that data can be exchanged.
302 *
303 * \note The channel is not immediately opened when this function returns - it must undergo a two way
304 * connection and configuration process first as the main Bluetooth stack processing task is
305 * repeatedly called. The returned channel is unusable by the user application until its State
306 * element has progressed to the Open state.
307 *
308 * \param[in] PSM PSM of the service that the channel is to be opened for
309 *
310 * \return Pointer to the channel information structure of the opened channel, or NULL if no free channels
311 */
312 Bluetooth_Channel_t* Bluetooth_OpenChannel(const uint16_t PSM)
313 {
314 Bluetooth_Channel_t* ChannelData = NULL;
315
316 /* Search through the channel information list for a free channel item */
317 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
318 {
319 if (Bluetooth_Connection.Channels[i].State == BT_Channel_Closed)
320 {
321 ChannelData = &Bluetooth_Connection.Channels[i];
322
323 /* Set the new channel structure's local channel number to a unique value within the connection orientated
324 channel address space */
325 ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);
326 break;
327 }
328 }
329
330 /* If no free channel item was found in the list, all channels are occupied - abort */
331 if (ChannelData == NULL)
332 return NULL;
333
334 /* Reset and fill out the allocated channel's information structure with defaults */
335 ChannelData->RemoteNumber = 0;
336 ChannelData->PSM = PSM;
337 ChannelData->LocalMTU = MAXIMUM_CHANNEL_MTU;
338 ChannelData->State = BT_Channel_WaitConnectRsp;
339
340 struct
341 {
342 BT_Signal_Header_t SignalCommandHeader;
343 BT_Signal_ConnectionReq_t ConnectionRequest;
344 } PacketData;
345
346 /* Fill out the Signal Command header in the response packet */
347 PacketData.SignalCommandHeader.Code = BT_SIGNAL_CONNECTION_REQUEST;
348 PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignalingIdentifier;
349 PacketData.SignalCommandHeader.Length = sizeof(PacketData.ConnectionRequest);
350
351 /* Fill out the Connection Request in the response packet */
352 PacketData.ConnectionRequest.PSM = PSM;
353 PacketData.ConnectionRequest.SourceChannel = ChannelData->LocalNumber;
354
355 Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
356
357 BT_ACL_DEBUG(1, ">> L2CAP Connection Request");
358 BT_ACL_DEBUG(2, "-- PSM 0x%04X", PacketData.ConnectionRequest.PSM);
359 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.ConnectionRequest.SourceChannel);
360
361 return ChannelData;
362 }
363
364 /** Closes a Bluetooth channel that is open to the currently connected remote device, so that no further data
365 * can be exchanged.
366 *
367 * \note The channel is not immediately closed when this function returns - it must undergo an asynchronous
368 * disconnection process first as the main Bluetooth stack processing task is repeatedly called. The
369 * returned channel is unusable by the user application upon return however the channel is not completely
370 * closed until its State element has progressed to the Closed state.
371 *
372 * \param[in,out] ACLChannel ACL channel information structure of the channel to close
373 */
374 void Bluetooth_CloseChannel(Bluetooth_Channel_t* const ACLChannel)
375 {
376 /* Don't try to close a non-existing or already closed channel */
377 if ((ACLChannel == NULL) || (ACLChannel->State == BT_Channel_Closed))
378 return;
379
380 /* Set the channel's state to the start of the teardown process */
381 ACLChannel->State = BT_Channel_WaitDisconnect;
382
383 struct
384 {
385 BT_Signal_Header_t SignalCommandHeader;
386 BT_Signal_DisconnectionReq_t DisconnectionRequest;
387 } PacketData;
388
389 /* Fill out the Signal Command header in the response packet */
390 PacketData.SignalCommandHeader.Code = BT_SIGNAL_DISCONNECTION_REQUEST;
391 PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignalingIdentifier;
392 PacketData.SignalCommandHeader.Length = sizeof(PacketData.DisconnectionRequest);
393
394 /* Fill out the Disconnection Request in the response packet */
395 PacketData.DisconnectionRequest.DestinationChannel = ACLChannel->RemoteNumber;
396 PacketData.DisconnectionRequest.SourceChannel = ACLChannel->LocalNumber;
397
398 Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
399
400 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Request");
401 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData.DisconnectionRequest.DestinationChannel);
402 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.DisconnectionRequest.SourceChannel);
403 }
404
405 /** Internal Bluetooth stack Signal Command processing routine for a Connection Request command.
406 *
407 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
408 */
409 static inline void Bluetooth_Signal_ConnectionReq(const BT_Signal_Header_t* const SignalCommandHeader)
410 {
411 BT_Signal_ConnectionReq_t ConnectionRequest;
412
413 Pipe_Read_Stream_LE(&ConnectionRequest, sizeof(ConnectionRequest));
414
415 Pipe_ClearIN();
416 Pipe_Freeze();
417
418 BT_ACL_DEBUG(1, "<< L2CAP Connection Request");
419 BT_ACL_DEBUG(2, "-- PSM: 0x%04X", ConnectionRequest.PSM);
420 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionRequest.SourceChannel);
421
422 /* Try to retrieve the existing channel's information structure if it exists */
423 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConnectionRequest.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
424
425 /* If an existing channel item with the correct remote channel number was not found, find a free channel entry */
426 if (ChannelData == NULL)
427 {
428 /* Look through the channel information list for a free entry */
429 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
430 {
431 if (Bluetooth_Connection.Channels[i].State == BT_Channel_Closed)
432 {
433 ChannelData = &Bluetooth_Connection.Channels[i];
434
435 /* Set the new channel structure's local channel number to a unique value within the connection orientated
436 channel address space */
437 ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);
438 break;
439 }
440 }
441 }
442
443 uint8_t ChannelStatus = BT_CONNECTION_REFUSED_RESOURCES;
444
445 /* Reset the channel item contents only if a channel entry was found for it */
446 if (ChannelData != NULL)
447 {
448 /* Check if the user application will allow the connection based on its PSM */
449 if (Bluetooth_ChannelConnectionRequest(ConnectionRequest.PSM))
450 {
451 ChannelData->RemoteNumber = ConnectionRequest.SourceChannel;
452 ChannelData->PSM = ConnectionRequest.PSM;
453 ChannelData->LocalMTU = MAXIMUM_CHANNEL_MTU;
454 ChannelData->State = BT_Channel_Config_WaitConfig;
455
456 ChannelStatus = BT_CONNECTION_SUCCESSFUL;
457 }
458 else
459 {
460 ChannelStatus = BT_CONNECTION_REFUSED_PSM;
461 }
462 }
463
464 struct
465 {
466 BT_Signal_Header_t SignalCommandHeader;
467 BT_Signal_ConnectionResp_t ConnectionResponse;
468 } ResponsePacket;
469
470 /* Fill out the Signal Command header in the response packet */
471 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_CONNECTION_RESPONSE;
472 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
473 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.ConnectionResponse);
474
475 /* Fill out the Connection Response in the response packet */
476 ResponsePacket.ConnectionResponse.DestinationChannel = ChannelData->LocalNumber;
477 ResponsePacket.ConnectionResponse.SourceChannel = ChannelData->RemoteNumber;
478 ResponsePacket.ConnectionResponse.Result = ChannelStatus;
479 ResponsePacket.ConnectionResponse.Status = 0x00;
480
481 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
482
483 BT_ACL_DEBUG(1, ">> L2CAP Connection Response");
484 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.ConnectionResponse.Result);
485 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket.ConnectionResponse.DestinationChannel);
486 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.ConnectionResponse.SourceChannel);
487 }
488
489 /** Internal Bluetooth stack Signal Command processing routine for a Connection Response command.
490 *
491 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
492 */
493 static inline void Bluetooth_Signal_ConnectionResp(const BT_Signal_Header_t* const SignalCommandHeader)
494 {
495 BT_Signal_ConnectionResp_t ConnectionResponse;
496
497 Pipe_Read_Stream_LE(&ConnectionResponse, sizeof(ConnectionResponse));
498
499 Pipe_ClearIN();
500 Pipe_Freeze();
501
502 BT_ACL_DEBUG(1, "<< L2CAP Connection Response");
503 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConnectionResponse.Result);
504 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionResponse.SourceChannel);
505 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConnectionResponse.DestinationChannel);
506
507 /* Search for the referenced channel in the channel information list */
508 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConnectionResponse.SourceChannel, CHANNEL_SEARCH_LOCALNUMBER);
509
510 /* Only progress if the referenced channel data was found */
511 if (ChannelData != NULL)
512 {
513 /* Set the channel structure's remote channel number to the channel allocated on the remote device */
514 ChannelData->RemoteNumber = ConnectionResponse.SourceChannel;
515 ChannelData->State = (ConnectionResponse.Result == BT_CONNECTION_SUCCESSFUL) ?
516 BT_Channel_Config_WaitConfig : BT_Channel_Closed;
517 }
518 }
519
520 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Request command.
521 *
522 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
523 */
524 static inline void Bluetooth_Signal_ConfigurationReq(const BT_Signal_Header_t* const SignalCommandHeader)
525 {
526 BT_Signal_ConfigurationReq_t ConfigurationRequest;
527
528 /* Allocate a buffer large enough to hold the variable number of configuration options in the request */
529 uint8_t OptionsLen = (SignalCommandHeader->Length - sizeof(ConfigurationRequest));
530 uint8_t Options[OptionsLen];
531
532 Pipe_Read_Stream_LE(&ConfigurationRequest, sizeof(ConfigurationRequest));
533 Pipe_Read_Stream_LE(&Options, sizeof(Options));
534
535 Pipe_ClearIN();
536 Pipe_Freeze();
537
538 /* Search for the referenced channel in the channel information list */
539 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConfigurationRequest.DestinationChannel, CHANNEL_SEARCH_LOCALNUMBER);
540
541 BT_ACL_DEBUG(1, "<< L2CAP Configuration Request");
542 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConfigurationRequest.DestinationChannel);
543 BT_ACL_DEBUG(2, "-- Options Len: 0x%04X", OptionsLen);
544
545 /* Only look at the channel configuration options if a valid channel entry for the local channel number was found */
546 if (ChannelData != NULL)
547 {
548 /* Iterate through each option in the configuration request to look for ones which can be processed */
549 uint8_t OptionPos = 0;
550 while (OptionPos < OptionsLen)
551 {
552 BT_Config_Option_Header_t* OptionHeader = (BT_Config_Option_Header_t*)&Options[OptionPos];
553 void* OptionData = &Options[OptionPos + sizeof(BT_Config_Option_Header_t)];
554
555 BT_ACL_DEBUG(2, "-- Option Type: 0x%04X", OptionHeader->Type);
556 BT_ACL_DEBUG(2, "-- Option Length: 0x%04X", (sizeof(BT_Config_Option_Header_t) + OptionHeader->Length));
557
558 /* Store the remote MTU option's value if present */
559 if (OptionHeader->Type == BT_CONFIG_OPTION_MTU)
560 ChannelData->RemoteMTU = *((uint16_t*)OptionData);
561
562 /* Progress to the next option in the packet */
563 OptionPos += (sizeof(BT_Config_Option_Header_t) + OptionHeader->Length);
564 }
565 }
566
567 struct
568 {
569 BT_Signal_Header_t SignalCommandHeader;
570 BT_Signal_ConfigurationResp_t ConfigurationResponse;
571 } ResponsePacket;
572
573 /* Fill out the Signal Command header in the response packet */
574 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_CONFIGURATION_RESPONSE;
575 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
576 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.ConfigurationResponse);
577
578 /* Fill out the Configuration Response in the response packet */
579 ResponsePacket.ConfigurationResponse.SourceChannel = ChannelData->RemoteNumber;
580 ResponsePacket.ConfigurationResponse.Flags = 0x00;
581 ResponsePacket.ConfigurationResponse.Result = (ChannelData != NULL) ? BT_CONFIGURATION_SUCCESSFUL : BT_CONFIGURATION_REJECTED;
582
583 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
584
585 if (ChannelData != NULL)
586 {
587 switch (ChannelData->State)
588 {
589 case BT_Channel_Config_WaitConfig:
590 ChannelData->State = BT_Channel_Config_WaitSendConfig;
591 break;
592 case BT_Channel_Config_WaitReqResp:
593 ChannelData->State = BT_Channel_Config_WaitResp;
594 break;
595 case BT_Channel_Config_WaitReq:
596 ChannelData->State = BT_Channel_Open;
597 Bluetooth_ChannelOpened(ChannelData);
598 break;
599 }
600 }
601
602 BT_ACL_DEBUG(1, ">> L2CAP Configuration Response");
603 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.ConfigurationResponse.SourceChannel);
604 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.ConfigurationResponse.Result);
605 }
606
607 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Response command.
608 *
609 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
610 */
611 static inline void Bluetooth_Signal_ConfigurationResp(const BT_Signal_Header_t* const SignalCommandHeader)
612 {
613 BT_Signal_ConfigurationResp_t ConfigurationResponse;
614
615 Pipe_Read_Stream_LE(&ConfigurationResponse, sizeof(ConfigurationResponse));
616
617 Pipe_ClearIN();
618 Pipe_Freeze();
619
620 BT_ACL_DEBUG(1, "<< L2CAP Configuration Response");
621 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConfigurationResponse.SourceChannel);
622 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConfigurationResponse.Result);
623
624 /* Search for the referenced channel in the channel information list */
625 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConfigurationResponse.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
626
627 /* Only update the channel's state if it was found in the channel list */
628 if (ChannelData != NULL)
629 {
630 /* Check if the channel configuration completed successfully */
631 if (ConfigurationResponse.Result == BT_CONFIGURATION_SUCCESSFUL)
632 {
633 switch (ChannelData->State)
634 {
635 case BT_Channel_Config_WaitReqResp:
636 ChannelData->State = BT_Channel_Config_WaitReq;
637 break;
638 case BT_Channel_Config_WaitResp:
639 ChannelData->State = BT_Channel_Open;
640 Bluetooth_ChannelOpened(ChannelData);
641 break;
642 }
643 }
644 else
645 {
646 /* Configuration failed - close the channel */
647 ChannelData->State = BT_Channel_Closed;
648 }
649 }
650 }
651
652 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Request command.
653 *
654 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
655 */
656 static inline void Bluetooth_Signal_DisconnectionReq(const BT_Signal_Header_t* const SignalCommandHeader)
657 {
658 BT_Signal_DisconnectionReq_t DisconnectionRequest;
659
660 Pipe_Read_Stream_LE(&DisconnectionRequest, sizeof(DisconnectionRequest));
661
662 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Request");
663 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionRequest.DestinationChannel);
664 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionRequest.SourceChannel);
665
666 Pipe_ClearIN();
667 Pipe_Freeze();
668
669 /* Search for the referenced channel in the channel information list */
670 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(DisconnectionRequest.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
671
672 struct
673 {
674 BT_Signal_Header_t SignalCommandHeader;
675 BT_Signal_DisconnectionResp_t DisconnectionResponse;
676 } ResponsePacket;
677
678 /* Fill out the Signal Command header in the response packet */
679 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_DISCONNECTION_RESPONSE;
680 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
681 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.DisconnectionResponse);
682
683 /* Fill out the Disconnection Response in the response packet */
684 ResponsePacket.DisconnectionResponse.DestinationChannel = ChannelData->RemoteNumber;
685 ResponsePacket.DisconnectionResponse.SourceChannel = ChannelData->LocalNumber;
686
687 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
688
689 /* If the channel was found in the channel list, close it */
690 if (ChannelData != NULL)
691 ChannelData->State = BT_Channel_Closed;
692
693 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Response");
694 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.DisconnectionResponse.SourceChannel);
695 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket.DisconnectionResponse.DestinationChannel);
696 }
697
698 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Response command.
699 *
700 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
701 */
702 static inline void Bluetooth_Signal_DisconnectionResp(const BT_Signal_Header_t* const SignalCommandHeader)
703 {
704 BT_Signal_DisconnectionResp_t DisconnectionResponse;
705
706 Pipe_Read_Stream_LE(&DisconnectionResponse, sizeof(DisconnectionResponse));
707
708 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Response");
709 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionResponse.DestinationChannel);
710 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionResponse.SourceChannel);
711
712 Pipe_ClearIN();
713 Pipe_Freeze();
714
715 /* Search for the referenced channel in the channel information list */
716 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(DisconnectionResponse.SourceChannel, CHANNEL_SEARCH_REMOTENUMBER);
717
718 /* If the channel was found in the channel list, close it */
719 if (ChannelData != NULL)
720 ChannelData->State = BT_Channel_Closed;
721 }
722
723 /** Internal Bluetooth stack Signal Command processing routine for an Echo Request command.
724 *
725 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
726 */
727 static inline void Bluetooth_Signal_EchoReq(const BT_Signal_Header_t* const SignalCommandHeader)
728 {
729 BT_ACL_DEBUG(1, "<< L2CAP Echo Request");
730
731 Pipe_ClearIN();
732 Pipe_Freeze();
733
734 struct
735 {
736 BT_Signal_Header_t SignalCommandHeader;
737 } ResponsePacket;
738
739 /* Fill out the Signal Command header in the response packet */
740 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_ECHO_RESPONSE;
741 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
742 ResponsePacket.SignalCommandHeader.Length = 0;
743
744 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
745
746 BT_ACL_DEBUG(1, ">> L2CAP Echo Response");
747 }
748
749 /** Internal Bluetooth stack Signal Command processing routine for an Information Request command.
750 *
751 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
752 */
753 static inline void Bluetooth_Signal_InformationReq(const BT_Signal_Header_t* const SignalCommandHeader)
754 {
755 BT_Signal_InformationReq_t InformationRequest;
756
757 Pipe_Read_Stream_LE(&InformationRequest, sizeof(InformationRequest));
758
759 BT_ACL_DEBUG(1, "<< L2CAP Information Request");
760 BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest.InfoType);
761
762 Pipe_ClearIN();
763 Pipe_Freeze();
764
765 struct
766 {
767 BT_Signal_Header_t SignalCommandHeader;
768 BT_Signal_InformationResp_t InformationResponse;
769
770 uint8_t Data[4];
771 } ResponsePacket;
772
773 uint8_t DataLen = 0;
774
775 /* Retrieve the requested information and store it in the outgoing packet, if found */
776 switch (InformationRequest.InfoType)
777 {
778 case BT_INFOREQ_MTU:
779 ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
780 DataLen = 2;
781
782 *((uint16_t*)&ResponsePacket.Data) = MAXIMUM_CHANNEL_MTU;
783 break;
784 case BT_INFOREQ_EXTENDEDFEATURES:
785 ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
786 DataLen = 4;
787
788 *((uint32_t*)&ResponsePacket.Data) = 0;
789 break;
790 default:
791 ResponsePacket.InformationResponse.Result = BT_INFORMATION_NOTSUPPORTED;
792 DataLen = 0;
793 break;
794 }
795
796 /* Fill out the Signal Command header in the response packet */
797 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_INFORMATION_RESPONSE;
798 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
799 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.InformationResponse) + DataLen;
800
801 /* Fill out the Information Response in the response packet */
802 ResponsePacket.InformationResponse.InfoType = InformationRequest.InfoType;
803
804 Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket) - sizeof(ResponsePacket.Data) + DataLen), NULL);
805
806 BT_ACL_DEBUG(1, ">> L2CAP Information Response");
807 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.InformationResponse.Result);
808 }
809