windows-nt/Source/XPSP1/NT/drivers/wdm/usb/driver/wceusbsh/usbutils.c

687 lines
23 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/* ++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
USBUTILS.C
Abstract:
USB configuration utility functions.
These functions are called in the context of PNP_START_DEVICE.
In order to mark them pageable we don't use a spinlock,
which is OK because of the context.
We do not use look-aside lists to manage pool allocs here since they are one-shot.
If the allocs fail then the load will fail.
Environment:
kernel mode only
Revision History:
07-14-99 : created
Authors:
Jeff Midkiff (jeffmi)
-- */
#include <wdm.h>
#include <stdio.h>
#include <stdlib.h>
#include <usbdi.h>
#include <usbdlib.h>
#include <ntddser.h>
#include "wceusbsh.h"
NTSTATUS
UsbSelectInterface(
IN PDEVICE_OBJECT PDevObj,
IN PUSB_CONFIGURATION_DESCRIPTOR PConfigDesc,
IN UCHAR AlternateSetting
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGEWCE1, UsbGetDeviceDescriptor)
#pragma alloc_text(PAGEWCE1, UsbSelectInterface)
#pragma alloc_text(PAGEWCE1, UsbConfigureDevice)
#endif
/*
Sample dump for the Anchor EZ-Link (AN2720) cable:
WCEUSBSH(0): DeviceDescriptor: fbfa8fe8
WCEUSBSH(0): Length 12
WCEUSBSH(0):
WCEUSBSH(0): Device Descriptor
WCEUSBSH(0): ------------------------
WCEUSBSH(0): bLength 12
WCEUSBSH(0): bDescriptorType 1
WCEUSBSH(0): bcdUSB 100
WCEUSBSH(0): bDeviceClass ff
WCEUSBSH(0): bDeviceSubClass ff
WCEUSBSH(0): bDeviceProtocol ff
WCEUSBSH(0): bMaxPacketSize0 8
WCEUSBSH(0): idVendor 547
WCEUSBSH(0): idProduct 2720
WCEUSBSH(0): bcdDevice 0
WCEUSBSH(0): iManufacturer 0
WCEUSBSH(0): iProduct 0
WCEUSBSH(0): iSerialNumber 0
WCEUSBSH(0): bNumConfigs 1
WCEUSBSH(0): ------------------------
WCEUSBSH(0):
WCEUSBSH(0): Configuration Descriptor
WCEUSBSH(0): ----------------
WCEUSBSH(0): bLength 9
WCEUSBSH(0): bDescriptorType 2
WCEUSBSH(0): wTotalLength d0
WCEUSBSH(0): bNumInterfaces 1
WCEUSBSH(0): bConfigurationValue 1
WCEUSBSH(0): iConfiguration 0
WCEUSBSH(0): bmAttributes a0
WCEUSBSH(0): MaxPower 32
WCEUSBSH(0): ----------------
WCEUSBSH(0):
WCEUSBSH(0): Interface Descriptor(0)
WCEUSBSH(0): ------------------------
WCEUSBSH(0): bLength 9
WCEUSBSH(0): bDescriptorType 4
WCEUSBSH(0): bInterfaceNumber 0
WCEUSBSH(0): bAlternateSetting 0
WCEUSBSH(0): bNumEndpoints 2
WCEUSBSH(0): bInterfaceClass ff
WCEUSBSH(0): bInterfaceSubClass ff
WCEUSBSH(0): bInterfaceProtocol ff
WCEUSBSH(0): iInterface 0
WCEUSBSH(0): ------------------------
WCEUSBSH(0):
WCEUSBSH(0): Interface Definition
WCEUSBSH(0): ------------------------
WCEUSBSH(0): Number of pipes 2
WCEUSBSH(0): Length 38
WCEUSBSH(0): Alt Setting 0
WCEUSBSH(0): Interface Number 0
WCEUSBSH(0): Class ff
WCEUSBSH(0): Subclass ff
WCEUSBSH(0): Protocol ff
WCEUSBSH(0): ------------------------
WCEUSBSH(0): 'COMM' Device Found at Index:0 InterfaceNumber:0 AlternateSetting: 0
WCEUSBSH(0):
WCEUSBSH(0): Pipe Information (0)
WCEUSBSH(0): ----------------
WCEUSBSH(0): Pipe Type 2
WCEUSBSH(0): Endpoint Addr 82
WCEUSBSH(0): MaxPacketSize 40
WCEUSBSH(0): Interval 0
WCEUSBSH(0): Handle fbfcef90
WCEUSBSH(0): MaxTransSize 1ffff
WCEUSBSH(0): ----------------
WCEUSBSH(0):
WCEUSBSH(0): Pipe Information (1)
WCEUSBSH(0): ----------------
WCEUSBSH(0): Pipe Type 2
WCEUSBSH(0): Endpoint Addr 2
WCEUSBSH(0): MaxPacketSize 40
WCEUSBSH(0): Interval 0
WCEUSBSH(0): Handle fbfcefac
WCEUSBSH(0): MaxTransSize 1ffff
WCEUSBSH(0): ----------------
WCEUSBSH(0): IntPipe: 0 DataOutPipe: fbfcefac DataInPipe: fbfcef90
*/
NTSTATUS
UsbGetDeviceDescriptor(
IN PDEVICE_OBJECT PDevObj
)
{
PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
NTSTATUS status;
ULONG descSize;
ULONG urbCDRSize;
PURB pUrb;
DbgDump(DBG_USB, (">UsbGetDeviceDescriptor\n"));
PAGED_CODE();
urbCDRSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
pUrb = ExAllocatePool(NonPagedPool, urbCDRSize);
if (pUrb != NULL) {
descSize = sizeof(USB_DEVICE_DESCRIPTOR);
RtlZeroMemory(&pDevExt->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
UsbBuildGetDescriptorRequest(pUrb,
(USHORT)urbCDRSize,
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
&pDevExt->DeviceDescriptor,
NULL,
descSize,
NULL );
status = UsbSubmitSyncUrb( PDevObj, pUrb, TRUE, DEFAULT_CTRL_TIMEOUT );
if (STATUS_SUCCESS == status) {
#if DBG
if (DebugLevel & DBG_USB) {
DbgDump(DBG_USB, ("Device Descriptor\n"));
DbgDump(DBG_USB, ("------------------------\n"));
DbgDump(DBG_USB, ("bLength 0x%x\n", pDevExt->DeviceDescriptor.bLength));
DbgDump(DBG_USB, ("bDescriptorType 0x%x\n", pDevExt->DeviceDescriptor.bDescriptorType));
DbgDump(DBG_USB, ("bcdUSB 0x%x\n", pDevExt->DeviceDescriptor.bcdUSB));
DbgDump(DBG_USB, ("bDeviceClass 0x%x\n", pDevExt->DeviceDescriptor.bDeviceClass));
DbgDump(DBG_USB, ("bDeviceSubClass 0x%x\n", pDevExt->DeviceDescriptor.bDeviceSubClass));
DbgDump(DBG_USB, ("bDeviceProtocol 0x%x\n", pDevExt->DeviceDescriptor.bDeviceProtocol));
DbgDump(DBG_USB, ("bMaxPacketSize0 0x%x\n", pDevExt->DeviceDescriptor.bMaxPacketSize0));
DbgDump(DBG_USB, ("idVendor 0x%x\n", pDevExt->DeviceDescriptor.idVendor));
DbgDump(DBG_USB, ("idProduct 0x%x\n", pDevExt->DeviceDescriptor.idProduct));
DbgDump(DBG_USB, ("bcdDevice 0x%x\n", pDevExt->DeviceDescriptor.bcdDevice));
DbgDump(DBG_USB, ("iManufacturer 0x%x\n", pDevExt->DeviceDescriptor.iManufacturer));
DbgDump(DBG_USB, ("iProduct 0x%x\n", pDevExt->DeviceDescriptor.iProduct));
DbgDump(DBG_USB, ("iSerialNumber 0x%x\n", pDevExt->DeviceDescriptor.iSerialNumber));
DbgDump(DBG_USB, ("bNumConfigs 0x%x\n", pDevExt->DeviceDescriptor.bNumConfigurations));
DbgDump(DBG_USB, ("------------------------\n"));
}
#endif
} else {
DbgDump(DBG_ERR, ("UsbSubmitSyncUrb error: 0x%x\n", status));
RtlZeroMemory(&pDevExt->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
}
ExFreePool(pUrb);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
DbgDump(DBG_ERR, ("UsbGetDeviceDescriptor 0x%x\n", status));
}
if (STATUS_INSUFFICIENT_RESOURCES == status) {
LogError( NULL,
PDevObj,
0, 0, 0,
ERR_GET_DEVICE_DESCRIPTOR,
status,
SERIAL_INSUFFICIENT_RESOURCES,
pDevExt->DeviceName.Length + sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0, NULL );
} else if (STATUS_SUCCESS != status ) {
// handles all other failures
LogError( NULL,
PDevObj,
0, 0, 0,
ERR_GET_DEVICE_DESCRIPTOR,
status,
SERIAL_HARDWARE_FAILURE,
pDevExt->DeviceName.Length + sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0,
NULL
);
}
DbgDump(DBG_USB, ("<UsbGetDeviceDescriptor 0x%x\n", status));
return status;
}
//
// BUGBUG: currently assumes 1 interface
//
NTSTATUS
UsbSelectInterface(
IN PDEVICE_OBJECT PDevObj,
IN PUSB_CONFIGURATION_DESCRIPTOR PConfigDesc,
IN UCHAR AlternateSetting
)
{
PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
NTSTATUS status = STATUS_SUCCESS;
PURB pUrb = NULL;
ULONG pipe;
ULONG index = 0;
UCHAR interfaceNumber = 0;
PUSBD_INTERFACE_INFORMATION pInterfaceInfo = NULL;
BOOLEAN foundCommDevice = FALSE;
USBD_INTERFACE_LIST_ENTRY interfaceList[2] = {0, 0};
DbgDump(DBG_USB, (">UsbSelectInterface %d\n", AlternateSetting));
PAGED_CODE();
if ( !PDevObj || !PConfigDesc ) {
status = STATUS_INVALID_PARAMETER;
DbgDump(DBG_ERR, ("UsbSelectInterface 0x%x\n", status));
goto SelectInterfaceError;
}
interfaceList[0].InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
PConfigDesc,
PConfigDesc,
-1,
AlternateSetting,
-1,
-1,
-1 );
if (interfaceList[0].InterfaceDescriptor) {
// interfaceList[1].InterfaceDescriptor = NULL;
DbgDump(DBG_USB, ("\n"));
DbgDump(DBG_USB, ("Interface Descriptor(%d)\n", interfaceNumber ));
DbgDump(DBG_USB, ("------------------------\n"));
DbgDump(DBG_USB, ("bLength 0x%x\n", interfaceList[0].InterfaceDescriptor->bLength ));
DbgDump(DBG_USB, ("bDescriptorType 0x%x\n", interfaceList[0].InterfaceDescriptor->bDescriptorType));
DbgDump(DBG_USB, ("bInterfaceNumber 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceNumber ));
DbgDump(DBG_USB, ("bAlternateSetting 0x%x\n", interfaceList[0].InterfaceDescriptor->bAlternateSetting ));
DbgDump(DBG_USB, ("bNumEndpoints 0x%x\n", interfaceList[0].InterfaceDescriptor->bNumEndpoints ));
DbgDump(DBG_USB, ("bInterfaceClass 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceClass ));
DbgDump(DBG_USB, ("bInterfaceSubClass 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceSubClass ));
DbgDump(DBG_USB, ("bInterfaceProtocol 0x%x\n", interfaceList[0].InterfaceDescriptor->bInterfaceProtocol ));
DbgDump(DBG_USB, ("iInterface 0x%x\n", interfaceList[0].InterfaceDescriptor->iInterface ));
DbgDump(DBG_USB, ("------------------------\n"));
pUrb = USBD_CreateConfigurationRequestEx( PConfigDesc,
&interfaceList[0]);
if ( pUrb ) {
//
// perform any pipe initialization here
//
PUSBD_INTERFACE_INFORMATION pInitInterfaceInfo = &pUrb->UrbSelectConfiguration.Interface;
for ( index = 0;
index < interfaceList[0].InterfaceDescriptor->bNumEndpoints;
index++) {
pInitInterfaceInfo->Pipes[index].MaximumTransferSize = pDevExt->MaximumTransferSize;
pInitInterfaceInfo->Pipes[index].PipeFlags = 0;
}
status = UsbSubmitSyncUrb(PDevObj, pUrb, TRUE, DEFAULT_CTRL_TIMEOUT );
if (STATUS_SUCCESS == status) {
pDevExt->ConfigurationHandle = pUrb->UrbSelectConfiguration.ConfigurationHandle;
pInterfaceInfo = &pUrb->UrbSelectConfiguration.Interface;
DbgDump(DBG_USB, ("Interface Definition\n" ));
DbgDump(DBG_USB, ("------------------------\n"));
DbgDump(DBG_USB, ("Number of pipes 0x%x\n", pInterfaceInfo->NumberOfPipes));
DbgDump(DBG_USB, ("Length 0x%x\n", pInterfaceInfo->Length));
DbgDump(DBG_USB, ("Alt Setting 0x%x\n", pInterfaceInfo->AlternateSetting));
DbgDump(DBG_USB, ("Interface Number 0x%x\n", pInterfaceInfo->InterfaceNumber));
DbgDump(DBG_USB, ("Class 0x%x\n", pInterfaceInfo->Class));
DbgDump(DBG_USB, ("Subclass 0x%x\n", pInterfaceInfo->SubClass));
DbgDump(DBG_USB, ("Protocol 0x%x\n", pInterfaceInfo->Protocol));
DbgDump(DBG_USB, ("------------------------\n"));
if ( (pInterfaceInfo->Class == USB_NULL_MODEM_CLASS) &&
(pInterfaceInfo->AlternateSetting == AlternateSetting) &&
(pInterfaceInfo->NumberOfPipes)) {
foundCommDevice = TRUE;
pDevExt->UsbInterfaceNumber = pInterfaceInfo->InterfaceNumber;
} else {
status = STATUS_NO_SUCH_DEVICE;
DbgDump(DBG_ERR, ("UsbSelectInterface 0x%x\n", status));
goto SelectInterfaceError;
}
} else {
DbgDump(DBG_ERR, ("UsbSubmitSyncUrb 0x%x\n", status));
goto SelectInterfaceError;
}
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
DbgDump(DBG_ERR, ("USBD_CreateConfigurationRequestEx 0x%x\n", status));
goto SelectInterfaceError;
}
DbgDump(DBG_USB, ("\n"));
DbgDump(DBG_USB, ("Function Device Found at Index:0x%x InterfaceNumber:0x%x AlternateSetting: 0x%x\n",
interfaceNumber, pDevExt->UsbInterfaceNumber, AlternateSetting));
//
// We found the interface we want, now discover the pipes
// The standard interface is defined to contain 1 bulk read, 1 bulk write, and an optional INT pipe
// BUGBUG: if there are more endpoints then they will overwrite the previous with this code.
//
ASSERT( pInterfaceInfo );
for ( pipe = 0; pipe < pInterfaceInfo->NumberOfPipes; pipe++) {
PUSBD_PIPE_INFORMATION pPipeInfo;
pPipeInfo = &pInterfaceInfo->Pipes[pipe];
DbgDump(DBG_USB, ("\n"));
DbgDump(DBG_USB, ("Pipe Information (%d)\n", pipe));
DbgDump(DBG_USB, ("----------------\n"));
DbgDump(DBG_USB, ("Pipe Type 0x%x\n", pPipeInfo->PipeType));
DbgDump(DBG_USB, ("Endpoint Addr 0x%x\n", pPipeInfo->EndpointAddress));
DbgDump(DBG_USB, ("MaxPacketSize 0x%x\n", pPipeInfo->MaximumPacketSize));
DbgDump(DBG_USB, ("Interval 0x%x\n", pPipeInfo->Interval));
DbgDump(DBG_USB, ("Handle 0x%x\n", pPipeInfo->PipeHandle));
DbgDump(DBG_USB, ("MaxTransSize 0x%x\n", pPipeInfo->MaximumTransferSize));
DbgDump(DBG_USB, ("----------------\n"));
//
// save pipe info in our device extension
//
if ( USB_ENDPOINT_DIRECTION_IN( pPipeInfo->EndpointAddress ) ) {
//
// Bulk Data In pipe
//
if ( USB_ENDPOINT_TYPE_BULK == pPipeInfo->PipeType) {
//
// Bulk IN pipe
//
pDevExt->ReadPipe.wIndex = pPipeInfo->EndpointAddress;
pDevExt->ReadPipe.hPipe = pPipeInfo->PipeHandle;
pDevExt->ReadPipe.MaxPacketSize = pPipeInfo->MaximumPacketSize;
} else if ( USB_ENDPOINT_TYPE_INTERRUPT == pPipeInfo->PipeType ) {
//
// INT Pipe - alloc a notify buffer for 1 packet
//
PVOID pOldBuff = NULL;
PVOID pNewBuff = NULL;
pDevExt->IntPipe.MaxPacketSize = pPipeInfo->MaximumPacketSize;
if ( pDevExt->IntPipe.MaxPacketSize ) {
pNewBuff = ExAllocatePool( NonPagedPool, pDevExt->IntPipe.MaxPacketSize );
if ( !pNewBuff ) {
status = STATUS_INSUFFICIENT_RESOURCES;
DbgDump(DBG_ERR, ("ExAllocatePool: 0x%x\n", status));
goto SelectInterfaceError;
}
} else {
DbgDump(DBG_ERR, ("No INT MaximumPacketSize\n"));
status = STATUS_NO_SUCH_DEVICE;
goto SelectInterfaceError;
}
if (pDevExt->IntBuff) {
pOldBuff = pDevExt->IntBuff;
ExFreePool(pOldBuff);
}
pDevExt->IntBuff = pNewBuff;
pDevExt->IntPipe.hPipe = pPipeInfo->PipeHandle;
pDevExt->IntPipe.wIndex = pPipeInfo->EndpointAddress;
pDevExt->IntReadTimeOut.QuadPart = MILLISEC_TO_100NANOSEC( g_lIntTimout );
} else {
DbgDump(DBG_ERR, ("Invalid IN PipeType"));
status = STATUS_NO_SUCH_DEVICE;
goto SelectInterfaceError;
}
} else if ( USB_ENDPOINT_DIRECTION_OUT( pPipeInfo->EndpointAddress ) ) {
//
// OUT EPs
//
if ( USB_ENDPOINT_TYPE_BULK == pPipeInfo->PipeType ) {
//
// Bulk OUT Pipe
//
pDevExt->WritePipe.hPipe = pPipeInfo->PipeHandle;
pDevExt->WritePipe.wIndex = pPipeInfo->EndpointAddress;
pDevExt->WritePipe.MaxPacketSize = pPipeInfo->MaximumPacketSize;
} else {
DbgDump(DBG_ERR, ("Invalid OUT PipeType"));
status = STATUS_NO_SUCH_DEVICE;
goto SelectInterfaceError;
}
} else {
DbgDump(DBG_ERR, ("Invalid EndpointAddress"));
status = STATUS_NO_SUCH_DEVICE;
goto SelectInterfaceError;
}
}
DbgDump(DBG_USB, ("\n"));
DbgDump(DBG_USB, ("INT Pipe: %p\t OUT Pipe: %p\t IN Pipe: %p\n",
pDevExt->IntPipe.hPipe, pDevExt->WritePipe.hPipe, pDevExt->ReadPipe.hPipe ));
} else {
DbgDump(DBG_ERR, ("USBD_ParseConfigurationDescriptorEx: No match not found\n"));
status = STATUS_NO_SUCH_DEVICE;
goto SelectInterfaceError;
}
//
// did we find all of our pipes?
//
SelectInterfaceError:
if ( !foundCommDevice || !pDevExt->ReadPipe.hPipe || !pDevExt->WritePipe.hPipe || (STATUS_SUCCESS != status) ) {
LogError( NULL,
PDevObj,
0, 0, 0,
ERR_SELECT_INTERFACE,
status,
(status == STATUS_INSUFFICIENT_RESOURCES) ? SERIAL_INSUFFICIENT_RESOURCES : SERIAL_HARDWARE_FAILURE,
pDevExt->DeviceName.Length + sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0, NULL );
}
if ( pUrb ) {
ExFreePool(pUrb);
}
DbgDump(DBG_USB, ("<UsbSelectInterface 0x%x\n", status));
return status;
}
NTSTATUS
UsbConfigureDevice(
IN PDEVICE_OBJECT PDevObj
)
{
PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
PUSB_CONFIGURATION_DESCRIPTOR pConDesc = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
PURB pUrb = NULL;
ULONG size;
ULONG urbCDRSize;
ULONG numConfigs;
UCHAR config;
DbgDump(DBG_USB, (">UsbConfigureDevice\n"));
PAGED_CODE();
urbCDRSize = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
// configure the device
pUrb = ExAllocatePool(NonPagedPool, urbCDRSize);
if (pUrb == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DbgDump(DBG_ERR, ("UsbConfigureDevice ERROR: 0x%x\n", status));
goto ConfigureDeviceError;
}
//
// there may be problems with the 82930 chip, so make this buffer bigger
// to prevent choking
//
size = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 256;
//
// get the number of configurations
//
numConfigs = pDevExt->DeviceDescriptor.bNumConfigurations;
//
// walk all of the configurations looking for a CDC device
//
for (config = 0; config < numConfigs; config++) {
//
// we will probably only do this once, maybe twice
//
while (TRUE) {
pConDesc = ExAllocatePool(NonPagedPool, size);
if (pConDesc == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DbgDump(DBG_ERR, ("ExAllocatePool: 0x%x\n", status));
goto ConfigureDeviceError;
}
//
// Get descriptor information from the host controller driver (HCD).
// All interface, endpoint, class-specific, and vendor-specific descriptors
// for the configuration also are retrieved
//
UsbBuildGetDescriptorRequest( pUrb,
(USHORT)urbCDRSize,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
config, // Index
0, // LanguageId
pConDesc,// TransferBuffer
NULL, // TransferBufferMdl
size, // TransferBufferLength
NULL); // Link
status = UsbSubmitSyncUrb( PDevObj, pUrb, TRUE, DEFAULT_CTRL_TIMEOUT );
if (status != STATUS_SUCCESS) {
DbgDump(DBG_ERR, ("UsbSubmitSyncUrb: 0x%x\n", status));
goto ConfigureDeviceError;
}
//
// see if we got enough data, we may get an error in URB because of
// buffer overrun
//
if ((pUrb->UrbControlDescriptorRequest.TransferBufferLength > 0)
&& (pConDesc->wTotalLength > size)) {
//
// size of data exceeds current buffer size, so allocate correct
// size
//
size = pConDesc->wTotalLength;
ExFreePool(pConDesc);
pConDesc = NULL;
} else {
break;
}
}
#if DBG
DbgDump(DBG_USB, ("\n"));
DbgDump(DBG_USB, ("Configuration Descriptor\n" ));
DbgDump(DBG_USB, ("----------------\n"));
DbgDump(DBG_USB, ("bLength 0x%x\n", pConDesc->bLength ));
DbgDump(DBG_USB, ("bDescriptorType 0x%x\n", pConDesc->bDescriptorType ));
DbgDump(DBG_USB, ("wTotalLength 0x%x\n", pConDesc->wTotalLength ));
DbgDump(DBG_USB, ("bNumInterfaces 0x%x\n", pConDesc->bNumInterfaces ));
DbgDump(DBG_USB, ("bConfigurationValue 0x%x\n", pConDesc->bConfigurationValue ));
DbgDump(DBG_USB, ("iConfiguration 0x%x\n", pConDesc->iConfiguration ));
DbgDump(DBG_USB, ("bmAttributes 0x%x\n", pConDesc->bmAttributes ));
DbgDump(DBG_USB, ("MaxPower 0x%x\n", pConDesc->MaxPower ));
DbgDump(DBG_USB, ("----------------\n"));
DbgDump(DBG_USB, ("\n"));
#endif
status = UsbSelectInterface(PDevObj, pConDesc, (UCHAR)g_ulAlternateSetting);
ExFreePool(pConDesc);
pConDesc = NULL;
//
// found a config we like
//
if (status == STATUS_SUCCESS)
break;
} // config
ConfigureDeviceError:
if (pUrb != NULL) {
ExFreePool(pUrb);
}
if (pConDesc != NULL) {
ExFreePool(pConDesc);
}
if (STATUS_INSUFFICIENT_RESOURCES == status) {
LogError( NULL,
PDevObj,
0, 0, 0,
ERR_CONFIG_DEVICE,
status,
SERIAL_INSUFFICIENT_RESOURCES,
pDevExt->DeviceName.Length + sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0, NULL );
} else if (STATUS_SUCCESS != status ) {
// handles all other failures
LogError( NULL,
PDevObj,
0, 0, 0,
ERR_CONFIG_DEVICE,
status,
SERIAL_HARDWARE_FAILURE,
pDevExt->DeviceName.Length + sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0, NULL );
}
DbgDump(DBG_USB, ("<UsbConfigureDevice (0x%x)\n", status));
return status;
}
// EOF