27 #ifndef _CRT_SECURE_NO_DEPRECATE
28 #define _CRT_SECURE_NO_DEPRECATE
30 #pragma warning(disable : 4996)
61 WINUSB_INTERFACE_HANDLE m_usbHandle[2];
62 uint8_t m_bulkInPipe, m_bulkOutPipe, m_interruptPipe, m_deviceSpeed;
68 static const int m_oCount = MAXIMUM_WAIT_OBJECTS - 1;
69 OVERLAPPED m_overlapped[m_oCount];
71 static const int m_fixedBufferSize = 8192;
72 static const int m_fastPolicyThreshold = 3;
73 uint8_t m_fixedBuffer[m_oCount][m_fixedBufferSize];
75 CRITICAL_SECTION m_mutex;
77 volatile bool m_running;
78 HANDLE m_waitEvents[m_oCount];
130 case LIBUSB_ERROR_IO:
133 case LIBUSB_ERROR_INVALID_PARAM:
136 case LIBUSB_ERROR_ACCESS:
139 case LIBUSB_ERROR_NO_DEVICE:
142 case LIBUSB_ERROR_NOT_FOUND:
145 case LIBUSB_ERROR_BUSY:
148 case LIBUSB_ERROR_TIMEOUT:
151 case LIBUSB_ERROR_OVERFLOW:
154 case LIBUSB_ERROR_PIPE:
157 case LIBUSB_ERROR_INTERRUPTED:
160 case LIBUSB_ERROR_NO_MEM:
163 case LIBUSB_ERROR_NOT_SUPPORTED:
166 case LIBUSB_ERROR_OTHER:
178 return "LIBUSB_SUCCESS";
180 case LIBUSB_ERROR_IO:
181 return "LIBUSB_ERROR_IO";
183 case LIBUSB_ERROR_INVALID_PARAM:
184 return "LIBUSB_ERROR_INVALID_PARAM";
186 case LIBUSB_ERROR_ACCESS:
187 return "LIBUSB_ERROR_ACCESS";
189 case LIBUSB_ERROR_NO_DEVICE:
190 return "LIBUSB_ERROR_NO_DEVICE";
192 case LIBUSB_ERROR_NOT_FOUND:
193 return "LIBUSB_ERROR_NOT_FOUND";
195 case LIBUSB_ERROR_BUSY:
196 return "LIBUSB_ERROR_BUSY";
198 case LIBUSB_ERROR_TIMEOUT:
199 return "LIBUSB_ERROR_TIMEOUT";
201 case LIBUSB_ERROR_OVERFLOW:
202 return "LIBUSB_ERROR_OVERFLOW";
204 case LIBUSB_ERROR_PIPE:
205 return "LIBUSB_ERROR_PIPE";
207 case LIBUSB_ERROR_INTERRUPTED:
208 return "LIBUSB_ERROR_INTERRUPTED";
210 case LIBUSB_ERROR_NO_MEM:
211 return "LIBUSB_ERROR_NO_MEM";
213 case LIBUSB_ERROR_NOT_SUPPORTED:
214 return "LIBUSB_ERROR_NOT_SUPPORTED";
216 case LIBUSB_ERROR_OTHER:
217 return "LIBUSB_ERROR_OTHER";
225 DWORD usbReadThreadFunc(
void*
obj)
235 d->m_running =
false;
240 d->m_running =
false;
246 void UsbInterfacePrivate::threadFunc()
248 HANDLE handles[1 + m_oCount];
249 handles[0] = m_quitEvent;
250 handles[m_oCount] = m_waitEvents[m_oCount - 1];
254 for (m_readIdx = 0; m_readIdx < (m_oCount - 1); ++m_readIdx)
256 handles[m_readIdx + 1] = m_waitEvents[m_readIdx];
258 m_overlapped[m_readIdx] = OVERLAPPED();
259 ::ResetEvent(m_waitEvents[m_readIdx]);
260 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx];
262 m_usbHandle[1], m_bulkInPipe, m_fixedBuffer[m_readIdx],
263 (ULONG)m_fixedBufferSize, 0,
264 &m_overlapped[m_readIdx]);
268 bool policyFast =
false;
273 m_overlapped[m_readIdx] = OVERLAPPED();
274 ::ResetEvent(m_waitEvents[m_readIdx]);
275 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx];
277 m_usbHandle[1], m_bulkInPipe, m_fixedBuffer[m_readIdx],
278 (ULONG)m_fixedBufferSize, 0,
279 &m_overlapped[m_readIdx]);
280 m_readIdx = (m_readIdx + 1) % m_oCount;
283 ::WaitForMultipleObjects(1 + m_oCount, handles,
FALSE, INFINITE);
284 #if 0 // not sure if this causes problems, but it should help in catching up
286 switch (tEnd - tBegin)
289 if (++fastCount > m_fastPolicyThreshold && !policyFast)
294 m_winUsb.SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
301 if (policyFast && fastCount <= m_fastPolicyThreshold)
305 UCHAR enable =
FALSE;
306 m_winUsb.SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
316 UCHAR enable =
FALSE;
317 m_winUsb.SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
333 if (waitResult >= WAIT_ABANDONED_0)
337 "WFMO abandoned: " << (waitResult - WAIT_OBJECT_0));
341 #ifndef XSENS_RELEASE
343 gJournal,
"WFMO trigger: " << (waitResult - WAIT_OBJECT_0));
349 if (!m_winUsb.GetOverlappedResult(
350 m_usbHandle[0], &m_overlapped[idx], &dataRead,
354 DWORD err = ::GetLastError();
357 case ERROR_SEM_TIMEOUT:
358 case ERROR_IO_INCOMPLETE:
367 "m_winUsb.GetOverlappedResult resulted in "
380 "m_winUsb.GetOverlappedResult resulted in "
381 << dataRead <<
" bytes being read");
383 &m_fixedBuffer[idx][0], dataRead,
XSDF_None);
384 ::EnterCriticalSection(&m_mutex);
385 m_varBuffer.append(
ref);
386 ::LeaveCriticalSection(&m_mutex);
420 d->m_threadHandle = INVALID_HANDLE_VALUE;
421 ::InitializeCriticalSection(&
d->m_mutex);
422 d->m_usbHandle[0] = 0;
423 d->m_usbHandle[1] = 0;
424 for (
int i = 0; i <
d->m_oCount; ++i)
426 d->m_waitEvents[i] = ::CreateEvent(
nullptr,
TRUE,
FALSE,
nullptr);
427 ::ResetEvent(
d->m_waitEvents[i]);
429 d->m_quitEvent = ::CreateEvent(
nullptr,
TRUE,
FALSE,
nullptr);
430 ::ResetEvent(
d->m_quitEvent);
443 ::CloseHandle(
d->m_quitEvent);
444 for (
int i = 0; i <
d->m_oCount; ++i)
445 ::CloseHandle(
d->m_waitEvents[i]);
446 ::DeleteCriticalSection(&
d->m_mutex);
468 if (
d->rx_log !=
nullptr)
fclose(
d->rx_log);
469 if (
d->tx_log !=
nullptr)
fclose(
d->tx_log);
477 if (
d->m_threadHandle != INVALID_HANDLE_VALUE)
481 ::SetEvent(
d->m_quitEvent);
484 ::CloseHandle(
d->m_threadHandle);
488 if (
d->m_usbHandle[0])
490 d->m_winUsb.Free(
d->m_usbHandle[0]);
491 d->m_usbHandle[0] =
nullptr;
493 if (
d->m_usbHandle[1])
495 d->m_winUsb.Free(
d->m_usbHandle[1]);
496 d->m_usbHandle[1] =
nullptr;
510 int result = LIBUSB_ERROR_OTHER;
511 while (result != LIBUSB_SUCCESS)
515 if (result == LIBUSB_SUCCESS)
543 if (
d->m_usbHandle[0])
545 d->m_winUsb.AbortPipe(
d->m_usbHandle[0],
d->m_bulkInPipe);
546 d->m_winUsb.FlushPipe(
d->m_usbHandle[0],
d->m_bulkInPipe);
547 d->m_winUsb.AbortPipe(
d->m_usbHandle[0],
d->m_bulkOutPipe);
548 d->m_winUsb.FlushPipe(
d->m_usbHandle[0],
d->m_bulkOutPipe);
550 if (
d->m_usbHandle[1])
552 d->m_winUsb.AbortPipe(
d->m_usbHandle[1],
d->m_bulkInPipe);
553 d->m_winUsb.FlushPipe(
d->m_usbHandle[1],
d->m_bulkInPipe);
554 d->m_winUsb.AbortPipe(
d->m_usbHandle[1],
d->m_bulkOutPipe);
555 d->m_winUsb.FlushPipe(
d->m_usbHandle[1],
d->m_bulkOutPipe);
558 unsigned char flushBuffer[256];
560 for (
int i = 0; i < 64; ++i)
564 flushBuffer,
sizeof(flushBuffer), &actual, 1) != LIBUSB_SUCCESS)
566 if (actual == 0)
break;
589 JLDEBUG(gJournal,
"Open usb port " << portInfo.portName().toStdString());
592 gJournal,
"Open usb port " << portInfo.usbBus() <<
":"
593 << portInfo.usbAddress());
599 gJournal,
"Port " << portInfo.portName().toStdString()
606 portInfo.portName().c_str(), GENERIC_WRITE | GENERIC_READ,
607 FILE_SHARE_WRITE | FILE_SHARE_READ,
nullptr, OPEN_EXISTING,
608 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
nullptr);
619 USB_INTERFACE_DESCRIPTOR interfaceDescriptor = {0, 0, 0, 0, 0, 0, 0, 0, 0};
620 WINUSB_PIPE_INFORMATION pipeInfo;
625 result =
d->m_winUsb.GetAssociatedInterface(
626 d->m_usbHandle[0], 0, &
d->m_usbHandle[1]);
631 DWORD err = GetLastError();
637 for (
int k = 0; k < 2; k++)
641 assert(
d->m_usbHandle[k] != 0);
643 result =
d->m_winUsb.QueryDeviceInformation(
644 d->m_usbHandle[k], DEVICE_SPEED, &
length, &speed);
649 d->m_deviceSpeed = speed;
650 result =
d->m_winUsb.QueryInterfaceSettings(
651 d->m_usbHandle[k], 0, &interfaceDescriptor);
655 for (
int i = 0; i < interfaceDescriptor.bNumEndpoints; i++)
657 result =
d->m_winUsb.QueryPipe(
658 d->m_usbHandle[k], 0, (UCHAR)i, &pipeInfo);
660 if (pipeInfo.PipeType == UsbdPipeTypeBulk &&
661 USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId))
663 d->m_bulkInPipe = pipeInfo.PipeId;
664 d->m_bulkInPipePacketSize = pipeInfo.MaximumPacketSize;
667 pipeInfo.PipeType == UsbdPipeTypeBulk &&
668 USB_ENDPOINT_DIRECTION_OUT(pipeInfo.PipeId))
670 d->m_bulkOutPipe = pipeInfo.PipeId;
672 else if (pipeInfo.PipeType == UsbdPipeTypeInterrupt)
674 d->m_interruptPipe = pipeInfo.PipeId;
691 ::ResetEvent(&
d->m_quitEvent);
702 libusb_device** deviceList;
715 libusb_device* device =
nullptr;
716 for (
int i = 0; i < listLength && device ==
nullptr; ++i)
718 libusb_device* dev = deviceList[i];
725 libusb_device_descriptor desc;
728 if (result != LIBUSB_SUCCESS)
break;
730 libusb_config_descriptor* configDesc;
733 if (result != LIBUSB_SUCCESS)
break;
739 ifCount < configDesc->bNumInterfaces &&
d->
m_interface == -1;
742 for (
uint8_t altsettingCount = 0;
744 configDesc->interface[ifCount].num_altsetting;
747 const libusb_endpoint_descriptor* endpoints =
748 configDesc->interface[ifCount]
749 .altsetting[altsettingCount]
751 int inEndpoint = -1, outEndpoint = -1;
752 for (
uint8_t i = 0; i < configDesc->interface[ifCount]
753 .altsetting[altsettingCount]
757 if ((endpoints[i].bmAttributes &
758 LIBUSB_TRANSFER_TYPE_MASK) !=
759 LIBUSB_TRANSFER_TYPE_BULK)
762 switch (endpoints[i].bEndpointAddress &
763 LIBUSB_ENDPOINT_DIR_MASK)
765 case LIBUSB_ENDPOINT_IN:
766 inEndpoint = endpoints[i].bEndpointAddress &
767 LIBUSB_ENDPOINT_ADDRESS_MASK;
770 case LIBUSB_ENDPOINT_OUT:
771 outEndpoint = endpoints[i].bEndpointAddress &
772 LIBUSB_ENDPOINT_ADDRESS_MASK;
777 if (outEndpoint == -1 || inEndpoint == -1)
continue;
794 result = LIBUSB_SUCCESS;
799 if (result != LIBUSB_SUCCESS)
811 libusb_device_handle* handle;
814 if (result != LIBUSB_SUCCESS)
828 if (result == LIBUSB_SUCCESS)
831 if (result != LIBUSB_SUCCESS)
833 for (
int j = 0; j < i; j++)
835 while (result != LIBUSB_SUCCESS)
856 #endif // !USE_WINUSB
857 JLDEBUG(gJournal,
"USB Port opened");
896 <<
", length=0x" <<
length);
904 ::EnterCriticalSection(&
d->m_mutex);
905 remaining = *
length =
d->m_varBuffer.size();
910 d->m_varBuffer.erase(0, *
length);
911 remaining =
d->m_varBuffer.size();
913 ::LeaveCriticalSection(&
d->m_mutex);
915 gJournal,
"returned success, read "
917 <<
" bytes, first: " << JLHEXLOG(((
char*)
data)[0]) <<
", "
918 << remaining <<
" remaining in buffer");
927 << actual <<
" bytes received");
928 if ((
res != LIBUSB_SUCCESS &&
res != LIBUSB_ERROR_TIMEOUT) ||
929 (
res == LIBUSB_ERROR_TIMEOUT && actual <= 0))
938 if (
d->rx_log ==
nullptr)
942 d->rx_log =
fopen(fname,
"wb");
945 #ifdef LOG_RX_TX_FLUSH
965 gJournal,
"Request to set timeout to "
966 << ms <<
" ms overridden, setting to 0 ms instead");
968 UCHAR enable =
FALSE;
970 d->m_winUsb.SetPipePolicy(
971 d->m_usbHandle[1],
d->m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR),
973 d->m_winUsb.SetPipePolicy(
974 d->m_usbHandle[1],
d->m_bulkInPipe, PIPE_TRANSFER_TIMEOUT,
979 JLDEBUG(gJournal,
"Setting timeout to " << ms);
994 JLDEBUG(gJournal,
"Setting RAWIO mode to " << enable);
998 UCHAR rawIo = (UCHAR)enable;
999 d->m_winUsb.SetPipePolicy(
1000 d->m_usbHandle[1],
d->m_bulkInPipe, RAW_IO,
sizeof(UCHAR),
1016 ULONG someSize =
sizeof(UCHAR);
1017 d->m_winUsb.GetPipePolicy(
1018 d->m_usbHandle[1],
d->m_bulkInPipe, RAW_IO, &someSize,
1020 return (rawIo != 0);
1047 <<
", length=" <<
length);
1050 char* bdata = (
char*)
data;
1100 if (written ==
nullptr) written = &bytes;
1108 d->m_winUsb.WritePipe(
1113 *written = dataWritten;
1116 while (*written <
length)
1124 if (result != LIBUSB_SUCCESS)
1129 << actual <<
" bytes sent");
1139 if (
d->tx_log ==
nullptr)
1143 d->tx_log =
fopen(fname,
"wb");
1145 fwrite(
data, 1, *written,
d->tx_log);
1146 #ifdef LOG_RX_TX_FLUSH
1163 libusb_device* dev =
1179 libusb_device* dev =