Last active
March 18, 2025 01:02
-
-
Save todbot/07a2ef16ec9ee83eb8980f8a128d660b to your computer and use it in GitHub Desktop.
demonstrate odd usb.core.USBError with max3421e, circuitpython
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # demonstrate odd usb.core.USBError with max3421e | |
| # requires "adafruit_usb_host_midi_todbot" below, which adds timeout on read()s | |
| # 12 May 2024 - @todbot | |
| import displayio | |
| displayio.release_displays() | |
| import time | |
| import board | |
| import usb | |
| import max3421e | |
| import adafruit_usb_host_midi_todbot as adafruit_usb_host_midi | |
| spi = board.SPI() | |
| cs = board.D10 | |
| irq = board.D9 | |
| host_chip = max3421e.Max3421E(spi, chip_select=cs, irq=irq) | |
| host_timeout = 0.001 | |
| while True: | |
| midi_usb_device = None | |
| for device in usb.core.find(find_all=True): | |
| try: | |
| midi_usb_device = adafruit_usb_host_midi.MIDI(device, host_timeout) | |
| print("Found vid/pid %04x/%04x" % (device.idVendor, device.idProduct), | |
| device.manufacturer, device.product) | |
| except ValueError: | |
| print("bad device:", device) | |
| while True: | |
| print(time.monotonic(), "UI task, should print continuously") | |
| time.sleep(0.1) | |
| b = midi_usb_device.read(1) | |
| if b: | |
| print("b:",b) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries | |
| # | |
| # SPDX-License-Identifier: MIT | |
| """ | |
| `adafruit_usb_host_midi` | |
| ================================================================================ | |
| CircuitPython USB host driver for MIDI devices | |
| * Author(s): Scott Shawcroft | |
| """ | |
| import usb.core | |
| import adafruit_usb_host_descriptors | |
| __version__ = "0.0.0+auto.0" | |
| __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_USB_Host_MIDI.git" | |
| DIR_IN = 0x80 | |
| class MIDI: | |
| def __init__(self, device, timeout=None): | |
| self.interface_number = 0 | |
| self.in_ep = 0 | |
| self.out_ep = 0 | |
| self.device = device | |
| self.timeout_ms = round(timeout * 1000) if timeout else 0 | |
| self.buf = bytearray(64) | |
| self.start = 0 | |
| self._remaining = 0 | |
| config_descriptor = adafruit_usb_host_descriptors.get_configuration_descriptor( | |
| device, 0 | |
| ) | |
| i = 0 | |
| midi_interface = False | |
| while i < len(config_descriptor): | |
| descriptor_len = config_descriptor[i] | |
| descriptor_type = config_descriptor[i + 1] | |
| if descriptor_type == adafruit_usb_host_descriptors.DESC_CONFIGURATION: | |
| config_value = config_descriptor[i + 5] | |
| elif descriptor_type == adafruit_usb_host_descriptors.DESC_INTERFACE: | |
| interface_number = config_descriptor[i + 2] | |
| interface_class = config_descriptor[i + 5] | |
| interface_subclass = config_descriptor[i + 6] | |
| midi_interface = interface_class == 0x1 and interface_subclass == 0x3 | |
| if midi_interface: | |
| self.interface_number= interface_number | |
| elif descriptor_type == adafruit_usb_host_descriptors.DESC_ENDPOINT: | |
| endpoint_address = config_descriptor[i + 2] | |
| if endpoint_address & DIR_IN: | |
| if midi_interface: | |
| self.in_ep = endpoint_address | |
| else: | |
| if midi_interface: | |
| self.out_ep = endpoint_address | |
| i += descriptor_len | |
| device.set_configuration() | |
| device.detach_kernel_driver(self.interface_number) | |
| def read(self, size): | |
| if self._remaining == 0: | |
| try: | |
| n = self.device.read(self.in_ep, self.buf, self.timeout_ms) | |
| self._remaining = n - 1 | |
| self.start = 1 | |
| except usb.core.USBTimeoutError as e: | |
| print("timeout error:",e) | |
| pass | |
| size = min(size, self._remaining) | |
| b = self.buf[self.start:self.start + size] | |
| self.start += size | |
| self._remaining -= size | |
| return b | |
| def readinto(self, buf): | |
| b = self.read(len(buf)) | |
| n = len(b) | |
| if n: | |
| buf[:] = b | |
| return n | |
| def __repr__(self): | |
| # also idProduct/idVendor for vid/pid | |
| return "MIDI Device " + str(self.device.manufacturer) + "/" + str(self.device.product) |
Author
Not (necessarily) related, but the code starting at line 41 in your adafruit_usb_host_midi_todbot.py
while i < len(config_descriptor):
descriptor_len = config_descriptor[i]
...
i += descriptor_len
is problematic when the descriptor is returned with nulls (zeros) as I have seen. Yes, I know, it shouldn't be all null, but it sometimes is - and then the above code loops forever (cuz the len is zero and it gets stuck there).
Just sayin'.
And this code is still in the library itself. :-/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
But when run, this code sees one
usb.core.USBTimeoutErrorand then errors out with ausb.core.USBError: