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