15 # include "xswinusb.h" 27 #ifndef _CRT_SECURE_NO_DEPRECATE 28 # define _CRT_SECURE_NO_DEPRECATE 30 # pragma warning(disable:4996) 60 WINUSB_INTERFACE_HANDLE m_usbHandle[2];
61 uint8_t m_bulkInPipe, m_bulkOutPipe, m_interruptPipe, m_deviceSpeed;
67 static const int m_oCount = MAXIMUM_WAIT_OBJECTS-1;
68 OVERLAPPED m_overlapped[m_oCount];
70 static const int m_fixedBufferSize = 8192;
71 static const int m_fastPolicyThreshold = 3;
72 uint8_t m_fixedBuffer[m_oCount][m_fixedBufferSize];
74 CRITICAL_SECTION m_mutex;
76 volatile bool m_running;
77 HANDLE m_waitEvents[m_oCount];
123 switch (libusbError) {
127 case LIBUSB_ERROR_IO:
130 case LIBUSB_ERROR_INVALID_PARAM:
133 case LIBUSB_ERROR_ACCESS:
136 case LIBUSB_ERROR_NO_DEVICE:
139 case LIBUSB_ERROR_NOT_FOUND:
142 case LIBUSB_ERROR_BUSY:
145 case LIBUSB_ERROR_TIMEOUT:
148 case LIBUSB_ERROR_OVERFLOW:
151 case LIBUSB_ERROR_PIPE:
154 case LIBUSB_ERROR_INTERRUPTED:
157 case LIBUSB_ERROR_NO_MEM:
160 case LIBUSB_ERROR_NOT_SUPPORTED:
163 case LIBUSB_ERROR_OTHER:
172 switch (libusbError) {
174 return "LIBUSB_SUCCESS";
176 case LIBUSB_ERROR_IO:
177 return "LIBUSB_ERROR_IO";
179 case LIBUSB_ERROR_INVALID_PARAM:
180 return "LIBUSB_ERROR_INVALID_PARAM";
182 case LIBUSB_ERROR_ACCESS:
183 return "LIBUSB_ERROR_ACCESS";
185 case LIBUSB_ERROR_NO_DEVICE:
186 return "LIBUSB_ERROR_NO_DEVICE";
188 case LIBUSB_ERROR_NOT_FOUND:
189 return "LIBUSB_ERROR_NOT_FOUND";
191 case LIBUSB_ERROR_BUSY:
192 return "LIBUSB_ERROR_BUSY";
194 case LIBUSB_ERROR_TIMEOUT:
195 return "LIBUSB_ERROR_TIMEOUT";
197 case LIBUSB_ERROR_OVERFLOW:
198 return "LIBUSB_ERROR_OVERFLOW";
200 case LIBUSB_ERROR_PIPE:
201 return "LIBUSB_ERROR_PIPE";
203 case LIBUSB_ERROR_INTERRUPTED:
204 return "LIBUSB_ERROR_INTERRUPTED";
206 case LIBUSB_ERROR_NO_MEM:
207 return "LIBUSB_ERROR_NO_MEM";
209 case LIBUSB_ERROR_NOT_SUPPORTED:
210 return "LIBUSB_ERROR_NOT_SUPPORTED";
212 case LIBUSB_ERROR_OTHER:
213 return "LIBUSB_ERROR_OTHER";
221 DWORD usbReadThreadFunc(
void*
obj)
229 d->m_running =
false;
233 d->m_running =
false;
239 void UsbInterfacePrivate::threadFunc()
241 HANDLE handles[1+m_oCount];
242 handles[0] = m_quitEvent;
243 handles[m_oCount] = m_waitEvents[m_oCount-1];
247 for (m_readIdx = 0 ; m_readIdx < (m_oCount-1); ++m_readIdx)
249 handles[m_readIdx+1] = m_waitEvents[m_readIdx];
251 m_overlapped[m_readIdx] = OVERLAPPED();
252 ::ResetEvent(m_waitEvents[m_readIdx]);
253 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx];
254 m_winUsb.ReadPipe(m_usbHandle[1],
256 m_fixedBuffer[m_readIdx],
257 (ULONG)m_fixedBufferSize,
259 &m_overlapped[m_readIdx]);
263 bool policyFast =
false;
268 m_overlapped[m_readIdx] = OVERLAPPED();
269 ::ResetEvent(m_waitEvents[m_readIdx]);
270 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx];
271 m_winUsb.ReadPipe(m_usbHandle[1],
273 m_fixedBuffer[m_readIdx],
274 (ULONG)m_fixedBufferSize,
276 &m_overlapped[m_readIdx]);
277 m_readIdx = (m_readIdx + 1) % m_oCount;
279 DWORD waitResult = ::WaitForMultipleObjects(1+m_oCount, handles,
FALSE, INFINITE);
280 #if 0 // not sure if this causes problems, but it should help in catching up 282 switch (tEnd - tBegin)
285 if (++fastCount > m_fastPolicyThreshold && !policyFast)
290 m_winUsb.SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
297 if (policyFast && fastCount <= m_fastPolicyThreshold)
301 UCHAR enable =
FALSE;
302 m_winUsb.SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
312 UCHAR enable =
FALSE;
313 m_winUsb.SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
329 if (waitResult >= WAIT_ABANDONED_0)
331 JLDEBUG(gJournal,
"WFMO abandoned: " << (waitResult - WAIT_OBJECT_0));
335 #ifndef XSENS_RELEASE 336 JLDEBUG(gJournal,
"WFMO trigger: " << (waitResult - WAIT_OBJECT_0));
342 if (!m_winUsb.GetOverlappedResult(m_usbHandle[0], &m_overlapped[idx], &dataRead,
FALSE))
345 DWORD err = ::GetLastError();
348 case ERROR_SEM_TIMEOUT:
349 case ERROR_IO_INCOMPLETE:
354 JLALERT(gJournal,
"m_winUsb.GetOverlappedResult resulted in windows error " << err);
363 JLTRACE(gJournal,
"m_winUsb.GetOverlappedResult resulted in " << dataRead <<
" bytes being read");
365 ::EnterCriticalSection(&m_mutex);
366 m_varBuffer.append(
ref);
367 ::LeaveCriticalSection(&m_mutex);
400 d->m_threadHandle = INVALID_HANDLE_VALUE;
401 ::InitializeCriticalSection(&
d->m_mutex);
402 d->m_usbHandle[0] = 0;
403 d->m_usbHandle[1] = 0;
404 for (
int i = 0; i <
d->m_oCount; ++i)
406 d->m_waitEvents[i] = ::CreateEvent(NULL,
TRUE,
FALSE, NULL);
407 ::ResetEvent(
d->m_waitEvents[i]);
409 d->m_quitEvent = ::CreateEvent(NULL,
TRUE,
FALSE, NULL);
410 ::ResetEvent(
d->m_quitEvent);
422 ::CloseHandle(
d->m_quitEvent);
423 for (
int i = 0; i <
d->m_oCount; ++i)
424 ::CloseHandle(
d->m_waitEvents[i]);
425 ::DeleteCriticalSection(&
d->m_mutex);
449 if (
d->rx_log != NULL)
451 if (
d->tx_log != NULL)
461 if (
d->m_threadHandle != INVALID_HANDLE_VALUE)
465 ::SetEvent(
d->m_quitEvent);
468 ::CloseHandle(
d->m_threadHandle);
472 if(
d->m_usbHandle[0]) {
473 d->m_winUsb.Free(
d->m_usbHandle[0]);
474 d->m_usbHandle[0] = NULL;
476 if(
d->m_usbHandle[1]) {
477 d->m_winUsb.Free(
d->m_usbHandle[1]);
478 d->m_usbHandle[1] = NULL;
488 int result = LIBUSB_ERROR_OTHER;
489 while (result != LIBUSB_SUCCESS) {
491 if (result == LIBUSB_SUCCESS) {
517 if(
d->m_usbHandle[0]) {
518 d->m_winUsb.AbortPipe(
d->m_usbHandle[0],
d->m_bulkInPipe);
519 d->m_winUsb.FlushPipe(
d->m_usbHandle[0],
d->m_bulkInPipe);
520 d->m_winUsb.AbortPipe(
d->m_usbHandle[0],
d->m_bulkOutPipe);
521 d->m_winUsb.FlushPipe(
d->m_usbHandle[0],
d->m_bulkOutPipe);
523 if(
d->m_usbHandle[1]) {
524 d->m_winUsb.AbortPipe(
d->m_usbHandle[1],
d->m_bulkInPipe);
525 d->m_winUsb.FlushPipe(
d->m_usbHandle[1],
d->m_bulkInPipe);
526 d->m_winUsb.AbortPipe(
d->m_usbHandle[1],
d->m_bulkOutPipe);
527 d->m_winUsb.FlushPipe(
d->m_usbHandle[1],
d->m_bulkOutPipe);
530 unsigned char flushBuffer[256];
532 for (
int i = 0; i < 64; ++i) {
534 flushBuffer,
sizeof(flushBuffer), &actual, 1) != LIBUSB_SUCCESS)
568 JLDEBUG(gJournal,
"Open usb port " << portInfo.portName().toStdString());
570 JLDEBUG(gJournal,
"Open usb port " << portInfo.usbBus() <<
":" << portInfo.usbAddress());
575 JLALERT(gJournal,
"Port " << portInfo.portName().toStdString() <<
" already open");
581 GENERIC_WRITE | GENERIC_READ,
582 FILE_SHARE_WRITE | FILE_SHARE_READ,
585 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
597 USB_INTERFACE_DESCRIPTOR interfaceDescriptor = {0,0,0,0,0,0,0,0,0};
598 WINUSB_PIPE_INFORMATION pipeInfo;
603 result =
d->m_winUsb.GetAssociatedInterface(
d->m_usbHandle[0],0,&
d->m_usbHandle[1]);
608 DWORD err = GetLastError();
614 for (
int k = 0; k<2;k++)
618 assert(
d->m_usbHandle[k] != 0);
620 result =
d->m_winUsb.QueryDeviceInformation(
d->m_usbHandle[k],
628 d->m_deviceSpeed = speed;
629 result =
d->m_winUsb.QueryInterfaceSettings(
d->m_usbHandle[k],
631 &interfaceDescriptor);
635 for(
int i=0;i<interfaceDescriptor.bNumEndpoints;i++)
637 result =
d->m_winUsb.QueryPipe(
d->m_usbHandle[k],
642 if(pipeInfo.PipeType == UsbdPipeTypeBulk &&
643 USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId))
645 d->m_bulkInPipe = pipeInfo.PipeId;
646 d->m_bulkInPipePacketSize =
647 pipeInfo.MaximumPacketSize;
649 else if(pipeInfo.PipeType == UsbdPipeTypeBulk &&
650 USB_ENDPOINT_DIRECTION_OUT(pipeInfo.PipeId))
652 d->m_bulkOutPipe = pipeInfo.PipeId;
654 else if(pipeInfo.PipeType == UsbdPipeTypeInterrupt)
656 d->m_interruptPipe = pipeInfo.PipeId;
673 ::ResetEvent(&
d->m_quitEvent);
684 libusb_device **deviceList;
695 libusb_device *device = NULL;
696 for (
int i = 0; i < listLength && device == NULL; ++i) {
697 libusb_device *dev = deviceList[i];
701 libusb_device_descriptor desc;
703 if (result != LIBUSB_SUCCESS)
706 libusb_config_descriptor *configDesc;
708 if (result != LIBUSB_SUCCESS)
714 for (
uint8_t ifCount = 0; ifCount < configDesc->bNumInterfaces &&
d->
m_interface == -1; ++ifCount) {
715 for (
uint8_t altsettingCount = 0; altsettingCount < configDesc->interface[ifCount].num_altsetting; altsettingCount++) {
716 const libusb_endpoint_descriptor *endpoints = configDesc->interface[ifCount].altsetting[altsettingCount].endpoint;
717 int inEndpoint = -1, outEndpoint = -1;
718 for (
uint8_t i = 0; i < configDesc->interface[ifCount].altsetting[altsettingCount].bNumEndpoints; i++) {
719 if ((endpoints[i].bmAttributes&LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK)
722 switch (endpoints[i].bEndpointAddress&LIBUSB_ENDPOINT_DIR_MASK) {
723 case LIBUSB_ENDPOINT_IN:
724 inEndpoint = endpoints[i].bEndpointAddress&LIBUSB_ENDPOINT_ADDRESS_MASK;
727 case LIBUSB_ENDPOINT_OUT:
728 outEndpoint = endpoints[i].bEndpointAddress&LIBUSB_ENDPOINT_ADDRESS_MASK;
734 if (outEndpoint == -1 || inEndpoint == -1)
750 result = LIBUSB_SUCCESS;
754 if (result != LIBUSB_SUCCESS) {
764 libusb_device_handle *handle;
766 if (result != LIBUSB_SUCCESS) {
776 if (result == LIBUSB_SUCCESS)
778 if (result != LIBUSB_SUCCESS) {
779 for (
int j = 0; j < i; j++) {
780 while (result != LIBUSB_SUCCESS) {
797 #endif // !USE_WINUSB 798 JLDEBUG(gJournal,
"USB Port opened");
840 ::EnterCriticalSection(&
d->m_mutex);
841 remaining = *
length =
d->m_varBuffer.size();
847 d->m_varBuffer.erase(0, *
length);
848 remaining =
d->m_varBuffer.size();
850 ::LeaveCriticalSection(&
d->m_mutex);
851 JLTRACE(gJournal,
"returned success, read " << *
length <<
" of " <<
maxLength <<
" bytes, first: " << JLHEXLOG(((
char*)
data)[0]) <<
", " << remaining <<
" remaining in buffer");
857 if ((
res != LIBUSB_SUCCESS &&
res != LIBUSB_ERROR_TIMEOUT) || (
res == LIBUSB_ERROR_TIMEOUT && actual <= 0))
866 if (
d->rx_log == NULL)
870 d->rx_log =
fopen(fname,
"wb");
873 #ifdef LOG_RX_TX_FLUSH 891 JLDEBUG(gJournal,
"Request to set timeout to " << ms <<
" ms overridden, setting to 0 ms instead");
893 UCHAR enable =
FALSE;
895 d->m_winUsb.SetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, IGNORE_SHORT_PACKETS,
sizeof(UCHAR), &enable);
896 d->m_winUsb.SetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, PIPE_TRANSFER_TIMEOUT,
sizeof(ULONG), &ms);
900 JLDEBUG(gJournal,
"Setting timeout to " << ms);
915 JLDEBUG(gJournal,
"Setting RAWIO mode to " << enable);
919 UCHAR rawIo = (UCHAR)enable;
920 d->m_winUsb.SetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, RAW_IO,
sizeof(UCHAR), &rawIo);
935 ULONG someSize =
sizeof(UCHAR);
936 d->m_winUsb.GetPipePolicy(
d->m_usbHandle[1],
d->m_bulkInPipe, RAW_IO, &someSize, &rawIo);
959 char *bdata = (
char *)
data;
1007 if (written == NULL)
1017 d->m_winUsb.WritePipe(
d->m_usbHandle[1],
1024 *written = dataWritten;
1027 while (*written <
length)
1032 if (result != LIBUSB_SUCCESS)
1044 if (
d->tx_log == NULL)
1048 d->tx_log =
fopen(fname,
"wb");
1050 fwrite(
data,1,*written,
d->tx_log);
1051 #ifdef LOG_RX_TX_FLUSH void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
An OS and compiler independent version of "memcpy".
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)
FILE BASE_IMPEXP * fopen(const char *fileName, const char *mode) MRPT_NO_THROWS
An OS-independent version of fopen.
#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 BASE_IMPEXP void BASE_IMPEXP fclose(FILE *f)
An OS-independent version of fclose.
Operation not implemented in this version (yet)
struct XsByteArray XsByteArray
XsResultValue waitForData(XsSize maxLength, void *data, XsSize *length=NULL)
Wait for data to arrive or a timeout to occur.
The specified i/o device can not be opened.
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
A required port could not be found.
Operation is invalid at this point.
uint32_t getTimeOfDay(tm *date_, time_t *secs_)
A platform-independent clock.
XsResultValue libusbErrorToXrv(int libusbError, XsResultValue hint=XRV_ERROR)
Map a libusb_error to XsResultValue.
No internal memory available.
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.
No serial port opened for reading/writing.
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)
The requested item was not found.
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=NULL)
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 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
An invalid parameter is supplied.
XSTYPES_DLL_API int64_t XsTime_timeStampNow(XsTimeStamp *now)
int BASE_IMPEXP sprintf(char *buf, size_t bufSize, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
#define XSENS_INVALID_THREAD
XsResultValue flushData(void)
Flush all data in the buffers to and from the device.
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
A generic error occurred.
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
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.
Unexpected message received (e.g. no acknowledge message received)
An I/O device is already opened with this object.
XSTYPES_DLL_API void xsNameThisThread(const char *threadName)
XSTYPES_DLL_API int XsPortInfo_usbBus(XsPortInfo const *thisPtr)
libUSB_bulk_transfer bulk_transfer
~UsbContext()
Destroy the USB context.
libUSB_ref_device ref_device