首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC++ USB 設備程式設計完整指南

     編輯:關於VC++

前言

隨著 USB 設備普及,應用程式常需枚舉、識別與存取各類 USB 裝置。本文系統整理 USB 控制器枚舉、HID 類別裝置、大容量儲存裝置 (U盤) 的程式設計方法,基於 VC++ 6.0 + XP DDK 環境實測。

一、USB 架構層級枚舉

標準枚舉路徑:控制器 → Hub → 連接埠 → 設備

1. 列舉主控制器

TCHAR HCName[64];
for (int i = 0; ; ++i) {
    wsprintf(HCName, L"\\\\.\\HCD%d", i);
    HANDLE hHC = CreateFile(HCName, GENERIC_WRITE, FILE_SHARE_WRITE,
                           NULL, OPEN_EXISTING, 0, NULL);
    if (hHC == INVALID_HANDLE_VALUE) break; // 無更多控制器
    
    // 取得驅動名稱與 Hub 連結
    USB_HUB_NAME hubName = {0};
    DWORD bytesRet;
    DeviceIoControl(hHC, IOCTL_USB_GET_HUB_NAME, NULL, 0,
                    &hubName, sizeof(hubName), &bytesRet, NULL);
    CloseHandle(hHC);
    
    EnumHub(hubName.ucHubName); // 遞迴列舉 Hub
}

2. 列舉 Hub 與連接埠


void EnumHub(WCHAR* hubPath) {
    HANDLE hHub = CreateFile(hubPath, GENERIC_WRITE, FILE_SHARE_WRITE,
                            NULL, OPEN_EXISTING, 0, NULL);
    USB_NODE_INFORMATION hubInfo = {0};
    DeviceIoControl(hHub, IOCTL_USB_GET_NODE_INFORMATION, NULL, 0,
                    &hubInfo, sizeof(hubInfo), &bytesRet, NULL);
    
    for (ULONG port = 1; port <= hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts; ++port) {
        USB_PORT_CONNECTOR_PROPERTIES portProp = {0};
        portProp.ConnectionIndex = port;
        DeviceIoControl(hHub, IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES,
                        &portProp, sizeof(portProp), &portProp, sizeof(portProp),
                        &bytesRet, NULL);
        if (portProp.DeviceConnected) {
            // 取得設備描述符
            USB_DEVICE_DESCRIPTOR devDesc;
            // ... 透過 IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX 取得詳細資訊
        }
    }
    CloseHandle(hHub);
}

二、HID 類別裝置 (滑鼠、鍵盤、搖桿)

使用 Windows HID API 簡化開發:


#include 
#include 

GUID hidGuid;
HidD_GetHidGuid(&hidGuid);

HDEVINFO hDevInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, 
                                        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

SP_DEVICE_INTERFACE_DATA devInterface = {0};
devInterface.cbSize = sizeof(devInterface);

for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &hidGuid, i, &devInterface); ++i) {
    DWORD reqSize = 0;
    SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterface, NULL, 0, &reqSize, NULL);
    
    PSP_DEVICE_INTERFACE_DETAIL_DATA detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, reqSize);
    detail->cbSize = sizeof(*detail);
    
    if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterface, detail, reqSize, NULL, NULL)) {
        HANDLE hDev = CreateFile(detail->DevicePath, GENERIC_READ|GENERIC_WRITE,
                                FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        HIDD_ATTRIBUTES attrs = {0};
        attrs.Size = sizeof(attrs);
        HidD_GetAttributes(hDev, &attrs);
        // attrs.VendorID, attrs.ProductID, attrs.VersionNumber
        CloseHandle(hDev);
    }
    LocalFree(detail);
}
SetupDiDestroyDeviceInfoList(hDevInfo);

注意:XP 下 `HidD_GetHidGuid` 可能無法列舉滑鼠鍵盤,需改用 `GUID_DEVINTERFACE_MOUSE`/`KEYBOARD`。

三、大容量儲存裝置 (U盤) 偵測


TCHAR drive[] = L"\\\\.\\E:"; // 遍歷磁碟機代號
HANDLE hDrive = CreateFile(drive, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
                          NULL, OPEN_EXISTING, 0, NULL);

STORAGE_PROPERTY_QUERY query = {0};
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;

STORAGE_DEVICE_DESCRIPTOR desc = {0};
DWORD bytesRet;
DeviceIoControl(hDrive, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
                &desc, sizeof(desc), &bytesRet, NULL);
// desc.BusType == BusTypeUsb 確認為 USB 裝置
// desc.VendorId, desc.ProductId, desc.ProductRevision 取得詳細資訊
CloseHandle(hDrive);

四、常見問題與解決方案

問題原因對策
CreateFile 失敗 (Access Denied)權限不足以系統管理員執行,或調整裝置安全性描述元
IOCTL 返回 ERROR_INVALID_FUNCTION驅動不支援該控制碼檢查驅動版本,嘗試替代 IOCTL
無法列舉特定廠商裝置私有協定/加密需廠商提供 SDK 或逆向分析

參考資源

  • USBView (Windows DDK 範例)
  • USB 2.0 規格書 Chapter 9 & 11
  • Microsoft HID 類別驅動文件
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved