?? liubo2004666_ezusbsys.c
字號:
{
ntStatus = Ezusb_CreateDeviceObject(DriverObject, &deviceObject, instance);
instance++;
} while (!NT_SUCCESS(ntStatus) && (instance < MAX_EZUSB_DEVICES));
if (NT_SUCCESS(ntStatus))
{
pdx = deviceObject->DeviceExtension;
//
// Non plug and play drivers usually create the device object in
// driver entry, and the I/O manager autimatically clears this flag.
// Since we are creating the device object ourselves in response to
// a PnP START_DEVICE IRP, we need to clear this flag ourselves.
//
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// This driver uses direct I/O for read/write requests
//
deviceObject->Flags |= DO_DIRECT_IO;
deviceObject->Flags |= DO_POWER_PAGABLE;
//
//
// store away the Physical device Object
//
pdx->PhysicalDeviceObject=PhysicalDeviceObject;
//
// Attach to the StackDeviceObject. This is the device object that what we
// use to send Irps and Urbs down the USB software stack
//
pdx->StackDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
ASSERT (pdx->StackDeviceObject != NULL);
pdx->LastFailedUrbStatus = 0;
pdx->usage = 1; // locked until RemoveDevice
KeInitializeEvent(&pdx->evRemove,
NotificationEvent,
FALSE); // set when use count drops to zero
}
Ezusb_KdPrint(("exit Ezusb_PnPAddDevice (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
Ezusb_CreateDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT *DeviceObject,
LONG Instance
)
/*++
Routine Description:
Creates a Functional DeviceObject
Arguments:
DriverObject - pointer to the driver object for device
DeviceObject - pointer to DeviceObject pointer to return
created device object.
Instance - instnace of the device create.
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Ezusb-0";
UNICODE_STRING deviceLinkUnicodeString;
WCHAR deviceNameBuffer[] = L"\\Device\\Ezusb-0";
UNICODE_STRING deviceNameUnicodeString;
PDEVICE_EXTENSION pdx;
STRING deviceName;
Ezusb_KdPrint(("enter Ezusb_CreateDeviceObject instance = %d\n", Instance));
//
// fix up device names based on Instance
//
deviceLinkBuffer[18] = (USHORT) ('0' + Instance);
deviceNameBuffer[14] = (USHORT) ('0' + Instance);
Ezusb_KdPrint(("Create Device name (%ws)\n", deviceNameBuffer));
RtlInitUnicodeString (&deviceNameUnicodeString,
deviceNameBuffer);
//
//Print out the unicode string
//NOTE: We must first convert the string to Unicode due to a bug in the Debugger that does not allow
// Unicode Strings to be printed to the debug device.
//
deviceName.Buffer = NULL;
ntStatus = RtlUnicodeStringToAnsiString (&deviceName,
&deviceNameUnicodeString,
TRUE);
if (NT_SUCCESS(ntStatus))
{
Ezusb_KdPrint(("Create Device Name (%s)\n", deviceName.Buffer));
RtlFreeAnsiString (&deviceName);
}
else
{
Ezusb_KdPrint(("Unicode to Ansi str failed w/ ntStatus: 0x%x\n",ntStatus));
}
ntStatus = IoCreateDevice (DriverObject,
sizeof (DEVICE_EXTENSION),
&deviceNameUnicodeString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
DeviceObject);
if (NT_SUCCESS(ntStatus))
{
// Initialize our device extension
pdx = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
RtlCopyMemory(pdx->DeviceLinkNameBuffer,
deviceLinkBuffer,
sizeof(deviceLinkBuffer));
pdx->OpenHandles = 0;
pdx->ConfigurationHandle = NULL;
pdx->DeviceDescriptor = NULL;
pdx->NeedCleanup = FALSE;
pdx->DataRingBuffer = NULL;
pdx->DescriptorRingBuffer = NULL;
pdx->Started = FALSE;
// Initialize our interface
pdx->Interface = NULL;
RtlInitUnicodeString (&deviceLinkUnicodeString,
deviceLinkBuffer);
Ezusb_KdPrint(("Create DosDevice name (%ws)\n", deviceLinkBuffer));
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
&deviceNameUnicodeString);
}
Ezusb_KdPrint(("exit Ezusb_CreateDeviceObject (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
Ezusb_CallUSBD(
IN PDEVICE_OBJECT fdo,
IN PURB Urb
)
/*++
Routine Description:
Passes a Usb Request Block (URB) to the USB class driver (USBD)
Note that we create our own IRP here and use it to send the request to
the USB software subsystem. This means that this routine is essentially
independent of the IRP that caused this driver to be called in the first
place. The IRP for this transfer is created, used, and then destroyed
in this routine.
However, note that this routine uses the Usb Request Block (urb) passed
in by the caller as the request block for the USB software stack.
Implementation of this routine may be changed depending on the specific
requirements of your driver. For example, while this routine issues a
synchronous request to the USB stack, you may wish to implement this as an
asynchronous request in which you set an IoCompletionRoutine to be called
when the request is complete.
Arguments:
fdo - pointer to the device object for this instance of an Ezusb Device
Urb - pointer to Urb request block
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
Ezusb_KdPrint (("enter Ezusb_CallUSBD\n"));
pdx = fdo->DeviceExtension;
// issue a synchronous request (see notes above)
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pdx->StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, /* INTERNAL */
&event,
&ioStatus);
// Prepare for calling the USB driver stack
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
// Set up the URB ptr to pass to the USB driver stack
nextStack->Parameters.Others.Argument1 = Urb;
Ezusb_KdPrint (("Calling USB Driver Stack\n"));
//
// Call the USB class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
ntStatus = IoCallDriver(pdx->StackDeviceObject,
irp);
Ezusb_KdPrint (("return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING)
{
Ezusb_KdPrint (("Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
Ezusb_KdPrint (("Wait for single object, returned %x\n", status));
}
else
{
ioStatus.Status = ntStatus;
}
Ezusb_KdPrint (("URB status = %x status = %x irp status %x\n",
Urb->UrbHeader.Status, status, ioStatus.Status));
//
// USBD maps the error code for us. USBD uses error codes in its URB
// structure that are more insightful into USB behavior. In order to
// match the NT Status codes, USBD maps its error codes into more general NT
// error categories so higher level drivers can decipher the error codes
// based on standard NT error code definitions.
//
ntStatus = ioStatus.Status;
//
// If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
// URB status in the device extension. After a failure, another IOCTL,
// IOCTL_EZUSB_GET_LAST_ERROR can be used to retrieve the URB status
// for the most recently failed URB. Of course, this status gets
// overwritten by subsequent failures, but it's better than nothing.
//
if (!(USBD_SUCCESS(Urb->UrbHeader.Status)))
pdx->LastFailedUrbStatus = Urb->UrbHeader.Status;
//
// if ioStatus.Status indicates an error (ie. the IRP failed) then return that.
// If ioStatus.Status indicates success, it is still possible that what we were
// trying to do failed. For example, if the IRP is cancelled, the status returned
// by the I/O manager for the IRP will not indicate an error. In that case, we
// should check the URB status. If it indicates anything other than
// USBD_SUCCESS, then we should return STATUS_UNSUCCESSFUL.
//
if (NT_SUCCESS(ntStatus))
{
if (!(USBD_SUCCESS(Urb->UrbHeader.Status)))
ntStatus = STATUS_UNSUCCESSFUL;
}
Ezusb_KdPrint(("exit Ezusb_CallUSBD (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
Ezusb_ConfigureDevice(
IN PDEVICE_OBJECT fdo
)
/*++
Routine Description:
Configures the USB device via USB-specific device requests and interaction
with the USB software subsystem.
Arguments:
fdo - pointer to the device object for this instance of the Ezusb Device
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION pdx;
NTSTATUS ntStatus;
PURB urb = NULL;
ULONG siz;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
Ezusb_KdPrint (("enter Ezusb_ConfigureDevice\n"));
pdx = fdo->DeviceExtension;
//
// Get memory for the USB Request Block (urb).
//
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb != NULL)
{
//
// Set size of the data buffer. Note we add padding to cover hardware faults
// that may cause the device to go past the end of the data buffer
//
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 16;
// Get the nonpaged pool memory for the data buffer
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if (configurationDescriptor != NULL) {
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
sizeof (USB_CONFIGURATION_DESCRIPTOR),/* Get only the configuration descriptor */
NULL);
ntStatus = Ezusb_CallUSBD(fdo, urb);
if (NT_SUCCESS(ntStatus)) {
Ezusb_KdPrint (("Configuration Descriptor is at %x, bytes txferred: %d\n\
Configuration Descriptor Actual Length: %d\n",
configurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength,
configurationDescriptor->wTotalLength));
}//if
} else {
ntStatus = STATUS_NO_MEMORY;
goto Exit_EzusbConfigureDevice;
}//if-else
// Determine how much data is in the entire configuration descriptor
// and add extra room to protect against accidental overrun
siz = configurationDescriptor->wTotalLength + 16;
// Free up the data buffer memory just used
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
// Get nonpaged pool memory for the data buffer
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
// Now get the entire Configuration Descriptor
if (configurationDescriptor != NULL) {
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
siz, // Get all the descriptor data
NULL);
ntStatus = Ezusb_CallUSBD(fdo, urb);
if (NT_SUCCESS(ntStatus)) {
Ezusb_KdPrint (("Entire Configuration Descriptor is at %x, bytes txferred: %d\n",
configurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength));
} else {
//Error in getting configuration descriptor
goto Exit_EzusbConfigureDevice;
}//else
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -