85 static std::string getDevicePath(HDEVINFO hDevInfo, SP_DEVINFO_DATA* DeviceInfoData)
87 char deviceInstanceID[MAX_DEVICE_ID_LEN];
88 SetupDiGetDeviceInstanceIdA(hDevInfo, DeviceInfoData, deviceInstanceID, MAX_DEVICE_ID_LEN, NULL);
89 return std::string(deviceInstanceID);
94 static inline std::string
searchOne(std::string
const& devpath, std::string
const& regex)
97 std::regex_search(devpath, sm, std::regex(regex));
104 static inline uint16_t vidFromDevPath(std::string
const& devpath)
108 auto t1 =
searchOne(devpath,
"VID_([0-9a-fA-F]{4}).*PID_.*");
111 return static_cast<uint16_t
>(std::stoi(t1,
nullptr, 16));
113 catch (std::invalid_argument&)
120 static inline uint16_t pidFromDevPath(std::string
const& devpath)
124 auto t1 =
searchOne(devpath,
"VID_.*PID_([0-9a-fA-F]{4})");
127 return static_cast<uint16_t
>(std::stoi(t1,
nullptr, 16));
129 catch (std::invalid_argument&)
149 BOOL bResult = FALSE;
151 ULONG requiredLength = 0;
154 GUID guid = { 0xfd51225c, 0x700a, 0x47e5, { 0x99, 0x99, 0xb2, 0xd9, 0x3, 0x1b, 0x88, 0xed } };
157 SP_DEVICE_INTERFACE_DATA interfaceData;
158 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detailData = NULL;
160 deviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
163 interfaceData.cbSize =
sizeof(SP_INTERFACE_DEVICE_DATA);
164 for (DWORD dwIndex = 0;
true; ++dwIndex)
166 BOOL bRet = SetupDiEnumDeviceInterfaces(deviceInfo, NULL, &guid, dwIndex, &interfaceData);
169 if (GetLastError() == ERROR_NO_MORE_ITEMS)
174 if (!SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength, NULL))
176 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
178 SetupDiDestroyDeviceInfoList(deviceInfo);
182 detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)LocalAlloc(LMEM_FIXED, requiredLength);
183 if (NULL == detailData)
185 SetupDiDestroyDeviceInfoList(deviceInfo);
189 detailData->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
191 SP_DEVINFO_DATA DevInfoData;
192 DevInfoData.cbSize =
sizeof(SP_DEVINFO_DATA);
193 bResult = SetupDiGetDeviceInterfaceDetailA(deviceInfo, &interfaceData, detailData,
length, &requiredLength, &DevInfoData);
197 LocalFree(detailData);
198 SetupDiDestroyDeviceInfoList(deviceInfo);
202 unsigned char serialNumber[256];
203 char* ptrEnd, *ptrStart = strchr(detailData->DevicePath,
'#');
206 ptrStart = strchr(ptrStart + 1,
'#');
209 ptrEnd = strchr(ptrStart + 1,
'#');
213 size_t ln = (size_t)((ptrEnd - ptrStart) - 1);
214 strncpy((
char*)serialNumber, ptrStart + 1, ln);
215 serialNumber[ln] =
'\0';
217 current.setPortName(detailData->DevicePath);
220 sscanf((
const char*)serialNumber,
"%X", &
id);
223 std::string devpath = getDevicePath(deviceInfo, &DevInfoData);
224 uint16_t vid = vidFromDevPath(devpath);
225 uint16_t pid = pidFromDevPath(devpath);
226 current.setVidPid(vid, pid);
228 ports.push_back(current);
232 SetupDiDestroyDeviceInfoList(deviceInfo);
234 #elif defined(HAVE_LIBUSB)
236 libusb_context* context;
237 int result = libUsb.init(&context);
238 if (result != LIBUSB_SUCCESS)
241 libusb_device** deviceList;
242 ssize_t deviceCount = libUsb.get_device_list(context, &deviceList);
243 for (ssize_t i = 0; i < deviceCount; i++)
245 libusb_device* device = deviceList[i];
246 libusb_device_descriptor desc;
247 result = libUsb.get_device_descriptor(device, &desc);
248 if (result != LIBUSB_SUCCESS)
254 libusb_device_handle* handle;
255 result = libUsb.open(device, &handle);
256 if (result != LIBUSB_SUCCESS)
259 unsigned char serialNumber[256];
260 result = libUsb.get_string_descriptor_ascii(handle, desc.iSerialNumber, serialNumber, 256);
262 libusb_config_descriptor* configDesc;
263 result = libUsb.get_active_config_descriptor(device, &configDesc);
264 if (result != LIBUSB_SUCCESS)
266 libUsb.close(handle);
270 bool kernelActive =
false;
271 for (uint8_t ifCount = 0; ifCount < configDesc->bNumInterfaces; ++ifCount)
273 int res = libUsb.kernel_driver_active(handle, ifCount);
274 kernelActive |= (res == 1);
277 libUsb.free_config_descriptor(configDesc);
282 sprintf(name,
"USB%03u:%03u", libUsb.get_bus_number(device),
283 libUsb.get_device_address(device));
284 current.setPortName(name);
287 sscanf((
const char*)serialNumber,
"%X", &
id);
289 current.setVidPid(desc.idVendor, desc.idProduct);
290 ports.push_back(current);
294 JLDEBUGG(
"Kernel driver active on USB" <<
295 libUsb.get_bus_number(device) <<
":" << libUsb.get_device_address(device) <<
296 " device " << serialNumber);
299 libUsb.close(handle);
301 libUsb.free_device_list(deviceList, 1);
302 libUsb.exit(context);