LWZ123999
LWZ123999
采纳率0%
2015-05-21 01:45

usb cdc(通信设备类)在用vc++写上层应用程序时遇到问题?

USB写一个应用时调用SetupDiEnumDeviceInterfaces()这个函数出错.

因为是CDC通信(端口(COM和LPT))而不是HID通信, 所以用得是固定"安装类"的GUID,网上也有很多人提过这问题,但一直木有人解决, 求救呀, 搞了很久很久了...

 GUID guidHID = {0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18};     //安装类GUID是在inf驱动文件上的GUID
    //HidD_GetHidGuid( &guidHID );    //因为不是HID设备,所以不用这个来获得GUID, 而是用上面这个固定GUID

    HDEVINFO hDevInfo = SetupDiGetClassDevs( &guidHID, NULL, 0, DIGCF_PRESENT );  //由于是"安装类的GUID"而非"接口类GUID", 所以在最后一个参数没加DIGCF_DEVICEINTERFACE

    if( INVALID_HANDLE_VALUE != hDevInfo )   //调用成功返回文件句柄, 如果调用失败返回INVALID_HANDLE_VALUE
    {
        SP_DEVICE_INTERFACE_DATA strtInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
        // 查找USB设备接口
        for( DWORD index=0; SetupDiEnumDeviceInterfaces(hDevInfo,NULL,&guidHID,index,&strtInterfaceData); ++index )   //程序在这一步出错, 枚举老返回0,导致没法进行下一步了
        {
            char buf[1000];
            SP_DEVICE_INTERFACE_DETAIL_DATA& strtDetailData = (SP_DEVICE_INTERFACE_DETAIL_DATA&)buf[0];
            strtDetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            // 若找到了设备,则读取设备路径名
            if( SetupDiGetDeviceInterfaceDetail(hDevInfo,&strtInterfaceData,&strtDetailData,_countof(buf),NULL,NULL) )
            {
                _tprintf( _T("[%d] path: %s\n"), index, strtDetailData.DevicePath );   //设备路径名

                //用CreateFile打开或创建设备
                HANDLE hUsb = CreateFile( strtDetailData.DevicePath, GENERIC_READ|GENERIC_WRITE//0
                    , FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
                if( INVALID_HANDLE_VALUE != hUsb )   //调用成功返回文件句柄, 如果调用失败返回INVALID_HANDLE_VALUE
                {
                    // 查询设备标识
                    HIDD_ATTRIBUTES strtAttrib = { sizeof(HIDD_ATTRIBUTES) };
                    //用HidD_GetAttributes获得特定HID属性
                    if( HidD_GetAttributes(hUsb,&strtAttrib) )
                    {
                        _tprintf( _T("VendorID : %hX\n"), strtAttrib.VendorID );
                        _tprintf( _T("ProductID: %hX\n"), strtAttrib.ProductID );
                        _tprintf( _T("VerNumber: %hX\n"), strtAttrib.VersionNumber );
                        if(strtAttrib.VendorID==0x3006 && strtAttrib.ProductID==0x1977)
                        {
                            _tprintf( _T("Find:VendorID-0x3006, ProductID-0x1977\n")); 
                            COMSTAT ComStat;
                            DWORD dwErrorFlags;
                            //ClearCommError(hUsb,&dwErrorFlags,&ComStat);  //读写设备之前应先调用这个函数清除错误标志

                            BYTE pBuffer[8] = {0};  
                            if( DeviceWrite(hUsb,pBuffer, 7)  )
                            {
                                for(int i=0;i<8;i++)
                                {
                                    _tprintf( _T("Read: %02X"),pBuffer[i]);
                                    if(((i+1)%16)==0)
                                    {
                                        _tprintf( _T("\n")); 
                                    }
                                }
                            }
                            else
                            {
                                _tprintf( _T("Read error"));
                            }
                        }

                    }
                    else
                        ShowError();

                    //释放资源
                    CloseHandle( hUsb );
                }
                else
                    ShowError();
            }
            else
                ShowError();
        }
        if( GetLastError() != ERROR_NO_MORE_ITEMS )
            ShowError();

        SetupDiDestroyDeviceInfoList( hDevInfo );
    }
    else
        ShowError();
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

3条回答

  • LWZ123999 LWZ123999 6年前

    没人回答呀,不知道是表达得不好还是为啥。。。。有点小伤心呀

    点赞 评论 复制链接分享
  • zzkjliu zzkjliu 6年前

    这种问题的解决如果对你来说有相当的经济价值,技术就不是问题。

    点赞 评论 复制链接分享
  • LWZ123999 LWZ123999 6年前

    问题已解决, 贴上那部分代码吧:
    int OpenUSBSerial() //打开USB串口设备
    {
    // 得到设备信息集

    HDEVINFO hDevInfo = SetupDiGetClassDevs(

    (LPGUID)&GUID_DEVCLASS_PORTS,

    NULL,

    0,

    DIGCF_PRESENT); // | DIGCF_ALLCLASSES

    if (hDevInfo == INVALID_HANDLE_VALUE)       
    {   
        printf("Error!   SetupDiGetClassDevs()   return   %d\n",   GetLastError());   
        SetupDiDestroyDeviceInfoList(hDevInfo);   
        return  0;       
    }   
    
    TCHAR   szBuf[MAX_PATH];   
    SP_DEVINFO_DATA  spDevInfoData = {sizeof(SP_DEVINFO_DATA)};   
    
    //开始列举设备   
    DWORD i = 0;
    for ( i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)   
    {   
        SP_DEVICE_INTERFACE_DATA  DeviceInterfaceData;   //在调用之前必须先设置好cbSize成员为该结构体的大小.--lwz
        DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
        BOOL nStatus = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &spDevInfoData.ClassGuid, i, &DeviceInterfaceData);
    
        //   得到设备名称   
        if ( SetupDiGetDeviceRegistryProperty(   
                                            hDevInfo,   
                                            &spDevInfoData,   
                                            SPDRP_DEVICEDESC,   
                                            NULL,     
                                            (PBYTE)szBuf,   
                                            MAX_PATH,     
                                            NULL) )   
        {   
            if(strcmp(szBuf,"DSPG USB DECT Port")==0)    //找到DSPG USB DECT Port这个设备 
            {
                printf("[%03d]   :   DeviceDesc   =   %s\n",   i,   szBuf);
                //   得到设备型号   
                if   (   SetupDiGetDeviceRegistryProperty(   
                                                        hDevInfo,   
                                                        &spDevInfoData,   
                                                        SPDRP_FRIENDLYNAME,   
                                                        NULL,     
                                                        (PBYTE)szBuf,   
                                                        MAX_PATH,     
                                                        NULL)   )   
                {   
                    printf("[%03d] : FriendName = %s\n", i, szBuf);    //输出为: DSPG USB DECT Port (COMxx)
    
                    TCHAR p1[MAX_PATH]=_T("\\\\.\\");   //即"\\.\"
                    TCHAR path2[MAX_PATH]=_T("COM");
                    TCHAR Path[14]="";
                    TCHAR *p,*p2;
    
                    p=_tcsstr(szBuf,path2);   //p= "COM15)"
    
                    p2 = lstrcat(p1,p);   //把p的字符串连接到p1后面, 结果为:"\\.\COM15)"
                    for(int i=0;i<lstrlen(p2)-1;i++)   //去掉"\\.\COM15)"最后一个字符")" 
                    {
                        Path[i] = p2[i];
                    }
    
                    //  _T("\\\\.\\COM15")
                    hUsb = CreateFile(
                                            Path,      //   "\\\\.\\COM15",实际名字就是"\\.\COM15"
                                            GENERIC_READ|GENERIC_WRITE,   
                                            0,//FILE_SHARE_READ|FILE_SHARE_WRITE, //0是独占不能共享不能多次打开
                                            NULL, 
                                            OPEN_EXISTING, //打开而不是创建
                                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //FILE_FLAG_OVERLAPPED 表示重叠方式
                                            NULL );
                    if(INVALID_HANDLE_VALUE == hUsb)  //调用成功返回文件句柄, 如果调用失败返回INVALID_HANDLE_VALUE
                    {
                        _tprintf( _T("CreateFile Error! \n"));
                        return -1;
                    }   
                    _tprintf( _T("CreateFile Succeed! \n"));
                }
    
            }
        }   
    
    }   
    
    printf("\nPort count = %d\n", i);
    return 0;
    

    }

    
    
    点赞 评论 复制链接分享