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