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