USB midi protocol understanding - c

I have a sound processor device with MIDI interface over USB. I would like to control the device from my PC besides the official app to the device. However I don't have the command protocol description.
I could get managed to dump a couple of USB packets to the device with the help of usbmon. They look like:
0x0B 0xB0 0x00 0x00
0x0C 0xC0 0x05 0x00
If I send this command from my app, then the device activates program no 5.
The protocol seems to be MIDI, but if I follow it and try to interact with another functions of the device, I get no desired result.
So, I am looking for any help to get it working. For example I need to learn how to select an effect or control the volume and another parameters.
Regards,
Dmitry

You'll find what you need in the Universal Serial Bus Device Class Definition for MIDI Devices and the MIDI specification.
Your example consists of two packets, each containing a MIDI event. They can be decoded as follows:
cable: 0
event: control change
channel number: 0
controller number: 0 (bank select)
controller value: 0
cable: 0
event: program change
channel number: 0
program number: 5

The Zoom G3X device uses the standard USB MIDI protocol.
However, just because it uses MIDI messages does not automatically imply that you know what these messages mean.
There are additional standards, such as General MIDI, but when the device is not a 'normal' synthesizer but an effect processor, most standard messages would not make sense.
To find out what MIDI messages the device accepts, look into the documentation.
If the messages are not documented (like in this case, where the device was meant to be used only with the supplied software), you have to do the changes on the device, and record any MIDI messages that it sends out (with amidi --dump, or aseqdump).
If the device does not send out messages to show changes in its current status, you have to capture the messages sent by the official app with a USB monitor (like usbmon in Linux).

Related

Reading response from a TOSR0X-T relay remotely connected with XBee module

I'd like to get the states of the relays on the board from the relay, but I can get only ACK back.
I have two XBee modules, one is connected to a computer with USB, and acts as a Serial device, the other is connected to a TOSR0X-T relay. I am planning to add more XBee modules to the network with more relays later, so I am using API mode, not the simple AT mode, because I need to address them separately.
I am sending TX frames with 64bit address to the remote XBee to open or close relays. That works fine, I get the ACK response frames properly. However if I send a message to get the relay states by sending 0x5B, I get back an ACK only, and I can find no way to get the actual data back indicating the relay states.
I am using node-serialport and the X-CTU software, but could not read the data, and the only example I found used both XBees connected to the same machine - that way an RX appeared on the destination XBee - but I need to get that remotely somehow.
TOSR0X-T documentation here only tells me about talking to it via TX messages, so I have no clue if I can achieve anything with commands (and how to do that).
The ACK you're seeing is likely the network-layer ACK, telling you that the remote XBee module received your packet. You need to use "AT mode" on the XBee connected to the TOSR0X-T, and address your TX API frames correctly for that mode (cluster 0x0011 of endpoint 0xE8).
If you've configured the XBee on your computer as the coordinator, the default settings of 0 for DH and DL on the relay's XBee module will result in all received serial bytes getting relayed back to the XBee on your computer, and coming through as RX frames.
After some experiments I could solve my problem.
Considering the CH (Channel) and ID (PAN ID) are matching - that is a requirement to be able to set up the network, I set up my XBees like this:
The Coordinator XBee (the one attached to the computer):
CE = 1 (for being coordinator)
MY = 0001
DH = 0
DL = 0
AP = 1 (in API mode)
The first End Point (the one attached to the TOSR0X-T):
CE = 0 (for being an endpoint)
MY = 000A (whatever you want), use FFFF for 64 bit responses
DH = 0
DL = 0001 (This is one I missed. It should be the Coordinator's MY)
AP = 0 (in AP mode)
So basically I did everything right, except the DH/DL addressing. For the Endpoint the DL must be set to the MY of the Coordinator. I read some articles where using FFFF and FFFE and things like that to set broadcasting, and I think I was confused by those informations.

C code to Read data from nonin Pulse Oximeter device via bluetooth Serial Port profile in linux

I am trying to communicate to the Nonin Pulse oximeter device to read the data (Pulse rate and SPO2 level) via Bluetooth. Nonin device supports SPP and HDP profile. I want to communicate through SPP profile. I am able to scan and pair with the device by the sample code available in Bluez.
Please tell me next steps how to send command and read data from the device. I have got struck at this point.
I realize this is a late response, but I recently setup data acquisition from a Nonin PalmSAT 2500A VET unit. I am using the RTC-1000 cable and an RS232 to USB converter.
This is straight from the manual:
"Information from the device, in the real-time mode, is sent in an ASCII serial format at 9600 baud with 9 data bits, 1 start bit, and 1 stop bit. The data are output at a rate of once per second.
NOTE: The 9th data bit is used for odd parity in memory playback mode. In real-time mode, it is always set to the mark condition. Therefore the real-time data may be read as 8 data bits, no parity.
Real-time data may be printed or displayed by devices other than the pulse oximeter. On power up a header is sent identifying the format and the time and date. Thereafter, the data are sent once per second in the following format:
SPO2=XXX HR=YYY
where “XXX” represents the SpO2 value, and “YYY” represents the pulse rate. The SpO2 and pulse rate will be displayed as “---” if there are no data available for the data reading."
Link to manual:
http://www.proactmedical.co.uk/proshop_support_docs/2500aman.pdf
What model oximeter are you working with?

C: Detecting how much data was written to a tap

I am working on a program where I'm reading from a Tap. The only issue is, I have no clue how to detect the end of one transmission to the tap and the start of another.
Does reading from the tap act the same way as a SOCK_STREAM ?
Tun/tap tries to look like a regular ethernet controller, but the tap device itself is accessed just like any other file descriptor.
Since it pretends to be an ethernet controller, you have to know in advance how big the ethernet frame itself was that was transmitted - this comes either from the software bridge that the tap device was attached to or the "length" field in the raw ethernet frame.
This, of course can only be the maximum of the MTU size of the tap device, which typically defaults to 1500 bytes.
So, before you do a read() on the file descriptor for the tap device, you've gotta figure out how big the ethernet frame actually is.

tty_tiocmset in linux kernel masks desired modem signal

I am running an embedded linux kernel on hardware that can be configured as DTE/DCE. In the tty/serial drivers in a file called tty_io.c there is a function tty_tiocmset() which takes a bit pattern from the tty_ioctl for setting/clearing specific modem control signals. Interestingly, the tty_tiocmset() function masks all other modem signals besides TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP (this mask is shown in the code below). However, if you look at the documentation it appears that all modem signals should be able to be set/cleared http://www.kernel.org/doc/man-pages/online/pages/man4/tty_ioctl.4.html scroll down to "Modem Control".
Does anybody simply know why this mask is present without other signals such as RI, CD, CTS, DSR? Also is there another way to use the unmodified driver to control the other modem signals?
Linux was originally hosted on the x86 PC platform, which used 8250-type UARTs. The modem signal names OUT1 & OUT2 are not EIA/RS-232 names but do appear in the Western Digital 8250 data sheet! Those 5 bits listed for tty_tiocmset() match (by name & function) the 5 bits available in the 8250 Modem Control Register. Any additional control lines would have to be implemented by logic external to the 8250.
Does anybody simply know why this mask is present without other signals such as RI, CD, CTS, DSR?
Those four that you mention are input signals to a DTE port, and PCs are normally configured (or assume/default) to be DTE.
Input signals would not appear in an output control register.
Maybe this is a bug when Linux is embedded in a device for a DCE port?
These input signals do appear in the Modem Status Register.
Also is there another way to use the unmodified driver to control the other modem signals?
You could remap OUT1 and OUT2 to whatever additional DTE signal(s) you need to output.
If you need to setup the port for DCE, then you may have to remap all four control lines.
For a DCE port (i.e. modem) there are typically only 4 output control lines: DCD, CTS, DSR, and RI. And there are exactly 4 output control bits (besides loopback) in the 8250 MCR!

C Linux Device Programming - Reading Straight from /Dev

I have been playing with creating sounds using mathematical wave functions in C. The next step in my project is getting user input from a MIDI keyboard controller in order to modulate the waves to different pitches.
My first notion was that this would be relatively simple and that Linux, being Linux, would allow me to read the raw data stream from my device like I would any other file.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
Despite these warnings, I did an experiment. I plugged in the MIDI controller and cat'ed the "/dev/midi1" device file. A steady stream of null characters appeared, and when I pressed a key on the MIDI controller several bytes appeared corresponding to the expected Message Chunks that a MIDI device should output. MIDI Protocol Info
So my questions are:
Why does the cat'ed stream behave this way?
Does this mean that there is a plug and play device driver already installed on my system?
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
Thank you in advanced for sharing your wisdom in these areas.
Why does the cat'ed stream behave this way?
Because that is presumably the raw MIDI data that is being received by the controller. The null bytes are probably some sort of sync tick.
Does this mean that there is a plug and play device driver already installed on my system?
Yes.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
<...>
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
I'm not sure what you're reading or how you're coming to this conclusion, but it's wrong. :) You've already got a perfectly good driver installed for your MIDI controller -- go ahead and use it!
Are you sure you are reading NUL bytes? And not 0xf8 bytes? Because 0xf8 is the MIDI time tick status and is usually sent periodically to keep the instruments in sync. Try reading the device using od:
od -vtx1 /dev/midi1
If you're seeing a bunch of 0xf8, it's okay. If you don't need the tempo information sent by your MIDI controller, either disable it on your controller or ignore those 0xf8 status bytes.
Also, for MIDI, keep in mind that the current MIDI status is usually sent once (to save on bytes) and then the payload bytes follow for as long as needed. For example, the pitch bend status is byte 0xeK (where K is the channel number, i.e. 0 to 15) and its payload is 7 bits of the least significant byte followed by 7 bits of the most significant bytes. Thus, maybe you got a weird controller and you're seeing only repeated payloads of some status, but any controller that's not stupid won't repeat what it doesn't need to.
Now for the driver: have a look at dmesg when you plug in your MIDI controller. Now if your OSS /dev/midi1 appears when you plug in your device (udev is doing this job), and dmesg doesn't shoot any error, you don't need anything else. The MIDI protocol is yet-another-serial-protocol that has a fixed baudrate and transmits/receives bytes. There's nothing complicated about that... just read from or write to the device and you're done.
The only issue is that queuing at some place could result in bad audio latency (if you're using the MIDI commands to control live audio, which I believe is what you're doing). It seems like those devices are mostly made for system exclusive messages, that is, for example, downloading some patch/preset for a synthesizer online and uploading it to the device using MIDI. Latency doesn't really matter in this situation.
Also have a look at the ALSA way of playing with MIDI on Linux.
If you are not developing a new MIDI controller hardware, you shouldn't worry about writing a driver for it. It's the user's concern installing their hardware, and the vendor's obligation to supply the drivers.
Under Linux, you just read the file. Now to interpret and make useful things with the data.

Resources