3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2010 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 incomming ACL packets, if any */
52 Bluetooth_ProcessIncommingACLPackets();
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
.SignallingIdentifier
;
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 /** Incomming ACL packet processing task. This task is called by the main ACL processing task to read in and process
112 * any incomming ACL packets to the device, handling signal requests as they are received or passing along channel
113 * data to the user application.
115 static void Bluetooth_ProcessIncommingACLPackets(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
));
131 Pipe_Read_Stream_LE(&DataHeader
, sizeof(DataHeader
));
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 - signalling channel should be processed by the stack internally */
141 if (DataHeader
.DestinationChannel
== BT_CHANNEL_SIGNALING
)
143 /* Read in the Signal Command header of the incomming packet */
144 BT_Signal_Header_t SignalCommandHeader
;
145 Pipe_Read_Stream_LE(&SignalCommandHeader
, sizeof(SignalCommandHeader
));
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
));
179 Pipe_Discard_Stream(ACLPacketHeader
.DataLength
- sizeof(RejectReason
));
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
);
196 /* Non-signalling packet received, read in the packet contents and pass to the user application */
197 uint8_t PacketData
[DataHeader
.PayloadLength
];
198 Pipe_Read_Stream_LE(PacketData
, DataHeader
.PayloadLength
);
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 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
, const uint8_t SearchKey
)
216 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
218 Bluetooth_Channel_t
* ChannelData
= &Bluetooth_Connection
.Channels
[i
];
220 /* Closed channels should be ignored as they are not considered valid data */
221 if (ChannelData
->State
== BT_Channel_Closed
)
224 bool FoundMatch
= false;
226 /* Search the current channel for the search key to see if it matches */
229 case CHANNEL_SEARCH_LOCALNUMBER
:
230 FoundMatch
= (SearchValue
== ChannelData
->LocalNumber
);
232 case CHANNEL_SEARCH_REMOTENUMBER
:
233 FoundMatch
= (SearchValue
== ChannelData
->RemoteNumber
);
235 case CHANNEL_SEARCH_PSM
:
236 FoundMatch
= (SearchValue
== ChannelData
->PSM
);
247 /** Sends a packet to the remote device on the specified channel.
249 * \param[in] Data Pointer to a buffer where the data is to be sourced from
250 * \param[in] DataLen Length of the data to send
251 * \param[in] Channel Channel information structure containing the destination channel's information, NULL to send
252 * to the remote device's signalling channel
254 * \return A value from the \ref BT_SendPacket_ErrorCodes_t enum
256 uint8_t Bluetooth_SendPacket(void* Data
, const uint16_t DataLen
, Bluetooth_Channel_t
* const ACLChannel
)
258 BT_ACL_Header_t ACLPacketHeader
;
259 BT_DataPacket_Header_t DataHeader
;
261 /* A remote device must be connected before a packet transmission is attempted */
262 if (!(Bluetooth_Connection
.IsConnected
))
263 return BT_SENDPACKET_NotConnected
;
265 /* If the destination channel is not the signalling channel and it is not currently fully open, abort */
266 if ((ACLChannel
== NULL
) || (ACLChannel
->State
!= BT_Channel_Open
))
267 return BT_SENDPACKET_ChannelNotOpen
;
269 /* Fill out the packet's header from the remote device connection information structure */
270 ACLPacketHeader
.ConnectionHandle
= (Bluetooth_Connection
.ConnectionHandle
| BT_ACL_FIRST_AUTOFLUSH
);
271 ACLPacketHeader
.DataLength
= sizeof(DataHeader
) + DataLen
;
272 DataHeader
.PayloadLength
= DataLen
;
273 DataHeader
.DestinationChannel
= (ACLChannel
== NULL
) ? BT_CHANNEL_SIGNALING
: ACLChannel
->RemoteNumber
;
275 Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE
);
277 Pipe_WaitUntilReady();
280 /* Write the packet contents to the pipe so that it can be sent to the remote device */
281 Pipe_Write_Stream_LE(&ACLPacketHeader
, sizeof(ACLPacketHeader
));
282 Pipe_Write_Stream_LE(&DataHeader
, sizeof(DataHeader
));
283 Pipe_Write_Stream_LE(Data
, DataLen
);
289 BT_ACL_DEBUG(2, "Packet Sent");
290 BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader
.ConnectionHandle
& 0x0FFF));
291 BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader
.DataLength
);
292 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader
.DestinationChannel
);
293 BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader
.PayloadLength
);
295 return BT_SENDPACKET_NoError
;
298 /** Opens a Bluetooth channel to the currently connected remote device, so that data can be exchanged.
300 * \note The channel is not immediately opened when this function returns - it must undergo a two way
301 * connection and configuration process first as the main Bluetooth stack processing task is
302 * repeatedly called. The returned channel is unusable by the user application until its State
303 * element has progressed to the Open state.
305 * \param[in] PSM PSM of the service that the channel is to be opened for
307 * \return Pointer to the channel information structure of the opened channel, or NULL if no free channels
309 Bluetooth_Channel_t
* Bluetooth_OpenChannel(const uint16_t PSM
)
311 Bluetooth_Channel_t
* ChannelData
= NULL
;
313 /* Search through the channel information list for a free channel item */
314 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
316 if (Bluetooth_Connection
.Channels
[i
].State
== BT_Channel_Closed
)
318 ChannelData
= &Bluetooth_Connection
.Channels
[i
];
320 /* Set the new channel structure's local channel number to a unique value within the connection orientated
321 channel address space */
322 ChannelData
->LocalNumber
= (BT_CHANNELNUMBER_BASEOFFSET
+ i
);
327 /* If no free channel item was found in the list, all channels are occupied - abort */
328 if (ChannelData
== NULL
)
331 /* Reset and fill out the allocated channel's information structure with defaults */
332 ChannelData
->RemoteNumber
= 0;
333 ChannelData
->PSM
= PSM
;
334 ChannelData
->LocalMTU
= MAXIMUM_CHANNEL_MTU
;
335 ChannelData
->State
= BT_Channel_WaitConnectRsp
;
339 BT_Signal_Header_t SignalCommandHeader
;
340 BT_Signal_ConnectionReq_t ConnectionRequest
;
343 /* Fill out the Signal Command header in the response packet */
344 PacketData
.SignalCommandHeader
.Code
= BT_SIGNAL_CONNECTION_REQUEST
;
345 PacketData
.SignalCommandHeader
.Identifier
= ++Bluetooth_Connection
.SignallingIdentifier
;
346 PacketData
.SignalCommandHeader
.Length
= sizeof(PacketData
.ConnectionRequest
);
348 /* Fill out the Connection Request in the response packet */
349 PacketData
.ConnectionRequest
.PSM
= PSM
;
350 PacketData
.ConnectionRequest
.SourceChannel
= ChannelData
->LocalNumber
;
352 Bluetooth_SendPacket(&PacketData
, sizeof(PacketData
), NULL
);
354 BT_ACL_DEBUG(1, ">> L2CAP Connection Request");
355 BT_ACL_DEBUG(2, "-- PSM 0x%04X", PacketData
.ConnectionRequest
.PSM
);
356 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData
.ConnectionRequest
.SourceChannel
);
361 /** Closes a Bluetooth channel that is open to the currently connected remote device, so that no further data
364 * \note The channel is not immediately closed when this function returns - it must undergo an asynchronous
365 * disconnection process first as the main Bluetooth stack processing task is repeatedly called. The
366 * returned channel is unusable by the user application upon return however the channel is not completely
367 * closed until its State element has progressed to the Closed state.
369 * \param[in,out] Channel Channel information structure of the channel to close
371 void Bluetooth_CloseChannel(Bluetooth_Channel_t
* const ACLChannel
)
373 /* Don't try to close a non-existing or already closed channel */
374 if ((ACLChannel
== NULL
) || (ACLChannel
->State
== BT_Channel_Closed
))
377 /* Set the channel's state to the start of the teardown process */
378 ACLChannel
->State
= BT_Channel_WaitDisconnect
;
382 BT_Signal_Header_t SignalCommandHeader
;
383 BT_Signal_DisconnectionReq_t DisconnectionRequest
;
386 /* Fill out the Signal Command header in the response packet */
387 PacketData
.SignalCommandHeader
.Code
= BT_SIGNAL_DISCONNECTION_REQUEST
;
388 PacketData
.SignalCommandHeader
.Identifier
= ++Bluetooth_Connection
.SignallingIdentifier
;
389 PacketData
.SignalCommandHeader
.Length
= sizeof(PacketData
.DisconnectionRequest
);
391 /* Fill out the Disconnection Request in the response packet */
392 PacketData
.DisconnectionRequest
.DestinationChannel
= ACLChannel
->RemoteNumber
;
393 PacketData
.DisconnectionRequest
.SourceChannel
= ACLChannel
->LocalNumber
;
395 Bluetooth_SendPacket(&PacketData
, sizeof(PacketData
), NULL
);
397 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Request");
398 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData
.DisconnectionRequest
.DestinationChannel
);
399 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData
.DisconnectionRequest
.SourceChannel
);
402 /** Internal Bluetooth stack Signal Command processing routine for a Connection Request command.
404 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
406 static inline void Bluetooth_Signal_ConnectionReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
408 BT_Signal_ConnectionReq_t ConnectionRequest
;
410 Pipe_Read_Stream_LE(&ConnectionRequest
, sizeof(ConnectionRequest
));
415 BT_ACL_DEBUG(1, "<< L2CAP Connection Request");
416 BT_ACL_DEBUG(2, "-- PSM: 0x%04X", ConnectionRequest
.PSM
);
417 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionRequest
.SourceChannel
);
419 /* Try to retrieve the existing channel's information structure if it exists */
420 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConnectionRequest
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
422 /* If an existing channel item with the correct remote channel number was not found, find a free channel entry */
423 if (ChannelData
== NULL
)
425 /* Look through the channel information list for a free entry */
426 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
428 if (Bluetooth_Connection
.Channels
[i
].State
== BT_Channel_Closed
)
430 ChannelData
= &Bluetooth_Connection
.Channels
[i
];
432 /* Set the new channel structure's local channel number to a unique value within the connection orientated
433 channel address space */
434 ChannelData
->LocalNumber
= (BT_CHANNELNUMBER_BASEOFFSET
+ i
);
440 uint8_t ChannelStatus
= BT_CONNECTION_REFUSED_RESOURCES
;
442 /* Reset the channel item contents only if a channel entry was found for it */
443 if (ChannelData
!= NULL
)
445 /* Check if the user application will allow the connection based on its PSM */
446 if (Bluetooth_ChannelConnectionRequest(ConnectionRequest
.PSM
))
448 ChannelData
->RemoteNumber
= ConnectionRequest
.SourceChannel
;
449 ChannelData
->PSM
= ConnectionRequest
.PSM
;
450 ChannelData
->LocalMTU
= MAXIMUM_CHANNEL_MTU
;
451 ChannelData
->State
= BT_Channel_Config_WaitConfig
;
453 ChannelStatus
= BT_CONNECTION_SUCCESSFUL
;
457 ChannelStatus
= BT_CONNECTION_REFUSED_PSM
;
463 BT_Signal_Header_t SignalCommandHeader
;
464 BT_Signal_ConnectionResp_t ConnectionResponse
;
467 /* Fill out the Signal Command header in the response packet */
468 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_CONNECTION_RESPONSE
;
469 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
470 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.ConnectionResponse
);
472 /* Fill out the Connection Response in the response packet */
473 ResponsePacket
.ConnectionResponse
.DestinationChannel
= ChannelData
->LocalNumber
;
474 ResponsePacket
.ConnectionResponse
.SourceChannel
= ChannelData
->RemoteNumber
;
475 ResponsePacket
.ConnectionResponse
.Result
= ChannelStatus
;
476 ResponsePacket
.ConnectionResponse
.Status
= 0x00;
478 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
480 BT_ACL_DEBUG(1, ">> L2CAP Connection Response");
481 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.ConnectionResponse
.Result
);
482 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket
.ConnectionResponse
.DestinationChannel
);
483 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket
.ConnectionResponse
.SourceChannel
);
486 /** Internal Bluetooth stack Signal Command processing routine for a Connection Response command.
488 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
490 static inline void Bluetooth_Signal_ConnectionResp(const BT_Signal_Header_t
* const SignalCommandHeader
)
492 BT_Signal_ConnectionResp_t ConnectionResponse
;
494 Pipe_Read_Stream_LE(&ConnectionResponse
, sizeof(ConnectionResponse
));
499 BT_ACL_DEBUG(1, "<< L2CAP Connection Response");
500 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConnectionResponse
.Result
);
501 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionResponse
.SourceChannel
);
502 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConnectionResponse
.DestinationChannel
);
504 /* Search for the referenced channel in the channel information list */
505 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConnectionResponse
.SourceChannel
, CHANNEL_SEARCH_LOCALNUMBER
);
507 /* Only progress if the referenced channel data was found */
508 if (ChannelData
!= NULL
)
510 /* Set the channel structure's remote channel number to the channel allocated on the remote device */
511 ChannelData
->RemoteNumber
= ConnectionResponse
.SourceChannel
;
512 ChannelData
->State
= (ConnectionResponse
.Result
== BT_CONNECTION_SUCCESSFUL
) ?
513 BT_Channel_Config_WaitConfig
: BT_Channel_Closed
;
517 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Request command.
519 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
521 static inline void Bluetooth_Signal_ConfigurationReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
523 BT_Signal_ConfigurationReq_t ConfigurationRequest
;
525 /* Allocate a buffer large enough to hold the variable number of configuration options in the request */
526 uint8_t OptionsLen
= (SignalCommandHeader
->Length
- sizeof(ConfigurationRequest
));
527 uint8_t Options
[OptionsLen
];
529 Pipe_Read_Stream_LE(&ConfigurationRequest
, sizeof(ConfigurationRequest
));
530 Pipe_Read_Stream_LE(&Options
, sizeof(Options
));
535 /* Search for the referenced channel in the channel information list */
536 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConfigurationRequest
.DestinationChannel
, CHANNEL_SEARCH_LOCALNUMBER
);
538 BT_ACL_DEBUG(1, "<< L2CAP Configuration Request");
539 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConfigurationRequest
.DestinationChannel
);
540 BT_ACL_DEBUG(2, "-- Options Len: 0x%04X", OptionsLen
);
542 /* Only look at the channel configuration options if a valid channel entry for the local channel number was found */
543 if (ChannelData
!= NULL
)
545 /* Iterate through each option in the configuration request to look for ones which can be processed */
546 uint8_t OptionPos
= 0;
547 while (OptionPos
< OptionsLen
)
549 BT_Config_Option_Header_t
* OptionHeader
= (BT_Config_Option_Header_t
*)&Options
[OptionPos
];
550 void* OptionData
= &Options
[OptionPos
+ sizeof(BT_Config_Option_Header_t
)];
552 BT_ACL_DEBUG(2, "-- Option Type: 0x%04X", OptionHeader
->Type
);
553 BT_ACL_DEBUG(2, "-- Option Length: 0x%04X", (sizeof(BT_Config_Option_Header_t
) + OptionHeader
->Length
));
555 /* Store the remote MTU option's value if present */
556 if (OptionHeader
->Type
== BT_CONFIG_OPTION_MTU
)
557 ChannelData
->RemoteMTU
= *((uint16_t*)OptionData
);
559 /* Progress to the next option in the packet */
560 OptionPos
+= (sizeof(BT_Config_Option_Header_t
) + OptionHeader
->Length
);
566 BT_Signal_Header_t SignalCommandHeader
;
567 BT_Signal_ConfigurationResp_t ConfigurationResponse
;
570 /* Fill out the Signal Command header in the response packet */
571 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_CONFIGURATION_RESPONSE
;
572 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
573 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.ConfigurationResponse
);
575 /* Fill out the Configuration Response in the response packet */
576 ResponsePacket
.ConfigurationResponse
.SourceChannel
= ChannelData
->RemoteNumber
;
577 ResponsePacket
.ConfigurationResponse
.Flags
= 0x00;
578 ResponsePacket
.ConfigurationResponse
.Result
= (ChannelData
!= NULL
) ? BT_CONFIGURATION_SUCCESSFUL
: BT_CONFIGURATION_REJECTED
;
580 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
582 if (ChannelData
!= NULL
)
584 switch (ChannelData
->State
)
586 case BT_Channel_Config_WaitConfig
:
587 ChannelData
->State
= BT_Channel_Config_WaitSendConfig
;
589 case BT_Channel_Config_WaitReqResp
:
590 ChannelData
->State
= BT_Channel_Config_WaitResp
;
592 case BT_Channel_Config_WaitReq
:
593 ChannelData
->State
= BT_Channel_Open
;
594 Bluetooth_ChannelOpened(ChannelData
);
599 BT_ACL_DEBUG(1, ">> L2CAP Configuration Response");
600 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket
.ConfigurationResponse
.SourceChannel
);
601 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.ConfigurationResponse
.Result
);
604 /** Internal Bluetooth stack Signal Command processing routine for a Configuration Response command.
606 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
608 static inline void Bluetooth_Signal_ConfigurationResp(const BT_Signal_Header_t
* const SignalCommandHeader
)
610 BT_Signal_ConfigurationResp_t ConfigurationResponse
;
612 Pipe_Read_Stream_LE(&ConfigurationResponse
, sizeof(ConfigurationResponse
));
617 BT_ACL_DEBUG(1, "<< L2CAP Configuration Response");
618 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConfigurationResponse
.SourceChannel
);
619 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConfigurationResponse
.Result
);
621 /* Search for the referenced channel in the channel information list */
622 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConfigurationResponse
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
624 /* Only update the channel's state if it was found in the channel list */
625 if (ChannelData
!= NULL
)
627 /* Check if the channel configuration completed successfuly */
628 if (ConfigurationResponse
.Result
== BT_CONFIGURATION_SUCCESSFUL
)
630 switch (ChannelData
->State
)
632 case BT_Channel_Config_WaitReqResp
:
633 ChannelData
->State
= BT_Channel_Config_WaitReq
;
635 case BT_Channel_Config_WaitResp
:
636 ChannelData
->State
= BT_Channel_Open
;
637 Bluetooth_ChannelOpened(ChannelData
);
643 /* Configuration failed - close the channel */
644 ChannelData
->State
= BT_Channel_Closed
;
649 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Request command.
651 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
653 static inline void Bluetooth_Signal_DisconnectionReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
655 BT_Signal_DisconnectionReq_t DisconnectionRequest
;
657 Pipe_Read_Stream_LE(&DisconnectionRequest
, sizeof(DisconnectionRequest
));
659 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Request");
660 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionRequest
.DestinationChannel
);
661 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionRequest
.SourceChannel
);
666 /* Search for the referenced channel in the channel information list */
667 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(DisconnectionRequest
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
671 BT_Signal_Header_t SignalCommandHeader
;
672 BT_Signal_DisconnectionResp_t DisconnectionResponse
;
675 /* Fill out the Signal Command header in the response packet */
676 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_DISCONNECTION_RESPONSE
;
677 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
678 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.DisconnectionResponse
);
680 /* Fill out the Disconnection Response in the response packet */
681 ResponsePacket
.DisconnectionResponse
.DestinationChannel
= ChannelData
->RemoteNumber
;
682 ResponsePacket
.DisconnectionResponse
.SourceChannel
= ChannelData
->LocalNumber
;
684 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
686 /* If the channel was found in the channel list, close it */
687 if (ChannelData
!= NULL
)
688 ChannelData
->State
= BT_Channel_Closed
;
690 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Response");
691 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket
.DisconnectionResponse
.SourceChannel
);
692 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket
.DisconnectionResponse
.DestinationChannel
);
695 /** Internal Bluetooth stack Signal Command processing routine for a Disconnection Response command.
697 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
699 static inline void Bluetooth_Signal_DisconnectionResp(const BT_Signal_Header_t
* const SignalCommandHeader
)
701 BT_Signal_DisconnectionResp_t DisconnectionResponse
;
703 Pipe_Read_Stream_LE(&DisconnectionResponse
, sizeof(DisconnectionResponse
));
705 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Response");
706 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionResponse
.DestinationChannel
);
707 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionResponse
.SourceChannel
);
712 /* Search for the referenced channel in the channel information list */
713 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(DisconnectionResponse
.SourceChannel
, CHANNEL_SEARCH_REMOTENUMBER
);
715 /* If the channel was found in the channel list, close it */
716 if (ChannelData
!= NULL
)
717 ChannelData
->State
= BT_Channel_Closed
;
720 /** Internal Bluetooth stack Signal Command processing routine for an Echo Request command.
722 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
724 static inline void Bluetooth_Signal_EchoReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
726 BT_ACL_DEBUG(1, "<< L2CAP Echo Request");
733 BT_Signal_Header_t SignalCommandHeader
;
736 /* Fill out the Signal Command header in the response packet */
737 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_ECHO_RESPONSE
;
738 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
739 ResponsePacket
.SignalCommandHeader
.Length
= 0;
741 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
743 BT_ACL_DEBUG(1, ">> L2CAP Echo Response");
746 /** Internal Bluetooth stack Signal Command processing routine for an Information Request command.
748 * \param[in] SignalCommandHeader Pointer to the start of the received packet's Signal Command header
750 static inline void Bluetooth_Signal_InformationReq(const BT_Signal_Header_t
* const SignalCommandHeader
)
752 BT_Signal_InformationReq_t InformationRequest
;
754 Pipe_Read_Stream_LE(&InformationRequest
, sizeof(InformationRequest
));
756 BT_ACL_DEBUG(1, "<< L2CAP Information Request");
757 BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest
.InfoType
);
764 BT_Signal_Header_t SignalCommandHeader
;
765 BT_Signal_InformationResp_t InformationResponse
;
772 /* Retrieve the requested information and store it in the outgoing packet, if found */
773 switch (InformationRequest
.InfoType
)
776 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_SUCCESSFUL
;
779 *((uint16_t*)&ResponsePacket
.Data
) = MAXIMUM_CHANNEL_MTU
;
781 case BT_INFOREQ_EXTENDEDFEATURES
:
782 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_SUCCESSFUL
;
785 *((uint32_t*)&ResponsePacket
.Data
) = 0;
788 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_NOTSUPPORTED
;
793 /* Fill out the Signal Command header in the response packet */
794 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_INFORMATION_RESPONSE
;
795 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
796 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.InformationResponse
) + DataLen
;
798 /* Fill out the Information Response in the response packet */
799 ResponsePacket
.InformationResponse
.InfoType
= InformationRequest
.InfoType
;
801 Bluetooth_SendPacket(&ResponsePacket
, (sizeof(ResponsePacket
) - sizeof(ResponsePacket
.Data
) + DataLen
), NULL
);
803 BT_ACL_DEBUG(1, ">> L2CAP Information Response");
804 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.InformationResponse
.Result
);