MIDI over USB middleman (MIDI message sniffing)

Status
Not open for further replies.

Tuoni

New member
G'day folks,

I don't have any source code yet, all I have is a vague idea :)

I'd appreciate some advice here. I've read today a good many posts and articles that seem to get close but not exactly to what I'm looking for so if you have time to read the full problem I'd be grateful.

TLDR; I want to 'sniff' some MIDI message passing between a PC application and piece of hardware, let's call it the controller for now.

The application (written by the manufacturer of the controller) recognises it as a special MIDI device presumably using the pid/vid. This is significant because it then enables new features in the software to support that specific controller. It seems that only the presence of the controller's pid/vid (possibly name as well) enable the features. There is no way to manually enable these enhanced features on a different MIDI port.

I want to intercept some of the controller's inbound MIDI messages in order to drive some additional hardware of my own while it is connected to the software.

I'm hoping to use a Teensy 3.2 (USB MID device) together with a host controller board (USB MIDI host) to act as the middleman in this scenario.

The challenge I see here is that the pid/vid of the middleman has to be that of the controller otherwise the PC won't recognise it as the special MIDI device.

I'm aware that I can change the pid/vid of the Teensy however that seems a rather brute-force way of doing things, it leaves a slightly sour taste like re-using a GUID when you know you shouldn't really be doing so

Is there a better way of doing this or am I on the right track here?

If I did go this way then the controller would identify itself to the Teensy (host board) with the same pid/vid as the Teensy is identifying itself to the PC.

There are no problems with slowing down the messages passing between the PC and the controller, they are short and not particularly time critical.

Any help would be gratefully appreciated and apologies if this has been asked before, I couldn't find this exact scenario but my mind is now so full of partial solutions that perhaps I've missed it somewhere in my reading.

Cheers,

Jason.
 
The middleman may need to emulate more than the vid/pid. It may have to copy all USB descriptors to fool the application. But I would start with a generic MIDI device and change the vid/pid then see if more is required.

The Teensy 3.6 has USB host and USB device ports so it is ideal for USB middleman applications. But any Teensy 3 with USB host controller board should also work. In either case, MIDI examples for USB host and device are included with USB libraries so making USB MIDI sniffer should not be difficult.
 
Thanks for the reply. So emulating seems to be the way to go.

I suspect as you say it may well need more than just the vid/pid and I'll do exactly what you suggest by adding in each descriptor until it is recognised as the device.

It also occurs to me that it may also use a challenge/response message to confirm identity as well - not for security purposes just as a belt and braces check. Certainly the controller sets to a specific state once it is recognised so there is at least some kind of reset message sent.

I'm quite familiar with MIDI having done a fair bit of desktop based software for it in the past however the USB host/device coding is totally new to me.

I'll grab myself a 3.6 after the holidays, it certainly looks the tool for the job!


Cheers
 
Why the reluctance to identify the company?

Have you looked to see if they publish anything about these features.

If they are truly limiting features to their own controllers they should be shamed a bit for it.

It's one thing to extend midi it's another to go proprietary just to tie customers to your hardware.
 
I always say this first... if you haven't read the USB spec, please at least read chapter 4 and the first part of chapter 5. The spec is huge, but this part is only a dozen pages and fairly easy to read. USB is filled with very specific terminology. To communicate effectively with us and others about USB details, knowing these specific terms is essential. Here's a direct link to just the PDF, to save you a little time digging for it over at www.usb.org.

https://www.pjrc.com/teensy/beta/usb20.pdf

You're (probably) going to need some way to view the USB communication. For crafting only a USB device, there are PC programs which can capture the USB traffic. I personally have not used any, but they are an imperfect but popular approach, mainly due to the low cost.

For the communication between Teensy 3.6's USB host port and a USB device plugged into it, no software running on your PC can help. Teensy 3.6 can print tons of info, and maybe that will be enough? But if you get stuck, the best but expensive answer is a hardware analyzer. This is the one I use.

https://www.totalphase.com/products/beagle-usb480/

They also make a cheaper one which is limited to only 12 Mbit/sec. Teensy 3.6 has 480 Mbit/sec speed on its host port, so that cheaper one will only work if your device is 1.5 or 12 Mbit/sec, or if you can find an ancient USB 1.1 hub the limits the speed to 12 Mbit/sec.

On the software side, the good news is both device and host are (more or less) divided into 2 parts - a complex low-level part does the communication of packets and enumeration, and simpler high-level parts do the protocols built on top of those packets.

In the core library, usb_dev.c, usb_desc.c, usb_mem.c are the main low-level stuff. If you look at the higher level files, like usb_serial.c, you'll see they call just a few functions to get packet buffers, fill them with data, and then give them to the low-level code with usb_tx() - and the reverse for receiving, call a function to get any new packet, use the data, the return the buffer to the low-level code. The main exception is if your device needs to do control transfers beyond basic enumeration. In that case, you'll need to add code into usb_dev.c. Lots of the existing device types do this, so hopefully it's not too hard to figure out. Just remember all that low-level stuff runs from interrupts.

In USBHost_t36.c, the division of labor is similar. The hard low-level stuff is in ehci.cpp, enumeration.cpp and memory.cpp. The API is explained in the comments in USBHost_t36.h. You add a C++ class that inherits from the base device class (for non-HID devices - there's a special base class if you use HID). You implement a claim() function which decides if your driver will manage that whole device or an interface within a device. If you do claim the device, you create pipes for the endpoints you want. When packets arrive, you'll get a callback (from interrupt context). In USBHost_t36, almost everything is event based, so to transmit you queue a transfer and then later when it's actually happened you get a callback notification. Likewise to receive, you queue transfers with buffers and the library calls your function when it's happened. The existing drivers should give you a pretty good idea how this works.

Again, I want to emphasize the importance of the USB lingo. USB is a complicated protocol. Using the proper terminology is critically important to communicate with other humans. Please do yourself a favor to read chapter 4 and part of chapter 5 in the spec, so you'll know these terms better. Knowing their specific meaning will make reading the code much easier, and if you buy one of those analyzers, you'll have the understanding to actually use it.
 
Thanks Paul for the very detailed reply. I shall absolutely work my way through the USB documentation so that I can speak the same language as the other developers on this forum.

I do have a background in serial comms and embedded programming (automated fare collection systems) however this was well before USB and all of our communications were HDLC bisync. That was many years ago:) and of course that protocol is largely unused now however at least I am familiar with the basics and C programming.

This is very much a hobby nowadays for me, I am still a commercial developer but nowadays an enterprise architect working on large-scale banking cloud-based systems.

I also provide private tutoring in music technology which is where the Teensy particularly appeals.

It is a definite pleasure to be back to working with clean and succinct code with defined constraints that actually makes things happen!

Cheers,
Jason.
 
Last edited:
Why the reluctance to identify the company?


Hi,

Sorry just noticed your reply. Nothing sinister!

I'm merely in friendly competition with some (non musical) mates to come up with an innovative use for the Teensy and don't want to drop any clues! The controller is in fact mentioned in various threads on these forums and the MIDI messages are well defined (they are GPLd through being included in an open source DAW). They don't tie their hardware to their software. Now I've had a chance to dig around a bit more it also turns out that the device can be configured manually and the software simply provides a courtesy short-cut of recognising the name and doing that for you.


I actually assumed it was more complex that it is.


Cheers,
Jason
 
Status
Not open for further replies.
Back
Top