Media Content Detector utility
mcd options* config_file &
QNX Neutrino
ARM, x86
Local mode
The local mode option (-L) may permit simpler configuration when stand-alone systems are used, as describe here.
Use local mode if a system using MCD is to be run as a stand-alone with respect to any services that use the MCD, and Qnet is running on the system (for example, for debugging).
When the MCD runs in local mode, the MCD:
Limitations
When the local mode option is used:
The mcd utility (media content detector, or MCD) monitors device and mediastore insertions and removals, and the presence of specified media content.
This utility page contains:
Overview
The MCD is a stand-alone utility for detecting devices, mediastores and specified media content. It is positioned between storage and USB device drivers, and any client application that needs to be informed of a device or mediastore activity, or of the presence of specified media types.
The MCD design separates the definition of actions conducted by the system from the implementation of these actions so that the actions can be easily edited or updated without changes to code.
MCD rules
The MCD provides a binary decision tree framework, applying rules and branching between rules according to match/fail results. These rules are used for detecting device and mediastore insertions and removals, and for classifying their content. They are specified in the MCD configuration file, and implemented with user callouts.
You can write rules for the MCD instructing it to monitor the presence or absence of any device, mediastore or file, as shown by the three examples below:
Monitor a mediastore
The rule below tells the MCD to monitor the physical insertion or removal of a CD-ROM mediastore on a device (the hardware) at the location /dev/cd*.
[/dev/cd*] Callout=CD_MEDIA_IOBLK
Monitor namespace changes
The rule below monitors changes (mount or unmount) of a device or mediastore (such as a USB storage device) on the system. These sorts of changes usually indicate the physical insertion or removal of the device (the hardware) and its filesystem mounting or unmounting.
[/fs/usb*] Callout=PATH_MEDIA_PROCMGR
Monitor the presence of files
The rule below polls the contents of /directory looking for files or directories that have been created in or removed from the directory being monitored. For example, typing touch /directory/file from a shell satisfies this rule, though no physical device has been inserted or removed.
[/directory/*] Callout=PATH_MEDIA_SCAN
MCD server
The MCD server:
Operational flow
This section describes the MCD's operational flow at startup, and on detection of a new device, mediastore or file.
Startup
At startup, the MCD server proceeds as follows:
Device or insertion
On detection of a device or mediastore insertion, or of the presence of a file of interest, the MCD proceeds as follows:
Configuring the MCD
The operation of the MCD is controlled by a configuration file. This file consists of named sections, each section defined by a name enclosed in square brackets: [ ], followed by parameter lines with the form key = value. These parameters apply only to the section in which they appear.
The MCD ignores blank lines and any leading or trailing white spaces. It treats lines beginning with a "#" or a ";" character as comments and ignores them as well.
Configuration file sections
A section of the MCD configuration file can be one of:
The example below presents a description: [/dev/cd0] and a rule: [DVD_AUDIO]:
[/dev/cd0] Callout = CD_MEDIA_IOBLK Argument = 1000,2000 Priority = 11,9 Start Rule = DVD_OR_CD [DVD_AUDIO] Callout = FNAME_MATCH Argument = /AUDIO_TS/AUDIO_TS.IFO Match Rule = DVD_VIDEO Fail Rule = DVD_VIDEO
Entity descriptions
For entity (device, mediastore or file) description sections, the section name is the entity the MCD monitors. This name can be a single name, such as /media/drive, or a wildcard pattern, such as /dev/umass*. If the section name is a wildcard pattern, the event notification routine defined by the Callout= for the section must be capable of handling every entity that matches the wildcard pattern.
Parameters
Configuration parameters are used differently according to the type of section (mediastore description, or content rule) in which they are used.
Parameters in an entity section of the configuration file are used as follows:
If you provide no Callout= routine, you should handle device, file or mediastore transitions externally with the notification provided through the resource manager interface.
Media content rules
For media content rule sections of the mcd configuration file, the section name is the name of the rule.
Parameters
Parameters in a media content rule section of the configuration file are used as follows:
Notification routine
The notification routine that runs when a mediastore matches a rule produces a match/fail result to indicate whether or not the media on the mediastore satisfies the routine's particular requirements. Based on the result produced by the rule, the MCD takes a branch to another rule, as specified by the Match Rule= or Fail Rule= parameters in the current section.
If no associated branch rule is provided for a rule's result, the MCD considers the rule to be terminal and content detection complete.
Using the MCD as a filesystem automounter
The MCD can be used as a filesystem automounter by creating a set of two-phase rules in the MCD configuration file. Two-phase rules are implemented in the MCD as follows:
First-level entries
Second-level entries
For an example of how to use the MCD as a filesystem automounter, see "Two-phase filesystem mount example" in the "Examples" section below.
The mcd resource manager interface
The MCD server presents a standard QNX Neutrino resource manager (filesystem-like) interface. The default top-level directory is /dev/mcd; it includes:
.insert and .eject files
The .insert and .eject files are write-only files in /dev/mcd. External programs can trigger the MCD's content detection process on the insertion or ejection of an entity by writing to the appropriate file the pathname of the entity that has been inserted or ejected; for example /dev/cd1 .
.devices directory
The .devices directory in /dev/mcd contains an entry for each entity (device, mediastore and monitored file) known to the system. Each entity is represented by a S_IFCHR/char-special file in this directory. These files hold information about the entity in fields as follows:
The "Client API" section below includes an example that illustrates how to use this interface.
Sequence number
The sequence number stored in st_ino for any entity (device, mediastore or file) can be either zero or non-zero. A value of zero means that the entity is not present in the system. A non-zero value means that the entity is present in the system.
At each re-insertion of the entity, the MCD increases the sequence number for that entity. Thus, for example, for a mediastore the values of st_ino might be in sequence: 1 (first insertion), 0 (removal), 3 (re-insertion), 0 (removal), 5 (re-insertion).
A client application can use the incrementing value of st_ino at each state change to check that it is up to date with, for example, a mediastore's activity after a series of rapid insertions and removals. For more information, see "Stale rules" below.
Example: Filesystem hierarchy
Below is a sample filesystem hierarchy:
$ ls -al /dev/mcd dr-xr-xr-x 1 root root 11 Aug 02 19:46 . n-w--w--w- 1 root root 0 Aug 02 19:46 .eject n-w--w--w- 1 root root 0 Aug 02 19:46 .insert nr--r--r-- 1 root root 0 Aug 02 19:46 CDDA_OR_DTS nr--r--r-- 1 root root 0 Aug 02 19:46 CD_AUDIO nr--r--r-- 1 root root 0 Aug 02 19:46 DVD_AUDIO nr--r--r-- 1 root root 0 Aug 02 19:46 DVD_OR_CD nr--r--r-- 1 root root 0 Aug 02 19:46 DVD_VIDEO nr--r--r-- 1 root root 0 Aug 02 19:46 MIXED_AV nr--r--r-- 1 root root 0 Aug 02 19:46 SVIDEO_CD nr--r--r-- 1 root root 0 Aug 02 19:46 VIDEO_CD
Read-only entries for rules
The top-level /dev/mcd directory contains read-only entries for each rule defined in the configuration file.
Client applications can read from here the name of the device that satisfied a particular rule, with the read blocking until a device with content matching that rule is available. A non-blocking select and notify mechanism is also available to allow the client to wait on multiple rules, or to perform other work until a rule is triggered. Following the notification, the client application can read the rule to determine the device.
Callout templates
The MCD server provides a framework from which you can build a content detection system. Callout routines provide all the specific functionality in such a content detection system.
The MCD includes some common routines available for use where required in a static-linked library bound into the server. The MCD also supports extension routines provided by third-parties in DLLs dynamically linked at runtime. Thus, the system is extensible: if you require a new, unsupported detection test, you can implement it outside the server framework and ship it as a separate library.
In the content detection system configuration file, all Callout= items refer to a callout. These callouts are identified as internal or external by their names:
Insertion and ejection notification
The prototype for media insertion notification callouts is:
void mcd_notify( char *iomgr[2], char *device, void *arg );
The MCD creates this routine in a dedicated thread, that should continually monitor the device. This thread should not return, except in the event of a serious error. If the thread encounters a serious error, it should set errno appropriately and return. On the return of an entity detection thread, the MCD will:
Arguments
device may be a wildcard, requiring the routine to monitor a group of devices, files or mediastores. When a device event occurs, the routine should write to the appropriate iomgr[] path the name of the specific device, mediastore or file that is affected by the event.
Built-in notification routines
The MCD's built-in media notification routines include:
The Argument= option sets the name of the USB enumeration server to connect to (typically "/dev/umass-enum").
The Argument= option sets the name of the special directory where the OS pathmgr maintains mountpoints (typically "/proc/mount").
The PATH_MEDIA_SCAN cause the MCD to behave differently, based on the presence or absence of a trailing "/" character at the end of the pathname, as follows:
The Argument= option sets the poll period, in milliseconds, for scanning the directory.
Media content determination
The prototype for content detection rule callouts is:
int mcd_content( char *device, void *arg );
Arguments
Returns
This routine returns values as follows:
Built-in content detection rules
The MCD's built-in content detection routines include:
It ignores The Argument= option. The rule matches only if the media is a DVD.
The Argument= option sets the filename of a file of mount rules. Since this option is opened and parsed each time the rule is run, you should consider locating this filename on a ramdisk or in /dev/shmem.
This rule is typically used as the Start Rule= of a two-phase configuration, where the resulting mount operation triggers a PATH_MEDIA_PROCMGR action. The rules are processed from the file in order, stopping at the first (fnmatch()) match that either succeeds or specifies to skip the device (when the rule has only a pattern and no mount information). In order to select the appropriate filesystem, you can specify multiple rules for a removable device.
The file format is one rule per line, with each line containing fields separated by white spaces. For example:
#Device_pattern Mount_point Fsys_type Mount_options /dev/cd* /fs/cd%# udf normv,format=udf,rrip,joliet,iso9660e,iso9660,audio /dev/umass*t1[124] /fs/usb%0 dos fsi=use /dev/umass*t[146] /fs/usb%0 dos /dev/hd*
The rules shown in the example above instruct the MCD to:
See "MOUNT_FSYS special sequences" below for more information about the mountpoint sequences. For more information about UDF, see fs-udf.so.
This rule is typically used as the Stop Rule= of a CD_MEDIA_IOBLK mediastore that uses the MOUNT_FSYS action, when a mount would otherwise persist after the mediastore ejection. If the mediastore is presented by a resmgr that will exit or be terminated by an external manager (such as USB), then that presentation implicitly unmounts any relevant filesystem without the need for this rule. However, in most instances where a MOUNT_FSYS is used, you should also configure a matching UNMOUNT_FSYS in order to ensure that the filesystem for an ejected mediastore is duly unmounted.
MOUNT_FSYS special sequences
The MOUNT_FSYS rule uses special sequences, as follows:
Below is a sample mcd.mnt file that uses the %# and %0 special sequences.
#------------------------------------------------------ # Device Mountpt Type Options #------------------------------------------------------ /dev/cd* /fs/cd%# udf normv /dev/umass[0-9]* / enum /dev/umass[0-9]*t1[1234] /fs/usb%0 dos /dev/umass[0-9]*t1[1234].* /fs/usb%0 dos /dev/umass[0-9]*t[146] /fs/usb%0 dos /dev/umass[0-9]*t[146].* /fs/usb%0 dos /dev/umass*t7[789] /fs/usb%0 qnx4 /dev/umass*t17[789] /fs/usb%0 qnx6 sync=optional /dev/umass[0-9]* /fs/usb%0 dos
Client API
The MCD uses special rule entries created in the resource manager filesystem to notify client applications of media content matches.
A client application can call open() to access the rule entry in which it is interested, and when that rule is matched, it can then use read() to read from the entry the name of the relevant mediastore. If QNET is active and the -L is not specified, the device name returned from reading the MCD rule entry is a fully-qualified-path-name (FQPN); this feature allows the string to be used as-is by any process on any node.
The read() function blocks until a match is made (unless oflag is set to O_NONBLOCK). For non-blocking notifications, use ionotify(). To wait on multiple rules, use select().
Maintained information
In order to inform each client once and only once of each match, the MCD server maintains state information about each mediastore, matched rule, and client application.
When a new mediastore is inserted, any matched rule triggers notifications to the interested clients. If the mediastore was inserted before a client registered with the MCD, the first read the client makes is satisfied immediately. This behavior eliminates any start-up race conditions, such as, for example, there being media already in a drive at system startup, and the content detection process completing before the higher-level client applications are even started.
Example: Media player
A very simple media player might be designed as follows:
int fd, cd; char device[_POSIX_PATH_MAX]; // Open the CD_AUDIO rule and wait for it to be matched. fd = open("/dev/mcd/CD_AUDIO", O_RDONLY); while (read(fd, device, sizeof(device)) != -1) { // At this point, device contains an audio CD ... cd = open(device, O_RDONLY); // ... read the toc, play it, etc. // Could monitor playback status with // DCMD_CAM_CDROMSUBCHNL. // If disk is ejected, this will fail. // Can loop back waiting for next insertion. // The rule will be re-armed for the // next match. close(cd); } close(fd);
Example: Polling
The mcd device Start Rule= and Stop Rule= rule chains are mutually exclusive: the ejection of a device cancels out inserted rules for that device (and vice-versa). Therefore, if you use select() or ionotify(), you should use them in conjunction with a non-blocking read(), as there is no guarantee that the notified state and/or rules of the trigger will remain valid (for example, if the media is ejected between the calls to ionotify() and read()).
The code snippet below illustrates one way to use ionotify() in conjunction with a non-blocking read():
<PRE> fd = open(rulename, O_RDONLY | O_NONBLOCK); SIGEV_UNBLOCK_INIT(&evt); for (;;) { while (ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &evt) != 0) { while (read(fd, device, sizeof(device)) > 0) { // 'device' matched on 'rulename' } } pause(); } </PRE>
Stale Rules
Stale rules may occur if there is client decoupling, and/or a delay between the notification and the use of inserted mediastore; for example, due to the spawning of a separate media application.
To avoid stale rules, the MCD can include the mediastore's insertion sequence number with the rule notification, and applications can then match this number against the device entry in the /dev/mcd/.devices directory. If the device has been ejected since the rule was triggered, these values will no longer match, indicating that the rule no longer applies to the current device content, and that new rules may have been re-triggered.
If the client application requires an insertion sequence number, the MCD uses an XTYPE read to return an additional uint32_t of data with the mediastore name, and the _IO_XTYPE_MQUEUE message priority code, avoiding the need to make changes to the global <sys/io_msg.h> header file.
// Get rule notification using an XTYPE read int fd; uint32_t seq1; char device[_POSIX_PATH_MAX]; fd = open("/dev/mcd/CD_AUDIO", O_RDONLY); _readx(fd, device, sizeof(device), _IO_XFLAG_BLOCK | _IO_XTYPE_MQUEUE, &seq1, sizeof(seq1)); // Open and check the current version of the inserted device int fd; struct stat st; uint32_t seq2; char entry[_POSIX_PATH_MAX]; fd = open(device, O_RDONLY); sprintf(device, "/dev/mcd/.devices/%s", device); seq2 = (stat(device, &st) != -1) ? st.st_ino : 0; // If these match, the CD_AUDIO rule is the same and still valid // and 'fd' is open on that version of the media if (seq1 == seq2) ...
Additional Information
This section describes how to use the MCD for specific operations:
Detecting other kinds of system media
To detect system media not handled by the routines included with the MCD:
Detecting USB and iPod devices
The MCD can manage any kind of device, provided that a notification mechanism is available to report on insertions and start the detection process.
For USB devices, you can use the following entry in the MCD configuration file:
[/fs/usb*] Callout = PATH_MEDIA_PROCMGR Argument = /proc/mount Priority = 11,10 Start Rule = ...
Targets running QNX Neutrino 6.3.n releases only. For USB devices, the umass-enum server in conjunction with the MCD's built-in USB_MEDIA_ENUM routine can provide the notification mechanism and start the detection process. Invoke umass-enum with the -r option to activate its resource manager interface, and use the following device entry in the MCD configuration file:
[/dev/umass/*] Callout = USB_MEDIA_ENUM Argument = /dev/umass-enum Priority = 11,10 Start Rule = ...
For iPod devices, the device entries dynamically attach pathnames (when these pathnames are present), and so can be handled with the MCD's built-in PATH_MEDIA_PROCMGR() routine. Use the following device entry in the MCD configuration file for iPods:
[/fs/ipod*] Callout = PATH_MEDIA_PROCMGR Argument = /proc/mount Priority = 11,10 Start Rule = ...
Pattern matching and case-sensitivity
The MCD's FNAME_MATCH routine attempts to access listed files by using the underlying filesystem, which applies any rules appropriate for that filesystem in conjunction with any specified mount options. Thus, case-sensitivity in pattern matching depends on:
The table below lists the case-sensitivity and case-preserving characteristics of some common filesystems:
filesystem | case-sensitive | case-preserving |
---|---|---|
FAT | No | No |
ISO-9660 | No | No |
Joliet | No | Yes |
QNX 4 | Yes | Yes |
RRIP | Yes | Yes |
VFAT | No | Yes |
Since the majority of mediastores used for multimedia storage are formatted for DOS/Windows use, it is likely that the filesystem will be case-insensitive. This case-insensitivity means that in any FNAME_MATCH rules the Argument= filename list can be given in either upper or lower case.
The FNAME_PATTERN routine processes directory entries from the filesystem through the libc fnmatch() function, which is case sensitive.
The directory output from each filesystem depends on whether it is case-preserving. If the filesystem is not case-preserving, then default rules are used to control the filename presentation. Refer to the cd case=lower|upper or the dos sfn=lower|upper|windows filesystem mount options.
Since the most common multimedia formats are case-preserving and will use the exact filename that a user or media application used to create their files, in any FNAME_PATTERN rules the Argument= pattern list should be given in both upper and lower case (as in the MIXED_AV rule in the Examples below.).
Matching a single rule
If you don't want multiple media types to match and only want to match the first rule, you can use the fact that if a matched rule has no Match Rule= branch the MCD stops its detection process.
In the configuration file, simply arrange the rules, from the Start Rule= through the Fail Rule= links, in priority order. Do not provide any Match Rule= branches. The MCD detection framework will test these rules in sequence until one is matched, then stop. For an example, see the VIDEO_CD and SVIDEO_CD entries in the Examples below.
Detecting CD insertion with non-media content
To be notified when a CD is inserted regardless of what content it contains, simply:
Your application can now block on that new rule, via the normal resource manager interface ("/dev/mcd/DISC_INSERTED"), waiting for device insertion. For example, one of the example configurations in this document could be modified as follows:
[/dev/cd0] Callout = CD_MEDIA_IOBLK Argument = 1000,2000 Priority = 11,9 Start Rule = DISC_INSERTED [DISC_INSERTED] Match Rule = DVD_OR_CD
CD-changer controlled by external firmware
To detect insertion events from a CD-changer that is controlled by external firmware (e.g. FJ-10), you should not use any of the built-in MCD detection callouts, but trigger the insertion notification directly from the CD-changer controller stack.
Internally, all built-in device detection callouts do their specific work, then write the name of the device to the special /dev/mcd/.insert entry. This behavior means that to detect insertions on changers controlled by external firmware, proceed as follows:
In the configuration file, the relevant device entry would be like this (note that no Callout= is specified in this situation):
[/dev/cd0] Priority = 11 Start Rule = ...
The insertion notification code in the driver is basically this:
int notify; notify = open("/dev/mcd/.insert", O_WRONLY); write(notify, "/dev/cd0", 8); close(notify);
Similar code to handle ejections can be written to /dev/mcd/.eject.
Using the MCD as a partition enumerator
The MCD's MOUNT_FSYS rule can be used to determine if partition enumeration has occurred on a device (USB stick). This capability can be used to try to mount a filesystem on the raw device, if the device has not been partitioned.
In order to determine if partition has occurred, use the following configuration:
The mcd.mnt rule used by that MOUNT_FSYS should include the following:
/dev/umass[0-9]* / enum /dev/umass[0-9]* /fs/usb%# dos /dev/umass[0-9]*t1[124] /fs/usb%# dos fsi=use /dev/umass[0-9]*t[146] /fs/usb%# dos
The control flow for this configuration is as follows:
Consider the following sample configuration file for a CD-based system:
# Sample CD/DVD disk identification rules. [/dev/cd0] Callout = CD_MEDIA_IOBLK Argument = 1000,2000 Priority = 11,9 Start Rule = DVD_OR_CD [DVD_OR_CD] Callout = DVD_OR_CD Match Rule = DVD_AUDIO Fail Rule = CD_AUDIO [DVD_AUDIO] Callout = FNAME_MATCH Argument = /AUDIO_TS/AUDIO_TS.IFO Match Rule = DVD_VIDEO Fail Rule = DVD_VIDEO [DVD_VIDEO] Callout = FNAME_MATCH Argument = /VIDEO_TS/VIDEO_TS.IFO Fail Rule = VIDEO_CD [CD_AUDIO] Callout = CD_AUDIO Match Rule = VIDEO_CD Fail Rule = VIDEO_CD [VIDEO_CD] Callout = FNAME_MATCH Argument = /VCD/INFO.VCD,/MPEGAV/AVSEQ01.DAT,/MPEGAV/MUSIC01.DAT Fail Rule = SVIDEO_CD [SVIDEO_CD] Callout = FNAME_MATCH Argument = /SVCD/INFO.SVD,/MPEGAV/AVSEQ01.MPG,/MPEG2/AVSEQ01.MPG Fail Rule = MIXED_AV [MIXED_AV] Callout = FNAME_PATTERN Argument = *.MP3,*.mp3,*.WMV,*.wmv,*.WMA,*.wma,*.AAC,*.aac,*.JPG,*.jpg,*.MPG,*.mpg
A single device, /dev/cd0, is monitored by the built-in CD_MEDIA_IOBLK() routine:
The DVD_AUDIO rule assumes the existence (using the built-in FNAME_MATCH test) of a /AUDIO_TS/AUDIO_TS.IFO file on the DVD indicating DVD audio content.
This behavior is similar to the behavior of the CD_AUDIO rule, as a CD can contain both audio and data content.
Rules for determining CD data content, such VIDEO_CD or SVIDEO_CD, have only a Fail branch, since a match at these levels is mutually exclusive with any further content. If these rules match, then the content detection process stops.
During the content detection processing phase, any clients that have registered against any matched rules will be notified. Multiple rules, or no rules at all, might be matched by an inserted CD: an enhanced audio CD with a bonus music video might match both CD_AUDIO and MIXED_AV rules, whereas a data CD backup of a development system would match none.
Two-phase filesystem mount example
Below is a configuration file involving USB devices; it requires that an external USB enumerator invoke devb-umass blk auto=partition disk name=umass in response to insertions.
[/dev/umass*t*] Callout = PATH_MEDIA_PROCMGR Argument = /proc/mount Priority = 11,10 Start Rule = MOUNT [MOUNT] Callout = MOUNT_FSYS Argument = /dev/shmem/mcd.mnt [/fs/usb*] Callout = PATH_MEDIA_PROCMGR Argument = /proc/mount Priority = 11,10 Start Rule = MIXED_AV [MIXED_AV] Callout = FNAME_PATTERN Argument = *.MP3,*.mp3,*.WMV,*.wmv,*.WMA,*.wma,*.AAC,*.aac,*.JPG,*.jpg,*.MPG,*.mpg
Note that the device pattern specified in the example above avoids the raw device itself and only applies to partition entries. The mount configuration /dev/shmem/mcd.mnt referred to contains:
/dev/umass*t1[124] /fs/usb%# dos /dev/umass*t[146] /fs/usb%# dos