1

I am having a hard time working with the USB connection on my Google Coral Board running Debian. I am trying to make sure the system can determine if the USB-C port hardware was plugged in. What is the best way to do this? Any help or advice is greatly appreciated!

2
  • Your intentions are a bit unclear - are you trying to tell if the port has something connected to it, or if a specific device is connected to a usb-c port? In any case you'll have to work from a usb device and trace back up where they are connected to (I'm not familiar with usb-c specifically but if it just draws current without being seen as a device it may make things much harder) . If you want to use an event-based approach the best place to hook yourself to is udevd, and walk up DEVPATH (on bootup the event would still be triggered as the usb devices are added). Nov 27, 2020 at 6:50
  • Thank you for your advice @ThomasGuyot-Sionnest. To be more clear, I am writing a source code so that my board can determine whether any kind of USB is plugged in this USB port. For example, when a USB is plugged in, the LED will turns green indicating that USB is present. If the USB is unplugged, the LED will turn red. Nov 27, 2020 at 16:05

1 Answer 1

3

My answer is generic to USB; I haven't tested USB-C specifically as I lack the hardware. In any case it should give you a general idea of what you need to do even if USB-C could be different than USB-1/2/3.

Based on your comments what I understand is that you want to light up per-port LEDs when a device is plugged in.

First you need an event-driven approach. udevd provides that, allowing you to write rules that are triggered when devices are added and removed (on boot all detected devices trigger an add event so you don't need any special handling for bootup). At first glance you might want to filter on SUBSYSTEM=usb and DEVTYPE=usb_device. With the proper rule in place, udevd will trigger a handler script to tell you when a device is added or removed, with some information about it such as the event type and device path in /sys.

Then your handler script will have to look up information contained in /sys to find if the device is connected to a known port one on one of the root usb hubs (see /sys/bus/usb/devices/usb[0-9]). Not all device add/removal will toggle a light as some could be added/removed form a hub, in which case only the hub itself would trigger the light. So for each event, check the symlink target for the port file - in the name of the target you will have the name of the hub followed by the port number.

For example, on my system... each usb version/speed seems to have its own bus, so if I look at the root hubs:

$ lsusb -t |grep ^/
/:  Bus 09.Port 1: Dev 1, Class=root_hub, Driver=ohci-pci/4p, 12M
/:  Bus 08.Port 1: Dev 1, Class=root_hub, Driver=ohci-pci/2p, 12M
/:  Bus 07.Port 1: Dev 1, Class=root_hub, Driver=ohci-pci/5p, 12M
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=ohci-pci/5p, 12M
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/4p, 480M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/5p, 480M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/5p, 480M

Buses 1,2,3 and 6,7,9 share the same physical ports (they share the same PCI device number, with only differing function). Same with buses 4 and 5 (even same PCI function, which also explain why they both uses the same xhci driver). Bus 8 is USB1 only. Some of these devices have internal USB headers, as I have only 4 onboard USB2 ports. It's even possible some don't have headers at all such as reserved for special onboard devices or other motherboard models based on the same chips/PCB.

This command looks at all devices connected to my desktop, excluding all interfaces (*:*), and prints the port symlink under them:

$ for f in /sys/bus/usb/devices/+([^:])/*port*; do printf '%-32s: %s\n' $f $(readlink $f); done
/sys/bus/usb/devices/1-2.1/port : ../1-2:1.0/1-2-port1
/sys/bus/usb/devices/1-2.2/port : ../1-2:1.0/1-2-port2
/sys/bus/usb/devices/1-2.4/port : ../1-2:1.0/1-2-port4
/sys/bus/usb/devices/1-2/port   : ../1-0:1.0/usb1-port2
/sys/bus/usb/devices/4-1/port   : ../4-0:1.0/usb4-port1
/sys/bus/usb/devices/5-1.1/port : ../5-1:1.0/5-1-port1
/sys/bus/usb/devices/5-1.3/port : ../5-1:1.0/5-1-port3
/sys/bus/usb/devices/5-1/port   : ../5-0:1.0/usb5-port1
/sys/bus/usb/devices/7-1/port   : ../7-0:1.0/usb7-port1

Note that I'm looking at devices under /sys/bus/usb/devices/; udev will give you the full path from /sys/devices/ - they are the same; you can use udevadm info to get the actual device path.

Looking at this and digging up underlying device infos, I can see I have my monitor hub on usb1-port2 with three devices (keyboard, mouse, webcam on 1-2); On buses 4/5 there is one USB3 hub showing as connected to both usb4-port1 and usb5-port1 (same physical port, EHCI/XHCI) and two USB3 devices under it (on 5-1); and finally a low-speed serial device on usb7-port1.

If you have 2nd level hubs within your device, you will need to find how to identify them and consider their ports as well. For example my RPi v3 has 4 external usb ports, but when I look at the devices the onboard controller from the SoC has just 1 USB2 port, on which there is a 5-port hub, first port connects the onboard USB Ethernet controller and the remaining 4 are usable USB ports.

Finally, if you have more than one root hub, you need a way to identify reliably each relevant hub - either using the vendor/model IDs (use numeric values only, the decoded names often comes from a local database and subject to change), or if you have multiple of the same hubs, the underlying bus ID (ex PCI ID if it's a PCI/PCIe device). PCI ID's are possibly subject to change with the underlying hardware (motherboard model and maybe even revision bumps), but you may be able to at least trust the device ID order if the root devices always use the same slot numbers. Then either based on the specs or by testing the ports, match each hub's port number to a physical port location. You may check the depth as well in case an external hub bears the same vendor/model id.


To configure udevd, see the manpage, man 7 udev. The udevadm tool is also very useful to configure rules, especially the info and monitor commands.

You can use lsusb and usbview and read the sysfs attributes to view information about connected devices.

USB-specific information found under sysfs is documented in The Linux-USB Host Side API section of the Linux Kernel documentation, and many attributes relate directly to the USB specifications.

You can find the USB class codes from https://www.usb.org, which can be useful to identify device types. For a more general description of the USB configuration hierarchy, see USB in a NutShell Chap. 5: USB Descriptors.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .