Norns/Sol - MIDI disconnecting

I am using my Norns Shield with a Winterbloom Sol, which is a Eurorack powered device with a USB B fullsize port on it. Norns is sending MIDI to Sol, but after a few minutes - sometimes as little as 30 seconds - Norns no longer sends MIDI to the Sol at all. I can only get it to work by unplugging Sol and plugging it in again.

This hasn’t happened with any other devices, including Linux devices, and because the Sol is powered from Eurorack, I seriously doubt that it’s a power issue. This happens on several scripts, including Awake and my own Quintessence.

Thanks for any advice!

1 Like

hi hi!

a few quick questions:

  • any messages printing to maiden during these disconnects?
  • does the device still populate if you enter this is the command line: for i = 1,#midi.devices do print(midi.devices[i].name) end?
  • if you ssh into norns and execute dmesg, do you see a wealth of urb status -32 errors? anything else stand out? feel free to drop into a pastebin :slight_smile:

happy to help with more info!

2 Likes

Yes, there are a TON of urb status -32 messages in dmesg all for usb 1-1.1.3.

In maiden, I see:

ttyACM found, but not a crow
dev_list_add: error allocating device data

Which I assume is just Norns being confused about Sol presenting a serial interface, but maybe the second line is unrelated.

Sol does not present as a MIDI device when running the code you mentioned; I just get virtual.

It could be that Sol having a CDC interface in addition to the MIDI interface that Norns is getting confused? It’s also possible that Sol is getting some data from Norns (via CDC or MIDI) that it doesn’t know how do deal with. Does Sol’s LED start flashing when this happens?

I’m happy to help in any way I can, however, I don’t currently have a Norns to test with.

1 Like

oh! thea, totally spaced that we could ping you on this! raaaad. thank you for popping in!

from what i understand of past occurrences — typically, the onslaught of urb status -32 errors come when a device transmits a lot of data to norns but doesn’t slow the transmission rate when the norns USB hub isn’t scheduling at the same rate or after a missed USB transaction. Roli and Continuumini devices notably exhibit these troubles with norns (@ngwese has been wrasslin’ with these two for a few years now).

the ttyACM notice is normal for serial devices being connected – the device monitor is poking to determine if there’s a crow present.

hopefully this helps a bit? if you want to paste the full dmesg printout to pastebin, we can take a look!

2 Likes

Sol shouldn’t send any data back to Norns under normal operation, it’s a one-way MIDI to CV converter.

I’m wondering if matron’s probing might be kicking Sol into its REPL (the CDC device is for the CircuitPython serial console). It seems to be writing "^^i\n\0", but I’m not sure off the top of my head how that would impact a CircuitPython device.

Y’all could maybe avoid doing serial probing if you check for Crow’s USB vendor and product ID first, which seems to be 0x0483 and 0x5740 respectively. You can use udev_device_get_sysattr_value to check them:

struct udev_device* usb
            = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");

if(usb == null) return -1;

const char* vendor = udev_device_get_sysattr_value(usb, "idVendor");
if(vendor == null || strncmp(vendor, "0483") != 0)  return -1;

const char* product = udev_device_get_sysattr_value(usb, "idProduct");
if(product == null || strncmp(product, "5740") != 0)  return -1;

(If this isn’t helpful, my apologies. I should probably get a norns so I can test this all out myself. :slight_smile: )

4 Likes

thanks for the bump to fix this, i’ve been meaning to. hoping quieting the serial will fix the midi.

5 Likes

Let me know if I can help in any way.

Here’s the patch I used to solve this issue. Perhaps not the most elegant but it does work perfectly in my usage.

From 0bbfd3c6ba6755e592cf0142317ccef6086ab6d7 Mon Sep 17 00:00:00 2001
From: Leonora Tindall <nora@nora.codes>
Date: Sun, 30 May 2021 06:55:13 +0700
Subject: [PATCH] check for Crow's USB identifiers before probing

fixes a bug where CircuitPython devices would be unable to work as MIDI
devices due to probing putting them into REPL mode
---
 matron/src/device/device_monitor.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/matron/src/device/device_monitor.c b/matron/src/device/device_monitor.c
index de50a93..15e660b 100644
--- a/matron/src/device/device_monitor.c
+++ b/matron/src/device/device_monitor.c
@@ -239,6 +239,29 @@ device_t check_dev_type(struct udev_device *dev) {
             for (int i = 0; i < DEV_TYPE_COUNT_PHYSICAL; i++) {
                 const char *node_pattern = w[i].node_pattern;
                 if (node_pattern[0] && fnmatch(node_pattern, node, 0) == 0) {
+                    if strncmp(node_pattern, "crow", 4) {
+                      struct udev_device* usb
+                                    = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");
+
+                      if(usb == NULL) {
+                        fprintf(stderr, ">> ttyACM found, but couldn't determine USB ID; not a crow\n");
+                        continue;
+                      }
+
+                      const char* vendor = udev_device_get_sysattr_value(usb, "idVendor");
+                      if(vendor == NULL || strncmp(vendor, "0483", 4) != 0)  {
+                        fprintf(stderr, ">> ttyACM found, but vendor ID was %s, not 0483; not a crow\n", vendor);
+                        continue;
+                      }
+
+
+                      const char* product = udev_device_get_sysattr_value(usb, "idProduct");
+                      if(product == NULL || strncmp(product, "5740", 4) != 0) {
+                        fprintf(stderr, ">> ttyACM found, but product ID was %s, not 5740\n; not a crow", product);
+                        continue;
+                      }
+                    }
+
                     t = i;
                     break;
                 }
-- 
2.11.0
4 Likes

nice! unfortunately the PID/VID are general to STM32 devices, so this may solve your situation but the final solution will be to check the product string (which is crow: telephone line) ref

i’ll get a fix in by the next release— but if you’re hacking in the neighborhood i’d welcome a PR

2 Likes

I did something similar awhile back for Teensy based devices (CDC) - specifically the neotrellis grid. This modification checks the subsystem, product name, vendor and ignores the node_pattern.

But… isnt all this moot with PR #1358 for the new grid detection?

2 Likes

that PR as it exists assumes non-grid CDC devices are crows: it needs a few more lines and testing

2 Likes

PR is in, should be merged to main shortly

3 Likes

With today’s norns update my circuitpython HID macropad seems to work as expected with device monitor: unmatched tty device instead of showing up as crow.

I do see some errors in maiden when plugging in, and also it appears to be showing up as both MIDI and HID - I’ll need to double check my cirpy libraries on that one.

maiden output on plug-in
device monitor: unmatched tty device

failed to open hid device: (null)

dev_list_add: error allocating device data

failed to open hid device: (null)

dev_list_add: error allocating device data

failed to open hid device: (null)

dev_list_add: error allocating device data

failed to open hid device: (null)

dev_list_add: error allocating device data

failed to init libevdev (Invalid argument)

dev_list_add: error allocating device data

HID device was added: 23 OMX-10 Macropad

HID device was added: 24 OMX-10 Macropad 2

this appears to be a mouse!

HID device was added: 25 OMX-10 Macropad 3

HID device was added: 26 OMX-10 Macropad 4

this appears to be an ASCII keyboard!
1 Like

What’s output of lsusb -v for your device?

details below
(SAMD21 device running circuitpython - setup as HID keyboard, but the circuitpython bootloader has usb_midi baked in it seems)

lsusb -v
Bus 001 Device 014: ID 239a:8012  
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x239a 
  idProduct          0x8012 
  bcdDevice            1.00
  iManufacturer           2 
  iProduct                3 
  iSerial                 1 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          218
    bNumInterfaces          6
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       0 None
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      0 None
      iInterface              4 
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x01
          call management
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              16
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 
      iInterface              5 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     80 Bulk-Only
      iInterface              6 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              7 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     195
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               8
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x05  EP 5 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               8
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface             11 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength            9
        bInCollection           1
        baInterfaceNr( 0)       5
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        5
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      3 MIDI Streaming
      bInterfaceProtocol      0 
      iInterface             10 
      MIDIStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength           37
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 1
        iJack                   8 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 2
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 3
        bNrInputPins            1
        baSourceID( 0)          2
        BaSourcePin( 0)         1
        iJack                   9 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                 4
        bNrInputPins            1
        baSourceID( 0)          1
        BaSourcePin( 0)         1
        iJack                   0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x07  EP 7 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       3

yep that’s a bunch of endpoints all right.

that list of failed to open hid device: (null) is my fault, i see it. it’s benign but we’ll patch it out.

nothing else jumps out as particularly weird:

the “Couldn’t open device…” is pretty normal, as is the “unavailable” HID descriptors. (there are ways around this but not worth getting into)

“appears to be a mouse/keyboard” means that libevdev decided that your device will emit the REL_X/REL_Y event codes, and the codes corresponding to the full(-ish) range of ASCII character keys, respectively.

(how does libevdev do this? i do not exactly know… maybe it fetches those descriptors through kernel calls… or maybe not.)

2 Likes