Question about mutex in rawhhid_recv

Status
Not open for further replies.

yeahtuna

Well-known member
Recently I've but a victim of slow HID read speeds in recent versions of Windows 10. I've had to increase my timeout values from 2ms all the way up to 50ms to prevent losing data. The real problem for me with long timeout values is that I need to read realtime data from up four USB HID devices.

As a work around, I'm trying to implement the calls to rawhid_recv on separate threads for each USB device. I was looking over the rawhid_recv code, and I see that there is a mutex in there. I'm guessing that's going to slow down my code? Does the mutex need to be there? If I ensure that multiple threads don't read from the same USB, can I just remove it? The code for rawhid_recv, most likely written by Paul, is below. I'd love to hear any insight you can offer.

Code:
int rawhid_recv(int num, void *buf, int len, int timeout) {
	hid_t *hid;
	unsigned char tmpbuf[516];
	OVERLAPPED ov;
	DWORD n, r;

	if (sizeof(tmpbuf) < len + 1) return -1;

	hid = get_hid(num);
	if (!hid || !hid->open) return -1;

	EnterCriticalSection(&rx_mutex);
	ResetEvent(&rx_event);
	memset(&ov, 0, sizeof(ov));
	ov.hEvent = rx_event;

	if (!ReadFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) {
		if (GetLastError() != ERROR_IO_PENDING) goto return_error;
		r = WaitForSingleObject(rx_event, timeout);
		if (r == WAIT_TIMEOUT) goto return_timeout;
		if (r != WAIT_OBJECT_0) goto return_error;
	}

	if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error;
	LeaveCriticalSection(&rx_mutex);
	if (n <= 0) return -1;
	n--;
	if (n > len) n = len;
	memcpy(buf, tmpbuf + 1, n);
	return n;
return_timeout:
	CancelIo(hid->handle);
	LeaveCriticalSection(&rx_mutex);
	return 0;
return_error:
	print_win32_err();
	LeaveCriticalSection(&rx_mutex);
	return -1;
}
 
So I managed to make this function multi-threaded. I needed up to four threads to use it on four separate Teensy devices, so I changed the declaration of rv_event to be an array of HANDLES, ditched the critical section, and used 'num' to select the appropriate rv_event. I could probably put the critical section back in, and like the rx_event, just make it an array. At any rate, my application is now reading at full speed again. Hurray.
 
Status
Not open for further replies.
Back
Top