146 auto serial = Communicator::createUniquePtr<SerialPortCommunicator>();
147 auto usb = Communicator::createUniquePtr<UsbCommunicator>();
152 LOGXSSCAN(
"Opening port " << portInfo.portName() <<
" (" << portInfo.portNumber() <<
") @ " << portInfo.baudrate() <<
" baud, expected device " << portInfo.deviceId());
175 XsTime::msleep(2000);
202 LOGXSSCAN(
"Setting flow control options for Awinda device to " <<
JLHEXLOG(portLinesOptions));
203 portInfo.setLinesOptions(portLinesOptions);
226 LOGXSSCAN(
"Scanning port " << portInfo.portName() <<
" at baudrate " << baud <<
" with timeout " << singleScanTimeout <<
" detectRs485 " << detectRs485);
237 portInfo.setBaudrate(baudrate);
238 res = fetchBasicInfo(portInfo, singleScanTimeout, detectRs485);
241 LOGXSSCAN(
"Scan successfully found device " << portInfo.deviceId() <<
" on port " << portInfo.portName());
242 portInfo.setBaudrate(baudrate);
252 LOGXSSCAN(
"Failed to fetch basic info within timeout");
290 LOGXSSCAN(
"No more available baudrates, failed to find device");
293 LOGXSSCAN(
"Checking next baudrate: " << baudrate);
295 LOGXSSCAN(
"Port scan aborted by external trigger");
319 if (!xsEnumerateSerialPorts(ports, ignoreNonXsensDevices))
325 return xsFilterResponsiveDevices(ports, baudrate, singleScanTimeout, detectRs485);
345 if (ports[p].isNetwork() || xsScanPort(ports[p], baudrate, singleScanTimeout, detectRs485))
349 LOGXSSCAN(
"Port : " << ports[p].portName() <<
" is not responsive, discarding");
350 ports.erase(ports.begin() + p);
361 std::sort(ports.begin(), ports.end());
371 std::string Scanner::getDevicePath(HDEVINFO hDevInfo, SP_DEVINFO_DATA* DeviceInfoData)
373 char deviceInstanceID[MAX_DEVICE_ID_LEN];
374 SetupDiGetDeviceInstanceIdA(hDevInfo, DeviceInfoData, deviceInstanceID, MAX_DEVICE_ID_LEN, NULL);
375 return std::string(deviceInstanceID);
390 return (pid != 0x0100);
394 return (pid >= 0xd388 && pid <= 0xd38f);
413 SP_DEVINFO_DATA DeviceInfoData;
417 hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, 0, DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
419 if (hDevInfo == INVALID_HANDLE_VALUE)
421 LOGXSSCAN(
"Failed to get any USB device information, check permissions");
426 DeviceInfoData.cbSize =
sizeof(SP_DEVINFO_DATA);
427 for (i = 0; !
abortPortScan && SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); ++i)
430 HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevInfo, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
431 if (hDeviceKey == INVALID_HANDLE_VALUE)
437 char pszPortName[256];
440 if ((RegQueryValueExA(hDeviceKey,
"PortName", NULL, &dwType, (LPBYTE) pszPortName, &dwSize) != ERROR_SUCCESS) || (dwType != REG_SZ))
445 if (_strnicmp(pszPortName,
"COM", 3))
447 int32_t nPort = atoi(&pszPortName[3]);
451 std::string devpath = getDevicePath(hDevInfo, &DeviceInfoData);
455 LOGXSSCAN(
"Found USB device " << devpath);
456 if (ignoreNonXsensDevices)
458 if (!isXsensUsbDevice(vid, pid))
460 LOGXSSCAN(
"Ignoring non-Xsens device " << devpath);
465 current.setPortName(pszPortName);
468 current.setVidPid(vid, pid);
469 ports.push_back(current);
476 SetupDiDestroyDeviceInfoList(hDevInfo);
479 std::sort(ports.begin(), ports.end());
483 struct udev* udev = xsudev.unew();
486 struct udev_enumerate* enumerate = xsudev.enumerate_new(udev);
488 xsudev.enumerate_add_match_subsystem(enumerate,
"tty");
489 xsudev.enumerate_scan_devices(enumerate);
491 struct udev_list_entry* devices, *dev_list_entry;
492 devices = xsudev.enumerate_get_list_entry(enumerate);
493 for (dev_list_entry = devices; dev_list_entry !=
nullptr; dev_list_entry = xsudev.list_entry_get_next(dev_list_entry))
495 const char* path = xsudev.list_entry_get_name(dev_list_entry);
496 auto devcleaner = [&](
struct udev_device *
d)
498 xsudev.device_unref(
d);
500 std::unique_ptr<
struct udev_device, decltype(devcleaner)>
501 device(xsudev.device_new_from_syspath(udev, path), devcleaner);
505 if (!xsudev.device_get_parent(device.get()))
509 struct udev_device* usbParentDevice = xsudev.device_get_parent_with_subsystem_devtype(device.get(),
"usb",
"usb_device");
510 unsigned int vid = 0, pid = 0;
513 const char* vendor = xsudev.device_get_sysattr_value(usbParentDevice,
"idVendor");
514 const char* product = xsudev.device_get_sysattr_value(usbParentDevice,
"idProduct");
516 if (vendor && product)
518 sscanf(vendor,
"%x", &vid);
519 sscanf(product,
"%x", &pid);
525 if (ignoreNonXsensDevices)
527 if (!isXsensUsbDevice(vid, pid))
529 LOGXSSCAN(
"Ignoring non-Xsens device " << path);
536 const char* devnode = xsudev.device_get_devnode(device.get());
537 if (strlen(devnode) > 255 || strncmp(devnode,
"/dev/ttyS", 9) == 0)
539 portInfo.setPortName(devnode);
540 portInfo.setVidPid(vid, pid);
544 const char* deviceidstring;
545 deviceidstring = xsudev.device_get_sysattr_value(usbParentDevice,
"serial");
549 sscanf(deviceidstring,
"%08X", &deviceId);
550 portInfo.setDeviceId(deviceId);
554 ports.push_back(portInfo);
556 xsudev.enumerate_unref(enumerate);
561 (void)ignoreNonXsensDevices;
563 struct dirent* entry;
565 if ((dir = opendir(
"/dev/")) == NULL)
568 while ((entry = readdir(dir)))
570 if (strncmp(
"ttyUSB", entry->d_name, 6) == 0)
573 sprintf(name,
"/dev/%s", entry->d_name);
574 current.setPortName(name);
575 ports.push_back(current);
609 #define ILLEGAL_HUB (0)
611 #define HUB_SEARCH_STRING ("Hub_#")
618 int Scanner::xsScanGetHubNumber(HDEVINFO hDevInfo, SP_DEVINFO_DATA* deviceInfoData)
624 if (SetupDiGetDeviceRegistryPropertyA(hDevInfo,
626 SPDRP_LOCATION_INFORMATION,
632 LOGXSSCAN(
"Registry access successful: \"" << buffer <<
"\"");
633 char const* hubString = strstr((
char const*)buffer, HUB_SEARCH_STRING);
635 result = strtol(hubString + strlen(HUB_SEARCH_STRING), 0, 10);
638 LOGXSSCAN(
"Get Hub Number failed with error " << GetLastError());
647 XsPortInfo Scanner::xsScanPortByHubId(
const char*
id)
649 assert(
id !=
nullptr);
653 LOGXSSCAN(
"xsScanPortByHubId with id " <<
id);
656 HDEVINFO hDevInfo = SetupDiGetClassDevs(
657 &GUID_DEVCLASS_PORTS,
660 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
663 if (hDevInfo == INVALID_HANDLE_VALUE)
665 LOGXSSCAN(
"Failed to get any USB device information, check permissions");
672 SP_DEVICE_INTERFACE_DATA devInterfaceData;
673 ZeroMemory(&devInterfaceData,
sizeof(SP_DEVICE_INTERFACE_DATA));
674 devInterfaceData.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
677 for (DWORD dwIndex = 0; port == 0; ++dwIndex)
679 BOOL bRet = SetupDiEnumDeviceInterfaces(
682 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
688 if (GetLastError() == ERROR_NO_MORE_ITEMS)
693 size_t buffer[1024 /
sizeof(size_t)];
695 SP_DEVINFO_DATA diData;
696 diData.cbSize =
sizeof(SP_DEVINFO_DATA);
697 SP_DEVICE_INTERFACE_DETAIL_DATA_A& ifdData = *(SP_DEVICE_INTERFACE_DETAIL_DATA_A*) buffer;
698 ifdData.cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
700 if (SetupDiGetDeviceInterfaceDetailA(hDevInfo, &devInterfaceData, &ifdData, 1020, &reqSize, &diData))
704 char* end = strrchr(ifdData.DevicePath,
'#');
707 end = strrchr(ifdData.DevicePath,
'#');
710 char*
start = strrchr(ifdData.DevicePath,
'+');
716 if (_strnicmp(
id, start, strlen(
id)) == 0)
720 HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevInfo, &diData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
721 if (hDeviceKey != INVALID_HANDLE_VALUE)
724 char pszPortName[256] =
"";
727 if ((RegQueryValueExA(hDeviceKey,
"PortName", NULL, &dwType, (LPBYTE) pszPortName, &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ))
731 if (!_strnicmp(pszPortName,
"COM", 3))
732 port = atoi(&pszPortName[3]);
733 portInfo.setPortName(pszPortName);
734 std::string devpath = getDevicePath(hDevInfo, &diData);
738 portInfo.setVidPid(vid, pid);
742 RegCloseKey(hDeviceKey);
748 SetupDiDestroyDeviceInfoList(hDevInfo);
767 HDEVINFO hDevInfo = SetupDiGetClassDevs(
768 &GUID_DEVINTERFACE_USB_DEVICE,
771 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
774 if (hDevInfo == INVALID_HANDLE_VALUE)
776 LOGXSSCAN(
"Failed to get any USB device information, check permissions");
783 SP_DEVICE_INTERFACE_DATA devInterfaceData;
784 ZeroMemory(&devInterfaceData,
sizeof(SP_DEVICE_INTERFACE_DATA));
785 devInterfaceData.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
786 for (DWORD dwIndex = 0; ; ++dwIndex)
788 BOOL bRet = SetupDiEnumDeviceInterfaces(
791 &GUID_DEVINTERFACE_USB_DEVICE,
797 if (GetLastError() == ERROR_NO_MORE_ITEMS)
802 size_t tmp1[1024 /
sizeof(size_t)];
803 size_t tmp2[1024 /
sizeof(size_t)];
804 char* buffer = (
char*) tmp1;
805 SP_DEVINFO_DATA diData;
806 diData.cbSize =
sizeof(SP_DEVINFO_DATA);
808 SP_DEVICE_INTERFACE_DETAIL_DATA_A& ifdData = *(SP_DEVICE_INTERFACE_DETAIL_DATA_A*) tmp2;
809 ifdData.cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
813 while (SetupDiGetDeviceInterfaceDetailA(hDevInfo, &devInterfaceData, &ifdData, 1020, &reqSize, &diData))
816 if (SetupDiGetDeviceRegistryPropertyA(hDevInfo, &diData, SPDRP_MFG, &dataT, (PBYTE)buffer, 256, NULL))
818 if (_strnicmp(buffer,
"xsens", 5))
824 hubNr = xsScanGetHubNumber(hDevInfo, &diData);
828 char* hubEnd = strrchr(ifdData.DevicePath,
'#');
829 if (!hubEnd || hubEnd == ifdData.DevicePath)
832 char* hubStart = strrchr(ifdData.DevicePath,
'#');
833 if (!hubStart || hubStart == ifdData.DevicePath)
836 port = xsScanPortByHubId(hubStart);
840 if (port.portName().size())
842 LOGXSSCAN(
"xsScanXsensUsbHubs Adding hub " << hubNr <<
" and port " << port.portName());
843 hubs.push_back(hubNr);
844 ports.push_back(port);
848 SetupDiDestroyDeviceInfoList(hDevInfo);
885 if (!xsScanXsensUsbHubs(hubs, ports))
889 for (
size_t i = 0; i < ports.size(); ++i)
890 if (_stricmp(ports[i].portName_c_str(), portInfo.portName_c_str()) == 0)
894 SP_DEVINFO_DATA devInfoData;
897 hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, 0, DIGCF_PRESENT | DIGCF_PROFILE);
899 if (hDevInfo == INVALID_HANDLE_VALUE)
903 devInfoData.cbSize =
sizeof(SP_DEVINFO_DATA);
904 for (DWORD i = 0; behindXsensHub ==
ILLEGAL_HUB && SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData); ++i)
915 if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo,
925 HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
926 if (hDeviceKey != INVALID_HANDLE_VALUE)
929 char pszPortName[256];
932 if ((RegQueryValueExA(hDeviceKey,
"PortName", NULL, &dwType, (LPBYTE) pszPortName, &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ))
939 if (_strnicmp(pszPortName,
"COM", 3))
942 if (_stricmp(pszPortName, portInfo.portName_c_str()) == 0)
946 int hub = xsScanGetHubNumber(hDevInfo, &devInfoData);
947 JLDEBUGG(
"Got hub " << hub <<
" for port " << std::string(pszPortName));
951 for (XsIntArray::const_iterator hi = hubs.begin(); hi != hubs.end(); ++hi)
955 behindXsensHub = hub;
965 RegCloseKey(hDeviceKey);
970 SetupDiDestroyDeviceInfoList(hDevInfo);
977 udev* udevInstance = xsudev.unew();
978 if (udevInstance == NULL)
980 fprintf(stderr,
"Unable to create udev object\n");
984 udev_enumerate* enumerate = xsudev.enumerate_new(udevInstance);
985 xsudev.enumerate_scan_devices(enumerate);
987 udev_list_entry* devices = xsudev.enumerate_get_list_entry(enumerate);
988 udev_list_entry* dev;
989 for (dev = devices; dev != NULL; dev = xsudev.list_entry_get_next(dev))
991 const char* path = xsudev.list_entry_get_name(dev);
992 udev_device* device = xsudev.device_new_from_syspath(udevInstance, path);
996 const char* devnode = xsudev.device_get_devnode(device);
997 if (!devnode || strcmp(devnode, portInfo.portName_c_str()) != 0)
1000 udev_device* parent = xsudev.device_get_parent_with_subsystem_devtype(device,
"usb",
"usb_device");
1004 const char* devpath = xsudev.device_get_sysattr_value(parent,
"devpath");
1011 xsudev.enumerate_unref(enumerate);
1012 xsudev.unref(udevInstance);