DUE USB CDC: Do not send any character if no program on the PC is listening to them. This avoids Marlin waiting until the user actually opens a program that is able to consume the output of Marlin

This commit is contained in:
etagle 2018-03-15 00:56:28 -03:00
parent 4aebe3d82e
commit 404fc94705
4 changed files with 45 additions and 5 deletions

View file

@ -36,6 +36,7 @@
// Imports from Atmel USB Stack/CDC implementation
extern "C" {
bool usb_task_cdc_isenabled(void);
bool usb_task_cdc_dtr_active(void);
bool udi_cdc_is_rx_ready(void);
int udi_cdc_getc(void);
bool udi_cdc_is_tx_ready(void);
@ -56,9 +57,11 @@ int MarlinSerialUSB::peek(void) {
if (pending_char >= 0)
return pending_char;
// If USB CDC not enumerated or not configured on the PC side
if (!usb_task_cdc_isenabled())
return -1;
// If no bytes sent from the PC
if (!udi_cdc_is_rx_ready())
return -1;
@ -73,9 +76,11 @@ int MarlinSerialUSB::read(void) {
return ret;
}
// If USB CDC not enumerated or not configured on the PC side
if (!usb_task_cdc_isenabled())
return -1;
// If no bytes sent from the PC
if (!udi_cdc_is_rx_ready())
return -1;
@ -83,7 +88,10 @@ int MarlinSerialUSB::read(void) {
}
bool MarlinSerialUSB::available(void) {
/* If Pending chars */
return pending_char >= 0 ||
/* or USB CDC enumerated and configured on the PC side and some
bytes where sent to us */
(usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
}
@ -92,11 +100,22 @@ void MarlinSerialUSB::flush(void) {
void MarlinSerialUSB::write(const uint8_t c) {
/* Do not even bother sending anything if USB CDC is not enumerated
or not configured on the PC side or there is no program on the PC
listening to our messages */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
return;
/* Wait until the PC has read the pending to be sent data */
while (usb_task_cdc_isenabled() &&
usb_task_cdc_dtr_active() &&
!udi_cdc_is_tx_ready()) {
};
if (!usb_task_cdc_isenabled())
/* Do not even bother sending anything if USB CDC is not enumerated
or not configured on the PC side or there is no program on the PC
listening to our messages at this point */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
return;
// Fifo full

View file

@ -1012,7 +1012,7 @@ iram_size_t udi_cdc_read_buf(void* buf, iram_size_t size)
return udi_cdc_multi_read_buf(0, buf, size);
}
iram_size_t udi_cdc_multi_get_free_tx_buffer(uint8_t port)
iram_size_t __attribute__((optimize("O0"))) udi_cdc_multi_get_free_tx_buffer(uint8_t port)
{
irqflags_t flags;
iram_size_t buf_sel_nb, retval;
@ -1097,7 +1097,7 @@ int udi_cdc_putc(int value)
return udi_cdc_multi_putc(0, value);
}
iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size)
iram_size_t __attribute__((optimize("O0"))) udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t size)
{
irqflags_t flags;
uint8_t buf_sel;

View file

@ -52,6 +52,7 @@
static volatile bool main_b_msc_enable = false;
static volatile bool main_b_cdc_enable = false;
static volatile bool main_b_dtr_active = false;
void HAL_idletask(void) {
// Attend SD card access from the USB MSD -- Prioritize access to improve speed
@ -69,7 +70,7 @@ void usb_task_msc_disable(void) { main_b_msc_enable = false; }
bool usb_task_msc_isenabled(void) { return main_b_msc_enable; }
bool usb_task_cdc_enable(const uint8_t port) { return ((main_b_cdc_enable = true)); }
void usb_task_cdc_disable(const uint8_t port) { main_b_cdc_enable = false; }
void usb_task_cdc_disable(const uint8_t port) { main_b_cdc_enable = false; main_b_dtr_active = false; }
bool usb_task_cdc_isenabled(void) { return main_b_cdc_enable; }
/*! \brief Called by CDC interface
@ -87,12 +88,17 @@ void usb_task_cdc_config(const uint8_t port, usb_cdc_line_coding_t *cfg) {
dwDTERate = cfg->dwDTERate;
}
void usb_task_cdc_set_dtr(const uint8_t port, const bool b_enable) {
// Keep DTR status
main_b_dtr_active = b_enable;
// Implement Arduino-Compatible kludge to enter programming mode from
// the native port:
// "Auto-reset into the bootloader is triggered when the port, already
// open at 1200 bps, is closed."
if (1200 == dwDTERate) {
// We check DTR state to determine if host port is open (bit 0 of lineState).
if (!b_enable)
@ -102,6 +108,8 @@ void usb_task_cdc_set_dtr(const uint8_t port, const bool b_enable) {
}
}
bool usb_task_cdc_dtr_active(void) { return main_b_dtr_active; }
/// Microsoft WCID descriptor
typedef struct USB_MicrosoftCompatibleDescriptor_Interface {
uint8_t bFirstInterfaceNumber;

View file

@ -78,6 +78,19 @@ void usb_task_cdc_disable(const uint8_t port);
*/
void usb_task_cdc_set_dtr(const uint8_t port, const bool b_enable);
/*! \brief Check if MSC is enumerated and configured on the PC side
*/
bool usb_task_msc_isenabled(void);
/*! \brief Check if CDC is enumerated and configured on the PC side
*/
bool usb_task_cdc_isenabled(void);
/*! \brief Check if CDC is actually OPEN by an application on the PC side
* assuming DTR signal means a program is listening to messages
*/
bool usb_task_cdc_dtr_active(void);
/*! \brief Called by UDC when USB Host request a extra string different
* of this specified in USB device descriptor
*/