📄 usbfx2lk_usb.cpp
字号:
//
// Since the support in the DDK isn't there, we simply
// added our own vendor specific command to determine if
// we're running at full or high speed. If you don't have
// this amount of flexibility with your device, you would
// need to cut and paste the appropriate definitions out
// of USBBUSIF.H in the Windows XP or Server 2003 build environment
// with the caveat of it not being officially documented or
// supported
//
///////////////////////////////////////////////////////////////////////////////
VOID DetermineDeviceSpeed(PUSBFX2LK_EXT DevExt)
{
DevExt->RunningAtHighSpeed = FALSE;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeed: Enter\n"));
#ifdef W2K
NTSTATUS status;
URB urb;
ULONG transferFlags;
//
// See the Notes section above, we've created
// a custom command to determine this while
// running on Win2K
//
RtlZeroMemory(&urb,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
//
// Build the vendor request with the appropriate
// flags and command
//
UsbBuildVendorRequest(&urb,
URB_FUNCTION_VENDOR_DEVICE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
(USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN),
0,
USBFX2LK_IS_HIGH_SPEED,
0,
0,
&DevExt->RunningAtHighSpeed,
NULL,
sizeof(BOOLEAN),
NULL);
//
// Make the request active on the device
//
status = SubmitUrb(DevExt, &urb);
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("DetermineDeviceSpeed: Failed to query speed - 0x%x (%s)\n",
status,OsrNtStatusToString(status)));
} else {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("DetermineDeviceSpeed: Device is running at %s speed.\n",
DevExt->RunningAtHighSpeed ? "HIGH" : "FULL"));
}
#else
NTSTATUS status;
PIRP irp;
KEVENT event;
PIO_STACK_LOCATION ioNextStack;
USB_BUS_INTERFACE_USBDI_V1 usbInterface;
//
// The way we determine our device speed on
// XP and later is by sending an IRP_MJ_PNP/
// IRP_MN_QUERY_INTERFACE IRP for the
// USB_BUS_INTERFACE_USBDI_GUID interface.
//
//
// Allocate an IRP with an appropriate number
// of stack locations for this request
//
irp = IoAllocateIrp(DevExt->DeviceToSendIrpsTo->StackSize,
FALSE);
if(!irp) {
//
// Can't allocate an IRP so we can't determine if
// we're at high speed.
//
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("DetermineDeviceSpeed: Failed to allocate an IRP. Defaulting to full speed\n"));
return;
}
//
// Assume failure.
//
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
//
// Initialize the IRP that we will be waiting on for the
// IRP to complete
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Get a pointer to the NEXT irp stack location.
// Because we are the ones who allocated the IRP,
// we do not have a current IRP stack location.
// Also, since we are passing the IRP down to the
// next lower driver, we want to modify the next
// stack location
//
ioNextStack = IoGetNextIrpStackLocation(irp);
//
// This is a PNP/QUERY_INTERFACE request
//
ioNextStack->MajorFunction = IRP_MJ_PNP;
ioNextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
//
// Setup the QUERY_INTERFACE stack location parameters
//
//
// Indicate which interface we're querying for
//
ioNextStack->Parameters.QueryInterface.InterfaceType =
&USB_BUS_INTERFACE_USBDI_GUID;
//
// Indicate which version of the interface we are querying
//
ioNextStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_1;
//
// Setup the buffer for the returned interface
//
ioNextStack->Parameters.QueryInterface.Interface = (PINTERFACE)&usbInterface;
//
// Set up the size of the buffer
//
ioNextStack->Parameters.QueryInterface.Size =
sizeof(USB_BUS_INTERFACE_USBDI_V1);
#ifdef IoForwardIrpSynchronously
//
// Pass the IRP down to the lower driver
//
if(IoForwardIrpSynchronously(DevExt->DeviceToSendIrpsTo,irp)) {
status = Irp->IoStatus.Status;
} else {
status = STATUS_UNSUCCESSFUL;
}
#else //IoForwardIrpSynchronously
//
// Setup a completion routine, passing the event as the
// context parameter. When the completion routine runs, it
// will set the event and stop completion processing by
// returning STATUS_MORE_PROCESSING_REQUIRED.
//
IoSetCompletionRoutine(irp,
DetermineDeviceSpeedCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE);
//
// Pass the IRP down to the lower driver
//
status = IoCallDriver(DevExt->DeviceToSendIrpsTo, irp);
if(status == STATUS_PENDING) {
//
// If the IRP was pended, then we must wait for the
// event to be signalled by our completion routine
//
(VOID)OsrWaitForSingleObject(&event);
//
// Retrieve the real completion status from the
// IRP
//
status = irp->IoStatus.Status;
}
#endif //IoForwardIrpSynchronously
//
// DId the call succeed?
//
if(NT_SUCCESS(status)) {
//
// We should have a valid IsDeviceHighSpeed routine to
// call through the interface
//
ASSERT(usbInterface.IsDeviceHighSpeed);
//
// Call the routine and see what we are running at
//
DevExt->RunningAtHighSpeed = usbInterface.IsDeviceHighSpeed(usbInterface.BusContext);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
("DetermineDeviceSpeed: Device is running at %s speed.\n",
DevExt->RunningAtHighSpeed ? "HIGH" : "FULL"));
} else {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("DetermineDeviceSpeed: Failed to query interface - 0x%x (%s)\n",
status,OsrNtStatusToString(status)));
}
//
// Delete the Irp that we allocated.
//
IoFreeIrp(irp);
#endif
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeed: Exit\n"));
return;
}
#ifndef IoForwardIrpSynchronously
///////////////////////////////////////////////////////////////////////////////
//
// DetermineDeviceSpeedCompletionRoutine
//
// This routine is a completion routine used to signal the completion
// of the IRP sent down by DetermineDeviceSpeed. It's only job is to
// set the event passed in as the context parameter and stop the processing
// of the IRP.
//
//
// INPUTS:
//
// DeviceObject - Address of the Devices Device Extension.
// Irp - Address of the QUERY_INTERFACE IRP sent down by
// DetermineDeviceSpeed
// Context - A pointer to a KEVENT
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// STATUS_MORE_PROCESSING_REQUIRED to stop completion processing of the IRP
//
// IRQL:
//
// IRQL <= DISPATCH_LEVEL
//
// CONTEXT:
//
// Arbitrary Context
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DetermineDeviceSpeedCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
PKEVENT event = (PKEVENT)Context;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeedCompletionRoutine: Enter\n"));
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
//
// Set the event
//
KeSetEvent(event, EVENT_INCREMENT, FALSE);
//
// And stop completion processing of the IRP
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeedCompletionRoutine: Exit\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
#endif //IoForwardIrpSynchronously
///////////////////////////////////////////////////////////////////////////////
//
// SubmitUrb
//
// This routine is called to synchronously submit the Input Urb to the USB
// device.
//
//
// INPUTS:
//
// DevExt - Address of the Devices Device Extension.
// Urb - Address of the USB to be delivered.
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// None
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary Context
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS SubmitUrb(PUSBFX2LK_EXT DevExt,PURB Urb)
{
PIRP irp = NULL;
KEVENT event;
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("SubmitUrb: Enter\n"));
//
// Initialize the Event that will be waited on if the underlying
// driver returns STATUS_PENDING
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Build the Irp to be used to submit the URB.
//
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
DevExt->DeviceToSendIrpsTo,
NULL,
0,
NULL,
0,
TRUE,
&event,
&ioStatus);
if(!irp) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("SubmitUrb: IoBuildDeviceIoControlRequest failed\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Put the URB to be submitted into the Others part of the next stack location.
// This urb will be passed to the USB Bus Driver for submission to our USB
// device.
//
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = Urb;
//
// Increment the number of outstanding requests.
//
OsrIncrementOutstandingIoCount(DevExt,__FILE__,__LINE__);
//
// Submit the Irp to the driver.
//
status = IoCallDriver(DevExt->DeviceToSendIrpsTo,irp);
//
// Wait for a response if not already completed.
//
if(status == STATUS_PENDING) {
(VOID)OsrWaitForSingleObject(&event);
//
// Get the completion status
//
status = ioStatus.Status;
}
//
// Decrement the number of outstanding requests.
//
OsrDecrementOutstandingIoCount(DevExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("SubmitUrb: Exit\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// SubmitIrpAndUrbAsync
//
// This routine is called to asynchronously submit the Input IRP and Urb to
// the USB device.
//
//
// INPUTS:
//
// DevExt - Address of the Devices Device Extension.
// IRP - Address of the IRP to setup for the URB transfer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -