diff --git a/reactos/drivers/bluetooth/directory.rbuild b/reactos/drivers/bluetooth/directory.rbuild new file mode 100644 index 00000000000..8d49812e7c6 --- /dev/null +++ b/reactos/drivers/bluetooth/directory.rbuild @@ -0,0 +1,7 @@ + + + + + diff --git a/reactos/drivers/bluetooth/fbtusb/fbtdev.c b/reactos/drivers/bluetooth/fbtusb/fbtdev.c new file mode 100755 index 00000000000..15f96e13e26 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtdev.c @@ -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 (inputBufferLengthFBT_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 (outputBufferLengthIoStatus.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 index 00000000000..4589ebf3563 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtpnp.c @@ -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; iNumberOfPipes; 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; iNumberOfPipes; 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; iNumberOfPipes; 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 index 00000000000..0bd6ceaa348 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtpwr.c @@ -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 index 00000000000..f8272895592 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtrwr.c @@ -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 (totalLengthMdlAddress); + 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 index 00000000000..353eab457c4 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtusb.c @@ -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 index 00000000000..d043b0a8ba6 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtusb.rbuild @@ -0,0 +1,15 @@ + + + + include + ntoskrnl + hal + usbd + fbtdev.c + fbtpnp.c + fbtpwr.c + fbtrwr.c + fbtusb.c + + fbtusb.rc + diff --git a/reactos/drivers/bluetooth/fbtusb/fbtusb.rc b/reactos/drivers/bluetooth/fbtusb/fbtusb.rc new file mode 100644 index 00000000000..3fbed8c50e7 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtusb.rc @@ -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 diff --git a/reactos/drivers/bluetooth/fbtusb/fbtwmi.c b/reactos/drivers/bluetooth/fbtusb/fbtwmi.c new file mode 100755 index 00000000000..66c8da6803c --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/fbtwmi.c @@ -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 index 00000000000..1e91486a2e1 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciCmdStructs.h @@ -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 index 00000000000..cb0dbf7eaee --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciCmds.h @@ -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 index 00000000000..f8894fe385c --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciDefs.h @@ -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 index 00000000000..98851627a65 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciErrors.h @@ -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 index 00000000000..0610b751822 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciEventStructs.h @@ -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 index 00000000000..a65c9f21872 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciEvents.h @@ -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 index 00000000000..1c3e631854a --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciLocal.h @@ -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 index 00000000000..c891b442ddd --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciOpCodes.h @@ -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 index 00000000000..727fe511afd --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciParms.h @@ -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 index 00000000000..c945bc00701 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciRoundTrip.h @@ -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 index 00000000000..d18ffc23999 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtHciSizes.h @@ -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 index 00000000000..0f211b45611 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtSeXcpt.h @@ -0,0 +1,22 @@ +#ifndef __SEEXCEPTION_H__ +#define __SEEXCEPTION_H__ + +#include + +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 index 00000000000..dda681845b0 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtdev.h @@ -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 index 00000000000..09e64919f38 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbthci.h @@ -0,0 +1,134 @@ +#ifndef _HCI_H_ +#define _HCI_H_ + +#include + +#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 index 00000000000..43b2a005654 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbthw.h @@ -0,0 +1,36 @@ +#ifndef _FBT_HW_H_ +#define _FBT_HW_H_ + +#include + +// 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 index 00000000000..3b572e59c65 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtlog.h @@ -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 index 00000000000..3ceebb2a18f --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtpnp.h @@ -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 index 00000000000..0c6f4bff160 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtpwr.h @@ -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 index 00000000000..38ac78b1177 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtreg.h @@ -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 index 00000000000..bca99e7c4be --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtrwr.h @@ -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 index 00000000000..42aed7c68de --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtusb.h @@ -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 +#include +#include +#include +#include +#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 index 00000000000..ef458ecab1b --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtusr.h @@ -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 +//#include + +// {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 index 00000000000..05e494bdc05 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtutil.h @@ -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 index 00000000000..2d4691c62c3 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtwmi.h @@ -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 index 00000000000..3d882b7caa3 --- /dev/null +++ b/reactos/drivers/bluetooth/fbtusb/include/fbtxcpt.h @@ -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 diff --git a/reactos/drivers/drivers.rbuild b/reactos/drivers/drivers.rbuild index 970810f015d..7e6a925055f 100644 --- a/reactos/drivers/drivers.rbuild +++ b/reactos/drivers/drivers.rbuild @@ -7,6 +7,9 @@ + + + diff --git a/reactos/drivers/usb/directory.rbuild b/reactos/drivers/usb/directory.rbuild index 50f53bccb70..e81eb8b291a 100644 --- a/reactos/drivers/usb/directory.rbuild +++ b/reactos/drivers/usb/directory.rbuild @@ -4,10 +4,10 @@ -