wxThread::ExitCode ReceiveFromDevice::Entry()
{
    bool error = false;//Indicates last state
    while(!TestDestroy())
    {
        DWORD read = 0;
        UCHAR buff[256]= {0};
        if(device->WinUSBHandle == INVALID_HANDLE_VALUE || !device->GetState())
        {
            Reset();
            if(error)
                Sleep(errSleep);
            error = true;
            continue;
        }
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(overlapped));
        overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);//(NULL, TRUE, FALSE, NULL);
        if(!WinUsb_ReadPipe(device->WinUSBHandle, IN_EP, data + received, IN_EP_PACKET, &read, &overlapped))
        {
            if(GetLastError() != ERROR_IO_PENDING)
            {
                Reset();
                if(error)
                    Sleep(errSleep);
                error = true;
                continue;
            }
        }
        while(WaitForSingleObject(overlapped.hEvent, 100) == WAIT_TIMEOUT)
        {
            if(TestDestroy())//Check whether the thread should be destroyed
            {
                CloseHandle(overlapped.hEvent);
                return 0;
            }
        }
        //Complete transfer - get received bytes
        WinUsb_GetOverlappedResult(device->WinUSBHandle, &overlapped, &read, FALSE);
        CloseHandle(overlapped.hEvent);//Clear event
        //Process data
        if(read == 0)
        {
            //Error occur, reset state
            Reset();
            if(error)
                Sleep(errSleep);
            error = true;
            continue;
        }
        error = false;
        //Increase counters
        received += read;
        receivedPackets++;
        //Check if we read entire message
        if(data[0] == receivedPackets)
        {
            ProcessMessage();
            Reset();
        }
    }
    return 0;
}
bool AdbWinUsbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,
                                                 ULONG* bytes_transferred,
                                                 bool wait) {
  if (NULL != bytes_transferred) {
    *bytes_transferred = 0;
  }

  if (!IsOpened()) {
    SetLastError(ERROR_INVALID_HANDLE);
    return false;
  }

  ULONG transfer;
  bool ret = WinUsb_GetOverlappedResult(
                  parent_winusb_io_object()->winusb_handle(),
                  overlapped(),
                  &transfer,
                  wait ? TRUE : FALSE) ? true : false;

  // TODO: This is bizzare but I've seen it happening
  // that GetOverlappedResult with wait set to true returns "prematurely",
  // with wrong transferred bytes value and GetLastError reporting
  // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop!
  ULONG error = GetLastError();

  if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) &&
      ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) {
    for (int trying = 0; trying < 10; trying++) {
      Sleep(2);
      ret = WinUsb_GetOverlappedResult(
                parent_winusb_io_object()->winusb_handle(),
                overlapped(),
                &transfer,
                wait ? TRUE : FALSE) ? true : false;
      error = GetLastError();
      if (!ret || (0 != transfer) ||
          ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) {
        break;
      }
    }
  }

  if (NULL != ovl_data) {
    CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED));
  }

  if (NULL != bytes_transferred) {
    *bytes_transferred = transfer;
  }

  return ret;
}
예제 #3
0
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;
		}
	}
}