# Device Information Files

Device information files (`.fdi` files is a shorthand) are used to merge arbitrary properties onto device objects. The way device information files works is that once all device properties are merged onto a device object it is tried against the set of installed device information files. Device information files are used for both merging facts and policy settings about devices.

## Matching

Each device information file got a number of `<match key="some_property" [string|int|bool|..]="required_value" >` directives that is tested against the properties of the device object. If all the match directives passes then the device information can include `<[merge|append|prepend|addset] key="some_property" type="[string|int|bool|..]">` directives to respectively merge new properties or append to existing properties on the device object. It's important to emphasize that any previously property stemming from device detection can be overridden by a device information file.

The `<match>`, `<merge>`, `<append>`, `<prepend>` and `<addset>` directives always requires the `key` attribute which must be either a property name on the device object in question or a path to a property on another device object. The latter case is expressed either through direct specification of the UDI, such as `/org/freedesktop/Hal/devices/computer:foo.bar` or indirect references such as `@info.parent:baz` where the latter means that the device object specified by the UDI in the string property `info.parent` should be used to query the property `baz`. It is also possible to use multiple indirections, e.g. for a volume on a USB memory stick the indirection `@block.storage_device:@storage.originating_device:usb.vendor_id` will reference the `usb.vendor_id` property on the device object representing the USB interface.

When the property to match have been determined a number of attributes can be used within the `<match>` tag:

- `string` - match a string property; for example `<match key="foo.bar" string="baz">` will match only if 'foo.bar' is a string property assuming the value 'baz'.

- `string_outof` - work like `string` but the match is done against a list of strings separated by ';'. For example: `<match key="system.hardware.product" string_outof="Satellite A30;Portable PC">` In this example the line matches if `system.hardware.product` is exactly 'Satellite A30' or 'Portable PC'.

- `int` - match an integer property

- `int_outof` - work like `int` but the match is done against a list of integer separated by ';'. For example: `<match key="usb.product_id" int_outof="0x1007;0x1008;0x1009">` In this example the line matches if `usb.product_id` is 0x1007, 0x1008 or 0x1009.

- `uint64` - match property with the 64-bit unsigned type

- `bool` - match a boolean property

- `double` - match a property of type double

- `exists` - used as `<match key="foo.bar" exists="true">`. Can be used with 'true' and 'false' respectively to match when a property exists and it doesn't.

- `empty` - can only be used on string or strlist properties with 'true' and 'false'. The semantics for 'true' is to match only when the string is non-empty.

- `is_ascii` - matches only when a string property contain only ASCII characters. Can be used with 'true' or 'false'.

- `is_absolute_path` - matches only when a string property represents an absolute path (the path doesn't have to exist). Can be used with 'true' or 'false'.

- `sibling_contains` - can only be used with string and strlist (string list). For a string key this matches when a sibling item contains the (sub-)string in the same property. For a string list, this is if a string matches an item in the list.

- `contains` - can only be used with string and strlist (string list). For a string key this matches when the property contains the given (sub-)string. For a string list this match if the given string match a item of the list.

- `contains_ncase` - like `contains` but the property and the given key are converted to lowercase before check.

- `contains_not` - can only be used with strlist (string list) and string properties. For a string list this match if the given string not match any of the item of the list (or the property is not set for the device). For a string this match of the property not contains the (sub-)string. You can use this attribute to construct if/else blocks together with e.g. `contains`.

- `contains_outof` - like `contains` but can be used only with strings and the match is done against a list of (sub-)strings separated by ';'. For example: `<match key="system.hardware.product" contains_outof="D600;D610;C540">` In this example the line matches if `system.hardware.product` contains D600, D610 or C540.

- `prefix` - can only be used with string properties. Matches if property begins with the key.

- `prefix_ncase` - like `prefix` but the property and the given key are converted to lowercase before the check.

- `prefix_outof` - like `prefix` but the match is done against a list of prefixes separated by ';'. For example: `<match key="system.hardware.product" prefix_outof="1860;2366;2371">` In this example the line matches if `system.hardware.product` starts with 1860, 2366 or 2371.

- `suffix` - can only be used with string properties. Matches if property ends with the key.

- `suffix_ncase` - like `suffix` but the property and the given key are converted to lowercase before the check.

- `compare_lt` - can be used on int, uint64, double and string properties to compare with a constant. Matches when the given property is less than the given constant using the default ordering.

- `compare_le` - like `compare_lt` but matches when less than or equal.

- `compare_gt` - like `compare_lt` but matches when greater than.

- `compare_ge` - like `compare_lt` but matches when greater than or equal.

- `compare_ne` - like `compare_lt` but matches when not equal.

## Merging

The `<merge>`, `<append>`, `<prepend>` and `<addset>` directives all require the `type` attribute which specifies what to merge. The following values are supported

- `string` - The value is copied to the property. For example `<merge key="foo.bar" type="string">baz</merge>` will merge the value 'baz' into the property 'foo.bar'.

- `strlist` - For `<merge>` the value is copied to the property and the current property will be overwritten. For `<append>` and `<prepend>` the value is append or prepend to the list as new item. For `<addset>` the strlist is treated as a set and the value is appended if, and only if, the value doesn't exist already. Usage of `<copy_property>` overwrite the complete list with the value of the given property to copy from.

- `bool` - Can merge the values 'true' or 'false'

- `int` - Merges an integer

- `uint64` - Merges an unsigned 64-bit integer

- `double` - Merges a double precision floating point number

- `copy_property` - Copies the value of a given property - supports paths with direct and indirect UDI's. For example `<merge key="foo.bar" type="copy_property">@info.parent:baz.bat</merge>` will merge the value of the property `baz.bat` on the device object with the UDI from the property `info.parent` into the property `foo.bar` on the device object being processed.

The `<remove>`, directive require only a key and can be used with all keys. For `strlist` there is additionally a special syntax to remove a item from the string list. For example to remove item 'bla' from property 'foo.bar': `<remove key="foo.bar" type="strlist">bla</remove>`

## Search Paths

Device Information files are read from two directories

- `/usr/share/hal/fdi` - for files provided by packages

- `/etc/hal/fdi` - for files provided by the system administrator / user

in exactly that order. This means that the files provided by the system administrator will be processed last such that they can overwrite / change properties caused by the device information files provided by packages. The following directory structure is used in `/usr/share/hal/fdi`

- `information` - device information files used to merge device information

  - `10freedesktop` - included with the hal package

  - `20thirdparty` - from a 3rd party, not included in hal package

- `policy` - device information files to merge policy properties such as addons or callouts.

  - `10osvendor` - included with the hal package

  - `20thirdparty` - from a 3rd party, not included in hal package

- `preprobe` - device information files read before probing devices

  - `10osvendor` - included with the hal package

  - `20thirdparty` - from a 3rd party, not included in hal package

As evident, third party packages should drop device information files in

- `/usr/share/hal/fdi/information/20thirdparty`

- `/usr/share/hal/fdi/policy/20thirdparty`

- `/usr/share/hal/fdi/preprobe/20thirdparty`

The `/etc/hal/fdi` tree uses this layout

- `information` - device information files used to merge device information

- `policy` - device information files to merge policy properties such as addons or callouts.

- `preprobe` - device information files to read before probing devices

All device information files are matched for every hal device object in the following order.

1. When a device is discovered, the `preprobe` device information files (e.g. all files from `/usr/share/hal/fdi/preprobe` and `/etc/hal/fdi/preprobe`) are processed.

   Typically, this class of device information files is used to tell HAL to leave the device alone by setting the bool property `info.ignore` to TRUE. It can also be used to run programs, preprobe callouts, prior to normal device investigation.

2. HAL now runs the preprobe callouts.

3. HAL now probes/investigates the device.

4. All the `information` device information files (e.g. all files from `/usr/share/hal/fdi/information` and `/etc/hal/fdi/information`) are processed.

   These device information files are typically used to associate extra information with a device object.

5. All the `policy` policy information files (e.g. all files from `/usr/share/hal/fdi/policy` and `/etc/hal/fdi/policy`) are processed.

   These device information files are typically used to associate callouts and addons with a device object.

6. HAL now runs the callouts, starts addons, and then finally announces the device on the system message bus.