我的USB设备在跟PC时会出现异常,使用 BUS Hound 的reset device可以将USB复位,然后通信正常。
想在程序中模拟reset device操作,百度一下,DeviceIoControl()发送IOCTL_INTERNAL_USB_CYCLE_PORT 可以实现。
可是我使用DeviceIoControl()函数每次都返回0。IOCTL_INTERNAL_USB_CYCLE_PORT 是控制命令,应该选择控制管道吗?那应该如何获得控制管道句柄?
下面是我使用输出管道发送命令的代码,GetLastError()返回1,使用输入管道返回的错误也一样。
想在程序中模拟reset device操作,百度一下,DeviceIoControl()发送IOCTL_INTERNAL_USB_CYCLE_PORT 可以实现。
可是我使用DeviceIoControl()函数每次都返回0。IOCTL_INTERNAL_USB_CYCLE_PORT 是控制命令,应该选择控制管道吗?那应该如何获得控制管道句柄?
下面是我使用输出管道发送命令的代码,GetLastError()返回1,使用输入管道返回的错误也一样。
char outPipe[32] = "PIPE01"; // pipe name for bulk output pipe on our test board
char completeDeviceName[256] = "";
HANDLE
OpenOneDevice (
IN HDEVINFO HardwareDeviceInfo,
IN PSP_INTERFACE_DEVICE_DATA DeviceInfoData,
IN char *devName
)
{
PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData = NULL;
ULONG predictedLength = 0;
ULONG requiredLength = 0;
HANDLE hOut = INVALID_HANDLE_VALUE; SetupDiGetInterfaceDeviceDetail (
HardwareDeviceInfo,
DeviceInfoData,
NULL, // probing so no output buffer yet
0, // probing so output buffer length of zero
&requiredLength,
NULL); // not interested in the specific dev-node
// cprintf(n,"%d",2);
predictedLength = requiredLength;
// sizeof (SP_FNCLASS_DEVICE_DATA) + 512;
functionClassDeviceData =(PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc (predictedLength);
functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA);
//
// Retrieve the information from Plug and Play.
//
if (! SetupDiGetInterfaceDeviceDetail (
HardwareDeviceInfo,
DeviceInfoData,
functionClassDeviceData,
predictedLength,
&requiredLength,
NULL)) {
free( functionClassDeviceData );
return INVALID_HANDLE_VALUE;
}
strcpy( devName,functionClassDeviceData->DevicePath) ;
//EB_Printf( "Attempting to open %s\n", devName );
hOut = CreateFile (
functionClassDeviceData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
0, // No special attributes
NULL); // No template file
if (INVALID_HANDLE_VALUE == hOut) {
//EB_Printf( "FAILED to open %s\n", devName );
}
free( functionClassDeviceData );
return hOut;
}
HANDLE
OpenUsbDevice( LPGUID pGuid, char *outNameBuf){
ULONG NumberDevices;
HANDLE hOut = INVALID_HANDLE_VALUE;
HDEVINFO hardwareDeviceInfo;
SP_INTERFACE_DEVICE_DATA deviceInfoData;
ULONG i;
BOOLEAN done;
PUSB_DEVICE_DESCRIPTOR usbDeviceInst;
PUSB_DEVICE_DESCRIPTOR *UsbDevices = &usbDeviceInst;
*UsbDevices = NULL;
NumberDevices = 0;
hardwareDeviceInfo = SetupDiGetClassDevs (
pGuid,
NULL, // Define no enumerator (global)
NULL, // Define no
(DIGCF_PRESENT | // Only Devices present
DIGCF_INTERFACEDEVICE)); // Function class devices.
//
// Take a wild guess at the number of devices we have;
// Be prepared to realloc and retry if there are more than we guessed
//
NumberDevices = 4;
done = FALSE;
deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
// sprintf(n,"%d",1);
i=0;
while (!done) {
NumberDevices *= 2;
// sprintf(n,"%d",NumberDevices);
if (*UsbDevices) {
*UsbDevices =
(PUSB_DEVICE_DESCRIPTOR)realloc (*UsbDevices, (NumberDevices * sizeof (USB_DEVICE_DESCRIPTOR)));
} else {
*UsbDevices =
(PUSB_DEVICE_DESCRIPTOR)calloc (NumberDevices, sizeof (USB_DEVICE_DESCRIPTOR));
}
if (NULL == *UsbDevices) {
// SetupDiDestroyDeviceInfoList destroys a device information set
// and frees all associated memory.
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
return INVALID_HANDLE_VALUE;
}
usbDeviceInst = *UsbDevices + i;
for (; i < NumberDevices; i++) { if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
0, // We don't care about specific PDOs
pGuid,
i,
&deviceInfoData)) {
hOut = OpenOneDevice (hardwareDeviceInfo, &deviceInfoData, outNameBuf);
if ( hOut != INVALID_HANDLE_VALUE ) {
done = TRUE;
break;
}
} else {
if (ERROR_NO_MORE_ITEMS == GetLastError()) {
done = TRUE;
break;
}
}
}
}
NumberDevices = i;
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
free ( *UsbDevices );
return hOut;
}BOOL
GetUsbDeviceFileName( LPGUID pGuid, char *outNameBuf)
{
HANDLE hDev = OpenUsbDevice( pGuid, outNameBuf );
if ( hDev != INVALID_HANDLE_VALUE )
{
CloseHandle( hDev );
return TRUE;
}
return FALSE;
}HANDLE
open_file( char *filename)
{
int success = 1;
HANDLE h;
if ( !GetUsbDeviceFileName(
(LPGUID) &GUID_CLASS_I82930_BULK,
completeDeviceName) )
{
return INVALID_HANDLE_VALUE;
}
strcat (completeDeviceName,
"\\"
);
strcat (completeDeviceName,
filename
); h = CreateFile(completeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (h == INVALID_HANDLE_VALUE) {
//NOISY(("Failed to open (%s) = %d", completeDeviceName, GetLastError()));
success = 0;
} else {
//NOISY(("Opened successfully.\n"));
}
return h;
}OnOK() //向USB发送控制代码
{
HANDLE DeviceHandle=open_file(outPipe);
bool a= DeviceIoControl(DeviceHandle,IOCTL_INTERNAL_USB_CYCLE_PORT,
NULL, 0, // no input buffer
NULL, 0, // output buffer
NULL, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
DWORD b=GetLastError();
CloseHandle(DeviceHandle);
//m_edit.SetWindowText((CString)completeDeviceName);
// CDialog::OnOK();
}
第二,你的下位程序可能有问题,以D12为例,在中断寄存器里有一个USB设备挂起状态的标志位,需要对此做出里。
驱动是由ARM提供的,没找到WDM驱动的源码,只有2000下的,我改了一下,对IOCTL_INTERNAL_USB_CYCLE_PORT进行处理,还有一些问题,不过现在我找到了解决的思路,在啃文档中。
我之前只做过简单的协安装程序DLL,没有真正接触过驱动,很多问题都一知半解
下面是我响应IOCTL_INTERNAL_USB_CYCLE_PORT的代码,返回错误。
再次感谢你们的回复,让我在迷茫中看到希望!
NTSTATUS CycleUSBD(
IN IN PDEVICE_OBJECT urbTargetDev
)
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION nextStack;
PIRP Irp;
IO_STATUS_BLOCK ioStatus;
Irp = IoBuildDeviceIoControlRequest (IOCTL_INTERNAL_USB_CYCLE_PORT,
urbTargetDev,
NULL,
0,
NULL,
0,
TRUE,
NULL,
&ioStatus);
if ( Irp == NULL )
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
return ntStatus;
}
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);
IoSetCancelRoutine(Irp, NULL);
ntStatus = IoCallDriver( urbTargetDev, Irp );
return ntStatus;
}
而且,IOCTL_INTERNAL_USB_CYCLE_PORT是内部命令,用DEVICEIOCONTROL是用不了的,用deviceiocontro能用的是irpStack->Parameters.DeviceIoControl.IoControlCode;
你看看的驱动里是不是Parameters.DeviceIoControl.IoControlCode有没有,没有可以自己加,然后重新编译驱动,
如果想做硬件复位,必须自己改驱动,自定义IOCONTROLCODE实现,然后用DeviceIocontrol
或者在你的协议里除控制端口其他端口定义。还有,我认为你说的这个问题,你的设备经常断的问题,根本不在软件。
而在下位程序,这个问题,我遇到过,
就是我举例子说的,中断寄存器里有一位,是专门标识是否挂起的,即是不是断开的,如果断开,掉用reconnect,重新连接USB设备,重新枚举。
我去看看芯片文档
//-----------------
case IOCTL_D12_RESET_DEVICE:
{
NTSTATUS ntStatus;
ULONG portStatus; D12_KdPrint (("D12TEST.SYS: Reset Device Test\n"));
TRAP(); // test this
//
// Check the port state, if it is disabled we will need
// to re-enable it
//
ntStatus = D12_GetPortStatus(DeviceObject, &portStatus); if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&
portStatus & USBD_PORT_CONNECTED) {
//
// port is disabled, attempt reset
//
//D12_EnableParentPort(DeviceObject);
D12_ResetParentPort(DeviceObject);
} }
并在驱动里面构建IRP来reset USB