arduino/ArduinoCore-samd

USBDevice.connected() does not work

pillilz opened this issue · 0 comments

USBDevice.connected() should return true if and only if the device is connected to a host.
Its actual return value does not reflect the connection state. If called repeatedly in a tight loop in connected state it shows periodic behavior. Every 2 seconds it returns false for 0.25s and true for the remaining time.

This is cause by two errors in the code:

bool USBDeviceClass::connected()
{
	// Count frame numbers
	uint8_t f = USB->DEVICE.FNUM.bit.FNUM;
	//delay(3);
	return f != USB->DEVICE.FNUM.bit.FNUM;
}

Error 1: FNUM is a 11bit number. Writing it to uint8_t variable discards the upper three bits and makes the comparison in the return statement invalid if FNUM is >= 256.

Error 2: Due to the commented out delay call, the two FNUM reads result in the same value with high probability, if I understand Wikipedia correctly, because it changes only every millisecond.

The errors explain the observed behavior. In connected state FNUM changes every millisecond. For 0 <= FNUM < 256 the return value is false. For 256 <= FNUM < 2048 the return value is true. In disconnected state FNUM does not change. Depending on its (random) value the function returns either true or false as described.

The following code fixes the issues for me.

bool USBDeviceClass::connected()
{
	// Count frame numbers
	uint16_t f = USB->DEVICE.FNUM.bit.FNUM;
	delay(1); // wait for next SOF
	return f != USB->DEVICE.FNUM.bit.FNUM;
}

Happy to raise a PR.