Windows設備信息獲取:(攝像頭,聲卡為例)Qt,WindowsAPI對比說明(1)

      網友投稿 1192 2022-05-29

      簡介

      近期一個小項目需要獲取本機攝像頭,聲卡的信息,提供配置文件,用作軟件配置。然后開始慢慢研究,說一下自己遇到的一些坑。

      系統環境

      Windows:Win10 Qt:5.8.5 VS:vs2013

      1

      2

      3

      相關資料

      USB 獲取設備VID,HID

      windows SetupAPI 介紹和使用

      獲取指定USB設備的VID PID和SerialNumber

      代碼片段

      USB HID,VID說明

      USB 獲取設備VID,HID

      里邊源碼說明:路徑:https://github.com/signal11/hidapi , 進入下載,我選擇zip,下載到本地,解壓

      資源結構如下:

      其實Windows,主要用了兩個文件,hidapi文件夾下的頭文件:hidapi.h,wendows文件夾下的,hid.c資源文件,其實windows文件下有測試工程,自己可以測試下。

      在上邊文章里說,需要編譯dll,放入工程下來調用,其實沒必要,你已經拿到源碼,直接把上述提到的兩個文件加入到自己的工程文件里,直接調用接口就可以。

      注意事項:

      SetupAPI.lib庫記得添加到附加庫目錄,否則會提示為未識別符號。

      1

      因為在源碼里邊沒有包含,所以需要注意自己手動在附加庫里邊添加。

      hid.c里邊添加 #pragma comment(lib,"SetupAPI.lib");

      1

      2

      因為只是查詢設備信息,所以只用了一下幾個相關函數:

      int HID_API_EXPORT hid_init(void) //驅動初始化 static HANDLE open_device(const char *path, BOOL enumerate) //打開設備,enumerate打開方式,只讀,只寫 int HID_API_EXPORT hid_exit(void);//退出 struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) //獲取設備相關信息 void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)//資源信息結構體釋放 HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) //根據HID,PID,序列號,打開設備

      1

      2

      3

      4

      5

      6

      設備信息結構體(鏈表) :hid_device_info:驅動路徑,VID,PID,序列號,設備發行號,生產廠商,設備名稱,設備使用頁,接口編號

      /** hidapi info structure */ struct hid_device_info { /** Platform-specific device path */ char *path; /** Device Vendor ID */ unsigned short vendor_id; /** Device Product ID */ unsigned short product_id; /** Serial Number */ wchar_t *serial_number; /** Device Release Number in binary-coded decimal, also known as Device Version Number */ unsigned short release_number; /** Manufacturer String */ wchar_t *manufacturer_string; /** Product string */ wchar_t *product_string; /** Usage Page for this Device/Interface (Windows/Mac only). */ unsigned short usage_page; /** Usage for this Device/Interface (Windows/Mac only).*/ unsigned short usage; /** The USB interface which this logical device represents. Valid on both Linux implementations in all cases, and valid on the Windows implementation only if the device contains more than one interface. */ int interface_number; /** Pointer to the next device */ struct hid_device_info *next; };

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      下面開始說,獲取設備信息函數(USB設備):

      struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) { BOOL res; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; /* Windows objects for interacting with the driver. */ GUID InterfaceClassGuid = { 0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 }; //GUID InterfaceClassGuid = {0xCA3E7AB9, 0xB4C3, 0x4AE6, 0x82, 0x51, 0x57, 0x9E, 0xF9, 0x33, 0x89, 0x0F}; //GUID InterfaceClassGuid = {0x36fc9e60, 0xc465, 0x11cf, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 }; //GUID InterfaceClassGuid = { 0x4d36e96cL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 }; SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; int device_index = 0; int i; if (hid_init() < 0) return NULL; /* Initialize the Windows objects. */ memset(&devinfo_data, 0x0, sizeof(devinfo_data)); devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); /* Iterate over each device in the HID class, looking for the right one. */ for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; HIDD_ATTRIBUTES attrib; res = SetupDiEnumDeviceInterfaces(device_info_set,NULL,&InterfaceClassGuid,device_index, &device_interface_data); if (!res) { /* A return of FALSE from this function means that there are no more devices. */ break; } /* Call with 0-sized detail size, and let the function tell us how long the detail struct needs to be. The size is put in &required_size. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, NULL, 0, &required_size, NULL); /* Allocate a long enough structure for device_interface_detail_data. */ device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); /* Get the detailed data for this device. The detail data gives us the device path for this device, which is then passed into CreateFile() to get a handle to the device. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, device_interface_detail_data, required_size, NULL, NULL); if (!res) { /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); Continue to the next device. */ goto cont; } /* Make sure this device is of Setup Class "HIDClass" and has a driver bound to it. */ for (i = 0; ; i++) { char driver_name[256]; /* Populate devinfo_data. This function will return failure when there are no more interfaces left. */ res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); if (!res) goto cont; res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (!res) goto cont; if (strcmp(driver_name, "HIDClass") == 0) { /* See if there's a driver bound. */ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (res) break; } } //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); /* Open a handle to the device */ write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); /* Check validity of write_handle. */ if (write_handle == INVALID_HANDLE_VALUE) { /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; } /* Get the Vendor ID and Product ID for this device. */ attrib.Size = sizeof(HIDD_ATTRIBUTES); HidD_GetAttributes(write_handle, &attrib); //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); /* Check the VID/PID to see if we should add this device to the enumeration list. */ if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && (product_id == 0x0 || attrib.ProductID == product_id)) { #define WSTR_LEN 512 const char *str; struct hid_device_info *tmp; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; BOOLEAN res; NTSTATUS nt_res; wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ size_t len; /* VID/PID match. Create the record. */ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Get the Usage Page and Usage for this device. */ res = HidD_GetPreparsedData(write_handle, &pp_data); if (res) { nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { cur_dev->usage_page = caps.UsagePage; cur_dev->usage = caps.Usage; } HidD_FreePreparsedData(pp_data); } /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; if (str) { len = strlen(str); cur_dev->path = (char*) calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '

      struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) { BOOL res; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; /* Windows objects for interacting with the driver. */ GUID InterfaceClassGuid = { 0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 }; //GUID InterfaceClassGuid = {0xCA3E7AB9, 0xB4C3, 0x4AE6, 0x82, 0x51, 0x57, 0x9E, 0xF9, 0x33, 0x89, 0x0F}; //GUID InterfaceClassGuid = {0x36fc9e60, 0xc465, 0x11cf, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 }; //GUID InterfaceClassGuid = { 0x4d36e96cL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 }; SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; int device_index = 0; int i; if (hid_init() < 0) return NULL; /* Initialize the Windows objects. */ memset(&devinfo_data, 0x0, sizeof(devinfo_data)); devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); /* Iterate over each device in the HID class, looking for the right one. */ for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; HIDD_ATTRIBUTES attrib; res = SetupDiEnumDeviceInterfaces(device_info_set,NULL,&InterfaceClassGuid,device_index, &device_interface_data); if (!res) { /* A return of FALSE from this function means that there are no more devices. */ break; } /* Call with 0-sized detail size, and let the function tell us how long the detail struct needs to be. The size is put in &required_size. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, NULL, 0, &required_size, NULL); /* Allocate a long enough structure for device_interface_detail_data. */ device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); /* Get the detailed data for this device. The detail data gives us the device path for this device, which is then passed into CreateFile() to get a handle to the device. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, device_interface_detail_data, required_size, NULL, NULL); if (!res) { /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); Continue to the next device. */ goto cont; } /* Make sure this device is of Setup Class "HIDClass" and has a driver bound to it. */ for (i = 0; ; i++) { char driver_name[256]; /* Populate devinfo_data. This function will return failure when there are no more interfaces left. */ res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); if (!res) goto cont; res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (!res) goto cont; if (strcmp(driver_name, "HIDClass") == 0) { /* See if there's a driver bound. */ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (res) break; } } //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); /* Open a handle to the device */ write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); /* Check validity of write_handle. */ if (write_handle == INVALID_HANDLE_VALUE) { /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; } /* Get the Vendor ID and Product ID for this device. */ attrib.Size = sizeof(HIDD_ATTRIBUTES); HidD_GetAttributes(write_handle, &attrib); //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); /* Check the VID/PID to see if we should add this device to the enumeration list. */ if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && (product_id == 0x0 || attrib.ProductID == product_id)) { #define WSTR_LEN 512 const char *str; struct hid_device_info *tmp; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; BOOLEAN res; NTSTATUS nt_res; wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ size_t len; /* VID/PID match. Create the record. */ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Get the Usage Page and Usage for this device. */ res = HidD_GetPreparsedData(write_handle, &pp_data); if (res) { nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { cur_dev->usage_page = caps.UsagePage; cur_dev->usage = caps.Usage; } HidD_FreePreparsedData(pp_data); } /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; if (str) { len = strlen(str); cur_dev->path = (char*) calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else cur_dev->path = NULL; /* Serial Number */ res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->serial_number = _wcsdup(wstr); } /* Manufacturer String */ res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->manufacturer_string = _wcsdup(wstr); } /* Product String */ res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->product_string = _wcsdup(wstr); } /* VID/PID */ cur_dev->vendor_id = attrib.VendorID; cur_dev->product_id = attrib.ProductID; /* Release Number */ cur_dev->release_number = attrib.VersionNumber; /* Interface Number. It can sometimes be parsed out of the path on Windows if a device has multiple interfaces. See http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or search for "Hardware IDs for HID Devices" at MSDN. If it's not in the path, it's set to -1. */ cur_dev->interface_number = -1; if (cur_dev->path) { char *interface_component = strstr(cur_dev->path, "&mi_"); if (interface_component) { char *hex_str = interface_component + 4; char *endptr = NULL; cur_dev->interface_number = strtol(hex_str, &endptr, 16); if (endptr == hex_str) { /* The parsing failed. Set interface_number to -1. */ cur_dev->interface_number = -1; } } } } cont_close: CloseHandle(write_handle); cont: /* We no longer need the detail data. It can be freed */ free(device_interface_detail_data); device_index++; } /* Close the device information handle. */ SetupDiDestroyDeviceInfoList(device_info_set); return root; }

      '; } else cur_dev->path = NULL; /* Serial Number */ res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->serial_number = _wcsdup(wstr); } /* Manufacturer String */ res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->manufacturer_string = _wcsdup(wstr); } /* Product String */ res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->product_string = _wcsdup(wstr); } /* VID/PID */ cur_dev->vendor_id = attrib.VendorID; cur_dev->product_id = attrib.ProductID; /* Release Number */ cur_dev->release_number = attrib.VersionNumber; /* Interface Number. It can sometimes be parsed out of the path on Windows if a device has multiple interfaces. See http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or search for "Hardware IDs for HID Devices" at MSDN. If it's not in the path, it's set to -1. */ cur_dev->interface_number = -1; if (cur_dev->path) { char *interface_component = strstr(cur_dev->path, "&mi_"); if (interface_component) { char *hex_str = interface_component + 4; char *endptr = NULL; cur_dev->interface_number = strtol(hex_str, &endptr, 16); if (endptr == hex_str) { /* The parsing failed. Set interface_number to -1. */ cur_dev->interface_number = -1; } } } } cont_close: CloseHandle(write_handle); cont: /* We no longer need the detail data. It can be freed */ free(device_interface_detail_data); device_index++; } /* Close the device information handle. */ SetupDiDestroyDeviceInfoList(device_info_set); return root; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      108

      109

      110

      111

      112

      113

      114

      115

      116

      117

      118

      119

      120

      121

      122

      123

      124

      125

      126

      127

      128

      129

      130

      131

      132

      133

      134

      135

      136

      137

      138

      139

      140

      Windows設備信息獲取:(攝像頭,聲卡為例)Qt,WindowsAPI對比說明(1)

      141

      142

      143

      144

      145

      146

      147

      148

      149

      150

      151

      152

      153

      154

      155

      156

      157

      158

      159

      160

      161

      162

      163

      164

      165

      166

      167

      168

      169

      170

      171

      172

      173

      174

      175

      176

      177

      178

      179

      180

      181

      182

      183

      184

      185

      186

      187

      188

      189

      190

      191

      192

      193

      194

      195

      196

      197

      198

      199

      200

      201

      202

      203

      204

      205

      206

      207

      208

      209

      210

      211

      212

      213

      214

      215

      216

      217

      218

      219

      220

      221

      222

      223

      224

      225

      hid_enumerate(unsigned short vendor_id, unsigned short product_id),函數思路主要為:根據GUID,獲取設備信息句柄,遍歷符合此信息句柄的所有設備,如果沒有匹配設備,則退出,查詢設備信息。

      GUID:GUID InterfaceClassGuid = { 0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };

      1

      自己測試,這個設備GUID,只能得到鼠標和鍵盤的設備信息。

      根據GUID獲取句柄信息

      device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

      1

      下邊三個函數時獲取設備接口信息,設備接口詳細信息

      res = SetupDiEnumDeviceInterfaces(device_info_set,NULL,&InterfaceClassGuid,device_index,&device_interface_data); res = SetupDiGetDeviceInterfaceDetailA(device_info_set,&device_interface_data,NULL,0, &required_size,NULL); res = SetupDiGetDeviceInterfaceDetailA(device_info_set,&device_interface_data, device_interface_detail_data, required_size, NULL, NULL);

      1

      2

      3

      獲取設備驅動類型{SPDRP_CLASS}:注意參數變化

      res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);

      1

      2

      后邊是根據設備信息,獲取HID,VID,然后根據相關信息獲取設備詳細信息,得到所需要的參數。

      后來我用了另一個方法,沒有找到需要的設備。

      獲取指定USB設備的VID PID和SerialNumber

      struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate_all(char * DeviceClassName) { BOOL res; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; /* Windows objects for interacting with the driver. */ GUID InterfaceClassGuid = {0}; SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; DWORD nSize = 0 ; if (hid_init() < 0) return NULL; /* Initialize the Windows objects. */ memset(&devinfo_data, 0x0, sizeof(devinfo_data)); devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES); /* Iterate over each device in the HID class, looking for the right one. */ TCHAR szDIS[MAX_PATH]; // Device Identification Strings, for (int i = 0; SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); i++) { nSize = 0; if (!SetupDiGetDeviceInstanceId(device_info_set, &devinfo_data, szDIS, sizeof(szDIS), &nSize)) { break; } // 設備識別串的前三個字符是否是"USB", 模板: USB\VID_XXXX&PID_XXXX\00000xxxxxxx char _cClassName[MAX_PATH] = { 0 }; wchar_t _cDeviceName[MAX_PATH] = { 0 }; char ClassName[MAX_PATH] = { 0 }; int _res = SetupDiGetDeviceRegistryProperty(device_info_set, &devinfo_data, SPDRP_CLASS, NULL, _cClassName, MAX_PATH, NULL); sprintf(ClassName, "%ls", _cClassName); if (strcmp(ClassName, DeviceClassName) == 0) { int res = SetupDiGetDeviceRegistryProperty(device_info_set, &devinfo_data, SPDRP_FRIENDLYNAME, NULL, _cDeviceName, sizeof(_cDeviceName), NULL); struct hid_device_info *tmp = NULL; tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; tmp->product_string = _wcsdup( _cDeviceName); //VID-PID if (strcmp(ClassName, "Camera") == 0) { tmp->vendor_id = (szDIS[8] - 0x30) * 16 * 16 * 16 + (szDIS[9] - 0x30) * 16 * 16 + (szDIS[10] - 0x30) * 16 + (szDIS[11] - 0x30); tmp->product_id = (szDIS[17] - 0x30) * 16 * 16 * 16 + (szDIS[18] - 0x30) * 16 * 16 + (szDIS[19] - 0x30) * 16 + (szDIS[20] - 0x30); } // wprintf(L"%ls\n", tmp->product_string); } } free(device_interface_detail_data); SetupDiDestroyDeviceInfoList(device_info_set); return root; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      獲取本機所有設備信息;

      device_info_set = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES);

      1

      拿到設備信息,設備數量,遍歷

      SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data)

      1

      得到設備實例路徑

      SetupDiGetDeviceInstanceId(device_info_set, &devinfo_data, szDIS, sizeof(szDIS), &nSize)

      1

      樣例如下:

      USB\VID_04F2&PID_B627&MI_00\6&385EEBCF&0&0000

      1

      拿到設備類名:SPDRP_CLASS

      SetupDiGetDeviceRegistryProperty(device_info_set, &devinfo_data, SPDRP_CLASS, NULL, _cClassName, MAX_PATH, NULL);

      1

      與需求設備類名做對比,相同則獲取設備名稱:

      if (strcmp(ClassName, DeviceClassName) == 0)

      1

      獲取設備名稱:SPDRP_FRIENDLYNAME,注意輸出寬字節問題。

      SetupDiGetDeviceRegistryProperty(device_info_set, &devinfo_data, SPDRP_FRIENDLYNAME, NULL, _cDeviceName, sizeof(_cDeviceName), NULL);

      1

      按照標準樣例,獲取HID,PID,為16進制,做了一個轉換處理

      tmp->vendor_id = (szDIS[8] - 0x30) * 16 * 16 * 16 + (szDIS[9] - 0x30) * 16 * 16 + (szDIS[10] - 0x30) * 16 + (szDIS[11] - 0x30); tmp->product_id = (szDIS[17] - 0x30) * 16 * 16 * 16 + (szDIS[18] - 0x30) * 16 * 16 + (szDIS[19] - 0x30) * 16 + (szDIS[20] - 0x30);

      1

      2

      setupAPI一些相關說明

      SetupDiGetDeviceRegistryProperty(device_info_set, &devinfo_data, SPDRP_FRIENDLYNAME, NULL, _cDeviceName, sizeof(_cDeviceName), NULL);

      1

      這些參數信息為:設備管理器,里邊詳細信息,做對照看一下即可。

      #define SPDRP_DEVICEDESC (0x00000000) #define SPDRP_HARDWAREID (0x00000001) #define SPDRP_COMPATIBLEIDS (0x00000002) #define SPDRP_UNUSED0 (0x00000003) #define SPDRP_SERVICE (0x00000004) #define SPDRP_UNUSED1 (0x00000005) #define SPDRP_UNUSED2 (0x00000006) #define SPDRP_CLASS (0x00000007) #define SPDRP_CLASSGUID (0x00000008) #define SPDRP_DRIVER (0x00000009) #define SPDRP_CONFIGFLAGS (0x0000000A) #define SPDRP_MFG (0x0000000B) #define SPDRP_FRIENDLYNAME (0x0000000C) #define SPDRP_LOCATION_INFORMATION (0x0000000D) #define SPDRP_PHYSICAL_DEVICE_OBJECT_NAME (0x0000000E) #define SPDRP_CAPABILITIES (0x0000000F) #define SPDRP_UI_NUMBER (0x00000010) #define SPDRP_UPPERFILTERS (0x00000011) #define SPDRP_LOWERFILTERS (0x00000012) #define SPDRP_BUSTYPEGUID (0x00000013) #define SPDRP_LEGACYBUSTYPE (0x00000014) #define SPDRP_BUSNUMBER (0x00000015) #define SPDRP_ENUMERATOR_NAME (0x00000016) #define SPDRP_SECURITY (0x00000017) #define SPDRP_SECURITY_SDS (0x00000018) #define SPDRP_DEVTYPE (0x00000019) #define SPDRP_EXCLUSIVE (0x0000001A) #define SPDRP_CHARACTERISTICS (0x0000001B) #define SPDRP_ADDRESS (0x0000001C) #define SPDRP_UI_NUMBER_DESC_FORMAT (0X0000001D) #define SPDRP_DEVICE_POWER_DATA (0x0000001E) #define SPDRP_REMOVAL_POLICY (0x0000001F) #define SPDRP_REMOVAL_POLICY_HW_DEFAULT (0x00000020) #define SPDRP_REMOVAL_POLICY_OVERRIDE (0x00000021) #define SPDRP_INSTALL_STATE (0x00000022) #define SPDRP_LOCATION_PATHS (0x00000023) #define SPDRP_MAXIMUM_PROPERTY (0x00000024) #define SPCRP_SECURITY (0x00000017) #define SPCRP_SECURITY_SDS (0x00000018) #define SPCRP_DEVTYPE (0x00000019) #define SPCRP_EXCLUSIVE (0x0000001A) #define SPCRP_CHARACTERISTICS (0x0000001B) #define SPCRP_MAXIMUM_PROPERTY (0x0000001C)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      樣例;

      //設備描述類名 根據類名查找對應設備 #define Camera "Camera" #define Media "MEDIA" #define Audio "AudioEndpoint"

      1

      2

      3

      4

      簡單調用,放入QStringList

      QStringList FileConsole::GetAudioDeviceNames() { QStringList strDeviceNames; struct hid_device_info *devs, *cur_dev; if (hid_init()) return{}; devs = hid_enumerate_all(Audio); cur_dev = devs; while (cur_dev) { QString name = QString::fromWCharArray(cur_dev->product_string); // qDebug() << " Product: " << name; strDeviceNames.push_back(name); cur_dev = cur_dev->next; } hid_free_enumeration(devs); return strDeviceNames; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      Qt自帶設備信息獲取。

      因為Qt自帶獲取,忘記把源碼上傳了,直接拿幫助文檔來說明。

      Qt下邊有兩個類:

      QAudioDeviceInfo Class //音頻設備信息類 QCameraInfo Class //攝像頭信息類

      1

      2

      攝像頭信息類獲取本地所有設備:

      這是幫助文檔里邊的一句話:關鍵:兩個函數,一個獲取默認攝像設備信息,一個是所有設備信息

      The static functions defaultCamera() and availableCameras() provide you a list of all available cameras.

      1

      遍歷打印所有驅動名稱,即可以根據這些信息做相關處理。

      QList cameras = QCameraInfo::availableCameras(); foreach (const QCameraInfo &cameraInfo, cameras) qDebug() << cameraInfo.deviceName();

      1

      2

      3

      音頻設備信息獲取:

      幫助文檔的一句話:注意幾個關鍵詞:默認輸入設備,默認輸出設備,所有設備信息。還有 QAudio::Mode.

      The static functions defaultInputDevice(), defaultOutputDevice(), and availableDevices() let you get a list of all available devices. Devices are fetched according to the value of mode this is specified by the QAudio::Mode enum. The QAudioDeviceInfo returned are only valid for the QAudio::Mode.

      1

      availableDevices(QAudio::Mode) ;

      1

      Mode的枚舉參數如下

      如上,遍歷打印所有設備的名稱。注意參數:這是QAudio::AudioOutput 所有輸出音頻輸出設備,即還要

      foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) qDebug() << "Device name: " << deviceInfo.deviceName();

      1

      2

      foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioIntput)) qDebug() << "Device name: " << deviceInfo.deviceName();

      1

      2

      其他問題

      我把編好的exe放到其他電腦上的時候,發現并沒有獲取他本地的一些設備信息,不管是Qt寫的還是調用windowsAPI,都沒有得到,所有系統兼容問題還得隨后測試,調試。

      如果有結果,隨后發布。

      源碼

      這次就不放源碼了,已經說明的很詳細了,如果有需要,留言就可以。

      其他說明,見下文:Windows設備信息獲取:(攝像頭,聲卡為例)Qt,WindowsAPI對比說明(2)

      API Qt Windows

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:【Java】【基礎類】詳解String類
      下一篇:【匯編實戰開發筆記】從匯編代碼中找出一段普通的for循環變成“死循環”的根本原因
      相關文章
      一本天堂ⅴ无码亚洲道久久| 亚洲乱色伦图片区小说 | 国产aⅴ无码专区亚洲av| 不卡精品国产_亚洲人成在线| 国产亚洲精品欧洲在线观看| 精品无码专区亚洲| 无码天堂va亚洲va在线va| 大胆亚洲人体视频| 亚洲国产精品成人AV无码久久综合影院| 久久精品亚洲AV久久久无码| 亚洲中文字幕AV在天堂| 亚洲真人无码永久在线观看| 亚洲精品国产首次亮相| 亚洲AV第一成肉网| 亚洲国产精品国产自在在线| 亚洲精品乱码久久久久久蜜桃| 亚洲色一色噜一噜噜噜| 久久精品国产亚洲7777| 亚洲女久久久噜噜噜熟女| 亚洲不卡中文字幕无码| 日韩精品亚洲人成在线观看| 亚洲精品永久www忘忧草| 亚洲乱人伦精品图片| 国产精品亚洲精品青青青| 亚洲精品无码专区| 亚洲国产中文字幕在线观看| 国产国拍精品亚洲AV片| 亚洲av一综合av一区| 在线观看亚洲一区二区| 精品亚洲AV无码一区二区| 亚洲精品无码久久久久牙蜜区| 国产综合成人亚洲区| 中文亚洲成a人片在线观看| 久久亚洲伊人中字综合精品| 亚洲视频免费观看| 国产精品亚洲综合久久| 深夜国产福利99亚洲视频| 狠狠亚洲婷婷综合色香五月排名 | 亚洲国产乱码最新视频| 亚洲丁香婷婷综合久久| 亚洲无线一二三四区手机|