Device-enumerator manager

Note: You must be root to start this manager.


enum-devices options

Runs on:



-c path
Specify one or more configuration files. The path can either be a single file, or the name of a directory:
  • If a single file, enum-devices reads the contents of the file.
  • If a directory, enum-devices reads the contents of all the files contained in the directory.

You can repeat this option to specify multiple configuration files and directories; you can also use a config clause in a configuration file to include other files and directories (see below).

Before it starts processing, enum-devices concatenates the contents of all the configuration files that you tell it to read.

Dump the device-lookup table.
-E enumerator
Start the second-pass enumerator program.
-e enumerator
Start the given enumerator command:
  • enum-bootdev
  • enum-legacy
  • enum-par
  • enum-pccard
  • enum-pci
  • enum-pnpbios
  • enum-pnpisa
  • enum-ser
-i prefix
Ignore any configuration files in directories whose names start with prefix.
-I suffix
Ignore any configuration files in directories whose names end with suffix.
Write the commands for starting the drivers to standard output rather than executing them.
Operate verbosely. The more v characters, the more verbose the output is.


This description of enum-devices includes the following sections;


The enum-devices manager enumerates the devices present on your computer. This manager first reads the configuration files specified by any -c command-line options.

Next, the configuration manager queries its various enumerators to discover what devices are on the system. It then matches these devices against the device IDs listed in the configuration files. If the device matches, enum-devices executes the action clauses associated with the device.

Note: Programs that are spawned by any start and requires clauses aren't actually started until all processing is completed, so that any built-up command lines are finished. If you want to perform an action regardless of what devices are present, use the all device ID.

Matching rules

Matching behavior for enum-devices is based on the "number of matches" in the enum-devices configuration file device statement. A secondary device statement may be created by placing a period (".") in front of the match field.

This method for matching devices with entries in the enum-devices configuration file can sometimes result in "ambiguities": a specified device that matches more than one entry in the enum-devices configuration file, rendering it impossible for the enumerator to select the preferred driver for the device.

For example, with a device fully specified as:


and with the following in the enum-devices configuration file:

device(usb, ven=1922,dev=1234)

device(usb, class=08,proto=00)

the specified device matches both the entries in the configuration file.

This ambiguity can be removed by either extending the match criteria for the preferred driver:

device(usb, ven=1922,dev=1234,class=08)

or by making one of the matching fields secondary; that is, by giving it a lower precedence that the other fields:

device(usb, .class=08,proto=00)

A "catch all" (an action that matches any device) is produced by simply entering the bus type for the device. For example:

    echo("No match found for device ven=$(ven),
    dev=$(dev), class=$(class), busno=$(busno),
    devno=$(devno), cfg=$(cfg), iface=$(iface),
    msven=$(msven), mscomp=$(mscomp),
    mssubcomp=$(mssubcomp)" )

Configuration files

Configuration files in the etc/system/enum/ directory include:


Configuration files in the etc/system/enum/devices/ directory contain device definitions; these files include:


Configuration files in the etc/system/enum/devices/usb/ directory include:


Configuration files in the etc/system/enum/include/ directory contain macro definitions; they include:

Configuration file precedence

The order of precedence for enum-devices configuration files is determined by one or both of the following criteria:

If files are added to an enumeration directory after the enumeration utility has been started, the enumerator picks up these files and assigns them a higher precedence than currently existing files.

Given the complexity associated with adding and removing files and directories during processing, QNX recommends that you:

Configuration file contents

A configuration file consists of statements for one or more devices. Each statement contains clauses that you want to execute if enum-devices finds those devices on your system.

The enum-devices configuration file is typically takes the following format:


Anything after a number sign (#) until the end of the line is considered a comment.

Each statement is in this form:


The device_id is either the keyword all or any number of identifiers in this form:

device(bus_type[, specification]...)

The bus types include at least the following:

Each clause is a keyword, followed by any required arguments. The clauses include:

Start a command.
Start a command if it isn't already running.
Start a command as an individual driver if the device might be removed.
Run the mount utility with the specified arguments.
Start a new bus enumerator.
Set a macro.
Add to a macro definition.
Set a macro to a value that depends on whether or not a string is found in an internal database.
Wait for a given pathname to appear.
Echo a string to a file.
Assign a name to a block of action clauses.
Load additional configuration files or directories.
Merge macro definitions.

The clauses are described in the sections that follow.

start clause

The start clause takes this form:

start[/wait] (system_command [, system_args] )

It runs the command and arguments specified by system_command. If you specify the /wait option, the enumerator pauses until the command terminates.

If you specify system_args, the manager searches for a start clause with a system_command that's identical to this one, and appends system_args to its command line. This is a useful way to start just one instance of a command, specifying the arguments needed for all of the devices found.

For example, this clause:

start(spooler -d$(path), -P$(pnpstr))

says to start spooler -d$(path), but tells enum-devices that if it's already encountered this command, just append -P$(pnpstr) to it. (The $(...) notation is for macro expansion; see the set clause, below.)

requires clause

The requires clause can be one of two forms:

requires[/wait] (system_command [, system_args] )
This form is similar to the start clause, but enum-devices checks to make sure that the command isn't already running on the system.
Note: If you specify system_args, don't forget the comma between system_command and system_args; if you omit it, enum-devices doesn't check to see if the command is already running — it might start the command more than once.

For example, the /etc/system/enum/devices/net enumeration file includes this line for the network devices that need io-pkt*:

requires[/wait] (@tag_string)
If you use this form, enum-devices searches all the pending action lines for tag names of tag_name (see the tag clause) and executes them. This can be useful when you need a certain ordering of various components.

If you specify the /wait option in either form, the enumerator pauses until the command terminates.

driver clause

The driver clause looks like this:

driver[/wait] (system_command [, system_args] )

It's similar to the start clause, but if the bus-enumerator process indicates that the device might be removed, enum-devices starts an individual driver process for the device (instead of tacking the system_args onto a previously specified driver for the same device). If the bus enumerator indicates that the device has been removed, a SIGTERM signal is sent to the driver process.

If you specify the /wait option, the enumerator pauses until the command terminates.

mount clause

The mount clause looks like this:

mount (mount_args [, umount_args] )

It spawns the mount command with the given mount_args arguments. If you specify any umount_args, they're passed to umount if or when the device is removed.

enumerator clause

The enumerator clause takes this form:

enumerator (enumerator_type)

It starts a new bus enumerator named enumerator_type.

set clause

The set clause takes this form:

set (macro_name, macro_definition)

This clause sets the definition of macro_name to be macro_definition. Whenever enum-devices finds $(macro_name) in any of the configuration files, it substitutes the macro_definition. For example:

set(DEVB_OPTIONS, cam quiet blk auto=partition)

You can recursively nest macros the way that you can in make.

append clause

The append clause looks like this:

append (macro_name, macro_definition)

This clause appends macro_definition to the definition of macro_name.

uniq clause

The uniq clause is in this form:

uniq (macro_name, uniq_name [, initial] )

This clause makes enum-devices search an internal database for the string uniq_name:

For example, you can use a uniq clause to keep track of how many instances of a device you've found, so you can create a unique path for a device:

uniq(sernum, devc-ser, 1)
driver(devc-ser8250 $(SER_OPTIONS), "-u$(sernum) $(ioport),$(irq)")

waitfor clause

The waitfor clause looks like this:

waitfor (pathname [, timeout] )

This clause makes enum-devices wait for up to timeout tenths of a second for pathname to appear. If you don't specify timeout, enum-devices waits for 10 seconds.

echo clause

The echo clause takes this form:

echo (string [, output_file] )

It echoes string to output_file. If this is the first occurrence of an echo to the file for this invocation of the configuration manager, enum-devices erases output_file before doing the echo. For subsequent occurrences, enum-devices appends to the file. If you don't specify an output_file, the output goes to standard output.

tag clause

The tag clause looks like this:

tag (tag_string)

It gives the name, tag_string, to the subsequent block of action clauses. Use this clause to indicate the commands to run when you use the second form of the requires clause.

config clause

The config clause is in this form:

config (path)

It makes enum-devices load an additional configuration file or directory, as specified by path. This clause works in the same way as the -c command-line option, except that the specified pathname is relative to the configuration file that contains the clause.

use clause

The use clause looks like this:

use (device_list)

When enum-devices encounters this clause, it:


When invoking an action-clause sequence, a number of of special macros are available for expansion. What they are depends on the bus that the device is present on.

For PCI devices, the macros are:

PCI vendor ID.
PCI device ID.
PCI index.
PCI bus number.
PCI function number.

Bus-enumerator protocol

To handle the bus-specific aspects of device enumeration, enum-devices spawns separate bus-enumerator programs. The standard output of these programs is connected to a pipe that enum-devices reads from. As the bus enumerator does its bus scan, it writes lines to standard output describing what it's found. Each line must be written to the pipe atomically. Each line starts with a one-character code (defined in <hw/enumdata.h> in the form ENUMER_CODE_*) and is immediately followed by the process ID of the bus enumerator.

Here are the lines that can be written for each C macro definition:

This line reports a permanently connected device (i.e., one that will never be removed while the system is running):
Dpid  { macro=value }

A sequence of macro names and values follows the D code and pid. If there's more than one macro, separate them with spaces. These are available for expansion in the action clauses that enum-devices invokes for the device.

You must define the following special macros because enum-devices uses them to identify the device:

#define ENUMER_SYM_BUSTYPE      "bus"
#define ENUMER_SYM_VENDOR       "ven"
#define ENUMER_SYM_SUBVENDOR    "dev"
#define ENUMER_SYM_CLASS        "class"
#define ENUMER_SYM_SUBCLASS     "subclass"
This is similar to ENUMER_CODE_DEV_PERM, except that the device might be removed while the system is running:
dpid  { macro=definition }

In addition to the required macro definitions above, be sure to define:

#define ENUMER_SYM_REMOVAL_ID   "removal_id"

The macro value should be a simple integer.

This is similar to ENUMER_CODE_DEV_PERM, except that the indicated device is already running on the system:
apid  { macro=definition }

If another bus enumerator reports the device, its driver shouldn't be started since it's already running.

This line is reported when a device is removed from a running system:
gpid  { macro=definition }

The only required macro definition is the ENUMER_SYM_REMOVAL_ID from above. The value should be the same integer that was used when the device was originally reported. The enum-devices program uses it to figure out which driver process to slay or which pathname to unmount.

This is used for reporting additional buses that need new enumerators started:
Bpid  { macro=definition }

It has the same syntax and requirements as ENUMER_CODE_DEV_PERM.

Write this line when the bus enumerator has finished scanning its bus:

When all the bus enumerators started have written this line, enum-devices invokes the required action clauses (note that ENUMER_CODE_BUS actions are invoked immediately). If no devices may be added/deleted from the bus, the bus enumerator should terminate after writing this line. If there are temporary devices, it should remain running and write ENUMER_CODE_DEV_TEMP and/or ENUMER_CODE_DEV_REMOVED events followed by another ENUMER_CODE_SCAN_DONE as devices are inserted or removed.

Write this line when the bus enumerator detects an error of some kind:
Epid    error_message_text

The enum-devices manager displays the error_message_text displayed to the user.

The enum-devices manager ignores this type of line. You can use it to provide additional information when the bus enumerator is run standalone:
#pid    comment_text


Here's a sample configuration file:

# prefixing generic commands
    # so we can say "pci($(ATI), ....) for readability
    set( ATI, 0x1234 )
    echo( "starting configuration" )

# Start a hard disk driver
    start( devb-ncr8 ncr8 pci=$(index) )

# Start a network driver (currently)
    start( io-pkt-v4, -d speedo pci=$(index) )

# Start a network driver (with mount support)
    requires( io-pkt-v4 )
    start( mount, -T none -o pci=$(index) ne2000 /dev/if0 )

# Start a graphics driver (sorta :-)
    echo( $(ven) $(dev) $(bus) $(device) $(function), /etc/devg.$(hostname) )

# postfixing generic commands
    echo( "Completed configuration" )
  • In the enum-devices configuration file, all text following a number sign (#) up to the end of the line is a comment.
  • The default enum-devices configuration files are for a standard x86 self-hosted implementation. If you use enum-devices in another environment, you may need to modify these default configuration files. For example, if only a subset of the enumerators specified by the default enumerator clause are present on your target system, you must remove from the configuration the enumerator clauses and the associated device statements for the absent enumerators.
  • The device enumerator doesn't start devb-fdc by default. If your system has a floppy drive, you can start the driver manually or uncomment the devb-fdc lines in the /etc/system/enum/devices/block file.