# The Discover Hardware Detection System

### G. Branden Robinson

### John R. Daily

Copyright © 2002 Progeny Linux Systems, Inc.

Copyright © 2002 Hewlett-Packard Company

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Linux is a registered trademark of Linus Torvalds.

$Progeny$

List of Figures
6-1. Linux interface
6-2. XFree86 interface

List of Examples
3-1. The `busclass_list` element
4-1. The `vendor_list` element
5-1. Sample device data
6-1. Defining an interface
6-2. Using the `linux` interface
6-3. Using the `xfree86` interface
7-1. Matching `device` elements
8-1. Using the `version` attribute of the `data` element
9-1. Scan the local buses
9-2. View PCI video cards
9-3. Query for the driver module for XFree86 server version 4.2.0
9-4. Get model and vendor information by type
10-1. Establishing default buses to scan
10-2. A more complex example
14-1. Linux PCI sysdep code

# What Is Discover?

Discover is a tool that reports information about a system's hardware. It uses operating system-dependent modules (selected at build time) to detect what hardware is actually on the system and provides system-independent interfaces for querying XML data sources about this hardware. These data sources contain specific information required to enable support for various devices via defined software interfaces. The tool can be accessed by linking to the Discover library or by calling discover (which itself links to the Discover library) and parsing its output. In the future, other interfaces (for example, modules for interpreted languages such as Perl and Python) may be included.

Why use Discover? There are at least a few reasons:

- Flexibility. Discover is designed from the ground up to be flexible. It is portable to a variety of operating environments, and its modular design supports the addition of arbitrary methods for querying the host operating system (OS) about installed devices. Discover is also designed to be flexible in terms of the types of data that can be retrieved. Discover does not tie the user to retrieving only one type of information, such as the name of the Linux kernel module that should be loaded to support a given device. Instead, Discover supports the association of arbitrary data with hardware devices, typically through specification of an interface to the hardware in question, such as a Linux kernel module or an XFree86 server driver module.

- Updatability. Many hardware-autodetection programs suffer from an inherent limitation in that they are restricted to reading hardware lists or databases that are stored on the local filesystem. This is not an efficient approach in the fast-moving world of consumer computer hardware, with new devices constantly being introduced. A couple of months after the latest version of your OS of choice is released, it may fail to recognize that the latest revision of, for instance, a video chipset is compatible with an older one, and can use the same software interfaces. Discover overcomes this problem by supporting the retrieval of hardware information via HTTP[1] ("over the web"). When HTTP access is impossible, Discover falls back to locally stored hardware lists.

- Portability. On top of its flexibility in terms of system interfaces to hardware, Discover has been written to be broadly portable to all of today's popular POSIX-compliant systems. Discover is not a Linux-only solution. Discover is intended to provide operating system vendors, computer manufacturers, and third-party vendors of software and peripherals with a powerful tool for describing the hardware they support to the interfaces they care about. Because Discover's data sources can be anywhere on the Internet, the OS vendor need not be the sole provider of hardware catalogs.

- Usability. Discover is not an in-house tool designed to solve a narrow class of problems. Discover is designed to be easy to use from the perspectives of the individual system administrator, the applications programmer, and the hardware manufacturer or support staff. Discover's XML database structure, its command-line tools, and its library API are well documented and support extensions to meet diverse demands.

- Freely licensed. Discover has a copyright license that is highly adaptable to the needs of the varied audiences to which Discover is targeted. Under the so-called "UCB/BSD" or "MIT/X Consortium" terms, after the names of American universities and some very well known software projects that used these terms, anyone is free to copy, modify, and distribute the software, and to extend (or not) these same freedoms to those who receive the software. Progeny would like to see Discover adopted by a wide variety of existing software products, such the various GNU/Linux distributions; the FreeBSD, NetBSD, and OpenBSD projects; the GNU Project of the Free Software Foundation; the XFree86 Project; system integrators; and the designers and manufacturers of computer hardware. We believe that Discover's design empowers those with the greatest knowledge of hardware and the software interfaces to that hardware to express that knowledge and make it available to the world, thereby ameliorating an entire class of computer configuration problems. Progeny does not want Discover's licensing to stand in the way of realizing that dream, which is why we have chosen these license terms.

We must take a moment to explain what Discover is not: Discover is not a replacement for the service — usually provided by the underlying operating system kernel or a user-space program that interfaces with it — of simply translating bus-specific vendor and model identifiers to human-readable names. Discover performs its own translations of this data as a convenience for generating human-readable reports, but it does not attempt to enumerate all hardware devices that exist for a particular bus architecture. Rather, Discover is intended only to catalog data for which there is some useful information to impart regarding software interfaces. Facilities already exist in modern operating systems for answering the questions "What is the name of this device?" and "Who manufactured it?" Discover's role is to answer questions like "What Linux kernel module do I need to load for this device to work?" More importantly, Discover will enable you to provide answers in the future to questions you don't even expect to ask today.

Discover is not intended to be a comprehensive hardware-management tool. It is an enabling technology, designed to provide data that a tool layered above it can use. Two applications are provided with Discover to demonstrate how the library can be leveraged: the command-line utility discover, and a Linux kernel module loading script, discover-modprobe, designed to be invoked at system boot time.

This manual is divided into four parts. First, we examine the Discover XML data file format, exploring the elements and attributes used to describe hardware and various interfaces to it. This part will enable you to read and understand a Discover XML file. Next, we offer some recommendations for writing your own Discover XML data. Knowing the syntax is valuable, but knowing how best to take advantage of it is even more useful. We then present the reference pages describing Progeny's Discover-based command-line tools and the configuration files used to control their behavior. You may want to use these references as a guide when implementing your own Discover-based applications. The final part describes the Discover library API so that you can develop your own solutions based on Discover. Appendices offer references to the formal descriptions of the Discover API and XML DTDs.

# I. Data Structure

# Chapter 1. Overview of the Discover Data Format

Most modern computer peripherals contain self-identifying information in a format standardized for the hardware interface (bus). This enables the OS on the host system to query or scan a bus and catalog the devices. In general, the OS stores this information in the same basic format in which it is returned, without translating it more times than necessary for device drivers to communicate with the peripheral. However, this information varies by bus type and is often insufficiently clear for human consumption. Furthermore, many operating systems do not contain a comprehensive database that maps each peripheral to every subsystem running on the OS that may want to communicate with that peripheral. Discover addresses these issues by providing flexible databases stored in XML format.

Extensible Markup Language (XML) is a highly flexible hypertext format. Discover uses XML exclusively to store hardware information externally. Some familiarity with XML syntax is therefore assumed. For more information, see the W3C's XML website.

For a formal description of Discover's XML data format, see the Discover Document Type Definition (DTD) document. The purpose of this document is to present the information in a form digestible by the novice.

Because each hardware bus type, such as PCI or USB, communicates different details about the connected devices (essentially, each one solves the same problem in a different way), Discover has a different set of lists for each bus type. For each bus, up to three lists are stored: a bus class list maps the bus specification's notion of a device type (hereinafter referred to as a "device class" to reduce confusion) to Discover's device types, which are used for running selective queries; a vendor list associates bus-specific vendor identification data with natural-language names for hardware vendors; and a device list contains information specific to individual devices.

# Chapter 2. Master List

When Discover is provided with a URL for the retrieval of hardware information, the data retrieved is expected to be in XML format and to contain further URLs for retrieval.

The root element must be `discover-data`, which has no attributes, and can only contain `location` elements.

The `location` element is always empty, and has three required attributes: `bus`, `type`, and `url`.

`location` Attributes

`type`

  This attribute can have one of these values: `busclass`, `device`, or `vendor`. See Chapter 3, Chapter 4, and Chapter 5.

`url`

  This must be a valid URL containing one of the three types of data lists.

`bus`

  This is the bus to which the URL applies. See Section 3.2.2 for a list of valid bus names.

# Chapter 3. Busclass Lists

As noted in the previous chapter, a busclass list provides a mapping between device classes recognized by the hardware bus and the device type names used by Discover. Because every bus is different, sometimes there is no perfect, one-to-one correspondence between Discover device types and the device classes recognized by a particular bus. This is one reason that the busclass lists, like other types of Discover data lists, are updatable. Revisions in a bus specification may demand updates to the mapping.

The device classes recognized by a bus are typically determined by the specification for the bus as determined by a standards committee or other technical body, and do not change frequently (if at all).

Example 3-1. The `busclass_list` element

    <?xml version="1.0"?>

    <busclass_list bus="usb">
      <busclass id="0202" name="modem"/>
      <busclass id="1030" name="broadband"/>
      <busclass id="0101" name="printer"/>
      <busclass id="ffff" name="imaging"/>
      <busclass id="0206" name="network"/>
      <busclass id="0300" name="humaninput"/>
      <busclass id="ff00" name="video"/>
      <busclass id="0000" name="unknown"/>
      <busclass id="0804" name="removabledisk"/>
    </busclass_list>

In the foregoing example, we can see one possible mapping of the USB bus's numeric device class IDs to Discover's device type names (see Section 3.2.2). The file begins by declaring the version of the XML standard to which it conforms, and then presents data. The format should be fairly familiar to those accustomed to HTML-style structured markup languages.

Not all of Discover's supported device types are listed in the example; for example, `display` is missing. This is not a problem, since not all buses are used for all hardware applications. USB 1.1 would be a poor choice of bus for VGA-compatible display controllers, for instance, because the available bandwidth on the USB 1.1 bus is insufficient to handle typical data loads for such devices.

Another infelicity in the above example is the association of the `ffff` device class ID with the Discover device type `imaging`. In actuality, a device type class of `ffff` in the USB specification indicates a device of an unknown classification. In practice, most consumer-level devices with this device class are scanners, one of the first applications of USB technology in the consumer marketplace. It is possible that in certain deployments, the association of USB's unknown device class ID with Discover's `imaging` device type is suboptimal — another reason the busclass lists are not hard-coded into the library.

## 3.1. The `busclass_list` element

A `busclass_list` element possesses a `bus` attribute and contains one or more `busclass` elements.

### 3.1.1. The `bus` attribute

The `bus` attribute of the `busclass_list` element is set to the name of the bus being described by the busclass list.

The `bus` attribute presently supports the following values:

- `ata`

- `pci`

- `pcmcia`

- `scsi`

- `usb`

We expect to support more buses in the future; `ieee1394` and `sbus` are possible candidates.

## 3.2. The `busclass` element

A `busclass` element possesses two attributes, `id` and `name`, and contains no elements.

### 3.2.1. The `id` attribute

The `id` attribute is set to a bus-specific device class identifier.

### 3.2.2. The `name` attribute

The `name` attribute is set to a Discover device type. Discover's device types are an effort to balance a few criteria:

- Device types ("bus classes" in Discover terminology) defined by the PCI specification

- Bus classes defined by the USB specification

- Bus classes defined by the SCSI specification

- Device types commonly conceived of by the personal computer user

Discover's definitions of device types will not meet with universal agreement; as happens in most categorization problems, some decisions had to be made arbitrarily. Discover does not attempt to solve the general problem of grouping various peripherals into categories; rather, Discover solves the problem for itself and uses bus-specific mappings to translate a device's own notion of its type to Discover's device type.

- `audio`

  A device capable of producing an analog or digital sound signal is an audio device. Typically, any device commonly referred to as a "sound card" is classified by Discover as an audio device.

- `bridge`

  A device that provides access to devices of a different type, commonly on a different bus, is a bridge device. For instance, consumer PCI chipsets often feature a bridge to ATA (also known as IDE) devices.

- `broadband`

  An interface device to a computer communications network implemented on top of a technology not explicitly designed for that purpose is a broadband device. Examples include ISDN terminal adapters as well as DSL and cable "modems"; analog phone-line modems are not included in this classification (see "modem" below).

- `display`

  A device controlled by the host machine's CPU and capable of producing an analog or digital video signal for output purposes is a display device. Typically, any device commonly referred to as a "video card" is classified by Discover as a display device.

- `fixeddisk`

  A high-speed, fixed magnetic storage device such as a hard disk drive is a fixeddisk device. Removable media devices such as floppy disk drives, CD-ROM drives, magneto-optical devices, tape drives, and Compact Flash card readers are not included in this classification.

- `humaninput`

  A device that receives tactile input from a person for the purpose of directing a computer's activity is a humaninput device. Examples include keyboards, mice, trackballs, joysticks, gamepads, digital tablets manipulated with a stylus or finger, and so forth. Input devices that rely upon non-tactile means of determining a person's intent, such as speech-recognition devices or cameras, are not included in this classification.

- `imaging`

  A device that captures still images for input purposes is an imaging device. Scanners and digital cameras are examples of imaging devices. Motion-capture devices such as television tuner cards, webcams, and digital video cameras are not included in this classification.

- `miscellaneous`

  Any device that cannot logically be classified as another device type is a miscellaneous device.

- `modem`

  An analog phone-line modulator/demodulator (modem) is classified by Discover as a modem device. No other kind of device is so classified.

- `network`

  An interface device to a conventional computer data communications network that does not require the use of a terminal adapter is a network device. For example, Ethernet and Token Ring network interface cards are network devices. Analog phone-line modems; terminal adapters for technologies such as ISDN and DSL; and "cable modems" are not "network" devices.

- `optical`

  An optical-technology storage device, often using read-only media, is an optical device. By far the most common examples of these devices are CD-ROM and DVD-ROM drives, including versions of these drives that can "burn" (write to) optical discs.

- `printer`

  A device that renders visual output in a permanent or semi-permanent manner to a physical medium is a printer. Typically, any device colloquially referred to as a "printer" is also classified by Discover as a printer.

- `removabledisk`

  Storage devices that feature removable media using just about any technology except that of magnetic tape, CD-ROM, and DVD-ROM drives are removabledisk devices. Examples include floppy disk drives, magneto-optical drives, and Compact Flash card readers.

- `tape`

  A sequential-access mass storage device using magnetic tape is a tape device. Commonly used for archival and backup purposes, DAT drives are examples of tape devices.

- `video`

  A device that produces a real-time digital video signal for input purposes is a video device. Webcams, digital video cameras, and television tuners are examples of video devices. Note that still digital cameras with "movie" capability are not considered video devices unless they can transmit the live video signal to the host in real time.

# Chapter 4. Vendor Lists

Many buses have vendor identification numbers that are registered with that bus's standardization body and programmed into the devices when they are manufactured. These numbers generally are assigned arbitrarily, and typically have little meaning to the end user; therefore, most hardware detection tools provide a way to translate these numeric vendor IDs to human-readable strings. Thus, instead of knowing that your PCI or AGP video card was manufactured by "1002," you can determine that it was manufactured by "ATI Technologies, Inc."

Example 4-1. The `vendor_list` element

    <?xml version="1.0"?>

    <vendor_list bus="pci">
      <vendor id="0675" name="Dynalink"/>
      <vendor id="0e11" name="Compaq Computer Corporation"/>
      <vendor id="1004" name="VLSI Technology Inc"/>
      <vendor id="1025" name="Acer Incorporated [ALI]"/>
      <vendor id="102b" name="Matrox Graphics, Inc."/>
      <vendor id="109e" name="Brooktree Corporation"/>
    </vendor_list>

The foregoing example is similar in structure to the busclass list example; a numeric vendor ID maps to a vendor name, which can be used by Discover for queries or reports generated for the user's benefit.

## 4.1. The `vendor_list` element

A `vendor_list` element possesses a `bus` attribute and contains one or more `vendor` elements.

### 4.1.1. The `bus` attribute

The `bus` attribute of the `vendor_list` element is set to the name of the bus being described by the vendor list.

The following bus attributes are supported:

- `ata`

- `pci`

- `pcmcia`

- `scsi`

- `usb`

## 4.2. The `vendor` element

A `vendor` element possesses two attributes, `id` and `name`, and contains no elements.

### 4.2.1. The `id` attribute

The `id` attribute is set to a bus-specific vendor identifier.

### 4.2.2. The `name` attribute

The `name` attribute is set to a human-readable vendor identifier, typically the official name of the corporation or other business entity that designed or manufactured that peripheral.

# Chapter 5. Device Lists

The device lists are the heart of Discover's functionality. They are the most frequently updated lists and contain the information of greatest value.

Discover's device lists not only provide a way to identify individual peripherals by name, but also permit the specification of an arbitrary quantity of organized data for each device, supporting an arbitrary number of software interfaces.

| The following is a fictitious example. The information within it is for illustrative purposes only. See Part II in The Discover Hardware Detection System for a discussion of the "real" hardware data as provided by Progeny, and for some suggested conventions on organizing the data namespace.

Example 5-1. Sample device data

    <?xml version="1.0"?>

    <device_list bus="pci">
      <device busclass="1984" model="0101" model_name="Cerebral Reprogrammer" vendor="B16B">
        <data class="linux">
          <data class="module">
            <data class="name">winston</data>
            <data class="options">base_address=0x300 manual_override=0</data>
          </data>
        </data>
        <data class="win2k">
          <data class="hal_driver">
            <data class="StrUglyHungarianNotatedDriverName">settlement</data>
            <data class="flags">NSA_KEY=96b5f3e3283a62c85f6cb6f4017135c2</data>
          </data>
        </data>
      </device>
    </device_list>

The example above includes a `device_list` element containing `device` elements, and a `device` element that defines the device itself, but reserves any software- or interface-specific details to the `data` elements it contains.

The actual data provided in the example is accessed by means of data paths; see Section 5.4 for further information.

## 5.1. The `device_list` element

A `device_list` element possesses a `bus` attribute and contains one or more `device` elements.

### 5.1.1. The `bus` attribute

The `bus` attribute of the `device_list` element is set to the name of the bus described by the device list.

The following bus attributes are supported:

- `ata`

- `pci`

- `pcmcia`

- `scsi`

- `usb`

## 5.2. The `device` element

A `device` element possesses four attributes:

- `busclass`

- `vendor`

- `model`

- `model_name`

All of these attributes must be specified for each `device` element. The `busclass` attribute is set to a busclass identifier, `vendor` to a vendor identifier, `model` to a bus-specific model identifier, and `model_name` to a human-readable vendor identifier, typically the name of the product under which the device reporting the `model` identifier is sold or otherwise distributed.

A `device` element contains zero or more `data` elements.

## 5.3. The `data` element

A `data` element possesses a mandatory `class` attribute, an optional `version` attribute, and zero or more `data` elements.

The ability to nest `data` elements inside other `data` elements affords interface designers and device driver authors the ability to specify a hierarchy of data, instead of being compelled to encapsulate only one piece of data per device for their interface.

### 5.3.1. The `class` attribute

A `class` attribute is set to an arbitrary value determined by an interface designer. For `data` elements whose parent element is a `device` element, this should be the name of the interface being described, such as `freebsd`, `linux`, or `xfree86`.

A `data` element whose parent element is a `data` element should set this attribute to a term reflecting the interface designer's intended data hierarchy. Discover does not mandate any particular hierarchy for interface designers.

### 5.3.2. The `version` attribute

Data elements have an optional attribute named `version`. This indicates a version range applicable to the data contained within the element. The purpose of this attribute is to permit the specification of data that is valid only for a range of versions of the given interface. For example, the Linux kernel changed some of the names of its modules between the 2.2 and 2.4 series.

Discover's range syntax, common in mathematical writings, is expressed as an interval; that is, it consists of a pair of endpoints with a comma between them, and brackets or parentheses as qualifiers for inclusion or exclusion of the endpoints' exact values. For example, the version specification `[1.0, 2.0)` matches any version less than 2.0 and greater than or equal to 1.0. It is the responsibility of the calling environment to specify the version of the interface actually in use. In other words, the Discover library does not take it upon itself to determine the currently running version of the Linux kernel, XFree86 X server, CUPS printing daemon, and so forth.

Due to the lack of consistent standards for version numbers (in fact, some version numbers aren't numbers at all), Discover requires simplifications for the `version` attribute. The versions that express the range must be in dotted-decimal form, such as `7.1.0`. The version that is supplied to the Discover library as part of a query (for example, via the `--data-version` argument to discover) may or may not comply with this requirement, but should be expressed such that it compares in a desirable way against version strings that do.

In place of the upper end of the range, `inf` (infinity) can be used if the information is still relevant and should be for forseeable versions.

## 5.4. Accessing the Device Data

Discover data is grouped into hierarchical `data` elements. This data can be accessed via its data path. The data path is the concatenation of the class attribute values of a `data` element and all its parents, separated by slash (`/`) characters. In the following example, `quux` is accessed via the data path "foo/bar":

    <data class="foo">
      <data class="bar">quux</data>
    </data>

In Example 5-1 above, we would determine the name of the Linux kernel module ("winston") for the "Cerebral Reprogrammer" device by referencing the data path `linux/module/name`; similarly, the data path `win2k/hal_driver/flags` returns `NSA_KEY=96b5f3e3283a62c85f6cb6f4017135c2`.

# II. Recommended Data Content Conventions

As discussed in the preface, Discover is not intended to be a replacement for system utilities such as lspci on Linux. A `device` element should exist for a piece of hardware only if there is some interface information to communicate about the hardware; that is, some `data` elements to house within the `device` element. This part of the manual contains Progeny's recommendations on how to organize that information for maximum utility.

# Chapter 6. Data Hierarchy

As discussed in Section 5.4, the XML structure around the data allows for a hierarchical view.

While Discover does not mandate any particular hierarchy or namespace organization for `data` elements, the XML files provided by Progeny express — and some applications based on Discover (such as discover-modprobe) expect — a certain structure for Linux kernel module and XFree86 configuration information.

At Progeny, we have often found it convenient to refer to a top-level `data` element's `class` attribute value as an "interface" (see the following example).

Example 6-1. Defining an interface

    <device busclass="0300" vendor="de8d" model="90a9" model_name="Stingray">
      <data class="xfree86">
        <data class="server" version="[3, 4)">
          <data class="name">XF86_SVGA</data>
        </data>
      </data>
      <data class="openbsd">
        <data class="security_level">untrusted</data>
      </data>
    </device>

In Example 6-1, two interfaces have been defined for the "Stingray" device: `xfree86` and `openbsd`.

## 6.1. Linux Kernel Modules

A hardware device that requires a particular Linux kernel module should have nested `data` elements to describe that module. The top-level `data` element should have a `class` attribute with a value of `linux`. Underneath that should be a `data` element with a `class` of `module`.

Within that `data` element, there should be one or two more, one with a `class` of `name`, and an optional one with a `class` of `options`. The former has as content the name of the module; the latter, options to be passed to modprobe.

Figure 6-1. Linux interface

    /linux
        |
        |-/module
              |
              |-/name
              |
              |-/options

In Figure 6-1, each component of the tree represents a `data` element; the label is the value of its `class` attribute.

If the kernel version affects the choice of module name or options, the top-level `linux` `data` element should have a version range attribute; see Section 5.3.2.

Example 6-2. Using the `linux` interface

    <device busclass="0204" model="1702" model_name="IS64PH ISDN Adapter" vendor="0675">
      <data class="linux">
        <data class="module">
           <data class="name">hisax</data>
           <data class="options">io=0x300 irq=11</data>
        </data>
      </data>
    </device>

See Example 8-1 for guidance on how to specify different Linux kernel modules for the same device, depending on the version of the Linux kernel in use.

## 6.2. XFree86 X Servers

The data hierarchy of a video card device (Discover's `display` type) should include a top-level `data` element with a `class` attribute of `xfree86` (the interface) and likely with a `version` attribute as well; nested within that element will be a `server` `data` element containing a `name` `data` element identifying the name of the server executable. For XFree86 version 4.0 or greater, the `name` will always be `XFree86`, and the `server` `data` element will also contain a `device` `data` element, which contains one or more `data` elements communicating information to be stored in the `XF86Config` file. The children of the `device` `data` element are named in correspondence with the syntax of the `XF86Config` file's `Device` section; see the XF86Config manual page for further information. In particular, note that in many cases only a `driver` `data` element is necessary.

Figure 6-2. XFree86 interface

    /xfree86
        |
        |-/server
              |
              |-/name
              |
              |-/device
                    |
                    |-/driver
                    |
                    |-/chipid
                    |
                    |-/chipset
                    |
                    |-/ramdac
                    |
                    |-/dacspeed
                    |
                    |-/videoram
                    |
                    |-/options
                    |
                    |-...

Figure 6-2 illustrates the `xfree86` interface. Example 6-3 shows how you might write `xfree86` interface information for a Discover `display` device.

Example 6-3. Using the `xfree86` interface

    <device busclass="0300" vendor="1002" model="4654" model_name="Mach64 VT [264VT FT]">
      <data class="xfree86">
        <data class="server" version="[4, inf)">
          <data class="name">XFree86</data>
          <data class="device">
            <data class="driver">ati</data>
          </data>
        </data>
        <data class="server" version="(0, 4)">
          <data class="name">XF86_Mach64</data>
        </data>
      </data>
    </device>

## 6.3. Locally-Defined Interfaces

Progeny recommends that publicly distributed Discover XML files avoid using the interface name `local`; that is, a `class` attribute value of `local` in a top-level `data` element. This means that data paths such as `local/foo/bar` should not be defined in a public Discover XML file, but both `foo/bar/local` and `foo/local/bar` are okay.

The intention is to reserve this part of the namespace for users' experiments with defining their own — and possibly future, widely adopted — interface definitions for Discover data. An interface definition could thus be "beta tested" by a person or organization to ensure that it is efficiently structured before it is unleashed upon the world elsewhere in the namespace, where people may write tools that expect to be able to resolve the interface definition's data paths.

Likewise, Progeny recommends that authors of applications that use Discover avoid traversing into a top-level `local` `data` element, which may impose an undesirable support burden on the designers of the interface while they are still working out their design. (The application also may not find the data it desires, or may not get back what it expects.)

# Chapter 7. Why Order Matters

When searching device elements, the first exact match will be selected. Subsequent matches are ignored.

Specifically, three comparisons are made:

1. The hardware must provide identification that matches attributes of the `device` element. As an example, a PCI device supplies numeric vendor and model identifiers, which are used to match the `model` and `vendor` attributes.

2. The `class` attributes of child `data` elements must match the data path as given to the library for searching.

3. The first version range, if any, associated with the nested `data` elements must encompass any version provided by the client.

Example 7-1. Matching `device` elements

Assume that the path `linux/module/name` is provided, along with a version of 2.4.2. The following is sample data; the `device` elements may be from the same or different data files.

    <device busclass="0000" vendor="102f" model="5555" model_name="100VG ethernet">
      <data class="linux" version="[2.4, inf)">
        <data class="modules">
            <data class="name">vg100</data>
        </data>
      </data>
      <data class="linux" version="[2.0, 2.2)">
        <data class="module">
            <data class="name">vg100</data>
            <data class="options">io=0x300</data>
        </data>
      </data>
    </device>

    <device busclass="0000" vendor="102f" model="5555" model_name="100VG ethernet">
      <data class="linux">
        <data class="module">
            <data class="name">vg100new</data>
        </data>
      </data>
      <data class="linux" version="[2.4, inf)">
        <data class="module">
            <data class="name">vg100old</data>
        </data>
      </data>
    </device>

  This item is the first one scanned, and would match, except that the requested data path includes "module" as a component, not "modules" as specified here.
  This item doesn't match because the provided range is outside the limits defined by the element. (2.4.2 is not greater than or equal to 2.0 and less than 2.2.)
  This item matches because no range is given, so "vg100new" is the value returned.
  This is the nearest match, but the Discover library will never select it because its previous sibling has no version range, and thus will catch any version provided.

# Chapter 8. Using Data Versioning

## 8.1. Specifying a Range

Because multiple versions of a software interface often are in simultaneous deployment, Progeny recommendeds that the upper bound of a `data` element's `version` attribute be defined as the first version that is inconsistent with the information provided within it, and that the upper end of the interval be open (terminated with a parenthesis). As an example, suppose we know that the name of the Linux kernel module to drive the RealTek RTL-8139 Ethernet device was `rtl8139` in the 2.2 kernel series and `8139too` in the 2.4 series. To express this, we would say the following:

Example 8-1. Using the `version` attribute of the `data` element

    <device_list bus="pci">
    <device busclass="0200" model="8139" model_name="RTL-8139" vendor="10ec">
      <data class="linux" version="[2.4,inf)">
        <data class="module">
           <data class="name">8139too</data>
        </data>
      </data>
      <data class="linux" version="[2.2,2.4)">
        <data class="module">
           <data class="name">rtl8139</data>
        </data>
      </data>
    </device>
    </device_list>

In the first data element, for instance, we would not use a version attribute of `[2.2.0,2.2.19]` because it is needlessly specific. What happens if the Linux kernel developers release Linux kernel 2.2.20? By saying `[2.2,2.4)`, we "catch" everything in the kernel 2.2 series[2] — past, present, and future.

## 8.2. How the Discover Library Matches a Range

The data files will be searched in order; the first data path that matches the version range or doesn't have a version range will be returned.

Recalling the discussion in Section 5.3.2, if you want the first data element matching the requested data path to also be the "fallback" element if no version range applies, you can duplicate that data element and place it at the end. However, a better practice is to make certain that all reasonable versions will match one of the ranges, and that the first range listed has an open-ended high end, such as `[2.4, inf)` for Linux kernel modules in Example 8-1. This will have the effect of "assuming" that all unversioned requests for `linux` data will be for Linux kernel 2.4 or later.

# III. Command-Line Tools

# Chapter 9. discover Manual Page

# discover

## Name

discover -- hardware detection utility

## Synopsis

discover [DATA_OPTIONS] [DISPLAY_OPTIONS] [--bus-summary] [bus...]

discover [DATA_OPTIONS] [DISPLAY_OPTIONS] --type-summary [type...]

discover [DATA_OPTIONS] --data-path=`path/to/data`... [--data-version=`version`] [--normalize-whitespace] [--format=`format string`] [type | id...]

DATA_OPTIONS

  - `-d | --disable-bus=`bus``

  - `-e | --enable-bus=`bus``

  - `--insert-url=`url``

  - `--append-url=`url``

  - `-v | --verbose`

DISPLAY_OPTIONS

  - `--model | --no-model`

  - `--model-id | --no-model-id`

  - `--vendor | --no-vendor`

  - `--vendor-id | --no-vendor-id`

## Description

discover provides an extensible hardware detection and reporting interface. Hardware information is stored in an XML data format and can be retrieved across the network.

Fundamental modes of operation:

- Display a list of hardware devices based on type of device or system bus on which the devices reside, via `--type-summary` or `--bus-summary` (the latter of which is the default behavior).

- Query specified data for attached hardware, via `--data-path`.

## Options

`-h | --help`

  Display a simple help message.

`-v | --verbose`

  Instruct the tool to provide feedback as it operates. This will affect the output as discover parses certain arguments, so this should appear early in the command line.

`-V | --version`

  Display the tool name and version.

`-b | --bus-summary`

  This is the default behavior: Display basic information regarding all devices on the appropriate buses. See Selecting Buses.

`-t | --type-summary`

  Summarize devices by class of hardware. Examples of valid device types include `broadband`, `fixeddisk`, `display`, and `network`. See Device Types.

`--data-path=`path/to/data``

  Query matching devices for detailed information. Device-specific data is stored in a hierarchical fashion, and the query argument comprises strings naming each level in that hierarchy.

  Typically, the top-level component of the data path will be the "platform" that will need the information, such as `linux` or `xfree86`. For example, to retrieve the Linux kernel module name for a piece of hardware, the `--data-path` argument would be `linux/module/name`.

  If multiple `--data-path` arguments are given and no format string (see `--format`) is provided, only the last path is used.

  See also the `--data-version` argument.

`--data-version=`version``

  Specify a version string for the platform that will use the information specified by the argument to `--data-path`.

  This string must be in dotted-decimal notation in order to be matched against a range of values, and thus may be shorter than the real version.

`--format=`format string``

  Dictate the output of the results of the queries specified by `--data-path` arguments. This format string should follow `printf(3)` specifications, although only `%s` and appropriate flags, precision, and width values are supported (or make sense); literal text and `%%` can also be used. The behavior when the string is poorly formatted is undefined. See also `--normalize-whitespace`.

`-d | --disable-bus=`bus``

  Use this option to override the list of buses to scan by default as defined in `discover.conf`. Use `all` as an argument to disable all buses; this is useful only if followed by `--enable-bus` (or `-e`) arguments.

`-e | --enable-bus=`bus``

  Specify a bus to be scanned.

`--insert-url=`url``

  Insert a URL at the head of the list of network resources to include in the search for hardware information. Earlier data overrides later data; to override the local data sources, insert URLs into the list. See also `--append-url`.

`--append-url=`url``

  Append a URL to the end of the list of network resources to search for hardware information. See also `--insert-url`.

`--model`

  Include the model description in summary information. This is enabled by default.

`--model-id`

  Include the numeric model identifier in summary information.

`--no-model`

  Do not include the model description in summary information.

`--no-model-id`

  Do not include the numeric model identifier in summary information. This is the default.

`--vendor`

  Include the vendor description in summary information. This is enabled by default.

`--vendor-id`

  Include the numeric vendor identifier in summary information.

`--no-vendor`

  Do not include the vendor description in summary information.

`--no-vendor-id`

  Do not include the numeric vendor identifier in summary information. This is the default.

`--normalize-whitespace`

  Consolidate whitespace in the results of a `--data-path` query. The default is not to do so, which faithfully reproduces all text in the raw XML data.

  With this option enabled, leading and trailing whitespace is removed, and any consecutive internal whitespaces are compressed to a single space character.

## Selecting Buses

`discover.conf` defines two lists of system buses: one to scan by default (used by the discover command), and one never to scan (used by the Discover library).

You can override and/or extend the list of default buses with `--disable-bus` and `--enable-bus`. The list of buses not to scan cannot be overridden without changing `discover.conf`, so that list should be used only for buses that may be dangerous to probe.

Both arguments take the string "all" as a value.

If a bus summary is being performed, which is indicated either by the presence of `--bus-summary` or the absence of `--type-summary` and `--data-path`, any unattached arguments on the command line will be interpreted as the only buses to scan. This is equivalent to using `--disable-bus all` before invoking `--enable-bus` for the buses of interest.

The following buses are currently supported by Discover:

- `ata`

- `pci`

- `pcmcia`

- `scsi`

- `usb`

## Device Types

Discover defines its own device types, to which the device types used by each bus are mapped. Discover currently recognizes the following device types:

- `audio`

  A device capable of producing an analog or digital sound signal is an audio device. Typically, any device commonly referred to as a "sound card" is classified by Discover as an audio device.

- `bridge`

  A device that provides access to devices of a different type, commonly on a different bus, is a bridge device. For instance, consumer PCI chipsets often feature a bridge to ATA (also known as IDE) devices.

- `broadband`

  An interface device to a computer communications network implemented on top of a technology not explicitly designed for that purpose is a broadband device. Examples include ISDN terminal adapters as well as DSL and cable "modems"; analog phone-line modems are not included in this classification (see "modem" below).

- `display`

  A device controlled by the host machine's CPU and capable of producing an analog or digital video signal for output purposes is a display device. Typically, any device commonly referred to as a "video card" is classified by Discover as a display device.

- `fixeddisk`

  A high-speed, fixed magnetic storage device such as a hard disk drive is a fixeddisk device. Removable media devices such as floppy disk drives, CD-ROM drives, magneto-optical devices, tape drives, and Compact Flash card readers are not included in this classification.

- `humaninput`

  A device that receives tactile input from a person for the purpose of directing a computer's activity is a humaninput device. Examples include keyboards, mice, trackballs, joysticks, gamepads, digital tablets manipulated with a stylus or finger, and so forth. Input devices that rely upon non-tactile means of determining a person's intent, such as speech-recognition devices or cameras, are not included in this classification.

- `imaging`

  A device that captures still images for input purposes is an imaging device. Scanners and digital cameras are examples of imaging devices. Motion-capture devices such as television tuner cards, webcams, and digital video cameras are not included in this classification.

- `miscellaneous`

  Any device that cannot logically be classified as another device type is a miscellaneous device.

- `modem`

  An analog phone-line modulator/demodulator (modem) is classified by Discover as a modem device. No other kind of device is so classified.

- `network`

  An interface device to a conventional computer data communications network that does not require the use of a terminal adapter is a network device. For example, Ethernet and Token Ring network interface cards are network devices. Analog phone-line modems; terminal adapters for technologies such as ISDN and DSL; and "cable modems" are not "network" devices.

- `optical`

  An optical-technology storage device, often using read-only media, is an optical device. By far the most common examples of these devices are CD-ROM and DVD-ROM drives, including versions of these drives that can "burn" (write to) optical discs.

- `printer`

  A device that renders visual output in a permanent or semi-permanent manner to a physical medium is a printer. Typically, any device colloquially referred to as a "printer" is also classified by Discover as a printer.

- `removabledisk`

  Storage devices that feature removable media using just about any technology except that of magnetic tape, CD-ROM, and DVD-ROM drives are removabledisk devices. Examples include floppy disk drives, magneto-optical drives, and Compact Flash card readers.

- `tape`

  A sequential-access mass storage device using magnetic tape is a tape device. Commonly used for archival and backup purposes, DAT drives are examples of tape devices.

- `video`

  A device that produces a real-time digital video signal for input purposes is a video device. Webcams, digital video cameras, and television tuners are examples of video devices. Note that still digital cameras with "movie" capability are not considered video devices unless they can transmit the live video signal to the host in real time.

## Examples

Example 9-1. Scan the local buses

    # discover
    Intel Corporation 82815 Chipset Host Bridge and Memory Controller Hub
    unknown unknown
    unknown unknown
    unknown unknown
    Intel Corporation 82815 Chipset IDE controller
    Intel Corporation 82815 Chipset USB (A)
    Intel Corporation 82815 System Management bus controller
    ATI Technologies, Inc. Rage 128 Pro GL [PF]
    3Com Corporation 3c905C-TX [Fast Etherlink]
    Ensoniq ES1371 [AudioPCI-97]
    unknown unknown

Example 9-2. View PCI video cards

    # discover -v --type-summary --disable-bus all --enable-bus pci display
    Disabled pci
    Disabled pcmcia
    Disabled scsi
    Disabled usb
    Enabled pci
    Loading XML data... pci Done
    Scanning buses... pci Done
    ATI Technologies, Inc. Rage 128 Pro GL [PF]

Example 9-3. Query for the driver module for XFree86 server version 4.2.0

    # discover --data-path=xfree86/server/device/driver --data-version=4.2.0 display
    ati

Example 9-4. Get model and vendor information by type

    $ discover -t --no-model
    Intel Corporation
    NVIDIA Corporation
    3Com Corporation
    $ discover -t --no-vendor
    82815 System Management bus controller
    Vanta [NV6]
    3c905C-TX [Fast Etherlink]

## Files

`/etc/discover.conf.d`

  The directory containing configuration files that control the default behavior for both the discover tool and the Discover library.

`file:///lib/discover/list.xml`

  An XML file containing URLs with hardware information. This list can be extended with `--append-url` and `--extend-url`.

## Authors

Josh Bressers, John R. Daily, and G. Branden Robinson developed the current implementation of Discover for Progeny Linux Systems.

The Linux implementation of the system-dependent interfaces is derived from detect, by MandrakeSoft SA.

## See Also

discover.conf(5), discover-modprobe(8)

# Chapter 10. `discover.conf` Manual Page

# discover.conf

## Name

discover.conf -- configuration file format for discover(1)

## Description

Discover looks for configuration files in a configuration directory, containing a number of files. These define the system buses that should be scanned by default, those that should never be scanned, and the URLs for hardware data files beyond the local copy provided with the software.

The file format is XML; the DTD is provided with the Discover software, and can be used for informational or validation purposes.

## Examples

Example 10-1. Establishing default buses to scan

    <?xml version="1.0"?>

    <!DOCTYPE conffile SYSTEM "conffile.dtd">

    <conffile>
      <busscan scan="default">
        <bus name="ata"/>
        <bus name="pci"/>
        <bus name="pcmcia"/>
        <bus name="scsi"/>
        <bus name="usb"/>
      </busscan>
    </conffile>

Example 10-2. A more complex example

    <?xml version="1.0"?>

    <!DOCTYPE conffile SYSTEM "conffile.dtd">

    <conffile>
      <busscan scan="default">
        <bus name="ata"/>
        <bus name="pci"/>
        <bus name="pcmcia"/>
        <bus name="usb"/>
      </busscan>
      <!-- My ancient SCSI card locks up when probed -->
      <busscan scan="never">
        <bus name="scsi"/>
      </busscan>
      <data-sources>
        <data-source url="http://www.example.com/discover/xfree86.xml"
                     label="Updated XFree86 hardware information">
      </data-sources>
    </conffile>

## Authors

Josh Bressers, John R. Daily, and G. Branden Robinson developed the current implementation of Discover for Progeny Linux Systems.

The Linux implementation of the system-dependent interfaces is derived from detect, by MandrakeSoft SA.

## See Also

discover(1)

# Chapter 11. discover-modprobe Manual Page

# discover-modprobe

## Name

discover-modprobe -- kernel module loading using discover(1)

## Synopsis

discover-modprobe [-n] [-v]

## Description

discover-modprobe loads kernel modules identified by discover. It will typically be invoked automatically at boot time.

## Options

`-n`

  Echo the modprobe invocations instead of running them.

`-v`

  Be verbose.

## Files

`/etc/discover-modprobe.conf`

  This configuration file defines the types of modules to load by default, and specific modules not to load.

`/var/lib/discover/crash`

  A crash file written and erased each time discover-modprobe attempts to load a module. If the file lingers, the computer is assumed to have crashed while loading that module, and the module name is added to `discover-modprobe.conf` as a module to skip in the future.

## See Also

discover-modprobe.conf(5), modprobe(8), discover(1)

# Chapter 12. `discover-modprobe.conf` Manual Page

# discover-modprobe.conf

## Name

discover-modprobe.conf -- configuration file for discover-modprobe(5)

## Description

`discover-modprobe.conf` is the configuration file for discover-modprobe, which is responsible for retrieving and loading kernel modules.

| This file is a shell script, and as such is subject to a string variable assignment syntax. No space is allowed between the variable name, the equal (=) sign, and the value(s) assigned. If multiple values are to be assigned, the list must be space-delimited with surrounding quotes.

Two directives can be used in this file: `types` and `skip`. Both can be defined multiple times.

`types`

  This describes the classes of hardware that should be scanned and queried.

`skip`

  These modules should never be loaded. See the "Files" section for details on the mechanism for generating these entries automatically.

## Files

`/var/lib/discover/crash`

  A crash file written and erased each time discover-modprobe attempts to load a module. If the file lingers, the computer is assumed to have crashed while loading that module, and the module name is added to `discover-modprobe.conf` as a module to skip in the future.

## See Also

discover-modprobe(8), modprobe(8), discover(1)

# IV. Library

# Chapter 13. The Discover Library

## 13.1. Library Design Principles

Lazy allocation is used throughout Discover. This means that there are no "init" functions, and no functions to scan the bus. Instead, retrieval functions scan or initialize as necessary. Each of these retrieval functions has an equivalent function for freeing the allocated memory. This is valuable to long-lived processes to aid in memory management, but even short-lived processes may want to use them to force reloading of the information.

## 13.2. Discover Data Sources

Discover knows about one data source by default: the local data from the `discover-data` package. Additional sources can be added with the `discover_conf_append_url` and `discover_conf_insert_url` functions. As their names suggest, they append or insert URLs on the data source list. Earlier data overrides later data; to override the local data sources, insert URLs.

## 13.3. The Bus Map

Most high-level operations begin at the bus map. Bus maps (discover_bus_map_t) are retrieved with calls to `discover_conf_get_bus_map` or `discover_conf_get_bus_map_by_name`. `discover_conf_get_bus_map` returns an array of maps, one for each supported bus, with the last element being all 0s. `discover_conf_get_bus_map_by_name` returns the map for the named bus. The map contains pointers to all the functions that operate on the bus, as well as the `scan_default` variable, which determines whether the bus is scanned by default. There is also a `scan_never` variable, but it is for internal use only. The name of the bus is stored in the `name` variable.

The following functions are available in the bus map. The "get" functions take a single discover_error_t argument and return a list of discover_device_t structures, while the "free" functions take no arguments and return no value.

`get_devices`

  Retrieve the list of devices found on this bus. Returns NULL if the bus is not present on the system, or if no devices are attached to it.

`xml_get_busclasses`

  Retrieve the list of busclasses for this bus (from the XML data sources).

`xml_get_devices`

  Retrieve the list of devices for this bus (from the XML data sources). Note that this is the list of devices that Discover knows about, not the list of devices present on the system.

`xml_get_vendors`

  Retrieve the list of vendors for this bus (from the XML data sources).

`xml_get_busclass_urls`

  Retrieve the list of URLs from which busclass data is retrieved. This function is probably not useful to most clients.

`xml_get_device_urls`

  Retrieve the list of URLs from which device data is retrieved. This function is probably not useful to most clients.

`xml_get_vendor_urls`

  Retrieve the list of URLs from which vendor data is retrieved. This function is probably not useful to most clients.

`free_devices`

  Free the list of devices.

`xml_free_busclasses`

  Free the list of busclasses.

`xml_free_devices`

  Free the list of devices (the XML data, not the list of devices found on the system).

`xml_free_vendors`

  Free the list of vendors.

`xml_free_busclass_urls`

  Free the list of busclass URLs.

`xml_free_device_urls`

  Free the list of device URLs.

`xml_free_vendor_urls`

  Free the list of vendor URLs.

## 13.4. Scanning the System

Discover provides a few ways to scan the system for information.

You can walk the bus map:

    for (i = 0; busmap[i].name; i++) {
        if (busmap[i].scan == DISCOVER_SCAN_DEFAULT) {
            devices = busmap[i].get_devices(&status);
            check_status(status);
            do_something_cool(devices);
        }
    }

You can scan a specific bus:

    devices = discover_get_pci_devices(&status);
    check_status(status);
    do_something_cool(devices);

Perhaps most usefully, you can scan for devices of a specific type:

    devices = discover_device_find("video", &status);
    check_status(status);
    do_something_video(devices);

## 13.5. Using discover_device_t Structures

Now that you have some device structures, what can you do with them? The most interesting operation is retrieving data with `discover_device_get_data`. Also available are `discover_device_get_vendor_name`, `discover_device_get_model_name`, `discover_device_get_model_id`, and `discover_device_get_vendor_id`.

`discover_device_get_data` takes a data path and a version number and searches for the first data structure that matches.

`discover_device_get_vendor_name` returns the human-readable name for the device's vendor.

`discover_device_get_model_name` returns the human-readable name for the device's model.

`discover_device_get_model_id` returns the bus-specific ID for the device model.

`discover_device_get_vendor_id` returns the bus-specific ID for the device vendor.

# Chapter 14. System Dependencies

## 14.1. API

The system-dependent code (sysdeps) that must be custom-written for each operating system conforms to a very simple API. Discover invokes `_discover_get_`busname`_raw()` with no arguments, and expects a linked list of discover_sysdep_data_t structures in return.

The discover_sysdep_data_t structures should contain as much descriptive information as they can regarding the devices discovered. Specifically, the three pieces of information desired are the busclass (device type), vendor identifier, and model identifier, which is a unique identification string that the vendor has provided for the given piece of hardware.

Example 14-1. Linux PCI sysdep code

    #include <config.h>

    #include <stdio.h>
    #include <stdlib.h>

    #include <sysdep.h>

    discover_sysdep_data_t *
    _discover_get_pci_raw(void)
    {
        FILE *f;
        char *line = NULL;
        size_t len = 0;
        discover_sysdep_data_t *head = NULL, *node, *last = NULL;
        unsigned int id;

        if ((f = fopen(PATH_PROC_PCI, "r"))) {
            while (getline(&line, &len, f) >= 0) {
                if (line[0] == '\n' || line[0] == '#') {
                    continue;
                }

                node = _discover_sysdep_data_new();
                sscanf(line, "%*04x\t%08x", &id);
                node->vendor = (id >> 16);
                node->model = id & 0xffff;

                if (head == NULL) {
                    head = node;
                    last = head;
                } else {
                    last->next = node;
                    last = node;
                }
            }
            free(line);
            fclose(f);
        }
        return head;
    }

# Appendix A. Discover API Reference

The API reference is here.

# Appendix B. Discover DTD

    <!-- $Progeny$ -->

    <!ELEMENT discover-data (location)*>

    <!ELEMENT location EMPTY>
    <!ATTLIST location bus          NMTOKEN #REQUIRED
                       type         NMTOKEN #REQUIRED
                       url          CDATA   #REQUIRED>

    <!ELEMENT busclass_list (busclass)*>
    <!ATTLIST busclass_list bus NMTOKEN #REQUIRED>

    <!ELEMENT busclass EMPTY>
    <!ATTLIST busclass id           NMTOKEN #REQUIRED
                       name         NMTOKEN #REQUIRED>

    <!ELEMENT vendor_list (vendor)*>
    <!ATTLIST vendor_list bus NMTOKEN #REQUIRED>

    <!ELEMENT vendor EMPTY>
    <!ATTLIST vendor id             CDATA #REQUIRED
                     name           CDATA #REQUIRED>

    <!ELEMENT device_list (device)*>
    <!ATTLIST device_list bus NMTOKEN #REQUIRED>

    <!ELEMENT device (data)*>
    <!ATTLIST device busclass       NMTOKEN #REQUIRED
                     model          CDATA #DEFAULT default
                     model_name     CDATA   #REQUIRED
                     vendor         CDATA #REQUIRED>

    <!ELEMENT data (#PCDATA|data)*>
    <!ATTLIST data class		NMTOKEN	#REQUIRED
                   version		CDATA	#IMPLIED>

    <!-- vim:set ai et sts=8 sw=8 tw=0: -->

# Appendix C. Discover Configuration File DTD

    <!-- $Progeny$ -->

    <!ELEMENT conffile (busscan*,data-sources?)>

    <!ELEMENT data-sources (data-source)*>
    <!ELEMENT data-source EMPTY>
    <!ATTLIST data-source url          CDATA #REQUIRED
                          label        CDATA #IMPLIED
                          place        NMTOKEN #IMPLIED>

    <!ELEMENT busscan (bus)*>

    <!-- The attributes will likely be handled by different parts of        -->
    <!-- Discover. If there is a list of buses never to scan, the library   -->
    <!-- should be aware of it. If there is a list of buses to scan by      -->
    <!-- default, that will be of interest to the client tool.              -->
    <!ATTLIST busscan scan (default|never) #REQUIRED>

    <!ELEMENT bus EMPTY>
    <!ATTLIST bus name              NMTOKEN #REQUIRED>

# Appendix D. Licensing Issue on the Linux Sysdeps

It should be noted that the Linux-specific files in the `sysdeps/linux` directory of the source distribution are derived from code written for the Detect library by MandrakeSoft SA, and are licensed under the GNU Project's General Public License (GPL).

Note that section 2 of the GPL places requirements on derived works that prevent licensees from exercising some of the permissions granted under the license on the rest of Discover. However, not everyone who modifies or distributes Discover will necessarily be subject to the terms of the GPL. If you do not compile, use, or distribute the Linux sysdeps (for instance, if you are building Discover for FreeBSD), then the license terms on them do not attach.

We realize, however, that it is desirable that all of Discover be under the the same license terms. There are a few possible solutions to this problem:

- If you do not need the Linux sysdeps, you can delete them from your copy of Discover.

- You can rewrite the Linux sysdeps. The resulting code will be your work, so the only limitations on you will be those imposed by Discover's license. If you do so, we encourage you to license your rewrite under the same terms as the rest of Discover — in that event, Progeny will be happy to incorporate your code into a future release of Discover.

- You can contact MandrakeSoft SA and negotiate a different license to their code that is used in the Linux sysdeps.

- You can contact MandrakeSoft SA and attempt to persuade them to relicense their code that is used in the Linux sydeps under the terms used by the rest of Discover. (MandrakeSoft SA would not have to abandon or assign their copyright.) If you succeed in this effort, please let Progeny know and we will update the license terms on our copy of the MandrakeSoft SA code.

- You can wait; eventually Progeny employees, or some volunteer, will rewrite the Linux sysdeps and license them under the terms that the rest of Discover uses.

The foregoing discussing is not legal advice and makes no claim to be such. It is a layperson's understanding of the licensing issues from a software developer's perspective. Progeny makes no warranties or guarantees as to the accuracy of the above analysis in a legal context. If you require a professional legal opinion, consult attorneys specializing in copyright and licensed to practice in the jurisdictions of interest to you or to your organization.

### Notes

[1] | Other protocols such as FTP are available but deprecated; Discover uses integrity verification mechanisms such as MD5 checksums in the HTTP protocol.
[2] | We would say `[2.2,2.3)` instead, but, like many Free Software projects, the Linux kernel uses odd minor version numbers to denote unstable, development series of the software, and even minor version numbers to denote stable, production series of the software. In the example, then, we arbitrarily treat all 2.3 series kernels the same as 2.2 kernels.