CapableRobot / CapableRobot_USBHub_Driver

https://www.crowdsupply.com/capable-robot-components/programmable-usb-hub
MIT License
20 stars 10 forks source link

hub power control failure #2

Closed xchen10gh closed 2 years ago

xchen10gh commented 3 years ago

Hi, After repeated ON/OFF cycles testing, the hub failed to communicate via I2C interface. This happens about 15-20 cycles and on two different Hubs. here is the backtrace: [root@linux] python3 status.py Traceback (most recent call last): File "/opt/CapableRobot_USBHub_Driver-0.2.8/capablerobot_usbhub/i2c.py", line 147, in read_i2c_block_data length = self.hub.handle.ctrl_transfer(REQ_OUT+1, self.CMD_I2C_WRITE, cmd, 0, [register], timeout=self.timeout) File "/usr/local/lib/python3.6/site-packages/pyusb-1.1.0-py3.6.egg/usb/core.py", line 1077, in ctrl_transfer File "/usr/local/lib/python3.6/site-packages/pyusb-1.1.0-py3.6.egg/usb/backend/libusb1.py", line 901, in ctrl_transfer File "/usr/local/lib/python3.6/site-packages/pyusb-1.1.0-py3.6.egg/usb/backend/libusb1.py", line 602, in _check usb.core.USBTimeoutError: [Errno 110] Operation timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "status.py", line 18, in hub = capablerobot_usbhub.USBHub() File "/opt/CapableRobot_USBHub_Driver-0.2.8/capablerobot_usbhub/main.py", line 86, in init self.attach(vendor, product) File "/opt/CapableRobot_USBHub_Driver-0.2.8/capablerobot_usbhub/main.py", line 184, in attach self.devices[device.key] = device File "/opt/CapableRobot_USBHub_Driver-0.2.8/capablerobot_usbhub/device.py", line 183, in key return self.serial[-self.main.KEY_LENGTH:] File "/opt/CapableRobot_USBHub_Driver-0.2.8/capablerobot_usbhub/device.py", line 171, in serial data = self.i2c.read_i2c_block_data(EEPROM_I2C_ADDR, EEPROM_EUI_ADDR, EEPROM_EUI_BYTES) File "/opt/CapableRobot_USBHub_Driver-0.2.8/capablerobot_usbhub/i2c.py", line 157, in read_i2c_block_data raise OSError('Unable to perform sucessful I2C read block data') OSError: Unable to perform sucessful I2C read block data [root@linux]

Removing the power adaptor and resetting the hub would bring it back to life again. here is more info about the hub: [root@linux]]# usbhub id

Revision / Serial : CRZRYC / 801F12FFFE3CD434 [root@linux]#

osterwood commented 3 years ago

I am sorry for the delay in replying to you -- my notifications were getting buried in a spam filter.

Does the I2C error occur immediately after a power cycle, or does it work for a while and then fail?

If it happens the first time you attempt to talk to the Hub after a power cycle, then this is like a fix for your issue:

https://github.com/CapableRobot/CapableRobot_USBHub_Firmware/commit/ff6286b40f435d46a75fb23fb3ab5a546ac54211

osterwood commented 3 years ago

Closing this issue as the creator seems inactive.

d-c-d commented 2 years ago

I get a similar error message "'Unable to perform sucessful I2C read block data" when running a loop like this while true ; do for f in on off ; do usbhub --verbose --disable-i2c data state --port 1 --$f ; sleep 1 ; done ; done while communicating to the host port The device under test is self-powered, so I'm just toggling data lines. Also - recover requires cycling power to the hub Haven't looked at USB bus traffic yet but could with ellisys explorer 200 Will look at putting the loop into code.py

d-c-d commented 2 years ago

@osterwood, I think it is noteworthy, that disconning the usb cable from the host connector, connecting it to the mcu port, interrupting to the REPL, and observing the soft reset, then returning cable back to the host connection did NOT help the recovery process

cycling power brought immediate recovery

osterwood commented 2 years ago

@d-c-d Thanks for brining this issue up. The I2C interface of the USB4715 is not particularly robust -- you'll notice several of closed issues in the firmware repo are related to various problems (hanging after cold start, errors trying to read EEPROM data, power, etc).

Finding the root cause of this issue has plagued me -- it seems to be related to particular units and / or the physical environment they are running in. I've been working on a "indirect" method of host control of the various I2C devices inside the Hub, so that the I2C controller of the USB4715 can just sit idle.

I'm happy to say, your report here got me to push this code over the line and it's ready for testing.

Prior to this, functions which the USB4715 could directly control (like controlling power state and reading link speed) did not touch the I2C bus, but many other functions did (like data disconnect control via a I2C GPIO expander, power measurements, and setting per-port power limits).

This new "indirect" link uses GPIO registers of the USB4715 which don't have any physical pin mapping to act as a message postbox between the Host and the MCU. This comm-link has been in place for a while, but had only been used to set configuration details on device. With these two commits it now allows for:

https://github.com/CapableRobot/CapableRobot_USBHub_Firmware/commit/ec66a90dfc572a701b62129fdfa1774e5d732c8e

https://github.com/CapableRobot/CapableRobot_USBHub_Driver/commit/1bcebe81fbd3ebd4a31e2e06e3de19e61b9affdc

I've not pushed this as a new release (yet), so you'll have to install on the host-side via this command: pip install git+https://github.com/CapableRobot/CapableRobot_USBHub_Driver --upgrade

On the firmware side, you can download that git repo, make sure the MCU drive is mounted, and then run ./usbhub_firmware.py firmware /PATH_TO_CIRCUITPY/

I'd love your feedback on these changes and let know if you run into any issues with the update (on host and on MCU).

osterwood commented 2 years ago

@d-c-d Did this (unreleased) indirect method of Hub control work for you?

NoahAndrews commented 2 years ago

I just got my hub, and 100% of the time, it would give me the I2C error. I just tried installing the unreleased firmware, and now it doesn't show up as a USB hub anymore, the Host LED doesn't turn on, and usbhub now reports that "No USB Hub was found" (yes, I updated to the pre-release of the driver too). Reverting back to the previous firmware (by checking out the previous commit, deleting the recently modified .py files on the CIRCUITPY drive, and then re-installing the firmware) did not fix it.

What steps should I take to figure out what's going on?

osterwood commented 2 years ago

Noah,

I am sorry to hear of your various troubles with the Hub. The head commit of the firmware repo should not prevent the Hub from being configured correctly and being detected by the connected host (regardless of the host-side driver version).

Can you connect a USB cable to the MCU port and enter into the CircuitPython console? There are useful debug messages there and if the firmware enters any errors, they will be reported. Once you connect, you may have to use CTRL-C and CTRL-D keystrokes to cause the firmware to reset (as messages which have already been printed are not visible to you).

Also, what version of the Hub do you have? E.g. does the MPN on the bottom end with ".1", ".2", or it is just CRZRYC?

NoahAndrews commented 2 years ago

No worries, we'll get it figured out.

I have the ".2" version. Here's the output when I delete and re-deploy the firmware using py usbhub_firmware.py firmware D:\:

soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

code.py output:
Circuitpython upgrade complete

Code stopped by auto-reload.
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

code.py output:
Circuitpython upgrade complete

My boot_out.txt file says Adafruit CircuitPython 6.3.0-dirty on 2021-12-02; Capable Robot Programmable USB Hub with samd51g19, so I think it's still running the correct version of CircuitPython (though I did mistakenly run py usbhub_firmware.py circuitpython at one point).

osterwood commented 2 years ago

Thanks for the debug output.

It looks like the firmware update process didn't complete as expected -- that output shows you are still running the "stub" firmware-update code.py (embedded in usbhub_firmware.py) -- instead of the code.py which causes the Hub to be configured.

I think all you need to do copy the real code.py from your local firmware download and over-write the code.py file on the MCU "drive".

I will look into why the firmware update process either didn't restore the original code.py file after the firmware update was complete. Does your firmware drive have a code.py.bkp file on it?

osterwood commented 2 years ago

One option to manually update to the head firmware is to download from GitHub (or checkout that commit on your local download) and copy the code.py file and the "lib" folder onto the MCU drive. That is all the "update_firmware.py" script does.

It is important that the code.py file revision match the revision of the lib folder. E.g. both should be the JAN 25 commit or both the previous commit -- mismatching would likely introduce errors.

NoahAndrews commented 2 years ago

I do have a code.py.bkp file.

Part of the issue may have been that I was forgetting to delete the code.py file before running the update_firmware script, and it was getting skipped as a result. Deleting it and re-running the script made the hub boot up correctly.

Unfortunately, I'm still getting the original error with the pre-release firmware and driver. However, I just noticed that there's a different error that occurs first:

> usbhub id
Traceback (most recent call last):
  File "c:\python38\lib\site-packages\capablerobot_usbhub\i2c.py", line 164, in read_i2c_block_data
    length = self.hub.handle.ctrl_transfer(REQ_OUT+1, self.CMD_I2C_WRITE, cmd, 0, [register], timeout=self.timeout)
  File "c:\python38\lib\site-packages\usb\core.py", line 1071, in ctrl_transfer
    self._ctx.managed_open()
  File "c:\python38\lib\site-packages\usb\core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "c:\python38\lib\site-packages\usb\core.py", line 131, in managed_open
    self.handle = self.backend.open_device(self.dev)
  File "c:\python38\lib\site-packages\usb\backend\libusb1.py", line 804, in open_device
    return _DeviceHandle(dev)
  File "c:\python38\lib\site-packages\usb\backend\libusb1.py", line 652, in __init__
    _check(_lib.libusb_open(self.devid, byref(self.handle)))
  File "c:\python38\lib\site-packages\usb\backend\libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 2] Entity not found

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Python38\Scripts\usbhub.exe\__main__.py", line 7, in <module>
  File "c:\python38\lib\site-packages\capablerobot_usbhub\console.py", line 239, in main
    cli()
  File "c:\python38\lib\site-packages\click\core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "c:\python38\lib\site-packages\click\core.py", line 782, in main
    rv = self.invoke(ctx)
  File "c:\python38\lib\site-packages\click\core.py", line 1256, in invoke
    Command.invoke(self, ctx)
  File "c:\python38\lib\site-packages\click\core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python38\lib\site-packages\click\core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "c:\python38\lib\site-packages\capablerobot_usbhub\console.py", line 74, in cli
    hub = USBHub(device=dict(disable_i2c=disable_i2c))
  File "c:\python38\lib\site-packages\capablerobot_usbhub\main.py", line 88, in __init__
    self.attach(vendor, product)
  File "c:\python38\lib\site-packages\capablerobot_usbhub\main.py", line 188, in attach
    self.devices[device.key] = device
  File "c:\python38\lib\site-packages\capablerobot_usbhub\device.py", line 211, in key
    return self.serial[-self.main.KEY_LENGTH:]
  File "c:\python38\lib\site-packages\capablerobot_usbhub\device.py", line 192, in serial
    data = self.i2c.read_i2c_block_data(EEPROM_I2C_ADDR, EEPROM_EUI_ADDR, EEPROM_EUI_BYTES)
  File "c:\python38\lib\site-packages\capablerobot_usbhub\i2c.py", line 176, in read_i2c_block_data
    raise OSError('Unable to perform sucessful I2C read block data')
OSError: Unable to perform sucessful I2C read block data
osterwood commented 2 years ago

Yeah - the firmware update script does need some work.

Do you get that error if you run with the "--disable-i2c" flag set? Even with the pre-release host-side software, the default behavior is to use I2C.

NoahAndrews commented 2 years ago

I get a similar but different error

> usbhub --disable-i2c id

Hub Key  : 1-28 (0)
MPN      : None
Traceback (most recent call last):
  File "c:\python38\lib\runpy.py", line 193, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\python38\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Python38\Scripts\usbhub.exe\__main__.py", line 7, in <module>
  File "c:\python38\lib\site-packages\capablerobot_usbhub\console.py", line 239, in main
    cli()
  File "c:\python38\lib\site-packages\click\core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "c:\python38\lib\site-packages\click\core.py", line 782, in main
    rv = self.invoke(ctx)
  File "c:\python38\lib\site-packages\click\core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python38\lib\site-packages\click\core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python38\lib\site-packages\click\core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "c:\python38\lib\site-packages\capablerobot_usbhub\console.py", line 111, in id
    print("Revision : {}".format(device.revision))
  File "c:\python38\lib\site-packages\capablerobot_usbhub\device.py", line 252, in revision
    data, _ = self.register_read(addr=0x3004, length=2)
  File "c:\python38\lib\site-packages\capablerobot_usbhub\device.py", line 117, in register_read
    data = list(self.handle.ctrl_transfer(REQ_IN, self.CMD_REG_READ, value, index, length))
  File "c:\python38\lib\site-packages\usb\core.py", line 1071, in ctrl_transfer
    self._ctx.managed_open()
  File "c:\python38\lib\site-packages\usb\core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "c:\python38\lib\site-packages\usb\core.py", line 131, in managed_open
    self.handle = self.backend.open_device(self.dev)
  File "c:\python38\lib\site-packages\usb\backend\libusb1.py", line 804, in open_device
    return _DeviceHandle(dev)
  File "c:\python38\lib\site-packages\usb\backend\libusb1.py", line 652, in __init__
    _check(_lib.libusb_open(self.devid, byref(self.handle)))
  File "c:\python38\lib\site-packages\usb\backend\libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 2] Entity not found
osterwood commented 2 years ago

That is progress.

It look like reading the device revisions (register 0x3004) is failing due to the the device handle not existing -- but I might be reading that stack trace a bit incorrectly (on a plane which is about to pull back from the gate).

I will be able to look into this in more detail tomorrow morning.

Have you done the register step to assign the device to the correct backend?

pip install capablerobot_usbregister
usbregister device usbhub
NoahAndrews commented 2 years ago

Have a good flight!

I have done that, yes. Here's the proof in Zadig: image

Side note, shouldn't the USB registration using libwdi be unnecessary, since the device supports WCID?


Hold on. usbregister attempts to assign the libusbk driver to the device, but apparently that isn't sticking (maybe thanks to WCID?)

NoahAndrews commented 2 years ago

Well, that was indeed the problem. When I used Zadig to switch the device to the libusbK driver, usbhub id worked, with or without the --disable-i2c option.

Shouldn't the device request the libusbK driver using WCID? (screenshot taken from https://github.com/pbatard/libwdi/wiki/WCID-Devices#microsoft-compatible-id-feature-descriptor) image

grvvy commented 2 years ago

I've encountered the same issue on my setup. I have two hubs of different revisions, both of which I have updated the firmware on with the method outlined above in this thread. I haven't tried usbregister yet, is that for Linux hosts? Currently running this on Ubuntu 20.04.

gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ pip install git+https://github.com/CapableRobot/CapableRobot_USBHub_Driver --upgrade
Collecting git+https://github.com/CapableRobot/CapableRobot_USBHub_Driver
  Cloning https://github.com/CapableRobot/CapableRobot_USBHub_Driver to /tmp/pip-req-build-kz0x0fye
  Running command git clone -q https://github.com/CapableRobot/CapableRobot_USBHub_Driver /tmp/pip-req-build-kz0x0fye
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Requirement already satisfied, skipping upgrade: pyusb<2.0.0,>=1.0.2 in /home/gsgadmin/.local/lib/python3.8/site-packages (from capablerobot-usbhub==0.5.0) (1.2.1)
Requirement already satisfied, skipping upgrade: click<8.0,>=7.0 in /usr/lib/python3/dist-packages (from capablerobot-usbhub==0.5.0) (7.0)
Requirement already satisfied, skipping upgrade: construct<3.0.0,>=2.9.51 in /home/gsgadmin/.local/lib/python3.8/site-packages (from capablerobot-usbhub==0.5.0) (2.10.68)
Requirement already satisfied, skipping upgrade: pyyaml<6.0,>=5.3 in /usr/lib/python3/dist-packages (from capablerobot-usbhub==0.5.0) (5.3.1)
Building wheels for collected packages: capablerobot-usbhub
  Building wheel for capablerobot-usbhub (PEP 517) ... done
  Created wheel for capablerobot-usbhub: filename=capablerobot_usbhub-0.5.0-py3-none-any.whl size=595499 sha256=0a31f9936a02aa21518fe8a91a11b9396cacf3c26274dc255f366aff020cd78b
  Stored in directory: /tmp/pip-ephem-wheel-cache-wue96tlb/wheels/b7/dc/4d/3c0a501ef644e6910208ee1c1a917474d91e9b37798a9c420f
Successfully built capablerobot-usbhub
Installing collected packages: capablerobot-usbhub
  Attempting uninstall: capablerobot-usbhub
    Found existing installation: capablerobot-usbhub 0.5.0
    Uninstalling capablerobot-usbhub-0.5.0:
      Successfully uninstalled capablerobot-usbhub-0.5.0
Successfully installed capablerobot-usbhub-0.5.0
gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ 
gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ ./usbhub_firmware.py firmware --force /media/gsgadmin/CIRCUITPY
Updating : lib/capablerobot_ucs2113.py
Updating : lib/capablerobot_eeprom.py
Updating : lib/capablerobot_usbhub.py
Updating : lib/capablerobot_tlc59116.py
Updating : lib/adafruit_bus_device/i2c_device.py
Updating : lib/adafruit_bus_device/spi_device.py
Updating : lib/adafruit_bus_device/__init__.py
Updating : code.py from code.py
gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ usbhub id
Hub Key  : D9D1 (0)
MPN      : CRZRYC
Revision : 1
Serial   : 801F12FFFE3CD9D1
USB Path : 1-92

gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ ./usbhub_firmware.py firmware --force /media/gsgadmin/CIRCUITPY
Updating : lib/capablerobot_ucs2113.py
Updating : lib/capablerobot_eeprom.py
Updating : lib/capablerobot_usbhub.py
Updating : lib/capablerobot_tlc59116.py
Updating : lib/adafruit_bus_device/i2c_device.py
Updating : lib/adafruit_bus_device/spi_device.py
Updating : lib/adafruit_bus_device/__init__.py
Updating : code.py from code.py
gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ usbhub id
Hub Key  : D9D1 (0)
MPN      : CRZRYC
Revision : 1
Serial   : 801F12FFFE3CD9D1
USB Path : 1-97

Hub Key  : 624C (1)
MPN      : CRZRYC
Revision : 2
Serial   : 682719FFFEA6624C
USB Path : 1-95

gsgadmin@testserver:~/CapableRobot_USBHub_Firmware$ cd ../greatfet/ci-scripts/
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --hub D9D1 power state
      Port 1       Port 2       Port 3       Port 4
          on           on           on           on
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --hub 624C power state
      Port 1       Port 2       Port 3       Port 4
          on           on           on           on
gsgadmin@testserver:~/greatfet/ci-scripts$ ./configure-hubs.sh --off
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --hub D9D1 power state
      Port 1       Port 2       Port 3       Port 4
         off          off          off          off
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --hub 624C power state
      Port 1       Port 2       Port 3       Port 4
         off          off          off          off
gsgadmin@testserver:~/greatfet/ci-scripts$ ./configure-hubs.sh --on
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --hub D9D1 power state
      Port 1       Port 2       Port 3       Port 4
          on           on           on           on
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --hub 624C power state
      Port 1       Port 2       Port 3       Port 4
          on           on           on           on
gsgadmin@testserver:~/greatfet/ci-scripts$ ./configure-hubs.sh --reset
Traceback (most recent call last):
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/i2c.py", line 133, in read_bytes
    data = list(self.hub.handle.ctrl_transfer(REQ_IN+1, self.CMD_I2C_READ, cmd, 0, number, timeout=self.timeout))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/core.py", line 1082, in ctrl_transfer
    ret = self._ctx.backend.ctrl_transfer(
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
    ret = _check(self.lib.libusb_control_transfer(
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/backend/libusb1.py", line 602, in _check
    raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBTimeoutError: [Errno 110] Operation timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/gsgadmin/.local/bin/usbhub", line 8, in <module>
    sys.exit(main())
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/console.py", line 237, in main
    cli()
  File "/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1134, in invoke
    Command.invoke(self, ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/console.py", line 74, in cli
    hub = USBHub(device=dict(disable_i2c=disable_i2c))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/main.py", line 88, in __init__
    self.attach(vendor, product)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/main.py", line 188, in attach
    self.devices[device.key] = device
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/device.py", line 212, in key
    return self.serial[-self.main.KEY_LENGTH:]
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/device.py", line 193, in serial
    data = self.i2c.read_i2c_block_data(EEPROM_I2C_ADDR, EEPROM_EUI_ADDR, EEPROM_EUI_BYTES)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/i2c.py", line 186, in read_i2c_block_data
    return self.read_bytes(addr, number, try_lock=False)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/i2c.py", line 140, in read_bytes
    raise OSError('Unable to perform sucessful I2C read')
OSError: Unable to perform sucessful I2C read
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub id
Traceback (most recent call last):
  File "/home/gsgadmin/.local/bin/usbhub", line 8, in <module>
    sys.exit(main())
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/console.py", line 237, in main
    cli()
  File "/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1134, in invoke
    Command.invoke(self, ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/console.py", line 74, in cli
    hub = USBHub(device=dict(disable_i2c=disable_i2c))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/main.py", line 88, in __init__
    self.attach(vendor, product)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/main.py", line 187, in attach
    device = USBHubDevice(weakref.proxy(self), handle, **self.device_kwargs)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/device.py", line 94, in __init__
    logging.debug("Firmware version {} running on {}".format(self.config.version, self.config.circuitpython_version))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/config.py", line 88, in version
    buf, _ = self.hub.register_read(addr=_MEM_IDENT, length=4)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/device.py", line 118, in register_read
    data = list(self.handle.ctrl_transfer(REQ_IN, self.CMD_REG_READ, value, index, length))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/core.py", line 1082, in ctrl_transfer
    ret = self._ctx.backend.ctrl_transfer(
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
    ret = _check(self.lib.libusb_control_transfer(
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/backend/libusb1.py", line 602, in _check
    raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBTimeoutError: [Errno 110] Operation timed out
gsgadmin@testserver:~/greatfet/ci-scripts$ usbhub --disable-i2c id
Traceback (most recent call last):
  File "/home/gsgadmin/.local/bin/usbhub", line 8, in <module>
    sys.exit(main())
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/console.py", line 237, in main
    cli()
  File "/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1134, in invoke
    Command.invoke(self, ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/console.py", line 74, in cli
    hub = USBHub(device=dict(disable_i2c=disable_i2c))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/main.py", line 88, in __init__
    self.attach(vendor, product)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/main.py", line 187, in attach
    device = USBHubDevice(weakref.proxy(self), handle, **self.device_kwargs)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/device.py", line 94, in __init__
    logging.debug("Firmware version {} running on {}".format(self.config.version, self.config.circuitpython_version))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/config.py", line 88, in version
    buf, _ = self.hub.register_read(addr=_MEM_IDENT, length=4)
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/capablerobot_usbhub/device.py", line 118, in register_read
    data = list(self.handle.ctrl_transfer(REQ_IN, self.CMD_REG_READ, value, index, length))
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/core.py", line 1082, in ctrl_transfer
    ret = self._ctx.backend.ctrl_transfer(
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/backend/libusb1.py", line 893, in ctrl_transfer
    ret = _check(self.lib.libusb_control_transfer(
  File "/home/gsgadmin/.local/lib/python3.8/site-packages/usb/backend/libusb1.py", line 602, in _check
    raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBTimeoutError: [Errno 110] Operation timed out

Sorry it's such a huge paste, this is what the script I'm using to control the ports looks like

#!/bin/bash
usbhub --hub D9D1 power state --port 1 $1
usbhub --hub D9D1 power state --port 2 $1
usbhub --hub D9D1 power state --port 3 $1
usbhub --hub D9D1 power state --port 4 $1
usbhub --hub 624C power state --port 1 $1
usbhub --hub 624C power state --port 2 $1
usbhub --hub 624C power state --port 3 $1
usbhub --hub 624C power state --port 4 $1
osterwood commented 2 years ago

@grvvy Few notes & thoughts for you:

#!/bin/bash
usbhub --disable-i2c --hub D9D1 power state --port 1,2,3,4 $1
usbhub --disable-i2c --hub 624C power state --port 1,2,3,4 $1
grvvy commented 2 years ago

Hi @osterwood, thanks for the response!

The problem with using --disable-i2c in this scenario is that the hub key changes:

$ usbhub --disable-i2c id
Hub Key  : 1-106 (0)
MPN      : None
Revision : 1
Serial   : None
USB Path : 1-106

Hub Key  : 1-109 (1)
MPN      : None
Revision : 2
Serial   : None
USB Path : 1-109

Is there a way to make sure one of the hub's keys is always 0 and the other's is always 1?

osterwood commented 2 years ago

You can use usb path as the hub key on the command line interface (e.g. 1-106 or 1-109), but I believe those increment if the Hub were to be unplugged or power cycled (and reset upon boot). Not ideal at all.

So, I just wrote and pushed a commit (https://github.com/CapableRobot/CapableRobot_USBHub_Driver/commit/8fb6c78b7994c8211975710f60490c92b7b6d88c) which extracts MPN, serial, and revision from the customized USB descriptor -- before falling back to using I2C (unless the --disable-i2c flag has been set).

Note this will need recent USB Hub firmware, as older firmware did not set the product description descriptor. Please try re-installing the host-side driver via git and let me know how this new version works out.

» python capablerobot_usbhub/console.py --disable-i2c id
Hub Key  : 9FCF (0)
MPN      : CRZRYC
Revision : 1
Serial   : 3C9FCF
USB Path : 8-12

Hub Key  : B6B1 (1)
MPN      : CRR3C4
Revision : 0
Serial   : 36B6B1
USB Path : 8-5
grvvy commented 2 years ago

This is working great! Thanks for the quick patch :beers:

osterwood commented 2 years ago

Glad to hear! Let me know if you run into any other issues.

AlexKlimaj commented 1 year ago

Hi Chris, I am running into this issue on a Hub I recently received. It looks like there is a patch but it has not been released to pip?