📄 usbfx2lk_usb.cpp
字号:
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary Context
//
// NOTES:
//
// The OSR FX2 Learning Kit device running the OSR standard firmware only
// offers one USB Interface.
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS SelectUsbInterfaces(PUSBFX2LK_EXT DevExt,
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
LONG numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
LONG interfaceNumber = 0;
LONG interfaceindex = 0;
ULONG i;
PURB urb = NULL;
NTSTATUS status;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
PUSBD_INTERFACE_LIST_ENTRY interfaceList = NULL;
PUSBD_INTERFACE_LIST_ENTRY tmp = NULL;
PUSBD_INTERFACE_INFORMATION Interface = NULL;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("SelectUsbInterfaces: Enter\n"));
//
// Allocate memory for the devices supported interfaces.
//
interfaceList = (PUSBD_INTERFACE_LIST_ENTRY) ExAllocatePoolWithTag(NonPagedPool,
sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1),'eliU');
//
// Confirm memory was allocated.
//
if(!interfaceList) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("SelectUsbInterfaces: Failed to allocate mem for interfaceList\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
tmp = interfaceList;
//
// Parse the received USB interfaces selecting one that matches our input criteria.
// Fortunately, we are not fussy and will take any interface found, which for our
// device is the only one we return.
//
while(interfaceNumber < numberOfInterfaces) {
//
// A driver would call USBD_ParseConfigurationDescriptorEx in order
// to select a interface that meets the input criteria of driver.
// This would work well, if the a device had different interfaces.
// Unfortunately, our device only has one interface, so this will
// select it.
//
interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
ConfigurationDescriptor,
ConfigurationDescriptor,
interfaceindex,
0, -1, -1, -1);
if(interfaceDescriptor) {
//
// An interface met our criteria, save the information
// in our interface list.
//
interfaceList->InterfaceDescriptor = interfaceDescriptor;
interfaceList->Interface = NULL;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("--------- Interface %d\n",interfaceNumber));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbLength = %d\n",interfaceList->InterfaceDescriptor->bLength));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbDescriptorType = %d\n",interfaceList->InterfaceDescriptor->bDescriptorType));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbInterfaceNumber = %d\n",interfaceList->InterfaceDescriptor->bInterfaceNumber));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbAlternateSetting = %d\n",interfaceList->InterfaceDescriptor->bAlternateSetting));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbNumEndpoints = %d\n",interfaceList->InterfaceDescriptor->bNumEndpoints));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbInterfaceClass = %d\n",interfaceList->InterfaceDescriptor->bInterfaceClass));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbInterfaceSubClass = %d\n",interfaceList->InterfaceDescriptor->bInterfaceSubClass));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tbInterfaceProtocol = %d\n",interfaceList->InterfaceDescriptor->bInterfaceProtocol));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("\tiInterface = %d\n\n",interfaceList->InterfaceDescriptor->iInterface));
interfaceList++;
interfaceNumber++;
}
interfaceindex++;
}
//
// Format a URB that will be used to select the input configuration
// that will be used to interface to the device.
//
interfaceList->InterfaceDescriptor = NULL;
interfaceList->Interface = NULL;
urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
//
// Make sure that a URB was allocated.
//
if(urb) {
//
// Set our pipe information into the interface pipes list.
// This tells our device our we will use the pipe.
//
Interface = &urb->UrbSelectConfiguration.Interface;
for(i=0; i<Interface->NumberOfPipes; i++) {
//
// Set the transfer size and any pipe flags we use
// USBD sets the rest of the Interface struct members
//
Interface->Pipes[i].MaximumTransferSize =
USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
}
//
// Submit the urb to the device.
//
status = SubmitUrb(DevExt, urb);
if(NT_SUCCESS(status)) {
//
// save a copy of interface information in the device extension.
//
DevExt->UsbInterface = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool,
Interface->Length,'eliU');
if(DevExt->UsbInterface) {
RtlCopyMemory(DevExt->UsbInterface,
Interface,
Interface->Length);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,("SelectUsbInterfaces: memory alloc for UsbInterface failed\n"));
goto SelectUsbInterfacesExit;
}
//
// Dump the interface to the debugger
//
Interface = &urb->UrbSelectConfiguration.Interface;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("---------\n"));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("NumberOfPipes 0x%x\n",
Interface->NumberOfPipes));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("Length 0x%x\n",
Interface->Length));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("Alt Setting 0x%x\n",
Interface->AlternateSetting));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("Interface Number 0x%x\n",
Interface->InterfaceNumber));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
Interface->Class,
Interface->SubClass,
Interface->Protocol));
//
// Initialize the PipeContext
// Dump the pipe info
//
if(Interface->NumberOfPipes) {
DevExt->PipeContext = (PUSBFX2LK_PIPE_CONTEXT) ExAllocatePoolWithTag(NonPagedPool,
Interface->NumberOfPipes *
sizeof(USBFX2LK_PIPE_CONTEXT),'xtcP');
if(DevExt->PipeContext) {
for(i=0; i<Interface->NumberOfPipes; i++) {
RtlCopyMemory(&DevExt->PipeContext[i].PipeInformation,
&Interface->Pipes[i],sizeof(USBD_PIPE_INFORMATION));
//
// Setup our convenience pointer
//
if (Interface->Pipes[i].PipeType == UsbdPipeTypeBulk) {
if (USBD_PIPE_DIRECTION_IN(&Interface->Pipes[i])) {
//
// This is the bulk IN pipe. Make sure we only
// have one
//
ASSERT(DevExt->BulkInPipe == NULL);
DevExt->BulkInPipe = &DevExt->PipeContext[i];
} else {
//
// This is the bulk OUT pipe. Make sure we only
// have one
//
ASSERT(DevExt->BulkOutPipe == NULL);
DevExt->BulkOutPipe = &DevExt->PipeContext[i];
}
} else {
//
// Our device has two bulk pipes and one iso pipe,
// we shouldn't get any other pipe besides iso here
//
ASSERT(Interface->Pipes[i].PipeType == UsbdPipeTypeInterrupt);
//
// And we only have one
//
ASSERT(DevExt->InterruptPipe == NULL);
DevExt->InterruptPipe = &DevExt->PipeContext[i];
}
}
DevExt->NumberOfPipes = Interface->NumberOfPipes;
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("SelectUsbInterfaces: memory alloc for UsbInterface failed\n"));
goto SelectUsbInterfacesExit;
}
}
for(i=0; i<Interface->NumberOfPipes; i++) {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("---------\n"));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("PipeType 0x%x\n",
Interface->Pipes[i].PipeType));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("EndpointAddress 0x%x\n",
Interface->Pipes[i].EndpointAddress));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("MaxPacketSize 0x%x\n",
Interface->Pipes[i].MaximumPacketSize));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("Interval 0x%x\n",
Interface->Pipes[i].Interval));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("Handle %p\n",
Interface->Pipes[i].PipeHandle));
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("MaximumTransferSize 0x%x\n",
Interface->Pipes[i].MaximumTransferSize));
}
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,("---------\n"));
} else {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,("Failed to select an interface\n"));
}
} else {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("SelectUsbInterfaces: USBD_CreateConfigurationRequestEx failed\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
}
//
// Clean up after ourselves and exit.
//
SelectUsbInterfacesExit:
if(tmp) {
ExFreePool(tmp);
}
if(urb) {
ExFreePool(urb);
}
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("SelectUsbInterfaces: Exit\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// DeconfigureUsbDevice
//
// This routine is called to release the Usb Device and deconfigure the
// descriptors.
//
//
// INPUTS:
//
// DevExt - Address of the Devices Device Extension.
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// None
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary Context
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DeconfigureUsbDevice(PUSBFX2LK_EXT DevExt)
{
PURB urb;
ULONG size = sizeof(struct _URB_SELECT_CONFIGURATION);;
NTSTATUS status;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DeconfigureUsbDevice: Enter\n"));
urb = (PURB) ExAllocatePoolWithTag(NonPagedPool, size,'csuO');
if(urb) {
UsbBuildSelectConfigurationRequest(urb, (USHORT)size, NULL);
status = SubmitUrb(DevExt,urb);
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
("DeconfigureUsbDevice: Failed to deconfigure device %08.8x %s\n",
status,OsrNtStatusToString(status)));
}
ExFreePool(urb);
} else {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,("DeconfigureUsbDevice: Failed to allocate urb\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
}
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DeconfigureUsbDevice: Exit\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// DetermineDeviceSpeed
//
// This routine is called by ConfigureUsbDevice to determine if the device
// is running at low or high speed.
//
//
// INPUTS:
//
// DevExt - Address of the Devices Device Extension.
//
// OUTPUTS:
//
// When finished, the RunningAtHighSpeed member of the
// device extension is set to either TRUE or FALSE
//
// RETURNS:
//
// None
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary Context
//
// NOTES:
// We need to determine if the device is running at high speed by querying
// for the USB_BUS_INTERFACE_USBDI_V1 interface. One slight problem here,
// USB 2.0 support wasn't added to Windows 2000 until SP4 and so the latest
// DDK is a bit behind. If you were to believe the DDK documentation and
// headers, you would think that this interface is not supported at ALL in
// Windows 2000. However, this exchange in
// microsoft.public.development.device.drivers in July 2004 says otherwise:
//
////////////////////////////////////////////////////////////////////////////
//
// Subject: Availability of USB_BUS_INTERFACE_USBDI_V1 in Windows 2000 Sp4 ?
//
// Hello,
//
// Since Windows 2000 Service PAck4 has support for USB 2.0 Enhanced USB
// Host Controller , I was wondering if it has support for
// USB_BUS_INTERFACE_USBDI_V1 structure , since i want to use its member
// ( PUSB_BUSIFFN_IS_DEVICE_HIGH_SPEED IsDeviceHighSpeed ) .
// MSDN says that this is supported only on WinXP onwards but i am
// thinking why should this not be available when Enhanced USB Host
// Controller driver is available on W2k sp4
//
// could anybody please clarify this?
//
// thanks in advance
// Taha
//
////////////////////////////////////////////////////////////////////////////
//
// Eliyas Yakub [MSFT] Jul 12, 10:41 am show options
// From: "Eliyas Yakub [MSFT]" <eliy...@online.microsoft.com>
// Date: Mon, 12 Jul 2004 10:41:52 -0700
//
// Looking at the code USBPORT code, I can definitely say it's available. I
// will bring this to our doc team's attention. Thanks.
//
// -Eliyas
//
////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -