qint32 QUsbDevice::open() { if (mConnected) return -1; if (!guidFromString(mFilter.guid, &mGuid)) return -1; if (!getDeviceHandle(mGuid, &mDevHandle)) return -1; else if (!getWinUSBHandle(mDevHandle, &mUsbHandle)) return -2; else if (!getUSBDeviceSpeed(mUsbHandle, &mDevSpeed)) return -3; else if (!queryDeviceEndpoints(mUsbHandle, &mPipeId)) return -4; ulong timeout = mTimeout; /* SetPipePolicy requires an unsigned long */ if (!WinUsb_SetPipePolicy(mUsbHandle, mConfig.readEp, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout)) { qWarning("Error WinUsb_SetPipePolicy: %d.\n", GetLastError()); return -5; } if (!WinUsb_SetPipePolicy(mUsbHandle, mConfig.writeEp, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout)) { qWarning("Error WinUsb_SetPipePolicy: %d.\n", GetLastError()); return -6; } bool enable = true; if (!WinUsb_SetPipePolicy(mUsbHandle, mConfig.readEp, IGNORE_SHORT_PACKETS, sizeof(enable), &enable)) { qWarning("Error WinUsb_SetPipePolicy: %d.\n", GetLastError()); return -7; } mConnected = true; return 0; }
void QUsbDevice::setTimeout(quint16 timeout) { UsbPrintFuncName(); if (mUsbHandle==INVALID_HANDLE_VALUE || !mConfig.writeEp || !mConfig.readEp) { return; } mTimeout = timeout; ulong _timeout = mTimeout; /* SetPipePolicy requires an unsigned long */ if (!WinUsb_SetPipePolicy(mUsbHandle, mConfig.readEp, PIPE_TRANSFER_TIMEOUT, sizeof(_timeout), &_timeout)) { qWarning("Error WinUsb_SetPipePolicy: %d.\n", GetLastError()); return; } if (!WinUsb_SetPipePolicy(mUsbHandle, mConfig.writeEp, PIPE_TRANSFER_TIMEOUT, sizeof(_timeout), &_timeout)) { qWarning("Error WinUsb_SetPipePolicy: %d.\n", GetLastError()); return; } }
/*! \brief Set the default timeout value to use in blocking operations. \details This function sets the value of m_timeout. There is no infinity value. The value 0 means that the default value is used. \param ms The desired timeout in milliseconds \returns XRV_OK if the timeout value was successfully updated */ XsResultValue UsbInterface::setTimeout(uint32_t ms) { #ifdef USE_WINUSB JLDEBUG(gJournal, "Request to set timeout to " << ms << " ms overridden, setting to 0 ms instead"); ms = 0; // no timeout ever UCHAR enable = FALSE; WinUsb_SetPipePolicy(d->m_usbHandle[1], d->m_bulkInPipe, IGNORE_SHORT_PACKETS, sizeof(UCHAR), &enable); //lint !e534 WinUsb_SetPipePolicy(d->m_usbHandle[1], d->m_bulkInPipe, PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &ms); //lint !e534 d->m_timeout = ms; #else JLDEBUG(gJournal, "Setting timeout to " << ms); if (ms == 0) d->m_timeout = 1; else d->m_timeout = ms; #endif return (d->m_lastResult = XRV_OK); }
/*! \brief Sets the RAWIO mode of the USB interface \note Only applies to WinUSB implementations \param enable : If true will enable RAW IO mode */ void UsbInterface::setRawIo(bool enable) { JLDEBUG(gJournal, "Setting RAWIO mode to " << enable); #ifdef USE_WINUSB enable = false; // never use raw IO UCHAR rawIo = (UCHAR)enable; WinUsb_SetPipePolicy(d->m_usbHandle[1], d->m_bulkInPipe, RAW_IO, sizeof(UCHAR), &rawIo); //lint !e534 #else (void)enable; #endif d->m_lastResult = XRV_OK; }
void QUsbDevice::flush() { UsbPrintFuncName(); if (mUsbHandle == INVALID_HANDLE_VALUE || !mConfig.readEp || !mConnected) { return; } ulong cbRead; uchar* data = new uchar[4096]; ulong timeout = 25; WinUsb_SetPipePolicy(mUsbHandle, mConfig.readEp, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout); WinUsb_ReadPipe(mUsbHandle, mConfig.readEp, data, 4096, &cbRead, NULL); timeout = mTimeout; WinUsb_SetPipePolicy(mUsbHandle, mConfig.readEp, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout); if (mDebug) qDebug("Flushed %d bytes from endpoint 0x%x", cbRead, (uint)mConfig.readEp); delete [] data; }
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { // Set timeout on endpoint // It might be more efficient to use async i/o here, but MS docs imply that // you have to create a new sync object for every call, which doesn't seem // efficient at all. So just set the pipe timeout and use sync i/o. ULONG tmp = timeout; if (!WinUsb_SetPipePolicy(dev->fd, ep, PIPE_TRANSFER_TIMEOUT, sizeof(tmp), &tmp)) return -EINVAL; // Perform transfer tmp = 0; if (!WinUsb_ReadPipe(dev->fd, ep, (unsigned char*)bytes, size, &tmp, NULL)) { tmp = GetLastError(); if (tmp == ERROR_SEM_TIMEOUT) return -LIBUSB_ETIMEDOUT; else return -EINVAL; } return tmp; }
void UsbInterfacePrivate::threadFunc() { HANDLE handles[1+m_oCount]; handles[0] = m_quitEvent; handles[m_oCount] = m_waitEvents[m_oCount-1]; //= { m_quitEvent, m_waitEvents[0], m_waitEvents[1] }; // start first read operation for (m_readIdx = 0 ; m_readIdx < (m_oCount-1); ++m_readIdx) { handles[m_readIdx+1] = m_waitEvents[m_readIdx]; //m_readIdx = 0; m_overlapped[m_readIdx] = OVERLAPPED(); ::ResetEvent(m_waitEvents[m_readIdx]); //lint !e534 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx]; WinUsb_ReadPipe(m_usbHandle[1], m_bulkInPipe, m_fixedBuffer[m_readIdx], (ULONG)m_fixedBufferSize, 0, &m_overlapped[m_readIdx]); //lint !e534 } int fastCount = 0; //m_readIdx = 1; bool policyFast = false; bool run = true; while (run) { // start follow-up read operation m_overlapped[m_readIdx] = OVERLAPPED(); ::ResetEvent(m_waitEvents[m_readIdx]); //lint !e534 m_overlapped[m_readIdx].hEvent = m_waitEvents[m_readIdx]; WinUsb_ReadPipe(m_usbHandle[1], m_bulkInPipe, m_fixedBuffer[m_readIdx], (ULONG)m_fixedBufferSize, 0, &m_overlapped[m_readIdx]); //lint !e534 m_readIdx = (m_readIdx + 1) % m_oCount; int64_t tBegin = XsTime_timeStampNow(0); DWORD waitResult = ::WaitForMultipleObjects(1+m_oCount, handles, FALSE, INFINITE); #if 1 // not sure if this causes problems, but it should help in catching up int64_t tEnd = XsTime_timeStampNow(0); switch (tEnd - tBegin) { case 0: if (++fastCount > 3 && !policyFast) { policyFast = true; // set fast policy UCHAR enable = TRUE; WinUsb_SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS, sizeof(UCHAR), &enable); //lint !e534 } break; case 1: if (fastCount) --fastCount; if (policyFast && fastCount <= 3) { // reset policy policyFast = false; UCHAR enable = FALSE; WinUsb_SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS, sizeof(UCHAR), &enable); //lint !e534 } break; default: fastCount = 0; if (policyFast) { // reset policy policyFast = false; UCHAR enable = FALSE; WinUsb_SetPipePolicy(m_usbHandle[1], m_bulkInPipe, IGNORE_SHORT_PACKETS, sizeof(UCHAR), &enable); //lint !e534 } break; } #endif // handle data switch (waitResult) { case WAIT_TIMEOUT: case WAIT_FAILED: case WAIT_OBJECT_0: run = false; break; default: if (waitResult >= WAIT_ABANDONED_0) { JLDEBUG(gJournal, "WFMO abandoned: " << (waitResult - WAIT_OBJECT_0)); break; } #ifndef XSENS_RELEASE JLDEBUG(gJournal, "WFMO trigger: " << (waitResult - WAIT_OBJECT_0)); #endif { // put data into buffer int idx = m_readIdx; DWORD dataRead = 0; if (!WinUsb_GetOverlappedResult(m_usbHandle[0], &m_overlapped[idx], &dataRead, FALSE)) { // error DWORD err = ::GetLastError(); switch (err) { case ERROR_SEM_TIMEOUT: case ERROR_IO_INCOMPLETE: //JLDEBUG(gJournal, "WinUsb_GetOverlappedResult resulted in acceptable windows error " << err); break; default: JLALERT(gJournal, "WinUsb_GetOverlappedResult resulted in windows error " << err); run = false; break; } //assert (err == ERROR_IO_INCOMPLETE); } else { // append unread data to var buffer JLTRACE(gJournal, "WinUsb_GetOverlappedResult resulted in " << dataRead << " bytes being read"); XsByteArray ref(&m_fixedBuffer[idx][0], dataRead, XSDF_None); ::EnterCriticalSection(&m_mutex); m_varBuffer.append(ref); ::LeaveCriticalSection(&m_mutex); } } break; } } }