C#編程-48:文本控件復習筆記_彭世瑜_新浪博客
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
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
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小時內刪除侵權內容。