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 =
libUSB_attach_kernel_driver attach_kernel_driver
Operation was performed successfully.
#define xsStartThread(func, param, pid)
Start a function as a thread.
XSTYPES_DLL_API int XsPortInfo_usbAddress(XsPortInfo const *thisPtr)
#define XS_MAX_FILENAME_LENGTH
uint8_t usbAddress() const
The address of the device (libusb/linux only)
unsigned __int16 uint16_t
UsbInterface()
Default constructor, initializes all members to their default values.
libUSB_unref_device unref_device
uint32_t getTimeout(void) const
Return the current timeout value.
bool isOpen(void) const
Return whether the USB communication port is open or not.
int void fclose(FILE *f)
An OS-independent version of fclose.
struct XsByteArray XsByteArray
libUSB_free_config_descriptor free_config_descriptor
UsbContext()
Create the USB context.
const char * libusbErrorToString(int libusbError)
Convert a libusb error to a human-readable string.
size_t XsSize
XsSize must be unsigned number!
GLsizei GLsizei GLuint * obj
XsResultValue libusbErrorToXrv(int libusbError, XsResultValue hint=XRV_ERROR)
Map a libusb_error to XsResultValue.
libUSB_free_device_list free_device_list
void setRawIo(bool enable)
Sets the RAWIO mode of the USB interface.
XsResultValue m_lastResult
The last result of an operation.
libusb_device_handle * m_deviceHandle
XsResultValue
Xsens result values.
void msleep(uint32_t ms)
A platform-independent sleep routine.
uint32_t m_endTime
The time at which an operation will end in ms, used by several functions.
libUSB_get_device_list get_device_list
Class for dynamic loading of winusb.
bool getRawIo(void)
Retrieves the state of the RAWIO mode of the USB interface.
libusb_context * m_usbContext
libUSB_claim_interface claim_interface
uint8_t usbBus() const
The USB bus number this device is on (libusb/linux only)
libUSB_get_device_descriptor get_device_descriptor
A context manager for libusb.
XsResultValue setTimeout(uint32_t ms)
Set the default timeout value to use in blocking operations.
XsResultValue closeUsb(void)
Close the USB communication port.
libUSB_get_device get_device
virtual XsResultValue writeData(const XsByteArray &data, XsSize *written=nullptr)
Write the data to the USB port.
HANDLE XsThread
A handle for a thread.
#define xsGetCurrentThreadHandle()
libUSB_kernel_driver_active kernel_driver_active
~UsbInterface()
Destructor, de-initializes, frees memory allocated for buffers, etc.
Private object for UsbInterface.
XsResultValue waitForData(XsSize maxLength, void *data, XsSize *length=nullptr)
Wait for data to arrive or a timeout to occur.
XsResultValue getLastResult(void) const
Return the error code of the last operation.
libUSB_detach_kernel_driver detach_kernel_driver
#define xsSetThreadPriority(thrd, prio)
void getPortName(XsString &portname) const
Retrieve the port name that was last successfully opened.
static UsbContext & getContextManager()
GLuint GLsizei GLsizei * length
XSTYPES_DLL_API int64_t XsTime_timeStampNow(XsTimeStamp *now)
#define XSENS_INVALID_THREAD
XsResultValue flushData(void)
Flush all data in the buffers to and from the device.
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
libUSB_get_device_address get_device_address
XsResultValue close(void)
Close the USB communication port.
virtual XsResultValue readData(XsSize maxLength, XsByteArray &data)
Read data from the USB port and put it into the data buffer.
unsigned __int32 uint32_t
libUSB_release_interface release_interface
libUSB_get_bus_number get_bus_number
GLsizei GLsizei GLenum GLenum const GLvoid * data
uint32_t getTimeOfDay(tm *date_, time_t *secs_)
A platform-independent clock.
libUSB_get_active_config_descriptor get_active_config_descriptor
XsResultValue open(const XsPortInfo &portInfo, uint32_t readBufSize=0, uint32_t writeBufSize=0)
Open a communication channel to the given USB port name.
XSTYPES_DLL_API void xsNameThisThread(const char *threadName)
XSTYPES_DLL_API int XsPortInfo_usbBus(XsPortInfo const *thisPtr)
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...
libUSB_bulk_transfer bulk_transfer
~UsbContext()
Destroy the USB context.
libUSB_ref_device ref_device
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".