82 #ifndef _CRT_SECURE_NO_DEPRECATE
83 #define _CRT_SECURE_NO_DEPRECATE
85 #pragma warning(disable:4996)
113 WINUSB_INTERFACE_HANDLE m_usbHandle[2];
114 uint8_t m_bulkInPipe, m_bulkOutPipe, m_interruptPipe, m_deviceSpeed;
115 uint16_t m_bulkInPipePacketSize;
120 static const int m_oCount = MAXIMUM_WAIT_OBJECTS - 1;
121 OVERLAPPED m_overlapped[m_oCount];
123 static const int m_fixedBufferSize = 8192;
124 uint8_t m_fixedBuffer[m_oCount][m_fixedBufferSize];
126 CRITICAL_SECTION m_mutex;
128 volatile std::atomic_bool m_running;
129 HANDLE m_waitEvents[m_oCount];
135 #elif defined(HAVE_LIBUSB)
136 int m_interfaceCount;
151 if (!m_claimedContexts)
152 m_libUsb.init(&m_usbContext);
161 if (!m_claimedContexts)
162 m_libUsb.exit(m_usbContext);
164 static libusb_context* m_usbContext;
167 static int m_claimedContexts;
169 UsbContext m_contextManager;
183 case LIBUSB_ERROR_IO:
186 case LIBUSB_ERROR_INVALID_PARAM:
189 case LIBUSB_ERROR_ACCESS:
192 case LIBUSB_ERROR_NO_DEVICE:
195 case LIBUSB_ERROR_NOT_FOUND:
198 case LIBUSB_ERROR_BUSY:
201 case LIBUSB_ERROR_TIMEOUT:
204 case LIBUSB_ERROR_OVERFLOW:
207 case LIBUSB_ERROR_PIPE:
210 case LIBUSB_ERROR_INTERRUPTED:
213 case LIBUSB_ERROR_NO_MEM:
216 case LIBUSB_ERROR_NOT_SUPPORTED:
219 case LIBUSB_ERROR_OTHER:
226 const char* libusbErrorToString(
int libusbError)
231 return "LIBUSB_SUCCESS";
233 case LIBUSB_ERROR_IO:
234 return "LIBUSB_ERROR_IO";
236 case LIBUSB_ERROR_INVALID_PARAM:
237 return "LIBUSB_ERROR_INVALID_PARAM";
239 case LIBUSB_ERROR_ACCESS:
240 return "LIBUSB_ERROR_ACCESS";
242 case LIBUSB_ERROR_NO_DEVICE:
243 return "LIBUSB_ERROR_NO_DEVICE";
245 case LIBUSB_ERROR_NOT_FOUND:
246 return "LIBUSB_ERROR_NOT_FOUND";
248 case LIBUSB_ERROR_BUSY:
249 return "LIBUSB_ERROR_BUSY";
251 case LIBUSB_ERROR_TIMEOUT:
252 return "LIBUSB_ERROR_TIMEOUT";
254 case LIBUSB_ERROR_OVERFLOW:
255 return "LIBUSB_ERROR_OVERFLOW";
257 case LIBUSB_ERROR_PIPE:
258 return "LIBUSB_ERROR_PIPE";
260 case LIBUSB_ERROR_INTERRUPTED:
261 return "LIBUSB_ERROR_INTERRUPTED";
263 case LIBUSB_ERROR_NO_MEM:
264 return "LIBUSB_ERROR_NO_MEM";
266 case LIBUSB_ERROR_NOT_SUPPORTED:
267 return "LIBUSB_ERROR_NOT_SUPPORTED";
269 case LIBUSB_ERROR_OTHER:
270 return "LIBUSB_ERROR_OTHER";
280 static DWORD usbReadThreadFunc(
void* obj)
296 d->m_running =
false;
300 void UsbInterfacePrivate::threadFunc()
302 HANDLE handles[1 + m_oCount];
303 handles[0] = m_quitEvent;
304 handles[m_oCount] = m_waitEvents[m_oCount - 1];
308 for (m_readIdx = 0 ; m_readIdx < (m_oCount - 1); ++m_readIdx)
310 handles[m_readIdx + 1] = m_waitEvents[m_readIdx];
311 m_overlapped[m_readIdx] = OVERLAPPED();
312 ::ResetEvent(m_waitEvents[m_readIdx]);
313 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx];
314 m_winUsb.ReadPipe(m_usbHandle[1], m_bulkInPipe, m_fixedBuffer[m_readIdx], (ULONG)m_fixedBufferSize, 0, &m_overlapped[m_readIdx]);
320 m_overlapped[m_readIdx] = OVERLAPPED();
321 ::ResetEvent(m_waitEvents[m_readIdx]);
322 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx];
323 m_winUsb.ReadPipe(m_usbHandle[1], m_bulkInPipe, m_fixedBuffer[m_readIdx], (ULONG)m_fixedBufferSize, 0, &m_overlapped[m_readIdx]);
324 m_readIdx = (m_readIdx + 1) % m_oCount;
325 DWORD waitResult = ::WaitForMultipleObjects(1 + m_oCount, handles, FALSE, INFINITE);
337 if (waitResult >= WAIT_ABANDONED_0)
339 JLDEBUGG(
"WFMO abandoned: " << (waitResult - WAIT_OBJECT_0));
343 #ifndef XSENS_RELEASE
344 JLDEBUGG(
"WFMO trigger: " << (waitResult - WAIT_OBJECT_0));
350 if (!m_winUsb.GetOverlappedResult(m_usbHandle[0], &m_overlapped[idx], &dataRead, FALSE))
353 DWORD err = ::GetLastError();
356 case ERROR_SEM_TIMEOUT:
357 case ERROR_IO_INCOMPLETE:
361 case ERROR_GEN_FAILURE:
362 JLDEBUGG(
"We seem to have lost contact with the usb device");
368 JLALERTG(
"m_winUsb.GetOverlappedResult resulted in windows error " << err);
377 JLTRACEG(
"m_winUsb.GetOverlappedResult resulted in " << dataRead <<
" bytes being read");
379 ::EnterCriticalSection(&m_mutex);
380 m_varBuffer.append(ref);
381 ::LeaveCriticalSection(&m_mutex);
389 #elif defined(HAVE_LIBUSB)
390 int UsbInterfacePrivate::UsbContext::m_claimedContexts = 0;
391 libusb_context* UsbInterfacePrivate::UsbContext::m_usbContext = NULL;
412 d->m_threadHandle = INVALID_HANDLE_VALUE;
413 ::InitializeCriticalSection(&
d->m_mutex);
414 d->m_usbHandle[0] = 0;
415 d->m_usbHandle[1] = 0;
416 for (
int i = 0; i < UsbInterfacePrivate::m_oCount; ++i)
418 d->m_waitEvents[i] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
419 ::ResetEvent(
d->m_waitEvents[i]);
421 d->m_quitEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
422 ::ResetEvent(
d->m_quitEvent);
435 ::CloseHandle(
d->m_quitEvent);
436 for (
int i = 0; i < UsbInterfacePrivate::m_oCount; ++i)
437 ::CloseHandle(
d->m_waitEvents[i]);
438 ::DeleteCriticalSection(&
d->m_mutex);
472 if (
d->m_threadHandle != INVALID_HANDLE_VALUE)
476 ::SetEvent(
d->m_quitEvent);
479 ::CloseHandle(
d->m_threadHandle);
483 if (
d->m_usbHandle[0])
485 d->m_winUsb.Free(
d->m_usbHandle[0]);
486 d->m_usbHandle[0] = NULL;
488 if (
d->m_usbHandle[1])
490 d->m_winUsb.Free(
d->m_usbHandle[1]);
491 d->m_usbHandle[1] = NULL;
498 #elif defined(HAVE_LIBUSB)
500 libusb_device* dev =
d->m_contextManager.m_libUsb.get_device(
d->
m_deviceHandle);
501 for (
int i = 0; i <
d->m_interfaceCount; i++)
503 int result = LIBUSB_ERROR_OTHER;
504 while (result != LIBUSB_SUCCESS)
506 result =
d->m_contextManager.m_libUsb.release_interface(
d->
m_deviceHandle, i);
507 if (result == LIBUSB_SUCCESS)
515 d->m_contextManager.m_libUsb.unref_device(dev);
533 if (
d->m_usbHandle[0])
535 d->m_winUsb.AbortPipe(
d->m_usbHandle[0],
d->m_bulkInPipe);
536 d->m_winUsb.FlushPipe(
d->m_usbHandle[0],
d->m_bulkInPipe);
537 d->m_winUsb.AbortPipe(
d->m_usbHandle[0],
d->m_bulkOutPipe);
538 d->m_winUsb.FlushPipe(
d->m_usbHandle[0],
d->m_bulkOutPipe);
540 if (
d->m_usbHandle[1])
542 d->m_winUsb.AbortPipe(
d->m_usbHandle[1],
d->m_bulkInPipe);
543 d->m_winUsb.FlushPipe(
d->m_usbHandle[1],
d->m_bulkInPipe);
544 d->m_winUsb.AbortPipe(
d->m_usbHandle[1],
d->m_bulkOutPipe);
545 d->m_winUsb.FlushPipe(
d->m_usbHandle[1],
d->m_bulkOutPipe);
547 #elif defined(HAVE_LIBUSB)
548 unsigned char flushBuffer[256];
550 for (
int i = 0; i < 64; ++i)
553 flushBuffer,
sizeof(flushBuffer), &actual, 1) != LIBUSB_SUCCESS)
589 JLDEBUGG(
"Open usb port " << portInfo.portName());
591 JLDEBUGG(
"Open usb port " << portInfo.usbBus() <<
":" << portInfo.usbAddress());
596 JLALERTG(
"Port " << portInfo.portName() <<
" already open");
601 d->
m_deviceHandle = CreateFileA(portInfo.portName_c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
612 USB_INTERFACE_DESCRIPTOR interfaceDescriptor = {0, 0, 0, 0, 0, 0, 0, 0, 0};
613 WINUSB_PIPE_INFORMATION pipeInfo;
617 result =
d->m_winUsb.GetAssociatedInterface(
d->m_usbHandle[0], 0, &
d->m_usbHandle[1]);
621 DWORD err = GetLastError();
627 for (
int k = 0; k < 2; k++)
631 assert(
d->m_usbHandle[k] != 0);
633 result =
d->m_winUsb.QueryDeviceInformation(
d->m_usbHandle[k], DEVICE_SPEED, &
length, &speed);
638 d->m_deviceSpeed = speed;
639 result =
d->m_winUsb.QueryInterfaceSettings(
d->m_usbHandle[k], 0, &interfaceDescriptor);
643 for (
int i = 0; i < interfaceDescriptor.bNumEndpoints; i++)
645 result =
d->m_winUsb.QueryPipe(
d->m_usbHandle[k], 0, (UCHAR) i, &pipeInfo);
647 if (pipeInfo.PipeType == UsbdPipeTypeBulk && USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId))
649 d->m_bulkInPipe = pipeInfo.PipeId;
650 d->m_bulkInPipePacketSize =
651 pipeInfo.MaximumPacketSize;
653 else if (pipeInfo.PipeType == UsbdPipeTypeBulk && USB_ENDPOINT_DIRECTION_OUT(pipeInfo.PipeId))
654 d->m_bulkOutPipe = pipeInfo.PipeId;
655 else if (pipeInfo.PipeType == UsbdPipeTypeInterrupt)
656 d->m_interruptPipe = pipeInfo.PipeId;
669 sprintf(
d->
m_portname,
"%s", portInfo.portName_c_str());
672 ::ResetEvent(&
d->m_quitEvent);
682 #elif defined(HAVE_LIBUSB)
683 libusb_device** deviceList;
684 ssize_t listLength =
d->m_contextManager.m_libUsb.get_device_list(
d->m_contextManager.m_usbContext, &deviceList);
694 libusb_device* device = NULL;
695 for (
int i = 0; i < listLength && device == NULL; ++i)
697 libusb_device* dev = deviceList[i];
698 if (
d->m_contextManager.m_libUsb.get_bus_number(dev) != bus ||
d->m_contextManager.m_libUsb.get_device_address(dev) != address)
701 libusb_device_descriptor desc;
702 result =
d->m_contextManager.m_libUsb.get_device_descriptor(dev, &desc);
703 if (result != LIBUSB_SUCCESS)
706 libusb_config_descriptor* configDesc;
707 result =
d->m_contextManager.m_libUsb.get_active_config_descriptor(dev, &configDesc);
708 if (result != LIBUSB_SUCCESS)
712 d->m_interfaceCount = configDesc->bNumInterfaces;
714 for (uint8_t ifCount = 0; ifCount < configDesc->bNumInterfaces &&
d->m_interface == -1; ++ifCount)
716 for (uint8_t altsettingCount = 0; altsettingCount < configDesc->interface[ifCount].num_altsetting; altsettingCount++)
718 const libusb_endpoint_descriptor* endpoints = configDesc->interface[ifCount].altsetting[altsettingCount].endpoint;
719 int inEndpoint = -1, outEndpoint = -1;
720 for (uint8_t i = 0; i < configDesc->interface[ifCount].altsetting[altsettingCount].bNumEndpoints; i++)
722 if ((endpoints[i].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK)
725 switch (endpoints[i].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
727 case LIBUSB_ENDPOINT_IN:
728 inEndpoint = endpoints[i].bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK;
731 case LIBUSB_ENDPOINT_OUT:
732 outEndpoint = endpoints[i].bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK;
738 if (outEndpoint == -1 || inEndpoint == -1)
741 d->m_interface = ifCount;
746 if (
d->m_interface == -1)
752 d->m_contextManager.m_libUsb.free_config_descriptor(configDesc);
753 d->m_contextManager.m_libUsb.ref_device(dev);
755 result = LIBUSB_SUCCESS;
758 d->m_contextManager.m_libUsb.free_device_list(deviceList, 1);
759 if (result != LIBUSB_SUCCESS)
761 d->m_contextManager.m_libUsb.unref_device(device);
767 d->m_contextManager.m_libUsb.unref_device(device);
771 libusb_device_handle* handle;
772 result =
d->m_contextManager.m_libUsb.open(device, &handle);
773 if (result != LIBUSB_SUCCESS)
775 d->m_contextManager.m_libUsb.unref_device(device);
780 for (
int i = 0; i <
d->m_interfaceCount; i++)
782 result =
d->m_contextManager.m_libUsb.kernel_driver_active(handle, i);
784 result =
d->m_contextManager.m_libUsb.detach_kernel_driver(handle, i);
785 if (result == LIBUSB_SUCCESS)
786 result =
d->m_contextManager.m_libUsb.claim_interface(handle, i);
787 if (result != LIBUSB_SUCCESS)
789 for (
int j = 0; j < i; j++)
791 while (result != LIBUSB_SUCCESS)
793 result =
d->m_contextManager.m_libUsb.release_interface(handle, j);
794 d->m_contextManager.m_libUsb.attach_kernel_driver(handle, j);
798 d->m_contextManager.m_libUsb.close(handle);
799 d->m_contextManager.m_libUsb.unref_device(device);
805 sprintf(
d->
m_portname,
"%s", portInfo.portName_c_str());
853 ::EnterCriticalSection(&
d->m_mutex);
861 remaining = (
XsFilePos)
d->m_varBuffer.size();
864 if (
d->m_threadedResult !=
XRV_OK)
867 ::LeaveCriticalSection(&
d->m_mutex);
868 JLTRACEG(
"returned success, read " << *
length <<
" of " << maxLength <<
" bytes, first: " <<
JLHEXLOG(((
char*)
data)[0]) <<
", " << remaining <<
" remaining in buffer");
871 #elif defined(HAVE_LIBUSB)
875 JLTRACEG(
"bulk read returned: " <<
d->libusbErrorToString(res) <<
". " << actual <<
" bytes received");
876 if ((res != LIBUSB_SUCCESS && res != LIBUSB_ERROR_TIMEOUT) || (res == LIBUSB_ERROR_TIMEOUT && actual <= 0))
890 if (!
d->rx_log.isOpen())
897 #ifdef LOG_RX_TX_FLUSH
915 JLDEBUGG(
"Request to set timeout to " << ms <<
" ms overridden, setting to 0 ms instead");
917 UCHAR enable = FALSE;
919 d->m_winUsb.SetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
920 d->m_winUsb.SetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, PIPE_TRANSFER_TIMEOUT,
sizeof(ULONG), &ms);
924 JLDEBUGG(
"Setting timeout to " << ms);
939 JLDEBUGG(
"Setting RAWIO mode to " << enable);
943 UCHAR rawIo = (UCHAR)enable;
944 d->m_winUsb.SetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, RAW_IO,
sizeof(UCHAR), &rawIo);
959 ULONG someSize =
sizeof(UCHAR);
960 d->m_winUsb.GetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, RAW_IO, &someSize, &rawIo);
983 char* bdata = (
char*)
data;
988 uint32_t eTime = XsTime::getTimeOfDay() + timeout;
992 while ((*
length < maxLength) && (XsTime::getTimeOfDay() <= eTime))
998 JLTRACEG(
"read " <<
length[0] <<
" of " << maxLength <<
" bytes");
1000 if (
length[0] < maxLength)
1031 if (written == NULL)
1041 d->m_winUsb.WritePipe(
d->m_usbHandle[1],
d->m_bulkOutPipe,
static_cast<PUCHAR
>(
const_cast<void*
>(
data)), (ULONG)
length, &dataWritten, NULL);
1043 *written = dataWritten;
1044 #elif defined(HAVE_LIBUSB)
1046 while (*written <
length)
1051 if (result != LIBUSB_SUCCESS)
1053 JLALERTG(
"bulk write failed: " <<
d->libusbErrorToString(result) <<
". " << actual <<
" bytes sent");
1065 CHECK_STATE_TX(*written,
data,
d->tx_log);
1067 if (!
d->tx_log.isOpen())
1071 d->tx_log.create(
XsString(fname),
true);
1073 d->tx_log.write(
data, 1, *written);
1074 #ifdef LOG_RX_TX_FLUSH
1086 #if defined(HAVE_LIBUSB)
1090 libusb_device* dev =
d->m_contextManager.m_libUsb.get_device(
d->
m_deviceHandle);
1091 return d->m_contextManager.m_libUsb.get_bus_number(dev);
1100 #if defined(HAVE_LIBUSB)
1104 libusb_device* dev =
d->m_contextManager.m_libUsb.get_device(
d->
m_deviceHandle);
1105 return d->m_contextManager.m_libUsb.get_device_address(dev);