//////////////////////////////////////////////////////////////////////////////
//文件名称:Usb.cpp
//文件功能:所有的与USB通讯相关的函数实现
//修改记录:
//
//Copyright Corporation, Ltd.
//All rights reserved.
/////////////////////////////////////////////////////////////////////////////
#include "UsbDrv.h"
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// UsbGetPortStatus: Issue Get Port Status IOCTL
NTSTATUS UsbGetPortStatus( IN PUSBDRV_DEVICE_EXTENSION dx, OUT ULONG* PortStatus)
{
NTSTATUS status ;
*PortStatus = 0;
status = CallUSBDI( dx, PortStatus, IOCTL_INTERNAL_USB_GET_PORT_STATUS , 0 );
TRACE1( "Got port status. PortStatus = %x", *PortStatus);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbResetPort: Reset port
NTSTATUS UsbResetPort( IN PUSBDRV_DEVICE_EXTENSION dx)
{
NTSTATUS status ;
status = CallUSBDI( dx, NULL, IOCTL_INTERNAL_USB_RESET_PORT , 0 );
#ifdef DEBUG_INTERFACE
TRACE1( "Port reset %x", status);
#endif//DEBUG_INTERFACE
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbResetDevice: Reset device if port not enabled
NTSTATUS UsbResetDevice( IN PUSBDRV_DEVICE_EXTENSION dx)
{
ULONG PortStatus = 0 ;
NTSTATUS status ;
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;
}
/////////////////////////////////////////////////////////////////////////////
// UsbGetUsbInfo: Get some USB information (W2000 only)
NTSTATUS UsbGetUsbInfo( IN PUSBDRV_DEVICE_EXTENSION dx)
{
int len = 0;
PUSB_HUB_NAME HubName ;
#if _WIN32_WINNT>=0x0500
USB_BUS_NOTIFICATION BusInfo;
//DebugPrintMsg("Getting bus info");
NTSTATUS status ;
status = CallUSBDI( dx, &BusInfo, IOCTL_INTERNAL_USB_GET_BUS_INFO , 0 );
#ifdef DEBUG_INTERFACE
TRACE3("Bus info: TotalBandwidth %d, ConsumedBandwidth %d and ControllerNameLength %d",
BusInfo.TotalBandwidth, BusInfo.ConsumedBandwidth, BusInfo.ControllerNameLength);
#endif//DEBUG_INTERFACE
len = BusInfo.ControllerNameLength+50;
HubName = (PUSB_HUB_NAME)ExAllocatePool( NonPagedPool, len);
RtlZeroMemory( HubName, len);
if( HubName==NULL)
return STATUS_INSUFFICIENT_RESOURCES;
status = CallUSBDI( dx, HubName, IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME, BusInfo.ControllerNameLength);
#ifdef DEBUG_INTERFACE
if( NT_SUCCESS(status))
TRACE2(" %d Controller name is %*S", HubName->ActualLength, HubName->HubName);
else
TRACE0("Cannot get controller name");
#endif//DEBUG_INTERFACE
ExFreePool(HubName);
return status;
#else
return STATUS_NOT_SUPPORTED;
#endif
}
/////////////////////////////////////////////////////////////////////////////
// UsbGetDeviceDescriptor: Get device descriptor (allocate memory for it)
// Remember to ExFreePool this memory
NTSTATUS UsbGetDeviceDescriptor( IN PUSBDRV_DEVICE_EXTENSION dx,
OUT PUSB_DEVICE_DESCRIPTOR deviceDescriptor,
OUT ULONG* Size)
{
NTSTATUS status ;
// Allocate memory for URB
USHORT UrbSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
ULONG sizeDescriptor = sizeof(USB_DEVICE_DESCRIPTOR);
PURB urb;
#ifdef DEBUG_INTERFACE
TRACE0("进入UsbGetDeviceDescriptor(),开始读取设备描述符");
#endif//DEBUG_INTERFACE
urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
if( urb==NULL)
{
// DebugPrintMsg("No URB memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Allocate memory for device descriptor
deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)ExAllocatePool(NonPagedPool, sizeDescriptor);
if( deviceDescriptor==NULL)
{
ExFreePool(urb);
TRACE0("No descriptor memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Build the Get Descriptor URB
UsbBuildGetDescriptorRequest(
urb, UrbSize,
USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, // Types, Index & LanguageId
deviceDescriptor, NULL, sizeDescriptor, // Transfer buffer
NULL); // Link URB
// Call the USB driver
//DebugPrintMsg("Getting device descriptor");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
TRACE2("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
}
// Remember count of bytes actually transferred
*Size = urb->UrbControlDescriptorRequest.TransferBufferLength;
TRACE0("设备描述符信息");
TRACE1("***** bLength = %x", deviceDescriptor->bLength);
TRACE1("***** bDescriptorType = %x", deviceDescriptor->bDescriptorType);
TRACE1("***** bcdUSB = %x", deviceDescriptor->bcdUSB);
TRACE1("***** bDeviceClass = %x", deviceDescriptor->bDeviceClass);
TRACE1("***** bDeviceSubClass = %x", deviceDescriptor->bDeviceSubClass);
TRACE1("***** bDeviceProtocol = %x", deviceDescriptor->bDeviceProtocol);
TRACE1("***** bMaxPacketSize0 = %x", deviceDescriptor->bMaxPacketSize0);
TRACE1("***** idVendor = %x", deviceDescriptor->idVendor);
TRACE1("***** idProduct = %x", deviceDescriptor->idProduct);
TRACE1("***** bcdDevice = %x", deviceDescriptor->bcdDevice);
TRACE1("***** iManufacturer = %x", deviceDescriptor->iManufacturer);
TRACE1("***** iProduct = %x", deviceDescriptor->iProduct);
TRACE1("***** iSerialNumber = %x", deviceDescriptor->iSerialNumber);
TRACE1("***** bNumConfigurations = %x", deviceDescriptor->bNumConfigurations);
ExFreePool(urb);
TRACE0("退出UsbGetDeviceDescriptor(),读取设备描述符结束");
return status;
}
/////////////////////////////////////////////////////////////////////////////
// UsbGetConfigurationDescriptors: Get specified Config and associated descriptors
// Allocate memory for descriptors.
// Remember to ExFreePool this memory
NTSTATUS UsbGetConfigurationDescriptors( IN PUSBDRV_DEVICE_EXTENSION dx,
OUT PUSB_CONFIGURATION_DESCRIPTOR *descriptors,
IN UCHAR ConfigIndex,
OUT ULONG* DescriptorsSize)
{
NTSTATUS status;
// Allocate memory for URB
USHORT UrbSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
PURB urb;
TRACE0(" Enter UsbGetConfigurationDescriptors()");
urb = (PURB)ExAllocatePool(NonPagedPool, UrbSize);
if( urb==NULL)
{
TRACE0("No URB memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Allocate memory just for basic config descriptor
*DescriptorsSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
*descriptors = (PUSB_CONFIGURATION_DESCRIPTOR)ExAllocatePool(NonPagedPool, *DescriptorsSize+16);
if( *descriptors==NULL)
{
TRACE0("No initial descriptor memory");
return STATUS_INSUFFICIENT_RESOURCES;
}
// Build the Get Descriptor URB
UsbBuildGetDescriptorRequest(
urb, UrbSize,
USB_CONFIGURATION_DESCRIPTOR_TYPE, ConfigIndex, 0,
*descriptors, NULL, *DescriptorsSize,
NULL);
// Call the USB driver
TRACE0("Getting basic configuration descriptor");
status = CallUSBDI( dx, urb,IOCTL_INTERNAL_USB_SUBMIT_URB,0);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
TRACE2("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
goto fail;
}
TRACE0("Configuration Descriptor:");
TRACE1("***** bLength = %x", (*descriptors)-