On macOS 12.6 running libusb 1.0.26, the host was seen to sometimes
make an incomplete ClearFeature(ENDPOINT_HALT) request when
ClearPipeStallBothEnds was called from libusb_cancel_transfer.
The host would send the SETUP packet, and the firmware would
call usb_transfer_schedule_ack to acknowledge the upcoming IN
token. However, the host would then not send the IN token,
proceeding directly to the next SETUP.
Since an empty transfer was queued to schedule the ACK, the
firmware would leak one transfer from the free_transfers list.
After a few iterations of this, the firmware would run out of
free transfers and the next request would hang waiting for one.
Fix this by flushing the transfer queues for the control endpoint
when a new SETUP is received, since that token implicitly cancels
any previously ongoing request.
Previously these calls were leaving the amplifiers on, since the
control settings passed were missing SWITCHCTRL_NO_TX_AMP_PWR and
SWITCHCTRL_NO_RX_AMP_PWR. Use the predefined SWITCHCTRL_SAFE here.
Also move these calls before setting the GPIO pins to output mode,
to avoid driving them to the wrong states briefly first.
Firmware now detects the hardware it is running on at startup and
refuses to run if it is compiled for the wrong platform. The board ID
returned by firmware to the host is now derived from run-time detection
rather than a compile-time value. A separate method to retrieve
compile-time supported platform is added.
On HackRF One, pin straps are checked to determine hardware revision.
This is informational to aid troubleshooting and does not affect any
function.
On rad1o, the UI update could block this loop from running for long
enough that it could stall in a state where neither of the conditions
was met.
Fix this by removing the 'phase' variable, in favour of a counter
tracking the number of bytes that have been scheduled for USB transfer.
Whenever there are enough bytes to schedule the next transfer, do so.
Meanwhile, the M0 count is prevented from wrapping around and clobbering
data not yet sent, because the M0 code monitors the m4_count variable
which is updated as each transfer completes.
The existing 'delay' function is not calibrated to any specific measure
of time. Add a new function using a loop with a known cycle count, to
produce delays of a given duration at a given CPU clock speed.
From USB 2.0, section 9.4.5:
"For endpoints using data toggle, regardless of whether an endpoint has
the Halt feature set, a ClearFeature(ENDPOINT_HALT) request always
results in the data toggle being reinitialized to DATA0."