3 Copyright (C) Dean Camera, 2012.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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
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.
39 TODO: Make SendPacket respect receiver's MTU
40 TODO: Make ReceivePacket stitch together MTU fragments (?)
43 #define INCLUDE_FROM_BLUETOOTH_ACLPACKETS_C
44 #include "BluetoothACLPackets.h"
46 /** Bluetooth ACL processing task. This task should be called repeatedly the main Bluetooth
47 * stack task to manage the ACL processing state.
49 void Bluetooth_ACLTask(void)
51 /* Process incoming ACL packets, if any */
52 Bluetooth_ProcessIncomingACLPackets();
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
++)
57 Bluetooth_Channel_t
* ChannelData
= &Bluetooth_Connection
.Channels
[i
];
59 bool MustSendConfigReq
= true;
61 /* Check if we are in a channel state which requires a configuration request to be sent */
62 switch (ChannelData
->State
)
64 case BT_Channel_Config_WaitConfig
:
65 ChannelData
->State
= BT_Channel_Config_WaitReqResp
;
67 case BT_Channel_Config_WaitSendConfig
:
68 ChannelData
->State
= BT_Channel_Config_WaitResp
;
71 MustSendConfigReq
= false;
75 /* Only send a configuration request if it the channel was in a state which required it */
76 if (MustSendConfigReq
)
80 BT_Signal_Header_t SignalCommandHeader
;
81 BT_Signal_ConfigurationReq_t ConfigurationRequest
;
85 BT_Config_Option_Header_t Header
;
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
);
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
;
103 Bluetooth_SendPacket(&PacketData
, sizeof(PacketData
), NULL
);
105 BT_ACL_DEBUG(1, ">> L2CAP Configuration Request");
106 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData
.ConfigurationRequest
.DestinationChannel
);
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.
115 static void Bluetooth_ProcessIncomingACLPackets(void)
117 BT_ACL_Header_t ACLPacketHeader
;
118 BT_DataPacket_Header_t DataHeader
;
120 Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE
);
123 if (!(Pipe_IsReadWriteAllowed()))
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
), NULL
);
131 Pipe_Read_Stream_LE(&DataHeader
, sizeof(DataHeader
), NULL
);
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
);
140 /* Check the packet's destination channel - signaling channel should be processed by the stack internally */
141 if (DataHeader
.DestinationChannel
== BT_CHANNEL_SIGNALING
)
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
), NULL
);
147 /* Dispatch to the appropriate handler function based on the Signal message code */
148 switch (SignalCommandHeader
.Code
)
150 case BT_SIGNAL_CONNECTION_REQUEST
:
151 Bluetooth_Signal_ConnectionReq(&SignalCommandHeader
);
153 case BT_SIGNAL_CONNECTION_RESPONSE
:
154 Bluetooth_Signal_ConnectionResp(&SignalCommandHeader
);
156 case BT_SIGNAL_CONFIGURATION_REQUEST
:
157 Bluetooth_Signal_ConfigurationReq(&SignalCommandHeader
);
159 case BT_SIGNAL_CONFIGURATION_RESPONSE
:
160 Bluetooth_Signal_ConfigurationResp(&SignalCommandHeader
);
162 case BT_SIGNAL_DISCONNECTION_REQUEST
:
163 Bluetooth_Signal_DisconnectionReq(&SignalCommandHeader
);
165 case BT_SIGNAL_DISCONNECTION_RESPONSE
:
166 Bluetooth_Signal_DisconnectionResp(&SignalCommandHeader
);
168 case BT_SIGNAL_ECHO_REQUEST
:
169 Bluetooth_Signal_EchoReq(&SignalCommandHeader
);
171 case BT_SIGNAL_INFORMATION_REQUEST
:
172 Bluetooth_Signal_InformationReq(&SignalCommandHeader
);
174 case BT_SIGNAL_COMMAND_REJECT
:
175 BT_ACL_DEBUG(1, "<< Command Reject");
177 uint16_t RejectReason
;
178 Pipe_Read_Stream_LE(&RejectReason
, sizeof(RejectReason
), NULL
);
179 Pipe_Discard_Stream(ACLPacketHeader
.DataLength
- sizeof(RejectReason
), NULL
);
183 BT_ACL_DEBUG(2, "-- Reason: %d", RejectReason
);
186 BT_ACL_DEBUG(1, "<< Unknown Signaling Command 0x%02X", SignalCommandHeader
.Code
);
188 Pipe_Discard_Stream(ACLPacketHeader
.DataLength
, NULL
);
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
, NULL
);
202 Bluetooth_PacketReceived(PacketData
, DataHeader
.PayloadLength
,
203 Bluetooth_GetChannelData(DataHeader
.DestinationChannel
, CHANNEL_SEARCH_LOCALNUMBER
));
207 /** Retrieves the channel information structure with the given local or remote channel number from the channel list.
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 \c CHANNEL_SEARCH_* mask
212 * \return Pointer to the matching channel information structure in the channel table if found, NULL otherwise
214 Bluetooth_Channel_t
* Bluetooth_GetChannelData(const uint16_t SearchValue
,
215 const uint8_t SearchKey
)
217 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
219 Bluetooth_Channel_t
* ChannelData
= &Bluetooth_Connection
.Channels
[i
];
221 /* Closed channels should be ignored as they are not considered valid data */
222 if (ChannelData
->State
== BT_Channel_Closed
)
225 bool FoundMatch
= false;
227 /* Search the current channel for the search key to see if it matches */
230 case CHANNEL_SEARCH_LOCALNUMBER
:
231 FoundMatch
= (SearchValue
== ChannelData
->LocalNumber
);
233 case CHANNEL_SEARCH_REMOTENUMBER
:
234 FoundMatch
= (SearchValue
== ChannelData
->RemoteNumber
);
236 case CHANNEL_SEARCH_PSM
:
237 FoundMatch
= (SearchValue
== ChannelData
->PSM
);
248 /** Sends a packet to the remote device on the specified channel.
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
255 * \return A value from the \ref BT_SendPacket_ErrorCodes_t enum
257 uint8_t Bluetooth_SendPacket(void* Data
,
258 const uint16_t DataLen
,
259 Bluetooth_Channel_t
* const ACLChannel
)
261 BT_ACL_Header_t ACLPacketHeader
;
262 BT_DataPacket_Header_t DataHeader
;
264 /* A remote device must be connected before a packet transmission is attempted */
265 if (!(Bluetooth_Connection
.IsConnected
))
266 return BT_SENDPACKET_NotConnected
;
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
;
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
;
278 Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE
);
280 Pipe_WaitUntilReady();
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
), NULL
);
285 Pipe_Write_Stream_LE(&DataHeader
, sizeof(DataHeader
), NULL
);
286 Pipe_Write_Stream_LE(Data
, DataLen
, NULL
);
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
);
298 return BT_SENDPACKET_NoError
;
301 /** Opens a Bluetooth channel to the currently connected remote device, so that data can be exchanged.
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.
308 * \param[in] PSM PSM of the service that the channel is to be opened for
310 * \return Pointer to the channel information structure of the opened channel, or NULL if no free channels
312 Bluetooth_Channel_t
* Bluetooth_OpenChannel(const uint16_t PSM
)
314 Bluetooth_Channel_t
* ChannelData
= NULL
;
316 /* Search through the channel information list for a free channel item */
317 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
319 if (Bluetooth_Connection
.Channels
[i
].State
== BT_Channel_Closed
)
321 ChannelData
= &Bluetooth_Connection
.Channels
[i
];
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
);
330 /* If no free channel item was found in the list, all channels are occupied - abort */
331 if (ChannelData
== NULL
)
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
;
342 BT_Signal_Header_t SignalCommandHeader
;
343 BT_Signal_ConnectionReq_t ConnectionRequest
;
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
);
351 /* Fill out the Connection Request in the response packet */
352 PacketData
.ConnectionRequest
.PSM
= PSM
;
353 PacketData
.ConnectionRequest
.SourceChannel
= ChannelData
->LocalNumber
;
355 Bluetooth_SendPacket(&PacketData
, sizeof(PacketData
), NULL
);
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
);
364 /** Closes a Bluetooth channel that is open to the currently connected remote device, so that no further data
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.
372 * \param[in,out] ACLChannel ACL channel information structure of the channel to close
374 void Bluetooth_CloseChannel(Bluetooth_Channel_t
* const ACLChannel
)
376 /* Don't try to close a non-existing or already closed channel */
377 if ((ACLChannel
== NULL
) || (ACLChannel
->State
== BT_Channel_Closed
))
380 /* Set the channel's state to the start of the teardown process */
381 ACLChannel
->State
= BT_Channel_WaitDisconnect
;
385 BT_Signal_Header_t SignalCommandHeader
;
386 BT_Signal_DisconnectionReq_t DisconnectionRequest
;
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
);
394 /* Fill out the Disconnection Request in the response packet */
395 PacketData
.DisconnectionRequest
.DestinationChannel
= ACLChannel
->RemoteNumber
;
396 PacketData
.DisconnectionRequest
.SourceChannel
= ACLChannel
->LocalNumber
;
398 Bluetooth_SendPacket(&PacketData
, sizeof(PacketData
), NULL
);
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
);
405 /** Internal Bluetooth stack Signal Command processing routine for a Connection Request command.
407 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
409 static inline void Bluetooth_Signal_ConnectionReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
411 BT_Signal_ConnectionReq_t ConnectionRequest
;
413 Pipe_Read_Stream_LE(&ConnectionRequest
, sizeof(ConnectionRequest
), NULL
);
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
);
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
);
425 /* If an existing channel item with the correct remote channel number was not found, find a free channel entry */
426 if (ChannelData
== NULL
)
428 /* Look through the channel information list for a free entry */
429 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
431 if (Bluetooth_Connection
.Channels
[i
].State
== BT_Channel_Closed
)
433 ChannelData
= &Bluetooth_Connection
.Channels
[i
];
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
);
443 uint8_t ChannelStatus
= BT_CONNECTION_REFUSED_RESOURCES
;
445 /* Reset the channel item contents only if a channel entry was found for it */
446 if (ChannelData
!= NULL
)
448 /* Check if the user application will allow the connection based on its PSM */
449 if (Bluetooth_ChannelConnectionRequest(ConnectionRequest
.PSM
))
451 ChannelData
->RemoteNumber
= ConnectionRequest
.SourceChannel
;
452 ChannelData
->PSM
= ConnectionRequest
.PSM
;
453 ChannelData
->LocalMTU
= MAXIMUM_CHANNEL_MTU
;
454 ChannelData
->State
= BT_Channel_Config_WaitConfig
;
456 ChannelStatus
= BT_CONNECTION_SUCCESSFUL
;
460 ChannelStatus
= BT_CONNECTION_REFUSED_PSM
;
466 BT_Signal_Header_t SignalCommandHeader
;
467 BT_Signal_ConnectionResp_t ConnectionResponse
;
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
);
475 /* Fill out the Connection Response in the response packet */
476 ResponsePacket
.ConnectionResponse
.DestinationChannel
= (ChannelData
!= NULL
) ? ChannelData
->LocalNumber
: 0;
477 ResponsePacket
.ConnectionResponse
.SourceChannel
= (ChannelData
!= NULL
) ? ChannelData
->RemoteNumber
: 0;
478 ResponsePacket
.ConnectionResponse
.Result
= ChannelStatus
;
479 ResponsePacket
.ConnectionResponse
.Status
= 0x00;
481 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
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
);
489 /** Internal Bluetooth stack Signal Command processing routine for a Connection Response command.
491 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
493 static inline void Bluetooth_Signal_ConnectionResp(const BT_Signal_Header_t
* const SignalCommandHeader
)
495 BT_Signal_ConnectionResp_t ConnectionResponse
;
497 Pipe_Read_Stream_LE(&ConnectionResponse
, sizeof(ConnectionResponse
), NULL
);
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
);
507 /* Search for the referenced channel in the channel information list */
508 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConnectionResponse
.SourceChannel
, CHANNEL_SEARCH_LOCALNUMBER
);
510 /* Only progress if the referenced channel data was found */
511 if (ChannelData
!= NULL
)
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
;
520 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Request command.
522 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
524 static inline void Bluetooth_Signal_ConfigurationReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
526 BT_Signal_ConfigurationReq_t ConfigurationRequest
;
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
];
532 Pipe_Read_Stream_LE(&ConfigurationRequest
, sizeof(ConfigurationRequest
), NULL
);
533 Pipe_Read_Stream_LE(&Options
, sizeof(Options
), NULL
);
538 /* Search for the referenced channel in the channel information list */
539 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConfigurationRequest
.DestinationChannel
, CHANNEL_SEARCH_LOCALNUMBER
);
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
);
545 /* Only look at the channel configuration options if a valid channel entry for the local channel number was found */
546 if (ChannelData
!= NULL
)
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
)
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
)];
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
));
558 /* Store the remote MTU option's value if present */
559 if (OptionHeader
->Type
== BT_CONFIG_OPTION_MTU
)
560 ChannelData
->RemoteMTU
= *((uint16_t*)OptionData
);
562 /* Progress to the next option in the packet */
563 OptionPos
+= (sizeof(BT_Config_Option_Header_t
) + OptionHeader
->Length
);
569 BT_Signal_Header_t SignalCommandHeader
;
570 BT_Signal_ConfigurationResp_t ConfigurationResponse
;
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
);
578 /* Fill out the Configuration Response in the response packet */
579 ResponsePacket
.ConfigurationResponse
.SourceChannel
= (ChannelData
!= NULL
) ? ChannelData
->RemoteNumber
: 0;
580 ResponsePacket
.ConfigurationResponse
.Flags
= 0x00;
581 ResponsePacket
.ConfigurationResponse
.Result
= (ChannelData
!= NULL
) ? BT_CONFIGURATION_SUCCESSFUL
: BT_CONFIGURATION_REJECTED
;
583 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
585 if (ChannelData
!= NULL
)
587 switch (ChannelData
->State
)
589 case BT_Channel_Config_WaitConfig
:
590 ChannelData
->State
= BT_Channel_Config_WaitSendConfig
;
592 case BT_Channel_Config_WaitReqResp
:
593 ChannelData
->State
= BT_Channel_Config_WaitResp
;
595 case BT_Channel_Config_WaitReq
:
596 ChannelData
->State
= BT_Channel_Open
;
597 Bluetooth_ChannelOpened(ChannelData
);
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
);
607 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Response command.
609 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
611 static inline void Bluetooth_Signal_ConfigurationResp(const BT_Signal_Header_t
* const SignalCommandHeader
)
613 BT_Signal_ConfigurationResp_t ConfigurationResponse
;
615 Pipe_Read_Stream_LE(&ConfigurationResponse
, sizeof(ConfigurationResponse
), NULL
);
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
);
624 /* Search for the referenced channel in the channel information list */
625 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConfigurationResponse
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
627 /* Only update the channel's state if it was found in the channel list */
628 if (ChannelData
!= NULL
)
630 /* Check if the channel configuration completed successfully */
631 if (ConfigurationResponse
.Result
== BT_CONFIGURATION_SUCCESSFUL
)
633 switch (ChannelData
->State
)
635 case BT_Channel_Config_WaitReqResp
:
636 ChannelData
->State
= BT_Channel_Config_WaitReq
;
638 case BT_Channel_Config_WaitResp
:
639 ChannelData
->State
= BT_Channel_Open
;
640 Bluetooth_ChannelOpened(ChannelData
);
646 /* Configuration failed - close the channel */
647 ChannelData
->State
= BT_Channel_Closed
;
652 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Request command.
654 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
656 static inline void Bluetooth_Signal_DisconnectionReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
658 BT_Signal_DisconnectionReq_t DisconnectionRequest
;
660 Pipe_Read_Stream_LE(&DisconnectionRequest
, sizeof(DisconnectionRequest
), NULL
);
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
);
669 /* Search for the referenced channel in the channel information list */
670 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(DisconnectionRequest
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
674 BT_Signal_Header_t SignalCommandHeader
;
675 BT_Signal_DisconnectionResp_t DisconnectionResponse
;
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
);
683 /* Fill out the Disconnection Response in the response packet */
684 ResponsePacket
.DisconnectionResponse
.DestinationChannel
= (ChannelData
!= NULL
) ? ChannelData
->RemoteNumber
: 0;
685 ResponsePacket
.DisconnectionResponse
.SourceChannel
= (ChannelData
!= NULL
) ? ChannelData
->LocalNumber
: 0;
687 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
689 /* If the channel was found in the channel list, close it */
690 if (ChannelData
!= NULL
)
691 ChannelData
->State
= BT_Channel_Closed
;
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
);
698 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Response command.
700 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
702 static inline void Bluetooth_Signal_DisconnectionResp(const BT_Signal_Header_t
* const SignalCommandHeader
)
704 BT_Signal_DisconnectionResp_t DisconnectionResponse
;
706 Pipe_Read_Stream_LE(&DisconnectionResponse
, sizeof(DisconnectionResponse
), NULL
);
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
);
715 /* Search for the referenced channel in the channel information list */
716 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(DisconnectionResponse
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
718 /* If the channel was found in the channel list, close it */
719 if (ChannelData
!= NULL
)
720 ChannelData
->State
= BT_Channel_Closed
;
723 /** Internal Bluetooth stack Signal Command processing routine for an Echo Request command.
725 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
727 static inline void Bluetooth_Signal_EchoReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
729 BT_ACL_DEBUG(1, "<< L2CAP Echo Request");
736 BT_Signal_Header_t SignalCommandHeader
;
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;
744 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
746 BT_ACL_DEBUG(1, ">> L2CAP Echo Response");
749 /** Internal Bluetooth stack Signal Command processing routine for an Information Request command.
751 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
753 static inline void Bluetooth_Signal_InformationReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
755 BT_Signal_InformationReq_t InformationRequest
;
757 Pipe_Read_Stream_LE(&InformationRequest
, sizeof(InformationRequest
), NULL
);
759 BT_ACL_DEBUG(1, "<< L2CAP Information Request");
760 BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest
.InfoType
);
767 BT_Signal_Header_t SignalCommandHeader
;
768 BT_Signal_InformationResp_t InformationResponse
;
775 /* Retrieve the requested information and store it in the outgoing packet, if found */
776 switch (InformationRequest
.InfoType
)
779 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_SUCCESSFUL
;
782 *((uint16_t*)&ResponsePacket
.Data
) = MAXIMUM_CHANNEL_MTU
;
784 case BT_INFOREQ_EXTENDEDFEATURES
:
785 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_SUCCESSFUL
;
788 *((uint32_t*)&ResponsePacket
.Data
) = 0;
791 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_NOTSUPPORTED
;
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
;
801 /* Fill out the Information Response in the response packet */
802 ResponsePacket
.InformationResponse
.InfoType
= InformationRequest
.InfoType
;
804 Bluetooth_SendPacket(&ResponsePacket
, (sizeof(ResponsePacket
) - sizeof(ResponsePacket
.Data
) + DataLen
), NULL
);
806 BT_ACL_DEBUG(1, ">> L2CAP Information Response");
807 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.InformationResponse
.Result
);