BMD

Section: Devices and Network Interfaces (4)
Updated: 08 Jan 1991
Index Return to Main Contents
 

NAME

bmd - Berkeley MIDI Driver  

SYNOPSIS

pseudo-device bmd 2 init bmdattach  

DESCRIPTION

The MIDI driver is a pseudo-device that provides a specialized interface to a MIDI device connected to a serial line. MIDI messages are read from and written to the chracter special device files /dev/midi0, /dev/midi1, etc. Once such a file is opened, it must be attached to a MIDI port, via the BMDATTACH ioctl. No operations (other than close) are allowed on the file until it has been attached. Note that a given MIDI device can only be opened by one process at a time, but a single port can be shared by many files. If a file is already in use, open will return EBUSY.

Messages are timestamped to make real time processing possible. Unwanted messages can be filtered out by command type.

MIDI messages are read and written using the following C date structure:

                struct midi_msg {
                        u_long mm_time;
                        u_char mm_data[4];
                #define mm_cmd mm_data[0]
                };

mm_time is a timestamp in MIDI ticks, and mm_data is the message. The message length is implicit in the command byte, which always must be present as the first byte in the message. The leftover bytes are ignored. Note that the driver will eliminate redundant status bytes (and occasionally resend the status so MIDI cables can be moved, devices powered up, etc. without resetting the device). Multiple messages can be read or written in a single system call.

System exclusives are handled by extending the mm_data field beyond the end of the structure. The end of the message is indicated by the eox MIDI status byte (0xf7), and the next message must begin at an aligned offset, computed using the BMDALIGN macro.

Messages are limited in length to BMD_MAXMSGLEN bytes. Naturally, this limitation only applies to system exclusives since all other message types are shorter than this. Inbound system exclusives longer than this length will be truncated, and the trailing eox omitted. In the case of non-truncated messages, an eox byte will always be present (even if the external device doesn't send one), so it's possible to determine if a message has been truncated.

A maximum message length is a nuisance but a reasonable implementation tradeoff. Since very long sysex messages impose delays that preclude real-time performance, there is no motivation to support them in BMD. Applications that require large sysexs (i.e., patch dumps) should simply use the raw interface (i.e. /dev/ttya).

In the presence of mutiple independent writers, MIDI message boundaries are maintained so the mixed output stream will be uncorrupted. Each writer has its own independent time base, with time starting at zero when the port is attached, and counting up at each MIDI clock tick. Time can be independently reset to an arbitrary value, but all writers must share the same clock rate.  

IOCTL CALLS

The ioctl command codes below are defined in <sundev/midi.h>. All commands require these includes:
        #include <sys/types.h>
        #include <sys/ioctl.h>
        #include <sundev/midi.h>

In addition to FIONREAD, FIONBIO, and FIOASYNC, (see fcntl(2)) the following commands may be applied to any open MIDI device. The (third) argument to the ioctl should be a pointer to the type indicated.
BMDATTACH (u_int)
Attach a file to a MIDI port (i.e., on a sparc, the argument should be 0 for serial port A and and 1 for B). This must be done before anything other operations.
BMDGTIME (u_long)
Return the current MIDI clock.
BMDSTIME (u_long)
Set the current MIDI clock for this file and flush the kernel buffers.
BMDFLUSH (void)
Flush the kernel buffers. Output already queued to the serial line is not affected.
BMDRATE (u_int)
Set the MIDI clock rate. The argument is the microsecond interval at which to increment the MIDI clock. The default rate is 1000, or one tick per millisecond. The actual rate used, which may be different from the request due to hardware constraints, is returned.
BMDECHO (int)
Loop back all inbound channel messages (after filtering) on the indicated MIDI channel. If the argument is not a valid channel (e.g. -1), echoing is disabled.
BMDFILTER (u_long)
Set an input filter to discard unwanted MIDI messages. The filter is a bitmask in which the bit number corresponds to the MIDI command number (i.e, bit 9 corresponds to "note on" messages). Those commands for which the corresponding bit is set will be ignored. If bit 15 is set, all system messages will be ignored. If only a particular system message should be discarded, leave bit 15 clear, and set bit 16+x where x is the low nybble of the system command. MIDIMASK is defined to midi.h to make this easier. For instance, to discard after touch and active sensing messages, use:

MIDIMASK(0xd0) | MIDIMASK(0xfe).
The default filter discards active sensing.
BMDPAUSE (void)
Stop the MIDI clock; output will remain queued in the kernel. The clock will stay paused until a BMDRESUME ioctl. If the file is closed while output is paused, the pending data will be flushed. This call will pause the output of all MIDI device files in the system.
BMDRESUME (void)
Re-start the MIDI clock.
BMDNWRITE (u_int)
Returns the number of messages that can be written without blocking, or if in non-blocking mode, doing a partial write. This is useful when an application wants to estimate how much work ahead to use.
BMDNBUF (u_int)
Set the minmum number of messages the kernel will wait for before returning from read or select. If the value is out of range, the limit is returned in the argument (and set). The default is one.
BMDWLO (u_long)
Set the low water mark for writes, i.e., the buffer length (in messages) that will cause a waiting select (or blocked write) to wakeup.
 

SEE ALSO

fcntl(2)  

FILES

/dev/midi0, /dev/midi1, etc.  

BUGS

BMD should be a streams module.

Inbound system exclusives that are terminated by a status byte whose message length is one (i.e. only tune request) will cause the latter message to be dropped.

Under SunOS, the MIDI driver will preempt the standard serial port driver. In other words, if you attach a MIDI file to a serial port that is already in use (i.e., by getty, slip, your kernel debugger etc.), the serial driver will stop receiving I/O. This is only a problem when you "accidently" use the wrong port. The BMD open system call should return EBUSY, but SunOS makes this too difficult.


 

Index

NAME
SYNOPSIS
DESCRIPTION
IOCTL CALLS
SEE ALSO
FILES
BUGS

This document was created by man2html, using the manual pages.
Time: 00:32:14 GMT, January 04, 2023