[FBTUSB]
authorCameron Gutman <aicommander@gmail.com>
Sat, 12 Jun 2010 00:29:09 +0000 (00:29 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sat, 12 Jun 2010 00:29:09 +0000 (00:29 +0000)
- Import the FreeBT USB generic bluetooth driver (abandoned)
- Some slight modifications to make it build
- WMI is currently commented out because our WMI headers are lacking (particularly wmistr.h)
- Not building by default for now

svn path=/trunk/; revision=47761

36 files changed:
reactos/drivers/bluetooth/directory.rbuild [new file with mode: 0644]
reactos/drivers/bluetooth/fbtusb/fbtdev.c [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/fbtpnp.c [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/fbtpwr.c [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/fbtrwr.c [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/fbtusb.c [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/fbtusb.rbuild [new file with mode: 0644]
reactos/drivers/bluetooth/fbtusb/fbtusb.rc [new file with mode: 0644]
reactos/drivers/bluetooth/fbtusb/fbtwmi.c [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciCmdStructs.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciCmds.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciDefs.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciErrors.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciEventStructs.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciEvents.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciLocal.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciOpCodes.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciParms.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciRoundTrip.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtHciSizes.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtSeXcpt.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtdev.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbthci.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbthw.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtlog.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtpnp.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtpwr.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtreg.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtrwr.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtusb.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtusr.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtutil.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtwmi.h [new file with mode: 0755]
reactos/drivers/bluetooth/fbtusb/include/fbtxcpt.h [new file with mode: 0755]
reactos/drivers/drivers.rbuild
reactos/drivers/usb/directory.rbuild

diff --git a/reactos/drivers/bluetooth/directory.rbuild b/reactos/drivers/bluetooth/directory.rbuild
new file mode 100644 (file)
index 0000000..8d49812
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
+<group xmlns:xi="http://www.w3.org/2001/XInclude">
+<!--directory name="fbtusb">
+       <xi:include href="fbtusb/fbtusb.rbuild" />
+</directory-->
+</group>
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtdev.c b/reactos/drivers/bluetooth/fbtusb/fbtdev.c
new file mode 100755 (executable)
index 0000000..15f96e1
--- /dev/null
@@ -0,0 +1,1198 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#include "fbtusb.h"
+#include "fbtpnp.h"
+#include "fbtpwr.h"
+#include "fbtdev.h"
+#include "fbtwmi.h"
+#include "fbtrwr.h"
+
+#include "fbtusr.h"
+
+// Dispatch routine for CreateHandle
+NTSTATUS FreeBT_DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    ULONG                       i;
+    NTSTATUS                    ntStatus;
+    PFILE_OBJECT                fileObject;
+    PDEVICE_EXTENSION           deviceExtension;
+    PIO_STACK_LOCATION          irpStack;
+    PFREEBT_PIPE_CONTEXT               pipeContext;
+    PUSBD_INTERFACE_INFORMATION        interface;
+
+    PAGED_CODE();
+
+    FreeBT_DbgPrint(3, ("FreeBT_DispatchCreate: Entered\n"));
+
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    fileObject = irpStack->FileObject;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    if (deviceExtension->DeviceState != Working)
+    {
+        ntStatus = STATUS_INVALID_DEVICE_STATE;
+        goto FreeBT_DispatchCreate_Exit;
+
+    }
+
+    if (deviceExtension->UsbInterface)
+    {
+        interface = deviceExtension->UsbInterface;
+
+    }
+
+    else
+    {
+        FreeBT_DbgPrint(1, ("UsbInterface not found\n"));
+        ntStatus = STATUS_INVALID_DEVICE_STATE;
+        goto FreeBT_DispatchCreate_Exit;
+
+    }
+
+    if (fileObject)
+    {
+        fileObject->FsContext = NULL;
+    }
+
+    else
+    {
+        ntStatus = STATUS_INVALID_PARAMETER;
+        goto FreeBT_DispatchCreate_Exit;
+
+    }
+
+       if (deviceExtension->OpenHandleCount>0)
+       {
+               ntStatus = STATUS_ACCESS_VIOLATION;
+               goto FreeBT_DispatchCreate_Exit;
+
+       }
+
+    // opening a device as opposed to pipe.
+    ntStatus = STATUS_SUCCESS;
+
+    InterlockedIncrement(&deviceExtension->OpenHandleCount);
+
+    // the device is idle if it has no open handles or pending PnP Irps
+    // since we just received an open handle request, cancel idle req.
+    if (deviceExtension->SSEnable)
+        CancelSelectSuspend(deviceExtension);
+
+FreeBT_DispatchCreate_Exit:
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FreeBT_DispatchCreate: Leaving\n"));
+    return ntStatus;
+
+}
+
+// Dispatch routine for CloseHandle
+NTSTATUS FreeBT_DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    NTSTATUS               ntStatus;
+    PFILE_OBJECT           fileObject;
+    PDEVICE_EXTENSION      deviceExtension;
+    PIO_STACK_LOCATION     irpStack;
+    PFREEBT_PIPE_CONTEXT  pipeContext;
+    PUSBD_PIPE_INFORMATION pipeInformation;
+
+    PAGED_CODE();
+
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    fileObject = irpStack->FileObject;
+    pipeContext = NULL;
+    pipeInformation = NULL;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    FreeBT_DbgPrint(3, ("FreeBT_DispatchClose: Entered\n"));
+
+    ntStatus = STATUS_SUCCESS;
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    InterlockedDecrement(&deviceExtension->OpenHandleCount);
+
+    FreeBT_DbgPrint(3, ("FreeBT_DispatchClose: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+// Called when a HCI Send on the control pipe completes
+NTSTATUS FreeBT_HCISendCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    ULONG               stageLength;
+    NTSTATUS            ntStatus;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_HCISendCompletion, status=0x%08X\n", Irp->IoStatus.Status));
+
+       if (Irp->PendingReturned)
+               IoMarkIrpPending(Irp);
+
+    ExFreePool(Context);
+       FreeBT_IoDecrement(DeviceObject->DeviceExtension);
+    ntStatus = Irp->IoStatus.Status;
+    Irp->IoStatus.Information = 0;
+
+    return ntStatus;
+
+}
+
+// Called the DeviceIOControl handler to send an HCI command received from the user
+// HCI Commands are sent on the (default) control pipe
+NTSTATUS FreeBT_SendHCICommand(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID IoBuffer, IN ULONG InputBufferLength)
+{
+       PDEVICE_EXTENSION       deviceExtension;
+    ULONG                              urbFlags;
+       ULONG                           stageLength;
+       PVOID                           pBuffer;
+       PURB                            urb;
+       NTSTATUS                        ntStatus;
+    PIO_STACK_LOCATION nextStack;
+       //PFBT_HCI_CMD_HEADER   pHCICommand;
+       //LARGE_INTEGER         delay;
+
+       deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+       if (!deviceExtension)
+       {
+               ntStatus=STATUS_INVALID_PARAMETER;
+               FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Failed to get DeviceExtension\n"));
+               Irp->IoStatus.Status = ntStatus;
+               Irp->IoStatus.Information = 0;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+               return ntStatus;
+
+       }
+
+       // The user is doing a reset, reset all the pipes as well, so that any
+       // old events or data are removed
+       /*pHCICommand=(PFBT_HCI_CMD_HEADER)IoBuffer;
+       if (pHCICommand->OpCode==FBT_HCI_CMD_RESET)
+       {
+               FreeBT_ResetPipe(DeviceObject, deviceExtension->EventPipe.PipeHandle);
+               FreeBT_ResetPipe(DeviceObject, deviceExtension->DataInPipe.PipeHandle);
+               FreeBT_ResetPipe(DeviceObject, deviceExtension->DataOutPipe.PipeHandle);
+               FreeBT_ResetPipe(DeviceObject, deviceExtension->AudioInPipe.PipeHandle);
+               FreeBT_ResetPipe(DeviceObject, deviceExtension->AudioOutPipe.PipeHandle);
+
+               // Wait a second for the device to recover
+               FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Sleeping\n"));
+               delay.QuadPart = -10000 * 5000; // 5s
+        KeWaitForSingleObject(&deviceExtension->DelayEvent,
+                              Executive,
+                              UserMode,
+                              FALSE,
+                              &delay);
+
+               FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Finished sleeping\n"));
+
+
+       }*/
+
+       // Create the URB
+    urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+    if(urb == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Failed to alloc mem for urb\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+               Irp->IoStatus.Status = ntStatus;
+               Irp->IoStatus.Information = 0;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+               return ntStatus;
+
+    }
+
+       UsbBuildVendorRequest(
+               urb,
+               URB_FUNCTION_CLASS_DEVICE, // This works, for CSR and Silicon Wave
+               sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
+               0,
+               0,
+               0,
+               0,
+               0,
+               IoBuffer,
+               NULL,
+               InputBufferLength,
+               NULL);
+
+    // use the original irp as an internal device control irp
+    nextStack = IoGetNextIrpStackLocation(Irp);
+    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+    nextStack->Parameters.Others.Argument1 = (PVOID) urb;
+    nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+
+    IoSetCompletionRoutine(
+               Irp,
+               (PIO_COMPLETION_ROUTINE)FreeBT_HCISendCompletion,
+               urb,
+               TRUE,
+               TRUE,
+               TRUE);
+
+    // We return STATUS_PENDING; call IoMarkIrpPending.
+    IoMarkIrpPending(Irp);
+
+       FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+       FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: Sending IRP %X to underlying driver\n", Irp));
+    ntStatus=IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    if(!NT_SUCCESS(ntStatus))
+    {
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: IoCallDriver fails with status %X\n", ntStatus));
+
+               FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand::"));
+               FreeBT_IoDecrement(deviceExtension);
+
+        // If the device was surprise removed out, the pipeInformation field is invalid.
+        // similarly if the request was cancelled, then we need not reset the device.
+        if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
+                       ntStatus = FreeBT_ResetDevice(DeviceObject);
+
+        else
+            FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
+
+               Irp->IoStatus.Status = ntStatus;
+               Irp->IoStatus.Information = 0;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+               return ntStatus;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: Completed successfully\n"));
+
+    return STATUS_PENDING;
+
+}
+
+// Called when a HCI Get on the event pipe completes
+NTSTATUS FreeBT_HCIEventCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    ULONG               stageLength;
+    NTSTATUS            ntStatus;
+    PIO_STACK_LOCATION  nextStack;
+    PURB                               urb;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_HCIEventCompletion, status=0x%08X\n", Irp->IoStatus.Status));
+
+       if (Irp->PendingReturned)
+               IoMarkIrpPending(Irp);
+
+    // initialize variables
+       urb=(PURB)Context;
+    ntStatus = Irp->IoStatus.Status;
+    Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+    nextStack = IoGetNextIrpStackLocation(Irp);
+
+    ExFreePool(Context);
+       FreeBT_IoDecrement(DeviceObject->DeviceExtension);
+
+    return ntStatus;
+
+}
+
+// Called from the DeviceIOControl handler to wait for an event on the interrupt pipe
+NTSTATUS FreeBT_GetHCIEvent(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID IoBuffer, IN ULONG InputBufferLength)
+{
+       PDEVICE_EXTENSION       deviceExtension;
+       PURB                            urb;
+       NTSTATUS                        ntStatus;
+    PIO_STACK_LOCATION nextStack;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: Entered\n"));
+
+    urb = NULL;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
+    if (urb==NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_GetHCIEvent: Failed to alloc mem for urb\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        goto FreeBT_GetHCIEvent_Exit;
+
+    }
+
+    UsbBuildInterruptOrBulkTransferRequest(
+                            urb,
+                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+                            deviceExtension->EventPipe.PipeHandle,
+                            IoBuffer,
+                            NULL,
+                            InputBufferLength,
+                            USBD_SHORT_TRANSFER_OK|USBD_TRANSFER_DIRECTION_IN,
+                            NULL);
+
+    // use the original irp as an internal device control irp, which we send down to the
+    // USB class driver in order to get our request out on the wire
+    nextStack = IoGetNextIrpStackLocation(Irp);
+    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+    nextStack->Parameters.Others.Argument1 = (PVOID) urb;
+    nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+
+    IoSetCompletionRoutine(
+               Irp,
+               (PIO_COMPLETION_ROUTINE)FreeBT_HCIEventCompletion,
+               urb,
+               TRUE,
+               TRUE,
+               TRUE);
+
+    // We return STATUS_PENDING; call IoMarkIrpPending.
+    IoMarkIrpPending(Irp);
+
+       FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    if (!NT_SUCCESS(ntStatus))
+    {
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: IoCallDriver fails with status %X\n", ntStatus));
+
+               FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent::"));
+               FreeBT_IoDecrement(deviceExtension);
+
+        // If the device was surprise removed out, the pipeInformation field is invalid.
+        // similarly if the request was cancelled, then we need not reset the pipe.
+        if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
+        {
+            ntStatus = FreeBT_ResetPipe(DeviceObject, deviceExtension->EventPipe.PipeHandle);
+            if(!NT_SUCCESS(ntStatus))
+            {
+                FreeBT_DbgPrint(1, ("FreeBT_ResetPipe failed\n"));
+                ntStatus = FreeBT_ResetDevice(DeviceObject);
+
+            }
+
+        }
+
+        else
+        {
+            FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
+
+        }
+
+        goto FreeBT_GetHCIEvent_Exit;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: Leaving\n"));
+
+    // Return STATUS_PENDING, when the lower driver completes the request,
+    // the FreeBT_HCIEventCompletion completion routine.
+    return STATUS_PENDING;
+
+FreeBT_GetHCIEvent_Exit:
+    Irp->IoStatus.Status=ntStatus;
+    Irp->IoStatus.Information=0;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: Failure (0x%08x), completing IRP\n", ntStatus));
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return ntStatus;
+
+}
+
+// DeviceIOControl dispatch
+NTSTATUS FreeBT_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    ULONG              code;
+    PVOID              ioBuffer;
+    ULONG              inputBufferLength;
+    ULONG              outputBufferLength;
+    ULONG              info;
+    NTSTATUS           ntStatus;
+    PDEVICE_EXTENSION  deviceExtension;
+    PIO_STACK_LOCATION irpStack;
+
+    info = 0;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    code = irpStack->Parameters.DeviceIoControl.IoControlCode;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
+    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
+    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
+
+    if (deviceExtension->DeviceState != Working)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: Invalid device state\n"));
+               ntStatus = STATUS_INVALID_DEVICE_STATE;
+               goto FreeBT_DispatchDevCtrlExit;
+
+       }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchDevCtrl::"));
+
+    // Make sure that any selective suspend request has been completed.
+    if (deviceExtension->SSEnable)
+    {
+           FreeBT_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
+        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+
+    }
+
+    switch(code)
+    {
+       case IOCTL_FREEBT_HCI_SEND_CMD:
+               FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_SEND_CMD received\n"));
+               if (inputBufferLength<FBT_HCI_CMD_MIN_SIZE)
+               {
+                       ntStatus = STATUS_BUFFER_TOO_SMALL;
+                       FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_SEND_CMD: Buffer too small\n"));
+                       goto FreeBT_DispatchDevCtrlExit;
+
+               }
+
+               if (inputBufferLength>FBT_HCI_CMD_MAX_SIZE)
+               {
+                       ntStatus = STATUS_INVALID_BUFFER_SIZE;
+                       FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_SEND_CMD: Buffer too long\n"));
+                       goto FreeBT_DispatchDevCtrlExit;
+
+               }
+
+               return FreeBT_SendHCICommand(DeviceObject, Irp, ioBuffer, inputBufferLength);
+               break;
+
+       case IOCTL_FREEBT_HCI_GET_EVENT:
+               FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_GET_EVENT received\n"));
+               if (outputBufferLength<FBT_HCI_EVENT_MAX_SIZE)
+               {
+                       ntStatus = STATUS_BUFFER_TOO_SMALL;
+                       FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_GET_EVENT: Buffer too small\n"));
+                       goto FreeBT_DispatchDevCtrlExit;
+
+               }
+
+               return FreeBT_GetHCIEvent(DeviceObject, Irp, ioBuffer, outputBufferLength);
+               break;
+
+    default:
+       FreeBT_DbgPrint(3, ("FBTUSB: Invalid IOCTL 0x%08x received\n", code));
+        ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+        break;
+
+    }
+
+FreeBT_DispatchDevCtrlExit:
+       Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = ntStatus;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return ntStatus;
+}
+
+// Submit URB_FUNCTION_RESET_PIPE
+NTSTATUS FreeBT_ResetPipe(IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE PipeHandle)
+{
+    PURB              urb;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    urb = NULL;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
+    if (urb)
+    {
+        urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
+        urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
+        urb->UrbPipeRequest.PipeHandle = PipeHandle;
+
+        ntStatus = CallUSBD(DeviceObject, urb);
+
+        ExFreePool(urb);
+
+    }
+
+    else
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+    if(NT_SUCCESS(ntStatus))
+    {
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ResetPipe - success\n"));
+        ntStatus = STATUS_SUCCESS;
+
+    }
+
+    else
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_ResetPipe - failed\n"));
+
+    return ntStatus;
+
+}
+
+// Call FreeBT_ResetParentPort to reset the device
+NTSTATUS FreeBT_ResetDevice(IN PDEVICE_OBJECT DeviceObject)
+{
+    NTSTATUS ntStatus;
+    ULONG    portStatus;
+
+    FreeBT_DbgPrint(3, ("FreeBT_ResetDevice: Entered\n"));
+
+    ntStatus = FreeBT_GetPortStatus(DeviceObject, &portStatus);
+
+    if ( (NT_SUCCESS(ntStatus)) && (!(portStatus & USBD_PORT_ENABLED)) && (portStatus & USBD_PORT_CONNECTED))
+        ntStatus=FreeBT_ResetParentPort(DeviceObject);
+
+    FreeBT_DbgPrint(3, ("FreeBT_ResetDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+// Read port status from the lower driver (USB class driver)
+NTSTATUS FreeBT_GetPortStatus(IN PDEVICE_OBJECT DeviceObject, IN OUT PULONG PortStatus)
+{
+    NTSTATUS           ntStatus;
+    KEVENT             event;
+    PIRP               irp;
+    IO_STATUS_BLOCK    ioStatus;
+    PIO_STACK_LOCATION nextStack;
+    PDEVICE_EXTENSION  deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FreeBT_GetPortStatus: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    *PortStatus = 0;
+
+    KeInitializeEvent(&event, NotificationEvent, FALSE);
+    irp = IoBuildDeviceIoControlRequest(
+                    IOCTL_INTERNAL_USB_GET_PORT_STATUS,
+                    deviceExtension->TopOfStackDeviceObject,
+                    NULL,
+                    0,
+                    NULL,
+                    0,
+                    TRUE,
+                    &event,
+                    &ioStatus);
+
+    if (NULL == irp)
+    {
+        FreeBT_DbgPrint(1, ("memory alloc for irp failed\n"));
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    nextStack = IoGetNextIrpStackLocation(irp);
+    ASSERT(nextStack != NULL);
+    nextStack->Parameters.Others.Argument1 = PortStatus;
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
+    if (STATUS_PENDING==ntStatus)
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+
+    else
+        ioStatus.Status = ntStatus;
+
+    ntStatus = ioStatus.Status;
+    FreeBT_DbgPrint(3, ("FreeBT_GetPortStatus: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+// Sends an IOCTL_INTERNAL_USB_RESET_PORT via the lower driver
+NTSTATUS FreeBT_ResetParentPort(IN PDEVICE_OBJECT DeviceObject)
+{
+    NTSTATUS           ntStatus;
+    KEVENT             event;
+    PIRP               irp;
+    IO_STATUS_BLOCK    ioStatus;
+    PIO_STACK_LOCATION nextStack;
+    PDEVICE_EXTENSION  deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FreeBT_ResetParentPort: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    KeInitializeEvent(&event, NotificationEvent, FALSE);
+    irp = IoBuildDeviceIoControlRequest(
+                    IOCTL_INTERNAL_USB_RESET_PORT,
+                    deviceExtension->TopOfStackDeviceObject,
+                    NULL,
+                    0,
+                    NULL,
+                    0,
+                    TRUE,
+                    &event,
+                    &ioStatus);
+
+    if (NULL == irp)
+    {
+        FreeBT_DbgPrint(1, ("memory alloc for irp failed\n"));
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    nextStack = IoGetNextIrpStackLocation(irp);
+    ASSERT(nextStack != NULL);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
+    if(STATUS_PENDING == ntStatus)
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+
+    else
+        ioStatus.Status = ntStatus;
+
+
+    ntStatus = ioStatus.Status;
+
+    FreeBT_DbgPrint(3, ("FreeBT_ResetParentPort: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+// Send an idle request to the lower driver
+NTSTATUS SubmitIdleRequestIrp(IN PDEVICE_EXTENSION DeviceExtension)
+{
+    PIRP                    irp;
+    NTSTATUS                ntStatus;
+    KIRQL                   oldIrql;
+    PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
+    PIO_STACK_LOCATION      nextStack;
+
+    FreeBT_DbgPrint(3, ("SubmitIdleRequest: Entered\n"));
+
+    irp = NULL;
+    idleCallbackInfo = NULL;
+
+    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+    if(PowerDeviceD0 != DeviceExtension->DevPower) {
+
+        ntStatus = STATUS_POWER_STATE_INVALID;
+
+        goto SubmitIdleRequestIrp_Exit;
+    }
+
+    KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
+
+    if(InterlockedExchange(&DeviceExtension->IdleReqPend, 1)) {
+
+        FreeBT_DbgPrint(1, ("Idle request pending..\n"));
+
+        KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+        ntStatus = STATUS_DEVICE_BUSY;
+
+        goto SubmitIdleRequestIrp_Exit;
+    }
+
+    //
+    // clear the NoIdleReqPendEvent because we are about
+    // to submit an idle request. Since we are so early
+    // to clear this event, make sure that if we fail this
+    // request we set back the event.
+    //
+    KeClearEvent(&DeviceExtension->NoIdleReqPendEvent);
+
+    idleCallbackInfo = (PUSB_IDLE_CALLBACK_INFO)ExAllocatePool(NonPagedPool, sizeof(struct _USB_IDLE_CALLBACK_INFO));
+
+    if(idleCallbackInfo) {
+
+        idleCallbackInfo->IdleCallback = (USB_IDLE_CALLBACK)IdleNotificationCallback;
+
+        idleCallbackInfo->IdleContext = (PVOID)DeviceExtension;
+
+        ASSERT(DeviceExtension->IdleCallbackInfo == NULL);
+
+        DeviceExtension->IdleCallbackInfo = idleCallbackInfo;
+
+        //
+        // we use IoAllocateIrp to create an irp to selectively suspend the
+        // device. This irp lies pending with the hub driver. When appropriate
+        // the hub driver will invoked callback, where we power down. The completion
+        // routine is invoked when we power back.
+        //
+        irp = IoAllocateIrp(DeviceExtension->TopOfStackDeviceObject->StackSize,
+                            FALSE);
+
+        if(irp == NULL) {
+
+            FreeBT_DbgPrint(1, ("cannot build idle request irp\n"));
+
+            KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
+                       IO_NO_INCREMENT,
+                       FALSE);
+
+            InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
+
+            KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+            ExFreePool(idleCallbackInfo);
+
+            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+            goto SubmitIdleRequestIrp_Exit;
+        }
+
+        nextStack = IoGetNextIrpStackLocation(irp);
+
+        nextStack->MajorFunction =
+                    IRP_MJ_INTERNAL_DEVICE_CONTROL;
+
+        nextStack->Parameters.DeviceIoControl.IoControlCode =
+                    IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;
+
+        nextStack->Parameters.DeviceIoControl.Type3InputBuffer =
+                    idleCallbackInfo;
+
+        nextStack->Parameters.DeviceIoControl.InputBufferLength =
+                    sizeof(struct _USB_IDLE_CALLBACK_INFO);
+
+
+        IoSetCompletionRoutine(irp,
+                               (PIO_COMPLETION_ROUTINE)IdleNotificationRequestComplete,
+                               DeviceExtension,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+        DeviceExtension->PendingIdleIrp = irp;
+
+        //
+        // we initialize the count to 2.
+        // The reason is, if the CancelSelectSuspend routine manages
+        // to grab the irp from the device extension, then the last of the
+        // CancelSelectSuspend routine/IdleNotificationRequestComplete routine
+        // to execute will free this irp. We need to have this schema so that
+        // 1. completion routine does not attempt to touch the irp freed by
+        //    CancelSelectSuspend routine.
+        // 2. CancelSelectSuspend routine doesnt wait for ever for the completion
+        //    routine to complete!
+        //
+        DeviceExtension->FreeIdleIrpCount = 2;
+
+        KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+        //
+        // check if the device is idle.
+        // A check here ensures that a race condition did not
+        // completely reverse the call sequence of SubmitIdleRequestIrp
+        // and CancelSelectiveSuspend
+        //
+
+        if(!CanDeviceSuspend(DeviceExtension) ||
+           PowerDeviceD0 != DeviceExtension->DevPower) {
+
+            //
+            // IRPs created using IoBuildDeviceIoControlRequest should be
+            // completed by calling IoCompleteRequest and not merely
+            // deallocated.
+            //
+
+            FreeBT_DbgPrint(1, ("Device is not idle\n"));
+
+            KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
+
+            DeviceExtension->IdleCallbackInfo = NULL;
+
+            DeviceExtension->PendingIdleIrp = NULL;
+
+            KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
+                       IO_NO_INCREMENT,
+                       FALSE);
+
+            InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
+
+            KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+            if(idleCallbackInfo) {
+
+                ExFreePool(idleCallbackInfo);
+            }
+
+            //
+            // it is still safe to touch the local variable "irp" here.
+            // the irp has not been passed down the stack, the irp has
+            // no cancellation routine. The worse position is that the
+            // CancelSelectSuspend has run after we released the spin
+            // lock above. It is still essential to free the irp.
+            //
+            if(irp) {
+
+                IoFreeIrp(irp);
+            }
+
+            ntStatus = STATUS_UNSUCCESSFUL;
+
+            goto SubmitIdleRequestIrp_Exit;
+        }
+
+        FreeBT_DbgPrint(3, ("Cancel the timers\n"));
+        //
+        // Cancel the timer so that the DPCs are no longer fired.
+        // Thus, we are making judicious usage of our resources.
+        // we do not need DPCs because we already have an idle irp pending.
+        // The timers are re-initialized in the completion routine.
+        //
+        KeCancelTimer(&DeviceExtension->Timer);
+
+        ntStatus = IoCallDriver(DeviceExtension->TopOfStackDeviceObject, irp);
+
+        if(!NT_SUCCESS(ntStatus)) {
+
+            FreeBT_DbgPrint(1, ("IoCallDriver failed\n"));
+
+            goto SubmitIdleRequestIrp_Exit;
+        }
+    }
+    else {
+
+        FreeBT_DbgPrint(1, ("Memory allocation for idleCallbackInfo failed\n"));
+
+        KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
+                   IO_NO_INCREMENT,
+                   FALSE);
+
+        InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
+
+        KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+SubmitIdleRequestIrp_Exit:
+
+    FreeBT_DbgPrint(3, ("SubmitIdleRequest: Leaving\n"));
+
+    return ntStatus;
+}
+
+
+VOID IdleNotificationCallback(IN PDEVICE_EXTENSION DeviceExtension)
+{
+    NTSTATUS                ntStatus;
+    POWER_STATE             powerState;
+    KEVENT                  irpCompletionEvent;
+    PIRP_COMPLETION_CONTEXT irpContext;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback: Entered\n"));
+
+    //
+    // Dont idle, if the device was just disconnected or being stopped
+    // i.e. return for the following DeviceState(s)
+    // NotStarted, Stopped, PendingStop, PendingRemove, SurpriseRemoved, Removed
+    //
+
+    if(DeviceExtension->DeviceState != Working) {
+
+        return;
+    }
+
+    //
+    // If there is not already a WW IRP pending, submit one now
+    //
+    if(DeviceExtension->WaitWakeEnable) {
+
+        IssueWaitWake(DeviceExtension);
+    }
+
+
+    //
+    // power down the device
+    //
+
+    irpContext = (PIRP_COMPLETION_CONTEXT)
+                 ExAllocatePool(NonPagedPool,
+                                sizeof(IRP_COMPLETION_CONTEXT));
+
+    if(!irpContext) {
+
+        FreeBT_DbgPrint(1, ("FBTUSB: IdleNotificationCallback: Failed to alloc memory for irpContext\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+    }
+    else {
+
+        //
+        // increment the count. In the HoldIoRequestWorkerRoutine, the
+        // count is decremented twice (one for the system Irp and the
+        // other for the device Irp. An increment here compensates for
+        // the sytem irp..The decrement corresponding to this increment
+        // is in the completion function
+        //
+
+        FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback::"));
+        FreeBT_IoIncrement(DeviceExtension);
+
+        powerState.DeviceState = (DEVICE_POWER_STATE) DeviceExtension->PowerDownLevel;
+
+        KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE);
+
+        irpContext->DeviceExtension = DeviceExtension;
+        irpContext->Event = &irpCompletionEvent;
+
+        ntStatus = PoRequestPowerIrp(
+                          DeviceExtension->PhysicalDeviceObject,
+                          IRP_MN_SET_POWER,
+                          powerState,
+                          (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc,
+                          irpContext,
+                          NULL);
+
+        if(STATUS_PENDING == ntStatus) {
+
+            FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback::"
+                           "waiting for the power irp to complete\n"));
+
+            KeWaitForSingleObject(&irpCompletionEvent,
+                                  Executive,
+                                  KernelMode,
+                                  FALSE,
+                                  NULL);
+        }
+    }
+
+    if(!NT_SUCCESS(ntStatus)) {
+
+        if(irpContext) {
+
+            ExFreePool(irpContext);
+        }
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback: Leaving\n"));
+}
+
+
+NTSTATUS IdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
+{
+    NTSTATUS                ntStatus;
+    POWER_STATE             powerState;
+    KIRQL                   oldIrql;
+    LARGE_INTEGER           dueTime;
+    PIRP                    idleIrp;
+    PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationRequestCompete: Entered\n"));
+
+    idleIrp = NULL;
+
+    ntStatus = Irp->IoStatus.Status;
+    if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED)
+    {
+        FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationRequestCompete: Idle irp completes with error::"));
+        switch(ntStatus)
+        {
+        case STATUS_INVALID_DEVICE_REQUEST:
+            FreeBT_DbgPrint(3, ("STATUS_INVALID_DEVICE_REQUEST\n"));
+            break;
+
+        case STATUS_CANCELLED:
+            FreeBT_DbgPrint(3, ("STATUS_CANCELLED\n"));
+            break;
+
+        case STATUS_DEVICE_BUSY:
+            FreeBT_DbgPrint(3, ("STATUS_DEVICE_BUSY\n"));
+            break;
+
+        case STATUS_POWER_STATE_INVALID:
+            FreeBT_DbgPrint(3, ("STATUS_POWER_STATE_INVALID\n"));
+            goto IdleNotificationRequestComplete_Exit;
+
+        default:
+            FreeBT_DbgPrint(3, ("default: status = %X\n", ntStatus));
+            break;
+
+        }
+
+        // if in error, issue a SetD0
+        FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationRequestComplete::"));
+        FreeBT_IoIncrement(DeviceExtension);
+
+        powerState.DeviceState = PowerDeviceD0;
+        ntStatus = PoRequestPowerIrp(
+                          DeviceExtension->PhysicalDeviceObject,
+                          IRP_MN_SET_POWER,
+                          powerState,
+                          (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc,
+                          DeviceExtension,
+                          NULL);
+
+        if(!NT_SUCCESS(ntStatus))
+            FreeBT_DbgPrint(1, ("PoRequestPowerIrp failed\n"));
+
+    }
+
+IdleNotificationRequestComplete_Exit:
+    KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
+    idleCallbackInfo = DeviceExtension->IdleCallbackInfo;
+    DeviceExtension->IdleCallbackInfo = NULL;
+
+    idleIrp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL);
+    InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
+
+    KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+    if(idleCallbackInfo)
+        ExFreePool(idleCallbackInfo);
+
+    // Since the irp was created using IoAllocateIrp,
+    // the Irp needs to be freed using IoFreeIrp.
+    // Also return STATUS_MORE_PROCESSING_REQUIRED so that
+    // the kernel does not reference this in the near future.
+    if(idleIrp)
+    {
+        FreeBT_DbgPrint(3, ("completion routine has a valid irp and frees it\n"));
+        IoFreeIrp(Irp);
+        KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
+
+    }
+
+    else
+    {
+        // The CancelSelectiveSuspend routine has grabbed the Irp from the device
+        // extension. Now the last one to decrement the FreeIdleIrpCount should
+        // free the irp.
+        if (0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount))
+        {
+            FreeBT_DbgPrint(3, ("completion routine frees the irp\n"));
+            IoFreeIrp(Irp);
+            KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
+
+        }
+
+    }
+
+    if(DeviceExtension->SSEnable)
+    {
+        FreeBT_DbgPrint(3, ("Set the timer to fire DPCs\n"));
+        dueTime.QuadPart = -10000 * IDLE_INTERVAL;               // 5000 ms
+        KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, &DeviceExtension->DeferredProcCall);
+        FreeBT_DbgPrint(3, ("IdleNotificationRequestCompete: Leaving\n"));
+
+    }
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+}
+
+VOID CancelSelectSuspend(IN PDEVICE_EXTENSION DeviceExtension)
+{
+    PIRP  irp;
+    KIRQL oldIrql;
+
+    FreeBT_DbgPrint(3, ("CancelSelectSuspend: Entered\n"));
+
+    irp = NULL;
+
+    KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
+
+    if(!CanDeviceSuspend(DeviceExtension))
+    {
+        FreeBT_DbgPrint(3, ("Device is not idle\n"));
+        irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL);
+
+    }
+
+    KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
+
+    // since we have a valid Irp ptr,
+    // we can call IoCancelIrp on it,
+    // without the fear of the irp
+    // being freed underneath us.
+    if(irp)
+    {
+        // This routine has the irp pointer.
+        // It is safe to call IoCancelIrp because we know that
+        // the compleiton routine will not free this irp unless...
+        //
+        //
+        if(IoCancelIrp(irp))
+        {
+            FreeBT_DbgPrint(3, ("IoCancelIrp returns TRUE\n"));
+
+               }
+
+        else
+        {
+            FreeBT_DbgPrint(3, ("IoCancelIrp returns FALSE\n"));
+
+               }
+
+        // ....we decrement the FreeIdleIrpCount from 2 to 1.
+        // if completion routine runs ahead of us, then this routine
+        // decrements the FreeIdleIrpCount from 1 to 0 and hence shall
+        // free the irp.
+        if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount))
+        {
+            FreeBT_DbgPrint(3, ("CancelSelectSuspend frees the irp\n"));
+            IoFreeIrp(irp);
+            KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("CancelSelectSuspend: Leaving\n"));
+
+    return;
+
+}
+
+VOID PoIrpCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
+{
+    PIRP_COMPLETION_CONTEXT irpContext;
+    irpContext = NULL;
+
+    FreeBT_DbgPrint(3, ("PoIrpCompletionFunc::"));
+
+    if(Context)
+        irpContext = (PIRP_COMPLETION_CONTEXT) Context;
+
+    // all we do is set the event and decrement the count
+    if(irpContext)
+    {
+        KeSetEvent(irpContext->Event, 0, FALSE);
+       FreeBT_IoDecrement(irpContext->DeviceExtension);
+        ExFreePool(irpContext);
+
+    }
+
+    return;
+
+}
+
+VOID PoIrpAsyncCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
+{
+    PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context;
+    FreeBT_DbgPrint(3, ("PoIrpAsyncCompletionFunc::"));
+    FreeBT_IoDecrement(DeviceExtension);
+
+    return;
+
+}
+
+VOID WWIrpCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
+{
+    PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context;
+
+    FreeBT_DbgPrint(3, ("WWIrpCompletionFunc::"));
+    FreeBT_IoDecrement(DeviceExtension);
+
+    return;
+
+}
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtpnp.c b/reactos/drivers/bluetooth/fbtusb/fbtpnp.c
new file mode 100755 (executable)
index 0000000..4589ebf
--- /dev/null
@@ -0,0 +1,1910 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#include "stdio.h"
+#include "fbtusb.h"
+#include "fbtpnp.h"
+#include "fbtpwr.h"
+#include "fbtdev.h"
+#include "fbtrwr.h"
+#include "fbtwmi.h"
+
+#include "fbtusr.h"
+
+// Handle PNP events
+NTSTATUS FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    PIO_STACK_LOCATION irpStack;
+    PDEVICE_EXTENSION  deviceExtension;
+    KEVENT             startDeviceEvent;
+    NTSTATUS           ntStatus;
+
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // since the device is removed, fail the Irp.
+    if (Removed == deviceExtension->DeviceState)
+       {
+        ntStatus = STATUS_DELETE_PENDING;
+        Irp->IoStatus.Status = ntStatus;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return ntStatus;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
+    FreeBT_IoIncrement(deviceExtension);
+    if (irpStack->MinorFunction == IRP_MN_START_DEVICE)
+       {
+        ASSERT(deviceExtension->IdleReqPend == 0);
+
+    }
+
+    else
+       {
+        if (deviceExtension->SSEnable)
+               {
+            CancelSelectSuspend(deviceExtension);
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: ///////////////////////////////////////////\n"));
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
+    FreeBT_DbgPrint(2, (PnPMinorFunctionString(irpStack->MinorFunction)));
+    switch (irpStack->MinorFunction)
+       {
+    case IRP_MN_START_DEVICE:
+        ntStatus = HandleStartDevice(DeviceObject, Irp);
+        break;
+
+    case IRP_MN_QUERY_STOP_DEVICE:
+        // if we cannot stop the device, we fail the query stop irp
+        ntStatus = CanStopDevice(DeviceObject, Irp);
+        if(NT_SUCCESS(ntStatus))
+               {
+            ntStatus = HandleQueryStopDevice(DeviceObject, Irp);
+            return ntStatus;
+
+        }
+
+        break;
+
+    case IRP_MN_CANCEL_STOP_DEVICE:
+        ntStatus = HandleCancelStopDevice(DeviceObject, Irp);
+        break;
+
+    case IRP_MN_STOP_DEVICE:
+        ntStatus = HandleStopDevice(DeviceObject, Irp);
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::IRP_MN_STOP_DEVICE::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        return ntStatus;
+
+    case IRP_MN_QUERY_REMOVE_DEVICE:
+        // if we cannot remove the device, we fail the query remove irp
+        ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
+
+        return ntStatus;
+
+    case IRP_MN_CANCEL_REMOVE_DEVICE:
+        ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
+        break;
+
+    case IRP_MN_SURPRISE_REMOVAL:
+        ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
+        FreeBT_IoDecrement(deviceExtension);
+        return ntStatus;
+
+    case IRP_MN_REMOVE_DEVICE:
+        ntStatus = HandleRemoveDevice(DeviceObject, Irp);
+        return ntStatus;
+
+    case IRP_MN_QUERY_CAPABILITIES:
+        ntStatus = HandleQueryCapabilities(DeviceObject, Irp);
+        break;
+
+    default:
+        IoSkipCurrentIrpStackLocation(Irp);
+
+        ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::default::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        return ntStatus;
+
+    }
+
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    KEVENT            startDeviceEvent;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+    LARGE_INTEGER     dueTime;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    deviceExtension->UsbConfigurationDescriptor = NULL;
+    deviceExtension->UsbInterface = NULL;
+    deviceExtension->PipeContext = NULL;
+
+    // We cannot touch the device (send it any non pnp irps) until a
+    // start device has been passed down to the lower drivers.
+    // first pass the Irp down
+    KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
+                           (PVOID)&startDeviceEvent,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    if (ntStatus == STATUS_PENDING)
+       {
+        KeWaitForSingleObject(&startDeviceEvent, Executive, KernelMode, FALSE, NULL);
+        ntStatus = Irp->IoStatus.Status;
+
+    }
+
+    if (!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: Lower drivers failed this Irp (0x%08x)\n", ntStatus));
+        return ntStatus;
+
+    }
+
+    // Read the device descriptor, configuration descriptor
+    // and select the interface descriptors
+    ntStatus = ReadandSelectDescriptors(DeviceObject);
+    if (!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: ReadandSelectDescriptors failed (0x%08x)\n", ntStatus));
+        return ntStatus;
+
+    }
+
+    // enable the symbolic links for system components to open
+    // handles to the device
+    ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, TRUE);
+    if (!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: IoSetDeviceInterfaceState failed (0x%08x)\n", ntStatus));
+        return ntStatus;
+
+    }
+
+    KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+
+    SET_NEW_PNP_STATE(deviceExtension, Working);
+    deviceExtension->QueueState = AllowRequests;
+
+    KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+    deviceExtension->FlagWWOutstanding = 0;
+    deviceExtension->FlagWWCancel = 0;
+    deviceExtension->WaitWakeIrp = NULL;
+
+    if (deviceExtension->WaitWakeEnable)
+       {
+        IssueWaitWake(deviceExtension);
+
+    }
+
+    ProcessQueuedRequests(deviceExtension);
+    if (WinXpOrBetter == deviceExtension->WdmVersion)
+       {
+        deviceExtension->SSEnable = deviceExtension->SSRegistryEnable;
+
+        // set timer.for selective suspend requests
+        if (deviceExtension->SSEnable)
+               {
+            dueTime.QuadPart = -10000 * IDLE_INTERVAL;               // 5000 ms
+            KeSetTimerEx(&deviceExtension->Timer, dueTime, IDLE_INTERVAL, &deviceExtension->DeferredProcCall);
+            deviceExtension->FreeIdleIrpCount = 0;
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+
+NTSTATUS ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject)
+{
+    PURB                   urb;
+    ULONG                  siz;
+    NTSTATUS               ntStatus;
+    PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
+
+    urb = NULL;
+    deviceDescriptor = NULL;
+
+    // 1. Read the device descriptor
+    urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
+    if(urb)
+       {
+        siz = sizeof(USB_DEVICE_DESCRIPTOR);
+        deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
+        if (deviceDescriptor)
+               {
+            UsbBuildGetDescriptorRequest(
+                    urb,
+                    (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
+                    USB_DEVICE_DESCRIPTOR_TYPE,
+                    0,
+                    0,
+                    deviceDescriptor,
+                    NULL,
+                    siz,
+                    NULL);
+
+            ntStatus = CallUSBD(DeviceObject, urb);
+            if (NT_SUCCESS(ntStatus))
+                       {
+                ASSERT(deviceDescriptor->bNumConfigurations);
+                ntStatus = ConfigureDevice(DeviceObject);
+
+            }
+
+            ExFreePool(urb);
+            ExFreePool(deviceDescriptor);
+
+        }
+
+        else
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for deviceDescriptor"));
+            ExFreePool(urb);
+            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+        }
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for urb"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+
+    return ntStatus;
+
+}
+
+NTSTATUS ConfigureDevice(IN PDEVICE_OBJECT DeviceObject)
+{
+    PURB                          urb;
+    ULONG                         siz;
+    NTSTATUS                      ntStatus;
+    PDEVICE_EXTENSION             deviceExtension;
+    PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
+
+    urb = NULL;
+    configurationDescriptor = NULL;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // Read the first configuration descriptor
+    // This requires two steps:
+    // 1. Read the fixed sized configuration desciptor (CD)
+    // 2. Read the CD with all embedded interface and endpoint descriptors
+    urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
+    if (urb)
+       {
+        siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
+        configurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
+
+        if(configurationDescriptor)
+               {
+            UsbBuildGetDescriptorRequest(
+                    urb,
+                    (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
+                    USB_CONFIGURATION_DESCRIPTOR_TYPE,
+                    0,
+                    0,
+                    configurationDescriptor,
+                    NULL,
+                    sizeof(USB_CONFIGURATION_DESCRIPTOR),
+                    NULL);
+
+            ntStatus = CallUSBD(DeviceObject, urb);
+            if(!NT_SUCCESS(ntStatus))
+                       {
+                FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: UsbBuildGetDescriptorRequest failed\n"));
+                goto ConfigureDevice_Exit;
+
+            }
+
+        }
+
+        else
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate mem for config Descriptor\n"));
+            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+            goto ConfigureDevice_Exit;
+
+        }
+
+        siz = configurationDescriptor->wTotalLength;
+        ExFreePool(configurationDescriptor);
+
+        configurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
+        if (configurationDescriptor)
+               {
+            UsbBuildGetDescriptorRequest(
+                    urb,
+                    (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
+                    USB_CONFIGURATION_DESCRIPTOR_TYPE,
+                    0,
+                    0,
+                    configurationDescriptor,
+                    NULL,
+                    siz,
+                    NULL);
+
+            ntStatus = CallUSBD(DeviceObject, urb);
+            if (!NT_SUCCESS(ntStatus))
+                       {
+                FreeBT_DbgPrint(1,("FBTUSB: ConfigureDevice: Failed to read configuration descriptor"));
+                goto ConfigureDevice_Exit;
+
+            }
+
+        }
+
+        else
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to alloc mem for config Descriptor\n"));
+            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+            goto ConfigureDevice_Exit;
+
+        }
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate memory for urb\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        goto ConfigureDevice_Exit;
+
+    }
+
+    if (configurationDescriptor)
+       {
+        // save a copy of configurationDescriptor in deviceExtension
+        // remember to free it later.
+        deviceExtension->UsbConfigurationDescriptor = configurationDescriptor;
+
+        if (configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
+        {
+            // this configuration supports remote wakeup
+            deviceExtension->WaitWakeEnable = 1;
+
+        }
+
+        else
+        {
+            deviceExtension->WaitWakeEnable = 0;
+
+        }
+
+        ntStatus = SelectInterfaces(DeviceObject, configurationDescriptor);
+
+    }
+
+    else
+       {
+        deviceExtension->UsbConfigurationDescriptor = NULL;
+
+    }
+
+ConfigureDevice_Exit:
+    if (urb)
+       {
+        ExFreePool(urb);
+
+    }
+
+    return ntStatus;
+
+}
+
+NTSTATUS SelectInterfaces(IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
+{
+    LONG                        numberOfInterfaces, interfaceNumber, interfaceindex;
+    ULONG                       i;
+    PURB                        urb;
+    PUCHAR                      pInf;
+    NTSTATUS                    ntStatus;
+    PDEVICE_EXTENSION           deviceExtension;
+    PUSB_INTERFACE_DESCRIPTOR   interfaceDescriptor;
+    PUSBD_INTERFACE_LIST_ENTRY  interfaceList,
+                                tmp;
+    PUSBD_INTERFACE_INFORMATION Interface;
+
+    urb = NULL;
+    Interface = NULL;
+    interfaceDescriptor = NULL;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
+    interfaceindex = interfaceNumber = 0;
+
+    // Parse the configuration descriptor for the interface;
+    tmp = interfaceList = (PUSBD_INTERFACE_LIST_ENTRY)
+               ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
+
+    if (!tmp)
+       {
+
+        FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to allocate mem for interfaceList\n"));
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+
+       FreeBT_DbgPrint(3, ("FBTUSB: -------------\n"));
+       FreeBT_DbgPrint(3, ("FBTUSB: Number of interfaces %d\n", numberOfInterfaces));
+
+    while (interfaceNumber < numberOfInterfaces)
+       {
+        interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
+                                            ConfigurationDescriptor,
+                                            ConfigurationDescriptor,
+                                            interfaceindex,
+                                            0, -1, -1, -1);
+
+        if (interfaceDescriptor)
+               {
+            interfaceList->InterfaceDescriptor = interfaceDescriptor;
+            interfaceList->Interface = NULL;
+            interfaceList++;
+            interfaceNumber++;
+
+        }
+
+        interfaceindex++;
+
+    }
+
+    interfaceList->InterfaceDescriptor = NULL;
+    interfaceList->Interface = NULL;
+    urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
+
+    if (urb)
+       {
+        Interface = &urb->UrbSelectConfiguration.Interface;
+        for (i=0; i<Interface->NumberOfPipes; i++)
+               {
+            // perform pipe initialization here
+            // set the transfer size and any pipe flags we use
+            // USBD sets the rest of the Interface struct members
+            Interface->Pipes[i].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
+
+        }
+
+        ntStatus = CallUSBD(DeviceObject, urb);
+        if (NT_SUCCESS(ntStatus))
+               {
+            // save a copy of interface information in the device extension.
+            deviceExtension->UsbInterface = (PUSBD_INTERFACE_INFORMATION) ExAllocatePool(NonPagedPool, Interface->Length);
+            if (deviceExtension->UsbInterface)
+                       {
+                RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length);
+
+            }
+
+            else
+                       {
+                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+                FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Memory alloc for UsbInterface failed\n"));
+
+            }
+
+            // Dump the interface to the debugger
+            Interface = &urb->UrbSelectConfiguration.Interface;
+
+            FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
+            FreeBT_DbgPrint(3, ("FBTUSB: NumberOfPipes 0x%x\n", Interface->NumberOfPipes));
+            FreeBT_DbgPrint(3, ("FBTUSB: Length 0x%x\n", Interface->Length));
+            FreeBT_DbgPrint(3, ("FBTUSB: Alt Setting 0x%x\n", Interface->AlternateSetting));
+            FreeBT_DbgPrint(3, ("FBTUSB: Interface Number 0x%x\n", Interface->InterfaceNumber));
+            FreeBT_DbgPrint(3, ("FBTUSB: Class, subclass, protocol 0x%x 0x%x 0x%x\n",
+                                 Interface->Class,
+                                 Interface->SubClass,
+                                 Interface->Protocol));
+
+                       if (Interface->Class==FREEBT_USB_STDCLASS && Interface->SubClass==FREEBT_USB_STDSUBCLASS &&
+                               Interface->Protocol==FREEBT_USB_STDPROTOCOL)
+                       {
+                               FreeBT_DbgPrint(3, ("FBTUSB: This is a standard USB Bluetooth device\n"));
+
+                       }
+
+                       else
+                       {
+                               FreeBT_DbgPrint(3, ("FBTUSB: WARNING: This device does not report itself as a standard USB Bluetooth device\n"));
+
+                       }
+
+            // Initialize the PipeContext
+            // Dump the pipe info
+            deviceExtension->PipeContext = (PFREEBT_PIPE_CONTEXT) ExAllocatePool(
+                                                NonPagedPool,
+                                                Interface->NumberOfPipes *
+                                                sizeof(FREEBT_PIPE_CONTEXT));
+
+            if (!deviceExtension->PipeContext)
+                       {
+                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+                FreeBT_DbgPrint(1, ("FBTUSB: Memory alloc for UsbInterface failed\n"));
+
+            }
+
+            else
+                       {
+                               FreeBT_DbgPrint(3, ("FBTUSB: SelectInterfaces: Allocated PipeContext %p\n", deviceExtension->PipeContext));
+                               for (i=0; i<Interface->NumberOfPipes; i++)
+                               {
+                                       deviceExtension->PipeContext[i].PipeOpen = FALSE;
+
+                                       FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
+                                       FreeBT_DbgPrint(3, ("FBTUSB: PipeType 0x%x\n", Interface->Pipes[i].PipeType));
+                                       FreeBT_DbgPrint(3, ("FBTUSB: EndpointAddress 0x%x\n", Interface->Pipes[i].EndpointAddress));
+                                       FreeBT_DbgPrint(3, ("FBTUSB: MaxPacketSize 0x%x\n", Interface->Pipes[i].MaximumPacketSize));
+                                       FreeBT_DbgPrint(3, ("FBTUSB: Interval 0x%x\n", Interface->Pipes[i].Interval));
+                                       FreeBT_DbgPrint(3, ("FBTUSB: Handle 0x%x\n", Interface->Pipes[i].PipeHandle));
+                                       FreeBT_DbgPrint(3, ("FBTUSB: MaximumTransferSize 0x%x\n", Interface->Pipes[i].MaximumTransferSize));
+
+                                       // Log the pipes
+                                       // Note the HCI Command endpoint won't appear here, because the Default Control Pipe
+                                       // is used for this. The Default Control Pipe is always present at EndPointAddress 0x0
+                                       switch (Interface->Pipes[i].EndpointAddress)
+                                       {
+                                               case FREEBT_STDENDPOINT_HCIEVENT:
+                                                       deviceExtension->PipeContext[i].PipeType=HciEventPipe;
+                                                       deviceExtension->EventPipe=Interface->Pipes[i];
+                                                       FreeBT_DbgPrint(3, ("FBTUSB: HCI Event Endpoint\n"));
+                                                       break;
+
+                                               case FREEBT_STDENDPOINT_ACLIN:
+                                                       deviceExtension->PipeContext[i].PipeType=AclDataIn;
+                                                       deviceExtension->DataInPipe=Interface->Pipes[i];
+                                                       FreeBT_DbgPrint(3, ("FBTUSB: ACL Data In Endpoint\n"));
+                                                       break;
+
+                                               case FREEBT_STDENDPOINT_ACLOUT:
+                                                       deviceExtension->PipeContext[i].PipeType=AclDataOut;
+                                                       deviceExtension->DataOutPipe=Interface->Pipes[i];
+                                                       FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
+                                                       break;
+
+                                               case FREEBT_STDENDPOINT_AUDIOIN:
+                                                       deviceExtension->PipeContext[i].PipeType=SCODataIn;
+                                                       deviceExtension->AudioInPipe=Interface->Pipes[i];
+                                                       FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
+                                                       break;
+
+                                               case FREEBT_STDENDPOINT_AUDIOOUT:
+                                                       deviceExtension->PipeContext[i].PipeType=SCODataOut;
+                                                       deviceExtension->AudioOutPipe=Interface->Pipes[i];
+                                                       FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
+                                                       break;
+
+                                       }
+
+                               }
+
+                       }
+
+            FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
+
+        }
+
+        else
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to select an interface\n"));
+
+        }
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: USBD_CreateConfigurationRequestEx failed\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    if (tmp)
+       {
+        ExFreePool(tmp);
+
+    }
+
+    if (urb)
+       {
+        ExFreePool(urb);
+
+    }
+
+    return ntStatus;
+}
+
+
+NTSTATUS DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject)
+{
+    PURB     urb;
+    ULONG    siz;
+    NTSTATUS ntStatus;
+
+    siz = sizeof(struct _URB_SELECT_CONFIGURATION);
+    urb = (PURB) ExAllocatePool(NonPagedPool, siz);
+    if (urb)
+       {
+        UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
+        ntStatus = CallUSBD(DeviceObject, urb);
+        if(!NT_SUCCESS(ntStatus))
+               {
+            FreeBT_DbgPrint(3, ("FBTUSB: DeconfigureDevice: Failed to deconfigure device\n"));
+
+        }
+
+        ExFreePool(urb);
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: DeconfigureDevice: Failed to allocate urb\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    return ntStatus;
+
+}
+
+NTSTATUS CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb)
+{
+    PIRP               irp;
+    KEVENT             event;
+    NTSTATUS           ntStatus;
+    IO_STATUS_BLOCK    ioStatus;
+    PIO_STACK_LOCATION nextStack;
+    PDEVICE_EXTENSION  deviceExtension;
+
+    irp = NULL;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    KeInitializeEvent(&event, NotificationEvent, FALSE);
+    irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
+                                        deviceExtension->TopOfStackDeviceObject,
+                                        NULL,
+                                        0,
+                                        NULL,
+                                        0,
+                                        TRUE,
+                                        &event,
+                                        &ioStatus);
+
+    if (!irp)
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: CallUSBD: IoBuildDeviceIoControlRequest failed\n"));
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    nextStack = IoGetNextIrpStackLocation(irp);
+    ASSERT(nextStack != NULL);
+    nextStack->Parameters.Others.Argument1 = Urb;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
+    if (ntStatus == STATUS_PENDING)
+       {
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        ntStatus = ioStatus.Status;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
+    FreeBT_IoDecrement(deviceExtension);
+    return ntStatus;
+
+}
+
+NTSTATUS HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // If we can stop the device, we need to set the QueueState to
+    // HoldRequests so further requests will be queued.
+    KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+
+    SET_NEW_PNP_STATE(deviceExtension, PendingStop);
+    deviceExtension->QueueState = HoldRequests;
+
+    KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+    // wait for the existing ones to be finished.
+    // first, decrement this operation
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+
+    IoSkipCurrentIrpStackLocation(Irp);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    KEVENT            event;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // Send this IRP down and wait for it to come back.
+    // Set the QueueState flag to AllowRequests,
+    // and process all the previously queued up IRPs.
+
+    // First check to see whether you have received cancel-stop
+    // without first receiving a query-stop. This could happen if someone
+    // above us fails a query-stop and passes down the subsequent
+    // cancel-stop.
+    if(PendingStop == deviceExtension->DeviceState)
+       {
+        KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        IoSetCompletionRoutine(Irp,
+                               (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
+                               (PVOID)&event,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+        ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+        if(ntStatus == STATUS_PENDING)
+               {
+            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+            ntStatus = Irp->IoStatus.Status;
+
+        }
+
+        if(NT_SUCCESS(ntStatus))
+               {
+            KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+
+            RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
+            deviceExtension->QueueState = AllowRequests;
+            ASSERT(deviceExtension->DeviceState == Working);
+
+            KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+            ProcessQueuedRequests(deviceExtension);
+
+        }
+
+    }
+
+    else
+       {
+        // spurious Irp
+        ntStatus = STATUS_SUCCESS;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    if(WinXpOrBetter == deviceExtension->WdmVersion)
+       {
+        if(deviceExtension->SSEnable)
+               {
+            // Cancel the timer so that the DPCs are no longer fired.
+            // Thus, we are making judicious usage of our resources.
+            // we do not need DPCs because the device is stopping.
+            // The timers are re-initialized while handling the start
+            // device irp.
+            KeCancelTimer(&deviceExtension->Timer);
+
+            // after the device is stopped, it can be surprise removed.
+            // we set this to 0, so that we do not attempt to cancel
+            // the timer while handling surprise remove or remove irps.
+            // when we get the start device request, this flag will be
+            // reinitialized.
+            deviceExtension->SSEnable = 0;
+
+            // make sure that if a DPC was fired before we called cancel timer,
+            // then the DPC and work-time have run to their completion
+            KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
+
+            // make sure that the selective suspend request has been completed.
+            KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
+
+        }
+
+    }
+
+    // after the stop Irp is sent to the lower driver object,
+    // the driver must not send any more Irps down that touch
+    // the device until another Start has occurred.
+    if (deviceExtension->WaitWakeEnable)
+       {
+        CancelWaitWake(deviceExtension);
+
+    }
+
+    KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+
+    SET_NEW_PNP_STATE(deviceExtension, Stopped);
+
+    KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+    // This is the right place to actually give up all the resources used
+    // This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace,
+    // etc.
+    ReleaseMemory(DeviceObject);
+
+    ntStatus = DeconfigureDevice(DeviceObject);
+
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+
+    IoSkipCurrentIrpStackLocation(Irp);
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // If we can allow removal of the device, we should set the QueueState
+    // to HoldRequests so further requests will be queued. This is required
+    // so that we can process queued up requests in cancel-remove just in
+    // case somebody else in the stack fails the query-remove.
+    ntStatus = CanRemoveDevice(DeviceObject, Irp);
+
+    KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+
+    deviceExtension->QueueState = HoldRequests;
+    SET_NEW_PNP_STATE(deviceExtension, PendingRemove);
+
+    KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    // Wait for all the requests to be completed
+    KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+
+    IoSkipCurrentIrpStackLocation(Irp);
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    KEVENT            event;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // We need to reset the QueueState flag to ProcessRequest,
+    // since the device resume its normal activities.
+
+    // First check to see whether you have received cancel-remove
+    // without first receiving a query-remove. This could happen if
+    // someone above us fails a query-remove and passes down the
+    // subsequent cancel-remove.
+    if(PendingRemove == deviceExtension->DeviceState)
+       {
+
+        KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        IoSetCompletionRoutine(Irp,
+                               (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
+                               (PVOID)&event,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+        ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+        if(ntStatus == STATUS_PENDING)
+               {
+            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+            ntStatus = Irp->IoStatus.Status;
+
+        }
+
+        if (NT_SUCCESS(ntStatus))
+               {
+            KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+
+            deviceExtension->QueueState = AllowRequests;
+            RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
+
+            KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+            // process the queued requests that arrive between
+            // QUERY_REMOVE and CANCEL_REMOVE
+            ProcessQueuedRequests(deviceExtension);
+
+        }
+
+    }
+
+    else
+       {
+           // spurious cancel-remove
+        ntStatus = STATUS_SUCCESS;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Entered\n"));
+
+    // initialize variables
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // 1. fail pending requests
+    // 2. return device and memory resources
+    // 3. disable interfaces
+    if(deviceExtension->WaitWakeEnable)
+       {
+        CancelWaitWake(deviceExtension);
+
+    }
+
+
+    if (WinXpOrBetter == deviceExtension->WdmVersion)
+       {
+        if (deviceExtension->SSEnable)
+               {
+            // Cancel the timer so that the DPCs are no longer fired.
+            // we do not need DPCs because the device has been surprise
+            // removed
+            KeCancelTimer(&deviceExtension->Timer);
+
+            deviceExtension->SSEnable = 0;
+
+            // make sure that if a DPC was fired before we called cancel timer,
+            // then the DPC and work-time have run to their completion
+            KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
+
+            // make sure that the selective suspend request has been completed.
+            KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
+
+        }
+
+    }
+
+    KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+    deviceExtension->QueueState = FailRequests;
+    SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved);
+    KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+    ProcessQueuedRequests(deviceExtension);
+
+    ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);
+    if(!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HandleSurpriseRemoval: IoSetDeviceInterfaceState::disable:failed\n"));
+
+    }
+
+    FreeBT_AbortPipes(DeviceObject);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+
+    IoSkipCurrentIrpStackLocation(Irp);
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL             oldIrql;
+    KEVENT            event;
+    ULONG             requestCount;
+    NTSTATUS          ntStatus;
+    PDEVICE_EXTENSION deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // The Plug & Play system has dictated the removal of this device.  We
+    // have no choice but to detach and delete the device object.
+    // (If we wanted to express an interest in preventing this removal,
+    // we should have failed the query remove IRP).
+    if(SurpriseRemoved != deviceExtension->DeviceState)
+       {
+
+        // we are here after QUERY_REMOVE
+        KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+        deviceExtension->QueueState = FailRequests;
+        KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+        if(deviceExtension->WaitWakeEnable)
+               {
+            CancelWaitWake(deviceExtension);
+
+        }
+
+        if(WinXpOrBetter == deviceExtension->WdmVersion)
+               {
+            if (deviceExtension->SSEnable)
+                       {
+                // Cancel the timer so that the DPCs are no longer fired.
+                // we do not need DPCs because the device has been removed
+                KeCancelTimer(&deviceExtension->Timer);
+
+                deviceExtension->SSEnable = 0;
+
+                // make sure that if a DPC was fired before we called cancel timer,
+                // then the DPC and work-time have run to their completion
+                KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
+
+                // make sure that the selective suspend request has been completed.
+                KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
+
+            }
+
+        }
+
+        ProcessQueuedRequests(deviceExtension);
+
+        ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);
+        if(!NT_SUCCESS(ntStatus))
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: HandleRemoveDevice: IoSetDeviceInterfaceState::disable:failed\n"));
+
+        }
+
+        FreeBT_AbortPipes(DeviceObject);
+
+    }
+
+    KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+    SET_NEW_PNP_STATE(deviceExtension, Removed);
+    KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+#ifdef ENABLE_WMI
+    FreeBT_WmiDeRegistration(deviceExtension);
+#endif
+
+    // Need 2 decrements
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
+    requestCount = FreeBT_IoDecrement(deviceExtension);
+
+    ASSERT(requestCount > 0);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
+    requestCount = FreeBT_IoDecrement(deviceExtension);
+
+    KeWaitForSingleObject(&deviceExtension->RemoveEvent,
+                          Executive,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    ReleaseMemory(DeviceObject);
+
+    // We need to send the remove down the stack before we detach,
+    // but we don't need to wait for the completion of this operation
+    // (and to register a completion routine).
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+
+    IoSkipCurrentIrpStackLocation(Irp);
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
+    IoDeleteDevice(DeviceObject);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    ULONG                i;
+    KEVENT               event;
+    NTSTATUS             ntStatus;
+    PDEVICE_EXTENSION    deviceExtension;
+    PDEVICE_CAPABILITIES pdc;
+    PIO_STACK_LOCATION   irpStack;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Entered\n"));
+
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
+
+    if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES))
+       {
+
+        FreeBT_DbgPrint(1, ("FBTUSB: HandleQueryCapabilities::request failed\n"));
+        ntStatus = STATUS_UNSUCCESSFUL;
+        return ntStatus;
+
+    }
+
+    // Add in the SurpriseRemovalOK bit before passing it down.
+    pdc->SurpriseRemovalOK = TRUE;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+
+    KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
+                           (PVOID)&event,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    if(ntStatus == STATUS_PENDING)
+       {
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
+        ntStatus = Irp->IoStatus.Status;
+
+    }
+
+    // initialize PowerDownLevel to disabled
+    deviceExtension->PowerDownLevel = PowerDeviceUnspecified;
+    if(NT_SUCCESS(ntStatus))
+       {
+        deviceExtension->DeviceCapabilities = *pdc;
+        for(i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++)
+               {
+            if(deviceExtension->DeviceCapabilities.DeviceState[i] < PowerDeviceD3)
+                       {
+                deviceExtension->PowerDownLevel = deviceExtension->DeviceCapabilities.DeviceState[i];
+
+            }
+
+        }
+
+        // since its safe to surprise-remove this device, we shall
+        // set the SurpriseRemoveOK flag to supress any dialog to
+        // user.
+        pdc->SurpriseRemovalOK = 1;
+
+    }
+
+    if(deviceExtension->PowerDownLevel == PowerDeviceUnspecified ||
+               deviceExtension->PowerDownLevel <= PowerDeviceD0)
+       {
+        deviceExtension->PowerDownLevel = PowerDeviceD2;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Leaving\n"));
+
+    return ntStatus;
+}
+
+
+VOID DpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
+/*++
+
+    DPC routine triggered by the timer to check the idle state
+    of the device and submit an idle request for the device.
+
+ --*/
+{
+    NTSTATUS          ntStatus;
+    PDEVICE_OBJECT    deviceObject;
+    PDEVICE_EXTENSION deviceExtension;
+    PIO_WORKITEM      item;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Entered\n"));
+
+    deviceObject = (PDEVICE_OBJECT)DeferredContext;
+    deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
+
+    // Clear this event since a DPC has been fired!
+    KeClearEvent(&deviceExtension->NoDpcWorkItemPendingEvent);
+
+    if(CanDeviceSuspend(deviceExtension))
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Device is Idle\n"));
+        item = IoAllocateWorkItem(deviceObject);
+
+        if (item)
+               {
+            IoQueueWorkItem(item, IdleRequestWorkerRoutine, DelayedWorkQueue, item);
+            ntStatus = STATUS_PENDING;
+
+        }
+
+        else
+               {
+            FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Cannot alloc memory for work item\n"));
+            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+            KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
+
+        }
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Idle event not signaled\n"));
+        KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Leaving\n"));
+}
+
+
+VOID IdleRequestWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
+{
+    PIRP                   irp;
+    NTSTATUS               ntStatus;
+    PDEVICE_EXTENSION      deviceExtension;
+    PIO_WORKITEM           workItem;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    workItem = (PIO_WORKITEM) Context;
+
+    if(CanDeviceSuspend(deviceExtension))
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is idle\n"));
+        ntStatus = SubmitIdleRequestIrp(deviceExtension);
+        if(!NT_SUCCESS(ntStatus))
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: IdleRequestWorkerRoutine: SubmitIdleRequestIrp failed\n"));
+
+        }
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is not idle\n"));
+
+    }
+
+    IoFreeWorkItem(workItem);
+
+    KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestsWorkerRoutine: Leaving\n"));
+
+}
+
+
+VOID ProcessQueuedRequests(IN OUT PDEVICE_EXTENSION DeviceExtension)
+/*++
+
+Routine Description:
+
+    Remove and process the entries in the queue. If this routine is called
+    when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
+    or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
+    If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
+    are complete with STATUS_DELETE_PENDING
+
+Arguments:
+
+    DeviceExtension - pointer to device extension
+
+Return Value:
+
+    None
+
+--*/
+{
+    KIRQL       oldIrql;
+    PIRP        nextIrp,
+                cancelledIrp;
+    PVOID       cancelRoutine;
+    LIST_ENTRY  cancelledIrpList;
+    PLIST_ENTRY listEntry;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Entered\n"));
+
+    cancelRoutine = NULL;
+    InitializeListHead(&cancelledIrpList);
+
+    // 1.  dequeue the entries in the queue
+    // 2.  reset the cancel routine
+    // 3.  process them
+    // 3a. if the device is active, send them down
+    // 3b. else complete with STATUS_DELETE_PENDING
+    while(1)
+       {
+        KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
+        if(IsListEmpty(&DeviceExtension->NewRequestsQueue))
+               {
+            KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
+            break;
+
+        }
+
+        listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
+        nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
+
+        cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);
+
+        // check if its already cancelled
+        if (nextIrp->Cancel)
+               {
+            if(cancelRoutine)
+                       {
+                // the cancel routine for this IRP hasnt been called yet
+                // so queue the IRP in the cancelledIrp list and complete
+                // after releasing the lock
+                InsertTailList(&cancelledIrpList, listEntry);
+
+            }
+
+            else
+                       {
+                           // the cancel routine has run
+                // it must be waiting to hold the queue lock
+                // so initialize the IRPs listEntry
+                InitializeListHead(listEntry);
+
+            }
+
+            KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
+
+        }
+
+        else
+               {
+            KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
+            if(FailRequests == DeviceExtension->QueueState)
+                       {
+                nextIrp->IoStatus.Information = 0;
+                nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
+                IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
+
+            }
+
+            else
+                       {
+                PIO_STACK_LOCATION irpStack;
+
+                FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
+                FreeBT_IoIncrement(DeviceExtension);
+
+                IoSkipCurrentIrpStackLocation(nextIrp);
+                IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
+
+                FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
+                FreeBT_IoDecrement(DeviceExtension);
+
+            }
+
+        }
+
+    }
+
+    while(!IsListEmpty(&cancelledIrpList))
+       {
+        PLIST_ENTRY cancelEntry = RemoveHeadList(&cancelledIrpList);
+
+        cancelledIrp = CONTAINING_RECORD(cancelEntry, IRP, Tail.Overlay.ListEntry);
+        cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
+        cancelledIrp->IoStatus.Information = 0;
+
+        IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Leaving\n"));
+
+    return;
+
+}
+
+NTSTATUS FreeBT_GetRegistryDword(IN PWCHAR RegPath, IN PWCHAR ValueName, IN OUT PULONG Value)
+{
+    ULONG                    defaultData;
+    WCHAR                    buffer[MAXIMUM_FILENAME_LENGTH];
+    NTSTATUS                 ntStatus;
+    UNICODE_STRING           regPath;
+    RTL_QUERY_REGISTRY_TABLE paramTable[2];
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Entered\n"));
+
+    regPath.Length = 0;
+    regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
+    regPath.Buffer = buffer;
+
+    RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
+    RtlMoveMemory(regPath.Buffer, RegPath, wcslen(RegPath) * sizeof(WCHAR));
+    RtlZeroMemory(paramTable, sizeof(paramTable));
+
+    paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+    paramTable[0].Name = ValueName;
+    paramTable[0].EntryContext = Value;
+    paramTable[0].DefaultType = REG_DWORD;
+    paramTable[0].DefaultData = &defaultData;
+    paramTable[0].DefaultLength = sizeof(ULONG);
+
+    ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE |
+                                      RTL_REGISTRY_OPTIONAL,
+                                      regPath.Buffer,
+                                      paramTable,
+                                      NULL,
+                                      NULL);
+
+    if (NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Success, Value = %X\n", *Value));
+        return STATUS_SUCCESS;
+    }
+
+    else
+       {
+               FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Failed\n"));
+        *Value = 0;
+        return STATUS_UNSUCCESSFUL;
+
+    }
+}
+
+
+NTSTATUS FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    PDEVICE_EXTENSION  deviceExtension;
+    KIRQL              oldIrql;
+    LIST_ENTRY         cleanupList;
+    PLIST_ENTRY        thisEntry,
+                       nextEntry,
+                       listHead;
+    PIRP               pendingIrp;
+    PIO_STACK_LOCATION pendingIrpStack,
+                       irpStack;
+    NTSTATUS           ntStatus;
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    InitializeListHead(&cleanupList);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
+
+    listHead = &deviceExtension->NewRequestsQueue;
+    for(thisEntry = listHead->Flink, nextEntry = thisEntry->Flink;
+       thisEntry != listHead;
+       thisEntry = nextEntry, nextEntry = thisEntry->Flink)
+       {
+        pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
+        pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);
+        if (irpStack->FileObject == pendingIrpStack->FileObject)
+               {
+            RemoveEntryList(thisEntry);
+
+            if (NULL == IoSetCancelRoutine(pendingIrp, NULL))
+                       {
+                InitializeListHead(thisEntry);
+
+            }
+
+            else
+                       {
+                InsertTailList(&cleanupList, thisEntry);
+
+            }
+
+        }
+
+    }
+
+    KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
+
+    while(!IsListEmpty(&cleanupList))
+       {
+        thisEntry = RemoveHeadList(&cleanupList);
+        pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
+
+        pendingIrp->IoStatus.Information = 0;
+        pendingIrp->IoStatus.Status = STATUS_CANCELLED;
+        IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
+
+    }
+
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    return STATUS_SUCCESS;
+
+}
+
+
+BOOLEAN CanDeviceSuspend(IN PDEVICE_EXTENSION DeviceExtension)
+{
+    FreeBT_DbgPrint(3, ("FBTUSB: CanDeviceSuspend: Entered\n"));
+
+    if ((DeviceExtension->OpenHandleCount == 0) && (DeviceExtension->OutStandingIO == 1))
+        return TRUE;
+
+       return FALSE;
+
+}
+
+NTSTATUS FreeBT_AbortPipes(IN PDEVICE_OBJECT DeviceObject)
+{
+    PURB                        urb;
+    ULONG                       i;
+    NTSTATUS                    ntStatus;
+    PDEVICE_EXTENSION           deviceExtension;
+    PFREEBT_PIPE_CONTEXT               pipeContext;
+    PUSBD_PIPE_INFORMATION      pipeInformation;
+    PUSBD_INTERFACE_INFORMATION interfaceInfo;
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    pipeContext = deviceExtension->PipeContext;
+    interfaceInfo = deviceExtension->UsbInterface;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Entered\n"));
+
+    if(interfaceInfo == NULL || pipeContext == NULL)
+        return STATUS_SUCCESS;
+
+    for(i=0; i<interfaceInfo->NumberOfPipes; i++)
+       {
+        if(pipeContext[i].PipeOpen)
+               {
+            FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Aborting open pipe %d\n", i));
+
+            urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
+            if (urb)
+                       {
+                urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
+                urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
+                urb->UrbPipeRequest.PipeHandle = interfaceInfo->Pipes[i].PipeHandle;
+
+                ntStatus = CallUSBD(DeviceObject, urb);
+
+                ExFreePool(urb);
+
+            }
+
+            else
+                       {
+                FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_AbortPipes: Failed to alloc memory for urb\n"));
+                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+                return ntStatus;
+
+            }
+
+            if(NT_SUCCESS(ntStatus))
+                pipeContext[i].PipeOpen = FALSE;
+
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Leaving\n"));
+
+    return STATUS_SUCCESS;
+
+}
+
+// Completion routine for PNP IRPs
+NTSTATUS IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    PKEVENT event = (PKEVENT) Context;
+    KeSetEvent(event, 0, FALSE);
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+}
+
+
+LONG FreeBT_IoIncrement(IN OUT PDEVICE_EXTENSION DeviceExtension)
+{
+    LONG  result = 0;
+    KIRQL oldIrql;
+
+    KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
+    result = InterlockedIncrement((PLONG)(&DeviceExtension->OutStandingIO));
+
+    // When OutStandingIO bumps from 1 to 2, clear the StopEvent
+    if (result == 2)
+        KeClearEvent(&DeviceExtension->StopEvent);
+
+       KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
+
+    FreeBT_DbgPrint(3, ("FreeBT_IoIncrement::%d\n", result));
+
+    return result;
+
+}
+
+LONG FreeBT_IoDecrement(IN OUT PDEVICE_EXTENSION DeviceExtension)
+{
+    LONG  result = 0;
+    KIRQL oldIrql;
+
+    KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
+
+    result = InterlockedDecrement((PLONG)(&DeviceExtension->OutStandingIO));
+
+    if (result == 1)
+        KeSetEvent(&DeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
+
+    if(result == 0)
+       {
+        ASSERT(Removed == DeviceExtension->DeviceState);
+        KeSetEvent(&DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
+
+    }
+
+    KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
+
+    FreeBT_DbgPrint(3, ("FreeBT_IoDecrement::%d\n", result));
+
+    return result;
+
+}
+
+NTSTATUS CanStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+   // For the time being, just allow it to be stopped
+   UNREFERENCED_PARAMETER(DeviceObject);
+   UNREFERENCED_PARAMETER(Irp);
+
+   return STATUS_SUCCESS;
+
+}
+
+NTSTATUS CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+
+{
+   // For the time being, just allow it to be removed
+   UNREFERENCED_PARAMETER(DeviceObject);
+   UNREFERENCED_PARAMETER(Irp);
+
+   return STATUS_SUCCESS;
+
+}
+
+NTSTATUS ReleaseMemory(IN PDEVICE_OBJECT DeviceObject)
+{
+    // Disconnect from the interrupt and unmap any I/O ports
+    PDEVICE_EXTENSION  deviceExtension;
+    UNICODE_STRING             uniDeviceName;
+    NTSTATUS                   ntStatus;
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    if (deviceExtension->UsbConfigurationDescriptor)
+       {
+               FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbConfigurationDescriptor\n"));
+        ExFreePool(deviceExtension->UsbConfigurationDescriptor);
+        deviceExtension->UsbConfigurationDescriptor = NULL;
+
+    }
+
+    if(deviceExtension->UsbInterface)
+       {
+               FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbInterface\n"));
+        ExFreePool(deviceExtension->UsbInterface);
+        deviceExtension->UsbInterface = NULL;
+
+    }
+
+    if(deviceExtension->PipeContext)
+       {
+               RtlInitUnicodeString(&uniDeviceName, deviceExtension->wszDosDeviceName);
+               ntStatus = IoDeleteSymbolicLink(&uniDeviceName);
+               if (!NT_SUCCESS(ntStatus))
+                       FreeBT_DbgPrint(3, ("FBTUSB: Failed to delete symbolic link %ws\n", deviceExtension->wszDosDeviceName));
+
+               FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing PipeContext %p\n", deviceExtension->PipeContext));
+        ExFreePool(deviceExtension->PipeContext);
+        deviceExtension->PipeContext = NULL;
+
+    }
+
+    return STATUS_SUCCESS;
+
+}
+
+PCHAR PnPMinorFunctionString (UCHAR MinorFunction)
+{
+    switch (MinorFunction)
+       {
+        case IRP_MN_START_DEVICE:
+            return "IRP_MN_START_DEVICE\n";
+
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+            return "IRP_MN_QUERY_REMOVE_DEVICE\n";
+
+        case IRP_MN_REMOVE_DEVICE:
+            return "IRP_MN_REMOVE_DEVICE\n";
+
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+            return "IRP_MN_CANCEL_REMOVE_DEVICE\n";
+
+        case IRP_MN_STOP_DEVICE:
+            return "IRP_MN_STOP_DEVICE\n";
+
+        case IRP_MN_QUERY_STOP_DEVICE:
+            return "IRP_MN_QUERY_STOP_DEVICE\n";
+
+        case IRP_MN_CANCEL_STOP_DEVICE:
+            return "IRP_MN_CANCEL_STOP_DEVICE\n";
+
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+            return "IRP_MN_QUERY_DEVICE_RELATIONS\n";
+
+        case IRP_MN_QUERY_INTERFACE:
+            return "IRP_MN_QUERY_INTERFACE\n";
+
+        case IRP_MN_QUERY_CAPABILITIES:
+            return "IRP_MN_QUERY_CAPABILITIES\n";
+
+        case IRP_MN_QUERY_RESOURCES:
+            return "IRP_MN_QUERY_RESOURCES\n";
+
+        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+            return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n";
+
+        case IRP_MN_QUERY_DEVICE_TEXT:
+            return "IRP_MN_QUERY_DEVICE_TEXT\n";
+
+        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+            return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n";
+
+        case IRP_MN_READ_CONFIG:
+            return "IRP_MN_READ_CONFIG\n";
+
+        case IRP_MN_WRITE_CONFIG:
+            return "IRP_MN_WRITE_CONFIG\n";
+
+        case IRP_MN_EJECT:
+            return "IRP_MN_EJECT\n";
+
+        case IRP_MN_SET_LOCK:
+            return "IRP_MN_SET_LOCK\n";
+
+        case IRP_MN_QUERY_ID:
+            return "IRP_MN_QUERY_ID\n";
+
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+            return "IRP_MN_QUERY_PNP_DEVICE_STATE\n";
+
+        case IRP_MN_QUERY_BUS_INFORMATION:
+            return "IRP_MN_QUERY_BUS_INFORMATION\n";
+
+        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+            return "IRP_MN_DEVICE_USAGE_NOTIFICATION\n";
+
+        case IRP_MN_SURPRISE_REMOVAL:
+            return "IRP_MN_SURPRISE_REMOVAL\n";
+
+        default:
+            return "IRP_MN_?????\n";
+
+    }
+
+}
+
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtpwr.c b/reactos/drivers/bluetooth/fbtusb/fbtpwr.c
new file mode 100755 (executable)
index 0000000..0bd6cea
--- /dev/null
@@ -0,0 +1,1062 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#include "fbtusb.h"
+#include "fbtpwr.h"
+#include "fbtpnp.h"
+#include "fbtdev.h"
+#include "fbtrwr.h"
+#include "fbtwmi.h"
+
+#include "fbtusr.h"
+
+// Handle power events
+NTSTATUS FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    NTSTATUS           ntStatus;
+    PIO_STACK_LOCATION irpStack;
+    PUNICODE_STRING    tagString;
+    PDEVICE_EXTENSION  deviceExtension;
+
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    // We don't queue power Irps, we'll only check if the
+    // device was removed, otherwise we'll take appropriate
+    // action and send it to the next lower driver. In general
+    // drivers should not cause long delays while handling power
+    // IRPs. If a driver cannot handle a power IRP in a brief time,
+    // it should return STATUS_PENDING and queue all incoming
+    // IRPs until the IRP completes.
+    if (Removed == deviceExtension->DeviceState)
+       {
+
+        // Even if a driver fails the IRP, it must nevertheless call
+        // PoStartNextPowerIrp to inform the Power Manager that it
+        // is ready to handle another power IRP.
+        PoStartNextPowerIrp(Irp);
+        Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return ntStatus;
+
+    }
+
+    if (NotStarted == deviceExtension->DeviceState)
+       {
+        // if the device is not started yet, pass it down
+        PoStartNextPowerIrp(Irp);
+        IoSkipCurrentIrpStackLocation(Irp);
+
+        return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    switch(irpStack->MinorFunction)
+       {
+    case IRP_MN_SET_POWER:
+        // The Power Manager sends this IRP for one of the
+        // following reasons:
+
+        // 1) To notify drivers of a change to the system power state.
+        // 2) To change the power state of a device for which
+        //    the Power Manager is performing idle detection.
+
+        // A driver sends IRP_MN_SET_POWER to change the power
+        // state of its device if it's a power policy owner for the
+        // device.
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n"));
+        IoMarkIrpPending(Irp);
+
+        switch(irpStack->Parameters.Power.Type)
+               {
+        case SystemPowerState:
+            HandleSystemSetPower(DeviceObject, Irp);
+            ntStatus = STATUS_PENDING;
+            break;
+
+        case DevicePowerState:
+            HandleDeviceSetPower(DeviceObject, Irp);
+            ntStatus = STATUS_PENDING;
+            break;
+
+        }
+
+        break;
+
+    case IRP_MN_QUERY_POWER:
+        // The Power Manager sends a power IRP with the minor
+        // IRP code IRP_MN_QUERY_POWER to determine whether it
+        // can safely change to the specified system power state
+        // (S1-S5) and to allow drivers to prepare for such a change.
+        // If a driver can put its device in the requested state,
+        // it sets status to STATUS_SUCCESS and passes the IRP down.
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n"));
+        IoMarkIrpPending(Irp);
+
+        switch(irpStack->Parameters.Power.Type)
+               {
+        case SystemPowerState:
+            HandleSystemQueryPower(DeviceObject, Irp);
+            ntStatus = STATUS_PENDING;
+            break;
+
+        case DevicePowerState:
+            HandleDeviceQueryPower(DeviceObject, Irp);
+            ntStatus = STATUS_PENDING;
+            break;
+
+        }
+
+        break;
+
+    case IRP_MN_WAIT_WAKE:
+        // The minor power IRP code IRP_MN_WAIT_WAKE provides
+        // for waking a device or waking the system. Drivers
+        // of devices that can wake themselves or the system
+        // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
+        // only to devices that always wake the system, such as
+        // the power-on switch.
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n"));
+        IoMarkIrpPending(Irp);
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        IoSetCompletionRoutine(
+                        Irp,
+                        (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine,
+                        deviceExtension,
+                        TRUE,
+                        TRUE,
+                        TRUE);
+
+        PoStartNextPowerIrp(Irp);
+        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+        if(!NT_SUCCESS(ntStatus))
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n"));
+
+        }
+
+        ntStatus = STATUS_PENDING;
+
+        // push back the count HERE and NOT in completion routine
+        // a pending Wait Wake Irp should not impede stopping the device
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::"));
+        FreeBT_IoDecrement(deviceExtension);
+        break;
+
+    case IRP_MN_POWER_SEQUENCE:
+        // A driver sends this IRP as an optimization to determine
+        // whether its device actually entered a specific power state.
+        // This IRP is optional. Power Manager cannot send this IRP.
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n"));
+
+    default:
+        PoStartNextPowerIrp(Irp);
+        IoSkipCurrentIrpStackLocation(Irp);
+        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+        if(!NT_SUCCESS(ntStatus))
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n"));
+
+        }
+
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        break;
+
+    }
+
+    return ntStatus;
+
+}
+
+NTSTATUS HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    NTSTATUS           ntStatus;
+    PDEVICE_EXTENSION  deviceExtension;
+    SYSTEM_POWER_STATE systemState;
+    PIO_STACK_LOCATION irpStack;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Entered\n"));
+
+    // initialize variables
+    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    systemState = irpStack->Parameters.Power.State.SystemState;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Query for system power state S%X\n"
+                        "FBTUSB: HandleSystemQueryPower: Current system power state S%X\n",
+                         systemState - 1,
+                         deviceExtension->SysPower - 1));
+
+    // Fail a query for a power state incompatible with waking up the system
+    if ((deviceExtension->WaitWakeEnable) && (systemState > deviceExtension->DeviceCapabilities.SystemWake))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HandleSystemQueryPower: Query for an incompatible system power state\n"));
+
+        PoStartNextPowerIrp(Irp);
+        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        return ntStatus;
+
+    }
+
+    // if querying for a lower S-state, issue a wait-wake
+    if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable))
+       {
+        IssueWaitWake(deviceExtension);
+
+    }
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(
+            Irp,
+            (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
+            deviceExtension,
+            TRUE,
+            TRUE,
+            TRUE);
+
+    ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Leaving\n"));
+
+    return STATUS_PENDING;
+
+}
+
+NTSTATUS HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
+{
+    NTSTATUS           ntStatus;
+    PDEVICE_EXTENSION  deviceExtension;
+    SYSTEM_POWER_STATE systemState;
+    PIO_STACK_LOCATION irpStack;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    systemState = irpStack->Parameters.Power.State.SystemState;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Set request for system power state S%X\n"
+                         "FBTUSB: HandleSystemSetPower: Current system power state S%X\n",
+                         systemState - 1,
+                         deviceExtension->SysPower - 1));
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(
+            Irp,
+            (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
+            deviceExtension,
+            TRUE,
+            TRUE,
+            TRUE);
+
+    ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Leaving\n"));
+
+    return STATUS_PENDING;
+
+}
+
+NTSTATUS HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+    NTSTATUS           ntStatus;
+    PDEVICE_EXTENSION  deviceExtension;
+    PIO_STACK_LOCATION irpStack;
+    DEVICE_POWER_STATE deviceState;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    deviceState = irpStack->Parameters.Power.State.DeviceState;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Query for device power state D%X\n"
+                         "FBTUSB: HandleDeviceQueryPower: Current device power state D%X\n",
+                         deviceState - 1,
+                         deviceExtension->DevPower - 1));
+
+    if (deviceExtension->WaitWakeEnable && deviceState > deviceExtension->DeviceCapabilities.DeviceWake)
+       {
+        PoStartNextPowerIrp(Irp);
+        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        return ntStatus;
+
+    }
+
+    if (deviceState < deviceExtension->DevPower)
+       {
+        ntStatus = STATUS_SUCCESS;
+
+    }
+
+    else
+       {
+        ntStatus = HoldIoRequests(DeviceObject, Irp);
+        if(STATUS_PENDING == ntStatus)
+               {
+            return ntStatus;
+
+        }
+
+    }
+
+    // on error complete the Irp.
+    // on success pass it to the lower layers
+    PoStartNextPowerIrp(Irp);
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+    if(!NT_SUCCESS(ntStatus))
+       {
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    }
+
+    else
+       {
+        IoSkipCurrentIrpStackLocation(Irp);
+        ntStatus=PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+
+NTSTATUS SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
+{
+    NTSTATUS           ntStatus;
+       PIO_STACK_LOCATION irpStack;
+
+    ntStatus = Irp->IoStatus.Status;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Entered\n"));
+
+    // lower drivers failed this Irp
+    if(!NT_SUCCESS(ntStatus))
+       {
+        PoStartNextPowerIrp(Irp);
+        FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine::"));
+        FreeBT_IoDecrement(DeviceExtension);
+
+        return STATUS_SUCCESS;
+
+    }
+
+    // ..otherwise update the cached system power state (IRP_MN_SET_POWER)
+    if(irpStack->MinorFunction == IRP_MN_SET_POWER)
+       {
+        DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState;
+
+    }
+
+    // queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
+    SendDeviceIrp(DeviceObject, Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Leaving\n"));
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+}
+
+VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp )
+{
+    NTSTATUS                  ntStatus;
+    POWER_STATE               powState;
+    PDEVICE_EXTENSION         deviceExtension;
+    PIO_STACK_LOCATION        irpStack;
+    SYSTEM_POWER_STATE        systemState;
+    DEVICE_POWER_STATE        devState;
+    PPOWER_COMPLETION_CONTEXT powerContext;
+
+    irpStack = IoGetCurrentIrpStackLocation(SIrp);
+    systemState = irpStack->Parameters.Power.State.SystemState;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n"));
+
+    // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
+    // we can choose deeper sleep states than our mapping but never choose
+    // lighter ones.
+    devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
+    powState.DeviceState = devState;
+
+    powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT));
+    if (!powerContext)
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    else
+       {
+        powerContext->DeviceObject = DeviceObject;
+        powerContext->SIrp = SIrp;
+
+        // in win2k PoRequestPowerIrp can take fdo or pdo.
+        ntStatus = PoRequestPowerIrp(
+                            deviceExtension->PhysicalDeviceObject,
+                            irpStack->MinorFunction,
+                            powState,
+                            (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,
+                            powerContext,
+                            NULL);
+
+    }
+
+    if (!NT_SUCCESS(ntStatus))
+       {
+        if (powerContext)
+               {
+            ExFreePool(powerContext);
+
+        }
+
+        PoStartNextPowerIrp(SIrp);
+        SIrp->IoStatus.Status = ntStatus;
+        SIrp->IoStatus.Information = 0;
+        IoCompleteRequest(SIrp, IO_NO_INCREMENT);
+
+        FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n"));
+
+}
+
+
+VOID DevPoCompletionRoutine(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN UCHAR MinorFunction,
+    IN POWER_STATE PowerState,
+    IN PVOID Context,
+    IN PIO_STATUS_BLOCK IoStatus
+    )
+{
+    PIRP                      sIrp;
+    PDEVICE_EXTENSION         deviceExtension;
+    PPOWER_COMPLETION_CONTEXT powerContext;
+
+    powerContext = (PPOWER_COMPLETION_CONTEXT) Context;
+    sIrp = powerContext->SIrp;
+    deviceExtension = (PDEVICE_EXTENSION) powerContext->DeviceObject->DeviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Entered\n"));
+
+    sIrp->IoStatus.Status = IoStatus->Status;
+    PoStartNextPowerIrp(sIrp);
+    sIrp->IoStatus.Information = 0;
+    IoCompleteRequest(sIrp, IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    ExFreePool(powerContext);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Leaving\n"));
+
+}
+
+NTSTATUS HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    KIRQL              oldIrql;
+    NTSTATUS           ntStatus;
+    POWER_STATE        newState;
+    PIO_STACK_LOCATION irpStack;
+    PDEVICE_EXTENSION  deviceExtension;
+    DEVICE_POWER_STATE newDevState,
+                       oldDevState;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    oldDevState = deviceExtension->DevPower;
+    newState = irpStack->Parameters.Power.State;
+    newDevState = newState.DeviceState;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n"
+                         "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n",
+                         newDevState - 1,
+                         deviceExtension->DevPower - 1));
+
+    if (newDevState < oldDevState)
+       {
+
+        FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n"));
+
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        IoSetCompletionRoutine(
+                Irp,
+                (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp,
+                deviceExtension,
+                TRUE,
+                TRUE,
+                TRUE);
+
+        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+       }
+
+    else
+       {
+        // newDevState >= oldDevState
+
+        // hold I/O if transition from D0 -> DX (X = 1, 2, 3)
+        // if transition from D1 or D2 to deeper sleep states,
+        // I/O queue is already on hold.
+        if(PowerDeviceD0 == oldDevState && newDevState > oldDevState)
+               {
+            // D0 -> DX transition
+            FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n"));
+
+            ntStatus = HoldIoRequests(DeviceObject, Irp);
+            if (!NT_SUCCESS(ntStatus))
+                       {
+                PoStartNextPowerIrp(Irp);
+                Irp->IoStatus.Status = ntStatus;
+                Irp->IoStatus.Information = 0;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+                FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::"));
+                FreeBT_IoDecrement(deviceExtension);
+
+                return ntStatus;
+
+            }
+
+            else
+                       {
+                goto HandleDeviceSetPower_Exit;
+
+            }
+
+        }
+
+        else if (PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState)
+               {
+            // D0 -> D0
+            // unblock the queue which may have been blocked processing
+            // query irp
+            FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n"));
+
+            KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
+            deviceExtension->QueueState = AllowRequests;
+            KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
+
+            ProcessQueuedRequests(deviceExtension);
+
+        }
+
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        IoSetCompletionRoutine(
+                Irp,
+                (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
+                deviceExtension,
+                TRUE,
+                TRUE,
+                TRUE);
+
+        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+        if(!NT_SUCCESS(ntStatus))
+               {
+            FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n"));
+
+        }
+
+    }
+
+HandleDeviceSetPower_Exit:
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n"));
+
+    return STATUS_PENDING;
+
+}
+
+NTSTATUS FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
+{
+    NTSTATUS           ntStatus;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Entered\n"));
+
+    ntStatus = Irp->IoStatus.Status;
+    if(Irp->PendingReturned)
+       {
+        IoMarkIrpPending(Irp);
+
+    }
+
+    if(!NT_SUCCESS(ntStatus))
+       {
+        PoStartNextPowerIrp(Irp);
+
+        FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp::"));
+        FreeBT_IoDecrement(DeviceExtension);
+
+        return STATUS_SUCCESS;
+
+    }
+
+    SetDeviceFunctional(DeviceObject, Irp, DeviceExtension);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Leaving\n"));
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+}
+
+NTSTATUS SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
+{
+    KIRQL              oldIrql;
+    NTSTATUS           ntStatus;
+    POWER_STATE        newState;
+    PIO_STACK_LOCATION irpStack;
+    DEVICE_POWER_STATE newDevState, oldDevState;
+
+    ntStatus = Irp->IoStatus.Status;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    newState = irpStack->Parameters.Power.State;
+    newDevState = newState.DeviceState;
+    oldDevState = DeviceExtension->DevPower;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Entered\n"));
+
+    // update the cached state
+    DeviceExtension->DevPower = newDevState;
+
+    // restore appropriate amount of state to our h/w
+    // this driver does not implement partial context
+    // save/restore.
+    PoSetPowerState(DeviceObject, DevicePowerState, newState);
+    if(PowerDeviceD0 == newDevState)
+       {
+        KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
+        DeviceExtension->QueueState = AllowRequests;
+        KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);
+
+        ProcessQueuedRequests(DeviceExtension);
+
+    }
+
+    PoStartNextPowerIrp(Irp);
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional::"));
+    FreeBT_IoDecrement(DeviceExtension);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Leaving\n"));
+
+    return STATUS_SUCCESS;
+
+}
+
+NTSTATUS FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
+{
+    NTSTATUS           ntStatus;
+    POWER_STATE        newState;
+    PIO_STACK_LOCATION irpStack;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Entered\n"));
+
+    ntStatus = Irp->IoStatus.Status;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    newState = irpStack->Parameters.Power.State;
+
+    if (NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER)
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: updating cache..\n"));
+        DeviceExtension->DevPower = newState.DeviceState;
+        PoSetPowerState(DeviceObject, DevicePowerState, newState);
+
+    }
+
+    PoStartNextPowerIrp(Irp);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp::"));
+    FreeBT_IoDecrement(DeviceExtension);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Leaving\n"));
+
+    return STATUS_SUCCESS;
+
+}
+
+NTSTATUS HoldIoRequests(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+
+{
+    NTSTATUS               ntStatus;
+    PIO_WORKITEM           item;
+    PDEVICE_EXTENSION      deviceExtension;
+    PWORKER_THREAD_CONTEXT context;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    deviceExtension->QueueState = HoldRequests;
+
+    context = (PWORKER_THREAD_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
+    if(context)
+       {
+        item = IoAllocateWorkItem(DeviceObject);
+
+        context->Irp = Irp;
+        context->DeviceObject = DeviceObject;
+        context->WorkItem = item;
+
+        if (item)
+               {
+            IoMarkIrpPending(Irp);
+            IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine, DelayedWorkQueue, context);
+            ntStatus = STATUS_PENDING;
+
+        }
+
+        else
+               {
+            FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Failed to allocate memory for workitem\n"));
+            ExFreePool(context);
+            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+        }
+
+    }
+
+    else
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequests: Failed to alloc memory for worker thread context\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+VOID HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
+{
+    PIRP                   irp;
+    NTSTATUS               ntStatus;
+    PDEVICE_EXTENSION      deviceExtension;
+    PWORKER_THREAD_CONTEXT context;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    context = (PWORKER_THREAD_CONTEXT) Context;
+    irp = (PIRP) context->Irp;
+
+    // wait for I/O in progress to finish.
+    // the stop event is signalled when the counter drops to 1.
+    // invoke FreeBT_IoDecrement twice: once each for the S-Irp and D-Irp.
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
+
+    // Increment twice to restore the count
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    // now send the Irp down
+    IoCopyCurrentIrpStackLocationToNext(irp);
+    IoSetCompletionRoutine(
+               irp,
+               (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
+               deviceExtension,
+               TRUE,
+               TRUE,
+               TRUE);
+
+    ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
+    if(!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequestsWorkerRoutine: Lower driver fail a power Irp\n"));
+
+    }
+
+    IoFreeWorkItem(context->WorkItem);
+    ExFreePool((PVOID)context);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Leaving\n"));
+
+}
+
+NTSTATUS QueueRequest(IN OUT PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
+{
+    KIRQL    oldIrql;
+    NTSTATUS ntStatus;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Entered\n"));
+
+    ntStatus = STATUS_PENDING;
+
+    ASSERT(HoldRequests == DeviceExtension->QueueState);
+
+    KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
+
+    InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry);
+    IoMarkIrpPending(Irp);
+    IoSetCancelRoutine(Irp, CancelQueued);
+
+    KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+VOID CancelQueued(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    PDEVICE_EXTENSION deviceExtension;
+    KIRQL             oldIrql;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    oldIrql = Irp->CancelIrql;
+
+    // Release the cancel spin lock
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    // Acquire the queue lock
+    KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);
+
+    // Remove the cancelled Irp from queue and release the lock
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+    KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
+
+    // complete with STATUS_CANCELLED
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Leaving\n"));
+
+    return;
+
+}
+
+NTSTATUS IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension)
+{
+    POWER_STATE poState;
+    NTSTATUS    ntStatus;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Entered\n"));
+
+    if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1))
+       {
+        return STATUS_DEVICE_BUSY;
+
+    }
+
+    InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);
+
+    // lowest state from which this Irp will wake the system
+    poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
+    ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject,
+                                 IRP_MN_WAIT_WAKE,
+                                 poState,
+                                 (PREQUEST_POWER_COMPLETE) WaitWakeCallback,
+                                 DeviceExtension,
+                                 &DeviceExtension->WaitWakeIrp);
+
+    if(!NT_SUCCESS(ntStatus))
+       {
+        InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+VOID CancelWaitWake(IN PDEVICE_EXTENSION DeviceExtension)
+{
+    PIRP Irp;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Entered\n"));
+
+    Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL);
+    if(Irp)
+       {
+        IoCancelIrp(Irp);
+        if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1))
+               {
+            PoStartNextPowerIrp(Irp);
+            Irp->IoStatus.Status = STATUS_CANCELLED;
+            Irp->IoStatus.Information = 0;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Leaving\n"));
+
+}
+
+NTSTATUS WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
+{
+    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Entered\n"));
+    if(Irp->PendingReturned)
+       {
+        IoMarkIrpPending(Irp);
+
+    }
+
+    // Nullify the WaitWakeIrp pointer-the Irp is released
+    // as part of the completion process. If it's already NULL,
+    // avoid race with the CancelWaitWake routine.
+    if(InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL))
+       {
+        PoStartNextPowerIrp(Irp);
+
+        return STATUS_SUCCESS;
+
+    }
+
+    // CancelWaitWake has run.
+    // If FlagWWCancel != 0, complete the Irp.
+    // If FlagWWCancel == 0, CancelWaitWake completes it.
+    if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1))
+       {
+        PoStartNextPowerIrp(Irp);
+
+        return STATUS_CANCELLED;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Leaving\n"));
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+}
+
+VOID WaitWakeCallback(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN UCHAR MinorFunction,
+    IN POWER_STATE PowerState,
+    IN PVOID Context,
+    IN PIO_STATUS_BLOCK IoStatus)
+{
+    NTSTATUS               ntStatus;
+    POWER_STATE            powerState;
+    PDEVICE_EXTENSION      deviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) Context;
+
+    InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);
+
+    if(!NT_SUCCESS(IoStatus->Status))
+       {
+        return;
+
+    }
+
+    // wake up the device
+    if(deviceExtension->DevPower == PowerDeviceD0)
+       {
+        FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n"));
+
+        return;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    powerState.DeviceState = PowerDeviceD0;
+    ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
+                                 IRP_MN_SET_POWER,
+                                 powerState,
+                                 (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc,
+                                 deviceExtension,
+                                 NULL);
+
+    if(deviceExtension->WaitWakeEnable)
+       {
+        IssueWaitWake(deviceExtension);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n"));
+
+    return;
+
+}
+
+
+PCHAR PowerMinorFunctionString (IN UCHAR MinorFunction)
+{
+    switch (MinorFunction)
+       {
+        case IRP_MN_SET_POWER:
+            return "IRP_MN_SET_POWER\n";
+
+        case IRP_MN_QUERY_POWER:
+            return "IRP_MN_QUERY_POWER\n";
+
+        case IRP_MN_POWER_SEQUENCE:
+            return "IRP_MN_POWER_SEQUENCE\n";
+
+        case IRP_MN_WAIT_WAKE:
+            return "IRP_MN_WAIT_WAKE\n";
+
+        default:
+            return "IRP_MN_?????\n";
+
+    }
+
+}
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtrwr.c b/reactos/drivers/bluetooth/fbtusb/fbtrwr.c
new file mode 100755 (executable)
index 0000000..f827289
--- /dev/null
@@ -0,0 +1,543 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#include "fbtusb.h"
+#include "fbtpnp.h"
+#include "fbtpwr.h"
+#include "fbtdev.h"
+#include "fbtrwr.h"
+#include "fbtwmi.h"
+
+#include "fbtusr.h"
+
+// Read/Write handler
+NTSTATUS FreeBT_DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    PMDL                                       mdl;
+    PURB                                       urb;
+    ULONG                                      totalLength;
+    ULONG                                      stageLength;
+    NTSTATUS                           ntStatus;
+    ULONG_PTR                          virtualAddress;
+    PFILE_OBJECT                       fileObject;
+    PDEVICE_EXTENSION          deviceExtension;
+    PIO_STACK_LOCATION         irpStack;
+    PIO_STACK_LOCATION         nextStack;
+    PFREEBT_RW_CONTEXT         rwContext;
+    ULONG                                      maxLength=0;
+
+    urb = NULL;
+    mdl = NULL;
+    rwContext = NULL;
+    totalLength = 0;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    fileObject = irpStack->FileObject;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: Entered\n"));
+
+    if (deviceExtension->DeviceState != Working)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Invalid device state\n"));
+        ntStatus = STATUS_INVALID_DEVICE_STATE;
+        goto FreeBT_DispatchRead_Exit;
+
+    }
+
+    // Make sure that any selective suspend request has been completed.
+    if (deviceExtension->SSEnable)
+    {
+           FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: Waiting on the IdleReqPendEvent\n"));
+        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+
+    }
+
+    rwContext = (PFREEBT_RW_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(FREEBT_RW_CONTEXT));
+    if (rwContext == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Failed to alloc mem for rwContext\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        goto FreeBT_DispatchRead_Exit;
+
+    }
+
+    if (Irp->MdlAddress)
+    {
+        totalLength = MmGetMdlByteCount(Irp->MdlAddress);
+
+    }
+
+       FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Transfer data length = %d\n", totalLength));
+    if (totalLength == 0)
+    {
+        ntStatus = STATUS_SUCCESS;
+        ExFreePool(rwContext);
+        goto FreeBT_DispatchRead_Exit;
+
+    }
+
+    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
+    if (totalLength > deviceExtension->DataInPipe.MaximumPacketSize)
+    {
+        stageLength = deviceExtension->DataInPipe.MaximumPacketSize;
+
+    }
+
+    else
+    {
+        stageLength = totalLength;
+
+    }
+
+    mdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL);
+    if (mdl == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Failed to alloc mem for mdl\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        ExFreePool(rwContext);
+        goto FreeBT_DispatchRead_Exit;
+
+    }
+
+    // map the portion of user-buffer described by an mdl to another mdl
+    IoBuildPartialMdl(Irp->MdlAddress, mdl, (PVOID) virtualAddress, stageLength);
+    urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
+    if (urb == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Failed to alloc mem for urb\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        ExFreePool(rwContext);
+        IoFreeMdl(mdl);
+        goto FreeBT_DispatchRead_Exit;
+
+    }
+
+    UsbBuildInterruptOrBulkTransferRequest(
+                            urb,
+                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+                            deviceExtension->DataInPipe.PipeHandle,
+                            NULL,
+                            mdl,
+                            stageLength,
+                            USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN,
+                            NULL);
+
+    // set FREEBT_RW_CONTEXT parameters.
+    rwContext->Urb             = urb;
+    rwContext->Mdl             = mdl;
+    rwContext->Length          = totalLength - stageLength;
+    rwContext->Numxfer         = 0;
+    rwContext->VirtualAddress  = virtualAddress + stageLength;
+
+    // use the original read/write irp as an internal device control irp
+    nextStack = IoGetNextIrpStackLocation(Irp);
+    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+    nextStack->Parameters.Others.Argument1 = (PVOID) urb;
+    nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+    IoSetCompletionRoutine(Irp,
+                           (PIO_COMPLETION_ROUTINE)FreeBT_ReadCompletion,
+                           rwContext,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    // We return STATUS_PENDING; call IoMarkIrpPending.
+    IoMarkIrpPending(Irp);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    if (!NT_SUCCESS(ntStatus))
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: IoCallDriver fails with status %X\n", ntStatus));
+
+        // if the device was yanked out, then the pipeInformation
+        // field is invalid.
+        // similarly if the request was cancelled, then we need not
+        // invoked reset pipe/device.
+        if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
+        {
+            ntStatus = FreeBT_ResetPipe(DeviceObject, deviceExtension->DataInPipe.PipeHandle);
+            if(!NT_SUCCESS(ntStatus))
+            {
+                FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: FreeBT_ResetPipe failed\n"));
+                ntStatus = FreeBT_ResetDevice(DeviceObject);
+
+            }
+
+        }
+
+        else
+        {
+            FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+       FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: URB sent to lower driver, IRP is pending\n"));
+
+    // we return STATUS_PENDING and not the status returned by the lower layer.
+    return STATUS_PENDING;
+
+FreeBT_DispatchRead_Exit:
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS FreeBT_ReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    ULONG                              stageLength;
+    NTSTATUS                   ntStatus;
+    PIO_STACK_LOCATION nextStack;
+    PFREEBT_RW_CONTEXT rwContext;
+       PDEVICE_EXTENSION       deviceExtension;
+
+       deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    rwContext = (PFREEBT_RW_CONTEXT) Context;
+    ntStatus = Irp->IoStatus.Status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ReadCompletion: Entered\n"));
+
+    if (NT_SUCCESS(ntStatus))
+    {
+               Irp->IoStatus.Information = rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+
+    }
+
+    else
+    {
+               Irp->IoStatus.Information = 0;
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_ReadCompletion: - failed with status = %X\n", ntStatus));
+
+    }
+
+    if (rwContext)
+    {
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ReadCompletion: ::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        ExFreePool(rwContext->Urb);
+        IoFreeMdl(rwContext->Mdl);
+        ExFreePool(rwContext);
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ReadCompletion: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+// Read/Write handler
+NTSTATUS FreeBT_DispatchWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    PMDL                                       mdl;
+    PURB                                       urb;
+    ULONG                                      totalLength;
+    ULONG                                      stageLength;
+    NTSTATUS                           ntStatus;
+    ULONG_PTR                          virtualAddress;
+    PFILE_OBJECT                       fileObject;
+    PDEVICE_EXTENSION          deviceExtension;
+    PIO_STACK_LOCATION         irpStack;
+    PIO_STACK_LOCATION         nextStack;
+    PFREEBT_RW_CONTEXT         rwContext;
+    ULONG                                      maxLength=0;
+
+    urb = NULL;
+    mdl = NULL;
+    rwContext = NULL;
+    totalLength = 0;
+    irpStack = IoGetCurrentIrpStackLocation(Irp);
+    fileObject = irpStack->FileObject;
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite: Entered\n"));
+
+    if (deviceExtension->DeviceState != Working)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Invalid device state\n"));
+        ntStatus = STATUS_INVALID_DEVICE_STATE;
+        goto FreeBT_DispatchWrite_Exit;
+
+    }
+
+    // Make sure that any selective suspend request has been completed.
+    if (deviceExtension->SSEnable)
+    {
+           FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteDispatch: Waiting on the IdleReqPendEvent\n"));
+        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+
+    }
+
+    rwContext = (PFREEBT_RW_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(FREEBT_RW_CONTEXT));
+    if (rwContext == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: Failed to alloc mem for rwContext\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        goto FreeBT_DispatchWrite_Exit;
+
+    }
+
+    if (Irp->MdlAddress)
+    {
+        totalLength = MmGetMdlByteCount(Irp->MdlAddress);
+
+    }
+
+       FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Transfer data length = %d\n", totalLength));
+    if (totalLength>FBT_HCI_DATA_MAX_SIZE)
+    {
+               FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Buffer exceeds maximum packet length (%d), failing IRP\n", FBT_HCI_DATA_MAX_SIZE));
+        ntStatus = STATUS_INVALID_BUFFER_SIZE;
+        ExFreePool(rwContext);
+        goto FreeBT_DispatchWrite_Exit;
+
+    }
+
+    if (totalLength<FBT_HCI_DATA_MIN_SIZE)
+    {
+               FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Zero length buffer, completing IRP\n"));
+        ntStatus = STATUS_BUFFER_TOO_SMALL;
+        ExFreePool(rwContext);
+        goto FreeBT_DispatchWrite_Exit;
+
+    }
+
+    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
+    if (totalLength > deviceExtension->DataOutPipe.MaximumPacketSize)
+    {
+        stageLength = deviceExtension->DataOutPipe.MaximumPacketSize;
+
+    }
+
+    else
+    {
+        stageLength = totalLength;
+
+    }
+
+    mdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL);
+    if (mdl == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Failed to alloc mem for mdl\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        ExFreePool(rwContext);
+        goto FreeBT_DispatchWrite_Exit;
+
+    }
+
+    // map the portion of user-buffer described by an mdl to another mdl
+    IoBuildPartialMdl(Irp->MdlAddress, mdl, (PVOID) virtualAddress, stageLength);
+    urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
+    if (urb == NULL)
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Failed to alloc mem for urb\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        ExFreePool(rwContext);
+        IoFreeMdl(mdl);
+        goto FreeBT_DispatchWrite_Exit;
+
+    }
+
+    UsbBuildInterruptOrBulkTransferRequest(
+                            urb,
+                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+                            deviceExtension->DataOutPipe.PipeHandle,
+                            NULL,
+                            mdl,
+                            stageLength,
+                            USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_OUT,
+                            NULL);
+
+    // set FREEBT_RW_CONTEXT parameters.
+    rwContext->Urb             = urb;
+    rwContext->Mdl             = mdl;
+    rwContext->Length          = totalLength - stageLength;
+    rwContext->Numxfer         = 0;
+    rwContext->VirtualAddress  = virtualAddress + stageLength;
+
+    // use the original read/write irp as an internal device control irp
+    nextStack = IoGetNextIrpStackLocation(Irp);
+    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+    nextStack->Parameters.Others.Argument1 = (PVOID) urb;
+    nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+    IoSetCompletionRoutine(Irp,
+                           (PIO_COMPLETION_ROUTINE)FreeBT_WriteCompletion,
+                           rwContext,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    // We return STATUS_PENDING; call IoMarkIrpPending.
+    IoMarkIrpPending(Irp);
+
+    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+    if (!NT_SUCCESS(ntStatus))
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: IoCallDriver fails with status %X\n", ntStatus));
+
+        // if the device was yanked out, then the pipeInformation
+        // field is invalid.
+        // similarly if the request was cancelled, then we need not
+        // invoked reset pipe/device.
+        if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
+        {
+            ntStatus = FreeBT_ResetPipe(DeviceObject, deviceExtension->DataOutPipe.PipeHandle);
+            if(!NT_SUCCESS(ntStatus))
+            {
+                FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_ResetPipe failed\n"));
+                ntStatus = FreeBT_ResetDevice(DeviceObject);
+
+            }
+
+        }
+
+        else
+        {
+            FreeBT_DbgPrint(3, ("FBTUSB: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+       FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite: URB sent to lower driver, IRP is pending\n"));
+
+    // we return STATUS_PENDING and not the status returned by the lower layer.
+    return STATUS_PENDING;
+
+FreeBT_DispatchWrite_Exit:
+    Irp->IoStatus.Status = ntStatus;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS FreeBT_WriteCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
+{
+    ULONG                              stageLength;
+    NTSTATUS                   ntStatus;
+    PIO_STACK_LOCATION nextStack;
+    PFREEBT_RW_CONTEXT rwContext;
+       PDEVICE_EXTENSION       deviceExtension;
+
+       deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    rwContext = (PFREEBT_RW_CONTEXT) Context;
+    ntStatus = Irp->IoStatus.Status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: Entered\n"));
+
+    if (NT_SUCCESS(ntStatus))
+    {
+        if (rwContext)
+        {
+            rwContext->Numxfer += rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+            if (rwContext->Length)
+            {
+                // More data to transfer
+                FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: Initiating next transfer\n"));
+                if (rwContext->Length > deviceExtension->DataOutPipe.MaximumPacketSize)
+                {
+                    stageLength = deviceExtension->DataOutPipe.MaximumPacketSize;
+
+                }
+
+                else
+                {
+                    stageLength = rwContext->Length;
+
+                }
+
+                IoBuildPartialMdl(Irp->MdlAddress, rwContext->Mdl, (PVOID) rwContext->VirtualAddress, stageLength);
+
+                // reinitialize the urb
+                rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength;
+                rwContext->VirtualAddress += stageLength;
+                rwContext->Length -= stageLength;
+
+                nextStack = IoGetNextIrpStackLocation(Irp);
+                nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+                nextStack->Parameters.Others.Argument1 = rwContext->Urb;
+                nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+
+                IoSetCompletionRoutine(Irp,
+                                       FreeBT_ReadCompletion,
+                                       rwContext,
+                                       TRUE,
+                                       TRUE,
+                                       TRUE);
+
+                IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+
+                return STATUS_MORE_PROCESSING_REQUIRED;
+
+            }
+
+            else
+            {
+                // No more data to transfer
+                               FreeBT_DbgPrint(1, ("FBTUSB: FreeNT_WriteCompletion: Write completed, %d bytes written\n", Irp->IoStatus.Information));
+                Irp->IoStatus.Information = rwContext->Numxfer;
+
+            }
+
+        }
+
+    }
+
+    else
+    {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeNT_WriteCompletion - failed with status = %X\n", ntStatus));
+
+    }
+
+    if (rwContext)
+    {
+        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: ::"));
+        FreeBT_IoDecrement(deviceExtension);
+
+        ExFreePool(rwContext->Urb);
+        IoFreeMdl(rwContext->Mdl);
+        ExFreePool(rwContext);
+
+    }
+
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: Leaving\n"));
+
+    return ntStatus;
+
+}
+
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtusb.c b/reactos/drivers/bluetooth/fbtusb/fbtusb.c
new file mode 100755 (executable)
index 0000000..353eab4
--- /dev/null
@@ -0,0 +1,341 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#include "stdio.h"
+#include "fbtusb.h"
+#include "fbtpnp.h"
+#include "fbtpwr.h"
+#include "fbtdev.h"
+#include "fbtwmi.h"
+#include "fbtrwr.h"
+
+#include "fbtusr.h"
+
+
+// Globals
+GLOBALS Globals;
+ULONG DebugLevel=255;
+
+// Forward declaration
+NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT  DriverObject, IN PUNICODE_STRING UniRegistryPath );
+VOID NTAPI FreeBT_DriverUnload(IN PDRIVER_OBJECT DriverObject);
+NTSTATUS NTAPI FreeBT_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
+
+#ifdef PAGE_CODE
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, DriverEntry)
+#pragma alloc_text(PAGE, FreeBT_DriverUnload)
+#endif
+#endif
+
+NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING UniRegistryPath)
+{
+    NTSTATUS        ntStatus;
+    PUNICODE_STRING registryPath;
+
+    registryPath = &Globals.FreeBT_RegistryPath;
+
+    registryPath->MaximumLength = UniRegistryPath->Length + sizeof(UNICODE_NULL);
+    registryPath->Length        = UniRegistryPath->Length;
+    registryPath->Buffer        = (PWSTR) ExAllocatePool(PagedPool, registryPath->MaximumLength);
+
+    if (!registryPath->Buffer)
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: Failed to allocate memory for registryPath\n"));
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+        goto DriverEntry_Exit;
+
+    }
+
+
+    RtlZeroMemory (registryPath->Buffer, registryPath->MaximumLength);
+    RtlMoveMemory (registryPath->Buffer, UniRegistryPath->Buffer, UniRegistryPath->Length);
+
+    ntStatus = STATUS_SUCCESS;
+
+    // Initialize the driver object with this driver's entry points.
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FreeBT_DispatchDevCtrl;
+    DriverObject->MajorFunction[IRP_MJ_POWER]          = FreeBT_DispatchPower;
+    DriverObject->MajorFunction[IRP_MJ_PNP]            = FreeBT_DispatchPnP;
+    DriverObject->MajorFunction[IRP_MJ_CREATE]         = FreeBT_DispatchCreate;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = FreeBT_DispatchClose;
+    DriverObject->MajorFunction[IRP_MJ_CLEANUP]        = FreeBT_DispatchClean;
+    DriverObject->MajorFunction[IRP_MJ_READ]           = FreeBT_DispatchRead;
+    DriverObject->MajorFunction[IRP_MJ_WRITE]          = FreeBT_DispatchWrite;
+#ifdef ENABLE_WMI
+    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = FreeBT_DispatchSysCtrl;
+#endif
+    DriverObject->DriverUnload                         = FreeBT_DriverUnload;
+    DriverObject->DriverExtension->AddDevice           = (PDRIVER_ADD_DEVICE) FreeBT_AddDevice;
+
+DriverEntry_Exit:
+    return ntStatus;
+
+}
+
+VOID NTAPI FreeBT_DriverUnload(IN PDRIVER_OBJECT DriverObject)
+{
+    PUNICODE_STRING registryPath;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DriverUnload: Entered\n"));
+
+    registryPath = &Globals.FreeBT_RegistryPath;
+    if(registryPath->Buffer)
+       {
+        ExFreePool(registryPath->Buffer);
+        registryPath->Buffer = NULL;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DriverUnload: Leaving\n"));
+
+    return;
+
+}
+
+// AddDevice, called when an instance of our supported hardware is found
+// Returning anything other than NT_SUCCESS here causes the device to fail
+// to initialise
+NTSTATUS NTAPI FreeBT_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+    NTSTATUS                   ntStatus;
+    PDEVICE_OBJECT             deviceObject;
+    PDEVICE_EXTENSION  deviceExtension;
+    POWER_STATE                        state;
+    KIRQL                              oldIrql;
+       UNICODE_STRING          uniDeviceName;
+       WCHAR                           wszDeviceName[255]={0};
+       UNICODE_STRING          uniDosDeviceName;
+       LONG                            instanceNumber=0;
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Entered\n"));
+
+    deviceObject = NULL;
+
+       swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber);
+       RtlInitUnicodeString(&uniDeviceName, wszDeviceName);
+       ntStatus=STATUS_OBJECT_NAME_COLLISION;
+       while (instanceNumber<99 && !NT_SUCCESS(ntStatus))
+       {
+               swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber);
+               uniDeviceName.Length = wcslen(wszDeviceName) * sizeof(WCHAR);
+               FreeBT_DbgPrint(1, ("FBTUSB: Attempting to create device %ws\n", wszDeviceName));
+               ntStatus = IoCreateDevice(
+                                               DriverObject,                   // our driver object
+                                               sizeof(DEVICE_EXTENSION),       // extension size for us
+                                               &uniDeviceName,                                 // name for this device
+                                               FILE_DEVICE_UNKNOWN,
+                                               0,                                                              // device characteristics
+                                               FALSE,                          // Not exclusive
+                                               &deviceObject);                 // Our device object
+
+               if (!NT_SUCCESS(ntStatus))
+                       instanceNumber++;
+
+       }
+
+    if (!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: Failed to create device object\n"));
+        return ntStatus;
+
+    }
+
+       FreeBT_DbgPrint(1, ("FBTUSB: Created device %ws\n", wszDeviceName));
+
+    deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
+    deviceExtension->FunctionalDeviceObject = deviceObject;
+    deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
+    deviceObject->Flags |= DO_DIRECT_IO;
+
+       swprintf(deviceExtension->wszDosDeviceName, L"\\DosDevices\\FbtUsb%02d", instanceNumber);
+       RtlInitUnicodeString(&uniDosDeviceName, deviceExtension->wszDosDeviceName);
+       ntStatus=IoCreateSymbolicLink(&uniDosDeviceName, &uniDeviceName);
+       if (!NT_SUCCESS(ntStatus))
+       {
+               FreeBT_DbgPrint(1, ("FBTUSB: Failed to create symbolic link %ws to %ws, status=0x%08x\n", deviceExtension->wszDosDeviceName, wszDeviceName, ntStatus));
+               IoDeleteDevice(deviceObject);
+               return ntStatus;
+
+       }
+
+       FreeBT_DbgPrint(1, ("FBTUSB: Created symbolic link %ws\n", deviceExtension->wszDosDeviceName));
+
+    KeInitializeSpinLock(&deviceExtension->DevStateLock);
+
+    INITIALIZE_PNP_STATE(deviceExtension);
+
+    deviceExtension->OpenHandleCount = 0;
+
+    // Initialize the selective suspend variables
+    KeInitializeSpinLock(&deviceExtension->IdleReqStateLock);
+    deviceExtension->IdleReqPend = 0;
+    deviceExtension->PendingIdleIrp = NULL;
+
+    // Hold requests until the device is started
+    deviceExtension->QueueState = HoldRequests;
+
+    // Initialize the queue and the queue spin lock
+    InitializeListHead(&deviceExtension->NewRequestsQueue);
+    KeInitializeSpinLock(&deviceExtension->QueueLock);
+
+    // Initialize the remove event to not-signaled.
+    KeInitializeEvent(&deviceExtension->RemoveEvent, SynchronizationEvent, FALSE);
+
+    // Initialize the stop event to signaled.
+    // This event is signaled when the OutstandingIO becomes 1
+    KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, TRUE);
+
+    // OutstandingIo count biased to 1.
+    // Transition to 0 during remove device means IO is finished.
+    // Transition to 1 means the device can be stopped
+    deviceExtension->OutStandingIO = 1;
+    KeInitializeSpinLock(&deviceExtension->IOCountLock);
+
+#ifdef ENABLE_WMI 
+    // Delegating to WMILIB
+    ntStatus = FreeBT_WmiRegistration(deviceExtension);
+    if (!NT_SUCCESS(ntStatus))
+       {
+        FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WmiRegistration failed with %X\n", ntStatus));
+        IoDeleteDevice(deviceObject);
+               IoDeleteSymbolicLink(&uniDosDeviceName);
+        return ntStatus;
+
+    }
+#endif
+
+    // Set the flags as underlying PDO
+    if (PhysicalDeviceObject->Flags & DO_POWER_PAGABLE)
+       {
+        deviceObject->Flags |= DO_POWER_PAGABLE;
+
+    }
+
+    // Typically, the function driver for a device is its
+    // power policy owner, although for some devices another
+    // driver or system component may assume this role.
+    // Set the initial power state of the device, if known, by calling
+    // PoSetPowerState.
+    deviceExtension->DevPower = PowerDeviceD0;
+    deviceExtension->SysPower = PowerSystemWorking;
+
+    state.DeviceState = PowerDeviceD0;
+    PoSetPowerState(deviceObject, DevicePowerState, state);
+
+    // attach our driver to device stack
+    // The return value of IoAttachDeviceToDeviceStack is the top of the
+    // attachment chain.  This is where all the IRPs should be routed.
+    deviceExtension->TopOfStackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
+    if (NULL == deviceExtension->TopOfStackDeviceObject)
+       {
+#ifdef ENABLE_WMI
+        FreeBT_WmiDeRegistration(deviceExtension);
+#endif
+        IoDeleteDevice(deviceObject);
+               IoDeleteSymbolicLink(&uniDosDeviceName);
+        return STATUS_NO_SUCH_DEVICE;
+
+    }
+
+    // Register device interfaces
+    ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject,
+                                         &GUID_CLASS_FREEBT_USB,
+                                         NULL,
+                                         &deviceExtension->InterfaceName);
+    if (!NT_SUCCESS(ntStatus))
+       {
+#ifdef ENABLE_WMI
+        FreeBT_WmiDeRegistration(deviceExtension);
+#endif
+        IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
+        IoDeleteDevice(deviceObject);
+               IoDeleteSymbolicLink(&uniDosDeviceName);
+        return ntStatus;
+
+    }
+
+    if (IoIsWdmVersionAvailable(1, 0x20))
+       {
+        deviceExtension->WdmVersion = WinXpOrBetter;
+
+    }
+
+    else if (IoIsWdmVersionAvailable(1, 0x10))
+       {
+        deviceExtension->WdmVersion = Win2kOrBetter;
+
+    }
+
+    else if (IoIsWdmVersionAvailable(1, 0x5))
+       {
+        deviceExtension->WdmVersion = WinMeOrBetter;
+
+    }
+
+    else if (IoIsWdmVersionAvailable(1, 0x0))
+       {
+        deviceExtension->WdmVersion = Win98OrBetter;
+
+    }
+
+    deviceExtension->SSRegistryEnable = 0;
+    deviceExtension->SSEnable = 0;
+
+    // WinXP only: check the registry flag indicating whether
+       // the device should selectively suspend when idle
+    if (WinXpOrBetter == deviceExtension->WdmVersion)
+       {
+        FreeBT_GetRegistryDword(FREEBT_REGISTRY_PARAMETERS_PATH,
+                                 L"BulkUsbEnable",
+                                 (PULONG)(&deviceExtension->SSRegistryEnable));
+        if (deviceExtension->SSRegistryEnable)
+               {
+            // initialize DPC
+            KeInitializeDpc(&deviceExtension->DeferredProcCall, DpcRoutine, deviceObject);
+
+            // initialize the timer.
+            // the DPC and the timer in conjunction,
+            // monitor the state of the device to
+            // selectively suspend the device.
+            KeInitializeTimerEx(&deviceExtension->Timer, NotificationTimer);
+
+            // Initialize the NoDpcWorkItemPendingEvent to signaled state.
+            // This event is cleared when a Dpc is fired and signaled
+            // on completion of the work-item.
+            KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent, NotificationEvent, TRUE);
+
+            // Initialize the NoIdleReqPendEvent to ensure that the idle request
+            // is indeed complete before we unload the drivers.
+            KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent, NotificationEvent, TRUE);
+
+        }
+
+    }
+
+    // Initialize the NoIdleReqPendEvent to ensure that the idle request
+    // is indeed complete before we unload the drivers.
+    KeInitializeEvent(&deviceExtension->DelayEvent, NotificationEvent, FALSE);
+
+    // Clear the DO_DEVICE_INITIALIZING flag.
+    // Note: Do not clear this flag until the driver has set the
+    // device power state and the power DO flags.
+    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+    InterlockedIncrement(&instanceNumber);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtusb.rbuild b/reactos/drivers/bluetooth/fbtusb/fbtusb.rbuild
new file mode 100644 (file)
index 0000000..d043b0a
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<module name="fbtusb" type="kernelmodedriver" installbase="system32/drivers" installname="fbtusb.sys" allowwarnings="true">
+       <include base="fbtusb">include</include>
+       <library>ntoskrnl</library>
+       <library>hal</library>
+       <library>usbd</library>
+       <file>fbtdev.c</file>
+       <file>fbtpnp.c</file>
+       <file>fbtpwr.c</file>
+       <file>fbtrwr.c</file>
+       <file>fbtusb.c</file>
+       <!--file>fbtwmi.c</file-->
+       <file>fbtusb.rc</file>
+</module>
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtusb.rc b/reactos/drivers/bluetooth/fbtusb/fbtusb.rc
new file mode 100644 (file)
index 0000000..3fbed8c
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "Generic USB Bluetooth Driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "fbtusb\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "fbtusb.sys\0"
+#include <reactos/version.rc>
diff --git a/reactos/drivers/bluetooth/fbtusb/fbtwmi.c b/reactos/drivers/bluetooth/fbtusb/fbtwmi.c
new file mode 100755 (executable)
index 0000000..66c8da6
--- /dev/null
@@ -0,0 +1,548 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#include "fbtusb.h"
+#include "fbtpwr.h"
+#include "fbtpnp.h"
+#include "fbtdev.h"
+#include "fbtrwr.h"
+#include "fbtwmi.h"
+
+#include "fbtusr.h"
+
+#define MOFRESOURCENAME L"MofResourceName"
+
+#define WMI_FREEBT_DRIVER_INFORMATION 0
+
+DEFINE_GUID (FREEBT_WMI_STD_DATA_GUID, 0x871B1A60, 0xD3EA, 0x4f2f, 0x81, 0x7b, 0x46, 0x5e, 0x44, 0x86, 0x7b, 0xf5);
+
+WMIGUIDREGINFO FreeBTWmiGuidList[1] =
+{
+       {
+               &FREEBT_WMI_STD_DATA_GUID, 1, 0 // driver information
+
+    }
+
+};
+
+NTSTATUS FreeBT_WmiRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)
+{
+    NTSTATUS ntStatus;
+
+    PAGED_CODE();
+
+    DeviceExtension->WmiLibInfo.GuidCount = sizeof (FreeBTWmiGuidList) / sizeof (WMIGUIDREGINFO);
+    DeviceExtension->WmiLibInfo.GuidList           = FreeBTWmiGuidList;
+    DeviceExtension->WmiLibInfo.QueryWmiRegInfo    = FreeBT_QueryWmiRegInfo;
+    DeviceExtension->WmiLibInfo.QueryWmiDataBlock  = FreeBT_QueryWmiDataBlock;
+    DeviceExtension->WmiLibInfo.SetWmiDataBlock    = FreeBT_SetWmiDataBlock;
+    DeviceExtension->WmiLibInfo.SetWmiDataItem     = FreeBT_SetWmiDataItem;
+    DeviceExtension->WmiLibInfo.ExecuteWmiMethod   = NULL;
+    DeviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
+
+    // Register with WMI
+    ntStatus = IoWMIRegistrationControl(DeviceExtension->FunctionalDeviceObject, WMIREG_ACTION_REGISTER);
+
+    return ntStatus;
+
+}
+
+NTSTATUS FreeBT_WmiDeRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+    return IoWMIRegistrationControl(DeviceExtension->FunctionalDeviceObject, WMIREG_ACTION_DEREGISTER);
+
+}
+
+NTSTATUS FreeBT_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+    PDEVICE_EXTENSION       deviceExtension;
+    SYSCTL_IRP_DISPOSITION  disposition;
+    NTSTATUS                ntStatus;
+    PIO_STACK_LOCATION      irpStack;
+
+    PAGED_CODE();
+
+    irpStack = IoGetCurrentIrpStackLocation (Irp);
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+       FreeBT_DbgPrint(3, ("FBTUSB: "));
+    FreeBT_DbgPrint(3, (WMIMinorFunctionString(irpStack->MinorFunction)));
+    if (Removed == deviceExtension->DeviceState)
+       {
+        ntStatus = STATUS_DELETE_PENDING;
+
+        Irp->IoStatus.Status = ntStatus;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return ntStatus;
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchSysCtrl::"));
+    FreeBT_IoIncrement(deviceExtension);
+
+    ntStatus = WmiSystemControl(&deviceExtension->WmiLibInfo,
+                                DeviceObject,
+                                Irp,
+                                &disposition);
+
+    switch(disposition)
+       {
+        case IrpProcessed:
+        {
+            // This irp has been processed and may be completed or pending.
+            break;
+
+        }
+
+        case IrpNotCompleted:
+        {
+            // This irp has not been completed, but has been fully processed.
+            // we will complete it now
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            break;
+
+        }
+
+        case IrpForward:
+        case IrpNotWmi:
+        {
+            // This irp is either not a WMI irp or is a WMI irp targeted
+            // at a device lower in the stack.
+            IoSkipCurrentIrpStackLocation (Irp);
+            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+            break;
+        }
+
+        default:
+        {
+            // We really should never get here, but if we do just forward....
+            ASSERT(FALSE);
+            IoSkipCurrentIrpStackLocation (Irp);
+            ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
+            break;
+
+        }
+
+    }
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchSysCtrl::"));
+    FreeBT_IoDecrement(deviceExtension);
+
+    return ntStatus;
+
+}
+
+NTSTATUS FreeBT_QueryWmiRegInfo(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    OUT ULONG           *RegFlags,
+    OUT PUNICODE_STRING InstanceName,
+    OUT PUNICODE_STRING *RegistryPath,
+    OUT PUNICODE_STRING MofResourceName,
+    OUT PDEVICE_OBJECT  *Pdo
+    )
+/*++
+
+Routine Description:
+
+    This routine is a callback into the driver to retrieve the list of
+    guids or data blocks that the driver wants to register with WMI. This
+    routine may not pend or block. Driver should NOT call
+    WmiCompleteRequest.
+
+Arguments:
+
+    DeviceObject is the device whose data block is being queried
+
+    *RegFlags returns with a set of flags that describe the guids being
+        registered for this device. If the device wants enable and disable
+        collection callbacks before receiving queries for the registered
+        guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
+        returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
+        the instance name is determined from the PDO associated with the
+        device object. Note that the PDO must have an associated devnode. If
+        WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
+        name for the device.
+
+    InstanceName returns with the instance name for the guids if
+        WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
+        caller will call ExFreePool with the buffer returned.
+
+    *RegistryPath returns with the registry path of the driver
+
+    *MofResourceName returns with the name of the MOF resource attached to
+        the binary file. If the driver does not have a mof resource attached
+        then this can be returned as NULL.
+
+    *Pdo returns with the device object for the PDO associated with this
+        device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
+        *RegFlags.
+
+Return Value:
+
+    status
+
+--*/
+{
+    PDEVICE_EXTENSION deviceExtension;
+
+    PAGED_CODE();
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiRegInfo: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    *RegFlags     = WMIREG_FLAG_INSTANCE_PDO;
+    *RegistryPath = &Globals.FreeBT_RegistryPath;
+    *Pdo          = deviceExtension->PhysicalDeviceObject;
+    RtlInitUnicodeString(MofResourceName, MOFRESOURCENAME);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiRegInfo: Leaving\n"));
+
+    return STATUS_SUCCESS;
+
+}
+
+NTSTATUS FreeBT_QueryWmiDataBlock(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp,
+    IN ULONG          GuidIndex,
+    IN ULONG          InstanceIndex,
+    IN ULONG          InstanceCount,
+    IN OUT PULONG     InstanceLengthArray,
+    IN ULONG          OutBufferSize,
+    OUT PUCHAR        Buffer
+    )
+/*++
+
+Routine Description:
+
+    This routine is a callback into the driver to query for the contents of
+    a data block. When the driver has finished filling the data block it
+    must call WmiCompleteRequest to complete the irp. The driver can
+    return STATUS_PENDING if the irp cannot be completed immediately.
+
+Arguments:
+
+    DeviceObject is the device whose data block is being queried
+
+    Irp is the Irp that makes this request
+
+    GuidIndex is the index into the list of guids provided when the
+        device registered
+
+    InstanceIndex is the index that denotes which instance of the data block
+        is being queried.
+
+    InstanceCount is the number of instances expected to be returned for
+        the data block.
+
+    InstanceLengthArray is a pointer to an array of ULONG that returns the
+        lengths of each instance of the data block. If this is NULL then
+        there was not enough space in the output buffer to fulfill the request
+        so the irp should be completed with the buffer needed.
+
+    OutBufferSize has the maximum size available to write the data
+        block.
+
+    Buffer on return is filled with the returned data block
+
+
+Return Value:
+
+    status
+
+--*/
+{
+    PDEVICE_EXTENSION deviceExtension;
+    NTSTATUS          ntStatus;
+    ULONG             size;
+    WCHAR             modelName[] = L"Aishverya\0\0";
+    USHORT            modelNameLen;
+
+    PAGED_CODE();
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Entered\n"));
+
+    size = 0;
+    modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR);
+
+    // Only ever registers 1 instance per guid
+    ASSERT((InstanceIndex == 0) && (InstanceCount == 1));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    switch (GuidIndex)
+       {
+    case WMI_FREEBT_DRIVER_INFORMATION:
+        size = sizeof(ULONG) + modelNameLen + sizeof(USHORT);
+        if (OutBufferSize < size )
+               {
+            FreeBT_DbgPrint(3, ("FBTUSB: OutBuffer too small\n"));
+            ntStatus = STATUS_BUFFER_TOO_SMALL;
+            break;
+
+        }
+
+        * (PULONG) Buffer = DebugLevel;
+        Buffer += sizeof(ULONG);
+
+        // put length of string ahead of string
+        *((PUSHORT)Buffer) = modelNameLen;
+        Buffer = (PUCHAR)Buffer + sizeof(USHORT);
+        RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen);
+        *InstanceLengthArray = size ;
+
+        ntStatus = STATUS_SUCCESS;
+        break;
+
+    default:
+        ntStatus = STATUS_WMI_GUID_NOT_FOUND;
+
+    }
+
+    ntStatus = WmiCompleteRequest(DeviceObject,
+                                Irp,
+                                ntStatus,
+                                size,
+                                IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+
+NTSTATUS FreeBT_SetWmiDataItem(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp,
+    IN ULONG          GuidIndex,
+    IN ULONG          InstanceIndex,
+    IN ULONG          DataItemId,
+    IN ULONG          BufferSize,
+    IN PUCHAR         Buffer
+    )
+/*++
+
+Routine Description:
+
+    This routine is a callback into the driver to set for the contents of
+    a data block. When the driver has finished filling the data block it
+    must call WmiCompleteRequest to complete the irp. The driver can
+    return STATUS_PENDING if the irp cannot be completed immediately.
+
+Arguments:
+
+    DeviceObject is the device whose data block is being queried
+
+    Irp is the Irp that makes this request
+
+    GuidIndex is the index into the list of guids provided when the
+        device registered
+
+    InstanceIndex is the index that denotes which instance of the data block
+        is being queried.
+
+    DataItemId has the id of the data item being set
+
+    BufferSize has the size of the data item passed
+
+    Buffer has the new values for the data item
+
+
+Return Value:
+
+    status
+
+--*/
+{
+    PDEVICE_EXTENSION deviceExtension;
+    NTSTATUS          ntStatus;
+    ULONG             info;
+
+    PAGED_CODE();
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataItem: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    info = 0;
+
+    switch(GuidIndex)
+       {
+    case WMI_FREEBT_DRIVER_INFORMATION:
+        if(DataItemId == 1)
+               {
+            if(BufferSize == sizeof(ULONG))
+                       {
+                DebugLevel = *((PULONG)Buffer);
+                ntStatus = STATUS_SUCCESS;
+                info = sizeof(ULONG);
+
+            }
+
+            else
+                       {
+                ntStatus = STATUS_INFO_LENGTH_MISMATCH;
+
+            }
+
+        }
+
+        else
+               {
+            ntStatus = STATUS_WMI_READ_ONLY;
+
+        }
+
+        break;
+
+    default:
+        ntStatus = STATUS_WMI_GUID_NOT_FOUND;
+
+    }
+
+    ntStatus = WmiCompleteRequest(DeviceObject,
+                                Irp,
+                                ntStatus,
+                                info,
+                                IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataItem: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+NTSTATUS FreeBT_SetWmiDataBlock(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp,
+    IN ULONG          GuidIndex,
+    IN ULONG          InstanceIndex,
+    IN ULONG          BufferSize,
+    IN PUCHAR         Buffer
+    )
+/*++
+
+Routine Description:
+
+    This routine is a callback into the driver to set the contents of
+    a data block. When the driver has finished filling the data block it
+    must call WmiCompleteRequest to complete the irp. The driver can
+    return STATUS_PENDING if the irp cannot be completed immediately.
+
+Arguments:
+
+    DeviceObject is the device whose data block is being queried
+
+    Irp is the Irp that makes this request
+
+    GuidIndex is the index into the list of guids provided when the
+        device registered
+
+    InstanceIndex is the index that denotes which instance of the data block
+        is being queried.
+
+    BufferSize has the size of the data block passed
+
+    Buffer has the new values for the data block
+
+--*/
+{
+    PDEVICE_EXTENSION deviceExtension;
+    NTSTATUS          ntStatus;
+    ULONG             info;
+
+    PAGED_CODE();
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataBlock: Entered\n"));
+
+    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+    info = 0;
+
+    switch(GuidIndex)
+       {
+    case WMI_FREEBT_DRIVER_INFORMATION:
+        if(BufferSize == sizeof(ULONG))
+               {
+            DebugLevel = *(PULONG) Buffer;
+            ntStatus = STATUS_SUCCESS;
+            info = sizeof(ULONG);
+
+        }
+
+        else
+               {
+            ntStatus = STATUS_INFO_LENGTH_MISMATCH;
+
+        }
+
+        break;
+
+    default:
+        ntStatus = STATUS_WMI_GUID_NOT_FOUND;
+
+    }
+
+    ntStatus = WmiCompleteRequest(DeviceObject,
+                                Irp,
+                                ntStatus,
+                                info,
+                                IO_NO_INCREMENT);
+
+    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataBlock: Leaving\n"));
+
+    return ntStatus;
+
+}
+
+PCHAR WMIMinorFunctionString(UCHAR MinorFunction)
+{
+    switch (MinorFunction)
+       {
+        case IRP_MN_CHANGE_SINGLE_INSTANCE:
+            return "IRP_MN_CHANGE_SINGLE_INSTANCE\n";
+
+        case IRP_MN_CHANGE_SINGLE_ITEM:
+            return "IRP_MN_CHANGE_SINGLE_ITEM\n";
+
+        case IRP_MN_DISABLE_COLLECTION:
+            return "IRP_MN_DISABLE_COLLECTION\n";
+
+        case IRP_MN_DISABLE_EVENTS:
+            return "IRP_MN_DISABLE_EVENTS\n";
+
+        case IRP_MN_ENABLE_COLLECTION:
+            return "IRP_MN_ENABLE_COLLECTION\n";
+
+        case IRP_MN_ENABLE_EVENTS:
+            return "IRP_MN_ENABLE_EVENTS\n";
+
+        case IRP_MN_EXECUTE_METHOD:
+            return "IRP_MN_EXECUTE_METHOD\n";
+
+        case IRP_MN_QUERY_ALL_DATA:
+            return "IRP_MN_QUERY_ALL_DATA\n";
+
+        case IRP_MN_QUERY_SINGLE_INSTANCE:
+            return "IRP_MN_QUERY_SINGLE_INSTANCE\n";
+
+        case IRP_MN_REGINFO:
+            return "IRP_MN_REGINFO\n";
+
+        default:
+            return "IRP_MN_?????\n";
+
+    }
+
+}
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciCmdStructs.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciCmdStructs.h
new file mode 100755 (executable)
index 0000000..1e91486
--- /dev/null
@@ -0,0 +1,721 @@
+#ifndef _FBT_HCI_CMD_STRUCTS_H
+#define _FBT_HCI_CMD_STRUCTS_H
+
+// Pack structures to single unsigned char boundries
+#pragma pack(push, 1)
+
+// Command Header
+typedef struct
+{
+    unsigned short     OpCode;
+    unsigned char      ParameterLength;
+
+} FBT_HCI_CMD_HEADER, *PFBT_HCI_CMD_HEADER;
+
+//  Link control commands
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              LAP[FBT_HCI_LAP_SIZE];
+    unsigned char              InquiryLength;
+    unsigned char              NumResponses;
+
+} FBT_HCI_INQUIRY, *PFBT_HCI_INQUIRY;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_INQUIRY_CANCEL, *PFBT_HCI_INQUIRY_CANCEL;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             MaxPeriodLength;
+    unsigned short             MinPeriodLength;
+    unsigned char              LAP[FBT_HCI_LAP_SIZE];
+    unsigned char              InquiryLength;
+    unsigned char              NumResponses;
+
+} FBT_HCI_PERIODIC_INQUIRY_MODE, *PFBT_HCI_PERIODIC_INQUIRY_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_EXIT_PERIODIC_INQUIRY_MODE, *PFBT_HCI_EXIT_PERIODIC_INQUIRY_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned short             PacketType;
+    unsigned char              PageScanRepetitionMode;
+    unsigned char              PageScanMode;
+    unsigned short             ClockOffset;
+    unsigned char              AllowRoleSwitch;
+
+} FBT_HCI_CREATE_CONNECTION, *PFBT_HCI_CREATE_CONNECTION;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned char              Reason;
+
+} FBT_HCI_DISCONNECT, *PFBT_HCI_DISCONNECT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             PacketType;
+
+} FBT_HCI_ADD_SCO_CONNECTION, *PFBT_HCI_ADD_SCO_CONNECTION;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              Role;
+
+} FBT_HCI_ACCEPT_CONNECTION_REQUEST, *PFBT_HCI_ACCEPT_CONNECTION_REQUEST;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              Reason;
+
+} FBT_HCI_REJECT_CONNECTION_REQUEST, *PFBT_HCI_REJECT_CONNECTION_REQUEST;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              LinkKey[FBT_HCI_LINK_KEY_SIZE];
+
+} FBT_HCI_LINK_KEY_REQUEST_REPLY, *PFBT_HCI_LINK_KEY_REQUEST_REPLY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+
+} FBT_HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY, *PFBT_HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              PINCodeLength;
+    unsigned char              PINCode[FBT_HCI_PIN_CODE_SIZE];
+
+} FBT_HCI_PIN_CODE_REQUEST_REPLY, *PFBT_HCI_PIN_CODE_REQUEST_REPLY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+
+} FBT_HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY, *PFBT_HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             PacketType;
+
+} FBT_HCI_CHANGE_CONNECTION_PACKET_TYPE, *PFBT_HCI_CHANGE_CONNECTION_PACKET_TYPE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_AUTHENTICATION_REQUESTED, *PFBT_HCI_AUTHENTICATION_REQUESTED;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned char              EncryptionEnable;
+
+} FBT_HCI_SET_CONNECTION_ENCRYPTION, *PFBT_HCI_SET_CONNECTION_ENCRYPTION;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_CHANGE_CONNECTION_LINK_KEY, *PFBT_HCI_CHANGE_CONNECTION_LINK_KEY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              KeyFlag;
+
+} FBT_HCI_MASTER_LINK_KEY, *PFBT_HCI_MASTER_LINK_KEY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              PageScanRepetitionMode;
+    unsigned char              PageScanMode;
+    unsigned short             ClockOffset;
+
+} FBT_HCI_REMOTE_NAME_REQUEST, *PFBT_HCI_REMOTE_NAME_REQUEST;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_REMOTE_SUPPORTED_FEATURES, *PFBT_HCI_READ_REMOTE_SUPPORTED_FEATURES;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_REMOTE_VERSION_INFORMATION, *PFBT_HCI_READ_REMOTE_VERSION_INFORMATION;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_CLOCK_OFFSET, *PFBT_HCI_READ_CLOCK_OFFSET;
+
+
+//  Link policy commands
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             HoldModeMaxInterval;
+    unsigned short             HoldModeMinInterval;
+
+} FBT_HCI_HOLD_MODE, *PFBT_HCI_HOLD_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             SniffMaxInterval;
+    unsigned short             SniffMinInterval;
+    unsigned short             SniffAttempt;
+    unsigned short             SniffTimeout;
+
+} FBT_HCI_SNIFF_MODE, *PFBT_HCI_SNIFF_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_EXIT_SNIFF_MODE, *PFBT_HCI_EXIT_SNIFF_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             BeaconMaxInterval;
+    unsigned short             BeaconMinInterval;
+
+} FBT_HCI_PARK_MODE, *PFBT_HCI_PARK_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_EXIT_PARK_MODE, *PFBT_HCI_EXIT_PARK_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned char              Flags;
+    unsigned char              ServiceType;
+    unsigned long              TokenRate;
+    unsigned long              PeakBandwidth;
+    unsigned long              Latency;
+    unsigned long              DelayVariation;
+
+} FBT_HCI_QOS_SETUP, *PFBT_HCI_QOS_SETUP;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_ROLE_DISCOVERY, *PFBT_HCI_ROLE_DISCOVERY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              Role;
+
+} FBT_HCI_SWITCH_ROLE, *PFBT_HCI_SWITCH_ROLE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_LINK_POLICY_SETTINGS, *PFBT_HCI_READ_LINK_POLICY_SETTINGS;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             LinkPolicySettings;
+
+} FBT_HCI_WRITE_LINK_POLICY_SETTINGS, *PFBT_HCI_WRITE_LINK_POLICY_SETTINGS;
+
+
+//  Host Controller and Baseband commands
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              EventMask[8];
+
+} FBT_HCI_SET_EVENT_MASK, *PFBT_HCI_SET_EVENT_MASK;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_RESET, *PFBT_HCI_RESET;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              FilterType;
+    unsigned char              FilterConditionType;
+    unsigned char              Condition[7];
+
+} FBT_HCI_SET_EVENT_FILTER, *PFBT_HCI_SET_EVENT_FILTER;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_FLUSH, *PFBT_HCI_FLUSH;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_PIN_TYPE, *PFBT_HCI_READ_PIN_TYPE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char                      PinType;
+
+} FBT_HCI_WRITE_PIN_TYPE, *PFBT_HCI_WRITE_PIN_TYPE;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_CREATE_NEW_UNIT_KEY, *PFBT_HCI_CREATE_NEW_UNIT_KEY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              ReadAllFlag;
+
+} FBT_HCI_READ_STORED_LINK_KEY, *PFBT_HCI_READ_STORED_LINK_KEY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              NumKeysToWrite;
+    unsigned char              BD_ADDR[FBT_HCI_VARIABLE_SIZE][FBT_HCI_BDADDR_SIZE];
+    unsigned char              LinkKey[FBT_HCI_VARIABLE_SIZE][FBT_HCI_LINK_KEY_SIZE];
+
+} FBT_HCI_WRITE_STORED_LINK_KEY, *PFBT_HCI_WRITE_STORED_LINK_KEY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char              DeleteAllFlag;
+
+} FBT_HCI_DELETE_STORED_LINK_KEY, *PFBT_HCI_DELETE_STORED_LINK_KEY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              Name[FBT_HCI_NAME_SIZE];
+
+} FBT_HCI_CHANGE_LOCAL_NAME, *PFBT_HCI_CHANGE_LOCAL_NAME;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_READ_LOCAL_NAME, *PFBT_HCI_READ_LOCAL_NAME;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_READ_CONNECTION_ACCEPT_TIMEOUT, *PFBT_HCI_READ_CONNECTION_ACCEPT_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnAcceptTimeout;
+
+} FBT_HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT, *PFBT_HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_PAGE_TIMEOUT, *PFBT_HCI_READ_PAGE_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             PageTimeout;
+
+} FBT_HCI_WRITE_PAGE_TIMEOUT, *PFBT_HCI_WRITE_PAGE_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_SCAN_ENABLE, *PFBT_HCI_READ_SCAN_ENABLE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              ScanEnable;
+
+} FBT_HCI_WRITE_SCAN_ENABLE, *PFBT_HCI_WRITE_SCAN_ENABLE;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_READ_PAGE_SCAN_ACTIVITY, *PFBT_HCI_READ_PAGE_SCAN_ACTIVITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             PageScanInterval;
+    unsigned short             PageScanWindow;
+
+} FBT_HCI_WRITE_PAGE_SCAN_ACTIVITY, *PFBT_HCI_WRITE_PAGE_SCAN_ACTIVITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_INQUIRY_SCAN_ACTIVITY, *PFBT_HCI_READ_INQUIRY_SCAN_ACTIVITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             InquiryScanInterval;
+    unsigned short             InquiryScanWindow;
+
+} FBT_HCI_WRITE_INQUIRY_SCAN_ACTIVITY, *PFBT_HCI_WRITE_INQUIRY_SCAN_ACTIVITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_AUTHENTICATION_ENABLE, *PFBT_HCI_READ_AUTHENTICATION_ENABLE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              AuthenticationEnable;
+
+} FBT_HCI_WRITE_AUTHENTICATION_ENABLE, *PFBT_HCI_WRITE_AUTHENTICATION_ENABLE;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_READ_ENCRYPTION_MODE, *PFBT_HCI_READ_ENCRYPTION_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              EncryptionMode;
+
+} FBT_HCI_WRITE_ENCRYPTION_MODE, *PFBT_HCI_WRITE_ENCRYPTION_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_CLASS_OF_DEVICE, *PFBT_HCI_READ_CLASS_OF_DEVICE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE];
+
+} FBT_HCI_WRITE_CLASS_OF_DEVICE, *PFBT_HCI_WRITE_CLASS_OF_DEVICE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_VOICE_SETTING, *PFBT_HCI_READ_VOICE_SETTING;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             VoiceSetting;
+
+} FBT_HCI_WRITE_VOICE_SETTING, *PFBT_HCI_WRITE_VOICE_SETTING;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_AUTOMATIC_FLUSH_TIMEOUT, *PFBT_HCI_READ_AUTOMATIC_FLUSH_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             FlushTimeout;
+
+} FBT_HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT, *PFBT_HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_NUM_BROADCAST_RETRANSMISSIONS, *PFBT_HCI_READ_NUM_BROADCAST_RETRANSMISSIONS;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              NumBroadcastRetran;
+
+} FBT_HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS, *PFBT_HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS;
+
+typedef struct
+{
+       FBT_HCI_CMD_HEADER      CommandHeader;
+
+} FBT_HCI_READ_HOLD_MODE_ACTIVITY, *PFBT_HCI_READ_HOLD_MODE_ACTIVITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              HoldModeActivity;
+
+} FBT_HCI_WRITE_HOLD_MODE_ACTIVITY, *PFBT_HCI_WRITE_HOLD_MODE_ACTIVITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned char              Type;
+
+} FBT_HCI_READ_TRANSMIT_POWER_LEVEL, *PFBT_HCI_READ_TRANSMIT_POWER_LEVEL;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_SCO_FLOW_CONTROL_ENABLE, *PFBT_HCI_READ_SCO_FLOW_CONTROL_ENABLE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              ScoFlowControlEnable;
+
+} FBT_HCI_WRITE_SCO_FLOW_CONTROL_ENABLE, *PFBT_HCI_WRITE_SCO_FLOW_CONTROL_ENABLE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              FlowControlEnable;
+
+} FBT_HCI_SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL, *PFBT_HCI_SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             AclDataPacketLength;
+    unsigned char              ScoDataPacketLength;
+    unsigned short             TotalNumAclDataPackets;
+    unsigned short             TotalNumScoDataPackets;
+
+} FBT_HCI_HOST_BUFFER_SIZE, *PFBT_HCI_HOST_BUFFER_SIZE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              NumberOfHandles;
+    unsigned short             ConnectionHandle[FBT_HCI_VARIABLE_SIZE];
+    unsigned short             HostNumOfCompletedPackets[FBT_HCI_VARIABLE_SIZE];
+
+} FBT_HCI_HOST_NUMBER_OF_COMPLETED_PACKETS, *PFBT_HCI_HOST_NUMBER_OF_COMPLETED_PACKETS;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_LINK_SUPERVISION_TIMEOUT, *PFBT_HCI_READ_LINK_SUPERVISION_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+    unsigned short             LinkSupervisionTimeout;
+
+} FBT_HCI_WRITE_LINK_SUPERVISION_TIMEOUT, *PFBT_HCI_WRITE_LINK_SUPERVISION_TIMEOUT;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_NUMBER_OF_SUPPORTED_IAC, *PFBT_HCI_READ_NUMBER_OF_SUPPORTED_IAC;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_CURRENT_IAC_LAP, *PFBT_HCI_READ_CURRENT_IAC_LAP;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              NumCurrentIac;
+    unsigned char              IacLap[FBT_HCI_VARIABLE_SIZE][FBT_HCI_LAP_SIZE];
+
+} FBT_HCI_WRITE_CURRENT_IAC_LAP, *PFBT_HCI_WRITE_CURRENT_IAC_LAP;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_PAGE_SCAN_PERIOD_MODE, *PFBT_HCI_READ_PAGE_SCAN_PERIOD_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              PageScanPeriodMode;
+
+} FBT_HCI_WRITE_PAGE_SCAN_PERIOD_MODE, *PFBT_HCI_WRITE_PAGE_SCAN_PERIOD_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_PAGE_SCAN_MODE, *PFBT_HCI_READ_PAGE_SCAN_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              PageScanMode;
+
+} FBT_HCI_WRITE_PAGE_SCAN_MODE, *PFBT_HCI_WRITE_PAGE_SCAN_MODE;
+
+
+//  Informational parameters
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_LOCAL_VERSION_INFORMATION, *PFBT_HCI_READ_LOCAL_VERSION_INFORMATION;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_LOCAL_SUPPORTED_FEATURES, *PFBT_HCI_READ_LOCAL_SUPPORTED_FEATURES;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_BUFFER_SIZE, *PFBT_HCI_READ_BUFFER_SIZE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_COUNTRY_CODE, *PFBT_HCI_READ_COUNTRY_CODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_BD_ADDR, *PFBT_HCI_READ_BD_ADDR;
+
+
+//  Status parameter commands
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_FAILED_CONTACT_COUNTER, *PFBT_HCI_READ_FAILED_CONTACT_COUNTER;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_RESET_FAILED_CONTACT_COUNTER, *PFBT_HCI_RESET_FAILED_CONTACT_COUNTER;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_GET_LINK_QUALITY, *PFBT_HCI_GET_LINK_QUALITY;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned short             ConnectionHandle;
+
+} FBT_HCI_READ_RSSI, *PFBT_HCI_READ_RSSI;
+
+
+//  Testing commands
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_READ_LOOPBACK_MODE, *PFBT_HCI_READ_LOOPBACK_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+    unsigned char              LoopbackMode;
+
+} FBT_HCI_WRITE_LOOPBACK_MODE, *PFBT_HCI_WRITE_LOOPBACK_MODE;
+
+typedef struct
+{
+    FBT_HCI_CMD_HEADER CommandHeader;
+
+} FBT_HCI_ENABLE_DEVICE_UNDER_TEST_MODE, *PFBT_HCI_ENABLE_DEVICE_UNDER_TEST_MODE;
+
+#pragma pack(pop)
+
+#endif // _FBT_HCI_CMD_STRUCTS_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciCmds.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciCmds.h
new file mode 100755 (executable)
index 0000000..cb0dbf7
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef _FBT_HCI_COMMANDS_H
+#define _FBT_HCI_COMMANDS_H
+
+#include "fbtHciOpcodes.h"
+#include "fbtHciSizes.h"
+
+#include "fbtHciCmdStructs.h"
+#include "fbtHciParms.h"
+
+// Utility macro to build a command CMD from ints constituent OCF/OGF
+#define FBT_HCI_CMD(nOCF, nOGF) ((unsigned short) nOCF + (unsigned short)(nOGF << 10))
+
+// HCI Command CMDs
+// Link control CMDs
+#define FBT_HCI_CMD_INQUIRY                                                            FBT_HCI_CMD(FBT_HCI_OCF_INQUIRY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_INQUIRY_CANCEL                                             FBT_HCI_CMD(FBT_HCI_OCF_INQUIRY_CANCEL, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_PERIODIC_INQUIRY_MODE                              FBT_HCI_CMD(FBT_HCI_OCF_PERIODIC_INQUIRY_MODE, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_EXIT_PERIODIC_INQUIRY_MODE                 FBT_HCI_CMD(FBT_HCI_OCF_EXIT_PERIODIC_INQUIRY_MODE, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_CREATE_CONNECTION                                  FBT_HCI_CMD(FBT_HCI_OCF_CREATE_CONNECTION, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_DISCONNECT                                                 FBT_HCI_CMD(FBT_HCI_OCF_DISCONNECT, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_ADD_SCO_CONNECTION                                 FBT_HCI_CMD(FBT_HCI_OCF_ADD_SCO_CONNECTION, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_ACCEPT_CONNECTION_REQUEST                  FBT_HCI_CMD(FBT_HCI_OCF_ACCEPT_CONNECTION_REQUEST, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_REJECT_CONNECTION_REQUEST                  FBT_HCI_CMD(FBT_HCI_OCF_REJECT_CONNECTION_REQUEST, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_LINK_KEY_REQUEST_REPLY                             FBT_HCI_CMD(FBT_HCI_OCF_LINK_KEY_REQUEST_REPLY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_LINK_KEY_REQUEST_NEGATIVE_REPLY            FBT_HCI_CMD(FBT_HCI_OCF_LINK_KEY_REQUEST_NEGATIVE_REPLY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_PIN_CODE_REQUEST_REPLY                             FBT_HCI_CMD(FBT_HCI_OCF_PIN_CODE_REQUEST_REPLY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_PIN_CODE_REQUEST_NEGATIVE_REPLY            FBT_HCI_CMD(FBT_HCI_OCF_PIN_CODE_REQUEST_NEGATIVE_REPLY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_CHANGE_CONNECTION_PACKET_TYPE              FBT_HCI_CMD(FBT_HCI_OCF_CHANGE_CONNECTION_PACKET_TYPE, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_AUTHENTICATION_REQUESTED                   FBT_HCI_CMD(FBT_HCI_OCF_AUTHENTICATION_REQUESTED, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_SET_CONNECTION_ENCRYPTION                  FBT_HCI_CMD(FBT_HCI_OCF_SET_CONNECTION_ENCRYPTION, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_CHANGE_CONNECTION_LINK_KEY                 FBT_HCI_CMD(FBT_HCI_OCF_CHANGE_CONNECTION_LINK_KEY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_MASTER_LINK_KEY                                            FBT_HCI_CMD(FBT_HCI_OCF_MASTER_LINK_KEY, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_REMOTE_NAME_REQUEST                                        FBT_HCI_CMD(FBT_HCI_OCF_REMOTE_NAME_REQUEST, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_READ_REMOTE_SUPPORTED_FEATURES             FBT_HCI_CMD(FBT_HCI_OCF_READ_REMOTE_SUPPORTED_FEATURES, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_READ_REMOTE_VERSION_INFORMATION            FBT_HCI_CMD(FBT_HCI_OCF_READ_REMOTE_VERSION_INFORMATION, FBT_HCI_OGF_LINK_CONTROL)
+#define FBT_HCI_CMD_READ_CLOCK_OFFSET                                  FBT_HCI_CMD(FBT_HCI_OCF_READ_CLOCK_OFFSET, FBT_HCI_OGF_LINK_CONTROL)
+
+// Link policy CMDs
+#define FBT_HCI_CMD_HOLD_MODE                                  FBT_HCI_CMD(FBT_HCI_OCF_HOLD_MODE, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_SNIFF_MODE                  FBT_HCI_CMD(FBT_HCI_OCF_SNIFF_MODE, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_EXIT_SNIFF_MODE             FBT_HCI_CMD(FBT_HCI_OCF_EXIT_SNIFF_MODE, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_PARK_MODE                   FBT_HCI_CMD(FBT_HCI_OCF_PARK_MODE, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_EXIT_PARK_MODE              FBT_HCI_CMD(FBT_HCI_OCF_EXIT_PARK_MODE, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_QOS_SETUP                   FBT_HCI_CMD(FBT_HCI_OCF_QOS_SETUP, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_ROLE_DISCOVERY              FBT_HCI_CMD(FBT_HCI_OCF_ROLE_DISCOVERY, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_SWITCH_ROLE                 FBT_HCI_CMD(FBT_HCI_OCF_SWITCH_ROLE, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_READ_LINK_POLICY_SETTINGS  FBT_HCI_CMD(FBT_HCI_OCF_READ_LINK_POLICY_SETTINGS, FBT_HCI_OGF_LINK_POLICY)
+#define FBT_HCI_CMD_WRITE_LINK_POLICY_SETTINGS FBT_HCI_CMD(FBT_HCI_OCF_WRITE_LINK_POLICY_SETTINGS, FBT_HCI_OGF_LINK_POLICY)
+
+// Host controller & baseband command CMDs
+#define FBT_HCI_CMD_SET_EVENT_MASK                            FBT_HCI_CMD(FBT_HCI_OCF_SET_EVENT_MASK, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_RESET                                     FBT_HCI_CMD(FBT_HCI_OCF_RESET, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_SET_EVENT_FILTER                          FBT_HCI_CMD(FBT_HCI_OCF_SET_EVENT_FILTER, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_FLUSH                                     FBT_HCI_CMD(FBT_HCI_OCF_FLUSH, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_PIN_TYPE                             FBT_HCI_CMD(FBT_HCI_OCF_READ_PIN_TYPE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_PIN_TYPE                            FBT_HCI_CMD(FBT_HCI_OCF_WRITE_PIN_TYPE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_CREATE_NEW_UNIT_KEY                       FBT_HCI_CMD(FBT_HCI_OCF_CREATE_NEW_UNIT_KEY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_STORED_LINK_KEY                      FBT_HCI_CMD(FBT_HCI_OCF_READ_STORED_LINK_KEY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_STORED_LINK_KEY                     FBT_HCI_CMD(FBT_HCI_OCF_WRITE_STORED_LINK_KEY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_DELETE_STORED_LINK_KEY                    FBT_HCI_CMD(FBT_HCI_OCF_DELETE_STORED_LINK_KEY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_CHANGE_LOCAL_NAME                         FBT_HCI_CMD(FBT_HCI_OCF_CHANGE_LOCAL_NAME, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_LOCAL_NAME                           FBT_HCI_CMD(FBT_HCI_OCF_READ_LOCAL_NAME, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_CONNECTION_ACCEPT_TIMEOUT            FBT_HCI_CMD(FBT_HCI_OCF_READ_CONNECTION_ACCEPT_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_CONNECTION_ACCEPT_TIMEOUT           FBT_HCI_CMD(FBT_HCI_OCF_WRITE_CONNECTION_ACCEPT_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_PAGE_TIMEOUT                         FBT_HCI_CMD(FBT_HCI_OCF_READ_PAGE_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_PAGE_TIMEOUT                        FBT_HCI_CMD(FBT_HCI_OCF_WRITE_PAGE_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_SCAN_ENABLE                          FBT_HCI_CMD(FBT_HCI_OCF_READ_SCAN_ENABLE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_SCAN_ENABLE                         FBT_HCI_CMD(FBT_HCI_OCF_WRITE_SCAN_ENABLE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_PAGE_SCAN_ACTIVITY                   FBT_HCI_CMD(FBT_HCI_OCF_READ_PAGE_SCAN_ACTIVITY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_PAGE_SCAN_ACTIVITY                  FBT_HCI_CMD(FBT_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY                FBT_HCI_CMD(FBT_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_INQUIRY_SCAN_ACTIVITY               FBT_HCI_CMD(FBT_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_AUTHENTICATION_ENABLE                FBT_HCI_CMD(FBT_HCI_OCF_READ_AUTHENTICATION_ENABLE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_AUTHENTICATION_ENABLE               FBT_HCI_CMD(FBT_HCI_OCF_WRITE_AUTHENTICATION_ENABLE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_ENCRYPTION_MODE                      FBT_HCI_CMD(FBT_HCI_OCF_READ_ENCRYPTION_MODE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_ENCRYPTION_MODE                     FBT_HCI_CMD(FBT_HCI_OCF_WRITE_ENCRYPTION_MODE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_CLASS_OF_DEVICE                      FBT_HCI_CMD(FBT_HCI_OCF_READ_CLASS_OF_DEVICE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_CLASS_OF_DEVICE                     FBT_HCI_CMD(FBT_HCI_OCF_WRITE_CLASS_OF_DEVICE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_VOICE_SETTING                        FBT_HCI_CMD(FBT_HCI_OCF_READ_VOICE_SETTING, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_VOICE_SETTING                       FBT_HCI_CMD(FBT_HCI_OCF_WRITE_VOICE_SETTING, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_AUTOMATIC_FLUSH_TIMEOUT              FBT_HCI_CMD(FBT_HCI_OCF_READ_AUTOMATIC_FLUSH_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_AUTOMATIC_FLUSH_TIMEOUT             FBT_HCI_CMD(FBT_HCI_OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_NUM_BROADCAST_RETRANSMISSIONS        FBT_HCI_CMD(FBT_HCI_OCF_READ_NUM_BROADCAST_RETRANSMISSIONS, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_NUM_BROADCAST_RETRANSMISSIONS       FBT_HCI_CMD(FBT_HCI_OCF_WRITE_NUM_BROADCAST_RETRANSMISSIONS, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_HOLD_MODE_ACTIVITY                   FBT_HCI_CMD(FBT_HCI_OCF_READ_HOLD_MODE_ACTIVITY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_HOLD_MODE_ACTIVITY                  FBT_HCI_CMD(FBT_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_TRANSMIT_POWER_LEVEL                 FBT_HCI_CMD(FBT_HCI_OCF_READ_TRANSMIT_POWER_LEVEL, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_SCO_FLOW_CONTROL_ENABLE              FBT_HCI_CMD(FBT_HCI_OCF_READ_SCO_FLOW_CONTROL_ENABLE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_SCO_FLOW_CONTROL_ENABLE             FBT_HCI_CMD(FBT_HCI_OCF_WRITE_SCO_FLOW_CONTROL_ENABLE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL  FBT_HCI_CMD(FBT_HCI_OCF_SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_HOST_BUFFER_SIZE                          FBT_HCI_CMD(FBT_HCI_OCF_HOST_BUFFER_SIZE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_HOST_NUMBER_OF_COMPLETED_PACKETS          FBT_HCI_CMD(FBT_HCI_OCF_HOST_NUMBER_OF_COMPLETED_PACKETS, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT             FBT_HCI_CMD(FBT_HCI_OCF_READ_LINK_SUPERVISION_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT            FBT_HCI_CMD(FBT_HCI_OCF_WRITE_LINK_SUPERVISION_TIMEOUT, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_NUMBER_OF_SUPPORTED_IAC              FBT_HCI_CMD(FBT_HCI_OCF_READ_NUMBER_OF_SUPPORTED_IAC, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_CURRENT_IAC_LAP                      FBT_HCI_CMD(FBT_HCI_OCF_READ_CURRENT_IAC_LAP, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_CURRENT_IAC_LAP                     FBT_HCI_CMD(FBT_HCI_OCF_WRITE_CURRENT_IAC_LAP, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_PAGE_SCAN_PERIOD_MODE                FBT_HCI_CMD(FBT_HCI_OCF_READ_PAGE_SCAN_PERIOD_MODE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_PAGE_SCAN_PERIOD_MODE               FBT_HCI_CMD(FBT_HCI_OCF_WRITE_PAGE_SCAN_PERIOD_MODE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_READ_PAGE_SCAN_MODE                       FBT_HCI_CMD(FBT_HCI_OCF_READ_PAGE_SCAN_MODE, FBT_HCI_OGF_CONTROL_BASEBAND)
+#define FBT_HCI_CMD_WRITE_PAGE_SCAN_MODE                      FBT_HCI_CMD(FBT_HCI_OCF_WRITE_PAGE_SCAN_MODE, FBT_HCI_OGF_CONTROL_BASEBAND)
+
+// Informational parameters CMDs
+#define FBT_HCI_CMD_READ_LOCAL_VERSION_INFORMATION         FBT_HCI_CMD(FBT_HCI_OCF_READ_LOCAL_VERSION_INFORMATION, FBT_HCI_OGF_INFORMATIONAL_PARAMETERS)
+#define FBT_HCI_CMD_LOCAL_SUPPPROTED_FEATURES              FBT_HCI_CMD(FBT_HCI_OCF_LOCAL_SUPPPROTED_FEATURES, FBT_HCI_OGF_INFORMATIONAL_PARAMETERS)
+#define FBT_HCI_CMD_READ_BUFFER_SIZE                       FBT_HCI_CMD(FBT_HCI_OCF_READ_BUFFER_SIZE, FBT_HCI_OGF_INFORMATIONAL_PARAMETERS)
+#define FBT_HCI_CMD_READ_COUNTRY_CODE                      FBT_HCI_CMD(FBT_HCI_OCF_READ_COUNTRY_CODE, FBT_HCI_OGF_INFORMATIONAL_PARAMETERS)
+#define FBT_HCI_CMD_READ_BD_ADDR                           FBT_HCI_CMD(FBT_HCI_OCF_READ_BD_ADDR, FBT_HCI_OGF_INFORMATIONAL_PARAMETERS)
+
+// Status parameters CMDs
+#define FBT_HCI_CMD_READ_FAILED_CONTACT_COUNTER            FBT_HCI_CMD(FBT_HCI_OCF_READ_FAILED_CONTACT_COUNTER, FBT_HCI_OGF_STATUS_PARAMETERS)
+#define FBT_HCI_CMD_RESET_FAILED_CONTACT_COUNTER           FBT_HCI_CMD(FBT_HCI_OCF_RESET_FAILED_CONTACT_COUNTER, FBT_HCI_OGF_STATUS_PARAMETERS)
+#define FBT_HCI_CMD_GET_LINK_QUALITY                       FBT_HCI_CMD(FBT_HCI_OCF_GET_LINK_QUALITY, FBT_HCI_OGF_STATUS_PARAMETERS)
+#define FBT_HCI_CMD_READ_RSSI                              FBT_HCI_CMD(FBT_HCI_OCF_READ_RSSI, FBT_HCI_OGF_STATUS_PARAMETERS)
+
+// Testing CMDs
+#define FBT_HCI_CMD_READ_LOOPBACK_MODE                     FBT_HCI_CMD(FBT_HCI_OCF_READ_LOOPBACK_MODE, FBT_HCI_OGF_TESTING)
+#define FBT_HCI_CMD_WRITE_LOOPBACK_MODE                    FBT_HCI_CMD(FBT_HCI_OCF_WRITE_LOOPBACK_MODE, FBT_HCI_OGF_TESTING)
+#define FBT_HCI_CMD_ENABLE_DEVICE_UNDER_TEST_MODE          FBT_HCI_CMD(FBT_HCI_OCF_ENABLE_DEVICE_UNDER_TEST_MODE, FBT_HCI_OGF_TESTING)
+
+// Packet Boundry Flags (ORed into the upper 8 bits of the connection handle)
+#define FBT_HCI_PACKET_BOUNDRY_FIRST         0x20
+#define FBT_HCI_PACKET_BOUNDRY_NEXT          0x10
+
+// HCI header types
+#define FBT_HCI_SYNC_HCI_COMMAND_PACKET        0x01
+#define FBT_HCI_SYNC_ACL_DATA_PACKET           0x02
+#define FBT_HCI_SYNC_SCO_DATA_PACKET           0x03
+#define FBT_HCI_SYNC_HCI_EVENT_PACKET          0x04
+
+// Packet types for use in CreateConnection
+#define FBT_HCI_PACKET_TYPE_DM1        0x0008  // 1 time slot, 1-18 bytes of data, FEC encoded
+#define FBT_HCI_PACKET_TYPE_DH1        0x0010  // 1 time slot, 1-28 bytes of data, not FEC encoded
+
+#define FBT_HCI_PACKET_TYPE_DM3        0x0400  // 3 time slots, 2-123 bytes of data, FEC encoded
+#define FBT_HCI_PACKET_TYPE_DH3        0x0800  // 3 time slots, 2-185 bytes of data, not FEC encoded
+
+#define FBT_HCI_PACKET_TYPE_DM5        0x4000  // 5 time slots, 2-226 bytes of data, FEC encoded
+#define FBT_HCI_PACKET_TYPE_DH5        0x8000  // 3 time slots, 2-341 bytes of data, not FEC encoded
+
+// LAP codes for use in Inquiry
+#define FBT_HCI_LAP_GIAC       0x9E8B33
+#define FBT_HCI_LAP_LIAC       0x9E8B00
+
+// Link Types
+#define FBT_HCI_LINK_TYPE_SCO          0x00
+#define FBT_HCI_LINK_TYPE_ACL          0x01
+
+// Maximum number of each type of handle
+#define FBT_HCI_MAX_ALLOWED_ACL_HANDLES        32
+#define FBT_HCI_MAX_ALLOWED_SCO_HANDLES        4
+
+#endif // _FBT_HCI_COMMANDS_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciDefs.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciDefs.h
new file mode 100755 (executable)
index 0000000..f8894fe
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _FBT_HCI_DEFS_H
+#define _FBT_HCI_DEFS_H
+
+#include "fbtHciCmds.h"
+#include "fbtHciEvents.h"
+#include "fbtHciErrors.h"
+
+#endif // _FBT_HCI_DEFS_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciErrors.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciErrors.h
new file mode 100755 (executable)
index 0000000..9885162
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _FBT_HCI_ERROR_H
+#define _FBT_HCI_ERROR_H
+
+#define FBT_HCI_ERROR_SUCCESS                                                          0x00
+#define FBT_HCI_UNKNOWN_HCI_COMMAND                                                                                    0x01
+#define FBT_HCI_UNKNOWN_CONNECTION_IDENTIFIER                                                          0x02
+#define FBT_HCI_HARDWARE_FAILURE                                                                                       0x03
+#define FBT_HCI_PAGE_TIMEOUT                                                                                           0x04
+#define FBT_HCI_AUTHENTICATION_FAILURE                                                                         0x05
+#define FBT_HCI_PIN_MISSING                                                                                                    0x06
+#define FBT_HCI_MEMORY_CAPACITY_EXCEEDED                                                                       0x07
+#define FBT_HCI_CONNECTION_TIMEOUT                                                                                     0x08
+#define FBT_HCI_CONNECTION_LIMIT EXCEEDED                                                                      0x09
+#define FBT_HCI_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE EXCEEDED                      0x0a
+#define FBT_HCI_ACL_CONNECTION_ALREADY_EXISTS                                                          0x0b
+#define FBT_HCI_COMMAND_DISALLOWED                                                                                     0x0c
+#define FBT_HCI_CONNECTION_REJECTED_DUE_TO_LIMITED RESOURCES                           0x0d
+#define FBT_HCI_CONNECTION_REJECTED_DUE_TO_SECURITY REASONS                                    0x0e
+#define FBT_HCI_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE BD_ADDR                                0x0f
+#define FBT_HCI_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED                                                     0x10
+#define FBT_HCI_UNSUPPORTED_FEATURE_OR_PARAMETER VALUE                                         0x11
+#define FBT_HCI_INVALID_HCI_COMMAND_PARAMETERS                                                         0x12
+#define FBT_HCI_REMOTE_USER_TERMINATED_CONNECTION                                                      0x13
+#define FBT_HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES       0x14
+#define FBT_HCI_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER OFF           0x15
+#define FBT_HCI_CONNECTION_TERMINATED_BY_LOCAL_HOST                                                    0x16
+#define FBT_HCI_REPEATED_ATTEMPTS                                                                                      0x17
+#define FBT_HCI_PAIRING_NOT ALLOWED                                                                                    0x18
+#define FBT_HCI_UNKNOWN_LMP_PDU                                                                                                0x19
+#define FBT_HCI_UNSUPPORTED_REMOTE_FEATURE                                                                     0x1a
+#define FBT_HCI_SCO_OFFSET_REJECTED                                                                                    0x1b
+#define FBT_HCI_SCO_INTERVAL_REJECTED                                                                          0x1c
+#define FBT_HCI_SCO_AIR_MODE_REJECTED                                                                          0x1d
+#define FBT_HCI_INVALID_LMP_PARAMETERS                                                                         0x1e
+#define FBT_HCI_UNSPECIFIED_ERROR                                                                                      0x1f
+#define FBT_HCI_UNSUPPORTED_LMP_PARAMETER_VALUE                                                                0x20
+#define FBT_HCI_ROLE_CHANGE_NOT_ALLOWED                                                                                0x21
+#define FBT_HCI_LMP_RESPONSE_TIMEOUT                                                                           0x22
+#define FBT_HCI_LMP_ERROR_TRANSACTION_COLLISION                                                                0x23
+#define FBT_HCI_LMP_PDU_NOT_ALLOWED                                                                                    0x24
+#define FBT_HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE                                                         0x25
+#define FBT_HCI_LINK_KEY_CAN_NOT_BE_CHANGED                                                                    0x26
+#define FBT_HCI_REQUESTED_QOS_NOT_SUPPORTED                                                                    0x27
+#define FBT_HCI_INSTANT_PASSED                                                                                         0x28
+#define FBT_HCI_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED                                                    0x29
+#define FBT_HCI_DIFFERENT_TRANSACTION_COLLISION                                                                0x2a
+#define FBT_HCI_QOS_UNACCEPTABLE PARAMETER                                                                     0x2c
+#define FBT_HCI_QOS_REJECTED                                                                                           0x2d
+#define FBT_HCI_CHANNEL_CLASSIFICATION_NOT_SUPPORTED                                           0x2e
+#define FBT_HCI_INSUFFICIENT_SECURITY                                                                          0x2f
+#define FBT_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE                                                       0x30
+#define FBT_HCI_ROLE_SWITCH_PENDING                                                                                    0x32
+#define FBT_HCI_RESERVED_SLOT_VIOLATION                                                                                0x34
+#define FBT_HCI_ROLE_SWITCH_FAILED                                                                                     0x35
+
+#define FBT_HCI_SUCCESS(x) (x==FBT_HCI_ERROR_SUCCESS)
+
+#endif // _FBT_HCI_ERROR_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciEventStructs.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciEventStructs.h
new file mode 100755 (executable)
index 0000000..0610b75
--- /dev/null
@@ -0,0 +1,319 @@
+#ifndef _FBT_HCI_EVENT_STRUCTS_H
+#define _FBT_HCI_EVENT_STRUCTS_H
+
+// Pack structures to single unsigned char boundries
+#pragma pack(push, 1)
+
+typedef struct
+{
+    unsigned char EventCode;
+    unsigned char ParameterLength;
+
+} FBT_HCI_EVENT_HEADER, *PFBT_HCI_EVENT_HEADER;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned char                      NumResponses;
+
+} FBT_HCI_INQUIRY_COMPLETE, *PFBT_HCI_INQUIRY_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      NumResponses;
+    unsigned char                      BD_ADDR[FBT_HCI_VARIABLE_SIZE][FBT_HCI_BDADDR_SIZE];
+    unsigned char                      PageScanRepetitionMode[FBT_HCI_VARIABLE_SIZE];
+    unsigned char                      PageScanPeriodMode[FBT_HCI_VARIABLE_SIZE];
+    unsigned char                      PageScanMode[FBT_HCI_VARIABLE_SIZE];
+    unsigned char                      ClassOfDevice[FBT_HCI_VARIABLE_SIZE][FBT_HCI_DEVICE_CLASS_SIZE];
+    unsigned short                     ClockOffset[FBT_HCI_VARIABLE_SIZE];
+
+} FBT_HCI_INQUIRY_RESULT, *PFBT_HCI_INQUIRY_RESULT;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char                      LinkType;
+    unsigned char                      EncryptionMode;
+
+} FBT_HCI_CONNECTION_COMPLETE, *PFBT_HCI_CONNECTION_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned long                      ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE];
+    unsigned char                      LinkType;
+
+} FBT_HCI_CONNECTION_REQUEST, *PFBT_HCI_CONNECTION_REQUEST;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      Reason;
+
+} FBT_HCI_DISCONNECTION_COMPLETE, *PFBT_HCI_DISCONNECTION_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+
+} FBT_HCI_AUTHENTICATION_COMPLETE, *PFBT_HCI_AUTHENTICATION_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char                      RemoteName[FBT_HCI_NAME_SIZE];
+
+} FBT_HCI_REMOTE_NAME_REQUEST_COMPLETE, *PFBT_HCI_REMOTE_NAME_REQUEST_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      EncryptionEnable;
+
+} FBT_HCI_ENCRYPTION_CHANGE, *PFBT_HCI_ENCRYPTION_CHANGE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+
+} FBT_HCI_CHANGE_CONNECTION_LINK_KEY_COMPLETE, *PFBT_HCI_CHANGE_CONNECTION_LINK_KEY_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      KeyFlag;
+
+} FBT_HCI_MASTER_LINK_KEY_COMPLETE, *PFBT_HCI_MASTER_LINK_KEY_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      LmpFeatures[8];
+
+} FBT_HCI_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE, *PFBT_HCI_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      LmpVersion;
+    unsigned short                     ManufacturerName;
+    unsigned short                     LmpSubversion;
+
+} FBT_HCI_READ_REMOTE_VERSION_INFORMATION_COMPLETE, *PFBT_HCI_READ_REMOTE_VERSION_INFORMATION_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      Flags;
+    unsigned char                      ServiceType;
+    unsigned long                      TokenRate;
+    unsigned long                      PeakBandwidth;
+    unsigned long                      Latency;
+    unsigned long                      DelayVariation;
+
+} FBT_HCI_QOS_SETUP_COMPLETE, *PFBT_HCI_QOS_SETUP_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      NumHCICommandPackets;
+    unsigned short                     OpCode;
+    unsigned char                      Parameters[FBT_HCI_VARIABLE_SIZE];
+
+} FBT_HCI_COMMAND_COMPLETE, *PFBT_HCI_COMMAND_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned char                      NumHCICommandPackets;
+    unsigned short                     OpCode;
+
+} FBT_HCI_COMMAND_STATUS, *PFBT_HCI_COMMAND_STATUS;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      HardwareCode;
+
+} FBT_HCI_HARDWARE_ERROR, *PFBT_HCI_HARDWARE_ERROR;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned short                     ConnectionHandle;
+
+} FBT_HCI_FLUSH_OCCURRED, *PFBT_HCI_FLUSH_OCCURRED;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char                      NewRole;
+
+} FBT_HCI_ROLE_CHANGE, *PFBT_HCI_ROLE_CHANGE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      NumberOfHandles;
+    unsigned short                     ConnectionHandle[FBT_HCI_VARIABLE_SIZE];
+    unsigned short                     NumberOfCompletedPackets[FBT_HCI_VARIABLE_SIZE];
+
+} FBT_HCI_NUMBER_OF_COMPLETED_PACKETS, *PFBT_HCI_NUMBER_OF_COMPLETED_PACKETS;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      CurrentMode;
+    unsigned short                     Interval;
+
+} FBT_HCI_MODE_CHANGE, *PFBT_HCI_MODE_CHANGE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      NumKeys;
+    unsigned char                      BD_ADDR[FBT_HCI_VARIABLE_SIZE][FBT_HCI_BDADDR_SIZE];
+    unsigned char                      LinkKey[FBT_HCI_VARIABLE_SIZE][FBT_HCI_LINK_KEY_SIZE];
+
+} FBT_HCI_RETURN_LINK_KEYS, *PFBT_HCI_RETURN_LINK_KEYS;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+
+} FBT_HCI_PIN_CODE_REQUEST, *PFBT_HCI_PIN_CODE_REQUEST;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+
+} FBT_HCI_LINK_KEY_REQUEST, *PFBT_HCI_LINK_KEY_REQUEST;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char                      LinkKey[FBT_HCI_LINK_KEY_SIZE];
+
+} FBT_HCI_LINK_KEY_NOTIFICATION, *PFBT_HCI_LINK_KEY_NOTIFICATION;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      HCICommandPacket[FBT_HCI_CMD_MAX_SIZE];
+
+} FBT_HCI_LOOPBACK_COMMAND, *PFBT_HCI_LOOPBACK_COMMAND;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      LinkType;
+
+} FBT_HCI_DATA_BUFFER_OVERFLOW, *PFBT_HCI_DATA_BUFFER_OVERFLOW;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned short                     ConnectionHandle;
+    unsigned char                      LmpMaxSlots;
+
+} FBT_HCI_MAX_SLOTS_CHANGE, *PFBT_HCI_MAX_SLOTS_CHANGE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned short                     ClockOffset;
+
+} FBT_HCI_READ_CLOCK_OFFSET_COMPLETE, *PFBT_HCI_READ_CLOCK_OFFSET_COMPLETE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      Status;
+    unsigned short                     ConnectionHandle;
+    unsigned short                     PacketType;
+
+} FBT_HCI_CONNECTION_PACKET_TYPE_CHANGED, *PFBT_HCI_CONNECTION_PACKET_TYPE_CHANGED;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned short                     ConnectionHandle;
+
+} FBT_HCI_QOS_VIOLATION, *PFBT_HCI_QOS_VIOLATION;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char                      PageScanMode;
+
+} FBT_HCI_PAGE_SCAN_MODE_CHANGE, *PFBT_HCI_PAGE_SCAN_MODE_CHANGE;
+
+typedef struct
+{
+    FBT_HCI_EVENT_HEADER       EventHeader;
+    unsigned char                      BD_ADDR[FBT_HCI_BDADDR_SIZE];
+    unsigned char                      PageScanRepetitionMode;
+
+} FBT_HCI_PAGE_SCAN_REPETITION_MODE_CHANGE, *PFBT_HCI_PAGE_SCAN_REPETITION_MODE_CHANGE;
+
+typedef struct
+{
+       unsigned char                   Status;
+       unsigned char                   HCIVersion;
+       unsigned short                  HCIRevision;
+       unsigned char                   LMPVersion;
+       unsigned short                  Manufacturer;
+       unsigned short                  LMPSubVersion;
+
+} FBT_HCI_READ_LOCAL_VERSION_INFORMATION_COMPLETE;
+
+// Data Packet Structure
+typedef struct
+{
+    unsigned short  ConnectionHandle:  12;
+    unsigned short  PacketBoundary:            2;
+    unsigned short  Broadcast:                 2;
+    unsigned short  DataLength;
+    unsigned char      Data[1];
+
+} FBT_HCI_DATA_PACKET, *PFBT_HCI_DATA_PACKET;
+
+#pragma pack(pop)
+
+#endif // _FBT_HCI_EVENT_STRUCTS_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciEvents.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciEvents.h
new file mode 100755 (executable)
index 0000000..a65c9f2
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _FBT_HCI_EVENTS_H
+#define _FBT_HCI_EVENTS_H
+
+#include "fbtHciEventStructs.h"
+
+#define        FBT_HCI_EVENT_INVALID                                                                   0x00
+#define        FBT_HCI_EVENT_INQUIRY_COMPLETE                                                  0x01
+#define        FBT_HCI_EVENT_INQUIRY_RESULT                                                    0x02
+#define        FBT_HCI_EVENT_CONNECTION_COMPLETE                                               0x03
+#define        FBT_HCI_EVENT_CONNECTION_REQUEST                                                0x04
+#define        FBT_HCI_EVENT_DISCONNECTION_COMPLETE                                    0x05
+#define        FBT_HCI_EVENT_AUTHENTICATION_COMPLETE                                   0x06
+#define        FBT_HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE                              0x07
+#define        FBT_HCI_EVENT_ENCRYPTION_CHANGE_EVENT                                   0x08
+#define        FBT_HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE               0x09
+#define        FBT_HCI_EVENT_MASTER_LINK_KEY_COMPLETE                                  0x0a
+#define        FBT_HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES                    0x0b
+#define        FBT_HCI_EVENT_READ_REMOTE_VERSION_INFORMATION                   0x0c
+#define        FBT_HCI_EVENT_QOS_SETUP_COMPLETE                                                0x0d
+#define        FBT_HCI_EVENT_COMMAND_COMPLETE                                                  0x0e
+#define        FBT_HCI_EVENT_COMMAND_STATUS                                                    0x0f
+#define        FBT_HCI_EVENT_HARDWARE_ERROR                                                    0x10
+#define        FBT_HCI_EVENT_FLUSH_OCCURRED                                                    0x11
+#define        FBT_HCI_EVENT_ROLE_CHANGE                                                               0x12
+#define        FBT_HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS                               0x13
+#define        FBT_HCI_EVENT_MODE_CHANGE                                                               0x14
+#define        FBT_HCI_EVENT_RETURN_LINK_KEYS                                                  0x15
+#define        FBT_HCI_EVENT_PIN_CODE_REQUEST                                                  0x16
+#define        FBT_HCI_EVENT_LINK_KEY_REQUEST                                                  0x17
+#define        FBT_HCI_EVENT_LINK_KEY_NOTIFICATION                                             0x18
+#define        FBT_HCI_EVENT_LOOPBACK_COMMAND                                                  0x19
+#define        FBT_HCI_EVENT_DATA_BUFFER_OVERFLOW_EVENT                                0x1a
+#define        FBT_HCI_EVENT_MAX_SLOTS_CHANGE                                                  0x1b
+#define        FBT_HCI_EVENT_READ_CLOCK_OFFSET                                                 0x1c
+#define        FBT_HCI_EVENT_CONNECTION_PACKET_TYPE_CHANGED                    0x1d
+#define        FBT_HCI_EVENT_QOS_VIOLATION                                                             0x1e
+#define        FBT_HCI_EVENT_PAGE_SCAN_MODE_CHANGE                                             0x1f
+#define        FBT_HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE                  0x20
+#define        FBT_HCI_EVENT_FLOW_SPECIFICATION_COMPLETE                               0x21
+#define        FBT_HCI_EVENT_INQUIRY_RESULT_WITH_RSSI                                  0x22
+#define        FBT_HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES_COMPLETE    0x23
+#define        FBT_HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE                   0x24
+#define        FBT_HCI_EVENT_SYNCHRONOUS_CONNECTION_CHANGED                    0x25
+
+#endif // _FBT_HCI_EVENTS_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciLocal.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciLocal.h
new file mode 100755 (executable)
index 0000000..1c3e631
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef _LOCAL_HCI_H_
+#define _LOCAL_HCI_H_
+
+#include "fbtHci.h"
+
+#define MAX_QUEUED_COMMANDS 100
+
+typedef struct _QueuedCommand
+{
+       USHORT  nCommand;
+       BYTE    *pResultBuffer;
+       DWORD   dwBufferSize;
+       HANDLE  hEvent;
+
+} QueuedCommand, *PQueuedCommand;
+
+// Local HCI command abstraction
+// 1. Send Command
+// 2. Wait for Command status / Command complete
+class CHciLocal : public CHci
+{
+public:
+       CHciLocal(void);
+       virtual ~CHciLocal(void);
+
+       virtual int                             QueueCommand(USHORT nCommand, BYTE *pResultBuffer=NULL, DWORD dwBufferSize=0);
+       virtual int                             QueueCommandStatus(USHORT nCommand);
+       virtual void                    DeQueueCommand(int nSlot);
+       virtual DWORD                   ClearQueue(void);
+       virtual PQueuedCommand  GetQueuedCommand(int nSlot);
+
+       virtual DWORD WaitForCommandComplete(int nSlot);
+       virtual DWORD WaitForCommandStatus(int nSlot, BYTE &nStatus);
+
+       virtual DWORD SendReset(void);
+       virtual DWORD SendWriteClassOfDevice(BYTE ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE]);
+       virtual DWORD SendSetEventFilter(
+                                       BYTE nFilterType,
+                                       BYTE nFilterConditionType,
+                                       BYTE nCondition[FBT_HCI_MAX_CONDITION_SIZE],
+                                       BYTE nConditionBytes);
+
+       virtual DWORD SendInquiry(ULONG nLAP, BYTE nInquiryLength, BYTE nNumResponses);
+       virtual DWORD SendInquiryCancel(void);
+    virtual DWORD SendCreateConnection(BYTE            BD_ADDR[FBT_HCI_BDADDR_SIZE],
+                                       USHORT  nPacketType,
+                                       BYTE            nPageScanRepetitionMode,
+                                       BYTE            nPageScanMode,
+                                       USHORT  nClockOffset,
+                                       BYTE            nAllowRoleSwitch);
+
+       virtual DWORD SendDisconnect(USHORT nConnectionHandle, BYTE nReason);
+       virtual DWORD SendSwitchRole(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE nRole);
+       virtual DWORD SendRemoteNameRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE nPageScanRepetitionMode, BYTE nPageScanMode, USHORT nClockOffset);
+       virtual DWORD SendReadLocalVersionInformation(FBT_HCI_READ_LOCAL_VERSION_INFORMATION_COMPLETE &CommandComplete);
+
+    virtual DWORD OnEvent(PFBT_HCI_EVENT_HEADER pEvent, DWORD dwLength);
+
+    virtual DWORD CommandCompleteHandler(USHORT nCommand, BYTE *pParameters, DWORD dwParameterLength);
+    virtual DWORD CommandStatusHandler(BYTE nStatus, USHORT nCommand);
+
+protected:
+       virtual int             FindCommandSlot(USHORT nCommand);
+
+       QueuedCommand           m_QueuedCommands[MAX_QUEUED_COMMANDS];
+       CRITICAL_SECTION        m_QueueCriticalSection;
+
+};
+
+
+#endif // _LOCAL_HCI_H_
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciOpCodes.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciOpCodes.h
new file mode 100755 (executable)
index 0000000..c891b44
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef _FBT_HCI_OPCODES_H
+#define _FBT_HCI_OPCODES_H
+
+// Opcode Group Field (OGF) codes
+#define FBT_HCI_OGF_LINK_CONTROL                                       0x01    // Link control group
+#define FBT_HCI_OGF_LINK_POLICY                                        0x02    // Link polic group
+#define FBT_HCI_OGF_CONTROL_BASEBAND                                   0x03    // Host Controller & Baseband group
+#define FBT_HCI_OGF_INFORMATIONAL_PARAMETERS                           0x04    // Information parameters group
+#define FBT_HCI_OGF_STATUS_PARAMETERS                                  0x05    // Status parameters group
+#define FBT_HCI_OGF_TESTING                                            0x06    // Test group
+
+// Opcode Command Field (OCF) codes
+// Link control commands
+#define FBT_HCI_OCF_INQUIRY                                    0x0001
+#define FBT_HCI_OCF_INQUIRY_CANCEL                             0x0002
+#define FBT_HCI_OCF_PERIODIC_INQUIRY_MODE                      0x0003
+#define FBT_HCI_OCF_EXIT_PERIODIC_INQUIRY_MODE                 0x0004
+#define FBT_HCI_OCF_CREATE_CONNECTION                          0x0005
+#define FBT_HCI_OCF_DISCONNECT                                 0x0006
+#define FBT_HCI_OCF_ADD_SCO_CONNECTION                         0x0007
+
+#define FBT_HCI_OCF_ACCEPT_CONNECTION_REQUEST                  0x0009
+#define FBT_HCI_OCF_REJECT_CONNECTION_REQUEST                  0x000A
+#define FBT_HCI_OCF_LINK_KEY_REQUEST_REPLY                     0x000B
+#define FBT_HCI_OCF_LINK_KEY_REQUEST_NEGATIVE_REPLY            0x000C
+#define FBT_HCI_OCF_PIN_CODE_REQUEST_REPLY                     0x000D
+#define FBT_HCI_OCF_PIN_CODE_REQUEST_NEGATIVE_REPLY            0x000E
+#define FBT_HCI_OCF_CHANGE_CONNECTION_PACKET_TYPE              0x000F
+
+#define FBT_HCI_OCF_AUTHENTICATION_REQUESTED                   0x0011
+#define FBT_HCI_OCF_SET_CONNECTION_ENCRYPTION                  0x0013
+#define FBT_HCI_OCF_CHANGE_CONNECTION_LINK_KEY                 0x0015
+#define FBT_HCI_OCF_MASTER_LINK_KEY                            0x0017
+#define FBT_HCI_OCF_REMOTE_NAME_REQUEST                        0x0019
+#define FBT_HCI_OCF_READ_REMOTE_SUPPORTED_FEATURES             0x001B
+#define FBT_HCI_OCF_READ_REMOTE_VERSION_INFORMATION            0x001D
+#define FBT_HCI_OCF_READ_CLOCK_OFFSET                          0x001F
+
+// Link policy commands
+#define FBT_HCI_OCF_HOLD_MODE                                  0x0001
+#define FBT_HCI_OCF_SNIFF_MODE                                 0x0003
+#define FBT_HCI_OCF_EXIT_SNIFF_MODE                            0x0004
+#define FBT_HCI_OCF_PARK_MODE                                  0x0005
+#define FBT_HCI_OCF_EXIT_PARK_MODE                             0x0006
+#define FBT_HCI_OCF_QOS_SETUP                                  0x0007
+#define FBT_HCI_OCF_ROLE_DISCOVERY                             0x0009
+#define FBT_HCI_OCF_SWITCH_ROLE                                0x000B
+#define FBT_HCI_OCF_READ_LINK_POLICY_SETTINGS                  0x000C
+#define FBT_HCI_OCF_WRITE_LINK_POLICY_SETTINGS                 0x000D
+
+// Host controller & baseband commands
+#define FBT_HCI_OCF_SET_EVENT_MASK                             0x0001
+#define FBT_HCI_OCF_RESET                                      0x0003
+#define FBT_HCI_OCF_SET_EVENT_FILTER                           0x0005
+#define FBT_HCI_OCF_FLUSH                                      0x0008
+#define FBT_HCI_OCF_READ_PIN_TYPE                              0x0009
+#define FBT_HCI_OCF_WRITE_PIN_TYPE                             0x000A
+#define FBT_HCI_OCF_CREATE_NEW_UNIT_KEY                        0x000B
+#define FBT_HCI_OCF_READ_STORED_LINK_KEY                       0x000D
+#define FBT_HCI_OCF_WRITE_STORED_LINK_KEY                      0x0011
+#define FBT_HCI_OCF_DELETE_STORED_LINK_KEY                     0x0012
+#define FBT_HCI_OCF_CHANGE_LOCAL_NAME                          0x0013
+#define FBT_HCI_OCF_READ_LOCAL_NAME                            0x0014
+#define FBT_HCI_OCF_READ_CONNECTION_ACCEPT_TIMEOUT             0x0015
+#define FBT_HCI_OCF_WRITE_CONNECTION_ACCEPT_TIMEOUT                            0x0016
+#define FBT_HCI_OCF_READ_PAGE_TIMEOUT                          0x0017
+#define FBT_HCI_OCF_WRITE_PAGE_TIMEOUT                         0x0018
+#define FBT_HCI_OCF_READ_SCAN_ENABLE                           0x0019
+#define FBT_HCI_OCF_WRITE_SCAN_ENABLE                          0x001A
+#define FBT_HCI_OCF_READ_PAGE_SCAN_ACTIVITY                    0x001B
+#define FBT_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY                   0x001C
+#define FBT_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY                 0x001D
+#define FBT_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY                0x001E
+#define FBT_HCI_OCF_READ_AUTHENTICATION_ENABLE                 0x001F
+#define FBT_HCI_OCF_WRITE_AUTHENTICATION_ENABLE                0x0020
+#define FBT_HCI_OCF_READ_ENCRYPTION_MODE                       0x0021
+#define FBT_HCI_OCF_WRITE_ENCRYPTION_MODE                      0x0022
+#define FBT_HCI_OCF_READ_CLASS_OF_DEVICE                       0x0023
+#define FBT_HCI_OCF_WRITE_CLASS_OF_DEVICE                      0x0024
+#define FBT_HCI_OCF_READ_VOICE_SETTING                         0x0025
+#define FBT_HCI_OCF_WRITE_VOICE_SETTING                        0x0026
+#define FBT_HCI_OCF_READ_AUTOMATIC_FLUSH_TIMEOUT               0x0027
+#define FBT_HCI_OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT              0x0028
+#define FBT_HCI_OCF_READ_NUM_BROADCAST_RETRANSMISSIONS         0x0029
+#define FBT_HCI_OCF_WRITE_NUM_BROADCAST_RETRANSMISSIONS        0x002A
+#define FBT_HCI_OCF_READ_HOLD_MODE_ACTIVITY                    0x002B
+#define FBT_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY                   0x002C
+#define FBT_HCI_OCF_READ_TRANSMIT_POWER_LEVEL                  0x002D
+#define FBT_HCI_OCF_READ_SCO_FLOW_CONTROL_ENABLE               0x002E
+#define FBT_HCI_OCF_WRITE_SCO_FLOW_CONTROL_ENABLE              0x002F
+#define FBT_HCI_OCF_SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL   0x0031
+#define FBT_HCI_OCF_HOST_BUFFER_SIZE                           0x0033
+#define FBT_HCI_OCF_HOST_NUMBER_OF_COMPLETED_PACKETS           0x0035
+#define FBT_HCI_OCF_READ_LINK_SUPERVISION_TIMEOUT              0x0036
+#define FBT_HCI_OCF_WRITE_LINK_SUPERVISION_TIMEOUT             0x0037
+#define FBT_HCI_OCF_READ_NUMBER_OF_SUPPORTED_IAC               0x0038
+#define FBT_HCI_OCF_READ_CURRENT_IAC_LAP                       0x0039
+#define FBT_HCI_OCF_WRITE_CURRENT_IAC_LAP                      0x003A
+#define FBT_HCI_OCF_READ_PAGE_SCAN_PERIOD_MODE                 0x003B
+#define FBT_HCI_OCF_WRITE_PAGE_SCAN_PERIOD_MODE                0x003C
+#define FBT_HCI_OCF_READ_PAGE_SCAN_MODE                        0x003D
+#define FBT_HCI_OCF_WRITE_PAGE_SCAN_MODE                       0x003E
+
+// Informational parameter commands
+#define FBT_HCI_OCF_READ_LOCAL_VERSION_INFORMATION             0x0001
+#define FBT_HCI_OCF_LOCAL_SUPPPROTED_FEATURES                  0x0003
+#define FBT_HCI_OCF_READ_BUFFER_SIZE                           0x0005
+#define FBT_HCI_OCF_READ_COUNTRY_CODE                          0x0007
+#define FBT_HCI_OCF_READ_BD_ADDR                               0x0009
+
+// Status parameters commands
+#define FBT_HCI_OCF_READ_FAILED_CONTACT_COUNTER                0x0001
+#define FBT_HCI_OCF_RESET_FAILED_CONTACT_COUNTER               0x0002
+#define FBT_HCI_OCF_GET_LINK_QUALITY                           0x0003
+#define FBT_HCI_OCF_READ_RSSI                                  0x0005
+
+// Test commands
+#define FBT_HCI_OCF_READ_LOOPBACK_MODE                         0x0001
+#define FBT_HCI_OCF_WRITE_LOOPBACK_MODE                        0x0002
+#define FBT_HCI_OCF_ENABLE_DEVICE_UNDER_TEST_MODE              0x0003
+
+#define FBT_HCI_OGF_FROM_COMMAND(cmd)                                                  (cmd>>10)
+#define FBT_HCI_OCF_FROM_COMMAND(cmd)                                                  (cmd&0x3FF)
+
+#endif // _FBT_HCI_OPCODES_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciParms.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciParms.h
new file mode 100755 (executable)
index 0000000..727fe51
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _FBT_HCI_PARAMETERS_H
+#define _FBT_HCI_PARAMETERS_H
+
+// HCI header types
+#define FBT_HCI_SYNC_HCI_COMMAND_PACKET                0x01
+#define FBT_HCI_SYNC_ACL_DATA_PACKET        0x02
+#define FBT_HCI_SYNC_SCO_DATA_PACKET        0x03
+#define FBT_HCI_SYNC_HCI_EVENT_PACKET       0x04
+
+// Packet types for use in CreateConnection
+#define FBT_HCI_PACKET_TYPE_DM1                                0x0008  // 1 time slot, 1-18 bytes of data, FEC encoded
+#define FBT_HCI_PACKET_TYPE_DH1                                0x0010  // 1 time slot, 1-28 bytes of data, not FEC encoded
+
+#define FBT_HCI_PACKET_TYPE_DM3                                0x0400  // 3 time slots, 2-123 bytes of data, FEC encoded
+#define FBT_HCI_PACKET_TYPE_DH3                                0x0800  // 3 time slots, 2-185 bytes of data, not FEC encoded
+
+#define FBT_HCI_PACKET_TYPE_DM5                                0x4000  // 5 time slots, 2-226 bytes of data, FEC encoded
+#define FBT_HCI_PACKET_TYPE_DH5                                0x8000  // 3 time slots, 2-341 bytes of data, not FEC encoded
+
+#define FBT_HCI_PACKET_TYPE_ALL                                (FBT_HCI_PACKET_TYPE_DM1|FBT_HCI_PACKET_TYPE_DH1|FBT_HCI_PACKET_TYPE_DM3|FBT_HCI_PACKET_TYPE_DH3|FBT_HCI_PACKET_TYPE_DM5|FBT_HCI_PACKET_TYPE_DH5)
+
+// LAP codes for use in Inquiry
+#define FBT_HCI_LAP_GIAC                                       0x9E8B33
+#define FBT_HCI_LAP_LIAC                                       0x9E8B00
+
+// Link Types
+#define FBT_HCI_LINK_TYPE_SCO                          0x00
+#define FBT_HCI_LINK_TYPE_ACL                          0x01
+
+// Roles
+#define FBT_HCI_ROLE_MASTER                                    0x00
+#define FBT_HCI_ROLE_SLAVE                                     0x01
+
+// Event Filters
+#define FBT_HCI_FILTER_NONE                                    0x00
+#define FBT_HCI_FILTER_INQUIRY_RESULT          0x01
+#define FBT_HCI_FILTER_CONNECTION_SETUP                0x02
+
+#define FBT_HCI_FILTER_ALL                                     0x00
+#define FBT_HCI_FILTER_CLASS_OF_DEVICE         0x01
+#define FBT_HCI_FILTER_BDADDR                          0x02
+
+// Data packet parameters
+#define FBT_HCI_PACKET_BOUNDARY_FRAGMENT       0x01
+#define FBT_HCI_PACKET_BOUNDARY_START          0x02
+
+#define FBT_HCI_BROADCAST_POINT_TO_POINT       0x00            
+#define FBT_HCI_BROADCAST_ACTIVE_SLAVE         0x01
+#define FBT_HCI_BROADCAST_PARKED_SLAVE         0x02
+
+#endif // _FBT_HCI_PARAMETERS_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciRoundTrip.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciRoundTrip.h
new file mode 100755 (executable)
index 0000000..c945bc0
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _ROUND_TRIP_HCI_H_
+#define _ROUND_TRIP_HCI_H_
+
+#include "fbtHciLocal.h"
+
+// Complete round trip HCI abstraction
+// 1. Send Command
+// 2. Wait for Command status / Command complete
+// 3. Wait fo event
+class CHciRoundTrip : public CHciLocal
+{
+public:
+
+       CHciRoundTrip();
+       virtual ~CHciRoundTrip();
+
+       virtual DWORD QueueEvent(BYTE EventCode, LPVOID pParameters, DWORD dwParameterLength);
+       virtual DWORD WaitForEvent();
+
+    virtual DWORD OnEvent(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length);
+
+       virtual DWORD ReadBDADDR(BYTE *BDADDR);
+       virtual DWORD ReadClassOfDevice(BYTE *ClassOfDevice);
+    virtual DWORD ReadLocalName(BYTE *Name);
+    virtual DWORD CreateConnection(BYTE  BD_ADDR[FBT_HCI_BDADDR_SIZE],
+                                                                  USHORT PacketType,
+                                                                  BYTE  PageScanRepetitionMode,
+                                                                  BYTE  PageScanMode,
+                                                                  USHORT ClockOffset,
+                                                                  BYTE  AllowRoleSwitch,
+                                                                  USHORT &ConnectionHandle);
+
+       virtual DWORD Disconnect(USHORT ConnectionHandler, BYTE Reason);
+       virtual DWORD SwitchRole(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role);
+    virtual DWORD RemoteNameRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE],
+                                                               BYTE PageScanRepetitionMode,
+                                                               BYTE PageScanMode,
+                                                               USHORT ClockOffset,
+                                                               BYTE Name[FBT_HCI_NAME_SIZE]);
+
+protected:
+       BYTE    m_PendingEvent;
+       LPVOID  m_pEventParameters;
+       DWORD   m_dwEventParameterLength;
+
+       HANDLE  m_hEventSignal;
+
+};
+
+
+#endif // _ROUND_TRIP_HCI_H_
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtHciSizes.h b/reactos/drivers/bluetooth/fbtusb/include/fbtHciSizes.h
new file mode 100755 (executable)
index 0000000..d18ffc2
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _FBT_HCI_SIZES_H
+#define _FBT_HCI_SIZES_H
+
+// Sizes
+#define FBT_HCI_CMD_MIN_SIZE           3
+#define FBT_HCI_CMD_MAX_SIZE           258
+
+#define FBT_HCI_EVENT_MAX_SIZE         257
+
+#define FBT_HCI_DATA_MIN_SIZE          5
+#define FBT_HCI_DATA_MAX_SIZE          343
+
+#define FBT_HCI_BDADDR_SIZE                    6
+#define FBT_HCI_NAME_SIZE                      248
+
+#define FBT_HCI_DEVICE_CLASS_SIZE      3
+
+#define FBT_HCI_LAP_SIZE                       3
+#define FBT_HCI_MAX_CONDITION_SIZE     7
+
+#define FBT_HCI_LINK_KEY_SIZE          16
+#define FBT_HCI_PIN_CODE_SIZE          16
+
+#define FBT_HCI_VARIABLE_SIZE       1
+
+
+#endif // _FBT_HCI_SIZES_H
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtSeXcpt.h b/reactos/drivers/bluetooth/fbtusb/include/fbtSeXcpt.h
new file mode 100755 (executable)
index 0000000..0f211b4
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __SEEXCEPTION_H__
+#define __SEEXCEPTION_H__
+
+#include <windows.h>
+
+class fbtSeException
+{
+       public:
+               fbtSeException(unsigned int nSeCode, _EXCEPTION_POINTERS* pExcPointers);
+               fbtSeException(fbtSeException & CseExc);
+
+               unsigned int GetSeCode(void);
+
+       private:
+               unsigned int m_nSeCode;
+               _EXCEPTION_POINTERS* m_pExcPointers;
+
+};
+
+void fbtXcptEnableSEHandling();
+
+#endif //__SEEXCEPTION_H__
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtdev.h b/reactos/drivers/bluetooth/fbtusb/include/fbtdev.h
new file mode 100755 (executable)
index 0000000..dda6818
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_DEV_H
+#define _FREEBT_DEV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NTSTATUS FreeBT_DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FreeBT_DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FreeBT_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FreeBT_ResetPipe(IN PDEVICE_OBJECT    DeviceObject, IN USBD_PIPE_HANDLE PipeInfo);
+NTSTATUS FreeBT_ResetDevice(IN PDEVICE_OBJECT DeviceObject);
+NTSTATUS FreeBT_GetPortStatus(IN PDEVICE_OBJECT DeviceObject, IN PULONG PortStatus);
+NTSTATUS FreeBT_ResetParentPort(IN IN PDEVICE_OBJECT DeviceObject);
+
+NTSTATUS SubmitIdleRequestIrp(IN PDEVICE_EXTENSION DeviceExtension);
+VOID IdleNotificationCallback(IN PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS IdleNotificationRequestComplete(
+    IN PDEVICE_OBJECT    DeviceObject,
+    IN PIRP              Irp,
+    IN PDEVICE_EXTENSION DeviceExtension);
+
+VOID CancelSelectSuspend(IN PDEVICE_EXTENSION DeviceExtension);
+VOID PoIrpCompletionFunc(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN UCHAR            MinorFunction,
+    IN POWER_STATE      PowerState,
+    IN PVOID            Context,
+    IN PIO_STATUS_BLOCK IoStatus);
+
+VOID PoIrpAsyncCompletionFunc(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN UCHAR MinorFunction,
+    IN POWER_STATE PowerState,
+    IN PVOID Context,
+    IN PIO_STATUS_BLOCK IoStatus);
+
+VOID WWIrpCompletionFunc(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN UCHAR            MinorFunction,
+    IN POWER_STATE      PowerState,
+    IN PVOID            Context,
+    IN PIO_STATUS_BLOCK IoStatus);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbthci.h b/reactos/drivers/bluetooth/fbtusb/include/fbthci.h
new file mode 100755 (executable)
index 0000000..09e6491
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef _HCI_H_
+#define _HCI_H_
+
+#include <windows.h>
+
+#include "fbthw.h"
+#include "fbtHciDefs.h"
+
+// Number of overlapped requests to have pending in the driver
+#define HCI_NUMBER_OF_OVERLAPPED_LISTENS       MAXIMUM_WAIT_OBJECTS-1
+
+// HCI Abstraction layer
+class CHci;
+typedef struct
+{
+       PFBT_HCI_EVENT_HEADER           pEvent;
+       DWORD                                           dwLength;
+       CHci                                            *pThis;
+
+} HCI_EVENT, *PHCI_EVENT;
+
+class CHci : public CBTHW
+{
+public:
+       CHci(void);
+       virtual ~CHci(void);
+
+       virtual DWORD StartEventListener(void);
+       virtual DWORD StopEventListener(void);
+    virtual DWORD OnEvent(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length);
+
+       static LPCTSTR GetEventText(BYTE Event);
+       static LPCTSTR GetStatusText(BYTE Status);
+       static LPCTSTR GetManufacturerName(USHORT Company);
+
+    virtual DWORD OnCommandComplete(BYTE NumHCICommandPackets, USHORT CommandOpcode, BYTE *Parameters, DWORD ParameterLength);
+    virtual DWORD OnCommandStatus(BYTE Status, BYTE NumHCICommandPackets, USHORT CommandOpcode);
+
+    virtual DWORD OnConnectionRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], ULONG ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE], BYTE LinkType);
+    virtual DWORD OnConnectionComplete(BYTE Status, USHORT ConnectionHandle, BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE LinkType, BYTE EncryptionMode);
+    virtual DWORD OnDisconnectionComplete(BYTE Status, USHORT ConnectionHandle, BYTE Reason);
+
+    virtual DWORD OnInquiryComplete(BYTE Status, BYTE NumResponses);
+    virtual DWORD OnInquiryResult(BYTE NumResponses, BYTE BD_ADDR[FBT_HCI_VARIABLE_SIZE][FBT_HCI_BDADDR_SIZE], BYTE PageScanRepetitionMode[FBT_HCI_VARIABLE_SIZE], BYTE PageScanPeriodMode[FBT_HCI_VARIABLE_SIZE], BYTE PageScanMode[FBT_HCI_VARIABLE_SIZE], BYTE ClassOfDevice[FBT_HCI_VARIABLE_SIZE][FBT_HCI_DEVICE_CLASS_SIZE], USHORT ClockOffset[FBT_HCI_VARIABLE_SIZE]);
+
+    virtual DWORD OnRemoteNameRequestComplete(BYTE Status, BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE RemoteName[FBT_HCI_NAME_SIZE]);
+
+    virtual DWORD OnRoleChange(BYTE Status, BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role);
+
+    virtual DWORD OnPINCodeRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE]);
+
+       virtual DWORD OnLinkKeyNotification(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE LinkKey[FBT_HCI_LINK_KEY_SIZE]);
+    virtual DWORD OnLinkKeyRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE]);
+
+       virtual DWORD OnAuthenticationComplete(BYTE Status, USHORT ConnectionHandle);
+
+       virtual DWORD OnReadLocalNameComplete(BYTE Status, BYTE Name[FBT_HCI_NAME_SIZE]);
+
+    virtual DWORD OnUnknown(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length);
+
+    virtual DWORD SendReset(void);
+
+    virtual DWORD SendInquiry(ULONG LAP, BYTE InquiryLength, BYTE NumResponses);
+    virtual DWORD SendInquiryCancel(void);
+
+    virtual DWORD SendReadBDADDR(void);
+
+    virtual DWORD SendWriteScanEnable(BYTE ScanEnable);
+
+    virtual DWORD SendWriteAuthenticationEnable(BYTE ScanEnable);
+
+    virtual DWORD SendSetEventFilter(BYTE FilterType,
+                                     BYTE FilterConditionType,
+                                     BYTE Condition[FBT_HCI_MAX_CONDITION_SIZE],
+                                                                        BYTE ConditionBytes);
+
+    virtual DWORD SendReadClassOfDevice(void);
+
+    virtual DWORD SendWriteClassOfDevice(BYTE ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE]);
+
+    virtual DWORD SendCreateConnection(BYTE            BD_ADDR[FBT_HCI_BDADDR_SIZE],
+                                       USHORT  PacketType,
+                                       BYTE            PageScanRepetitionMode,
+                                       BYTE            PageScanMode,
+                                       USHORT  ClockOffset,
+                                       BYTE            AllowRoleSwitch);
+
+    virtual DWORD SendAcceptConnectionRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE RoleSwitch);
+
+    virtual DWORD SendDisconnect(USHORT ConnectionHandle, BYTE  Reason);
+
+    virtual DWORD SendWriteLinkSupervisionTimeout(USHORT ConnectionHandle, USHORT LinkSupervisionTimeout);
+
+    virtual DWORD SendWritePageTimeout(USHORT PageTimeout);
+
+    virtual DWORD SendRemoteNameRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE PageScanRepetitionMode, BYTE PageScanMode, USHORT ClockOffset);
+
+    virtual DWORD SendReadLocalName(void);
+
+    virtual DWORD SendChangeLocalName(BYTE Name[FBT_HCI_NAME_SIZE]);
+
+       virtual DWORD SendSwitchRole(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role);
+
+       virtual DWORD SendPINCodeRequestReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE PINCodeLength, BYTE PINCode[FBT_HCI_PIN_CODE_SIZE]);
+       virtual DWORD SendPINCodeRequestNegativeReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE]);
+
+       virtual DWORD SendLinkKeyRequestReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE LinkKey[FBT_HCI_LINK_KEY_SIZE]);
+       virtual DWORD SendLinkKeyRequestNegativeReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE]);
+
+       virtual DWORD SendReadLocalVersionInformation(void);
+
+       DWORD CompareBDADDRs(BYTE BD_ADDR1[FBT_HCI_BDADDR_SIZE], BYTE BD_ADDR2[FBT_HCI_BDADDR_SIZE]);
+
+protected:
+       friend static DWORD CALLBACK Listener(LPVOID pContext);
+       friend static DWORD EventHandler(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length);
+
+       virtual DWORD SendHciCommand(PFBT_HCI_CMD_HEADER lpCommand, DWORD dwBufferSize);
+
+    DWORD SendListenForEvent(OVERLAPPED *pOverlapped, BYTE *pEventBuffer);
+
+    HANDLE     m_hStopListeningEvent;
+    HANDLE     m_hListenerReadyEvent;
+    HANDLE     m_hListenerThread;
+
+    DWORD      m_dwListenerThreadId;
+
+    OVERLAPPED  m_Overlappeds[HCI_NUMBER_OF_OVERLAPPED_LISTENS];
+    BYTE               m_pEventBuffers[HCI_NUMBER_OF_OVERLAPPED_LISTENS][FBT_HCI_EVENT_MAX_SIZE];
+
+};
+
+
+#endif // _HCI_H_
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbthw.h b/reactos/drivers/bluetooth/fbtusb/include/fbthw.h
new file mode 100755 (executable)
index 0000000..43b2a00
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _FBT_HW_H_
+#define _FBT_HW_H_
+
+#include <winioctl.h>
+
+// HW Driver Abstraction layer
+class CBTHW
+{
+public:
+       // The driver is opened for OVERLAPPED I/O
+    CBTHW();
+    virtual ~CBTHW();
+
+       // Set the driver instances symbolic name
+    void    SetDeviceName(LPCTSTR szDeviceName);
+    DWORD      GetDeviceName(LPTSTR szBuffer, DWORD dwBufferSize);
+
+       // Open a handle to the driver instance
+    virtual DWORD   Attach(LPCSTR szDeviceName);
+    virtual DWORD   Detach();
+    HANDLE  GetDriverHandle();
+    BOOL    IsAttached() {return GetDriverHandle()!=INVALID_HANDLE_VALUE;}
+
+       // Send a command to the driver
+    DWORD      SendCommand(DWORD dwCommand, LPVOID lpInBuffer=NULL, DWORD dwInBufferSize=0, LPVOID lpOutBuffer=NULL, DWORD dwOutBufferSize=0, OVERLAPPED *pOverlapped=NULL);
+       DWORD   SendData(LPVOID lpBuffer, DWORD dwBufferSize, DWORD *dwBytesSent, OVERLAPPED *pOverlapped);
+       DWORD   GetData(LPVOID lpBuffer, DWORD dwBufferSize, DWORD *dwBytesRead, OVERLAPPED *pOverlapped);
+
+protected:
+    HANDLE  m_hDriver;
+    TCHAR   m_szDeviceName[1024];
+
+};
+
+
+#endif // _FBT_HW_H_
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtlog.h b/reactos/drivers/bluetooth/fbtusb/include/fbtlog.h
new file mode 100755 (executable)
index 0000000..3b572e5
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _FBT_DEBUG
+#define _FBT_DEBUG
+
+#define fbtLog_None                    0
+#define fbtLog_Failure         1
+#define fbtLog_Warning         2
+#define fbtLog_Notice          3
+#define fbtLog_Enter           4
+#define fbtLog_Exit                    4
+#define fbtLog_Verbose         5
+#define fbtLog_Exception       0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fbtLog(unsigned int nLevel, const char *szText, ...);
+BOOL fbtLogSetFile(char *szDebugFile);
+void fbtLogSetLevel(unsigned int nLevel);
+unsigned int fbtLogGetLevel(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtpnp.h b/reactos/drivers/bluetooth/fbtusb/include/fbtpnp.h
new file mode 100755 (executable)
index 0000000..3ceebb2
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_PNP_H
+#define _FREEBT_PNP_H
+
+#define REMOTE_WAKEUP_MASK 0x20
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NTSTATUS FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject);
+NTSTATUS ConfigureDevice(IN PDEVICE_OBJECT DeviceObject);
+NTSTATUS SelectInterfaces(IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
+NTSTATUS DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject);
+NTSTATUS CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb);
+VOID ProcessQueuedRequests(IN OUT PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS FreeBT_GetRegistryDword(IN PWCHAR RegPath, IN PWCHAR ValueName, IN OUT PULONG Value);
+NTSTATUS FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+VOID DpcRoutine(
+    IN PKDPC Dpc,
+    IN PVOID DeferredContext,
+    IN PVOID SystemArgument1,
+    IN PVOID SystemArgument2);
+
+VOID IdleRequestWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
+NTSTATUS FreeBT_AbortPipes(IN PDEVICE_OBJECT DeviceObject);
+NTSTATUS IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
+NTSTATUS CanStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS ReleaseMemory(IN PDEVICE_OBJECT DeviceObject);
+LONG FreeBT_IoIncrement(IN OUT PDEVICE_EXTENSION DeviceExtension);
+LONG FreeBT_IoDecrement(IN OUT PDEVICE_EXTENSION DeviceExtension);
+BOOLEAN CanDeviceSuspend(IN PDEVICE_EXTENSION DeviceExtension);
+PCHAR PnPMinorFunctionString (IN UCHAR MinorFunction);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtpwr.h b/reactos/drivers/bluetooth/fbtusb/include/fbtpwr.h
new file mode 100755 (executable)
index 0000000..0c6f4bf
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_POWER_H
+#define _FREEBT_POWER_H
+
+typedef struct _POWER_COMPLETION_CONTEXT
+{
+    PDEVICE_OBJECT DeviceObject;
+    PIRP           SIrp;
+
+} POWER_COMPLETION_CONTEXT, *PPOWER_COMPLETION_CONTEXT;
+
+typedef struct _WORKER_THREAD_CONTEXT
+{
+    PDEVICE_OBJECT DeviceObject;
+    PIRP           Irp;
+    PIO_WORKITEM   WorkItem;
+
+} WORKER_THREAD_CONTEXT, *PWORKER_THREAD_CONTEXT;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NTSTATUS FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+NTSTATUS SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension);
+VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+VOID DevPoCompletionRoutine(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN UCHAR            MinorFunction,
+    IN POWER_STATE      PowerState,
+    IN PVOID            Context,
+    IN PIO_STATUS_BLOCK IoStatus
+    );
+
+NTSTATUS HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS HoldIoRequests(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+VOID HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
+NTSTATUS QueueRequest(IN OUT PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp);
+VOID CancelQueued(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension);
+VOID CancelWaitWake(IN PDEVICE_EXTENSION DeviceExtension);
+VOID WaitWakeCallback(
+       IN PDEVICE_OBJECT   DeviceObject,
+    IN UCHAR            MinorFunction,
+    IN POWER_STATE      PowerState,
+    IN PVOID            Context,
+    IN PIO_STATUS_BLOCK IoStatus
+    );
+
+PCHAR PowerMinorFunctionString(IN UCHAR MinorFunction);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtreg.h b/reactos/drivers/bluetooth/fbtusb/include/fbtreg.h
new file mode 100755 (executable)
index 0000000..38ac78b
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef REG_H
+#define REG_H
+
+class CReg
+{
+       public:
+               // Constructor
+               CReg(LPCSTR lpszSubKey, HKEY hRootKey=HKEY_CURRENT_USER, REGSAM regSam=KEY_ALL_ACCESS, BOOL bCreate=TRUE);
+               
+               // Destructor
+               ~CReg();
+
+               // Get the specified registry value
+               BOOL GetValue(LPCSTR lpszValueName, LPVOID lpvData, DWORD *dwBuffSize=NULL, DWORD *dwDataType=NULL);
+               BOOL GetValue(LPCSTR lpszValueName, LPSTR lpszValue, DWORD dwBalueSize);
+//             BOOL GetValue(LPCSTR lpszValueName, CString &szData, DWORD *dwDataType=NULL);
+               BOOL GetValue(LPCSTR lpszValueName, DWORD &dwData);
+               BOOL GetValue(LPCSTR lpszValueName, BOOL &bData);
+               
+               // Set the specified registry value
+               BOOL SetValue(LPCSTR lpszValueName, const LPVOID lpvData, DWORD dwDataSize, DWORD dwDataType=REG_SZ);
+               BOOL SetValue(LPCSTR lpszValueName, LPCSTR lpszValue, DWORD dwDataSize=0, DWORD dwDataType=REG_SZ);
+               BOOL SetValue(LPCSTR lpszValueName, LPSTR lpszValue, DWORD dwValueSize);
+//             BOOL SetValue(LPCSTR lpszValueName, CString &szData, DWORD dwDataSize=0, DWORD dwDataType=REG_SZ);
+               BOOL SetValue(LPCSTR lpszValueName, DWORD dwData);
+               BOOL SetValue(LPCSTR lpszValueName, BOOL bData);
+
+               // Delete a value in the key
+               BOOL DeleteValue(LPCSTR lpszValueName);
+
+               // Delete all the values in the key
+               BOOL DeleteValues();
+               
+               // Delete a sub key
+               BOOL DeleteKey(LPCSTR lpszKeyName);
+
+               // Retrieve the names of the values in the key
+//             BOOL EnumerateValues(CStringArray &nszValueNames);
+               
+               BOOL IsValid() {return m_hKey!=NULL;}
+
+       protected:
+               // Create a new registry key
+               LONG Create(LPCSTR lpszSubKey, HKEY hRootKey, HKEY *hKey=NULL, REGSAM regSam=NULL);
+
+               // Open the specified registry key (creates if non-existant)
+               LONG Open(LPCSTR lpszSubKey, HKEY hRootKey, HKEY *hKey=NULL, REGSAM regSam=NULL, BOOL bCreate=TRUE);
+
+               BOOL DeleteKey(HKEY hRootKey, HKEY hKey, LPCSTR szKey, LPCSTR szSubKey);
+               
+//             CString m_szKey;                // Name of key this object wraps
+               char    m_szKey[1024];  // Name of key this object wraps
+               HKEY    m_hRootKey;             // Root key of the wrapped key
+               HKEY    m_hKey;                 // Key generated by Open/Create
+               
+};
+
+#endif
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtrwr.h b/reactos/drivers/bluetooth/fbtusb/include/fbtrwr.h
new file mode 100755 (executable)
index 0000000..bca99e7
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_RWR_H
+#define _FREEBT_RWR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _FREEBT_RW_CONTEXT
+{
+    PURB                                       Urb;
+    PMDL                                       Mdl;
+    ULONG                                      Length;                         // remaining to xfer
+    ULONG                                      Numxfer;                        // cumulate xfer
+    ULONG_PTR                          VirtualAddress;         // va for next segment of xfer.
+
+} FREEBT_RW_CONTEXT, * PFREEBT_RW_CONTEXT;
+
+NTSTATUS FreeBT_DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FreeBT_ReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
+NTSTATUS FreeBT_DispatchWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FreeBT_WriteCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtusb.h b/reactos/drivers/bluetooth/fbtusb/include/fbtusb.h
new file mode 100755 (executable)
index 0000000..42aed7c
--- /dev/null
@@ -0,0 +1,262 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_H
+#define _FREEBT_H
+
+#include <initguid.h>
+#include <wdm.h>
+#include <wmilib.h>
+#include <wmistr.h>
+#include <windef.h>
+#include "usbdi.h"
+#include "usbdlib.h"
+
+// Pull in all the command, event and structure definitions
+#include "fbtHciDefs.h"
+
+// Standard USB Wireless/Bluetooth class, etc
+#define FREEBT_USB_STDCLASS            0xE0            // Wireless Controller
+#define FREEBT_USB_STDSUBCLASS 0x01            // RF Controller
+#define FREEBT_USB_STDPROTOCOL 0x01            // Bluetooth Programming
+
+// Recommended Bluetooth Endpoints
+#define FREEBT_STDENDPOINT_HCICMD      0x00    // HCI Command
+#define FREEBT_STDENDPOINT_HCIEVENT    0x81    // HCI Event
+#define FREEBT_STDENDPOINT_ACLIN       0x82    // HCI Data In
+#define FREEBT_STDENDPOINT_ACLOUT      0x02    // HCI Data Out
+#define FREEBT_STDENDPOINT_AUDIOIN     0x83    // SCO In
+#define FREEBT_STDENDPOINT_AUDIOOUT    0x03    // SCO Out
+
+
+#define OBTTAG (ULONG) 'OBTU'
+
+#undef ExAllocatePool
+#define ExAllocatePool(type, size) ExAllocatePoolWithTag(type, size, OBTTAG);
+
+#if DBG
+
+#define FreeBT_DbgPrint(level, _x_) \
+            if((level) <= DebugLevel) { \
+                DbgPrint _x_; \
+            }
+
+#else
+
+#define FreeBT_DbgPrint(level, _x_)
+
+#endif
+
+typedef struct _GLOBALS
+{
+    UNICODE_STRING     FreeBT_RegistryPath;
+
+} GLOBALS;
+
+#define IDLE_INTERVAL 5000
+
+typedef enum _PIPETYPE
+{
+       HciCommandPipe,
+       HciEventPipe,
+       AclDataIn,
+       AclDataOut,
+       SCODataIn,
+       SCODataOut
+
+} FREEBT_PIPETYPE;
+
+typedef enum _DEVSTATE
+{
+    NotStarted,         // not started
+    Stopped,            // device stopped
+    Working,            // started and working
+    PendingStop,        // stop pending
+    PendingRemove,      // remove pending
+    SurpriseRemoved,    // removed by surprise
+    Removed             // removed
+
+} DEVSTATE;
+
+typedef enum _QUEUE_STATE
+{
+    HoldRequests,       // device is not started yet
+    AllowRequests,      // device is ready to process
+    FailRequests        // fail both existing and queued up requests
+
+} QUEUE_STATE;
+
+typedef enum _WDM_VERSION
+{
+    WinXpOrBetter,
+    Win2kOrBetter,
+    WinMeOrBetter,
+    Win98OrBetter
+
+} WDM_VERSION;
+
+#define INITIALIZE_PNP_STATE(_Data_)    \
+        (_Data_)->DeviceState =  NotStarted;\
+        (_Data_)->PrevDevState = NotStarted;
+
+#define SET_NEW_PNP_STATE(_Data_, _state_) \
+        (_Data_)->PrevDevState =  (_Data_)->DeviceState;\
+        (_Data_)->DeviceState = (_state_);
+
+#define RESTORE_PREVIOUS_PNP_STATE(_Data_)   \
+        (_Data_)->DeviceState =   (_Data_)->PrevDevState;
+
+
+// registry path used for parameters
+// global to all instances of the driver
+#define FREEBT_REGISTRY_PARAMETERS_PATH  L"\\REGISTRY\\Machine\\System\\CurrentControlSet\\SERVICES\\BULKUSB\\Parameters"
+
+typedef struct _FREEBT_PIPE_CONTEXT
+{
+    BOOLEAN                    PipeOpen;
+       FREEBT_PIPETYPE PipeType;
+
+} FREEBT_PIPE_CONTEXT, *PFREEBT_PIPE_CONTEXT;
+
+// A structure representing the instance information associated with
+// this particular device.
+typedef struct _DEVICE_EXTENSION
+{
+    // Functional Device Object
+    PDEVICE_OBJECT FunctionalDeviceObject;
+
+    // Device object we call when submitting Urbs
+    PDEVICE_OBJECT TopOfStackDeviceObject;
+
+    // The bus driver object
+    PDEVICE_OBJECT PhysicalDeviceObject;
+
+    // Name buffer for our named Functional device object link
+    // The name is generated based on the driver's class GUID
+    UNICODE_STRING InterfaceName;
+
+    // Bus drivers set the appropriate values in this structure in response
+    // to an IRP_MN_QUERY_CAPABILITIES IRP. Function and filter drivers might
+    // alter the capabilities set by the bus driver.
+    DEVICE_CAPABILITIES DeviceCapabilities;
+
+    // Configuration Descriptor
+    PUSB_CONFIGURATION_DESCRIPTOR UsbConfigurationDescriptor;
+
+    // Interface Information structure
+    PUSBD_INTERFACE_INFORMATION UsbInterface;
+
+    // Pipe context for the driver
+    PFREEBT_PIPE_CONTEXT PipeContext;
+
+    // current state of device
+    DEVSTATE DeviceState;
+
+    // state prior to removal query
+    DEVSTATE PrevDevState;
+
+    // obtain and hold this lock while changing the device state,
+    // the queue state and while processing the queue.
+    KSPIN_LOCK DevStateLock;
+
+    // current system power state
+    SYSTEM_POWER_STATE SysPower;
+
+    // current device power state
+    DEVICE_POWER_STATE DevPower;
+
+    // Pending I/O queue state
+    QUEUE_STATE QueueState;
+
+    // Pending I/O queue
+    LIST_ENTRY NewRequestsQueue;
+
+    // I/O Queue Lock
+    KSPIN_LOCK QueueLock;
+
+    KEVENT RemoveEvent;
+
+    KEVENT StopEvent;
+
+    ULONG OutStandingIO;
+
+    KSPIN_LOCK IOCountLock;
+
+    // Selective Suspend variables
+    LONG SSEnable;
+    LONG SSRegistryEnable;
+    PUSB_IDLE_CALLBACK_INFO IdleCallbackInfo;
+    PIRP PendingIdleIrp;
+    LONG IdleReqPend;
+    LONG FreeIdleIrpCount;
+    KSPIN_LOCK IdleReqStateLock;
+    KEVENT NoIdleReqPendEvent;
+
+    // Default power state to power down to on self-susped
+    ULONG PowerDownLevel;
+
+    // remote wakeup variables
+    PIRP WaitWakeIrp;
+    LONG FlagWWCancel;
+    LONG FlagWWOutstanding;
+    LONG WaitWakeEnable;
+
+    // Open handle count
+    LONG OpenHandleCount;
+
+    // Selective suspend model uses timers, dpcs and work item.
+    KTIMER Timer;
+
+    KDPC DeferredProcCall;
+
+    // This event is cleared when a DPC/Work Item is queued.
+    // and signaled when the work-item completes.
+    // This is essential to prevent the driver from unloading
+    // while we have DPC or work-item queued up.
+    KEVENT NoDpcWorkItemPendingEvent;
+
+    // WMI information
+    WMILIB_CONTEXT WmiLibInfo;
+
+    // WDM version
+    WDM_VERSION WdmVersion;
+
+    // Pipe type
+    FREEBT_PIPETYPE    PipeType;
+
+    // User accessible object name
+       WCHAR wszDosDeviceName[50];
+
+       // A never triggered event used for delaying execution
+       KEVENT DelayEvent;
+
+       // Significant pipes
+       USBD_PIPE_INFORMATION EventPipe;
+       USBD_PIPE_INFORMATION DataInPipe;
+       USBD_PIPE_INFORMATION DataOutPipe;
+       USBD_PIPE_INFORMATION AudioInPipe;
+       USBD_PIPE_INFORMATION AudioOutPipe;
+
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+
+typedef struct _IRP_COMPLETION_CONTEXT
+{
+    PDEVICE_EXTENSION DeviceExtension;
+    PKEVENT Event;
+
+} IRP_COMPLETION_CONTEXT, *PIRP_COMPLETION_CONTEXT;
+
+extern GLOBALS Globals;
+extern ULONG DebugLevel;
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtusr.h b/reactos/drivers/bluetooth/fbtusb/include/fbtusr.h
new file mode 100755 (executable)
index 0000000..ef458ec
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_USER_H
+#define _FREEBT_USER_H
+
+#include <initguid.h>
+//#include <winioctl.h>
+
+// {7591F7C7-E760-434a-92D3-C1869930423C}
+DEFINE_GUID(GUID_CLASS_FREEBT_USB,
+0x7591f7c7, 0xe760, 0x434a, 0x92, 0xd3, 0xc1, 0x86, 0x99, 0x30, 0x42, 0x3c);
+
+#define FREEBT_IOCTL_INDEX             0x0000
+
+
+#define IOCTL_FREEBT_GET_CONFIG_DESCRIPTOR     CTL_CODE(FILE_DEVICE_UNKNOWN,     \
+                                                     FREEBT_IOCTL_INDEX,     \
+                                                     METHOD_BUFFERED,         \
+                                                     FILE_ANY_ACCESS)
+
+#define IOCTL_FREEBT_HCI_SEND_CMD                      CTL_CODE(FILE_DEVICE_UNKNOWN,     \
+                                                                                                               FREEBT_IOCTL_INDEX + 1, \
+                                                                                                               METHOD_BUFFERED,         \
+                                                                                                               FILE_ANY_ACCESS)
+
+#define IOCTL_FREEBT_HCI_GET_EVENT                     CTL_CODE(FILE_DEVICE_UNKNOWN,     \
+                                                                                                               FREEBT_IOCTL_INDEX + 2, \
+                                                                                                               METHOD_BUFFERED,         \
+                                                                                                               FILE_ANY_ACCESS)
+
+#endif
+
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtutil.h b/reactos/drivers/bluetooth/fbtusb/include/fbtutil.h
new file mode 100755 (executable)
index 0000000..05e494b
--- /dev/null
@@ -0,0 +1,3 @@
+#include "fbtXcpt.h"
+#include "fbtLog.h"
+#include "fbtReg.h"
\ No newline at end of file
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtwmi.h b/reactos/drivers/bluetooth/fbtusb/include/fbtwmi.h
new file mode 100755 (executable)
index 0000000..2d4691c
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (c) 2004, Antony C. Roberts
+
+// Use of this file is subject to the terms
+// described in the LICENSE.TXT file that
+// accompanies this file.
+//
+// Your use of this file indicates your
+// acceptance of the terms described in
+// LICENSE.TXT.
+//
+// http://www.freebt.net
+
+#ifndef _FREEBT_WMI_H
+#define _FREEBT_WMI_H
+
+//#define ENABLE_WMI
+
+NTSTATUS FreeBT_WmiRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS FreeBT_WmiDeRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension);
+NTSTATUS FreeBT_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS FreeBT_QueryWmiRegInfo(
+    IN PDEVICE_OBJECT DeviceObject,
+    OUT ULONG *RegFlags,
+    OUT PUNICODE_STRING InstanceName,
+    OUT PUNICODE_STRING *RegistryPath,
+    OUT PUNICODE_STRING MofResourceName,
+    OUT PDEVICE_OBJECT *Pdo);
+
+NTSTATUS FreeBT_SetWmiDataItem(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp,
+    IN ULONG          GuidIndex,
+    IN ULONG          InstanceIndex,
+    IN ULONG          DataItemId,
+    IN ULONG          BufferSize,
+    IN PUCHAR         Buffer);
+
+NTSTATUS FreeBT_SetWmiDataBlock(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp,
+    IN ULONG          GuidIndex,
+    IN ULONG          InstanceIndex,
+    IN ULONG          BufferSize,
+    IN PUCHAR         Buffer);
+
+NTSTATUS FreeBT_QueryWmiDataBlock(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp,
+    IN ULONG          GuidIndex,
+    IN ULONG          InstanceIndex,
+    IN ULONG          InstanceCount,
+    IN OUT PULONG     InstanceLengthArray,
+    IN ULONG          OutBufferSize,
+    OUT PUCHAR        Buffer);
+
+PCHAR WMIMinorFunctionString(UCHAR MinorFunction);
+
+#endif
diff --git a/reactos/drivers/bluetooth/fbtusb/include/fbtxcpt.h b/reactos/drivers/bluetooth/fbtusb/include/fbtxcpt.h
new file mode 100755 (executable)
index 0000000..3d882b7
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _FBT_EXCEPT_H
+
+#include "fbtLog.h"
+
+#ifdef __cplusplus
+
+#include "fbtSeXcpt.h"
+
+#define FBT_TRY try {
+#define FBT_CATCH } catch (fbtSeException *e) { fbtLog(fbtLog_Failure, "Exception %08X caught at line %u in file %s", e->GetSeCode(), __LINE__, __FILE__); fbtLog(fbtLog_Exception, "Exception %08X caught at line %u in file %s", e->GetSeCode(), __LINE__, __FILE__);
+#define FBT_CATCH_RETURN(RETVAL) FBT_CATCH return RETVAL;}
+#define FBT_CATCH_NORETURN FBT_CATCH return;}
+
+#else
+
+#define FBT_TRY __try{
+#define FBT_CATCH } __except(EXCEPTION_EXECUTE_HANDLER) { fbtLog(fbtLog_Failure, "Exception %08X caught at line %u in file %s (%s)", GetExceptionCode(), __LINE__, __FILE__, GetCommandLine()); fbtLog(fbtLog_Exception, "Exception %08X caught at line %u in file %s (%s)", GetExceptionCode(), __LINE__, __FILE__, GetCommandLine());
+#define FBT_CATCH_RETURN(RETVAL) FBT_CATCH return RETVAL;}
+#define FBT_CATCH_NORETURN FBT_CATCH return;}
+#define FBT_CATCH_NODEBUG_RETURN(x) } __except(EXCEPTION_EXECUTE_HANDLER) { return x;}
+
+#endif // __cplusplus
+
+#endif _FBT_EXCEPT_H
index 970810f..7e6a925 100644 (file)
@@ -7,6 +7,9 @@
 <directory name="battery">
        <xi:include href="battery/directory.rbuild" />
 </directory>
 <directory name="battery">
        <xi:include href="battery/directory.rbuild" />
 </directory>
+<directory name="bluetooth">
+       <xi:include href="bluetooth/directory.rbuild" />
+</directory>
 <directory name="bus">
        <xi:include href="bus/directory.rbuild" />
 </directory>
 <directory name="bus">
        <xi:include href="bus/directory.rbuild" />
 </directory>
index 50f53bc..e81eb8b 100644 (file)
@@ -4,10 +4,10 @@
        <directory name="nt4compat">
                <xi:include href="nt4compat/directory.rbuild" />
        </directory>
        <directory name="nt4compat">
                <xi:include href="nt4compat/directory.rbuild" />
        </directory>
-       <!--directory name="usbd">
+       <directory name="usbd">
                <xi:include href="usbd/usbd.rbuild" />
        </directory>
                <xi:include href="usbd/usbd.rbuild" />
        </directory>
-       <directory name="usbhub">
+       <!--directory name="usbhub">
                <xi:include href="usbhub/usbhub.rbuild" />
        </directory>
        <directory name="usbstor">
                <xi:include href="usbhub/usbhub.rbuild" />
        </directory>
        <directory name="usbstor">