📄 cusbintf.cpp
字号:
for(UCHAR i = 0; i < config_count; i++)
{
//Set the default configuration size. If it is too small, we will have to call this twice.
DWORD dwConfigSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 256;
USB_CONFIGURATION_DESCRIPTOR* pConfig;
BOOLEAN query_config = TRUE; //This flag is TRUE when we should send a query.
while(query_config)
{
if(dwConfigSize % 8)
{
dwConfigSize = ((dwConfigSize /8) + 1 ) * 8;
DbgLogInfo(("CUsbInterface::UsbConfigGetDescriptor : adjusting size to %d\n",dwConfigSize));
}
pConfig = (USB_CONFIGURATION_DESCRIPTOR *) new BYTE[dwConfigSize];
if(!pConfig)
{
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory(pConfig, dwConfigSize);
//Set up the URB to get the configuration from the device
UsbBuildGetDescriptorRequest(
p_urb,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
i, //Configuration number
0,
pConfig,
0,
dwConfigSize,
0);
//Send the URB to the USB bus driver.
status = UsbCall_GSPN(p_urb);
//Default to not having to do the query again.
query_config = FALSE;
if(NT_SUCCESS(status))
{
//Our buffer was too small. Reallocate it with the size provided, and
// send the request again.
if ((p_urb->UrbControlDescriptorRequest.TransferBufferLength > 0) &&
(pConfig->wTotalLength > dwConfigSize))
{
//Save the size
dwConfigSize = pConfig->wTotalLength;
delete [] pConfig;
pConfig = NULL;
//Query for the configuration again.
query_config = TRUE;
}
}
else
{
delete [] pConfig;
pConfig = NULL;
}
}
if (pConfig)
{
//We were successful. Save the configuration descriptor
_p_configs[i] = pConfig;
status = STATUS_SUCCESS;
DumpUsbConfigDescriptor(pConfig);
}
}
delete p_urb;
return (status);
}
/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::assignInterface
//
// This is a helper function that save's interface information
//
VOID CUsbInterface::assignInterface(USBD_INTERFACE_INFORMATION* p_interface, DWORD index)
{
DWORD interface_size = p_interface->Length;
_p_interfaces[index] = (USBD_INTERFACE_INFORMATION *) new BYTE[interface_size];
if(_p_interfaces[index])
{
RtlCopyMemory(_p_interfaces[index], p_interface, interface_size);
DumpUsbInterfaceInfo(_p_interfaces[index]);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbConfigSelect
//
// Select a USB configuration
//
NTSTATUS CUsbInterface::UsbConfigSelect(ULONG configuration_number)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
USBD_INTERFACE_INFORMATION* p_interface;
POLARIS_REV_ID rev_id = (POLARIS_REV_ID)getRevID();
//Make sure the configuration number is valid
if (configuration_number >= ((ULONG)_device_descriptor.bNumConfigurations & 0xFF))
{
DbgLogError(("UsbConfigSelect: invalid configuration number: %x\n", configuration_number));
configuration_number = 0;
}
//Make sure we have the configuration descriptor.
if(!_p_configs || !_p_configs[configuration_number])
{
return STATUS_UNSUCCESSFUL;
}
USB_CONFIGURATION_DESCRIPTOR* p_config = _p_configs[configuration_number];
//Allocate the interface list
PUSBD_INTERFACE_LIST_ENTRY interface_list = new USBD_INTERFACE_LIST_ENTRY[p_config->bNumInterfaces + 1];
if (!interface_list)
{
DbgLogError(("CUsbInterface::UsbConfigSelect() can not allocate interfaceList\n"));
delete [] _p_interfaces;
_p_interfaces = NULL;
return (status);
}
RtlZeroMemory(interface_list, sizeof(USBD_INTERFACE_LIST_ENTRY) * (p_config->bNumInterfaces + 1));
//Get a pointer to each interface descriptor from the configuration descriptor.
UCHAR i;
if(rev_id == POLARIS_REVID_T0)
{
DbgLog(("the revision is T0\n"));
for (i = 0; i < p_config->bNumInterfaces; i++)
{
//the interface number is change according different scenario, so Interface =-1, Alternate = -1 (not Specifies)
interface_list[i].InterfaceDescriptor =
USBD_ParseConfigurationDescriptorEx(
p_config,
p_config,
-1, // Interface
-1, // Alternate Setting
-1, // Class - don't care
-1, // SubClass - don't care
-1); // Protocol - don't care
}
}
else if(rev_id >=POLARIS_REVID_A0)
{
DbgLog(("the revision is A0\n"));
for (i = 0; i < p_config->bNumInterfaces; i++)
{
interface_list[i].InterfaceDescriptor =
USBD_ParseConfigurationDescriptorEx(
p_config,
p_config,
(i+1), // Interface
0, // Alternate Setting
-1, // Class - don't care
-1, // SubClass - don't care
-1); // Protocol - don't care
}
}
else
{
DbgLogError(("Invalid revision ID\n"));
delete [] interface_list;
return STATUS_UNSUCCESSFUL;
}
//Set the last interface entry iin the list to NULL
interface_list[i].InterfaceDescriptor = NULL;
interface_list[i].Interface = NULL;
//Create a URB to select the requested configuration
PURB p_urb = USBD_CreateConfigurationRequestEx(p_config, &interface_list[0]);
if(!p_urb)
{
delete [] interface_list;
return STATUS_INSUFFICIENT_RESOURCES;
}
//Send the URB to select the configuration
status = UsbCall_GSPN(p_urb);
if (NT_SUCCESS(status) && USBD_SUCCESS(p_urb->UrbHeader.Status))
{
// free previous allocated interfaces
freeInterfaces();
//Allocate new interfaces
_p_interfaces = new PUSBD_INTERFACE_INFORMATION[p_config->bNumInterfaces];
if (!_p_interfaces)
{
ExFreePool(p_urb);
delete [] interface_list;
DbgLogError(("CUsbInterface::UsbConfigSelect() can not allocate _p_interfaces\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(_p_interfaces, sizeof(PUSBD_INTERFACE_INFORMATION) * p_config->bNumInterfaces);
//Save the current configuration index and handle
_config_index = configuration_number;
_config_handle = p_urb->UrbSelectConfiguration.ConfigurationHandle;
//For each interface, copy the interface information into our member variable.
ULONG interface_offset = 0;
for (i = 0; i < p_config->bNumInterfaces; i++)
{
p_interface = (PUSBD_INTERFACE_INFORMATION)
((PBYTE)&p_urb->UrbSelectConfiguration.Interface + interface_offset);
interface_offset += p_interface->Length;
assignInterface(p_interface, i);
}
}
ExFreePool(p_urb);
delete [] interface_list;
DbgLog(("Select Configuration successful\n"));
return (status);
}
/////////////////////////////////////////////////////////////////////////////////////////
//UsbInterfaceSelect
//
// Select a USB interface and alternate setting
//
NTSTATUS CUsbInterface::UsbInterfaceSelect(UCHAR interface_number, UCHAR alternate_setting)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL);
UCHAR interface_number_rev=0;
DWORD revID = getRevID();
if(revID==POLARIS_REVID_T0)
{
interface_number_rev = interface_number;
}
else if(revID >=POLARIS_REVID_A0)
{
interface_number_rev = interface_number+1;
}
else
{
DbgLogError(("Invaild revision ID\n"));
KeReleaseMutex(&_mutex, FALSE);
return status;
}
if (isInterfaceValid(interface_number))
{
//Check that alternate setting 1 exists for this interface.
PUSB_INTERFACE_DESCRIPTOR p_interface =
USBD_ParseConfigurationDescriptorEx(
_p_configs[_config_index],
_p_configs[_config_index],
interface_number_rev, // Interface
1, // Alternate Setting 1
-1, // Class - don't care
-1, // SubClass - don't care
-1); // Protocol - don't care
if (!p_interface)
{
KeReleaseMutex(&_mutex, FALSE);
//There is only one setting. Return success if we are selecting alternate
// setting 0 since we are already on it. If we are trying to select
// some other alternate setting, fail.
return ((0 == alternate_setting) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
//Get the interface descriptor for the selected interface and alternate setting.
p_interface =
USBD_ParseConfigurationDescriptorEx(_p_configs[_config_index],
_p_configs[_config_index],
interface_number_rev, // Interface
alternate_setting, // Alternate Setting
-1, // Class - don't care
-1, // SubClass - don't care
-1); // Protocol - don't care
if (!p_interface)
{
//Invalid interface and/or alternate setting
DbgLogError(("CUsbInterface::UsbInterfaceSelect() pInterfaceDescriptor is NULL\n"));
KeReleaseMutex(&_mutex, FALSE);
return STATUS_UNSUCCESSFUL;
}
UCHAR pipe_count = p_interface->bNumEndpoints;
ULONG urb_size = GET_SELECT_INTERFACE_REQUEST_SIZE(pipe_count);
PURB p_urb = (PURB) new BYTE[urb_size];
if(!p_urb)
{
KeReleaseMutex(&_mutex, FALSE);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(p_urb, urb_size);
UsbBuildSelectInterfaceRequest(
p_urb,
(USHORT)urb_size,
_config_handle,
interface_number_rev,
alternate_setting);
PUSBD_INTERFACE_INFORMATION p_interface_info =
(PUSBD_INTERFACE_INFORMATION)&p_urb->UrbSelectInterface.Interface;
p_interface_info->Length = GET_USBD_INTERFACE_SIZE(pipe_count);
//For isochronous pipes, set the maximum transfer size to 0x20000
for(UCHAR i = 0; i < pipe_count; i++)
{
if(p_interface_info->Pipes[i].PipeType == UsbdPipeTypeIsochronous)
{
p_interface_info->Pipes[i].MaximumTransferSize = 0x20000;
}
}
//Send the URB to the USB bus driver
status = UsbCall_GSPN(p_urb);
//If it was successful, save the interface information
if (NT_SUCCESS(status) && USBD_SUCCESS(p_urb->UrbHeader.Status))
{
// free previous allocated interfaces
if (_p_interfaces[interface_number])
{
delete [] (BYTE *)_p_interfaces[interface_number];
_p_interfaces[interface_number] = NULL;
}
//Get the interface information
p_interface_info =
(PUSBD_INTERFACE_INFORMATION)&p_urb->UrbSelectInterface.Interface;
assignInterface(p_interface_info, interface_number);
}
else
{
DbgLogError((
"CUsbInterface::UsbInterfaceSelect() FAILED NT Status(0x%x) USB Status(0x%x)\n",
status,
p_urb->UrbHeader.Status));
status = STATUS_UNSUCCESSFUL;
}
delete [] p_urb;
}
KeReleaseMutex(&_mutex, FALSE);
return (status);
}
#ifndef USBD_STATUS_XACT_ERROR
#define USBD_STATUS_XACT_ERROR ((USBD_STATUS)0xC0000011L)
#endif //USBD_STATUS_XACT_ERROR
#ifndef USBD_STATUS_BABBLE_DETECTED
#define USBD_STATUS_BABBLE_DETECTED ((USBD_STATUS)0xC0000012L)
#endif //USBD_STATUS_BABBLE_DETECTED
#ifndef USBD_STATUS_ISO_NOT_ACCESSED_BY_HW
#define USBD_STATUS_ISO_NOT_ACCESSED_BY_HW ((USBD_STATUS)0xC0020000L)
#endif //USBD_STATUS_ISO_NOT_ACCESSED_BY_HW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -