}
NTSTATUS UsbResetPort(IN PUSBKBD_DEVICE_EXTENSION dx) {
DebugPrintMsg('Resetting port');
NTSTATUS status = CallUSBDI(dx, NULL, IOCTL_INTERNAL_USB_RESET_PORT);
DebugPrint('Port reset %x', status);
return status;
}
NTSTATUS UsbResetDevice(IN PUSBKBD_DEVICE_EXTENSION dx) {
ULONG PortStatus;
NTSTATUS status = UsbGetPortStatus(dx, PortStatus);
if (!NT_SUCCESS(status)) return status;
// Give up if device not connected
if (!(PortStatus & USBD_PORT_CONNECTED)) return STATUS_NO_SUCH_DEVICE;
// Return OK if port enabled
if (PortStatus & USBD_PORT_ENABLED) return status;
// Port disabled so attempt reset
status = UsbResetPort(dx);
if (!NT_SUCCESS(status)) return status;
// See if it is now working
status = UsbGetPortStatus(dx, PortStatus);
if (!NT_SUCCESS(status)) return status;
if (!(PortStatus & USBD_PORT_CONNECTED) || !(PortStatus & USBD_PORT_ENABLED)) return STATUS_NO_SUCH_DEVICE;
return status;
}
The Usb.cpp module contains many routines that build and send off URBs for processing by the USB class drivers.
Next,
The following parameters to
The final job for
Listing 21.4 Getting a USB device descriptor
NTSTATUS UsbGetDeviceDescriptor(IN PUSBKBD_DEVICE_EXTENSION dx, OUT PUSB_DEVICE_DESCRIPT0R& deviceDescriptor, OUT ULONGS Size) {
// Allocate memory for URB
USHORT UrbSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
PURB urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
if (urb==NULL) {
DebugPrintMsg('No URB memory');
return STATUS_INSUFFICIENT_RESOURCES;
}
// Allocate memory for device descriptor
ULONG sizeDescriptor = sizeof(USB_DEVICE_DESCRIPTOR);
deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)ExAllocatePool(NonPagedPool, sizeDescriptor);
if (deviceDescriptor==NULL) {
ExFreePool(urb);
DebugPrintMsg('No descriptor memory');
return STATUS_INSUFFICIENT_RESOURCES;
}
// Build the Get Descriptor URB
UsbBuildGetDescriptorRequest(urb, UrbSize,
USB_DEVICE_QESCRIPTOR_TYPE, 0, 0, // Types, Index & LanguageId
deviceDescriptor, NULL, sizeDescriptor, // Transfer buffer
NULL); // Link URB
// Call the USB driver
DebugPrintMsg('Getting device descriptor');
NTSTATUS status = CallUSBDI(dx, urb);
// Check statuses
if (!NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status)) {
DebugPrint('status %x URB status %x', status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
}
// Remember count of bytes actually transferred
Size = urb->UrbControlDescriptorRequest.TransferBufferLength;
ExFreePool(urb);
return status;
}
To start using a device, your driver must select one interface within one configuration. This is more of a job than you might expect. Routine
1. Get the configuration, interface, endpoint descriptors, etc.
2. Find the appropriate interface descriptor.
3. Issue a select configuration URB.
4. Save the configuration handle and handles to any pipes that you use.