Home > Software engineering >  Asynchronous read HID packet loss
Asynchronous read HID packet loss

Time:09-26

Question:
Was in a Windows application and HID device communications, the problem of asynchronous read found lost data, found that the driver layer receives the data is not in the receive buffer waiting for application to read right away, but the loss of uncertain long after the data stored in the cache,

Specific operation is as follows:
1, open the file in asynchronous read way open:
Hd=CreateFile (HidFunctionClassData - & gt; DevicePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING FILE_FLAG_OVERLAPPED, NULL);

2, open the Settings after receiving the cache size, and the setting of the readout confirm set success:
HidD_SetNumInputBuffers (hd, 128);
HidD_GetNumInputBuffers (hd, & amp; InputBufSize);

3, use ReadFile read data:
ReadFile (handle, rBuffer, "Capabilities. InputReportByteLength, & amp; DwRet, & amp; ROverLap);
WaitForSingleObject (rOverLap hEvent, 100);

4, launched a dedicated thread of data received, polling read;

The specific phenomenon:
Under a machine every 15 ms upload a frame data, PC every 20 ms receiving time, found that start each receives a frame is lost a frame, after receive the uncertain long data not losing data, until receive the cache is full;

Analysis:
If the driver layer of the received data into the receive buffer, so before receiving cache under data is not lost, so now, no doubt is the beginning of the data into the cache, or has been received.

Read function is as follows:
 int HIDDeviceRead (HANDLE HANDLE, LPVOID lpBuffer, dwords dwSize) 
{
If (handle==NULL | | handle==INVALID_HANDLE_VALUE)
return 0;
If (rOverLap hEvent==NULL | | rOverLap. HEvent==INVALID_HANDLE_VALUE)
return 0;
If (lpBuffer==NULL)
return 0;

BYTE rBuffer [512]={0};
DWORD dwRet;
BOOL bRet=0;
DWORD err;
Char log [128].

RBuffer [0]=0 x00;

//the call is successful, returns non-zero, call is not successful, returns 0
if (! ReadFile (handle, rBuffer, "Capabilities. InputReportByteLength, & amp; DwRet, & amp; ROverLap))
{
If ((err=GetLastError ())!=ERROR_IO_PENDING)
{
Sprintf (log, "Read data err: % d. \ r \ n", err);
_cprintf (log);
Return bRet.
}

If (: : WaitForSingleObject (rOverLap hEvent, 100).=WAIT_TIMEOUT)
{
//: : the GetOverlappedResult (handle, & amp; ROverLap, & amp; DwRet, TRUE);
DwRet=rOverLap. InternalHigh;

BRet=min (dwRet dwSize);
Memcpy (lpBuffer, & amp; RBuffer [1], bRet);
}

}
The else
{
BRet=min (dwRet dwSize);
Memcpy (lpBuffer, & amp; RBuffer [1], bRet);
}
ResetEvent (wOverLap hEvent);

Return bRet.
}

CodePudding user response:

People found it difficult to control to asynchronously and PC 20 ms you read it once, and underneath is 15 ms a, reading speed is slower than the speed of hair, unavoidably cause problems, why not synchronously?
Open a thread to read data block type, if there is no data ReadFile blocks where such guarantee as long as there is data can be received,

CodePudding user response:

Reasonable asynchronous frequency than sent to frequency should read? Otherwise it will lead to packet loss

CodePudding user response:

Add: once every 20 ms read here is a test cache doesn't work this deliberately set,

CodePudding user response:

reference 1st floor jason_wentzel response:
personal feel bad asynchronous control, and PC 20 ms you read it once, and underneath is 15 ms a, reading speed is slower than the speed of hair, unavoidably cause problems, why not synchronously?
Open a thread to read data block type, if there is no data ReadFile blocks where such guarantee as long as there is data can be received,


Synchronously reads bad control thread exit;

CodePudding user response:

refer to the second floor zgl7903 response:
reasonable asynchronous frequency than sent to frequency should read? Otherwise it will lead to packet loss


Every 20 ms read here is a test cache doesn't work this deliberately set, there will be a real use threads polling read;

CodePudding user response:

Fyi:
//loop to a function every time send 200 bytes (this is the fixed) buffer, 
//a function need to incoming buffer, the circulation of 240 bytes (fixed) new buffer for processing,
//when dealing with each new printing takes two bytes of the buffer
# ifdef _MSC_VER
# pragma warning (4996) disable:
# endif
# include & lt; stdio.h>
# include & lt; Stdlib. H>
# include & lt; String. H>
# ifdef _MSC_VER
# include & lt; Windows. H>
# include & lt; Process. H>
# include & lt; IO. H>
# define MYVOID void
# define vsnprintf _vsnprintf
# the else
# include & lt; Unistd. H>
# include & lt; Sys/time. H>
# include & lt; Pthread. H>
# define CRITICAL_SECTION pthread_mutex_t
# define MYVOID void *
# endif
//the Log {
# define MAXLOGSIZE 20000000
# define MAXLINSIZE 16000
# include & lt; Time. H>
# include & lt; Sys/timeb. H>
# include & lt; Stdarg. H>
Char logfilename1 []="MyLog1. Log";
Char logfilename2 []="MyLog2. Log";
The static char logstr [MAXLINSIZE + 1];
Char datestr [16].
Char timestr [16].
Char MSS [4].
CRITICAL_SECTION cs_log;
The FILE * flog;
# ifdef _MSC_VER
The Lock (CRITICAL_SECTION void * l) {
The EnterCriticalSection (l);
}
Void Unlock (CRITICAL_SECTION * l) {
LeaveCriticalSection (l);
}
Void sleep_ms (int) ms {
Sleep (ms).
}
# the else
The Lock (CRITICAL_SECTION void * l) {
Pthread_mutex_lock (l);
}
Void Unlock (CRITICAL_SECTION * l) {
Pthread_mutex_unlock (l);
}
Void sleep_ms (int) ms {
Usleep (ms * 1000);
}
# endif
Void LogV (const char * pszFmt, va_list argp) {
* struct tm now;
Struct timeb TB;

If (NULL==pszFmt | | 0==pszFmt [0]) return;
Vsnprintf (logstr, MAXLINSIZE pszFmt, argp);
Ftime (& amp; TB);
Now=localtime (& amp; TB. Time);
Sprintf (datestr, "% d % % 4 d - 02-02 d", now - & gt; Tm_year + 1900, now - & gt; Tm_mon + 1, now - & gt; Tm_mday);
Sprintf (timestr, "02 02 02 % d: % d: % d", now - & gt; Tm_hour, now - & gt; Tm_min, now - & gt; Tm_sec); nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull
  • Related