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
;