Skip to content

CDC Serial send blocks when host closes connection #106

@NicoHood

Description

@NicoHood

Sample code:

    while(true)
    {
        LED_ON();
        _delay_ms(500);
        LED_OFF();
        _delay_ms(500);
        for(uint8_t i = 0; i<100;i++){
            if(VirtualSerial_CDC_Interface.State.ControlLineStates.HostToDevice){
                CDC_Device_SendByte(&VirtualSerial_CDC_Interface, 'a');
            }            
        }
  }

The problem is also described here:
http://www.avrfreaks.net/forum/lufa-usb-cdc-detect-when-host-application-connects

The DTR line determines if the host opened the serial port or not. If DTR is set, you should be able to send. Problem1: The CDC class driver does not check the DTR line for sending, only if baud != 0. If you manually add the check there is a remaining Problem2: The host does not clear anything if he closes the port (not even a single setup request happens).

I've tried the Arduino USB core, which does seem to handle the problem like this:

  • Do a DTR check
  • On the first error of a writing stream, abort

In this case it really helps to stop sending if you know the USB device will timeout. This might work for sending a stream (println), but in my case I am using stdio/printf so every byte will be sent on its own.

Arduino sketch comparison:

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  //Serial.print("testegorogkrhtrhkhprtkpj\n"); <-- This works fine
  for(uint8_t i = 0; i<100;i++){
      Serial.write('a');  // <- This also crashes
  }
}

I am using ArchLinux:

Linux hostname 4.9.65-1-lts #1 SMP Fri Nov 24 13:02:16 CET 2017 x86_64 GNU/Linux

I am not sure if this a linux problem and since when this happens. Maybe someone can check on older kernels or windows. If they behave the same, we should try to fix it.

The only solution I can imagine is to set an error flag and do not accept sending requests until a timeout is reached.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions