3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
31 #define INCLUDE_FROM_BLUETOOTH_ACLPACKETS_C
32 #include "BluetoothACLPackets.h"
34 void Bluetooth_ACLTask(void)
36 Bluetooth_ProcessACLPackets();
38 for (uint8_t i
= 0; i
< BLUETOOTH_MAX_OPEN_CHANNELS
; i
++)
40 Bluetooth_Channel_t
* ChannelData
= &Bluetooth_Connection
.Channels
[i
];
42 bool MustSendConfigReq
= true;
44 switch (ChannelData
->State
)
46 case Channel_Config_WaitConfig
:
47 ChannelData
->State
= Channel_Config_WaitReqResp
;
49 case Channel_Config_WaitSendConfig
:
50 ChannelData
->State
= Channel_Config_WaitResp
;
53 MustSendConfigReq
= false;
57 if (MustSendConfigReq
)
61 BT_Signal_Header_t SignalCommandHeader
;
62 BT_Signal_ConfigurationReq_t ConfigurationRequest
;
66 BT_Config_Option_Header_t Header
;
71 PacketData
.SignalCommandHeader
.Code
= BT_SIGNAL_CONFIGURATION_REQUEST
;
72 PacketData
.SignalCommandHeader
.Identifier
= ++Bluetooth_Connection
.SignallingIdentifier
;
73 PacketData
.SignalCommandHeader
.Length
= sizeof(PacketData
.ConfigurationRequest
) +
74 sizeof(PacketData
.Option_LocalMTU
);
75 PacketData
.ConfigurationRequest
.DestinationChannel
= ChannelData
->RemoteNumber
;
76 PacketData
.ConfigurationRequest
.Flags
= 0;
77 PacketData
.Option_LocalMTU
.Header
.Type
= BT_CONFIG_OPTION_MTU
;
78 PacketData
.Option_LocalMTU
.Header
.Length
= sizeof(PacketData
.Option_LocalMTU
.Value
);
79 PacketData
.Option_LocalMTU
.Value
= ChannelData
->LocalMTU
;
81 Bluetooth_SendPacket(&PacketData
, sizeof(PacketData
), NULL
);
83 BT_ACL_DEBUG(1, ">> L2CAP Configuration Request", NULL
);
84 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData
.ConfigurationRequest
.DestinationChannel
);
89 static void Bluetooth_ProcessACLPackets(void)
91 BT_ACL_Header_t ACLPacketHeader
;
92 BT_DataPacket_Header_t DataHeader
;
94 Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE
);
97 if (!(Pipe_IsReadWriteAllowed()))
103 Pipe_Read_Stream_LE(&ACLPacketHeader
, sizeof(ACLPacketHeader
));
104 Pipe_Read_Stream_LE(&DataHeader
, sizeof(DataHeader
));
106 BT_ACL_DEBUG(2, "", NULL
);
107 BT_ACL_DEBUG(2, "Packet Received", NULL
);
108 BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader
.ConnectionHandle
& 0x0FFF));
109 BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader
.DataLength
);
110 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader
.DestinationChannel
);
111 BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader
.PayloadLength
);
113 if (DataHeader
.DestinationChannel
== BT_CHANNEL_SIGNALING
)
115 BT_Signal_Header_t SignalCommandHeader
;
116 Pipe_Read_Stream_LE(&SignalCommandHeader
, sizeof(SignalCommandHeader
));
118 switch (SignalCommandHeader
.Code
)
120 case BT_SIGNAL_CONNECTION_REQUEST
:
121 Bluetooth_Signal_ConnectionReq(&ACLPacketHeader
, &DataHeader
, &SignalCommandHeader
);
123 case BT_SIGNAL_CONFIGURATION_REQUEST
:
124 Bluetooth_Signal_ConfigurationReq(&ACLPacketHeader
, &DataHeader
, &SignalCommandHeader
);
126 case BT_SIGNAL_DISCONNECTION_REQUEST
:
127 Bluetooth_Signal_DisconnectionReq(&ACLPacketHeader
, &DataHeader
, &SignalCommandHeader
);
129 case BT_SIGNAL_ECHO_REQUEST
:
130 Bluetooth_Signal_EchoReq(&ACLPacketHeader
, &DataHeader
, &SignalCommandHeader
);
132 case BT_SIGNAL_INFORMATION_REQUEST
:
133 Bluetooth_Signal_InformationReq(&ACLPacketHeader
, &DataHeader
, &SignalCommandHeader
);
136 BT_ACL_DEBUG(1, "<< Unknown Signaling Command 0x%02X", SignalCommandHeader
.Code
);
138 Pipe_Discard_Stream(ACLPacketHeader
.DataLength
);
146 Bluetooth_PacketReceived(&DataHeader
.PayloadLength
, Bluetooth_GetChannelData(DataHeader
.DestinationChannel
, true));
148 Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE
);
149 Pipe_Discard_Stream(DataHeader
.PayloadLength
);
155 uint8_t Bluetooth_SendPacket(void* Data
, uint16_t DataLen
, Bluetooth_Channel_t
* Channel
)
157 BT_ACL_Header_t ACLPacketHeader
;
158 BT_DataPacket_Header_t DataHeader
;
160 if (!(Bluetooth_Connection
.IsConnected
))
161 return BT_SENDPACKET_NotConnected
;
163 if ((Channel
!= NULL
) && (Channel
->State
!= Channel_Open
))
164 return BT_SENDPACKET_ChannelNotOpen
;
166 // TODO: Add packet fragmentation here after retrieving the device's signal channel MTU
168 ACLPacketHeader
.ConnectionHandle
= Bluetooth_Connection
.ConnectionHandle
| (1 << 13);
169 ACLPacketHeader
.DataLength
= sizeof(DataHeader
) + DataLen
;
170 DataHeader
.PayloadLength
= DataLen
;
171 DataHeader
.DestinationChannel
= (Channel
== NULL
) ? BT_CHANNEL_SIGNALING
: Channel
->RemoteNumber
;
173 Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE
);
176 Pipe_Write_Stream_LE(&ACLPacketHeader
, sizeof(ACLPacketHeader
));
177 Pipe_Write_Stream_LE(&DataHeader
, sizeof(DataHeader
));
178 Pipe_Write_Stream_LE(Data
, DataLen
);
182 BT_ACL_DEBUG(2, "", NULL
);
183 BT_ACL_DEBUG(2, "Packet Sent", NULL
);
184 BT_ACL_DEBUG(2, "-- Connection Handle: 0x%04X", (ACLPacketHeader
.ConnectionHandle
& 0x0FFF));
185 BT_ACL_DEBUG(2, "-- Data Length: 0x%04X", ACLPacketHeader
.DataLength
);
186 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DataHeader
.DestinationChannel
);
187 BT_ACL_DEBUG(2, "-- Payload Length: 0x%04X", DataHeader
.PayloadLength
);
189 return BT_SENDPACKET_NoError
;
192 static inline void Bluetooth_Signal_ConnectionReq(BT_ACL_Header_t
* ACLPacketHeader
,
193 BT_DataPacket_Header_t
* DataHeader
,
194 BT_Signal_Header_t
* SignalCommandHeader
)
196 BT_Signal_ConnectionReq_t ConnectionRequest
;
198 Pipe_Read_Stream_LE(&ConnectionRequest
, sizeof(ConnectionRequest
));
203 BT_ACL_DEBUG(1, "<< L2CAP Connection Request", NULL
);
204 BT_ACL_DEBUG(2, "-- PSM: 0x%04X", ConnectionRequest
.PSM
);
205 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ConnectionRequest
.SourceChannel
);
207 Bluetooth_Channel_t
* ChannelData
= Bluetooth_InitChannelData(ConnectionRequest
.SourceChannel
, ConnectionRequest
.PSM
);
211 BT_Signal_Header_t SignalCommandHeader
;
212 BT_Signal_ConnectionResp_t ConnectionResponse
;
215 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_CONNECTION_RESPONSE
;
216 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
217 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.ConnectionResponse
);
218 ResponsePacket
.ConnectionResponse
.Result
= (ChannelData
== NULL
) ? BT_CONNECTION_REFUSED_RESOURCES
: BT_CONNECTION_SUCCESSFUL
;
219 ResponsePacket
.ConnectionResponse
.DestinationChannel
= ChannelData
->LocalNumber
;
220 ResponsePacket
.ConnectionResponse
.SourceChannel
= ChannelData
->RemoteNumber
;
221 ResponsePacket
.ConnectionResponse
.Status
= 0x00;
223 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
225 BT_ACL_DEBUG(1, ">> L2CAP Connection Response", NULL
);
226 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.ConnectionResponse
.Result
);
227 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket
.ConnectionResponse
.SourceChannel
);
228 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket
.ConnectionResponse
.DestinationChannel
);
231 static inline void Bluetooth_Signal_ConfigurationReq(BT_ACL_Header_t
* ACLPacketHeader
,
232 BT_DataPacket_Header_t
* DataHeader
,
233 BT_Signal_Header_t
* SignalCommandHeader
)
235 BT_Signal_ConfigurationReq_t ConfigurationRequest
;
238 Pipe_Read_Stream_LE(&ConfigurationRequest
, sizeof(ConfigurationRequest
));
239 OptionsLen
= (DataHeader
->PayloadLength
- sizeof(*SignalCommandHeader
));
241 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(ConfigurationRequest
.DestinationChannel
, false);
245 BT_Config_Option_Header_t OptionHeader
;
247 Pipe_Read_Stream_LE(&OptionHeader
, sizeof(OptionHeader
));
249 if ((OptionHeader
.Type
== BT_CONFIG_OPTION_MTU
) && (ChannelData
!= NULL
))
250 Pipe_Read_Stream_LE(&ChannelData
->RemoteMTU
, sizeof(ChannelData
->RemoteMTU
));
252 Pipe_Discard_Stream(OptionHeader
.Length
);
254 OptionsLen
-= (sizeof(OptionHeader
) + OptionHeader
.Length
);
260 BT_ACL_DEBUG(1, "<< L2CAP Configuration Request", NULL
);
261 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ConfigurationRequest
.DestinationChannel
);
262 BT_ACL_DEBUG(2, "-- Options Len: 0x%04X", ConfigurationRequest
.DestinationChannel
);
263 BT_ACL_DEBUG(2, "-- Remote MTU: 0x%04X", ChannelData
->RemoteMTU
);
267 BT_Signal_Header_t SignalCommandHeader
;
268 BT_Signal_ConfigurationResp_t ConfigurationResponse
;
271 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_CONFIGURATION_RESPONSE
;
272 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
273 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.ConfigurationResponse
);
274 ResponsePacket
.ConfigurationResponse
.SourceChannel
= ChannelData
->RemoteNumber
;
275 ResponsePacket
.ConfigurationResponse
.Flags
= 0x00;
276 ResponsePacket
.ConfigurationResponse
.Result
= (ChannelData
!= NULL
) ? BT_CONFIGURATION_SUCCESSFUL
: BT_CONFIGURATION_REJECTED
;
278 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
280 if (ChannelData
!= NULL
)
282 switch (ChannelData
->State
)
284 case Channel_Config_WaitConfig
:
285 ChannelData
->State
= Channel_Config_WaitSendConfig
;
287 case Channel_Config_WaitReqResp
:
288 ChannelData
->State
= Channel_Config_WaitResp
;
290 case Channel_Config_WaitReq
:
291 ChannelData
->State
= Channel_Open
;
296 BT_ACL_DEBUG(1, ">> L2CAP Configuration Response", NULL
);
297 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket
.ConfigurationResponse
.SourceChannel
);
298 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.ConfigurationResponse
.Result
);
301 static inline void Bluetooth_Signal_DisconnectionReq(BT_ACL_Header_t
* ACLPacketHeader
,
302 BT_DataPacket_Header_t
* DataHeader
,
303 BT_Signal_Header_t
* SignalCommandHeader
)
305 BT_Signal_DisconnectionReq_t DisconnectionRequest
;
307 Pipe_Read_Stream_LE(&DisconnectionRequest
, sizeof(DisconnectionRequest
));
309 BT_ACL_DEBUG(1, "<< L2CAP Disconnection Request", NULL
);
310 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", DisconnectionRequest
.DestinationChannel
);
311 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", DisconnectionRequest
.SourceChannel
);
316 Bluetooth_Channel_t
* ChannelData
= Bluetooth_GetChannelData(DisconnectionRequest
.SourceChannel
, true);
320 BT_Signal_Header_t SignalCommandHeader
;
321 BT_Signal_DisconnectionResp_t DisconnectionResponse
;
324 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_DISCONNECTION_RESPONSE
;
325 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
326 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.DisconnectionResponse
);
327 ResponsePacket
.DisconnectionResponse
.DestinationChannel
= ChannelData
->LocalNumber
;
328 ResponsePacket
.DisconnectionResponse
.SourceChannel
= ChannelData
->RemoteNumber
;
330 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
332 if (ChannelData
!= NULL
)
333 ChannelData
->State
= Channel_Closed
;
335 BT_ACL_DEBUG(1, ">> L2CAP Disconnection Response", NULL
);
336 BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", ResponsePacket
.DisconnectionResponse
.SourceChannel
);
337 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", ResponsePacket
.DisconnectionResponse
.DestinationChannel
);
340 static inline void Bluetooth_Signal_EchoReq(BT_ACL_Header_t
* ACLPacketHeader
,
341 BT_DataPacket_Header_t
* DataHeader
,
342 BT_Signal_Header_t
* SignalCommandHeader
)
344 BT_ACL_DEBUG(1, "<< L2CAP Echo Request", NULL
);
351 BT_Signal_Header_t SignalCommandHeader
;
354 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_ECHO_RESPONSE
;
355 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
356 ResponsePacket
.SignalCommandHeader
.Length
= 0;
358 Bluetooth_SendPacket(&ResponsePacket
, sizeof(ResponsePacket
), NULL
);
360 BT_ACL_DEBUG(1, ">> L2CAP Echo Response", NULL
);
363 static inline void Bluetooth_Signal_InformationReq(BT_ACL_Header_t
* ACLPacketHeader
,
364 BT_DataPacket_Header_t
* DataHeader
,
365 BT_Signal_Header_t
* SignalCommandHeader
)
367 BT_Signal_InformationReq_t InformationRequest
;
369 Pipe_Read_Stream_LE(&InformationRequest
, sizeof(InformationRequest
));
371 BT_ACL_DEBUG(1, "<< L2CAP Information Request", NULL
);
372 BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest
.InfoType
);
379 BT_Signal_Header_t SignalCommandHeader
;
380 BT_Signal_InformationResp_t InformationResponse
;
387 switch (InformationRequest
.InfoType
)
390 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_SUCCESSFUL
;
393 *((uint16_t*)&ResponsePacket
.Data
) = MAXIMUM_CHANNEL_MTU
;
395 case BT_INFOREQ_EXTENDEDFEATURES
:
396 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_SUCCESSFUL
;
399 *((uint32_t*)&ResponsePacket
.Data
) = 0;
402 ResponsePacket
.InformationResponse
.Result
= BT_INFORMATION_NOTSUPPORTED
;
407 ResponsePacket
.SignalCommandHeader
.Code
= BT_SIGNAL_INFORMATION_RESPONSE
;
408 ResponsePacket
.SignalCommandHeader
.Identifier
= SignalCommandHeader
->Identifier
;
409 ResponsePacket
.SignalCommandHeader
.Length
= sizeof(ResponsePacket
.InformationResponse
) + DataLen
;
411 Bluetooth_SendPacket(&ResponsePacket
, (sizeof(ResponsePacket
) - sizeof(ResponsePacket
.Data
) + DataLen
), NULL
);
413 BT_ACL_DEBUG(1, ">> L2CAP Information Response", NULL
);
414 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket
.InformationResponse
.Result
);