Strange Behavior with USB Hub

It took me a couple of days to pinpoint the issue.

I have a fancy setup, Rock Pi 4 and Google Coral Dev Board stacked up, meanwhile, Rock Pi 4 and my Windows PC share keyboard, mouse and card reader through a UGreen USB switch (it’s a USB hub with a switch button).

I want Rock Pi 4 and Google Coral Dev Board talk through a 6 inch USB-A to USB-C cable directly, using ethernet over USB.

The drill is, Google Coral acts as a USB gadget/OTG (it’s configured with g_ether.ko module out of box, running Debian too by the way), and Rock Pi 4 runs USBNET which is already built into the kernel. It supposed to be a simple job, but didn’t work for days, I tried everything I could think of but no luck. Interesting enough, the two boards worked together perfectly when communicating serial through the same cable when setting up (ran things like fastboot), only problematic when trying ethernet over USB.

This evening, I plugged the Google board into the UGreen hub, all of sudden Rock Pi 4 USBNET fired up and recognized the Google board, I can ssh to the Google board through USB instead of bouncing around the router. Seems once Rock Pi 4 has the external USB hub plugged in it starts being fussy (it only hates ethernet but no issue with serial communication whatsoever).

I really don’t understand:roll_eyes:. But if you are facing the same problem, the hub is where to look.

For better understanding, two questions.
Are you using this USB switch?


Did you connect the devices like this?

1 Like

Yes, your picture is very accurate.
When it’s not working, there is no USBNET event show up in dmesg at all. Maybe not many people use Google board this way but I guess there should be users ssh Pi Zeros through USB
The USB hub switch is not powered with DC, so that’s not a factor.

I guess it probably has something to do with the udev rule I added for the Coral board, I’ll play with it a little this evening.

I think this is the cause:
[85672.446813] usb 8-1: new SuperSpeed USB device number 105 using xhci-hcd
[85672.473129] usb 8-1: Dual-Role OTG device on non-HNP port
[85672.473793] usb 8-1: set a_alt_hnp_support failed: -32
Basically, the Google Dev Board acts as an OTG device, Rock Pi 4 is supposed to act as OTG host, (even if the switch is set to host position), it doesn’t have the OTG host software stack to finish the job.
Question for @jack, which “Dual Role” USB module I should load for Rock Pi 4, if I need Rock Pi 4 to be the OTG host?

Thanks

I see, rk3399 uses DesignWare DRD, ran “cat /lib/modules/$(uname -r)/modules.builtin” shows dwc2/dwc3 are already built in, don’t why I’m getting “usb 8-1: Dual-Role OTG device on non-HNP port”

what if you plug the google board to the lower USB3 port?

I tried all 4 ports had the same errors. When switched to device, the messages are different but that’s not what I need:
[ 191.787672] usb usb7: USB disconnect, device number 1
[ 191.789424] xhci-hcd xhci-hcd.8.auto: USB bus 7 deregistered
[ 191.790605] rockchip-dwc3 usb0: USB unconnected
[ 193.430525] phy phy-ff770000.syscon:usb2-phy@e450.1: charger = USB_FLOATING_CHARGER

Switching back to host position, USB connected but HNP didn’t happen so the connection is useless:
[ 386.098336] usb usb8: New USB device found, idVendor=1d6b, idProduct=0003
[ 386.098354] usb usb8: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 386.098369] usb usb8: Product: xHCI Host Controller
[ 386.098383] usb usb8: Manufacturer: Linux 4.4.154-78-rockchip-00017-g625c2b2 xhci-hcd
[ 386.098397] usb usb8: SerialNumber: xhci-hcd.8.auto
[ 386.100177] hub 8-0:1.0: USB hub found
[ 386.100247] hub 8-0:1.0: 1 port detected
[ 386.100985] rockchip-dwc3 usb0: USB HOST connected

The errors in the log came from usbcore. Inspect the code in usb/hub.c:

static int usb_enumerate_device_otg(struct usb_device* udev)
{
int err = 0;
#ifdef CONFIG_USB_OTG
/*

  • OTG-aware devices on OTG-capable root hubs may be able to use SRP,
  • to wake us after we’ve powered off VBUS; and HNP, switching roles
  • “host” to “peripheral”. The OTG descriptor helps figure this out.
    */
    if (!udev->bus->is_b_host
    && udev->config*
    && udev->parent == udev->bus->root_hub)
    {
    struct usb_otg_descriptor *desc = NULL;
    struct usb_bus bus = udev->bus;
    unsigned port1 = udev->portnum;

    dev_info(&udev->dev, “Dual-Role OTG device on %sHNP port\n”,
    (port1 == bus->otg_port) ? “” : “non-”
    );
    /
    enable HNP before suspend, it’s simpler /
    if (port1 == bus->otg_port) {

    dev_err(&udev->dev, “can’t set HNP mode: %d\n”, err);

    } else if (desc->bLength == sizeof
    (struct usb_otg_descriptor)) {
    /
    Set a_alt_hnp_support for legacy otg device */

    if (err < 0)
    dev_err(&udev->dev,
    "set a_alt_hnp_support failed: %d\n", err);

So obviously bus->otg_port was not set to true. It happened in both armhf and arm64 build.
Searching the drivers directory, besides some vendor specific code (like NXP/Freescale code, they are not supposed to be related to the issue here) only dwc_otg_hcd.c and dwc2/hcd.c (hcd means Host Controller Driver) have a line:

hcd->otg_port = 1;

dwc3 uses a new struct I need extra time to read the code. But anyway, the USB ports on RockPi4 are not reporting as OTG ports, which is incorrect since they are supposed to be “DUAL MODE” (regardless the switch is on host or device)

This issue has a long history tracing back as early as 2011 when people trying to plug in Android phones to their Linux computer (mostly Ubuntu). Seems the most effective solutions is “update your kernel to version xx.xx” LOL.

Maybe I’d give Ubuntu a try. I always prefer lightweight over redundant features, but Debian will leave me no option if it couldn’t accomplish some very basic functions.

I even turned off OTG support completely and rebuilt the kernel, but still getting the same errors.

Something wrong here, that piece of code not even supposed to be compiled. The building tool settings? The symbol CONFIG_USB_OTG is unset in .config, usb/hub.c is recompiled without the symbol, how did this piece of code get into the kernel? Some other setting is overwriting it? It’s frustrating.

This is driving me nuts! CONFIG_USB_OTG is unset, that piece of code is definitely NOT in usb/hub.o, the message is not in it, where did the kernel get that message from?!

“CONFIG_USB_OTG” could come from a Make file.

CONFIG_USB_OTG is y in the default config.

https://github.com/radxa/kernel/blob/release-4.4-rockpi4/arch/arm64/configs/rockchip_linux_defconfig#L1021

I need to set up fstab and mount /boot correctly in order to use the kernel I built, after that and reboot I can ssh to the Google board through USB cable!

The question is, is it correct to enable OTG on Rock Pi 4 by default? I’m quoting from /usb/core/Kconfig:

config USB_OTG
bool “OTG support”
depends on PM
default n
help
The most notable feature of USB OTG is support for a
“Dual-Role” device, which can act as either a device
or a host. The initial role is decided by the type of
plug inserted and can be changed later when two dual
role devices talk to each other.

Select this only if your board has Mini-AB/Micro-AB
connector.

Rock Pi 4 doesn’t have mini/micro connectors.

I can confirm that, USB flash drive is working correctly on RockPi4 after I removed the OTG support.

Besides in Makefile USB_OTG default value is “n”. I’m not sure at what point it was turned on by default in the build, could came from rockchip settings? If the build was intended for low end tablets with micro-USBs, the setting is reasonable, but not for devices like RockPi4. I suggest to turn it off.