USBHostSerial connection to Ardunio (CDC Device)

I had two problems when using the USBHostSerial to connect to an Arduino UNO as a USB Serial device.

Symptoms of Problem

The USBHost library seemed to detect the CDC serial device just fine. It did not, however, properly initialize the connection. The Arduino UNO has TX and RX LEDs to indicate serial traffic. These LEDs did not light up, indicating that the serial connection was not properly initialized.

Problem #1: The Communication Interface

The USB communication devices class (CDC) uses two interfaces. The first (Interface 0) is the Communication Interface. The second (Interface 1) is the Data Interface. The communication interface is used to control the channel, setting parameters like baud rate, and other signals like DTR.

The USBHostSerial class configures the port as follows:

from USBHostSerial.cpp line 128-ish

    // set line coding
    int res = host->controlWrite(   dev,
                                    USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
                                    SET_LINE_CODING,
                                    0, serial_intf, (uint8_t *)&line_coding, 7);

The key here is the *serial_intf*. This is configured earlier in the code to the DATA interface, not the Communications interface. Essentially, it appears that the code is sending the configuration to the wrong interface. One minor change, swapping *serial_intf* for *0*, and the connection came to life:

modified USBHostSerial.cpp line 128-ish

    // set line coding
    int res = host->controlWrite(   dev,
                                    USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
                                    SET_LINE_CODING,
                                    0, 0, (uint8_t *)&line_coding, 7);

I am not sure if this is a bug in the library. Maybe some devices can accept the control packets on the data interface 1, I am not sure. This did not work for the Arduino.

Problem #2: C++ Inheritance Quirks?

The USBHostSerial class inherits from the Stream class, allowing nice stream-related functions like printf. This is done by overriding the virtual methods *_getc* and *_putc*. For some reason, I found that these overridden virtual methods were not being consistently called. Sometimes they would work, but then later in my code they wouldn't.

Rather than figure out all the intricacies of C++ inheritance, I just implemented mirror methods: *getch* and *putch* and called them instead. The different naming of these methods seemed to cut through the inheritance problem. Also, I added a method for sending larger buffers.

Source Code

Coming soon as part of one of my projects.

References

A good overview of the USB Serial CDC and virtual COM ports: http://www.lvr.com/usb_virtual_com_port.htm


Please log in to post comments.