Programming the Microsoft Windows Driver Model中描述: 多功能设备 如果你的设备有一个配置和多个接口,Microsoft的总线驱动程序将自动把这种设备当作一个组合的,或多功能设备。你必须为每个接口提供一个功能驱动程序,通过在INF中用接口类和子类替换厂商标识和产品标识。总线驱动程序为每个接口创建一个物理设备对象(PDO),这样,PnP管理器就可以装载独立的驱动程序。当任何一个功能驱动程序读取配置描述符时,总线驱动程序就提供一个修改后的仅描述一个接口的描述符。关于INF文件中的设备标识的各种可能形式请参考第十二章。
以上是书上的一段话,我做了些试验说明事情不是那么回事 例如我的设备有两个INTERFACE第一个INTERFACE中只有一个中断端点EP1 第二个INTERFACE 中有两个批端点,分别为EP2和EP3,按上面的意思,端点EP2,和EP3是不可用的,而我在配置的过程中获取这些端点的句柄,之后向这些端点读/写数据完全可以,是不是说上面书上的描述有问题?
我的配置代码如下:
///////////////////////////////////////////////////////////////////////////// //UsbSelectConfiguration: 选择配置 NTSTATUS UsbSelectConfiguration( IN PUSER_DEVICE_EXTENSION dx) { // 获取所有描述符 PUSB_CONFIGURATION_DESCRIPTOR Descriptors = NULL; ULONG size; ULONG i; NTSTATUS status = UsbGetConfigurationDescriptors( dx, Descriptors, 0, size); if( !NT_SUCCESS(status)) { FreeIfAllocated(Descriptors); return status; }
USBD_INTERFACE_LIST_ENTRY ilist[3];
//从复合的配置描述符中寻找第一个接口描述符 PUSB_INTERFACE_DESCRIPTOR id = USBD_ParseConfigurationDescriptorEx( Descriptors, Descriptors, 0, -1, -1, -1, -1); //均为搜索条件 -1表示无 if( id==NULL) { FreeIfAllocated(Descriptors); return STATUS_NO_SUCH_DEVICE; }
//用第一个接口描述符填充接口数组 ilist[0].InterfaceDescriptor = id; ilist[0].Interface = NULL; //这将指向urb->UrbSelectConfiguration.Interface
//找到第二个接口 id = USBD_ParseConfigurationDescriptorEx( Descriptors, Descriptors, 1, -1, -1, -1, -1); //均为搜索条件 -1表示无 if( id==NULL) { FreeIfAllocated(Descriptors); return STATUS_NO_SUCH_DEVICE; } ilist[1].InterfaceDescriptor = id; ilist[1].Interface=NULL;
//表示结束 ilist[2].InterfaceDescriptor= NULL; ilist[2].Interface=NULL;
// 创建 select configuration URB PURB urb = USBD_CreateConfigurationRequestEx( Descriptors, ilist);
if(urb==NULL) DebugPrint("urb is null");
status = CallUSBDI( dx->NextStackDevice, urb); if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status)) { DebugPrint("Error Status:%x urb Status:%x",status,urb->UrbHeader.Status); status = STATUS_UNSUCCESSFUL; } else { dx->UsbConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle; PUSBD_INTERFACE_INFORMATION InterfaceInfo = &urb->UrbSelectConfiguration.Interface; DebugPrint("EndPoint Number:%d",InterfaceInfo->NumberOfPipes);
PUSBD_PIPE_INFORMATION pi = &InterfaceInfo->Pipes[0];
pi=&(ilist[1].Interface->Pipes[0]); dx->hEpBulkWrite = pi->PipeHandle;//这是我获取第二个接口中EP2的方法 pi=&(ilist[1].Interface->Pipes[1]); dx->hEpBulkRead=pi->PipeHandle;//这是获取EP3的方法 }
FreeIfAllocated(urb); FreeIfAllocated(Descriptors); return status; }
|