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_BLUETOOTHHCICOMMANDS_C
32 #include "BluetoothHCICommands.h"
34 /** Current processing state of the HCI portion of the Bluetooth stack. */
35 uint8_t Bluetooth_HCIProcessingState
;
37 /** Next HCI state to enter once the last issued HCI command has completed. */
38 static uint8_t Bluetooth_HCINextState
;
40 /** Temporary Bluetooth Device Address, for HCI responses which much include the detination address */
41 static uint8_t Bluetooth_TempDeviceAddress
[6];
44 /** Bluetooth HCI processing task. This task should be called repeatedly the main Bluetooth
45 * stack task to manage the HCI processing state.
47 void Bluetooth_HCITask(void)
49 BT_HCICommand_Header_t HCICommandHeader
;
51 switch (Bluetooth_HCIProcessingState
)
53 case Bluetooth_ProcessEvents
:
54 Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE
);
57 if (Pipe_IsReadWriteAllowed())
59 BT_HCIEvent_Header_t HCIEventHeader
;
61 /* Read in the event header to fetch the event code and payload length */
62 Pipe_Read_Stream_LE(&HCIEventHeader
, sizeof(HCIEventHeader
));
64 /* Create a temporary buffer for the event parameters */
65 uint8_t EventParams
[HCIEventHeader
.ParameterLength
];
67 /* Read in the event parameters into the temporary buffer */
68 Pipe_Read_Stream_LE(&EventParams
, HCIEventHeader
.ParameterLength
);
71 BT_HCI_DEBUG(1, "Event Received (0x%02X)", HCIEventHeader
.EventCode
);
73 switch (HCIEventHeader
.EventCode
)
75 case EVENT_COMMAND_COMPLETE
:
76 BT_HCI_DEBUG(1, "<< Command Complete", NULL
);
77 Bluetooth_HCIProcessingState
= Bluetooth_HCINextState
;
79 case EVENT_COMMAND_STATUS
:
80 BT_HCI_DEBUG(1, "<< Command Status", NULL
);
81 BT_HCI_DEBUG(2, "-- Status Code: 0x%02X", (((BT_HCIEvent_CommandStatus_t
*)&EventParams
)->Status
));
83 /* If the execution of a command failed, reset the stack */
84 if (((BT_HCIEvent_CommandStatus_t
*)&EventParams
)->Status
)
85 Bluetooth_HCIProcessingState
= Bluetooth_Init
;
87 case EVENT_CONNECTION_REQUEST
:
88 BT_HCI_DEBUG(1, "<< Connection Request", NULL
);
89 BT_HCI_DEBUG(2, "-- Link Type: 0x%02X", (((BT_HCIEvent_ConnectionRequest_t
*)&EventParams
)->LinkType
));
91 /* Need to store the remote device's BT address in a temporary buffer for later use */
92 memcpy(Bluetooth_TempDeviceAddress
,
93 &((BT_HCIEvent_ConnectionRequest_t
*)&EventParams
)->RemoteAddress
,
94 sizeof(Bluetooth_TempDeviceAddress
));
96 bool IsACLConnection
= (((BT_HCIEvent_ConnectionRequest_t
*)&EventParams
)->LinkType
== 0x01);
98 /* Only accept the connection if it is a ACL (data) connection, a device is not already connected
99 and the user application has indicated that the connection should be allowed */
100 Bluetooth_HCIProcessingState
= (Bluetooth_Connection
.IsConnected
|| !(IsACLConnection
) ||
101 !(Bluetooth_ConnectionRequest(Bluetooth_TempDeviceAddress
))) ?
102 Bluetooth_Conn_RejectConnection
: Bluetooth_Conn_AcceptConnection
;
104 BT_HCI_DEBUG(2, "-- Connection %S", (Bluetooth_HCIProcessingState
== Bluetooth_Conn_RejectConnection
) ?
105 PSTR("REJECTED") : PSTR("ACCEPTED"));
108 case EVENT_PIN_CODE_REQUEST
:
109 BT_HCI_DEBUG(1, "<< Pin Code Request", NULL
);
111 /* Need to store the remote device's BT address in a temporary buffer for later use */
112 memcpy(Bluetooth_TempDeviceAddress
,
113 &((BT_HCIEvent_PinCodeReq_t
*)&EventParams
)->RemoteAddress
,
114 sizeof(Bluetooth_TempDeviceAddress
));
116 Bluetooth_HCIProcessingState
= Bluetooth_Conn_SendPINCode
;
118 case EVENT_LINK_KEY_REQUEST
:
119 BT_HCI_DEBUG(1, "<< Link Key Request", NULL
);
121 /* Need to store the remote device's BT address in a temporary buffer for later use */
122 memcpy(Bluetooth_TempDeviceAddress
,
123 &((BT_HCIEvent_LinkKeyReq_t
*)&EventParams
)->RemoteAddress
,
124 sizeof(Bluetooth_TempDeviceAddress
));
126 Bluetooth_HCIProcessingState
= Bluetooth_Conn_SendLinkKeyNAK
;
128 case EVENT_CONNECTION_COMPLETE
:
129 BT_HCI_DEBUG(1, "<< Connection Complete", NULL
);
130 BT_HCI_DEBUG(2, "-- Handle: 0x%04X", ((BT_HCIEvent_ConnectionComplete_t
*)&EventParams
)->ConnectionHandle
);
132 /* Need to store the remote device's BT address in a temporary buffer for later use */
133 memcpy(Bluetooth_Connection
.RemoteAddress
,
134 &((BT_HCIEvent_ConnectionComplete_t
*)&EventParams
)->RemoteAddress
,
135 sizeof(Bluetooth_TempDeviceAddress
));
137 /* Store the created connection handle and indicate that the connection has been established */
138 Bluetooth_Connection
.ConnectionHandle
= ((BT_HCIEvent_ConnectionComplete_t
*)&EventParams
)->ConnectionHandle
;
139 Bluetooth_Connection
.IsConnected
= true;
141 Bluetooth_ConnectionComplete();
143 case EVENT_DISCONNECTION_COMPLETE
:
144 BT_HCI_DEBUG(1, "<< Disconnection Complete", NULL
);
146 /* Device disconnected, indicate connection information no longer valid */
147 Bluetooth_Connection
.IsConnected
= false;
149 Bluetooth_DisconnectionComplete();
151 Bluetooth_HCIProcessingState
= Bluetooth_Init
;
160 BT_HCI_DEBUG(1, "# Init", NULL
);
162 /* Reset the connection information structure to destroy any previous connection state */
163 memset(&Bluetooth_Connection
, 0x00, sizeof(Bluetooth_Connection
));
165 Bluetooth_HCIProcessingState
= Bluetooth_Init_Reset
;
167 case Bluetooth_Init_Reset
:
168 BT_HCI_DEBUG(1, "# Reset", NULL
);
170 HCICommandHeader
= (BT_HCICommand_Header_t
)
172 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_RESET
},
176 /* Send the command to reset the bluetooth dongle controller */
177 Bluetooth_SendHCICommand(&HCICommandHeader
, NULL
, 0);
179 Bluetooth_HCINextState
= Bluetooth_Init_SetLocalName
;
180 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
182 case Bluetooth_Init_SetLocalName
:
183 BT_HCI_DEBUG(1, "# Set Local Name", NULL
);
185 HCICommandHeader
= (BT_HCICommand_Header_t
)
187 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME
},
188 ParameterLength
: 248,
191 /* Send the command to set the bluetooth dongle's name for other devices to see */
192 Bluetooth_SendHCICommand(&HCICommandHeader
, Bluetooth_DeviceConfiguration
.Name
, strlen(Bluetooth_DeviceConfiguration
.Name
));
194 Bluetooth_HCINextState
= Bluetooth_Init_SetDeviceClass
;
195 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
197 case Bluetooth_Init_SetDeviceClass
:
198 BT_HCI_DEBUG(1, "# Set Device Class", NULL
);
200 HCICommandHeader
= (BT_HCICommand_Header_t
)
202 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE
},
206 /* Send the command to set the class of the device for other devices to see */
207 Bluetooth_SendHCICommand(&HCICommandHeader
, &Bluetooth_DeviceConfiguration
.Class
, 3);
209 Bluetooth_HCINextState
= Bluetooth_Init_WriteScanEnable
;
210 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
212 case Bluetooth_Init_WriteScanEnable
:
213 BT_HCI_DEBUG(1, "# Write Scan Enable", NULL
);
215 HCICommandHeader
= (BT_HCICommand_Header_t
)
217 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE
},
221 uint8_t Interval
= BT_SCANMODE_InquiryAndPageScans
;
223 /* Send the command to set the remote device scanning mode */
224 Bluetooth_SendHCICommand(&HCICommandHeader
, &Interval
, 1);
226 Bluetooth_HCINextState
= Bluetooth_ProcessEvents
;
227 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
229 case Bluetooth_Conn_AcceptConnection
:
230 BT_HCI_DEBUG(1, "# Accept Connection", NULL
);
232 HCICommandHeader
= (BT_HCICommand_Header_t
)
234 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST
},
235 ParameterLength
: sizeof(BT_HCICommand_AcceptConnectionReq_t
),
238 /* Copy over the temporary BT device address saved from the Connection Request event, indicate slave
240 BT_HCICommand_AcceptConnectionReq_t AcceptConnectionParams
;
241 memcpy(AcceptConnectionParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
,
242 sizeof(AcceptConnectionParams
.RemoteAddress
));
243 AcceptConnectionParams
.SlaveRole
= true;
245 /* Send the command to accept the remote connection request */
246 Bluetooth_SendHCICommand(&HCICommandHeader
, &AcceptConnectionParams
, sizeof(BT_HCICommand_AcceptConnectionReq_t
));
248 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
250 case Bluetooth_Conn_RejectConnection
:
251 BT_HCI_DEBUG(1, "# Reject Connection", NULL
);
253 HCICommandHeader
= (BT_HCICommand_Header_t
)
255 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_REJECT_CONNECTION_REQUEST
},
256 ParameterLength
: sizeof(BT_HCICommand_RejectConnectionReq_t
),
259 /* Copy over the temporary BT device address saved from the Connection Request event, indicate failure
260 to accept the connection due to limited device resources or incorrect device address */
261 BT_HCICommand_RejectConnectionReq_t RejectConnectionParams
;
262 memcpy(RejectConnectionParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
, sizeof(RejectConnectionParams
.RemoteAddress
));
263 RejectConnectionParams
.Reason
= Bluetooth_Connection
.IsConnected ? ERROR_LIMITED_RESOURCES
: ERROR_UNACCEPTABLE_BDADDR
;
265 /* Send the command to reject the remote connection request */
266 Bluetooth_SendHCICommand(&HCICommandHeader
, &RejectConnectionParams
, sizeof(BT_HCICommand_RejectConnectionReq_t
));
268 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
270 case Bluetooth_Conn_SendPINCode
:
271 BT_HCI_DEBUG(1, "# Send Pin Code", NULL
);
273 HCICommandHeader
= (BT_HCICommand_Header_t
)
275 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY
},
276 ParameterLength
: sizeof(BT_HCICommand_PinCodeResp_t
),
279 /* Copy over the temporary BT device address saved from the PIN Code Request event, copy over the
280 local PIN authentication code to the response */
281 BT_HCICommand_PinCodeResp_t PINCodeRequestParams
;
282 memcpy(PINCodeRequestParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
, sizeof(PINCodeRequestParams
.RemoteAddress
));
283 PINCodeRequestParams
.PINCodeLength
= strlen(Bluetooth_DeviceConfiguration
.PINCode
);
284 memcpy(PINCodeRequestParams
.PINCode
, Bluetooth_DeviceConfiguration
.PINCode
, sizeof(PINCodeRequestParams
.PINCode
));
286 /* Send the command to transmit the device's local PIN number for authentication */
287 Bluetooth_SendHCICommand(&HCICommandHeader
, &PINCodeRequestParams
, sizeof(BT_HCICommand_PinCodeResp_t
));
289 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
291 case Bluetooth_Conn_SendLinkKeyNAK
:
292 BT_HCI_DEBUG(1, "# Send Link Key NAK", NULL
);
294 HCICommandHeader
= (BT_HCICommand_Header_t
)
296 OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_LINK_KEY_REQUEST_NEG_REPLY
},
297 ParameterLength
: sizeof(BT_HCICommand_LinkKeyNAKResp_t
),
300 /* Copy over the temporary BT device address saved from the Link Key Request event */
301 BT_HCICommand_LinkKeyNAKResp_t LinkKeyNAKParams
;
302 memcpy(LinkKeyNAKParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
, sizeof(LinkKeyNAKParams
.RemoteAddress
));
304 /* Send the command to transmit the link key NAK to the receiver */
305 Bluetooth_SendHCICommand(&HCICommandHeader
, &LinkKeyNAKParams
, sizeof(BT_HCICommand_LinkKeyNAKResp_t
));
307 Bluetooth_HCIProcessingState
= Bluetooth_ProcessEvents
;
312 /** Sends a Bluetooth HCI control command to the attached Bluetooth device.
314 * \param HCICommandHeader HCI command header to send to the attached device
315 * \param Parameters Pointer to the source of the control parameters (if any)
316 * \param ParameterLength Length of the parameters to send in bytes
318 * \return A value from the USB_Host_SendControlErrorCodes_t enum.
320 static uint8_t Bluetooth_SendHCICommand(BT_HCICommand_Header_t
* HCICommandHeader
, void* Parameters
, uint16_t ParameterLength
)
322 /* Need to reserve the amount of bytes given in the header for the complete payload */
323 uint8_t CommandBuffer
[sizeof(BT_HCICommand_Header_t
) + HCICommandHeader
->ParameterLength
];
325 USB_ControlRequest
= (USB_Request_Header_t
)
327 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_DEVICE
),
331 .wLength
= sizeof(CommandBuffer
)
334 /* Copy over the HCI command header to the allocated buffer */
335 memcpy(CommandBuffer
, HCICommandHeader
, sizeof(BT_HCICommand_Header_t
));
337 /* Zero out the parameter section of the response so that all padding bytes are known to be zero */
338 memset(&CommandBuffer
[sizeof(BT_HCICommand_Header_t
)], 0x00, HCICommandHeader
->ParameterLength
);
340 /* Copy over the command parameters (if any) to the command buffer - note, the number of actual source parameter bytes
341 may differ to those in the header; any difference in length is filled with 0x00 padding bytes */
342 memcpy(&CommandBuffer
[sizeof(BT_HCICommand_Header_t
)], Parameters
, ParameterLength
);
344 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
345 return USB_Host_SendControlRequest(CommandBuffer
);