Skip to content

Instantly share code, notes, and snippets.

@todbot
Last active May 12, 2024 20:40
Show Gist options
  • Save todbot/07a2ef16ec9ee83eb8980f8a128d660b to your computer and use it in GitHub Desktop.
Save todbot/07a2ef16ec9ee83eb8980f8a128d660b to your computer and use it in GitHub Desktop.
demonstrate odd usb.core.USBError with max3421e, circuitpython
# 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)
# 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)
@todbot
Copy link
Author

todbot commented May 12, 2024

But when run, this code sees one usb.core.USBTimeoutError and then errors out with a usb.core.USBError:

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Found vid/pid 1c75/0288 Arturia Arturia KeyStep 32
705.569 UI task, should print continuously
timeout error: 
705.683 UI task, should print continuously
Traceback (most recent call last):
  File "code.py", line 35, in <module>
  File "adafruit_usb_host_midi_todbot.py", line 70, in read
usb.core.USBError: 

Code done running.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment