我的USB设备在跟PC时会出现异常,使用 BUS Hound 的reset device可以将USB复位,然后通信正常。
想在程序中模拟reset device操作,百度一下,DeviceIoControl()发送IOCTL_INTERNAL_USB_CYCLE_PORT 可以实现。
可是我使用DeviceIoControl()函数每次都返回0。IOCTL_INTERNAL_USB_CYCLE_PORT 是控制命令,应该选择控制管道吗?那应该如何获得控制管道句柄?
下面是我使用输出管道发送命令的代码,GetLastError()返回1,使用输入管道返回的错误也一样。

解决方案 »

  1.   

    char inPipe[32] = "PIPE00";     // pipe name for bulk input pipe on our test board
    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();
    }
      

  2.   

    如果设备总是异常,比如放在那过阵子就掉线,或者通讯一会就掉线,那么首先应该解决硬件问题,把硬件弄稳定了再说。还有,我不明白为什么不用设备本身所用的USB器件厂家提供的接口函数,而去随便百度一个例子?
      

  3.   

    第一,你的驱动里在IOCTL.C里你确定处理了IOCTL_INTERNAL_USB_CYCLE_PORT?
    第二,你的下位程序可能有问题,以D12为例,在中断寄存器里有一个USB设备挂起状态的标志位,需要对此做出里。
      

  4.   

    非常感谢你们的回复!的确这个方法不是从源头解决问题,但是交给我的问题是如何复位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;
    }
      

  5.   

    IOCTL_INTERNAL_USB_CYCLE_PORT据我搜索查的,这个命令是软复位,并不真正复位USB通信
    而且,IOCTL_INTERNAL_USB_CYCLE_PORT是内部命令,用DEVICEIOCONTROL是用不了的,用deviceiocontro能用的是irpStack->Parameters.DeviceIoControl.IoControlCode;
    你看看的驱动里是不是Parameters.DeviceIoControl.IoControlCode有没有,没有可以自己加,然后重新编译驱动,
    如果想做硬件复位,必须自己改驱动,自定义IOCONTROLCODE实现,然后用DeviceIocontrol
    或者在你的协议里除控制端口其他端口定义。还有,我认为你说的这个问题,你的设备经常断的问题,根本不在软件。
    而在下位程序,这个问题,我遇到过,
    就是我举例子说的,中断寄存器里有一位,是专门标识是否挂起的,即是不是断开的,如果断开,掉用reconnect,重新连接USB设备,重新枚举。
      

  6.   

    你们用的usb芯片是什么芯片?
    我去看看芯片文档
      

  7.   

       switch (ioControlCode) 
    //-----------------
      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);
            }        }
      

  8.   

    IOCTL_INTERNAL_USB_RESET_PORT 
    并在驱动里面构建IRP来reset USB