Make Bluetooth signalling handler routines use the generic Bluetooth_SendPacket(...
[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 #define INCLUDE_FROM_BLUETOOTH_ACLPACKETS_C
32 #include "BluetoothACLPackets.h"
33
34 void Bluetooth_ACLTask(void)
35 {
36 Bluetooth_ProcessACLPackets();
37
38 for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)
39 {
40 Bluetooth_Channel_t* ChannelData = &Bluetooth_Connection.Channels[i];
41
42 bool MustSendConfigReq = true;
43
44 switch (ChannelData->State)
45 {
46 case Channel_Config_WaitConfig:
47 ChannelData->State = Channel_Config_WaitReqResp;
48 break;
49 case Channel_Config_WaitSendConfig:
50 ChannelData->State = Channel_Config_WaitResp;
51 break;
52 default:
53 MustSendConfigReq = false;
54 break;
55 }
56
57 if (MustSendConfigReq)
58 {
59 struct
60 {
61 BT_Signal_Header_t SignalCommandHeader;
62 BT_Signal_ConfigurationReq_t ConfigurationRequest;
63
64 struct
65 {
66 BT_Config_Option_Header_t Header;
67 uint16_t Value;
68 } Option_LocalMTU;
69 } PacketData;
70
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;
80
81 Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);
82
83 BT_ACL_DEBUG(1, ">> L2CAP Configuration Request", NULL);
84 BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData.ConfigurationRequest.DestinationChannel);
85 }
86 }
87 }
88
89 static void Bluetooth_ProcessACLPackets(void)
90 {
91 BT_ACL_Header_t ACLPacketHeader;
92 BT_DataPacket_Header_t DataHeader;
93
94 Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE);
95 Pipe_Unfreeze();
96
97 if (!(Pipe_IsReadWriteAllowed()))
98 {
99 Pipe_Freeze();
100 return;
101 }
102
103 Pipe_Read_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
104 Pipe_Read_Stream_LE(&DataHeader, sizeof(DataHeader));
105
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);
112
113 if (DataHeader.DestinationChannel == BT_CHANNEL_SIGNALING)
114 {
115 BT_Signal_Header_t SignalCommandHeader;
116 Pipe_Read_Stream_LE(&SignalCommandHeader, sizeof(SignalCommandHeader));
117
118 switch (SignalCommandHeader.Code)
119 {
120 case BT_SIGNAL_CONNECTION_REQUEST:
121 Bluetooth_Signal_ConnectionReq(&ACLPacketHeader, &DataHeader, &SignalCommandHeader);
122 break;
123 case BT_SIGNAL_CONFIGURATION_REQUEST:
124 Bluetooth_Signal_ConfigurationReq(&ACLPacketHeader, &DataHeader, &SignalCommandHeader);
125 break;
126 case BT_SIGNAL_DISCONNECTION_REQUEST:
127 Bluetooth_Signal_DisconnectionReq(&ACLPacketHeader, &DataHeader, &SignalCommandHeader);
128 break;
129 case BT_SIGNAL_ECHO_REQUEST:
130 Bluetooth_Signal_EchoReq(&ACLPacketHeader, &DataHeader, &SignalCommandHeader);
131 break;
132 case BT_SIGNAL_INFORMATION_REQUEST:
133 Bluetooth_Signal_InformationReq(&ACLPacketHeader, &DataHeader, &SignalCommandHeader);
134 break;
135 default:
136 BT_ACL_DEBUG(1, "<< Unknown Signaling Command 0x%02X", SignalCommandHeader.Code);
137
138 Pipe_Discard_Stream(ACLPacketHeader.DataLength);
139 Pipe_ClearIN();
140 Pipe_Freeze();
141 break;
142 }
143 }
144 else
145 {
146 Bluetooth_PacketReceived(&DataHeader.PayloadLength, Bluetooth_GetChannelData(DataHeader.DestinationChannel, true));
147
148 Pipe_SelectPipe(BLUETOOTH_DATA_IN_PIPE);
149 Pipe_Discard_Stream(DataHeader.PayloadLength);
150 Pipe_ClearIN();
151 Pipe_Freeze();
152 }
153 }
154
155 uint8_t Bluetooth_SendPacket(void* Data, uint16_t DataLen, Bluetooth_Channel_t* Channel)
156 {
157 BT_ACL_Header_t ACLPacketHeader;
158 BT_DataPacket_Header_t DataHeader;
159
160 if (!(Bluetooth_Connection.IsConnected))
161 return BT_SENDPACKET_NotConnected;
162
163 if ((Channel != NULL) && (Channel->State != Channel_Open))
164 return BT_SENDPACKET_ChannelNotOpen;
165
166 // TODO: Add packet fragmentation here after retrieving the device's signal channel MTU
167
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;
172
173 Pipe_SelectPipe(BLUETOOTH_DATA_OUT_PIPE);
174 Pipe_Unfreeze();
175
176 Pipe_Write_Stream_LE(&ACLPacketHeader, sizeof(ACLPacketHeader));
177 Pipe_Write_Stream_LE(&DataHeader, sizeof(DataHeader));
178 Pipe_Write_Stream_LE(Data, DataLen);
179
180 Pipe_Freeze();
181
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);
188
189 return BT_SENDPACKET_NoError;
190 }
191
192 static inline void Bluetooth_Signal_ConnectionReq(BT_ACL_Header_t* ACLPacketHeader,
193 BT_DataPacket_Header_t* DataHeader,
194 BT_Signal_Header_t* SignalCommandHeader)
195 {
196 BT_Signal_ConnectionReq_t ConnectionRequest;
197
198 Pipe_Read_Stream_LE(&ConnectionRequest, sizeof(ConnectionRequest));
199
200 Pipe_ClearIN();
201 Pipe_Freeze();
202
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);
206
207 Bluetooth_Channel_t* ChannelData = Bluetooth_InitChannelData(ConnectionRequest.SourceChannel, ConnectionRequest.PSM);
208
209 struct
210 {
211 BT_Signal_Header_t SignalCommandHeader;
212 BT_Signal_ConnectionResp_t ConnectionResponse;
213 } ResponsePacket;
214
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;
222
223 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
224
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);
229 }
230
231 static inline void Bluetooth_Signal_ConfigurationReq(BT_ACL_Header_t* ACLPacketHeader,
232 BT_DataPacket_Header_t* DataHeader,
233 BT_Signal_Header_t* SignalCommandHeader)
234 {
235 BT_Signal_ConfigurationReq_t ConfigurationRequest;
236 uint8_t OptionsLen;
237
238 Pipe_Read_Stream_LE(&ConfigurationRequest, sizeof(ConfigurationRequest));
239 OptionsLen = (DataHeader->PayloadLength - sizeof(*SignalCommandHeader));
240
241 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(ConfigurationRequest.DestinationChannel, false);
242
243 while (OptionsLen)
244 {
245 BT_Config_Option_Header_t OptionHeader;
246
247 Pipe_Read_Stream_LE(&OptionHeader, sizeof(OptionHeader));
248
249 if ((OptionHeader.Type == BT_CONFIG_OPTION_MTU) && (ChannelData != NULL))
250 Pipe_Read_Stream_LE(&ChannelData->RemoteMTU, sizeof(ChannelData->RemoteMTU));
251 else
252 Pipe_Discard_Stream(OptionHeader.Length);
253
254 OptionsLen -= (sizeof(OptionHeader) + OptionHeader.Length);
255 }
256
257 Pipe_ClearIN();
258 Pipe_Freeze();
259
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);
264
265 struct
266 {
267 BT_Signal_Header_t SignalCommandHeader;
268 BT_Signal_ConfigurationResp_t ConfigurationResponse;
269 } ResponsePacket;
270
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;
277
278 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
279
280 if (ChannelData != NULL)
281 {
282 switch (ChannelData->State)
283 {
284 case Channel_Config_WaitConfig:
285 ChannelData->State = Channel_Config_WaitSendConfig;
286 break;
287 case Channel_Config_WaitReqResp:
288 ChannelData->State = Channel_Config_WaitResp;
289 break;
290 case Channel_Config_WaitReq:
291 ChannelData->State = Channel_Open;
292 break;
293 }
294 }
295
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);
299 }
300
301 static inline void Bluetooth_Signal_DisconnectionReq(BT_ACL_Header_t* ACLPacketHeader,
302 BT_DataPacket_Header_t* DataHeader,
303 BT_Signal_Header_t* SignalCommandHeader)
304 {
305 BT_Signal_DisconnectionReq_t DisconnectionRequest;
306
307 Pipe_Read_Stream_LE(&DisconnectionRequest, sizeof(DisconnectionRequest));
308
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);
312
313 Pipe_ClearIN();
314 Pipe_Freeze();
315
316 Bluetooth_Channel_t* ChannelData = Bluetooth_GetChannelData(DisconnectionRequest.SourceChannel, true);
317
318 struct
319 {
320 BT_Signal_Header_t SignalCommandHeader;
321 BT_Signal_DisconnectionResp_t DisconnectionResponse;
322 } ResponsePacket;
323
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;
329
330 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
331
332 if (ChannelData != NULL)
333 ChannelData->State = Channel_Closed;
334
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);
338 }
339
340 static inline void Bluetooth_Signal_EchoReq(BT_ACL_Header_t* ACLPacketHeader,
341 BT_DataPacket_Header_t* DataHeader,
342 BT_Signal_Header_t* SignalCommandHeader)
343 {
344 BT_ACL_DEBUG(1, "<< L2CAP Echo Request", NULL);
345
346 Pipe_ClearIN();
347 Pipe_Freeze();
348
349 struct
350 {
351 BT_Signal_Header_t SignalCommandHeader;
352 } ResponsePacket;
353
354 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_ECHO_RESPONSE;
355 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
356 ResponsePacket.SignalCommandHeader.Length = 0;
357
358 Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), NULL);
359
360 BT_ACL_DEBUG(1, ">> L2CAP Echo Response", NULL);
361 }
362
363 static inline void Bluetooth_Signal_InformationReq(BT_ACL_Header_t* ACLPacketHeader,
364 BT_DataPacket_Header_t* DataHeader,
365 BT_Signal_Header_t* SignalCommandHeader)
366 {
367 BT_Signal_InformationReq_t InformationRequest;
368
369 Pipe_Read_Stream_LE(&InformationRequest, sizeof(InformationRequest));
370
371 BT_ACL_DEBUG(1, "<< L2CAP Information Request", NULL);
372 BT_ACL_DEBUG(2, "-- Info Type: 0x%04X", InformationRequest.InfoType);
373
374 Pipe_ClearIN();
375 Pipe_Freeze();
376
377 struct
378 {
379 BT_Signal_Header_t SignalCommandHeader;
380 BT_Signal_InformationResp_t InformationResponse;
381
382 uint8_t Data[4];
383 } ResponsePacket;
384
385 uint8_t DataLen = 0;
386
387 switch (InformationRequest.InfoType)
388 {
389 case BT_INFOREQ_MTU:
390 ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
391 DataLen = 2;
392
393 *((uint16_t*)&ResponsePacket.Data) = MAXIMUM_CHANNEL_MTU;
394 break;
395 case BT_INFOREQ_EXTENDEDFEATURES:
396 ResponsePacket.InformationResponse.Result = BT_INFORMATION_SUCCESSFUL;
397 DataLen = 4;
398
399 *((uint32_t*)&ResponsePacket.Data) = 0;
400 break;
401 default:
402 ResponsePacket.InformationResponse.Result = BT_INFORMATION_NOTSUPPORTED;
403 DataLen = 0;
404 break;
405 }
406
407 ResponsePacket.SignalCommandHeader.Code = BT_SIGNAL_INFORMATION_RESPONSE;
408 ResponsePacket.SignalCommandHeader.Identifier = SignalCommandHeader->Identifier;
409 ResponsePacket.SignalCommandHeader.Length = sizeof(ResponsePacket.InformationResponse) + DataLen;
410
411 Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket) - sizeof(ResponsePacket.Data) + DataLen), NULL);
412
413 BT_ACL_DEBUG(1, ">> L2CAP Information Response", NULL);
414 BT_ACL_DEBUG(2, "-- Result: 0x%02X", ResponsePacket.InformationResponse.Result);
415 }