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 #include "BluetoothHCICommands.h"
33 static Bluetooth_HCICommand_Header_t HCICommandHeader
;
34 static Bluetooth_HCIEvent_Header_t HCIEventHeader
;
36 uint8_t Bluetooth_HCIProcessingState
;
37 static uint8_t Bluetooth_TempDeviceAddress
[6];
39 static uint8_t Bluetooth_SendHCICommand(void* Parameters
, uint8_t ParamLength
)
41 uint8_t CommandBuffer
[sizeof(HCICommandHeader
) + HCICommandHeader
.ParameterLength
];
43 USB_ControlRequest
= (USB_Request_Header_t
)
45 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_DEVICE
),
49 .wLength
= sizeof(CommandBuffer
)
52 memset(CommandBuffer
, 0x00, sizeof(CommandBuffer
));
53 memcpy(CommandBuffer
, &HCICommandHeader
, sizeof(HCICommandHeader
));
56 memcpy(&CommandBuffer
[sizeof(HCICommandHeader
)], Parameters
, ParamLength
);
58 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
60 return USB_Host_SendControlRequest(CommandBuffer
);
63 static bool Bluetooth_GetNextHCIEventHeader(void)
65 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE
);
68 if (!(Pipe_IsReadWriteAllowed()))
74 Pipe_Read_Stream_LE(&HCIEventHeader
, sizeof(HCIEventHeader
));
80 static void Bluetooth_DiscardRemainingHCIEventParameters(void)
82 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE
);
85 Pipe_Discard_Stream(HCIEventHeader
.ParameterLength
);
90 HCIEventHeader
.ParameterLength
= 0;
93 void Bluetooth_ProcessHCICommands(void)
97 switch (Bluetooth_HCIProcessingState
)
100 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE
);
102 memset(&Bluetooth_Connection
, 0x00, sizeof(Bluetooth_Connection
));
104 Bluetooth_HCIProcessingState
= Bluetooth_Init_Reset
;
106 case Bluetooth_Init_Reset
:
107 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
109 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_RESET
},
113 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_Reset", NULL
);
115 ErrorCode
= Bluetooth_SendHCICommand(NULL
, 0);
119 while (!(Bluetooth_GetNextHCIEventHeader()))
121 if (USB_HostState
== HOST_STATE_Unattached
)
125 Bluetooth_DiscardRemainingHCIEventParameters();
126 } while (HCIEventHeader
.EventCode
!= EVENT_COMMAND_COMPLETE
);
128 Bluetooth_HCIProcessingState
= Bluetooth_Init_ReadBufferSize
;
130 case Bluetooth_Init_ReadBufferSize
:
131 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
133 OpCode
: {OGF
: OGF_CTRLR_INFORMATIONAL
, OCF
: OGF_CTRLR_INFORMATIONAL_READBUFFERSIZE
},
137 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_ReadBufferSize", NULL
);
139 ErrorCode
= Bluetooth_SendHCICommand(NULL
, 0);
143 while (!(Bluetooth_GetNextHCIEventHeader()))
145 if (USB_HostState
== HOST_STATE_Unattached
)
149 Bluetooth_DiscardRemainingHCIEventParameters();
150 } while (HCIEventHeader
.EventCode
!= EVENT_COMMAND_COMPLETE
);
152 Bluetooth_HCIProcessingState
= Bluetooth_Init_SetEventMask
;
154 case Bluetooth_Init_SetEventMask
:
155 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
157 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_SET_EVENT_MASK
},
161 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetEventMask", NULL
);
163 uint8_t EventMask
[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
164 ErrorCode
= Bluetooth_SendHCICommand(&EventMask
, 8);
166 BT_DEBUG("(HCI) -- Event mask: 0x%02X%02X%02X%02X%02X%02X%02X%02X", EventMask
[7], EventMask
[6], EventMask
[5], EventMask
[4],
167 EventMask
[3], EventMask
[2], EventMask
[1], EventMask
[0]);
170 while (!(Bluetooth_GetNextHCIEventHeader()))
172 if (USB_HostState
== HOST_STATE_Unattached
)
176 Bluetooth_DiscardRemainingHCIEventParameters();
177 } while (HCIEventHeader
.EventCode
!= EVENT_COMMAND_COMPLETE
);
180 Bluetooth_HCIProcessingState
= Bluetooth_Init_SetLocalName
;
182 case Bluetooth_Init_SetLocalName
:
183 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
185 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME
},
186 ParameterLength
: 248,
189 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetLocalName", NULL
);
190 BT_DEBUG("(HCI) -- Name: %s", Bluetooth_DeviceConfiguration
.Name
);
192 ErrorCode
= Bluetooth_SendHCICommand(Bluetooth_DeviceConfiguration
.Name
, strlen(Bluetooth_DeviceConfiguration
.Name
));
196 while (!(Bluetooth_GetNextHCIEventHeader()))
198 if (USB_HostState
== HOST_STATE_Unattached
)
202 Bluetooth_DiscardRemainingHCIEventParameters();
203 } while (HCIEventHeader
.EventCode
!= EVENT_COMMAND_COMPLETE
);
205 Bluetooth_HCIProcessingState
= Bluetooth_Init_SetDeviceClass
;
207 case Bluetooth_Init_SetDeviceClass
:
208 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
210 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE
},
214 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetDeviceClass", NULL
);
216 ErrorCode
= Bluetooth_SendHCICommand(&Bluetooth_DeviceConfiguration
.Class
, 3);
220 while (!(Bluetooth_GetNextHCIEventHeader()))
222 if (USB_HostState
== HOST_STATE_Unattached
)
226 Bluetooth_DiscardRemainingHCIEventParameters();
227 } while (HCIEventHeader
.EventCode
!= EVENT_COMMAND_COMPLETE
);
229 Bluetooth_HCIProcessingState
= Bluetooth_Init_WriteScanEnable
;
231 case Bluetooth_Init_WriteScanEnable
:
232 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
234 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE
},
238 BT_DEBUG("(HCI) Enter State: Bluetooth_Init_WriteScanEnable", NULL
);
240 uint8_t Interval
= InquiryAndPageScans
;
241 ErrorCode
= Bluetooth_SendHCICommand(&Interval
, 1);
245 while (!(Bluetooth_GetNextHCIEventHeader()))
247 if (USB_HostState
== HOST_STATE_Unattached
)
251 Bluetooth_DiscardRemainingHCIEventParameters();
252 } while (HCIEventHeader
.EventCode
!= EVENT_COMMAND_COMPLETE
);
254 Bluetooth_HCIProcessingState
= Bluetooth_PrepareToProcessEvents
;
256 case Bluetooth_PrepareToProcessEvents
:
257 BT_DEBUG("(HCI) Enter State: Bluetooth_ProcessEvents", NULL
);
259 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
261 case Bluetooth_ProcessEvents
:
262 if (Bluetooth_GetNextHCIEventHeader())
264 BT_DEBUG("(HCI) Event Code: 0x%02X", HCIEventHeader
.EventCode
);
266 if (HCIEventHeader
.EventCode
== EVENT_COMMAND_STATUS
)
268 Bluetooth_HCIEvent_CommandStatus_Header_t CommandStatusHeader
;
270 Pipe_Read_Stream_LE(&CommandStatusHeader
, sizeof(CommandStatusHeader
));
271 HCIEventHeader
.ParameterLength
-= sizeof(CommandStatusHeader
);
273 BT_DEBUG("(HCI) >> Command status: 0x%02X", CommandStatusHeader
.CommandStatus
);
275 if (CommandStatusHeader
.CommandStatus
)
276 Bluetooth_HCIProcessingState
= Bluetooth_Init
;
278 else if (HCIEventHeader
.EventCode
== EVENT_CONNECTION_REQUEST
)
280 Bluetooth_HCIEvent_ConnectionRequest_Header_t ConnectionRequestParams
;
282 Pipe_Read_Stream_LE(&ConnectionRequestParams
, sizeof(ConnectionRequestParams
));
283 HCIEventHeader
.ParameterLength
-= sizeof(ConnectionRequestParams
);
285 BT_DEBUG("(HCI) >> Connection Request from device %02X:%02X:%02X:%02X:%02X:%02X",
286 ConnectionRequestParams
.RemoteAddress
[5], ConnectionRequestParams
.RemoteAddress
[4],
287 ConnectionRequestParams
.RemoteAddress
[3], ConnectionRequestParams
.RemoteAddress
[2],
288 ConnectionRequestParams
.RemoteAddress
[1], ConnectionRequestParams
.RemoteAddress
[0]);
289 BT_DEBUG("(HCI) -- Device Class: 0x%02X%04X", ConnectionRequestParams
.ClassOfDevice_Service
,
290 ConnectionRequestParams
.ClassOfDevice_MajorMinor
);
291 BT_DEBUG("(HCI) -- Link Type: 0x%02x", ConnectionRequestParams
.LinkType
);
293 memcpy(Bluetooth_TempDeviceAddress
, ConnectionRequestParams
.RemoteAddress
,
294 sizeof(Bluetooth_TempDeviceAddress
));
296 Bluetooth_HCIProcessingState
= (Bluetooth_Connection
.IsConnected
) ? Bluetooth_Conn_RejectConnection
:
297 Bluetooth_Conn_AcceptConnection
;
299 else if (HCIEventHeader
.EventCode
== EVENT_DISCONNECTION_COMPLETE
)
301 BT_DEBUG("(HCI) >> Disconnection from device complete.", NULL
);
302 Bluetooth_HCIProcessingState
= Bluetooth_Init
;
304 else if (HCIEventHeader
.EventCode
== EVENT_CONNECTION_COMPLETE
)
306 Bluetooth_HCIEvent_ConnectionComplete_Header_t ConnectionCompleteParams
;
308 Pipe_Read_Stream_LE(&ConnectionCompleteParams
, sizeof(ConnectionCompleteParams
));
309 HCIEventHeader
.ParameterLength
-= sizeof(ConnectionCompleteParams
);
311 BT_DEBUG("(HCI) >> Connection to device complete.", NULL
);
312 BT_DEBUG("(HCI) -- Status: %d", ConnectionCompleteParams
.Status
);
313 BT_DEBUG("(HCI) -- Handle: %d", ConnectionCompleteParams
.ConnectionHandle
);
315 if (ConnectionCompleteParams
.Status
== 0x00)
317 memcpy(Bluetooth_Connection
.DeviceAddress
, ConnectionCompleteParams
.RemoteAddress
,
318 sizeof(Bluetooth_Connection
.DeviceAddress
));
319 Bluetooth_Connection
.ConnectionHandle
= ConnectionCompleteParams
.ConnectionHandle
;
320 Bluetooth_Connection
.IsConnected
= true;
323 else if (HCIEventHeader
.EventCode
== EVENT_PIN_CODE_REQUEST
)
325 Pipe_Read_Stream_LE(&Bluetooth_TempDeviceAddress
, sizeof(Bluetooth_TempDeviceAddress
));
326 HCIEventHeader
.ParameterLength
-= sizeof(Bluetooth_TempDeviceAddress
);
328 BT_DEBUG("(HCI) >> PIN code Request from device %02X:%02X:%02X:%02X:%02X:%02X",
329 Bluetooth_TempDeviceAddress
[5], Bluetooth_TempDeviceAddress
[4], Bluetooth_TempDeviceAddress
[3],
330 Bluetooth_TempDeviceAddress
[2], Bluetooth_TempDeviceAddress
[1], Bluetooth_TempDeviceAddress
[0]);
332 Bluetooth_HCIProcessingState
= Bluetooth_Conn_SendPINCode
;
334 else if (HCIEventHeader
.EventCode
== EVENT_COMMAND_COMPLETE
)
336 BT_DEBUG("(HCI) >> Command Complete", NULL
);
339 BT_DEBUG("(HCI) -- Unread Event Param Length: %d", HCIEventHeader
.ParameterLength
);
341 Bluetooth_DiscardRemainingHCIEventParameters();
345 case Bluetooth_Conn_AcceptConnection
:
346 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
348 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST
},
349 ParameterLength
: sizeof(Bluetooth_HCICommand_AcceptConnectionRequest_Params_t
),
352 BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_AcceptConnection", NULL
);
354 Bluetooth_HCICommand_AcceptConnectionRequest_Params_t AcceptConnectionParams
;
356 memcpy(AcceptConnectionParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
,
357 sizeof(Bluetooth_TempDeviceAddress
));
358 AcceptConnectionParams
.SlaveRole
= true;
360 Bluetooth_SendHCICommand(&AcceptConnectionParams
, sizeof(AcceptConnectionParams
));
362 Bluetooth_HCIProcessingState
= Bluetooth_PrepareToProcessEvents
;
364 case Bluetooth_Conn_RejectConnection
:
365 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
367 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST
},
368 ParameterLength
: sizeof(Bluetooth_HCICommand_RejectConnectionRequest_Params_t
),
371 BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_RejectConnection", NULL
);
373 Bluetooth_HCICommand_RejectConnectionRequest_Params_t RejectConnectionParams
;
375 memcpy(RejectConnectionParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
,
376 sizeof(Bluetooth_TempDeviceAddress
));
377 RejectConnectionParams
.Reason
= ERROR_LIMITED_RESOURCES
;
379 Bluetooth_SendHCICommand(&AcceptConnectionParams
, sizeof(AcceptConnectionParams
));
381 Bluetooth_HCIProcessingState
= Bluetooth_PrepareToProcessEvents
;
383 case Bluetooth_Conn_SendPINCode
:
384 HCICommandHeader
= (Bluetooth_HCICommand_Header_t
)
386 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY
},
387 ParameterLength
: sizeof(Bluetooth_HCICommand_PinCodeResponse_Params_t
),
390 BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_SendPINCode", NULL
);
391 BT_DEBUG("(HCI) -- PIN: %s", Bluetooth_DeviceConfiguration
.PINCode
);
393 Bluetooth_HCICommand_PinCodeResponse_Params_t PINCodeRequestParams
;
395 memcpy(PINCodeRequestParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
,
396 sizeof(Bluetooth_TempDeviceAddress
));
397 PINCodeRequestParams
.PINCodeLength
= strlen(Bluetooth_DeviceConfiguration
.PINCode
);
398 memcpy(PINCodeRequestParams
.PINCode
, Bluetooth_DeviceConfiguration
.PINCode
,
399 sizeof(Bluetooth_DeviceConfiguration
.PINCode
));
401 Bluetooth_SendHCICommand(&PINCodeRequestParams
, sizeof(PINCodeRequestParams
));
403 Bluetooth_HCIProcessingState
= Bluetooth_PrepareToProcessEvents
;