BluetoothACLPackets.c 30.4 KB
Newer Older
1
2
/*
             LUFA Library
Dean Camera's avatar
Dean Camera committed
3
     Copyright (C) Dean Camera, 2010.
4
5
6
7
8
9
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

/*
Dean Camera's avatar
Dean Camera committed
10
  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
11

12
13
14
15
16
17
18
  Permission to use, copy, modify, distribute, and sell this 
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in 
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting 
  documentation, and that the name of the author not be used in 
  advertising or publicity pertaining to distribution of the 
19
20
21
22
23
24
25
26
27
28
29
30
  software without specific, written prior permission.

  The author disclaim all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

31
32
33
34
35
36
/*
	TODO: Make SendPacket respect receiver's MTU
	TODO: Make ReceivePacket stitch together MTU fragments (?)
	TODO: Add channel opened/closed callbacks
 */

37
38
39
#define  INCLUDE_FROM_BLUETOOTH_ACLPACKETS_C
#include "BluetoothACLPackets.h"

40
41
42
/** Bluetooth ACL processing task. This task should be called repeatedly the main Bluetooth
 *  stack task to manage the ACL processing state.
 */
43
void Bluetooth_ACLTask(void)
44
{
45
46
	/* Process incomming ACL packets, if any */
	Bluetooth_ProcessIncommingACLPackets();
47
	
48
	/* Check for any half-open channels, send configuration details to the remote device if found */
49
50
51
52
53
54
	for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
	{
		Bluetooth_Channel_t* ChannelData = &Bluetooth_Connection.Channels[i];
	
		bool MustSendConfigReq = true;
	
55
		/* Check if we are in a channel state which requires a configuration request to be sent */
56
57
58
59
60
61
62
63
64
65
66
67
68
		switch (ChannelData->State)
		{
			case Channel_Config_WaitConfig:
				ChannelData->State = Channel_Config_WaitReqResp;
				break;
			case Channel_Config_WaitSendConfig:
				ChannelData->State = Channel_Config_WaitResp;
				break;
			default:
				MustSendConfigReq  = false;
				break;
		}
		
69
		/* Only send a configuration request if it the channel was in a state which required it */
70
71
		if (MustSendConfigReq)
		{
72
73
74
75
76
77
78
79
80
81
82
			struct
			{
				BT_Signal_Header_t           SignalCommandHeader;
				BT_Signal_ConfigurationReq_t ConfigurationRequest;
				
				struct
				{
					BT_Config_Option_Header_t Header;
					uint16_t Value;
				} Option_LocalMTU;
			} PacketData;
83
			
84
			/* Fill out the Signal Command header in the response packet */
85
86
87
88
			PacketData.SignalCommandHeader.Code            = BT_SIGNAL_CONFIGURATION_REQUEST;
			PacketData.SignalCommandHeader.Identifier      = ++Bluetooth_Connection.SignallingIdentifier;
			PacketData.SignalCommandHeader.Length          = sizeof(PacketData.ConfigurationRequest) +
			                                                 sizeof(PacketData.Option_LocalMTU);
89
90

			/* Fill out the Configuration Request in the response packet, including local MTU information */
91
92
93
94
95
96
97
			PacketData.ConfigurationRequest.DestinationChannel = ChannelData->RemoteNumber;
			PacketData.ConfigurationRequest.Flags          = 0;
			PacketData.Option_LocalMTU.Header.Type         = BT_CONFIG_OPTION_MTU;
			PacketData.Option_LocalMTU.Header.Length       = sizeof(PacketData.Option_LocalMTU.Value);
			PacketData.Option_LocalMTU.Value               = ChannelData->LocalMTU;

			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
106
107
108
109
/** Incomming ACL packet processing task. This task is called by the main ACL processing task to read in and process
 *  any incomming ACL packets to the device, handling signal requests as they are received or passing along channel
 *  data to the user application.
 */
static void Bluetooth_ProcessIncommingACLPackets(void)
110
111
112
{
	BT_ACL_Header_t        ACLPacketHeader;
	BT_DataPacket_Header_t DataHeader;
113
114
115
116
117
118
119
120
121
122

	Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE);
	Pipe_Unfreeze();
	
	if (!(Pipe_IsReadWriteAllowed()))
	{
		Pipe_Freeze();
		return;
	}
	  
123
	/* Read in the received ACL packet headers when it has been discovered that a packet has been received */
124
125
126
	Pipe_Read_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
	Pipe_Read_Stream_LE(&DataHeader, sizeof(DataHeader));

127
128
	BT_ACL_DEBUG(2, "");
	BT_ACL_DEBUG(2, "Packet Received");
129
130
131
132
	BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader.ConnectionHandle & 0x0FFF));
	BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader.DataLength);
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader.DestinationChannel);
	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
143
		switch (SignalCommandHeader.Code)
		{
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
159
				break;
			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
172
173
174
175
176
177
178
				
				uint16_t RejectReason;
				Pipe_Read_Stream_LE(&RejectReason, sizeof(RejectReason));
				Pipe_Discard_Stream(ACLPacketHeader.DataLength - sizeof(RejectReason));
				Pipe_ClearIN();
				Pipe_Freeze();				
			
				BT_ACL_DEBUG(2, "-- Reason: %d", RejectReason);
				break;
179
			default:
180
				BT_ACL_DEBUG(1, "<< Unknown Signaling Command 0x%02X", SignalCommandHeader.Code);
181
	
182
183
184
185
186
187
188
189
				Pipe_Discard_Stream(ACLPacketHeader.DataLength);
				Pipe_ClearIN();		
				Pipe_Freeze();
				break;
		}
	}
	else
	{
190
191
192
		/* Non-signalling packet received, read in the packet contents and pass to the user application */
		uint8_t PacketData[DataHeader.PayloadLength];
		Pipe_Read_Stream_LE(PacketData, DataHeader.PayloadLength);
193
		Pipe_ClearIN();
194
		Pipe_Freeze();
195

196
197
		Bluetooth_PacketReceived(PacketData, DataHeader.PayloadLength,
		                         Bluetooth_GetChannelData(DataHeader.DestinationChannel, CHANNEL_SEARCH_LOCALNUMBER));
198
199
200
	}
}

201
202
/** Sends a packet to the remote device on the specified channel.
 *
203
204
205
206
 * \param[in] Data     Pointer to a buffer where the data is to be sourced from
 * \param[in] DataLen  Length of the data to send
 * \param[in] Channel  Channel information structure containing the destination channel's information, NULL to send
 *                     to the remote device's signalling channel
207
208
209
 *
 * \return A value from the \ref BT_SendPacket_ErrorCodes_t enum
 */
210
uint8_t Bluetooth_SendPacket(void* Data, const uint16_t DataLen, Bluetooth_Channel_t* const Channel)
211
{
212
213
214
	BT_ACL_Header_t        ACLPacketHeader;
	BT_DataPacket_Header_t DataHeader;

215
	/* A remote device must be connected before a packet transmission is attempted */
216
	if (!(Bluetooth_Connection.IsConnected))
217
218
	  return BT_SENDPACKET_NotConnected;

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
230
231

	Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE);
	Pipe_Unfreeze();
	
232
	/* Write the packet contents to the pipe so that it can be sent to the remote device */
233
234
235
	Pipe_Write_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
	Pipe_Write_Stream_LE(&DataHeader, sizeof(DataHeader));
	Pipe_Write_Stream_LE(Data, DataLen);
236
	Pipe_ClearOUT();
237
	
238
	Pipe_Freeze();
239
	
240
241
	BT_ACL_DEBUG(2, "");
	BT_ACL_DEBUG(2, "Packet Sent");
242
243
244
245
246
	BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader.ConnectionHandle & 0x0FFF));
	BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader.DataLength);
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader.DestinationChannel);
	BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader.PayloadLength);

247
	return BT_SENDPACKET_NoError;
248
249
}

250
251
252
253
254
255
256
/** Opens a bluetooth channel to the currently connected remote device, so that data can be exchanged.
 *
 *  \note The channel is not immediately opened when this function returns - it must undergo a two way
 *        connection and configuration process first as the main Bluetooth stack processing task is
 *        repeatedly called. The returned channel is unusable by the user application until its State
 *        element has progressed to the Open state.
 *
257
 *  \param[in] PSM  PSM of the service that the channel is to be opened for
258
259
260
 *
 *  \return Pointer to the channel information structure of the opened channel, or NULL if no free channels
 */
261
Bluetooth_Channel_t* Bluetooth_OpenChannel(const uint16_t PSM)
262
263
264
{
	Bluetooth_Channel_t* ChannelData = NULL;

265
	/* Search through the channel information list for a free channel item */
266
267
268
269
	for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
	{
		if (Bluetooth_Connection.Channels[i].State == Channel_Closed)
		{
270
271
272
273
			ChannelData = &Bluetooth_Connection.Channels[i];
			
			/* Set the new channel structure's local channel number to a unique value within the connection orientated
			   channel address space */
274
			ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);
275
276
277
278
			break;
		}
	}

279
	/* If no free channel item was found in the list, all channels are occupied - abort */
280
281
282
	if (ChannelData == NULL)
	  return NULL;

283
	/* Reset and fill out the allocated channel's information structure with defaults */
284
285
286
	ChannelData->RemoteNumber = 0;
	ChannelData->PSM          = PSM;
	ChannelData->LocalMTU     = MAXIMUM_CHANNEL_MTU;
287
	ChannelData->State        = Channel_WaitConnectRsp;
288
289
290
291
292
293
294
	  
	struct
	{
		BT_Signal_Header_t        SignalCommandHeader;
		BT_Signal_ConnectionReq_t ConnectionRequest;
	} PacketData;

295
	/* Fill out the Signal Command header in the response packet */
296
297
298
	PacketData.SignalCommandHeader.Code              = BT_SIGNAL_CONNECTION_REQUEST;
	PacketData.SignalCommandHeader.Identifier        = ++Bluetooth_Connection.SignallingIdentifier;
	PacketData.SignalCommandHeader.Length            = sizeof(PacketData.ConnectionRequest);
299
300
	
	/* Fill out the Connection Request in the response packet */
301
302
303
304
305
	PacketData.ConnectionRequest.PSM                 = PSM;
	PacketData.ConnectionRequest.SourceChannel       = ChannelData->LocalNumber;
	
	Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);

306
	BT_ACL_DEBUG(1, ">> L2CAP Connection Request");
307
308
309
310
311
312
	BT_ACL_DEBUG(2, "-- PSM 0x%04X", PacketData.ConnectionRequest.PSM);
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.ConnectionRequest.SourceChannel);

	return ChannelData;
}

313
314
315
316
317
318
319
320
/** Closes a bluetooth channel that is open to the currently connected remote device, so that no further data
 *  can be exchanged.
 *
 *  \note The channel is not immediately closed when this function returns - it must undergo an asynchronous
 *        disconnection process first as the main Bluetooth stack processing task is repeatedly called. The
 *        returned channel is unusable by the user application upon return however the channel is not completely
 *        closed until its State element has progressed to the Closed state.
 *
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
327
	if ((Channel == NULL) || (Channel->State == Channel_Closed))
	  return;
328
329

	/* Set the channel's state to the start of the teardown process */
330
331
332
333
334
335
336
337
	Channel->State = Channel_WaitDisconnect;

	struct
	{
		BT_Signal_Header_t           SignalCommandHeader;
		BT_Signal_DisconnectionReq_t DisconnectionRequest;
	} PacketData;
	
338
	/* Fill out the Signal Command header in the response packet */
339
340
341
	PacketData.SignalCommandHeader.Code            = BT_SIGNAL_DISCONNECTION_REQUEST;
	PacketData.SignalCommandHeader.Identifier      = ++Bluetooth_Connection.SignallingIdentifier;
	PacketData.SignalCommandHeader.Length          = sizeof(PacketData.DisconnectionRequest);
342
343

	/* Fill out the Disconnection Request in the response packet */
344
345
346
347
348
	PacketData.DisconnectionRequest.DestinationChannel = Channel->RemoteNumber;
	PacketData.DisconnectionRequest.SourceChannel = Channel->LocalNumber;

	Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
	
349
	BT_ACL_DEBUG(1, ">> L2CAP Disconnection Request");
350
351
352
353
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData.DisconnectionRequest.DestinationChannel);	
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.DisconnectionRequest.SourceChannel);	
}

354
355
/** Internal Bluetooth stack Signal Command processing routine for a Connection Request command.
 *
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
363
364
365
366
	
	Pipe_Read_Stream_LE(&ConnectionRequest, sizeof(ConnectionRequest));

	Pipe_ClearIN();
	Pipe_Freeze();

367
	BT_ACL_DEBUG(1, "<< L2CAP Connection Request");
368
369
	BT_ACL_DEBUG(2, "-- PSM: 0x%04X", ConnectionRequest.PSM);
	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
376
	if (ChannelData == NULL)
	{
377
		/* Look through the channel information list for a free entry */
378
379
380
381
		for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
		{
			if (Bluetooth_Connection.Channels[i].State == Channel_Closed)
			{
382
383
384
385
				ChannelData = &Bluetooth_Connection.Channels[i];

				/* Set the new channel structure's local channel number to a unique value within the connection orientated
				   channel address space */
386
				ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);
387
388
389
390
				break;
			}
		}
	}
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
396
	if (ChannelData != NULL)
	{
397
398
399
400
401
402
403
		/* Check if the user application will allow the connection based on its PSM */
		if (Bluetooth_ChannelConnectionRequest(ConnectionRequest.PSM))
		{
			ChannelData->RemoteNumber = ConnectionRequest.SourceChannel;
			ChannelData->PSM          = ConnectionRequest.PSM;
			ChannelData->LocalMTU     = MAXIMUM_CHANNEL_MTU;
			ChannelData->State        = Channel_Config_WaitConfig;
404
			
405
406
407
408
409
410
			ChannelStatus = BT_CONNECTION_SUCCESSFUL;
		}
		else
		{
			ChannelStatus = BT_CONNECTION_REFUSED_PSM;		
		}
411
412
	}
	
413
414
415
416
417
418
	struct
	{
		BT_Signal_Header_t         SignalCommandHeader;
		BT_Signal_ConnectionResp_t ConnectionResponse;
	} ResponsePacket;

419
	/* Fill out the Signal Command header in the response packet */
420
421
422
	ResponsePacket.SignalCommandHeader.Code              = BT_SIGNAL_CONNECTION_RESPONSE;
	ResponsePacket.SignalCommandHeader.Identifier        = SignalCommandHeader->Identifier;
	ResponsePacket.SignalCommandHeader.Length            = sizeof(ResponsePacket.ConnectionResponse);
423
424

	/* Fill out the Connection Response in the response packet */
425
426
	ResponsePacket.ConnectionResponse.DestinationChannel = ChannelData->LocalNumber;
	ResponsePacket.ConnectionResponse.SourceChannel      = ChannelData->RemoteNumber;
427
	ResponsePacket.ConnectionResponse.Result             = ChannelStatus;
428
429
430
431
	ResponsePacket.ConnectionResponse.Status             = 0x00;
	
	Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);

432
	BT_ACL_DEBUG(1, ">> L2CAP Connection Response");
433
434
	BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.ConnectionResponse.Result);
	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
439
/** Internal Bluetooth stack Signal Command processing routine for a Connection Response command.
 *
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
445
446
447
448
449
450
{
	BT_Signal_ConnectionResp_t ConnectionResponse;
	
	Pipe_Read_Stream_LE(&ConnectionResponse, sizeof(ConnectionResponse));

	Pipe_ClearIN();
	Pipe_Freeze();

451
	BT_ACL_DEBUG(1, "<< L2CAP Connection Response");
452
453
454
455
	BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConnectionResponse.Result);	
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionResponse.SourceChannel);	
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConnectionResponse.DestinationChannel);	

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
461
	if (ChannelData != NULL)
	{
462
		/* Set the channel structure's remote channel number to the channel allocated on the remote device */
463
464
465
466
467
468
		ChannelData->RemoteNumber = ConnectionResponse.SourceChannel;
		ChannelData->State        = (ConnectionResponse.Result == BT_CONNECTION_SUCCESSFUL) ?
		                             Channel_Config_WaitConfig : Channel_Closed;
	}
}

469
470
/** Internal Bluetooth stack Signal Command processing routine for a Configuration Request command.
 *
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
479
	uint8_t OptionsLen = (SignalCommandHeader->Length - sizeof(ConfigurationRequest));
	uint8_t Options[OptionsLen];
480

481
482
	Pipe_Read_Stream_LE(&ConfigurationRequest, sizeof(ConfigurationRequest));	
	Pipe_Read_Stream_LE(&Options, sizeof(Options));
483

484
485
486
	Pipe_ClearIN();
	Pipe_Freeze();

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
492
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConfigurationRequest.DestinationChannel);
	BT_ACL_DEBUG(2, "-- Remote MTU: 0x%04X", ChannelData->RemoteMTU);
493
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 */
	if (ChannelData != NULL)
497
	{
498
499
500
501
502
		/* Iterate through each option in the configuration request to look for ones which can be processed */
		uint8_t OptionPos = 0;
		while (OptionPos < OptionsLen)
		{
			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
509
510
			
			/* Store the remote MTU option's value if present */
			if (OptionHeader->Type == BT_CONFIG_OPTION_MTU)
			  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
518
519
520
521
522
	struct
	{
		BT_Signal_Header_t            SignalCommandHeader;
		BT_Signal_ConfigurationResp_t ConfigurationResponse;
	} ResponsePacket;

523
	/* Fill out the Signal Command header in the response packet */
524
525
526
	ResponsePacket.SignalCommandHeader.Code              = BT_SIGNAL_CONFIGURATION_RESPONSE;
	ResponsePacket.SignalCommandHeader.Identifier        = SignalCommandHeader->Identifier;
	ResponsePacket.SignalCommandHeader.Length            = sizeof(ResponsePacket.ConfigurationResponse);
527
528

	/* Fill out the Configuration Response in the response packet */
529
530
531
532
533
	ResponsePacket.ConfigurationResponse.SourceChannel   = ChannelData->RemoteNumber;
	ResponsePacket.ConfigurationResponse.Flags           = 0x00;
	ResponsePacket.ConfigurationResponse.Result          = (ChannelData != NULL) ? BT_CONFIGURATION_SUCCESSFUL : BT_CONFIGURATION_REJECTED;

	Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
534
535

	if (ChannelData != NULL)
536
537
538
539
540
541
542
543
544
545
546
547
548
549
	{
		switch (ChannelData->State)
		{
			case Channel_Config_WaitConfig:
				ChannelData->State = Channel_Config_WaitSendConfig;
				break;
			case Channel_Config_WaitReqResp:
				ChannelData->State = Channel_Config_WaitResp;
				break;
			case Channel_Config_WaitReq:
				ChannelData->State = Channel_Open;
				break;
		}
	}
550

551
	BT_ACL_DEBUG(1, ">> L2CAP Configuration Response");
552
553
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.ConfigurationResponse.SourceChannel);
	BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.ConfigurationResponse.Result);
554
}
555

556
557
/** Internal Bluetooth stack Signal Command processing routine for a Configuration Response command.
 *
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
563
564
565
566
567
568
{
	BT_Signal_ConfigurationResp_t ConfigurationResponse;

	Pipe_Read_Stream_LE(&ConfigurationResponse, sizeof(ConfigurationResponse));

	Pipe_ClearIN();
	Pipe_Freeze();
	
569
	BT_ACL_DEBUG(1, "<< L2CAP Configuration Response");
570
571
572
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConfigurationResponse.SourceChannel);
	BT_ACL_DEBUG(2, "-- Result: 0x%02X", ConfigurationResponse.Result);

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
577
	
	/* Only update the channel's state if it was found in the channel list */
	if (ChannelData != NULL)
578
	{
579
580
		/* Check if the channel configuration completed successfuly */
		if (ConfigurationResponse.Result == BT_CONFIGURATION_SUCCESSFUL)
581
582
583
584
585
586
587
588
589
		{
			switch (ChannelData->State)
			{
				case Channel_Config_WaitReqResp:
					ChannelData->State = Channel_Config_WaitReq;
					break;
				case Channel_Config_WaitResp:
					ChannelData->State = Channel_Open;
					break;
590
591
592
593
594
595
596
			}	
		}
		else
		{
			/* Configuration failed - close the channel */
			ChannelData->State = Channel_Closed;
		}
597
598
599
	}
}

600
601
/** Internal Bluetooth stack Signal Command processing routine for a Disconnection Request command.
 *
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
609
	
	Pipe_Read_Stream_LE(&DisconnectionRequest, sizeof(DisconnectionRequest));

610
	BT_ACL_DEBUG(1, "<< L2CAP Disconnection Request");
611
612
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionRequest.DestinationChannel);
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionRequest.SourceChannel);
613
614
615
616
	
	Pipe_ClearIN();
	Pipe_Freeze();
	
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
621
622
623
624
625
	struct
	{
		BT_Signal_Header_t            SignalCommandHeader;
		BT_Signal_DisconnectionResp_t DisconnectionResponse;
	} ResponsePacket;

626
	/* Fill out the Signal Command header in the response packet */
627
628
629
	ResponsePacket.SignalCommandHeader.Code                 = BT_SIGNAL_DISCONNECTION_RESPONSE;
	ResponsePacket.SignalCommandHeader.Identifier           = SignalCommandHeader->Identifier;
	ResponsePacket.SignalCommandHeader.Length               = sizeof(ResponsePacket.DisconnectionResponse);
630
631

	/* Fill out the Disconnection Response in the response packet */
632
633
	ResponsePacket.DisconnectionResponse.DestinationChannel = ChannelData->RemoteNumber;
	ResponsePacket.DisconnectionResponse.SourceChannel      = ChannelData->LocalNumber;
634
635
636

	Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);

637
	/* If the channel was found in the channel list, close it */
638
639
640
	if (ChannelData != NULL)
	  ChannelData->State = Channel_Closed;

641
	BT_ACL_DEBUG(1, ">> L2CAP Disconnection Response");
642
643
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket.DisconnectionResponse.SourceChannel);
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket.DisconnectionResponse.DestinationChannel);
644
645
}

646
647
/** Internal Bluetooth stack Signal Command processing routine for a Disconnection Response command.
 *
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
653
654
655
{
	BT_Signal_DisconnectionResp_t DisconnectionResponse;
	
	Pipe_Read_Stream_LE(&DisconnectionResponse, sizeof(DisconnectionResponse));

656
	BT_ACL_DEBUG(1, "<< L2CAP Disconnection Response");
657
658
659
660
661
662
	BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionResponse.DestinationChannel);
	BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionResponse.SourceChannel);
	
	Pipe_ClearIN();
	Pipe_Freeze();
	
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
667
	/* If the channel was found in the channel list, close it */	
	if (ChannelData != NULL)
668
669
670
	  ChannelData->State = Channel_Closed;
}

671
672
/** Internal Bluetooth stack Signal Command processing routine for an Echo Request command.
 *
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
680
681
	
	Pipe_ClearIN();
	Pipe_Freeze();
	
682
683
684
685
686
	struct
	{
		BT_Signal_Header_t SignalCommandHeader;
	} ResponsePacket;

687
	/* Fill out the Signal Command header in the response packet */
688
689
690
	ResponsePacket.SignalCommandHeader.Code                 = BT_SIGNAL_ECHO_RESPONSE;
	ResponsePacket.SignalCommandHeader.Identifier           = SignalCommandHeader->Identifier;
	ResponsePacket.SignalCommandHeader.Length               = 0;
691
	
692
693
	Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);

694
	BT_ACL_DEBUG(1, ">> L2CAP Echo Response");
695
696
}

697
698
/** Internal Bluetooth stack Signal Command processing routine for an Information Request command.
 *
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
706

	Pipe_Read_Stream_LE(&InformationRequest, sizeof(InformationRequest));

707
	BT_ACL_DEBUG(1, "<< L2CAP Information Request");
708
	BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest.InfoType);
709
710
711
712
	
	Pipe_ClearIN();
	Pipe_Freeze();

713
714
	struct
	{
715
		BT_Signal_Header_t          SignalCommandHeader;
716
717
718
719
720
721
722
		BT_Signal_InformationResp_t InformationResponse;
		
		uint8_t Data[4];
	} ResponsePacket;
	
	uint8_t DataLen = 0;
	
723
	/* Retrieve the requested information and store it in the outgoing packet, if found */
724
725
726
	switch (InformationRequest.InfoType)
	{
		case BT_INFOREQ_MTU:		
727
728
			ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
			DataLen = 2;
729
			
730
			*((uint16_t*)&ResponsePacket.Data) = MAXIMUM_CHANNEL_MTU;
731
732
			break;
		case BT_INFOREQ_EXTENDEDFEATURES:
733
734
			ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
			DataLen = 4;
735
			
736
			*((uint32_t*)&ResponsePacket.Data) = 0;
737
738
			break;
		default:
739
740
			ResponsePacket.InformationResponse.Result = BT_INFORMATION_NOTSUPPORTED;
			DataLen = 0;
741
742
743
			break;
	}
	
744
	/* Fill out the Signal Command header in the response packet */
745
746
747
748
	ResponsePacket.SignalCommandHeader.Code                 = BT_SIGNAL_INFORMATION_RESPONSE;
	ResponsePacket.SignalCommandHeader.Identifier           = SignalCommandHeader->Identifier;
	ResponsePacket.SignalCommandHeader.Length               = sizeof(ResponsePacket.InformationResponse) + DataLen;

749
750
751
	/* Fill out the Information Response in the response packet */
	ResponsePacket.InformationResponse.InfoType = InformationRequest.InfoType;
	
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
}