📄 rwusb.cpp
字号:
case STATUS_TIMEOUT:
Adapter->NumDataErrors++;
DEBUGMSG(DBG_FUNC, (" UsbIoCompleteRead STATUS_TIMEOUT\n"));
break;
case STATUS_PENDING:
DEBUGMSG(DBG_FUNC, (" UsbIoCompleteRead STATUS_PENDING\n"));
break;
case STATUS_DEVICE_DATA_ERROR:
// can get during shutdown
Adapter->NumDataErrors++;
DEBUGMSG(DBG_FUNC, (" UsbIoCompleteRead STATUS_DEVICE_DATA_ERROR\n"));
break;
case STATUS_UNSUCCESSFUL:
Adapter->NumDataErrors++;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead STATUS_UNSUCCESSFUL\n"));
break;
case STATUS_INSUFFICIENT_RESOURCES:
Adapter->NumDataErrors++;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead STATUS_INSUFFICIENT_RESOURCES\n"));
break;
case STATUS_INVALID_PARAMETER:
Adapter->NumDataErrors++;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead STATUS_INVALID_PARAMETER\n"));
break;
case STATUS_CANCELLED:
DEBUGMSG(DBG_FUNC, (" UsbIoCompleteRead STATUS_CANCELLED\n"));
break;
case STATUS_DEVICE_NOT_CONNECTED:
// can get during shutdown
Adapter->NumDataErrors++;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead STATUS_DEVICE_NOT_CONNECTED\n"));
break;
case STATUS_DEVICE_POWER_FAILURE:
// can get during shutdown
Adapter->NumDataErrors++;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead STATUS_DEVICE_POWER_FAILURE\n"));
break;
default: // 默认值
Adapter->NumDataErrors++;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead UNKNOWN WEIRD STATUS = 0x%x, dec %d\n",status,status ));
break;
}
//
// 如果不成功,需释放接收缓冲
//
if ( STATUS_SUCCESS != status )
{
pRecBuf->state = STATE_FREE;
}
//
// 释放IRP和分配给它的MDL
//
IoFreeIrp( pIrp );
pRecBuf->Irp = NULL;
Adapter->NumReads++; // 读取成功
UsbDecIoCount( Adapter ); // 使挂起的读IRP减1
if (( STATUS_SUCCESS != status ) && ( STATUS_CANCELLED != status ))
{
PURB urb = (PURB) pRecBuf->Urb;
DEBUGMSG(DBG_ERR, (" UsbIoCompleteRead error, will schedule a clear stall via URB_FUNCTION_RESET_PIPE\n"));
DEBUGMSG(DBG_ERR, (" USBD status = 0x%x\n", urb->UrbHeader.Status));
DEBUGMSG(DBG_ERR, (" NT status = 0x%x\n", status));
//
// 什么也没读到,重启管道
//
InterlockedExchange( &Adapter->fPendingReadClearStall, TRUE );
ScheduleWorkItem( Adapter,
ResetPipeCallback, Adapter->BulkInPipeHandle, 0);
}
KeSetEvent(&pRecBuf->Event, 0, FALSE);
//
// 当返回的状态为STATUS_MORE_PROCESSING_REQUIRED时,UsbIoCompleteRead完成例程将在此IRP处停止工作
//
status = STATUS_MORE_PROCESSING_REQUIRED;
DEBUGMSG(DBG_FUNC, ("-UsbIoCompleteRead\n"));
return status;
}
VOID
ProcessDataCallBack( PUSB_WORK_ITEM pWorkItem )
{
PUSB_DEVICE Adapter;
PRCV_BUFFER pRecBuf;
Adapter = (PUSB_DEVICE) pWorkItem->pDevice;
pRecBuf = ( PRCV_BUFFER ) pWorkItem->InfoBuf;
ProcessData(
Adapter,
pRecBuf
);
FreeWorkItem( pWorkItem );
}
/*****************************************************************************
//
//
// ConfigureDevice
//
// USB设备的配置例程
//
//
*****************************************************************************/
NTSTATUS
ConfigureDevice(
IN PUSB_DEVICE DeviceExt
)
{
PUSB_DEVICE Adapter;
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
ULONG size;
DEBUGMSG(DBG_FUNC,(" +ConfigureDevice()\n"));
Adapter = DeviceExt;
ASSERT( ((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor == NULL );
urb = (PURB) &((PUSB_INFO) Adapter->pUsbInfo)->DescriptorUrb;
// When USB_CONFIGURATION_DESCRIPTOR_TYPE is specified for DescriptorType
// in a call to UsbBuildGetDescriptorRequest(),
// all interface, endpoint, class-specific, and vendor-specific descriptors
// for the configuration also are retrieved.
// The caller must allocate a buffer large enough to hold all of this
// information or the data is truncated without error.
// Therefore the 'siz' set below is just a 'good guess', and we may have to retry
size = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 40; // Store size, may need to free
// We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest()
// has a big enough device->UsbConfigurationDescriptor buffer not to truncate
while( 1 )
{
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor = MemAlloc( size);
if ( !((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor )
{
MemFree(urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
return STATUS_INSUFFICIENT_RESOURCES;
}
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor,
NULL,
size,
NULL);
ntStatus = CallUSBD(DeviceExt, urb); //Get Usb Config Descriptor; done in main thread
DEBUGMSG(DBG_OUT,(" ConfigureDevice() Configuration Descriptor = %x, len %x\n",
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength));
//
// if we got some data see if it was enough.
// NOTE: we may get an error in URB because of buffer overrun
if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor->wTotalLength > size)
{
MemFree(((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor, size);
size = ((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor->wTotalLength;
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor = NULL;
}
else
{
break; // we got it on the first try
}
} // end, while (retry loop )
ASSERT( ((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor );
if (!NT_SUCCESS(ntStatus)) {
DEBUGMSG( DBG_ERR,(" ConfigureDevice() Get Config Descriptor FAILURE (%x)\n", ntStatus));
goto release;
}
//
// We have the configuration descriptor for the configuration we want.
// Now we issue the select configuration command to get
// the pipes associated with this configuration.
//
ntStatus = SelectInterface(DeviceExt,
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationDescriptor
);
if (!NT_SUCCESS(ntStatus))
{
DEBUGMSG( DBG_ERR,(" ConfigureDevice() SelectInterface() FAILURE (%x)\n", ntStatus));
}
/*else
{
//
// Next we must get the Class-Specific Descriptor
// Get the USB dongle's Class-Specific descriptor; this has many
// characterisitics we must tell Ndis about, such as supported speeds,
// BOFS required, rate sniff-supported flag, turnaround time, window size,
// data size.
//
ntStatus = GetClassDescriptor( device, &(device->ClassDesc));
if (NT_SUCCESS(ntStatus))
{
// fill out device from class-specific descriptor info
}
}*/
release:
DEBUGMSG(DBG_FUNC,(" -ConfigureDevice (%x)\n", ntStatus));
return ntStatus;
}
/*****************************************************************************
//
//
// SelectInterface
//
// USB设备的配置接口例程
//
//
*****************************************************************************/
NTSTATUS
SelectInterface(
IN PUSB_DEVICE DeviceExt,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
{
PUSB_DEVICE Adapter;
NTSTATUS ntStatus;
PURB selurb = NULL;
ULONG i;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
PUSBD_INTERFACE_INFORMATION Interface = NULL;
DEBUGMSG(DBG_FUNC,(" +SelectInterface\n"));
Adapter = DeviceExt;
//
// USB driver only supports one interface, we must parse
// the configuration descriptor for the interface
// and remember the pipes.
//
// USBD_ParseConfigurationDescriptorEx searches a given configuration
// descriptor and returns a pointer to an interface that matches the
// given search criteria. We only support one interface on this device
//
interfaceDescriptor =
USBD_ParseConfigurationDescriptorEx( // 寻找一个给定的配置描述符和返回一个指向与搜索条件匹配的接口指针
ConfigurationDescriptor, // 指向包含要寻找的那个接口的USB配置描述符
ConfigurationDescriptor, // 指向描述符内的地址,此地址由ConfigurationDescriptor提供,并作为搜索的起始地址
-1, // 指定被检索接口的设备定义索引,如果它不是一个搜索条件,则应该设置为-1
-1, // 指定被检索接口的设备定义可选设置索引,如果调用者不希望此可选设置值为搜索的条件,则此参数应该设置为-1
-1, // 指定被检索接口类的由设备或USB定义的接口类标识符,如果调用者不希望此接口级别的值为搜索条件,则此参数应该设置为-1
-1, // 指定被检索接口类的由设备或USB定义的接口子类标识符,如果调用者不希望此接口子类的值为搜索条件,则此参数应该设置为-1
-1 // 指定被检索接口协议的、由设备或USB定义的标识符,如果调用者不希望此接口协议的值为搜索条件,则此参数应该为-1
);
if ( !interfaceDescriptor)
{
DEBUGMSG(DBG_ERR,("SelectInterface() ParseConfigurationDescriptorEx() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
if ( interfaceDescriptor )
{
USBD_INTERFACE_LIST_ENTRY interfaces[2] = { // 一个接口数组,该数组是用来插入到一个配置请求的
{interfaceDescriptor,NULL},
{NULL, NULL}, // fence to terminate the array
};
selurb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, interfaces); // 分配并格式化一个URB,以便为USB设备选择一个配置
if(!selurb)
{
DEBUGMSG(DBG_ERR,("SelectInterface()::USBD_CreateConfigurationRequest() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
// 不要调用MemFree(),因为缓冲区是由USBD_CreateConfigurationRequest
// 分配的,而不是MemAlloc()
ExFreePool(selurb); // 释放存储池的一个块
return STATUS_INSUFFICIENT_RESOURCES;
}
DEBUGMSG(DBG_OUT,(" USBD_CreateConfigurationRequest created the urb\n"));
Interface = &selurb->UrbSelectConfiguration.Interface;
DEBUGMSG(DBG_OUT,(" After USBD_CreateConfigurationRequest, before CallUBD\n"));
/* if (Interface)
{
for (i = 0; i < Interface->NumberOfPipes; ++i)
{
if(!(Interface->Pipes[i].EndpointAddress ==(UCHAR) 0x81) && (Interface->Pipes[i].MaximumPacketSize == 64))
{
DEBUGMSG(DBG_OUT,(" - Bulk in Endpoint has wrong attributes\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
if(!(Interface->Pipes[i].EndpointAddress ==(UCHAR) 0x02) && (Interface->Pipes[i].MaximumPacketSize == 64))
{
DEBUGMSG(DBG_OUT,(" - Bulk out Endpoint has wrong attributes\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
if(!(Interface->Pipes[i].EndpointAddress ==(UCHAR) 0x83) && (Interface->Pipes[i].MaximumPacketSize == 8))
{
DEBUGMSG(DBG_OUT,(" - Bulk out Endpoint has wrong attributes\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
}
}
else//如果If(Interface)失败
{
DEBUGMSG(DBG_ERR,("SelectInterface()::Interface=&selurb->UrbSelectConfiguration.Interface failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}*/
for (i=0; i< Interface->NumberOfPipes; i++)
{
//
// 处理管道的初始化,设置最大的传输量
// 注意, 在选定了接口后,USb可以改变
// 传输量
if(Interface->Pipes[i].PipeType==UsbdPipeTypeBulk )
{
Interface->Pipes[i].MaximumTransferSize = MAX_PACKET_SIZE;
}
}
/*
UsbBuildSelectConfigurationRequest(selurb,
(USHORT)sizeof(selurb),
ConfigurationDescriptor);*/
ntStatus = CallUSBD(DeviceExt, selurb); // 传递URB结构到USBD
((PUSB_INFO) Adapter->pUsbInfo)->UsbConfigurationHandle =
selurb->UrbSelectConfiguration.ConfigurationHandle;
}
else
{
DEBUGMSG(DBG_ERR,("SelectInterface() USBD_CreateConfigurationRequest() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS(ntStatus))
{
//
// 保存该设备的配置句柄
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -