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();

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

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

问题已解决, 贴上那部分代码吧:
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;

}