USB通讯的尝试

转载自http://blog.vckbase.com/bruceteen/archive/2010/12/17/52208.html

下载了一个不知道谁写的UsbPort代码,里面不相干的文件很多,有用的就几行(代码错误得一塌糊涂,必须初始化的变量没初始化,“==号”写成“=号”,……),历经多次失败终于运行正确,步骤如下:
1. 去微软网站下载WinDDK,现改名叫WDK,最新版本是GRMWDK_EN_7600_1.ISO,安装它。因为必须的文件hidsdi.h,hidpi.h,hidusage.h,hid.lib, hidclass.lib, hidparse.lib在VC中没自带。
2. 将WDK安装目录加入到VC设定中,加入到工程设定中是没用的
   menu:Tools\Options\Projects and Solutions\VC++ Directories,右边Show directories for中选择Include files,将两个目录添加进去,顺序如下:
   C:\WinDDK\7600.16385.1\inc\ddk
   $(VCInstallDir)include
   $(VCInstallDir)atlmfc\include
   C:\WinDDK\7600.16385.1\inc\api
   $(WindowsSdkDir)\include
   $(FrameworkSDKDir)include
   即保证 C:\WinDDK\7600.16385.1\inc\api 在 $(WindowsSdkDir)\include 前面,这样#include <windows.h>等才用的是WDK中的文件,否则不匹配导致编译失败。
   menu:Tools\Options\Projects and Solutions\VC++ Directories,右边Show directories for中选择Library files,添加 C:\WinDDK\7600.16385.1\lib\wxp\i386
3. 修改后的代码如下:
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <setupapi.h>
#pragma comment( lib, "setupapi.lib" )
extern "C" {
#include <hidsdi.h>
}
#pragma comment( lib, "hid.lib" )

#define ShowError() ShowError_(_T(__FILE__),__LINE__)
void ShowError_(LPCTSTR file, long line)
{
    LPVOID lpMsgBuf;
    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS
        , NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL );
    _tprintf( _T("---ERROR %s(%ld): %s\n"), file, line, (LPCTSTR)lpMsgBuf );
    LocalFree( lpMsgBuf );
}

int main()
{
    GUID guidHID;
    HidD_GetHidGuid( &guidHID );
    _tprintf( _T("HID GUID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n")
        , guidHID.Data1, guidHID.Data2, guidHID.Data3
        , guidHID.Data4[0], guidHID.Data4[1], guidHID.Data4[2], guidHID.Data4[3], guidHID.Data4[4]
        , guidHID.Data4[5], guidHID.Data4[6], guidHID.Data4[7] );

    HDEVINFO hDevInfo = SetupDiGetClassDevs( &guidHID, NULL, 0, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE );
    if( INVALID_HANDLE_VALUE != hDevInfo )
    {
        SP_DEVICE_INTERFACE_DATA strtInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
        for( DWORD index=0; SetupDiEnumDeviceInterfaces(hDevInfo,NULL,&guidHID,index,&strtInterfaceData); ++index )
        {
            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 );

                HANDLE hUsb = CreateFile( strtDetailData.DevicePath, 0//GENERIC_READ|GENERIC_WRITE
                    , FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
                if( INVALID_HANDLE_VALUE != hUsb )
                {
                    // 查询设备标识
                    HIDD_ATTRIBUTES strtAttrib = { sizeof(HIDD_ATTRIBUTES) };
                    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 );
                    }
                    else
                        ShowError();

                    CloseHandle( hUsb );
                }
                else
                    ShowError();
            }
            else
                ShowError();
        }
        if( GetLastError() != ERROR_NO_MORE_ITEMS )
            ShowError();

        SetupDiDestroyDeviceInfoList( hDevInfo );
    }
    else
        ShowError();

    return 0;
}


假如不想下载庞大的WDK包,我打包了必须的文件(XP系统),连同测试工程,下载地址为:http://blog.vckbase.com/Files/bruceteen/USBTest.zip
使用API操作USB太麻烦了,[七猫]告诉我可以用LibUSB-Win32(http://sourceforge.net/apps/trac/libusb-win32/wiki)
a. 调用usb_init函数,进行初始化
b. 调用usb_find_busses、usb_find_devices和usb_get_busses这三个函数获得已找到的USB总线序列;然后通过链表遍历所有的USB设备,根据已知的要打开USB设备的ID(VID/PID),找到相应的USB设备;最后调用usb_open函数打开该USB设备(在这里假设总线上没有相同VID和PID的USB设备。如果总线上存在着相同VID和PID的设备,还需要进行其他条件判断,比如设备名称,以保证是打开的是期望的USB设备)。
c. 使用usb_control_msg函数与USB设备进行通信,向USB设备读取数据或写入数据。
d. 关闭USB设备。

 

你可能感兴趣的:(null,include,interface,通讯,attributes,winddk)