MRPT  1.9.9
enumerateusbdevices.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #include "enumerateusbdevices.h"
10 #include "xcommunicationconfig.h"
11 
12 #ifdef _WIN32
13 #include <windows.h>
14 
15 #include <devguid.h>
16 #include <regstr.h>
17 #include <setupapi.h>
18 #include <string.h>
19 #else
20 #include <dirent.h>
21 #include <cstdlib>
22 #include <cstring>
23 #include "xslibusb.h"
24 #endif
25 
26 #define XSENS_VENDOR_ID 0x2639
27 #define ATMEL_VENDOR_ID 0x03eb // needed for old MTw
28 #define ATMEL_BORROWED_PRODUCT_ID 0x2307 // needed for old MTw
29 
30 /*! \brief Enumerate Xsens USB devices
31 
32  If the OS already has drivers running for a device, the device should
33  already have been
34  found by xsEnumerateSerialPorts().
35 
36  \param[in,out] ports The list of serial ports to append to
37 */
39 {
40  XsPortInfo current;
41 #ifdef USE_WINUSB
42  BOOL bResult = FALSE;
43  ULONG length;
44  ULONG requiredLength = 0;
45 
46  // {FD51225C-700A-47e5-9999-B2D9031B88ED}
47  GUID guid = {0xfd51225c,
48  0x700a,
49  0x47e5,
50  {0x99, 0x99, 0xb2, 0xd9, 0x3, 0x1b, 0x88, 0xed}};
51 
52  HDEVINFO deviceInfo;
53  SP_DEVICE_INTERFACE_DATA interfaceData;
54  PSP_DEVICE_INTERFACE_DETAIL_DATA_A detailData = nullptr;
55 
56  deviceInfo = SetupDiGetClassDevs(
57  &guid, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
58 
59  // Initialize variables.
60  interfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
61  int port = 0;
62  for (DWORD dwIndex = 0; port == 0; ++dwIndex)
63  {
64  BOOL bRet = SetupDiEnumDeviceInterfaces(
65  deviceInfo, nullptr, &guid, dwIndex, &interfaceData);
66  if (!bRet)
67  {
68  if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
69  }
70  else
71  {
72  if (!SetupDiGetDeviceInterfaceDetail(
73  deviceInfo, &interfaceData, nullptr, 0, &requiredLength,
74  nullptr))
75  {
76  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
77  {
78  SetupDiDestroyDeviceInfoList(deviceInfo);
79  return false;
80  }
81  }
82  detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)LocalAlloc(
83  LMEM_FIXED, requiredLength);
84  if (nullptr == detailData)
85  {
86  SetupDiDestroyDeviceInfoList(deviceInfo);
87  return false;
88  }
89 
90  detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
91  length = requiredLength;
92  SP_DEVINFO_DATA DevInfoData;
93  DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
94  bResult = SetupDiGetDeviceInterfaceDetailA(
95  deviceInfo, &interfaceData, detailData, length, &requiredLength,
96  &DevInfoData);
97 
98  if (!bResult)
99  {
100  LocalFree(detailData);
101  SetupDiDestroyDeviceInfoList(deviceInfo);
102  return false;
103  }
104 
105  unsigned char serialNumber[256];
106  char *ptrEnd, *ptrStart = strchr(detailData->DevicePath, '#');
107  if (!ptrStart) continue;
108  ptrStart = strchr(ptrStart + 1, '#');
109  if (!ptrStart) continue;
110  ptrEnd = strchr(ptrStart + 1, '#');
111  if (!ptrEnd) continue;
112 
113  strncpy((char*)serialNumber, ptrStart + 1, ptrEnd - ptrStart - 1);
114  serialNumber[ptrEnd - ptrStart - 1] = '\0';
115 
116  current.setPortName(detailData->DevicePath);
117 
118  int id = 0;
119  sscanf((const char*)serialNumber, "%X", &id);
120  current.setDeviceId((uint32_t)id);
121 
122  ports.push_back(current);
123  }
124  }
125 
126  SetupDiDestroyDeviceInfoList(deviceInfo);
127  return true;
128 #else
129  XsLibUsb libUsb;
130  libusb_context* context;
131  int result = libUsb.init(&context);
132  if (result != LIBUSB_SUCCESS) return false;
133 
134  libusb_device** deviceList;
135  ssize_t deviceCount = libUsb.get_device_list(context, &deviceList);
136  for (ssize_t i = 0; i < deviceCount; i++)
137  {
138  libusb_device* device = deviceList[i];
139  libusb_device_descriptor desc;
140  result = libUsb.get_device_descriptor(device, &desc);
141  if (result != LIBUSB_SUCCESS) continue;
142 
143  if (desc.idVendor != XSENS_VENDOR_ID &&
144  desc.idVendor != ATMEL_VENDOR_ID)
145  continue;
146 
147  libusb_device_handle* handle;
148  result = libUsb.open(device, &handle);
149  if (result != LIBUSB_SUCCESS)
150  {
151  libUsb.unref_device(device);
152  continue;
153  }
154 
155  unsigned char serialNumber[256];
156  result = libUsb.get_string_descriptor_ascii(
157  handle, desc.iSerialNumber, serialNumber, 256);
158 
159  if (desc.idVendor == ATMEL_VENDOR_ID &&
160  desc.idProduct == ATMEL_BORROWED_PRODUCT_ID)
161  {
162  unsigned char productName[256];
163  result = libUsb.get_string_descriptor_ascii(
164  handle, desc.iProduct, productName, 256);
165 
166  if (strcmp("Xsens COM port", (const char*)productName) != 0)
167  {
168  libUsb.close(handle);
169  continue;
170  }
171  }
172 
173  libusb_config_descriptor* configDesc;
174  result = libUsb.get_active_config_descriptor(device, &configDesc);
175  if (result != LIBUSB_SUCCESS) continue;
176 
177  bool kernelActive = false;
178  for (uint8_t ifCount = 0; ifCount < configDesc->bNumInterfaces;
179  ++ifCount)
180  {
181  int res = libUsb.kernel_driver_active(handle, ifCount);
182  kernelActive |= (res == 1);
183  }
184 
185  libUsb.free_config_descriptor(configDesc);
186 
187  if (!kernelActive)
188  {
189  char name[256];
190  sprintf(
191  name, "USB%03u:%03u", libUsb.get_bus_number(device),
192  libUsb.get_device_address(device));
193  current.setPortName(name);
194 
195  int id = 0;
196  sscanf((const char*)serialNumber, "%d", &id);
197  current.setDeviceId((uint32_t)id);
198  ports.push_back(current);
199  }
200  else
201  {
202  JLDEBUG(
203  gJournal, "Kernel driver active on USB"
204  << libUsb.get_bus_number(device) << ":"
205  << libUsb.get_device_address(device) << " device "
206  << serialNumber);
207  }
208  libUsb.close(handle);
209  }
210  libUsb.free_device_list(deviceList, 1);
211  libUsb.exit(context);
212  return true;
213 #endif
214 }
#define XSENS_VENDOR_ID
libUSB_close close
Definition: xslibusb.h:61
libUSB_unref_device unref_device
Definition: xslibusb.h:66
libUSB_open open
Definition: xslibusb.h:60
libUSB_init init
Definition: xslibusb.h:58
libUSB_free_config_descriptor free_config_descriptor
Definition: xslibusb.h:70
#define ATMEL_BORROWED_PRODUCT_ID
int BOOL
Definition: xstypedefs.h:77
libUSB_get_string_descriptor_ascii get_string_descriptor_ascii
Definition: xslibusb.h:77
unsigned char uint8_t
Definition: rptypes.h:44
libUSB_free_device_list free_device_list
Definition: xslibusb.h:76
bool xsEnumerateUsbDevices(XsPortInfoList &ports)
Enumerate Xsens USB devices.
libUSB_get_device_list get_device_list
Definition: xslibusb.h:75
libUSB_get_device_descriptor get_device_descriptor
Definition: xslibusb.h:74
libUSB_kernel_driver_active kernel_driver_active
Definition: xslibusb.h:62
libUSB_exit exit
Definition: xslibusb.h:59
#define JLDEBUG(...)
#define FALSE
Definition: xmlParser.h:230
GLuint GLsizei GLsizei * length
Definition: glext.h:4079
GLuint const GLchar * name
Definition: glext.h:4068
libUSB_get_device_address get_device_address
Definition: xslibusb.h:73
GLuint res
Definition: glext.h:7385
unsigned __int32 uint32_t
Definition: rptypes.h:50
libUSB_get_bus_number get_bus_number
Definition: xslibusb.h:71
libUSB_get_active_config_descriptor get_active_config_descriptor
Definition: xslibusb.h:69
#define XsPortInfoList
int sprintf(char *buf, size_t bufSize, const char *format,...) noexcept MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
Definition: os.cpp:191
#define ATMEL_VENDOR_ID



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019