Enabling PL2303 serial communication via USB on TX1

Hi,

I am having problems connecting a serial USB device to my TX1 development kit. From what I can tell, it seems that a driver or module (or both) is missing.

On a “regular” Linux PC, I get the following

dmesg --follow

messages when plugging the device into a USB port:

[2355542.226959] usb 1-3: new full-speed USB device number 3 using xhci_hcd
[2355542.411733] usb 1-3: New USB device found, idVendor=0557, idProduct=2021
[2355542.411742] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[2355542.411749] usb 1-3: Product: ATEN USB to Serial Bridge
[2355542.411755] usb 1-3: Manufacturer: Prolific Technology Inc.
[2355542.412565] pl2303 1-3:1.0: pl2303 converter detected
[2355542.413353] usb 1-3: pl2303 converter now attached to ttyUSB0

But on the TX1, I never see the final two rows:

[89482.252714] usb 1-3: new full-speed USB device number 3 using xhci-tegra
[89482.280931] usb 1-3: New USB device found, idVendor=0557, idProduct=2021
[89482.289140] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[89482.297582] usb 1-3: Product: ATEN USB to Serial Bridge
[89482.304488] usb 1-3: Manufacturer: Prolific Technology Inc.

Nothing appears to be detecting and grabbing the device and assigning it to a /dev/ttyUSB address.

Output from

zcat /proc/config.gz |egrep '(CONFIG_USB_SERIAL_FTDI|SERIAL_CONSOLE)'
# CONFIG_USB_SERIAL_CONSOLE is not set
CONFIG_USB_SERIAL_FTDI_SIO=y

I have seen many similar threads, but only hand-wavy explanations as to how to resolve issues like this. Could someone please direct me to some concrete information on exactly what to do? I’d prefer not having to rebuild the entire kernel, if possible.

The dmesg would tend to support your suspicion that the driver is missing. USB is correctly detecting and announcing the device, but nothing seems to have taken ownership for the Jetson case.

However, there are several different serial UART chipsets out there. FTDI is the most common, and so far as I know most Linux systems have this one available by default. Apparently the ATEN serial bridge is pl2303 instead of FTDI. What do you see from:

zcat /proc/config.gz | grep PL2303

It should show something like:

CONFIG_USB_SERIAL_PL2303=y

If this is present, then it may just be that udev is somehow getting involved. There could actually be a file generated in “/dev”, but of a different name than you expect. I doubt this is the case since dmesg didn’t mention anything, but I wouldn’t rule this out completely.

FYI, a serial UART is not a serial console. The CONFIG_USB_SERIAL_CONSOLE is unrelated to the normal operation of a serial UART. The serial console already exists on the J21 connector via an integrated UART.

Something you could do is watch this as you insert or remove the cable, carefully watching to see if anything changes:

watch -n 1 ls -C /dev/tty

I can confirm that PL2303 is enabled in /proc/config.gz:

CONFIG_USB_SERIAL_PL2303=y

Looking for changes by watching ls -C /dev/tty* does not reveal anything either, sadly.

I have looked at all the files in /etc/udev/rules.d/ but I cannot see anything there that would affect this device. For reference, here is a complete listing of what lsusb tells me:

sudo lsusb -vvv -d "0557:2021"

Bus 001 Device 006: ID 0557:2021 ATEN International Co., Ltd
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x0557 ATEN International Co., Ltd
  idProduct          0x2021
  bcdDevice            4.00
  iManufacturer           1 Prolific Technology Inc.
  iProduct                2 ATEN USB to Serial Bridge
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           39
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Status:     0x0000
  (Bus Powered)

A comment first on how USB deals with new devices…

The device can report a class, and if the class is a known generic class (such as bulk storage or human interface device), then the device follows a generic standard and no extra driver will be required. In the case of hardware requiring a specific driver, and not one of the generic classes, the device will be labeled as “Vendor Specific Class”. Your device shows as vendor specific, and so it needs a driver for that exact device.

When a class is not sufficient to define what the device is in terms of generic drivers the mechanism for making this determination reverts to a registry of the manufacturer and device IDs. Your lsusb shows the manufacturer ID is 0x0557, and the device ID is 0x2021. I tried looking this up here (I don’t know how current this list is, but this should be at least somewhat recent…and if not here, then likely Linux doesn’t know the ID either):
http://www.linux-usb.org/usb.ids

Although the manufacturer is there, the specific ID is not. Even if this chip uses the same driver as one of their other devices I don’t think Linux could make that association without extra help. I don’t know if this would be sufficient or not, but it might be a starting place (personally, if I could change for an FTDI device, I’d just get a new cable…but probably you have a reason for using this device):
https://www.linuxquestions.org/questions/linux-hardware-18/forcing-a-specific-driver-for-a-device-through-udev-836411/

“udev” is designed to be able to trigger upon a hot plug event. USB is one “subsystem”, and within that the idProduct and idVendor are the hex values mentioned above…this would trigger udev to cause some action to occur. Usually this is for renaming or setting up entries in “/dev”.

The files in “/lib/udev/…” are part of your system’s packages, and those should not be edited. Files in “/etc/udev/rules.d/” are meant to be configured by you to customize your system. Until the USB registry gets the idProduct for that particular idVendor, and until that works its way into Linux, this would be a method to get USB and the driver to work together. I don’t have one to test, so I can’t say there is any guarantee. It is simple to do though, you’d just create a human readable text file.

If you were to look at files in “/etc/udev/rules.d/”, then you’d find that some are actual files, and others are symbolic links into the permanent files of “/lib/udev/rules.d/”. A typical customization (though not on Jetsons) is that the default graphical or text boot mode is set by a symbolic link pointing into the specific “/lib/udev/rules.d/” file via a symbolic link in “/etc/udev/rules.d/”. In cases where the system is completely customized, and not picking from one of several standard choices, that file is an actual file in “/etc/udev/rules.d/”. Your rule will need to be a real file.

An interesting example for you would in fact be the more common FTDI version…FTDI does the same thing, it’s just a different driver and ID pair (later I’ll mention an ATEN Intl entry…same manufacturer as your device, different idProduct). On L4T R28.2.1 I see this in “/lib/udev/rules.d/”, within file named “77-mm-usb-serial-adapters-greylist.rules”:

# FTDI-based serial adapters
#   FTDI does USB to serial converter ICs; and it's very likely that they'll
#   never do modems themselves, so it should be safe to add a rule only based
#   on the vendor Id.
ATTRS{idVendor}=="0403", ENV{ID_MM_DEVICE_MANUAL_SCAN_ONLY}="1"

That first URL I mentioned shows instead this other entry (which I’ve modified with part of your information…but be careful because this is not valid in your case):

SUBSYSTEM="usb", ATTRS{idVendor}="0557", ATTRS{idProduct}="2021", RUN+="modprobe ftdi_sio" NAME="Whatever"

…notice that this action is designed to insert a kernel module, but your device driver is not in the form of a module (plus it is an FTDI module and yours is pl2303). Nor is the FTDI driver on the default Jetson…these are integrated. I believe this is why there is a difference between that other URL’s example and any integrated feature.

So I am going to suggest this test…copy “/lib/udev/rules.d/77-mm-usb-serial-adapters-greylist.rules” to “/etc/udev/rules.d/”. Any edits you make will override the “/lib” version. Removing this file from “/etc/udev/rules.d/” will revert to the original file. Until edits are made, this is the same as doing nothing.

Now edit “/etc/udev/rules.d/77-mm-usb-serial-adapters-greylist.rules”. It isn’t particularly important, but notice the lines are sorted in increasing order of idVendor. Copy the line for a related ATEN Intl product (probably also a serial UART), and place it just below the original. Edit the idProduct to become “2021”. It’ll look like this:

ATTRS{idVendor}=="<b><i><u>0557</u></i></b>", ATTRS{idProduct}=="<b><i><u>2021</u></i></b>", ENV{ID_MM_DEVICE_MANUAL_SCAN_ONLY}="1"

Reboot. See if the “/dev/” file now shows up (use the same “dmesg --follow” while inserting the cable and watch the “/dev/tty*” files). If this works, all is good. If not, then it is easy to remove the “/etc/udev/rules.d/” version of this file and thus revert to original behavior. Even if this doesn’t work it should be harmless in a failure case.

Thank you for a very detailed answer. Unfortunately, this test did not change anything. I copied the greylist rules from /lib to /etc and added the line as you suggested (with idProduct==“2021”, below a line with idProduct == “2008”). I rebooted the TX1 development kit and tried again, with dmesg --follow and watching /dev/tty*. No change.

I can see an entry in /dev/bus/usb/001/003 (e.g.; the device number increments each time I replug the adapter), but I know too little to be able to say if this is useful or not.

What is most confusing to me is that I have a Linux PC running a vanilla Ubuntu 16.04 installation, and there the serial adapter works absolutely fine.

I do happen to have a TX2 dev kit in the lab as well, and I haven’t tried the USB serial adapter on that. I’m guessing the setup should be very similar on the TX2 (I’m thinking if I need to rule out some weird hardware issue scenarios). I might just try that if I get the time, just to collect more data on the problem. I’m also very much open for other suggestions or ideas.

USB is functioning as expected, but the driver is not loading. The reason the driver does not load is that the manufacturer used a different device ID than what the driver knows about…the different ID is saying this is different hardware even if the driver is the same (and we don’t really know the driver is the same, but I suspect it is).

The USB end itself is working as expected, and even the driver is working as expected. The problem is we need a way to tell the driver to use this device when it has been told the device is wrong. I had hoped that telling udev to load the right driver would be sufficient, but apparently the driver still knows the device is incorrect for that driver.

Perhaps it isn’t the driver I expect. Your PC where it works could be useful to find out that information. If you freshly boot your PC, and do not have the device connected, run “lsmod” and see which modules are listed. Then monitor “dmesg --follow” as before, and plug in the device. Not only will you be interested in any information which might be mentioned there, but more importantly…note which module loads. Although you should write a file with a note of the modules present prior to plug-in, you might also run:

watch -n 1 lsmod

See if we can find out some detail about the providing driver which we are currently missing.

Or…if this is just a serial UART cable and not something more, then perhaps getting an FTDI version would be easier.

So - running dmesg --follow on the working PC after a fresh boot gives me this output:

[  374.833015] usb 1-4: new full-speed USB device number 2 using xhci_hcd
[  375.017804] usb 1-4: New USB device found, idVendor=0557, idProduct=2021
[  375.017813] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  375.017820] usb 1-4: Product: ATEN USB to Serial Bridge
[  375.017825] usb 1-4: Manufacturer: Prolific Technology Inc.
[  375.035192] usbcore: registered new interface driver usbserial
[  375.035230] usbcore: registered new interface driver usbserial_generic
[  375.035266] usbserial: USB Serial support registered for generic
[  375.040015] usbcore: registered new interface driver pl2303
[  375.040056] usbserial: USB Serial support registered for pl2303
[  375.040091] pl2303 1-4:1.0: pl2303 converter detected
[  375.041906] usb 1-4: pl2303 converter now attached to ttyUSB0

And the top rows of lsmod which are added after plugging in the device are

Module                  Size  Used by
pl2303                 20480  0
usbserial              53248  1 pl2303

And yes, we are looking into other ways of connecting the serial device directly to the TX1, probably using FTDI. But it’s fun to learn stuff too!

It really looks like the PC uses the pl2303 driver I had originally expected to work. However, it is the combination of vendor ID and product ID being looked up in a table which associates a vendor specific driver to a USB component. That table is updated periodically. I am suspicious that the table used on the Jetson is out of date compared to the table used on the PC:

The literal file is “usb.ids”, and the command to do the update is:

sudo update-usbids

Try that, reboot, and see if plugging in the device results in seeing the driver load.

Updated file is now in /var/lib/usbutils/usb.ids . Reboot and trying again had no effect. I tried with using the 77-mm-usb-serial-adapters-greylist.rules file, and without it. Nothing changes.

I also compared with the file on the PC; that file was written on Oct 23 2015. Neither that nor the newly created file has an entry for device id 2021 and vendor 0557.

I am starting to wonder if I’m missing part of the bigger picture here; if there is something in the way I have set up the TX1 that is somehow blocking certain functions.
I have noticed that each time I reboot the TX1, /etc/resolv.conf changes the nameserver to 127.0.1.1 which results in all DNS queries failing. I had to manually change this (again) in order to run the update-usbids command.

I had originally flashed the TX1 using Jetpack 3.1 and that time I was forced to connect it via the USB cable from a host PC. I then realized I wanted the newer version and redid the process with Jetpack 3.3. This time I did not need the USB cable, as the TX1 appeared to be detected as connected to our local network.
I must admit, I have no idea how this dark magic with Docker really works, but like I said, I am beginning to suspect that there are larger forces at work here that I do not understand.

This may seem long and complicated, but probably that’s only because I’m explaining what leads up to this problem…it seems your PC kernel is simply newer than the Jetson kernel. What follows is an explanation of finding out what went wrong and how to “back port” the feature…but this is really so simple your main effort will simply be in taking your current kernel configuration, saving it for use in a new and edited kernel, and then flashing as needed. I’m not covering flash, but once you see what is needed we can add details as necessary for building and installing the edits.

If I go here I do see product ID 2021 listed:
https://cateee.net/lkddb/web-lkddb/USB_SERIAL_PL2303.html

If I go to the kernel source as provided for the TX1 on R28.2 and look at this (which is what you get with “CONFIG_USB_SERIAL_PL2303=y”):

drivers/usb/serial/pl2303.h

…I see:

#define PL2303_VENDOR_ID        <b>0x067b</b>
#define PL2303_PRODUCT_ID       0x2303

Note that 067b is the “manufacturer” ID, and not the vendor ID, as reported in lsusb. Either the driver in 4.4.38, for L4T, is incorrect in using manufacturer ID in place of vendor ID, or else the vendor ID is not known, or else the device itself has made a mistake (explained below, this was updated in 4.4.168). Calling the manufacturer ID the vendor ID is probably a mistake (though a text description from dmesg won’t necessarily be wrong send the manufacturer listed is correct), but in newer kernels this won’t matter since having all devices using the same driver mix and match labels won’t change how it functions.

Bottom line though: The pl2303 driver on the TX1’s 4.4.38 kernel does not recognize the device because the driver uses 0x067b instead of 0x0557 on manufacturer ID. Your manufacturer is indeed 0x067b, but this is not what the driver should be using to see compatibility. The table of device IDs lacks 0x0557 in combination with 0x2021. A bit of editing can fix this by adding the 0x0557 version.

So it is worth explaining something in the USB chipset industry. Every chipset manufacturer has registered with usb.org, and has a unique ID issued (this is the idVendor). This chipset might be used in either its own product or a third party product. If the manufacturer of the chipset and the product are the same, then vendor ID and manufacturer ID are the same. If someone purchases a chipset from a chipset vendor, and has the money to register IDs, then the vendor ID and product ID are unique to that manufacturer; on the other hand, if the manufacturer is using a standardized part from some chipset they did not create, such as FTDI, then the original chipset manufacturer vendor ID and product ID can be used…FTDI allows purchase of USB serial UARTs pre-burned with their vendor and product ID, or optionally blank so that the manufacturer using their chipset can completely customize. Both are valid. Your 0557:2021 is a third party chipset used by manufacturer 067b.

Regardless of whether the vendor and manufacturer use only the vendor’s ID, or a custom manufacturer setup, the chipset uses the same driver. There is a table of ID combinations which all use the same driver. Your chipset obviously uses the pl2303 driver.

I believe the newer kernel version on the desktop PC understands the idVendor of 0x0557 simply because it was updated (the desktop PC has a newer kernel version). I hate to say it, but because the feature was compiled directly in you may need to edit this in the kernel source and replace the kernel itself using the edited version. It wouldn’t be technically correct since 0x067b is also valid, but you could simply edit this line in “drivers/usb/serial/pl2303.h” (I recommend against this, it is only for illustration):

- #define PL2303_VENDOR_ID        0x067b
+ #define PL2303_VENDOR_ID        0x0557

To actually do this correctly you’d update the table of vendor/product IDs used by the driver by editing “drivers/serial/usb/pl2303.h” and the “.c”. In “pl2303.h” you’d go to this block and add a new line:

#define ATEN_VENDOR_ID          0x0557
#define ATEN_VENDOR_ID2         0x0547
#define ATEN_PRODUCT_ID         0x2008
[i][u][b]// This would be added so we can name iProduct 2021:
#define ATEN_PRODUCT_ID2         0x2021[/b][/u][/i]

…and then in “pl2303.c” you’d register the new combination of IDs. You’d find this block, and then insert code:

...
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
[i][u][b]// NEW CODE LINE...note the "2"...this combines iVendor and iProduct to allow your case:
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) },[/b][/u][/i]
        { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
        { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },

This means regardless of whether there is a bug in checking manufacturer ID when scanning the device or not that the combination of IDs would correctly find the device driver is associated with your device.

If you need information on building the kernel (and modules as well since the base kernel is being edited) you can ask. Do take your running Jetson’s “/proc/config.gz”, save a reference copy somewhere safe, and gunzip it and rename it as “.config” for your starting configuration. CONFIG_LOCALVERSION would normally be “-tegra” if you wanted to match the module search location, but such a change as this implies it should be something custom, e.g.:

CONFIG_LOCALVERSION="-pl2303"

Honestly, if this is just a serial UART cable and there is nothing special about it, I’d just switch to an FTDI cable. If it is part of something else, then you’ll need to go through the extra effort due to the driver missing the 0557:2021 ID combination.

This looks like it was corrected in 4.4.168 (this may have been corrected earlier than that, but this is the version I examined), and if you want to see how the actual changes were arranged, see this and compare the combination of vendor and product IDs being put in the table:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/usb/serial/pl2303.h?h=v4.4.168
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/usb/serial/pl2303.c?h=v4.4.168

Thank you for some pretty remarkable detective work. We have decided to connect our serial devices directly through serial ports instead, but in the future I hope someone will find this thread and be helped by the information contained within. I certainly have been.

Do you mean through the integrated serial ports? If so, and if speed is to exceed 115200, be sure to use two stop bits instead of one.