Make sure that the NVM bus/controller busy waits in the AVRISP MKII clone project...
[pub/USBasp.git] / Demos / Host / Incomplete / BluetoothHost / Lib / BluetoothHCICommands.c
index b4720e5..740ce67 100644 (file)
@@ -1,13 +1,13 @@
 /*\r
              LUFA Library\r
 /*\r
              LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
+     Copyright (C) Dean Camera, 2010.\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
-  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
 \r
   Permission to use, copy, modify, distribute, and sell this \r
   software and its documentation for any purpose is hereby granted\r
 \r
   Permission to use, copy, modify, distribute, and sell this \r
   software and its documentation for any purpose is hereby granted\r
   this software.\r
 */\r
 \r
   this software.\r
 */\r
 \r
-#include "BluetoothHCICommands.h"\r
+/*\r
+       TODO: Add local to remote device connections\r
+ */\r
 \r
 \r
-static   Bluetooth_HCICommand_Header_t HCICommandHeader;\r
-static   Bluetooth_HCIEvent_Header_t   HCIEventHeader;\r
+#define  INCLUDE_FROM_BLUETOOTHHCICOMMANDS_C\r
+#include "BluetoothHCICommands.h"\r
 \r
 \r
-         uint8_t                       Bluetooth_HCIProcessingState;\r
-static   uint8_t                       Bluetooth_TempDeviceAddress[6];\r
+/** Temporary Bluetooth Device Address, for HCI responses which much include the detination address */\r
+static uint8_t Bluetooth_TempDeviceAddress[6];\r
 \r
 \r
-static uint8_t Bluetooth_SendHCICommand(void* Parameters, uint8_t ParamLength)\r
+/** Bluetooth HCI processing task. This task should be called repeatedly the main Bluetooth\r
+ *  stack task to manage the HCI processing state.\r
+ */\r
+void Bluetooth_HCITask(void)\r
 {\r
 {\r
-       uint8_t CommandBuffer[sizeof(HCICommandHeader) + HCICommandHeader.ParameterLength];\r
-\r
-       USB_ControlRequest = (USB_Request_Header_t)\r
-               {\r
-                       .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_DEVICE),\r
-                       .bRequest      = 0,\r
-                       .wValue        = 0,\r
-                       .wIndex        = 0,\r
-                       .wLength       = sizeof(CommandBuffer)\r
-               };\r
-               \r
-       memset(CommandBuffer, 0x00, sizeof(CommandBuffer));\r
-       memcpy(CommandBuffer, &HCICommandHeader, sizeof(HCICommandHeader));\r
-       \r
-       if (ParamLength)\r
-         memcpy(&CommandBuffer[sizeof(HCICommandHeader)], Parameters, ParamLength);\r
-\r
-       Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
-\r
-       return USB_Host_SendControlRequest(CommandBuffer);\r
-}\r
+       BT_HCICommand_Header_t HCICommandHeader;\r
 \r
 \r
-static bool Bluetooth_GetNextHCIEventHeader(void)\r
-{\r
-       Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);\r
-       Pipe_Unfreeze();\r
-       \r
-       if (!(Pipe_IsReadWriteAllowed()))\r
+       switch (Bluetooth_State.CurrentHCIState)\r
        {\r
        {\r
-               Pipe_Freeze();\r
-               return false;\r
-       }\r
-         \r
-       Pipe_Read_Stream_LE(&HCIEventHeader, sizeof(HCIEventHeader));\r
-         \r
-       Pipe_Freeze();\r
-\r
-       return true;\r
-}\r
+               case Bluetooth_ProcessEvents:\r
+                       Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);\r
+                       Pipe_Unfreeze();\r
+                       \r
+                       if (Pipe_IsReadWriteAllowed())\r
+                       {\r
+                               BT_HCIEvent_Header_t HCIEventHeader;\r
 \r
 \r
-static void Bluetooth_DiscardRemainingHCIEventParameters(void)\r
-{\r
-       Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);\r
-       \r
-       Pipe_Unfreeze();\r
-       Pipe_Discard_Stream(HCIEventHeader.ParameterLength);\r
-       Pipe_ClearIN();\r
-       Pipe_Freeze();\r
-}\r
+                               /* Read in the event header to fetch the event code and payload length */\r
+                               Pipe_Read_Stream_LE(&HCIEventHeader, sizeof(HCIEventHeader));\r
+                               \r
+                               /* Create a temporary buffer for the event parameters */\r
+                               uint8_t EventParams[HCIEventHeader.ParameterLength];\r
 \r
 \r
-void Bluetooth_ProcessHCICommands(void)\r
-{\r
-       uint8_t ErrorCode;\r
+                               /* Read in the event parameters into the temporary buffer */\r
+                               Pipe_Read_Stream_LE(&EventParams, HCIEventHeader.ParameterLength);\r
+                               Pipe_ClearIN();\r
+                               \r
+                               BT_HCI_DEBUG(1, "Event Received (0x%02X)", HCIEventHeader.EventCode);\r
 \r
 \r
-       switch (Bluetooth_HCIProcessingState)\r
-       {\r
-               case Bluetooth_Init:\r
-                       Pipe_SelectPipe(BLUETOOTH_EVENTS_PIPE);\r
+                               switch (HCIEventHeader.EventCode)\r
+                               {\r
+                                       case EVENT_COMMAND_COMPLETE:\r
+                                               BT_HCI_DEBUG(1, "<< Command Complete");\r
+                                               \r
+                                               /* Check which operation was completed in case we need to process the even parameters */\r
+                                               switch (((BT_HCIEvent_CommandComplete_t*)&EventParams)->Opcode)\r
+                                               {\r
+                                                       case (OGF_CTRLR_INFORMATIONAL | OCF_CTRLR_INFORMATIONAL_READBDADDR):\r
+                                                               /* A READ BDADDR command completed, copy over the local device's BDADDR from the response */\r
+                                                               memcpy(Bluetooth_State.LocalBDADDR,\r
+                                                                      &((BT_HCIEvent_CommandComplete_t*)&EventParams)->ReturnParams[1],\r
+                                                                      sizeof(Bluetooth_State.LocalBDADDR));\r
+                                                               break;\r
+                                               }\r
+                                               \r
+                                               Bluetooth_State.CurrentHCIState = Bluetooth_State.NextHCIState;\r
+                                               break;\r
+                                       case EVENT_COMMAND_STATUS:\r
+                                               BT_HCI_DEBUG(1, "<< Command Status");\r
+                                               BT_HCI_DEBUG(2, "-- Status Code: 0x%02X", (((BT_HCIEvent_CommandStatus_t*)&EventParams)->Status));\r
+\r
+                                               /* If the execution of a command failed, reset the stack */\r
+                                               if (((BT_HCIEvent_CommandStatus_t*)&EventParams)->Status)\r
+                                                 Bluetooth_State.CurrentHCIState = Bluetooth_Init;\r
+                                               break;\r
+                                       case EVENT_CONNECTION_REQUEST:\r
+                                               BT_HCI_DEBUG(1, "<< Connection Request");\r
+                                               BT_HCI_DEBUG(2, "-- Link Type: 0x%02X", (((BT_HCIEvent_ConnectionRequest_t*)&EventParams)->LinkType));\r
+\r
+                                               /* Need to store the remote device's BT address in a temporary buffer for later use */\r
+                                               memcpy(Bluetooth_TempDeviceAddress,\r
+                                                      &((BT_HCIEvent_ConnectionRequest_t*)&EventParams)->RemoteAddress,\r
+                                                      sizeof(Bluetooth_TempDeviceAddress));\r
+                                                          \r
+                                               bool IsACLConnection = (((BT_HCIEvent_ConnectionRequest_t*)&EventParams)->LinkType == 0x01);\r
+\r
+                                               /* Only accept the connection if it is a ACL (data) connection, a device is not already connected\r
+                                                  and the user application has indicated that the connection should be allowed */\r
+                                               Bluetooth_State.CurrentHCIState = (Bluetooth_Connection.IsConnected || !(IsACLConnection) ||\r
+                                                                                                             !(Bluetooth_ConnectionRequest(Bluetooth_TempDeviceAddress))) ?\r
+                                                                                                             Bluetooth_Conn_RejectConnection : Bluetooth_Conn_AcceptConnection;\r
+\r
+                                               BT_HCI_DEBUG(2, "-- Connection %S", (Bluetooth_State.CurrentHCIState == Bluetooth_Conn_RejectConnection) ?\r
+                                                                                    PSTR("REJECTED") : PSTR("ACCEPTED"));\r
+\r
+                                               break;\r
+                                       case EVENT_PIN_CODE_REQUEST:\r
+                                               BT_HCI_DEBUG(1, "<< Pin Code Request");\r
+\r
+                                               /* Need to store the remote device's BT address in a temporary buffer for later use */\r
+                                               memcpy(Bluetooth_TempDeviceAddress,\r
+                                                      &((BT_HCIEvent_PinCodeReq_t*)&EventParams)->RemoteAddress,\r
+                                                      sizeof(Bluetooth_TempDeviceAddress));\r
+\r
+                                               Bluetooth_State.CurrentHCIState = Bluetooth_Conn_SendPINCode;\r
+                                               break;\r
+                                       case EVENT_LINK_KEY_REQUEST:\r
+                                               BT_HCI_DEBUG(1, "<< Link Key Request");\r
+                                               \r
+                                               /* Need to store the remote device's BT address in a temporary buffer for later use */\r
+                                               memcpy(Bluetooth_TempDeviceAddress,\r
+                                                      &((BT_HCIEvent_LinkKeyReq_t*)&EventParams)->RemoteAddress,\r
+                                                      sizeof(Bluetooth_TempDeviceAddress));                                            \r
+                                               \r
+                                               Bluetooth_State.CurrentHCIState = Bluetooth_Conn_SendLinkKeyNAK;\r
+                                               break;\r
+                                       case EVENT_CONNECTION_COMPLETE:\r
+                                               BT_HCI_DEBUG(1, "<< Connection Complete");\r
+                                               BT_HCI_DEBUG(2, "-- Handle: 0x%04X", ((BT_HCIEvent_ConnectionComplete_t*)&EventParams)->ConnectionHandle);\r
+\r
+                                               /* Need to store the remote device's BT address in a temporary buffer for later use */\r
+                                               memcpy(Bluetooth_Connection.RemoteAddress,\r
+                                                      &((BT_HCIEvent_ConnectionComplete_t*)&EventParams)->RemoteAddress,\r
+                                                      sizeof(Bluetooth_TempDeviceAddress));\r
+\r
+                                               /* Store the created connection handle and indicate that the connection has been established */\r
+                                               Bluetooth_Connection.ConnectionHandle = ((BT_HCIEvent_ConnectionComplete_t*)&EventParams)->ConnectionHandle;\r
+                                               Bluetooth_Connection.IsConnected      = true;\r
+                                               \r
+                                               Bluetooth_ConnectionComplete();                                         \r
+                                               break;\r
+                                       case EVENT_DISCONNECTION_COMPLETE:\r
+                                               BT_HCI_DEBUG(1, "<< Disconnection Complete");\r
+\r
+                                               /* Device disconnected, indicate connection information no longer valid */\r
+                                               Bluetooth_Connection.IsConnected = false;\r
+                                               \r
+                                               Bluetooth_DisconnectionComplete();\r
+                                               \r
+                                               Bluetooth_State.CurrentHCIState = Bluetooth_Init;\r
+                                               break;\r
+                               }\r
+                       }\r
                        \r
                        \r
+                       Pipe_Freeze();\r
+                       \r
+                       break;\r
+               case Bluetooth_Init:\r
+                       BT_HCI_DEBUG(1, "# Init");\r
+\r
+                       Bluetooth_State.IsInitialized = false;\r
+\r
+                       /* Reset the connection information structure to destroy any previous connection state */\r
                        memset(&Bluetooth_Connection, 0x00, sizeof(Bluetooth_Connection));\r
                        memset(&Bluetooth_Connection, 0x00, sizeof(Bluetooth_Connection));\r
-                                                          \r
-                       Bluetooth_HCIProcessingState = Bluetooth_Init_Reset; \r
+\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_Init_Reset; \r
                        break;\r
                case Bluetooth_Init_Reset:\r
                        break;\r
                case Bluetooth_Init_Reset:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Reset");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                        {\r
                        {\r
-                               OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_RESET},\r
+                               OpCode: (OGF_CTRLR_BASEBAND | OCF_CTRLR_BASEBAND_RESET),\r
                                ParameterLength: 0,\r
                        };\r
                                ParameterLength: 0,\r
                        };\r
-                       \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Init_Reset", NULL);\r
-\r
-                       ErrorCode = Bluetooth_SendHCICommand(NULL, 0);\r
 \r
 \r
-                       do\r
-                       {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {\r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
-               \r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
-\r
-                       Bluetooth_HCIProcessingState = Bluetooth_Init_ReadBufferSize;\r
+                       /* Send the command to reset the bluetooth dongle controller */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, NULL, 0);\r
+                       \r
+                       Bluetooth_State.NextHCIState    = Bluetooth_Init_ReadBufferSize;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Init_ReadBufferSize:\r
                        break;\r
                case Bluetooth_Init_ReadBufferSize:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Read Buffer Size");\r
+               \r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                        {\r
                        {\r
-                               OpCode: {OGF: OGF_CTRLR_INFORMATIONAL, OCF: OGF_CTRLR_INFORMATIONAL_READBUFFERSIZE},\r
+                               OpCode: (OGF_CTRLR_INFORMATIONAL | OCF_CTRLR_INFORMATIONAL_READBUFFERSIZE),\r
                                ParameterLength: 0,\r
                        };\r
                                ParameterLength: 0,\r
                        };\r
-               \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Init_ReadBufferSize", NULL);\r
 \r
 \r
-                       ErrorCode = Bluetooth_SendHCICommand(NULL, 0);\r
+                       /* Send the command to read the bluetooth buffer size (mandatory before device sends any data) */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, NULL, 0);\r
 \r
 \r
-                       do\r
-                       {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {\r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
-\r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
-\r
-                       Bluetooth_HCIProcessingState = Bluetooth_Init_SetEventMask;             \r
+                       Bluetooth_State.NextHCIState    = Bluetooth_Init_GetBDADDR;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                        break;\r
-               case Bluetooth_Init_SetEventMask:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
-                       {\r
-                               OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_SET_EVENT_MASK},\r
-                               ParameterLength: 8,\r
-                       };\r
+               case Bluetooth_Init_GetBDADDR:\r
+                       BT_HCI_DEBUG(1, "# Get BDADDR");\r
                \r
                \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetEventMask", NULL);\r
-                       \r
-                       uint8_t EventMask[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\r
-                       ErrorCode = Bluetooth_SendHCICommand(&EventMask, 8);\r
-\r
-                       BT_DEBUG("(HCI) -- Event mask: 0x%02X%02X%02X%02X%02X%02X%02X%02X", EventMask[7], EventMask[6], EventMask[5], EventMask[4],\r
-                                                                                           EventMask[3], EventMask[2], EventMask[1], EventMask[0]);\r
-                       do\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                        {\r
                        {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {\r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
+                               OpCode: (OGF_CTRLR_INFORMATIONAL | OCF_CTRLR_INFORMATIONAL_READBDADDR),\r
+                               ParameterLength: 0,\r
+                       };\r
 \r
 \r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
-               \r
+                       /* Send the command to retrieve the BDADDR of the inserted bluetooth dongle */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, NULL, 0);\r
 \r
 \r
-                       Bluetooth_HCIProcessingState = Bluetooth_Init_SetLocalName;             \r
+                       Bluetooth_State.NextHCIState    = Bluetooth_Init_SetLocalName;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Init_SetLocalName:\r
                        break;\r
                case Bluetooth_Init_SetLocalName:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Set Local Name");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                                {\r
                                {\r
-                                       OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME},\r
+                                       OpCode: (OGF_CTRLR_BASEBAND | OCF_CTRLR_BASEBAND_WRITE_LOCAL_NAME),\r
                                        ParameterLength: 248,\r
                                };\r
 \r
                                        ParameterLength: 248,\r
                                };\r
 \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetLocalName", NULL);\r
-                       BT_DEBUG("(HCI)  -- Name: %s", Bluetooth_DeviceConfiguration.Name);\r
+                       /* Send the command to set the bluetooth dongle's name for other devices to see */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, Bluetooth_DeviceConfiguration.Name, strlen(Bluetooth_DeviceConfiguration.Name));\r
 \r
 \r
-                       ErrorCode = Bluetooth_SendHCICommand(Bluetooth_DeviceConfiguration.Name, strlen(Bluetooth_DeviceConfiguration.Name));\r
-                       \r
-                       do\r
-                       {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {\r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
-\r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
-                       \r
-                       Bluetooth_HCIProcessingState = Bluetooth_Init_SetDeviceClass;\r
+                       Bluetooth_State.NextHCIState    = Bluetooth_Init_SetDeviceClass;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Init_SetDeviceClass:\r
                        break;\r
                case Bluetooth_Init_SetDeviceClass:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Set Device Class");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                                {\r
                                {\r
-                                       OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE},\r
+                                       OpCode: (OGF_CTRLR_BASEBAND | OCF_CTRLR_BASEBAND_WRITE_CLASS_OF_DEVICE),\r
                                        ParameterLength: 3,\r
                                };\r
 \r
                                        ParameterLength: 3,\r
                                };\r
 \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Init_SetDeviceClass", NULL);\r
-\r
-                       ErrorCode = Bluetooth_SendHCICommand(&Bluetooth_DeviceConfiguration.Class, 3);\r
+                       /* Send the command to set the class of the device for other devices to see */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, &Bluetooth_DeviceConfiguration.Class, 3);\r
 \r
 \r
-                       do\r
-                       {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {\r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
-\r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
-\r
-                       Bluetooth_HCIProcessingState = Bluetooth_Init_WriteScanEnable;  \r
+                       Bluetooth_State.NextHCIState    = Bluetooth_Init_WriteScanEnable;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Init_WriteScanEnable:\r
                        break;\r
                case Bluetooth_Init_WriteScanEnable:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Write Scan Enable");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                        {\r
                        {\r
-                               OpCode: {OGF: OGF_CTRLR_BASEBAND, OCF: OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE},\r
+                               OpCode: (OGF_CTRLR_BASEBAND | OCF_CTRLR_BASEBAND_WRITE_SCAN_ENABLE),\r
                                ParameterLength: 1,\r
                        };\r
                                ParameterLength: 1,\r
                        };\r
-                       \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Init_WriteScanEnable", NULL);\r
-\r
-                       uint8_t Interval = InquiryAndPageScans;\r
-                       ErrorCode = Bluetooth_SendHCICommand(&Interval, 1);\r
-\r
-                       do\r
-                       {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {\r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
 \r
 \r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
-\r
-                       Bluetooth_HCIProcessingState = Bluetooth_PrepareToProcessEvents;\r
-                       break;\r
-               case Bluetooth_PrepareToProcessEvents:\r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_ProcessEvents", NULL);\r
-\r
-                       Bluetooth_HCIProcessingState     = Bluetooth_ProcessEvents;\r
-                       break;\r
-               case Bluetooth_ProcessEvents:\r
-                       if (Bluetooth_GetNextHCIEventHeader())\r
-                       {\r
-                               BT_DEBUG("(HCI) Event Code: 0x%02X", HCIEventHeader.EventCode);\r
+                       uint8_t Interval = BT_SCANMODE_InquiryAndPageScans;\r
                        \r
                        \r
-                               if (HCIEventHeader.EventCode == EVENT_COMMAND_STATUS)\r
-                               {\r
-                                       Bluetooth_HCIEvent_CommandStatus_Header_t CommandStatusHeader;\r
-\r
-                                       Pipe_Read_Stream_LE(&CommandStatusHeader, sizeof(CommandStatusHeader));\r
-                                       HCIEventHeader.ParameterLength -= sizeof(CommandStatusHeader);\r
-                                                                               \r
-                                       BT_DEBUG("(HCI) >> Command status: 0x%02X", CommandStatusHeader.CommandStatus);\r
-                                       \r
-                                       if (CommandStatusHeader.CommandStatus)\r
-                                         Bluetooth_HCIProcessingState = Bluetooth_Init;\r
-                               }\r
-                               else if (HCIEventHeader.EventCode == EVENT_CONNECTION_REQUEST)\r
-                               {\r
-                                       Bluetooth_HCIEvent_ConnectionRequest_Header_t ConnectionRequestParams;\r
-                                       \r
-                                       Pipe_Read_Stream_LE(&ConnectionRequestParams, sizeof(ConnectionRequestParams));\r
-                                       HCIEventHeader.ParameterLength -= sizeof(ConnectionRequestParams);\r
-\r
-                                       BT_DEBUG("(HCI) >> Connection Request from device %02X:%02X:%02X:%02X:%02X:%02X",\r
-                                                ConnectionRequestParams.RemoteAddress[5], ConnectionRequestParams.RemoteAddress[4], \r
-                                                ConnectionRequestParams.RemoteAddress[3], ConnectionRequestParams.RemoteAddress[2], \r
-                                                ConnectionRequestParams.RemoteAddress[1], ConnectionRequestParams.RemoteAddress[0]);\r
-                                       BT_DEBUG("(HCI) -- Device Class: 0x%02X%04X", ConnectionRequestParams.ClassOfDevice_Service,\r
-                                                                                     ConnectionRequestParams.ClassOfDevice_MajorMinor);\r
-                                       BT_DEBUG("(HCI) -- Link Type: 0x%02x", ConnectionRequestParams.LinkType);\r
-                                       \r
-                                       memcpy(Bluetooth_TempDeviceAddress, ConnectionRequestParams.RemoteAddress,\r
-                                              sizeof(Bluetooth_TempDeviceAddress));\r
-\r
-                                       Bluetooth_HCIProcessingState = (Bluetooth_Connection.IsConnected) ? Bluetooth_Conn_RejectConnection :\r
-                                                                                                               Bluetooth_Conn_AcceptConnection;\r
-                               }\r
-                               else if (HCIEventHeader.EventCode == EVENT_DISCONNECTION_COMPLETE)\r
-                               {\r
-                                       BT_DEBUG("(HCI) >> Disconnection from device complete.", NULL);\r
-                                       Bluetooth_HCIProcessingState = Bluetooth_Init;\r
-                               }\r
-                               else if (HCIEventHeader.EventCode == EVENT_CONNECTION_COMPLETE)\r
-                               {\r
-                                       Bluetooth_HCIEvent_ConnectionComplete_Header_t ConnectionCompleteParams;\r
-                                       \r
-                                       Pipe_Read_Stream_LE(&ConnectionCompleteParams, sizeof(ConnectionCompleteParams));\r
-                                       HCIEventHeader.ParameterLength -= sizeof(ConnectionCompleteParams);\r
-\r
-                                       BT_DEBUG("(HCI) >> Connection to device complete.", NULL);\r
-                                       BT_DEBUG("(HCI) -- Status: %d", ConnectionCompleteParams.Status);\r
-                                       BT_DEBUG("(HCI) -- Handle: %d", ConnectionCompleteParams.ConnectionHandle);\r
-                                       \r
-                                       if (ConnectionCompleteParams.Status == 0x00)\r
-                                       {\r
-                                               memcpy(Bluetooth_Connection.DeviceAddress, ConnectionCompleteParams.RemoteAddress,\r
-                                                          sizeof(Bluetooth_Connection.DeviceAddress));\r
-                                               Bluetooth_Connection.ConnectionHandle = ConnectionCompleteParams.ConnectionHandle;\r
-                                               Bluetooth_Connection.IsConnected = true;\r
-                                       }\r
-                               }\r
-                               else if (HCIEventHeader.EventCode == EVENT_PIN_CODE_REQUEST)\r
-                               {\r
-                                       Pipe_Read_Stream_LE(&Bluetooth_TempDeviceAddress, sizeof(Bluetooth_TempDeviceAddress));\r
-                                       HCIEventHeader.ParameterLength -= sizeof(Bluetooth_TempDeviceAddress);\r
-\r
-                                       BT_DEBUG("(HCI) >> PIN code Request from device %02X:%02X:%02X:%02X:%02X:%02X", \r
-                                                        Bluetooth_TempDeviceAddress[5], Bluetooth_TempDeviceAddress[4], Bluetooth_TempDeviceAddress[3],\r
-                                                        Bluetooth_TempDeviceAddress[2], Bluetooth_TempDeviceAddress[1], Bluetooth_TempDeviceAddress[0]);\r
-                                                        \r
-                                       Bluetooth_HCIProcessingState = Bluetooth_Conn_SendPINCode;\r
-                               }\r
-                               \r
-                               BT_DEBUG("(HCI) -- Unread Event Param Length: %d", HCIEventHeader.ParameterLength);\r
+                       /* Send the command to set the remote device scanning mode */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, &Interval, 1);\r
+                       \r
+                       Bluetooth_State.NextHCIState    = Bluetooth_Init_FinalizeInit;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
+                       break;\r
+               case Bluetooth_Init_FinalizeInit:\r
+                       Bluetooth_State.IsInitialized = true;\r
 \r
 \r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       }\r
+                       /* Fire the user application callback to indicate that the stack is now fully initialized */\r
+                       Bluetooth_StackInitialized();\r
 \r
 \r
+                       Bluetooth_State.NextHCIState    = Bluetooth_ProcessEvents;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Conn_AcceptConnection:\r
                        break;\r
                case Bluetooth_Conn_AcceptConnection:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Accept Connection");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                                {\r
                                {\r
-                                       OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST},\r
-                                       ParameterLength: sizeof(Bluetooth_HCICommand_AcceptConnectionRequest_Params_t),\r
+                                       OpCode: (OGF_LINK_CONTROL | OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST),\r
+                                       ParameterLength: sizeof(BT_HCICommand_AcceptConnectionReq_t),\r
                                };\r
                                };\r
-                       \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_AcceptConnection", NULL);\r
 \r
 \r
-                       Bluetooth_HCICommand_AcceptConnectionRequest_Params_t AcceptConnectionParams;\r
-                                                        \r
+                       /* Copy over the temporary BT device address saved from the Connection Request event, indicate slave\r
+                          connection role */\r
+                       BT_HCICommand_AcceptConnectionReq_t AcceptConnectionParams;\r
                        memcpy(AcceptConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress,\r
                        memcpy(AcceptConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress,\r
-                              sizeof(Bluetooth_TempDeviceAddress));\r
+                              sizeof(AcceptConnectionParams.RemoteAddress));\r
                        AcceptConnectionParams.SlaveRole = true;\r
 \r
                        AcceptConnectionParams.SlaveRole = true;\r
 \r
-                       Bluetooth_SendHCICommand(&AcceptConnectionParams, sizeof(AcceptConnectionParams));\r
+                       /* Send the command to accept the remote connection request */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, &AcceptConnectionParams, sizeof(BT_HCICommand_AcceptConnectionReq_t));\r
                        \r
                        \r
-                       Bluetooth_HCIProcessingState     = Bluetooth_PrepareToProcessEvents;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Conn_RejectConnection:\r
                        break;\r
                case Bluetooth_Conn_RejectConnection:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Reject Connection");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                                {\r
                                {\r
-                                       OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_ACCEPT_CONNECTION_REQUEST},\r
-                                       ParameterLength: sizeof(Bluetooth_HCICommand_RejectConnectionRequest_Params_t),\r
+                                       OpCode: (OGF_LINK_CONTROL | OCF_LINK_CONTROL_REJECT_CONNECTION_REQUEST),\r
+                                       ParameterLength: sizeof(BT_HCICommand_RejectConnectionReq_t),\r
                                };\r
                                };\r
-                       \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_RejectConnection", NULL);\r
-\r
-                       Bluetooth_HCICommand_RejectConnectionRequest_Params_t RejectConnectionParams;\r
 \r
 \r
-                       memcpy(RejectConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress,\r
-                              sizeof(Bluetooth_TempDeviceAddress));\r
-                       RejectConnectionParams.Reason = ERROR_LIMITED_RESOURCES;\r
+                       /* Copy over the temporary BT device address saved from the Connection Request event, indicate failure\r
+                          to accept the connection due to limited device resources or incorrect device address */\r
+                       BT_HCICommand_RejectConnectionReq_t RejectConnectionParams;\r
+                       memcpy(RejectConnectionParams.RemoteAddress, Bluetooth_TempDeviceAddress, sizeof(RejectConnectionParams.RemoteAddress));\r
+                       RejectConnectionParams.Reason = Bluetooth_Connection.IsConnected ? ERROR_LIMITED_RESOURCES : ERROR_UNACCEPTABLE_BDADDR;\r
 \r
 \r
-                       Bluetooth_SendHCICommand(&AcceptConnectionParams, sizeof(AcceptConnectionParams));\r
+                       /* Send the command to reject the remote connection request */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, &RejectConnectionParams, sizeof(BT_HCICommand_RejectConnectionReq_t));\r
                \r
                \r
-                       Bluetooth_HCIProcessingState     = Bluetooth_PrepareToProcessEvents;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
                case Bluetooth_Conn_SendPINCode:\r
                        break;\r
                case Bluetooth_Conn_SendPINCode:\r
-                       HCICommandHeader = (Bluetooth_HCICommand_Header_t)\r
+                       BT_HCI_DEBUG(1, "# Send Pin Code");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
                                {\r
                                {\r
-                                       OpCode: {OGF: OGF_LINK_CONTROL, OCF: OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY},\r
-                                       ParameterLength: sizeof(Bluetooth_HCICommand_PinCodeResponse_Params_t),\r
+                                       OpCode: (OGF_LINK_CONTROL | OCF_LINK_CONTROL_PIN_CODE_REQUEST_REPLY),\r
+                                       ParameterLength: sizeof(BT_HCICommand_PinCodeResp_t),\r
                                };\r
                                };\r
-                       \r
-                       BT_DEBUG("(HCI) Enter State: Bluetooth_Conn_SendPINCode", NULL);\r
-                       BT_DEBUG("(HCI) -- PIN: %s", Bluetooth_DeviceConfiguration.PINCode);\r
 \r
 \r
-                       Bluetooth_HCICommand_PinCodeResponse_Params_t PINCodeRequestParams;\r
-               \r
-                       memcpy(PINCodeRequestParams.RemoteAddress, Bluetooth_TempDeviceAddress,\r
-                              sizeof(Bluetooth_TempDeviceAddress));\r
+                       /* Copy over the temporary BT device address saved from the PIN Code Request event, copy over the\r
+                          local PIN authentication code to the response */\r
+                       BT_HCICommand_PinCodeResp_t PINCodeRequestParams;\r
+                       memcpy(PINCodeRequestParams.RemoteAddress, Bluetooth_TempDeviceAddress, sizeof(PINCodeRequestParams.RemoteAddress));\r
                        PINCodeRequestParams.PINCodeLength = strlen(Bluetooth_DeviceConfiguration.PINCode);\r
                        PINCodeRequestParams.PINCodeLength = strlen(Bluetooth_DeviceConfiguration.PINCode);\r
-                       memcpy(PINCodeRequestParams.PINCode, Bluetooth_DeviceConfiguration.PINCode,\r
-                              sizeof(Bluetooth_DeviceConfiguration.PINCode));\r
+                       memcpy(PINCodeRequestParams.PINCode, Bluetooth_DeviceConfiguration.PINCode, sizeof(PINCodeRequestParams.PINCode));\r
                        \r
                        \r
-                       Bluetooth_SendHCICommand(&PINCodeRequestParams, sizeof(PINCodeRequestParams));\r
-               \r
-                       do\r
-                       {\r
-                               while (!(Bluetooth_GetNextHCIEventHeader()))\r
-                               {                               \r
-                                       if (USB_HostState == HOST_STATE_Unattached)\r
-                                         return;\r
-                               }\r
+                       /* Send the command to transmit the device's local PIN number for authentication */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, &PINCodeRequestParams, sizeof(BT_HCICommand_PinCodeResp_t));\r
+\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
+                       break;\r
+               case Bluetooth_Conn_SendLinkKeyNAK:\r
+                       BT_HCI_DEBUG(1, "# Send Link Key NAK");\r
+\r
+                       HCICommandHeader = (BT_HCICommand_Header_t)\r
+                               {\r
+                                       OpCode: (OGF_LINK_CONTROL | OCF_LINK_CONTROL_LINK_KEY_REQUEST_NEG_REPLY),\r
+                                       ParameterLength: sizeof(BT_HCICommand_LinkKeyNAKResp_t),\r
+                               };\r
+\r
+                       /* Copy over the temporary BT device address saved from the Link Key Request event */\r
+                       BT_HCICommand_LinkKeyNAKResp_t LinkKeyNAKParams;\r
+                       memcpy(LinkKeyNAKParams.RemoteAddress, Bluetooth_TempDeviceAddress, sizeof(LinkKeyNAKParams.RemoteAddress));\r
 \r
 \r
-                               Bluetooth_DiscardRemainingHCIEventParameters();\r
-                       } while (HCIEventHeader.EventCode != EVENT_COMMAND_COMPLETE);\r
+                       /* Send the command to transmit the link key NAK to the receiver */\r
+                       Bluetooth_SendHCICommand(&HCICommandHeader, &LinkKeyNAKParams, sizeof(BT_HCICommand_LinkKeyNAKResp_t));\r
 \r
 \r
-                       Bluetooth_HCIProcessingState     = Bluetooth_PrepareToProcessEvents;\r
+                       Bluetooth_State.CurrentHCIState = Bluetooth_ProcessEvents;\r
                        break;\r
        }\r
 }\r
                        break;\r
        }\r
 }\r
+\r
+/** Sends a Bluetooth HCI control command to the attached Bluetooth device.\r
+ *\r
+ *  \param[in] HCICommandHeader  HCI command header to send to the attached device\r
+ *  \param[in] Parameters        Pointer to the source of the control parameters (if any)\r
+ *  \param[in] ParameterLength   Length of the parameters to send in bytes\r
+ *\r
+ *  \return A value from the USB_Host_SendControlErrorCodes_t enum.\r
+ */\r
+static uint8_t Bluetooth_SendHCICommand(const BT_HCICommand_Header_t* const HCICommandHeader, const void* Parameters, const uint16_t ParameterLength)\r
+{\r
+       /* Need to reserve the amount of bytes given in the header for the complete payload */\r
+       uint8_t CommandBuffer[sizeof(BT_HCICommand_Header_t) + HCICommandHeader->ParameterLength];\r
+\r
+       USB_ControlRequest = (USB_Request_Header_t)\r
+               {\r
+                       .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_DEVICE),\r
+                       .bRequest      = 0,\r
+                       .wValue        = 0,\r
+                       .wIndex        = 0,\r
+                       .wLength       = sizeof(CommandBuffer)\r
+               };\r
+\r
+       /* Copy over the HCI command header to the allocated buffer */\r
+       memcpy(CommandBuffer, HCICommandHeader, sizeof(BT_HCICommand_Header_t));\r
+       \r
+       /* Zero out the parameter section of the response so that all padding bytes are known to be zero */\r
+       memset(&CommandBuffer[sizeof(BT_HCICommand_Header_t)], 0x00, HCICommandHeader->ParameterLength);\r
+\r
+       /* Copy over the command parameters (if any) to the command buffer - note, the number of actual source parameter bytes\r
+          may differ to those in the header; any difference in length is filled with 0x00 padding bytes */\r
+       memcpy(&CommandBuffer[sizeof(BT_HCICommand_Header_t)], Parameters, ParameterLength);\r
+       \r
+       Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
+       return USB_Host_SendControlRequest(CommandBuffer);\r
+}\r