Re: Raspberry Pi 3B Over-current USB

From: Archimedes Gaviola <archimedes.gaviola_at_gmail.com>
Date: Fri, 06 May 2022 14:03:41 UTC
On Tue, Apr 12, 2022 at 5:16 PM Archimedes Gaviola <
archimedes.gaviola@gmail.com> wrote:

>
>
> On Mon, Apr 11, 2022 at 9:59 PM Hans Petter Selasky <hps@selasky.org>
> wrote:
>
>> On 4/11/22 15:59, Archimedes Gaviola wrote:
>> > Hi Hans,
>> >
>> > Noted on the self-powered hub, thanks for the suggestion, I will try.
>> >
>> > Just wanted to share the observation from the testing I've conducted
>> with
>> > my Raspberry Pi 4B with the same 14.0-CURRENT to check if overcurrent is
>> > also experienced and it did, there was overcurrent and each ports' power
>> > shut-off during the situation but it was able to recover back. I
>> initiated
>> > the command 'usbconfig reset' and each port gloriously came back alive
>> one
>> > by one and loaded my USB keyboard and Prolific uplcom(4) drivers into
>> > functional and operational states. My measuring device is showing the
>> same
>> > amount of current 460mA while the voltage stayed at 5.05 from a
>> baseline of
>> > 5.15 voltshttps://filebin.net/10vy575q6h2yl8og. Unlike my RPi 3B,
>> voltage
>> > dropped to 4.93 from a baseline of 5.19 volts. So, the difference I
>> > observed is when the voltage dropped below 5, the system will not give a
>> > chance to make the ports come back alive as a sort of protection
>> mechanism.
>> > Sharing to you the logs below (with hw.usb.uhub.debug=1).
>>
>> FreeBSD does not actively check and use "bMaxPower" .
>>
>
> Hi Hans,
>
> It's okay, just tried your recommendation on a self-powered USB hub, my
> Prolific device is now working. Thanks a lot!
>
> Archimedes
>

Hi Hans,

I got my Prolific PL2303 USB-serial device working in RPi 3B without the
self-powered USB hub. I've extended the code /usr/src/sys/dev/usb/usb_hub.c
in the uhub_explore() routine specific to handling overcurrent condition.
Below are the added lines of code.

freebsd@generic:~ % diff -Nur /usr/src/sys/dev/usb/usb_hub.c.orig
/usr/src/sys/dev/usb/usb_hub.c
--- /usr/src/sys/dev/usb/usb_hub.c.orig 2022-04-29 10:52:44.787344000 +0000
+++ /usr/src/sys/dev/usb/usb_hub.c      2022-05-03 07:29:45.159470000 +0000
@@ -1045,6 +1045,25 @@
                            udev, NULL, portno, UHF_C_PORT_OVER_CURRENT);
                        if (err != USB_ERR_NORMAL_COMPLETION)
                                retval = err;
+
+                       /* Turn on hub port power if current get
normalized. */
+                       DPRINTF("Turn on power on port %d.\n", portno);
+                       err = usbd_req_set_port_feature(
+                           udev, NULL, portno, UHF_PORT_POWER);
+                       if (err != USB_ERR_NORMAL_COMPLETION)
+                               retval = err;
+
+                       /* Re-validate if overcurrent still exists. */
+                       err = uhub_read_port_status(sc, portno);
+                       if (err != USB_ERR_NORMAL_COMPLETION)
+                               retval = err;
+                       if (sc->sc_st.port_change &
UPS_C_OVERCURRENT_INDICATOR) {
+                               DPRINTF("Overcurrent condition on port
%u.\n", portno);
+                               err = usbd_req_clear_port_feature(
+                                   udev, NULL, portno,
UHF_C_PORT_OVER_CURRENT);
+                               if (err != USB_ERR_NORMAL_COMPLETION)
+                                       retval = err;
+                       }
                }

The existing code will shut-off the USB hub port(s) right away after
encountering overcurrent and these code extensions will give chance to USB
devices by turning on the USB hub port power by calling
usbd_req_set_port_feature() with UHF_PORT_POWER argument. Turning on the
USB hub port power will verify if the current gets normalized when a USB
device is already plugged-in to a port because unlike the first time when
the USB device is inserted, there's a tendency of an abrupt current being
introduced to the system. So, when there's overcurrent situation and when
the USB device status is normal, the wPortChange value will just change
from 0x0008 (UPS_C_OVERCURRENT_INDICATOR) to 0x0001 (UPS_C_CONNECT_STATUS)
otherwise when the USB device status is not normal, it will be re-validated
for overcurrent situation thus calling again the
usbd_req_clear_port_feature() with UHF_C_PORT_OVER_CURRENT argument to sets
the ports power to shut-off.

So, based on the actual testing and logs when my Prolific PL2303 device
gets inserted to one of my RPi 3B USB port,

usb_needs_explore:
usb_bus_powerd: bus=0xffff000089394000
uhub_intr_callback:
uhub_explore: udev=0xffffa00001124000 addr=1
usb_needs_explore:
uhub_read_port_status: port 1, wPortStatus=0x0503, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_explore: udev=0xffffa000012ed000 addr=2
uhub_read_port_status: port 1, wPortStatus=0x0503, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION

uhub_read_port_status: port 2, wPortStatus=0x0000, wPortChange=0x0008,
err=USB_ERR_NORMAL_COMPLETION
uhub_explore: Overcurrent on port 2.
uhub_explore: Turn on power on port 2.

(Above 3 lines, an overcurrent is detected followed by turning on the power
on port 2 and the wPortChange=0x0008 is in UPS_C_OVERCURRENT_INDICATOR, an
overcurrent status.)

uhub_read_port_status: port 2, wPortStatus=0x0101, wPortChange=0x0001,
err=USB_ERR_NORMAL_COMPLETION

(After some time, port 2 is already having wPortChange=0x0001, it's now
getting UPS_C_CONNECT_STATUS which is in connected status. Due to this
status, the code exits and never executes the re-validation of overcurrent
code as it's no longer manifesting the overcurrent status.)

uhub_reattach_port: reattaching port 2
uhub_read_port_status: port 2, wPortStatus=0x0101, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_reattach_port: Port 2 is in Host Mode
uhub_intr_callback:
usb_needs_explore:
uhub_read_port_status: port 2, wPortStatus=0x0103, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_intr_callback:
usb_needs_explore:
usb_bus_port_set_device: bus 0xffff000089394000 devices[5] =
0xffffa00018900000

ugen1.5: <Prolific Technology Inc. USB-Serial Controller> at usbus1
uplcom0 on uhub1
uplcom0: <Prolific Technology Inc. USB-Serial Controller, class 0/0, rev
2.00/3.00, addr 5> on usbus1

(The above 3 lines give the info of my PL2303 Prolific ugen(4) and
uplcom(4) device drivers were loaded successfully. Below logs are for the
rest of my USB devices such as my keyboards and Epson printer.)

uhub_read_port_status: port 3, wPortStatus=0x0301, wPortChange=0x0001,
err=USB_ERR_NORMAL_COMPLETION
uhub_reattach_port: reattaching port 3
ugen1.6: <A4Tech USB Keyboard> at usbus1 (disconnected)
ukbd0: at uhub1, port 3, addr 6 (disconnected)
uhub_child_location: device not on hub
uhub_child_pnpinfo: device not on hub
ukbd0: detached
uhid0: at uhub1, port 3, addr 6 (disconnected)
uhub_child_location: device not on hub
uhub_child_pnpinfo: device not on hub
uhid0: detached
usb_bus_port_set_device: bus 0xffff000089394000 devices[6] = 0
uhub_read_port_status: port 3, wPortStatus=0x0301, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_reattach_port: Port 3 is in Host Mode
uhub_intr_callback:
usb_needs_explore:
uhub_reset_tt_callback: TT buffer reset
uhub_reset_tt_callback: TT buffer reset
usb_needs_explore:
uhub_intr_callback:
usb_needs_explore:
uhub_read_port_status: port 3, wPortStatus=0x0303, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
usb_bus_port_set_device: bus 0xffff000089394000 devices[6] =
0xffffa000017ab000
ugen1.6: <A4Tech USB Keyboard> at usbus1
ukbd0 on uhub1
ukbd0: <A4Tech USB Keyboard, class 0/0, rev 2.00/1.05, addr 6> on usbus1
kbd1 at ukbd0
uhid0 on uhub1
uhid0: <A4Tech USB Keyboard, class 0/0, rev 2.00/1.05, addr 6> on usbus1
uhub_read_port_status: port 4, wPortStatus=0x0101, wPortChange=0x0001,
err=USB_ERR_NORMAL_COMPLETION
uhub_reattach_port: reattaching port 4
ugen1.7: <USB Adapter USB Device> at usbus1 (disconnected)
ukbd1: at uhub1, port 4, addr 7 (disconnected)
uhub_child_location: device not on hub
uhub_child_pnpinfo: device not on hub
ukbd1: detached
usb_bus_port_set_device: bus 0xffff000089394000 devices[7] = 0
uhub_read_port_status: port 4, wPortStatus=0x0101, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_reattach_port: Port 4 is in Host Mode
uhub_read_port_status: port 4, wPortStatus=0x0103, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
usb_bus_port_set_device: bus 0xffff000089394000 devices[7] =
0xffffa00018909000
ugen1.7: <USB Adapter USB Device> at usbus1
ukbd1 on uhub1
ukbd1: <USB Adapter USB Device, class 0/0, rev 1.10/0.01, addr 7> on usbus1
kbd2 at ukbd1
uhub_read_port_status: port 5, wPortStatus=0x0103, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
usb_bus_powerd: bus=0xffff000089394000
uhub_explore: udev=0xffffa00001124000 addr=1
uhub_reset_tt_callback: TT buffer reset
uhub_read_port_status: port 1, wPortStatus=0x0503, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_reset_tt_callback: TT buffer reset
uhub_explore: udev=0xffffa000012ed000 addr=2
uhub_reset_tt_callback: TT buffer reset
uhub_read_port_status: port 1, wPortStatus=0x0503, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_read_port_status: port 2, wPortStatus=0x0103, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_read_port_status: port 3, wPortStatus=0x0303, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_read_port_status: port 4, wPortStatus=0x0103, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION
uhub_read_port_status: port 5, wPortStatus=0x0103, wPortChange=0x0000,
err=USB_ERR_NORMAL_COMPLETION

root@generic:~ # usbconfig
ugen1.1: <DWCOTG OTG Root HUB> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps)
pwr=SAVE (0mA)
ugen1.2: <vendor 0x0424 product 0x9514> at usbus1, cfg=0 md=HOST spd=HIGH
(480Mbps) pwr=SAVE (2mA)
ugen1.3: <vendor 0x0424 product 0xec00> at usbus1, cfg=0 md=HOST spd=HIGH
(480Mbps) pwr=ON (2mA)
ugen1.4: <EPSON EPSON UB-U03II> at usbus1, cfg=0 md=HOST spd=FULL (12Mbps)
pwr=ON (10mA)
ugen1.5: <Prolific Technology Inc. USB-Serial Controller> at usbus1, cfg=0
md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
ugen1.6: <A4Tech USB Keyboard> at usbus1, cfg=0 md=HOST spd=LOW (1.5Mbps)
pwr=ON (100mA)
ugen1.7: <USB Adapter USB Device> at usbus1, cfg=0 md=HOST spd=FULL
(12Mbps) pwr=ON (100mA)

With these added extensions for some days now (14-CURRENT dated April 21,
2022), so far my RPi 3B is working normally, I haven't experienced any
system crash or freeze, keyboard, printer and PL2303 Prolific devices are
working well without any problems even the USB Ethernet (ue0) is working as
well. Plugging and unplugging this PL2303 Prolific device every now and
then from each port works as expected. Doing "usbconfig reset" works
normally as performed. Lastly, this also works with my RPi 4B.

Any comments or suggestions as I am not a seasoned kernel coder :-)

Thanks,
Archimedes