lufa: Fix console_putc
buffering before host and hid_listen become ready
This commit is contained in:
parent
a4abe50f18
commit
91a125baeb
1 changed files with 49 additions and 6 deletions
|
|
@ -120,20 +120,35 @@ static bool console_is_ready(void)
|
||||||
|
|
||||||
static bool console_putc(uint8_t c)
|
static bool console_putc(uint8_t c)
|
||||||
{
|
{
|
||||||
if (!console_is_ready())
|
|
||||||
goto EXIT;
|
|
||||||
|
|
||||||
// return immediately if called while interrupt
|
// return immediately if called while interrupt
|
||||||
if (!(SREG & (1<<SREG_I)))
|
if (!(SREG & (1<<SREG_I)))
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
|
|
||||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
if (USB_DeviceState != DEVICE_STATE_Configured && !ringbuf_is_full(&sendbuf))
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
|
|
||||||
uint8_t ep = Endpoint_GetCurrentEndpoint();
|
if (!console_is_ready() && !ringbuf_is_full(&sendbuf))
|
||||||
|
goto EXIT;
|
||||||
|
|
||||||
|
/* Data lost considerations:
|
||||||
|
* 1. When buffer is full at early satage of startup, we will have to start sending
|
||||||
|
* before console_is_ready() returns true. Data can be lost even if sending data
|
||||||
|
* seems to be successful on USB. hid_listen on host is not ready perhaps?
|
||||||
|
* Sometime first few packets are lost when buffer is full at startup.
|
||||||
|
* 2. When buffer is full and USB pipe is not ready, new coming data will be lost.
|
||||||
|
* 3. console_task() cannot send data in buffer while main loop is blocked.
|
||||||
|
*/
|
||||||
|
/* retry timeout */
|
||||||
|
const uint8_t CONSOLE_TIMOUT = 5; // 1 is too small, 2 seems to be enough for Linux
|
||||||
|
static uint8_t timeout = CONSOLE_TIMOUT;
|
||||||
|
uint16_t prev = timer_read();
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
uint8_t ep = Endpoint_GetCurrentEndpoint();
|
||||||
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
|
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
|
||||||
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
|
|
||||||
|
AGAIN:
|
||||||
|
if (Endpoint_IsStalled() || !Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
|
||||||
goto EXIT_RESTORE_EP;
|
goto EXIT_RESTORE_EP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,16 +159,44 @@ static bool console_putc(uint8_t c)
|
||||||
// clear bank when it is full
|
// clear bank when it is full
|
||||||
if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
|
if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
|
||||||
Endpoint_ClearIN();
|
Endpoint_ClearIN();
|
||||||
|
timeout = CONSOLE_TIMOUT; // re-enable retry only when host can receive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write c to bank directly if there is no others in buffer
|
// write c to bank directly if there is no others in buffer
|
||||||
if (ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
|
if (ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
|
||||||
Endpoint_Write_8(c);
|
Endpoint_Write_8(c);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear bank when there are chars in bank
|
||||||
|
if (Endpoint_BytesInEndpoint() && Endpoint_IsINReady()) {
|
||||||
|
// Windows needs to fill packet with 0
|
||||||
|
while (Endpoint_IsReadWriteAllowed()) {
|
||||||
|
Endpoint_Write_8(0);
|
||||||
|
}
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
timeout = CONSOLE_TIMOUT; // re-enable retry only when host can receive
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
Endpoint_SelectEndpoint(ep);
|
Endpoint_SelectEndpoint(ep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* retry when buffer is full.
|
||||||
|
* once timeout this is disabled until host receives actually,
|
||||||
|
* otherwise this will block or make main loop execution sluggish.
|
||||||
|
*/
|
||||||
|
if (ringbuf_is_full(&sendbuf) && timeout) {
|
||||||
|
uint16_t curr = timer_read();
|
||||||
|
if (curr != prev) {
|
||||||
|
timeout--;
|
||||||
|
prev = curr;
|
||||||
|
}
|
||||||
|
goto AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
EXIT_RESTORE_EP:
|
EXIT_RESTORE_EP:
|
||||||
Endpoint_SelectEndpoint(ep);
|
Endpoint_SelectEndpoint(ep);
|
||||||
EXIT:
|
EXIT:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue