📄 usb.c
字号:
Arguments:
DeviceObject - pointer to the physical device object (PDO)
Urb - pointer to an already-formatted Urb request block
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
USB2COM_KdPrint( DBGLVL_MAXIMUM,("enter USB2COM_CallUSBD\n"));
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceExtension->TopOfStackDeviceObject, //Points to the next-lower driver's device object
NULL, // optional input bufer; none needed here
0, // input buffer len if used
NULL, // optional output bufer; none needed here
0, // output buffer len if used
TRUE, // If InternalDeviceControl is TRUE the target driver's Dispatch
// outine for IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_SCSI
// is called; otherwise, the Dispatch routine for
// IRP_MJ_DEVICE_CONTROL is called.
&event, // event to be signalled on completion
&ioStatus); // Specifies an I/O status block to be set when the request is completed the lower driver.
//
// As an alternative, we could call KeDelayExecutionThread, wait for some
// period of time, and try again....but we keep it simple for right now
//
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
USB2COM_ASSERT(nextStack != NULL);
//
// pass the URB to the USB driver stack
//
nextStack->Parameters.Others.Argument1 = Urb;
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
USB2COM_KdPrint( DBGLVL_MAXIMUM,("USB2COM_CallUSBD() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
} else {
ioStatus.Status = ntStatus;
}
USB2COM_KdPrint( DBGLVL_MAXIMUM,("USB2COM_CallUSBD() URB status = %x status = %x irp status %x\n",
Urb->UrbHeader.Status, status, ioStatus.Status));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
USB2COM_KdPrintCond( DBGLVL_MAXIMUM, !NT_SUCCESS( ntStatus ), ("exit USB2COM_CallUSBD FAILED (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
UsbDoControlTransfer(
IN PDEVICE_OBJECT DeviceObject,
IN USHORT Function,
IN ULONG TransferFlags,
IN UCHAR bRequest,
IN USHORT wValue,
IN USHORT wIndex,
IN USHORT wLength,
IN PVOID UserBuffer,
ULONG *UserBufferSize)
{
ULONG InputBufferSize;
NTSTATUS status = STATUS_SUCCESS;
USHORT UrbSize;
PURB urb;
ULONG nRetries = 3;
USB2COM_KdPrint( DBGLVL_MEDIUM,("enter UsbDoControlTransfer\n"));
// Check input parameters
InputBufferSize = *UserBufferSize;
RetryCallUSBD:
*UserBufferSize = 0;
if( UserBuffer==NULL)
return STATUS_INVALID_PARAMETER;
// Allocate memory for URB
UrbSize = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
urb = (PURB)USB2COM_ExAllocatePool(NonPagedPool, UrbSize);
if( urb == NULL)
{
USB2COM_KdPrint( DBGLVL_HIGH,("No URB memory %d\n",UrbSize));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Build Do Control transfer request
UsbBuildVendorRequest(
urb,
Function,
UrbSize,
TransferFlags,
0,//Specifies a value, from 4 to 31 inclusive,
//that becomes part of the request type code in the USB-defined setup packet.
bRequest,
wValue,
wIndex,
UserBuffer,
NULL,
wLength,
NULL
);
// Call the USB driver
status = USB2COM_CallUSBD(DeviceObject, urb);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
USB2COM_KdPrint(
DBGLVL_HIGH,
("status %x URB status %x\n", status, urb->UrbHeader.Status)
);
status = STATUS_UNSUCCESSFUL;
}
*UserBufferSize = urb->UrbControlVendorClassRequest.TransferBufferLength;
USB2COM_KdPrint(
DBGLVL_MEDIUM,
("TransferBufferLength = %d\n",
*UserBufferSize)
);
if(USBD_STATUS_DEV_NOT_RESPONDING == urb->UrbHeader.Status ||
urb->UrbHeader.Status == 0x80000005)//for win2k
{
ULONG PortStatus;
USB2COM_ExFreePool(urb);
if( KeGetCurrentIrql() < DISPATCH_LEVEL ){
LARGE_INTEGER delay;
delay.QuadPart = - 10 * 1000 * 5; // 5 ms
KeDelayExecutionThread( KernelMode, TRUE, &delay );
USB2COM_KdPrint(DBGLVL_DEFAULT,("Device not responding sleep 10 ms\n"));
}else{
USB2COM_KdPrint(DBGLVL_DEFAULT,("Device not responding want sleep but KeGetCurrentIrql() >= DISPATCH_LEVEL\n"));
}
if(--nRetries)
goto RetryCallUSBD;
}else
USB2COM_ExFreePool(urb);
USB2COM_KdPrint( DBGLVL_MEDIUM,("leave UsbDoControlTransfer status=%x\n",status));
return status;
}
NTSTATUS
USB2COM_ConfigureDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Initializes a given instance of the device on the USB and
selects and saves the configuration.
Arguments:
DeviceObject - pointer to the physical device object for this instance of the 82930
device.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
USB2COM_KdPrint( DBGLVL_HIGH,("enter USB2COM_ConfigureDevice\n"));
deviceExtension = DeviceObject->DeviceExtension;
USB2COM_ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );
urb = USB2COM_ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if ( !urb )
return STATUS_INSUFFICIENT_RESOURCES;
// When USB_CONFIGURATION_DESCRIPTOR_TYPE is specified for DescriptorType
// in a call to UsbBuildGetDescriptorRequest(),
// all interface, endpoint, class-specific, and vendor-specific descriptors
// for the configuration also are retrieved.
// The caller must allocate a buffer large enough to hold all of this
// information or the data is truncated without error.
// Therefore the 'siz' set below is just a 'good guess', and we may have to retry
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 512;
// We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest()
// has a big enough deviceExtension->UsbConfigurationDescriptor buffer not to truncate
while( 1 ) {
deviceExtension->UsbConfigurationDescriptor = USB2COM_ExAllocatePool(NonPagedPool, siz);
if ( !deviceExtension->UsbConfigurationDescriptor ) {
USB2COM_ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
deviceExtension->UsbConfigurationDescriptor,
NULL,
siz,
NULL);
ntStatus = USB2COM_CallUSBD(DeviceObject, urb);
USB2COM_KdPrint( DBGLVL_HIGH,("USB2COM_CallUSBD() Configuration Descriptor = %x, len %x\n",
deviceExtension->UsbConfigurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength));
//
// if we got some data see if it was enough.
// NOTE: we may get an error in URB because of buffer overrun
if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&
deviceExtension->UsbConfigurationDescriptor->wTotalLength > siz) {
siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength;
USB2COM_ExFreePool(deviceExtension->UsbConfigurationDescriptor);
deviceExtension->UsbConfigurationDescriptor = NULL;
} else {
break; // we got it on the first try
}
} // end, while (retry loop )
USB2COM_ExFreePool(urb);
USB2COM_ASSERT( deviceExtension->UsbConfigurationDescriptor );
//
// We have the configuration descriptor for the configuration we want.
// Now we issue the select configuration command to get
// the pipes associated with this configuration.
//
ntStatus = USB2COM_SelectInterface(DeviceObject,
deviceExtension->UsbConfigurationDescriptor);
USB2COM_KdPrint( DBGLVL_HIGH,("exit USB2COM_ConfigureDevice (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USB2COM_SelectInterface(
IN PDEVICE_OBJECT DeviceObject,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
/*++
Routine Description:
Initializes an 82930 with (possibly) multiple interfaces;
This minidriver only supports one interface (with multiple endpoints).
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
ConfigurationDescriptor - pointer to the USB configuration
descriptor containing the interface and endpoint
descriptors.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb = NULL;
ULONG i;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
PUSBD_INTERFACE_INFORMATION Interface = NULL;
USHORT siz;
PUCHAR pInf;
USB2COM_KdPrint( DBGLVL_MEDIUM,("enter USB2COM_SelectInterface\n"));
deviceExtension = DeviceObject->DeviceExtension;
USB2COM_KdPrint( DBGLVL_HIGH,("USB2COM_SelectInterface() called with NULL Interface\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -