Changed stream wait timeout counter to be 16-bit, so that very long timeout periods...
[pub/USBasp.git] / Demos / BluetoothHost / BluetoothHCICommands.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 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 #include "BluetoothHCICommands.h"
32
33 static Bluetooth_HCICommand_Header_t HCICommandHeader;
34 static Bluetooth_HCIEvent_Header_t HCIEventHeader;
35
36 uint8_t Bluetooth_HCIProcessingState;
37 static uint8_t Bluetooth_TempDeviceAddress[6];
38
39 static uint8_t Bluetooth_SendHCICommand(void* Parameters, uint8_t ParamLength)
40 {
41 uint8_t CommandBuffer[sizeof(HCICommandHeader) + HCICommandHeader.ParameterLength];
42
43 USB_HostRequest = (USB_Host_Request_Header_t)
44 {
45 bmRequestType: (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_DEVICE),
46 bRequest: 0,
47 wValue: 0,
48 wIndex: 0,
49 wLength: sizeof(CommandBuffer)
50 };
51
52 memset(CommandBuffer, 0x00, sizeof(CommandBuffer));
53 memcpy(CommandBuffer, &HCICommandHeader, sizeof(HCICommandHeader));
54
55 if (ParamLength)
56 memcpy(&CommandBuffer[sizeof(HCICommandHeader)], Parameters, ParamLength);
57
58 return USB_Host_SendControlRequest(CommandBuffer);
59 }
60
61 static bool Bluetooth_GetNextHCIEventHeader(void)
62 {
63 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);
64 Pipe_Unfreeze();
65
66 if (!(Pipe_ReadWriteAllowed()))
67 return false;
68
69 Pipe_Read_Stream_LE(&HCIEventHeader, sizeof(HCIEventHeader));
70
71 return true;
72 }
73
74 static void Bluetooth_DiscardRemainingHCIEventParameters(void)
75 {
76 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);
77 Pipe_Discard_Stream(HCIEventHeader.ParameterLength);
78 Pipe_ClearCurrentBank();
79 }
80
81 void Bluetooth_ProcessHCICommands(void)
82 {
83 uint8_t ErrorCode;
84
85 switch (Bluetooth_HCIProcessingState)
86 {
87 case Bluetooth_Init:
88 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);
89 Pipe_SetInfiniteINRequests();
90
91 memset(&Bluetooth_Connection, 0x00, sizeof(Bluetooth_Connection));
92
93 Bluetooth_HCIProcessingState = Bluetooth_Init_Reset;
94 break;
95 case Bluetooth_Init_Reset:
96 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
97 {
98 OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_RESET},
99 ParameterLength: 0,
100 };
101
102 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_Reset", NULL);
103
104 ErrorCode = Bluetooth_SendHCICommand(NULL, 0);
105
106 do
107 {
108 while (!(Bluetooth_GetNextHCIEventHeader()));
109 Bluetooth_DiscardRemainingHCIEventParameters();
110 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
111
112 Bluetooth_HCIProcessingState = Bluetooth_Init_ReadBufferSize;
113 break;
114 case Bluetooth_Init_ReadBufferSize:
115 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
116 {
117 OpCode: {OGF: OGF_CTRLR_INFORMATIONAL, OCF: OGF_CTRLR_INFORMATIONAL_READBUFFERSIZE},
118 ParameterLength: 0,
119 };
120
121 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_ReadBufferSize", NULL);
122
123 ErrorCode = Bluetooth_SendHCICommand(NULL, 0);
124
125 do
126 {
127 while (!(Bluetooth_GetNextHCIEventHeader()));
128 Bluetooth_DiscardRemainingHCIEventParameters();
129 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
130
131 Bluetooth_HCIProcessingState = Bluetooth_Init_SetEventMask;
132 break;
133 case Bluetooth_Init_SetEventMask:
134 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
135 {
136 OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_SET_EVENT_MASK},
137 ParameterLength: 8,
138 };
139
140 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetEventMask", NULL);
141
142 uint8_t EventMask[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
143 ErrorCode = Bluetooth_SendHCICommand(&EventMask, 8);
144
145 BT_DEBUG("(HCI) -- Event mask: 0x%02X%02X%02X%02X%02X%02X%02X%02X", EventMask[7], EventMask[6], EventMask[5], EventMask[4],
146 EventMask[3], EventMask[2], EventMask[1], EventMask[0]);
147 do
148 {
149 while (!(Bluetooth_GetNextHCIEventHeader()));
150 Bluetooth_DiscardRemainingHCIEventParameters();
151 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
152
153
154 Bluetooth_HCIProcessingState = Bluetooth_Init_SetLocalName;
155 break;
156 case Bluetooth_Init_SetLocalName:
157 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
158 {
159 OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME},
160 ParameterLength: 248,
161 };
162
163 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetLocalName", NULL);
164 BT_DEBUG("(HCI) -- Name: %s", Bluetooth_DeviceConfiguration.Name);
165
166 ErrorCode = Bluetooth_SendHCICommand(Bluetooth_DeviceConfiguration.Name, strlen(Bluetooth_DeviceConfiguration.Name));
167
168 do
169 {
170 while (!(Bluetooth_GetNextHCIEventHeader()));
171 Bluetooth_DiscardRemainingHCIEventParameters();
172 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
173
174 Bluetooth_HCIProcessingState = Bluetooth_Init_SetDeviceClass;
175 break;
176 case Bluetooth_Init_SetDeviceClass:
177 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
178 {
179 OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE},
180 ParameterLength: 3,
181 };
182
183 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetDeviceClass", NULL);
184
185 ErrorCode = Bluetooth_SendHCICommand(&Bluetooth_DeviceConfiguration.Class, 3);
186
187 do
188 {
189 while (!(Bluetooth_GetNextHCIEventHeader()));
190 Bluetooth_DiscardRemainingHCIEventParameters();
191 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
192
193 Bluetooth_HCIProcessingState = Bluetooth_Init_WriteScanEnable;
194 break;
195 case Bluetooth_Init_WriteScanEnable:
196 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
197 {
198 OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE},
199 ParameterLength: 1,
200 };
201
202 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_WriteScanEnable", NULL);
203
204 uint8_t Interval = InquiryAndPageScans;
205 ErrorCode = Bluetooth_SendHCICommand(&Interval, 1);
206
207 do
208 {
209 while (!(Bluetooth_GetNextHCIEventHeader()));
210 Bluetooth_DiscardRemainingHCIEventParameters();
211 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
212
213 Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents;
214 break;
215 case Bluetooth_PrepareToProcessEvents:
216 BT_DEBUG("(HCI) Enter State: Bluetooth_ProcessEvents", NULL);
217
218 Bluetooth_HCIProcessingState = Bluetooth_ProcessEvents;
219 break;
220 case Bluetooth_ProcessEvents:
221 if (Bluetooth_GetNextHCIEventHeader())
222 {
223 BT_DEBUG("(HCI) Event Code: 0x%02X", HCIEventHeader.EventCode);
224
225 if (HCIEventHeader.EventCode == EVENT_COMMAND_STATUS)
226 {
227 Bluetooth_HCIEvent_CommandStatus_Header_t CommandStatusHeader;
228
229 Pipe_Read_Stream_LE(&CommandStatusHeader, sizeof(CommandStatusHeader));
230 HCIEventHeader.ParameterLength -= sizeof(CommandStatusHeader);
231
232 BT_DEBUG("(HCI) >> Command status: 0x%02X", CommandStatusHeader.CommandStatus);
233
234 if (CommandStatusHeader.CommandStatus)
235 Bluetooth_HCIProcessingState = Bluetooth_Init;
236 }
237 else if (HCIEventHeader.EventCode == EVENT_CONNECTION_REQUEST)
238 {
239 Bluetooth_HCIEvent_ConnectionRequest_Header_t ConnectionRequestParams;
240
241 Pipe_Read_Stream_LE(&ConnectionRequestParams, sizeof(ConnectionRequestParams));
242 HCIEventHeader.ParameterLength -= sizeof(ConnectionRequestParams);
243
244 BT_DEBUG("(HCI) >> Connection Request from device %02X:%02X:%02X:%02X:%02X:%02X",
245 ConnectionRequestParams.RemoteAddress[5], ConnectionRequestParams.RemoteAddress[4],
246 ConnectionRequestParams.RemoteAddress[3], ConnectionRequestParams.RemoteAddress[2],
247 ConnectionRequestParams.RemoteAddress[1], ConnectionRequestParams.RemoteAddress[0]);
248 BT_DEBUG("(HCI) -- Device Class: 0x%02X%04X", ConnectionRequestParams.ClassOfDevice_Service,
249 ConnectionRequestParams.ClassOfDevice_MajorMinor);
250 BT_DEBUG("(HCI) -- Link Type: 0x%02x", ConnectionRequestParams.LinkType);
251
252 memcpy(Bluetooth_TempDeviceAddress, ConnectionRequestParams.RemoteAddress,
253 sizeof(Bluetooth_TempDeviceAddress));
254
255 Bluetooth_HCIProcessingState = (Bluetooth_Connection.IsConnected) ? Bluetooth_Conn_RejectConnection :
256 Bluetooth_Conn_AcceptConnection;
257 }
258 else if (HCIEventHeader.EventCode == EVENT_DISCONNECTION_COMPLETE)
259 {
260 BT_DEBUG("(HCI) >> Disconnection from device complete.", NULL);
261 Bluetooth_HCIProcessingState = Bluetooth_Init;
262 }
263 else if (HCIEventHeader.EventCode == EVENT_CONNECTION_COMPLETE)
264 {
265 Bluetooth_HCIEvent_ConnectionComplete_Header_t ConnectionCompleteParams;
266
267 Pipe_Read_Stream_LE(&ConnectionCompleteParams, sizeof(ConnectionCompleteParams));
268 HCIEventHeader.ParameterLength -= sizeof(ConnectionCompleteParams);
269
270 BT_DEBUG("(HCI) >> Connection to device complete.", NULL);
271 BT_DEBUG("(HCI) -- Status: %d", ConnectionCompleteParams.Status);
272 BT_DEBUG("(HCI) -- Handle: %d", ConnectionCompleteParams.ConnectionHandle);
273
274 if (ConnectionCompleteParams.Status == 0x00)
275 {
276 memcpy(Bluetooth_Connection.DeviceAddress, ConnectionCompleteParams.RemoteAddress,
277 sizeof(Bluetooth_Connection.DeviceAddress));
278 Bluetooth_Connection.ConnectionHandle = ConnectionCompleteParams.ConnectionHandle;
279 Bluetooth_Connection.IsConnected = true;
280 }
281 }
282 else if (HCIEventHeader.EventCode == EVENT_PIN_CODE_REQUEST)
283 {
284 Pipe_Read_Stream_LE(&Bluetooth_TempDeviceAddress, sizeof(Bluetooth_TempDeviceAddress));
285 HCIEventHeader.ParameterLength -= sizeof(Bluetooth_TempDeviceAddress);
286
287 BT_DEBUG("(HCI) >> PIN code Request from device %02X:%02X:%02X:%02X:%02X:%02X",
288 Bluetooth_TempDeviceAddress[5], Bluetooth_TempDeviceAddress[4], Bluetooth_TempDeviceAddress[3],
289 Bluetooth_TempDeviceAddress[2], Bluetooth_TempDeviceAddress[1], Bluetooth_TempDeviceAddress[0]);
290
291 Bluetooth_HCIProcessingState = Bluetooth_Conn_SendPINCode;
292 }
293
294 BT_DEBUG("(HCI) -- Unread Event Param Length: %d", HCIEventHeader.ParameterLength);
295
296 Bluetooth_DiscardRemainingHCIEventParameters();
297 }
298
299 break;
300 case Bluetooth_Conn_AcceptConnection:
301 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
302 {
303 OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST},
304 ParameterLength: sizeof(Bluetooth_HCICommand_AcceptConnectionRequest_Params_t),
305 };
306
307 BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_AcceptConnection", NULL);
308
309 Bluetooth_HCICommand_AcceptConnectionRequest_Params_t AcceptConnectionParams;
310
311 memcpy(AcceptConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress,
312 sizeof(Bluetooth_TempDeviceAddress));
313 AcceptConnectionParams.SlaveRole = true;
314
315 Bluetooth_SendHCICommand(&AcceptConnectionParams, sizeof(AcceptConnectionParams));
316
317 Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents;
318 break;
319 case Bluetooth_Conn_RejectConnection:
320 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
321 {
322 OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST},
323 ParameterLength: sizeof(Bluetooth_HCICommand_RejectConnectionRequest_Params_t),
324 };
325
326 BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_RejectConnection", NULL);
327
328 Bluetooth_HCICommand_RejectConnectionRequest_Params_t RejectConnectionParams;
329
330 memcpy(RejectConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress,
331 sizeof(Bluetooth_TempDeviceAddress));
332 RejectConnectionParams.Reason = ERROR_LIMITED_RESOURCES;
333
334 Bluetooth_SendHCICommand(&AcceptConnectionParams, sizeof(AcceptConnectionParams));
335
336 Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents;
337 break;
338 case Bluetooth_Conn_SendPINCode:
339 HCICommandHeader = (Bluetooth_HCICommand_Header_t)
340 {
341 OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY},
342 ParameterLength: sizeof(Bluetooth_HCICommand_PinCodeResponse_Params_t),
343 };
344
345 BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_SendPINCode", NULL);
346 BT_DEBUG("(HCI) -- PIN: %s", Bluetooth_DeviceConfiguration.PINCode);
347
348 Bluetooth_HCICommand_PinCodeResponse_Params_t PINCodeRequestParams;
349
350 memcpy(PINCodeRequestParams.RemoteAddress, Bluetooth_TempDeviceAddress,
351 sizeof(Bluetooth_TempDeviceAddress));
352 PINCodeRequestParams.PINCodeLength = strlen(Bluetooth_DeviceConfiguration.PINCode);
353 memcpy(PINCodeRequestParams.PINCode, Bluetooth_DeviceConfiguration.PINCode,
354 sizeof(Bluetooth_DeviceConfiguration.PINCode));
355
356 Bluetooth_SendHCICommand(&PINCodeRequestParams, sizeof(PINCodeRequestParams));
357
358 do
359 {
360 while (!(Bluetooth_GetNextHCIEventHeader()));
361 Bluetooth_DiscardRemainingHCIEventParameters();
362 } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);
363
364 Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents;
365 break;
366 }
367 }