Skip to content

Adafruit_CircuitPython_USB_Host_MIDI: __init__ fails on bad adafruit_usb_host_descriptors result #9930

Open
@RobCranfill

Description

@RobCranfill

CircuitPython version

Adafruit CircuitPython 9.2.1 on 2024-11-20; Adafruit Feather RP2040 USB Host with rp2040

Code/REPL

# A simplified (no UART output) version of 
#   examples/usb_host_midi_simpletest_rp2040usbfeather.py

# SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
# pylint: disable=unused-import


import usb.core
import adafruit_midi
# from adafruit_midi.note_on import NoteOn
# from adafruit_midi.note_off import NoteOff
# from adafruit_midi.control_change import ControlChange
# from adafruit_midi.pitch_bend import PitchBend
import adafruit_usb_host_midi


print("Looking for midi device")
raw_midi = None
while raw_midi is None:
    for device in usb.core.find(find_all=True):
        try:
            raw_midi = adafruit_usb_host_midi.MIDI(device)
            print("Found", hex(device.idVendor), hex(device.idProduct))
        except ValueError:
            continue

# output not needed for this demo/test
# # This setup is to use TX pin on Feather RP2040 with USB Type A Host as MIDI out
# # You must wire up the needed resistors and jack yourself
# # This will forward all MIDI messages from the device to hardware uart MIDI
# uart = busio.UART(rx=board.RX, tx=board.TX, baudrate=31250, timeout=0.001)

midi_device = adafruit_midi.MIDI(midi_in=raw_midi, in_channel=0)
# midi_uart = adafruit_midi.MIDI(midi_out=uart, midi_in=uart)


while True:
    msg = midi_device.receive()
    if msg:
        print("midi msg:", msg)
        # midi_uart.send(msg)

Behavior

Run the code with a Roland FP30X MIDI keyboard attached and you get the following output, but which never returns from the constructor to adafruit_usb_host_midi.MIDI:

soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Looking for midi device
Found 0x582 0x29c

CTRL-C gets the following:

Traceback (most recent call last):
File "code.py", line 7, in
File "usb_host_midi_simpletest_rp2040usbfeather.py", line 40, in
File "adafruit_midi/init.py", line 128, in receive
File "/lib/adafruit_usb_host_midi.py", line 99, in read
KeyboardInterrupt:

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

Description

This error happens intermittently, along with succeeding perhaps 50% of the time. (It also gets a "usb.core.USBError: No configuration set" error, which is something else but perhaps a clue as to why nulls are being returned that cause the problem at hand.)

Here are 3 runs:

Success:

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Looking for midi device
Found 0x582 0x29c
midi msg: NoteOn(note=84, velocity=43, channel=0)
midi msg: NoteOn(note=86, velocity=42, channel=0)
...

Failure with usb**.core.USBError: No configuration set** error:

code.py output:
Looking for midi device
Found 0x582 0x29c
Traceback (most recent call last):
File "code.py", line 7, in
File "usb_host_midi_simpletest_rp2040usbfeather.py", line 40, in
File "adafruit_midi/init.py", line 128, in receive
File "/lib/adafruit_usb_host_midi.py", line 99, in read
usb.core.USBError: No configuration set

Code done running.

Failure but with my added null catcher:

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Looking for midi device
Traceback (most recent call last):
File "code.py", line 7, in
File "usb_host_midi_simpletest_rp2040usbfeather.py", line 24, in
File "/lib/adafruit_usb_host_midi.py", line 55, in init
Exception: adafruit_usb_host_descriptors has a null!

Code done running.

Additional information

If you make the following change to adafruit_usb_host_midi.py (starting at line 53, duplicated here)

            descriptor_len = config_descriptor[i]
            if descriptor_len == 0:                                             # cran
                raise Exception("adafruit_usb_host_descriptors has a null!")    # cran

you will see that previously the constructor got stuck in an infinite loop because config_descriptor[0] (as well as all the others!) has a value of 0, and the code
i += descriptor_len
at the end of the loop here never increments.

I'm not sure what the best way to handle this null value from config_descriptor is, but this works for me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugrp2Both RP2 microcontrollersusb

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions