[USB-BRINGUP]

- Fix bug in HidUsb_AbortPipe, which passed the wrong handle
- Implement reset port routine
- Implement reset worker routine when reading report fails

svn path=/branches/usb-bringup/; revision=54797
This commit is contained in:
Johannes Anderwald 2011-12-31 18:22:18 +00:00
parent d5ab604853
commit eb5e8a089b
3 changed files with 240 additions and 24 deletions

View file

@ -6,6 +6,6 @@ list(APPEND SOURCE
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)

View file

@ -175,6 +175,7 @@ HidUsb_AbortPipe(
PHID_DEVICE_EXTENSION DeviceExtension;
PURB Urb;
NTSTATUS Status;
PUSBD_PIPE_INFORMATION PipeInformation;
//
// get device extension
@ -194,13 +195,20 @@ HidUsb_AbortPipe(
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// get pipe information
//
PipeInformation = HidUsb_GetInputInterruptInterfaceHandle(HidDeviceExtension->InterfaceInfo);
ASSERT(PipeInformation);
ASSERT(PipeInformation->PipeHandle);
//
// init urb
//
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 @@ HidUsb_AbortPipe(
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
@ -256,6 +313,92 @@ HidCreate(
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
HidUsb_ReadReportCompletion(
@ -267,12 +410,7 @@ HidUsb_ReadReportCompletion(
PHID_DEVICE_EXTENSION DeviceExtension;
PURB Urb;
PUCHAR Buffer;
//
// get device extension
//
DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
PHID_USB_RESET_CONTEXT ResetContext;
//
// get urb
@ -281,24 +419,85 @@ HidUsb_ReadReportCompletion(
ASSERT(Urb);
//
// FIXME handle error
// did the reading report succeed / cancelled
//
ASSERT(Urb->UrbHeader.Status == USBD_STATUS_SUCCESS);
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;
}
//
// FIXME handle error
// get device extension
//
ASSERT(Irp->IoStatus.Status == STATUS_SUCCESS);
Buffer = Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferLength == 4);
DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
//
// store result
// allocate reset context
//
Irp->IoStatus.Information = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
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;
DPRINT("[HIDUSB] ReadCompletion Information %lu Buffer %x %x %x %x\n", Buffer[0] & 0xFF, Buffer[1] & 0xFF, Buffer[2] & 0xFF, Buffer[3] & 0xFF);
//
// 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 @@ HidInternalDeviceControl(
}
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;
}
@ -703,6 +902,7 @@ Hid_PnpCompletion(
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
Hid_DispatchUrb(
IN PDEVICE_OBJECT DeviceObject,
@ -750,11 +950,6 @@ Hid_DispatchUrb(
//
IoStack->Parameters.Others.Argument1 = (PVOID)Urb;
//
// set completion routine
//
IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
//
// call driver
//
@ -1333,6 +1528,7 @@ HidPnp(
// complete request
//
Irp->IoStatus.Status = Status;
DPRINT1("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -44,6 +44,26 @@ typedef struct
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,