3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  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. 
  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
)); 
  81 static void Bluetooth_DiscardRemainingHCIEventParameters(void) 
  83         Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE
); 
  86         Pipe_Discard_Stream(HCIEventHeader
.ParameterLength
); 
  91 void Bluetooth_ProcessHCICommands(void) 
  95         switch (Bluetooth_HCIProcessingState
) 
  98                         Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE
); 
 100                         memset(&Bluetooth_Connection
, 0x00, sizeof(Bluetooth_Connection
)); 
 102                         Bluetooth_HCIProcessingState 
= Bluetooth_Init_Reset
;  
 104                 case Bluetooth_Init_Reset
: 
 105                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 107                                 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_RESET
}, 
 111                         BT_DEBUG("(HCI) Enter State: Bluetooth_Init_Reset", NULL
); 
 113                         ErrorCode 
= Bluetooth_SendHCICommand(NULL
, 0); 
 117                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 118                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 119                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 121                         Bluetooth_HCIProcessingState 
= Bluetooth_Init_ReadBufferSize
; 
 123                 case Bluetooth_Init_ReadBufferSize
: 
 124                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 126                                 OpCode
: {OGF
: OGF_CTRLR_INFORMATIONAL
, OCF
: OGF_CTRLR_INFORMATIONAL_READBUFFERSIZE
}, 
 130                         BT_DEBUG("(HCI) Enter State: Bluetooth_Init_ReadBufferSize", NULL
); 
 132                         ErrorCode 
= Bluetooth_SendHCICommand(NULL
, 0); 
 136                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 137                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 138                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 140                         Bluetooth_HCIProcessingState 
= Bluetooth_Init_SetEventMask
;              
 142                 case Bluetooth_Init_SetEventMask
: 
 143                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 145                                 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_SET_EVENT_MASK
}, 
 149                         BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetEventMask", NULL
); 
 151                         uint8_t EventMask
[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 
 152                         ErrorCode 
= Bluetooth_SendHCICommand(&EventMask
, 8); 
 154                         BT_DEBUG("(HCI) -- Event mask: 0x%02X%02X%02X%02X%02X%02X%02X%02X", EventMask
[7], EventMask
[6], EventMask
[5], EventMask
[4], 
 155                                                                                             EventMask
[3], EventMask
[2], EventMask
[1], EventMask
[0]); 
 158                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 159                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 160                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 163                         Bluetooth_HCIProcessingState 
= Bluetooth_Init_SetLocalName
;              
 165                 case Bluetooth_Init_SetLocalName
: 
 166                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 168                                         OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME
}, 
 169                                         ParameterLength
: 248, 
 172                         BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetLocalName", NULL
); 
 173                         BT_DEBUG("(HCI)  -- Name: %s", Bluetooth_DeviceConfiguration
.Name
); 
 175                         ErrorCode 
= Bluetooth_SendHCICommand(Bluetooth_DeviceConfiguration
.Name
, strlen(Bluetooth_DeviceConfiguration
.Name
)); 
 179                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 180                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 181                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 183                         Bluetooth_HCIProcessingState 
= Bluetooth_Init_SetDeviceClass
; 
 185                 case Bluetooth_Init_SetDeviceClass
: 
 186                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 188                                         OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE
}, 
 192                         BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetDeviceClass", NULL
); 
 194                         ErrorCode 
= Bluetooth_SendHCICommand(&Bluetooth_DeviceConfiguration
.Class
, 3); 
 198                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 199                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 200                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 202                         Bluetooth_HCIProcessingState 
= Bluetooth_Init_WriteScanEnable
;   
 204                 case Bluetooth_Init_WriteScanEnable
: 
 205                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 207                                 OpCode
: {OGF
: OGF_CTRLR_BASEBAND
, OCF
: OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE
}, 
 211                         BT_DEBUG("(HCI) Enter State: Bluetooth_Init_WriteScanEnable", NULL
); 
 213                         uint8_t Interval 
= InquiryAndPageScans
; 
 214                         ErrorCode 
= Bluetooth_SendHCICommand(&Interval
, 1); 
 218                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 219                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 220                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 222                         Bluetooth_HCIProcessingState 
= Bluetooth_PrepareToProcessEvents
; 
 224                 case Bluetooth_PrepareToProcessEvents
: 
 225                         BT_DEBUG("(HCI) Enter State: Bluetooth_ProcessEvents", NULL
); 
 227                         Bluetooth_HCIProcessingState     
= Bluetooth_ProcessEvents
; 
 229                 case Bluetooth_ProcessEvents
: 
 230                         if (Bluetooth_GetNextHCIEventHeader()) 
 232                                 BT_DEBUG("(HCI) Event Code: 0x%02X", HCIEventHeader
.EventCode
); 
 234                                 if (HCIEventHeader
.EventCode 
== EVENT_COMMAND_STATUS
) 
 236                                         Bluetooth_HCIEvent_CommandStatus_Header_t CommandStatusHeader
; 
 238                                         Pipe_Read_Stream_LE(&CommandStatusHeader
, sizeof(CommandStatusHeader
)); 
 239                                         HCIEventHeader
.ParameterLength 
-= sizeof(CommandStatusHeader
); 
 241                                         BT_DEBUG("(HCI) >> Command status: 0x%02X", CommandStatusHeader
.CommandStatus
); 
 243                                         if (CommandStatusHeader
.CommandStatus
) 
 244                                           Bluetooth_HCIProcessingState 
= Bluetooth_Init
; 
 246                                 else if (HCIEventHeader
.EventCode 
== EVENT_CONNECTION_REQUEST
) 
 248                                         Bluetooth_HCIEvent_ConnectionRequest_Header_t ConnectionRequestParams
; 
 250                                         Pipe_Read_Stream_LE(&ConnectionRequestParams
, sizeof(ConnectionRequestParams
)); 
 251                                         HCIEventHeader
.ParameterLength 
-= sizeof(ConnectionRequestParams
); 
 253                                         BT_DEBUG("(HCI) >> Connection Request from device %02X:%02X:%02X:%02X:%02X:%02X", 
 254                                                  ConnectionRequestParams
.RemoteAddress
[5], ConnectionRequestParams
.RemoteAddress
[4],  
 255                                                  ConnectionRequestParams
.RemoteAddress
[3], ConnectionRequestParams
.RemoteAddress
[2],  
 256                                                  ConnectionRequestParams
.RemoteAddress
[1], ConnectionRequestParams
.RemoteAddress
[0]); 
 257                                         BT_DEBUG("(HCI) -- Device Class: 0x%02X%04X", ConnectionRequestParams
.ClassOfDevice_Service
, 
 258                                                                                       ConnectionRequestParams
.ClassOfDevice_MajorMinor
); 
 259                                         BT_DEBUG("(HCI) -- Link Type: 0x%02x", ConnectionRequestParams
.LinkType
); 
 261                                         memcpy(Bluetooth_TempDeviceAddress
, ConnectionRequestParams
.RemoteAddress
, 
 262                                                sizeof(Bluetooth_TempDeviceAddress
)); 
 264                                         Bluetooth_HCIProcessingState 
= (Bluetooth_Connection
.IsConnected
) ? Bluetooth_Conn_RejectConnection 
: 
 265                                                                                                                 Bluetooth_Conn_AcceptConnection
; 
 267                                 else if (HCIEventHeader
.EventCode 
== EVENT_DISCONNECTION_COMPLETE
) 
 269                                         BT_DEBUG("(HCI) >> Disconnection from device complete.", NULL
); 
 270                                         Bluetooth_HCIProcessingState 
= Bluetooth_Init
; 
 272                                 else if (HCIEventHeader
.EventCode 
== EVENT_CONNECTION_COMPLETE
) 
 274                                         Bluetooth_HCIEvent_ConnectionComplete_Header_t ConnectionCompleteParams
; 
 276                                         Pipe_Read_Stream_LE(&ConnectionCompleteParams
, sizeof(ConnectionCompleteParams
)); 
 277                                         HCIEventHeader
.ParameterLength 
-= sizeof(ConnectionCompleteParams
); 
 279                                         BT_DEBUG("(HCI) >> Connection to device complete.", NULL
); 
 280                                         BT_DEBUG("(HCI) -- Status: %d", ConnectionCompleteParams
.Status
); 
 281                                         BT_DEBUG("(HCI) -- Handle: %d", ConnectionCompleteParams
.ConnectionHandle
); 
 283                                         if (ConnectionCompleteParams
.Status 
== 0x00) 
 285                                                 memcpy(Bluetooth_Connection
.DeviceAddress
, ConnectionCompleteParams
.RemoteAddress
, 
 286                                                            sizeof(Bluetooth_Connection
.DeviceAddress
)); 
 287                                                 Bluetooth_Connection
.ConnectionHandle 
= ConnectionCompleteParams
.ConnectionHandle
; 
 288                                                 Bluetooth_Connection
.IsConnected 
= true; 
 291                                 else if (HCIEventHeader
.EventCode 
== EVENT_PIN_CODE_REQUEST
) 
 293                                         Pipe_Read_Stream_LE(&Bluetooth_TempDeviceAddress
, sizeof(Bluetooth_TempDeviceAddress
)); 
 294                                         HCIEventHeader
.ParameterLength 
-= sizeof(Bluetooth_TempDeviceAddress
); 
 296                                         BT_DEBUG("(HCI) >> PIN code Request from device %02X:%02X:%02X:%02X:%02X:%02X",  
 297                                                          Bluetooth_TempDeviceAddress
[5], Bluetooth_TempDeviceAddress
[4], Bluetooth_TempDeviceAddress
[3], 
 298                                                          Bluetooth_TempDeviceAddress
[2], Bluetooth_TempDeviceAddress
[1], Bluetooth_TempDeviceAddress
[0]); 
 300                                         Bluetooth_HCIProcessingState 
= Bluetooth_Conn_SendPINCode
; 
 303                                 BT_DEBUG("(HCI) -- Unread Event Param Length: %d", HCIEventHeader
.ParameterLength
); 
 305                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 309                 case Bluetooth_Conn_AcceptConnection
: 
 310                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 312                                         OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST
}, 
 313                                         ParameterLength
: sizeof(Bluetooth_HCICommand_AcceptConnectionRequest_Params_t
), 
 316                         BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_AcceptConnection", NULL
); 
 318                         Bluetooth_HCICommand_AcceptConnectionRequest_Params_t AcceptConnectionParams
; 
 320                         memcpy(AcceptConnectionParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
, 
 321                                sizeof(Bluetooth_TempDeviceAddress
)); 
 322                         AcceptConnectionParams
.SlaveRole 
= true; 
 324                         Bluetooth_SendHCICommand(&AcceptConnectionParams
, sizeof(AcceptConnectionParams
)); 
 326                         Bluetooth_HCIProcessingState     
= Bluetooth_PrepareToProcessEvents
; 
 328                 case Bluetooth_Conn_RejectConnection
: 
 329                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 331                                         OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST
}, 
 332                                         ParameterLength
: sizeof(Bluetooth_HCICommand_RejectConnectionRequest_Params_t
), 
 335                         BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_RejectConnection", NULL
); 
 337                         Bluetooth_HCICommand_RejectConnectionRequest_Params_t RejectConnectionParams
; 
 339                         memcpy(RejectConnectionParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
, 
 340                                sizeof(Bluetooth_TempDeviceAddress
)); 
 341                         RejectConnectionParams
.Reason 
= ERROR_LIMITED_RESOURCES
; 
 343                         Bluetooth_SendHCICommand(&AcceptConnectionParams
, sizeof(AcceptConnectionParams
)); 
 345                         Bluetooth_HCIProcessingState     
= Bluetooth_PrepareToProcessEvents
; 
 347                 case Bluetooth_Conn_SendPINCode
: 
 348                         HCICommandHeader 
= (Bluetooth_HCICommand_Header_t
) 
 350                                         OpCode
: {OGF
: OGF_LINK_CONTROL
, OCF
: OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY
}, 
 351                                         ParameterLength
: sizeof(Bluetooth_HCICommand_PinCodeResponse_Params_t
), 
 354                         BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_SendPINCode", NULL
); 
 355                         BT_DEBUG("(HCI) -- PIN: %s", Bluetooth_DeviceConfiguration
.PINCode
); 
 357                         Bluetooth_HCICommand_PinCodeResponse_Params_t PINCodeRequestParams
; 
 359                         memcpy(PINCodeRequestParams
.RemoteAddress
, Bluetooth_TempDeviceAddress
, 
 360                                sizeof(Bluetooth_TempDeviceAddress
)); 
 361                         PINCodeRequestParams
.PINCodeLength 
= strlen(Bluetooth_DeviceConfiguration
.PINCode
); 
 362                         memcpy(PINCodeRequestParams
.PINCode
, Bluetooth_DeviceConfiguration
.PINCode
, 
 363                                sizeof(Bluetooth_DeviceConfiguration
.PINCode
)); 
 365                         Bluetooth_SendHCICommand(&PINCodeRequestParams
, sizeof(PINCodeRequestParams
)); 
 369                                 while (!(Bluetooth_GetNextHCIEventHeader())); 
 370                                 Bluetooth_DiscardRemainingHCIEventParameters(); 
 371                         } while (HCIEventHeader
.EventCode 
!= EVENT_COMMAND_COMPLETE
); 
 373                         Bluetooth_HCIProcessingState     
= Bluetooth_PrepareToProcessEvents
;