Author: janderwald Date: Sat Dec 31 18:22:18 2011 New Revision: 54797
URL: http://svn.reactos.org/svn/reactos?rev=54797&view=rev Log: [USB-BRINGUP] - Fix bug in HidUsb_AbortPipe, which passed the wrong handle - Implement reset port routine - Implement reset worker routine when reading report fails
Modified: branches/usb-bringup/drivers/hid/hidusb/CMakeLists.txt branches/usb-bringup/drivers/hid/hidusb/hidusb.c branches/usb-bringup/drivers/hid/hidusb/hidusb.h
Modified: branches/usb-bringup/drivers/hid/hidusb/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/hid/hidusb/C... ============================================================================== --- branches/usb-bringup/drivers/hid/hidusb/CMakeLists.txt [iso-8859-1] (original) +++ branches/usb-bringup/drivers/hid/hidusb/CMakeLists.txt [iso-8859-1] Sat Dec 31 18:22:18 2011 @@ -6,6 +6,6 @@ add_library(hidusb SHARED ${SOURCE})
set_module_type(hidusb kernelmodedriver) -add_importlibs(hidusb hidclass ntoskrnl usbd) +add_importlibs(hidusb hidclass ntoskrnl usbd hal)
add_cab_target(hidusb 2)
Modified: branches/usb-bringup/drivers/hid/hidusb/hidusb.c URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/hid/hidusb/h... ============================================================================== --- branches/usb-bringup/drivers/hid/hidusb/hidusb.c [iso-8859-1] (original) +++ branches/usb-bringup/drivers/hid/hidusb/hidusb.c [iso-8859-1] Sat Dec 31 18:22:18 2011 @@ -175,6 +175,7 @@ PHID_DEVICE_EXTENSION DeviceExtension; PURB Urb; NTSTATUS Status; + PUSBD_PIPE_INFORMATION PipeInformation;
// // get device extension @@ -193,6 +194,13 @@ // return STATUS_INSUFFICIENT_RESOURCES; } + + // + // get pipe information + // + PipeInformation = HidUsb_GetInputInterruptInterfaceHandle(HidDeviceExtension->InterfaceInfo); + ASSERT(PipeInformation); + ASSERT(PipeInformation->PipeHandle);
// // init urb @@ -200,7 +208,7 @@ RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST)); Urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE; Urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST); - Urb->UrbPipeRequest.PipeHandle = HidDeviceExtension->ConfigurationHandle; + Urb->UrbPipeRequest.PipeHandle = PipeInformation->PipeHandle;
// // dispatch request @@ -218,7 +226,56 @@ return Status; }
- +NTSTATUS +HidUsb_ResetPort( + IN PDEVICE_OBJECT DeviceObject) +{ + KEVENT Event; + PIRP Irp; + PHID_DEVICE_EXTENSION DeviceExtension; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + // + // get device extension + // + DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // init event + // + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + // + // build irp + // + Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_RESET_PORT, DeviceExtension->NextDeviceObject, NULL, 0, NULL, 0, TRUE, &Event, &IoStatusBlock); + if (!Irp) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // send the irp + // + Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + // + // wait for request completion + // + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + // + // done + // + return IoStatusBlock.Status; +}
NTSTATUS NTAPI @@ -255,6 +312,92 @@ // return STATUS_SUCCESS; } + +VOID +NTAPI +HidUsb_ResetWorkerRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Ctx) +{ + NTSTATUS Status; + ULONG PortStatus; + PHID_USB_RESET_CONTEXT ResetContext; + PHID_DEVICE_EXTENSION DeviceExtension; + + DPRINT1("[HIDUSB] ResetWorkerRoutine\n"); + + // + // get context + // + ResetContext = (PHID_USB_RESET_CONTEXT)Ctx; + + // + // get device extension + // + DeviceExtension = (PHID_DEVICE_EXTENSION)ResetContext->DeviceObject->DeviceExtension; + + // + // get port status + // + Status = HidUsb_GetPortStatus(ResetContext->DeviceObject, &PortStatus); + DPRINT1("[HIDUSB] ResetWorkerRoutine GetPortStatus %x\n", Status); + if (NT_SUCCESS(Status)) + { + if (!(PortStatus & USB_PORT_STATUS_ENABLE)) + { + // + // port is disabled + // + Status = HidUsb_ResetInterruptPipe(ResetContext->DeviceObject); + DPRINT1("[HIDUSB] ResetWorkerRoutine ResetPipe %x\n", Status); + } + else + { + // + // abort pipe + // + Status = HidUsb_AbortPipe(ResetContext->DeviceObject); + DPRINT1("[HIDUSB] ResetWorkerRoutine AbortPipe %x\n", Status); + if (NT_SUCCESS(Status)) + { + // + // reset port + // + Status = HidUsb_ResetPort(ResetContext->DeviceObject); + DPRINT1("[HIDUSB] ResetPort %x\n", Status); + if (Status == STATUS_DEVICE_DATA_ERROR) + { + // + // invalidate device state + // + IoInvalidateDeviceState(DeviceExtension->PhysicalDeviceObject); + } + + // + // reset interrupt pipe + // + if (NT_SUCCESS(Status)) + { + // + // reset pipe + // + Status = HidUsb_ResetInterruptPipe(ResetContext->DeviceObject); + DPRINT1("[HIDUSB] ResetWorkerRoutine ResetPipe %x\n", Status); + } + } + } + } + + // + // cleanup + // + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + IoFreeWorkItem(ResetContext->WorkItem); + ResetContext->Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(ResetContext->Irp, IO_NO_INCREMENT); + ExFreePool(ResetContext); +} +
NTSTATUS NTAPI @@ -267,6 +410,44 @@ PHID_DEVICE_EXTENSION DeviceExtension; PURB Urb; PUCHAR Buffer; + PHID_USB_RESET_CONTEXT ResetContext; + + // + // get urb + // + Urb = (PURB)Context; + ASSERT(Urb); + + // + // did the reading report succeed / cancelled + // + if (NT_SUCCESS(Irp->IoStatus.Status) || Irp->IoStatus.Status == STATUS_CANCELLED || Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED) + { + // + // store result length + // + Irp->IoStatus.Information = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; + + // + // FIXME handle error + // + ASSERT(Urb->UrbHeader.Status == USBD_STATUS_SUCCESS); + + + Buffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer; + ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferLength == 4); + DPRINT("[HIDUSB] ReadCompletion Information %lu Buffer %x %x %x %x\n", Buffer[0] & 0xFF, Buffer[1] & 0xFF, Buffer[2] & 0xFF, Buffer[3] & 0xFF); + + // + // free the urb + // + ExFreePool(Context); + + // + // finish completion + // + return STATUS_SUCCESS; + }
// // get device extension @@ -275,30 +456,48 @@ HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
// - // get urb - // - Urb = (PURB)Context; - ASSERT(Urb); - - // - // FIXME handle error - // - ASSERT(Urb->UrbHeader.Status == USBD_STATUS_SUCCESS); - - // - // FIXME handle error - // - ASSERT(Irp->IoStatus.Status == STATUS_SUCCESS); - - Buffer = Urb->UrbBulkOrInterruptTransfer.TransferBuffer; - ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferLength == 4); - - // - // store result - // - Irp->IoStatus.Information = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; - - DPRINT("[HIDUSB] ReadCompletion Information %lu Buffer %x %x %x %x\n", Buffer[0] & 0xFF, Buffer[1] & 0xFF, Buffer[2] & 0xFF, Buffer[3] & 0xFF); + // allocate reset context + // + ResetContext = (PHID_USB_RESET_CONTEXT)ExAllocatePool(NonPagedPool, sizeof(HID_USB_RESET_CONTEXT)); + if (ResetContext) + { + // + // allocate work item + // + ResetContext->WorkItem = IoAllocateWorkItem(DeviceObject); + if (ResetContext->WorkItem) + { + // + // init reset context + // + ResetContext->Irp = Irp; + ResetContext->DeviceObject = DeviceObject; + + // + // queue the work item + // + IoQueueWorkItem(ResetContext->WorkItem, HidUsb_ResetWorkerRoutine, DelayedWorkQueue, ResetContext); + + // + // free urb + // + ExFreePool(Urb); + + // + // defer completion + // + return STATUS_MORE_PROCESSING_REQUIRED; + } + // + // free context + // + ExFreePool(ResetContext); + } + + // + // free urb + // + ExFreePool(Urb);
// // complete request @@ -563,7 +762,7 @@ } case IOCTL_HID_READ_REPORT: { - //DPRINT1("[HIDUSB] IOCTL_HID_READ_REPORT\n"); + DPRINT1("[HIDUSB] IOCTL_HID_READ_REPORT\n"); Status = HidUsb_ReadReport(DeviceObject, Irp); return Status; } @@ -702,6 +901,7 @@ // return STATUS_MORE_PROCESSING_REQUIRED; } +
NTSTATUS Hid_DispatchUrb( @@ -749,11 +949,6 @@ // store urb // IoStack->Parameters.Others.Argument1 = (PVOID)Urb; - - // - // set completion routine - // - IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
// // call driver @@ -1333,6 +1528,7 @@ // complete request // Irp->IoStatus.Status = Status; + DPRINT1("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status); IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
Modified: branches/usb-bringup/drivers/hid/hidusb/hidusb.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/hid/hidusb/h... ============================================================================== --- branches/usb-bringup/drivers/hid/hidusb/hidusb.h [iso-8859-1] (original) +++ branches/usb-bringup/drivers/hid/hidusb/hidusb.h [iso-8859-1] Sat Dec 31 18:22:18 2011 @@ -44,6 +44,26 @@ PHID_DESCRIPTOR HidDescriptor; }HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
+typedef struct +{ + // + // request irp + // + PIRP Irp; + + // + // work item + // + PIO_WORKITEM WorkItem; + + // + // device object + // + PDEVICE_OBJECT DeviceObject; + +}HID_USB_RESET_CONTEXT, *PHID_USB_RESET_CONTEXT; + + NTSTATUS Hid_GetDescriptor( IN PDEVICE_OBJECT DeviceObject,