hal draft spec
david at fubar.dk
Wed Sep 10 00:47:19 EEST 2003
At http://www.ometer.com/hardware.html Havoc Pennington writes:
> Making Hardware Just Work
> This is a draft document last updated July 10, 2003. Please send
> comments to Havoc.
> That I know of, nobody is working on implementing this yet. You
> should do it!
I'm a first-time poster to OSS lists. If this is the wrong list, I
I also apologize, in advance, for this long mail...
So, I have been playing around with working on a ''hardware abstraction
library'' over the last week. I was inspired by Havoc's paper.
The reason I'm sending this mail is to get some feedback on the
architecture and design before working on a real implementation. Is
anyone else working on this?
I'm hoping this can result in some kind of work leading up to a
freedesktop.org specification and subsequent perhaps a freedesktop.org
I got a prototype implementation with some short cuts relative to my
draft spec below.. I'm prepared, at some point (e.g. when it conforms to
some specification), to release this under a free software license.
Let me try to explain what my prototype currently does. It's supposed,
at best, to be some kind of draft spec..
First a definition: A device is encapsulated by a Device object,
containing the following two entities
o a textual id that uniquely identifies the device. This must be
an ASCII string.
o a set of (key, value) pairs. Key is an ASCII string, while value
is an UTF8 string
PROGRAMS AND LIBRARIES
My prototype is built using D-Bus and it contains the following elements
o libhal - hardware abstraction library
This is the hardware abstraction library, in short it provides
functions named hal_list_devices, hal_device_set_property,
hal_device_get_property as well as notifications when device
a device changes state and when properties change cf. Havoc's
It communicates with hald, the hardware abstraction layer daemon,
using D-Bus. It gets all the devices and their properties using a
single method call. Changes in the hardware list is broadcast from
hald (using org.freedesktop.DBus.broadcast) and received by
processing linking with libhal.
Caveat: Uses a separate thread.
Caveat #2: Could potentially use a lot of memory per process
o hal_hotplug - hardware abstraction library hotplug helper
This is a process that reports when a device is added or removed.
Currently it only support USB devices and Linux. To use it I
change /proc/sys/kernel/hotplug to point to the executable.
o hald - hardware abstraction library daemon
This is a daemon that handles communication with a) processes
linking to libhal; and b) hotplug agents.
For hotplug agents, like USB, it gets the standard USB information.
This information is simply stored as properties in the Device*
A device-driver is searched for, and if one is found additional
properties are merged into the Device* object. Based on these
properties certain things happen as specified in section
Caveat: My current implementation of hald only works with hotplug
devices. It could be integrated to probe hardware using existing
Caveat #2: see DEVICE DESCRIPTIONS
Caveat #3: Device lists are store in-memory
A very simple application using libhal; it simply shows the list of
devices and their properties. This is updated when it changes. This
is my main testbed.
The prototype implementation is currently tied to Linux but moving it to
other OS's should be straightforward. The only real dependency I
explicitly have is dbus-1 (which, btw, is very nice software)
The following properties are always present for a device and must
conform to the the values and semantics below
Bus = usb | pci | bluetooth ... ; Physical bus-type the device is
; attached to. Is Bus the right
; word to use? (think bluetooth)
State = unplugged | ; the device is unplugged (only possible with
disabled | ; the device is disabled (active choice by the
booting | ; the device is booting (e.g. uploading firmware
; or mounting itself into the filesystem)
shutdown | ; the device is shutting down (e.g. unmounting
; itself from the filesystem)
enabled | ; the device is enabled and ready to use
enabled_req_user | ; the device is enabled but requires some
; user configuration (e.g. where to mount
; a storage device etc.) to function
; (see property ConfigureProgram,
error_kernel | ; there was an error loading kernel drivers
; when booting the device
error_bootprog | ; there was an error invoking the Bootprogram
; when booting the device
needs_driver ; the device needs a device-info file.
; Implies, and is implied by, Driver==false
Driver = true | ; A driver was identified for this device
; If this is set to true, then the property
; DriverIdentifier must exist and the value
; must be a unique id of the driver.
; (reverse domainname style)
false ; No driver was identified for this device.
; Desktop Environments should react to this
; and provide means for the user to locate/
; install/force a driver etc.
; (blacklists / whitelists)
For a device with State==enabled|enabled_req_user, the following
fields must be present and conform to the values and semantics below
Vendor = <string> ; Name of the vendor of the device
Product = <string> ; Name of the product this device represents
DriverVendor = <string> ; Name of the vendor of the device driver
Category = Storage | ;For devices that a filesystem can be mapped onto
Camera | ; Still Imaging, camera-like devices
Input | ; Devices that allows the user to interact with
; the host computer
... ; (need to expand on this.. should we fix this
; or can new devices introduce new Categories?
; I think the latter...)
One or more of the following properties may be present for a device. If
they are, they must conform to the values and semantics below
Serial = <string> ; A string unique to the instance of the
; device plugged in
Persistent = true | ; even though the device is not plugged in it
; will still appear in the device list with
; state unplugged. All properties for the device
; will remain persistent (this is useful for
; 'personal' devices such as PDA's, MP3 players
; or cameras)
false ; the device and all it's properties will be
; removed once the device is not present. This
; is the default behaviour.
RequireDisable = true | ; The device requires the user explicitly
; to 'stop' (disable) the device before
; removing it. (This might be useful for
; storage devices)
; Desktop environments SHOULD offer a
; 'stop icon' in the notification area if
; any devices with State==enabled* and
; RequireDisable==true is in the device list
false ; The device doesn't require to be stopped.
; This is the default (think USB HID devices)
BootProgram = /path/to/executable
When a device is just plugged in or enabled, this program is executed.
While the program is running the State property of the device is set to
If the return code is 0 the property State will be set to enabled. This
means that the device is ready to use. If the return code is 1 the
property State will be set to enabled_req_user. This means that input is
required from the user to function properly. Otherwise it will be set
to error_bootprog. This means there was an error booting/configuring
The two arguments to this program is a) the unique id of the
device; and b) the string 'boot'. This way the program can populate the
necessary properties for using the device (using libhal) and create the
necessary /dev files, major/minor numbers, permissions etc.
This program MUST NOT attempt to integrate with the Desktop Environment.
If user intervention is required, then the program can return 1 (to set
the State property to enabled_req_user) and then the Desktop Environment
will prompt the user for configuration.
Optionally, the property ConfigureProgram can be set to HINT the DE
of a program for configuration.. When the DE have gathered input from
the user and added the requried properties from the device, the DE can
prompt hald to run ConfigureProgram again.
Optionally, and orthogonal to setting ConfigureProgram the property
ConfigureRequiredProperties can be set HINT the DE of what the user
needs to configure..
Devices with Bootprograms that return 1, e.g. requires user
intervention, SHOULD set the property Persistent to true
(TODO: security, privileges?)
ShutdownProgram = /path/to/executable
When a device is removed or disabled, this program is executed. While
the program is running the State property of the device is 'shutdown'
The two arguments to this program is a) the unique id of the device and
b) the string 'shutdown'
(TODO: Should an application using libhal be able to veto a shutdown?)
(TODO: can this fail? how should
we handle it?)
(TODO: security, privileges?)
KernelModules = mod1 mod2 ...
A whitespace separated list of kernel modules that will be loaded in
order once the device is inserted just prior to running the Bootprogram.
When the drivers are loading the State property is set to booting
If the loading of the kernel modules fails the State property will be
set to error_kernel
Once the ShutdownProgram is finished these modules will be removed in
the reverse order. (TODO: can this fail?)
ConfigureProgram = /path/to/executable
A program the DE can run if a the State property is set to
enabled_req_user. It is usually supplied by the device vendor. Device
vendors should be discouraged to supply proprietary configuration
programs if a solution not requiring such a program exist.
ConfigureRequiredProperties = Property1 ...
A list of properties that needs to be set before the device is fully
configured. This is normally set when Bootprog returns 1 since this sets
property State to enabled_req_user
If Bus==usb the following properties are always present. See the USB
standard for semantics
usb.idVendor ; hexadecimal
usb.idProduct ; hexadecimal
usb.bcdDevice ; hexadecimal
usb.bDeviceClass ; decimal
usb.bDeviceSubClass ; decimal
usb.bDeviceProtocol ; decimal
usb.bInterfaceClass ; decimal
usb.bInterfaceSubClass ; decimal
usb.bInterfaceProtocol ; decimal
If Bus==usb and if usbfs (formerly usbdevfs) is enabled (this is
linux-centric I realize)
usb.devfs ; Where the USB "drivers" list lives
usb.device ; The path to the usbfs node for this device
Required properties for devices where Category=Storage when
State=enabled (Note: is it too oldschool to require that a storage
device can be mounted in the UNIX filesystem?)
UnixMountpoint = /path/to/mount ; Location in the local file-
; system where the device is
Optional properties for devices where Category=Storage
GnomeVfsUrl = <URL> ; Gnome VFS URL where the storage on
; the device can be accessed
KdeVfsUrl = <URL> ; KDS VFS URL (is it called that?) where
; the device can be accessed
UnixDevice = /path/to/dev ; UNIX device that is mounted
I could go on here, but I hope you get the picture. This should really
be in a specification somewhere.
Suppose you are inserting an USB Compact Flash Reader into your computer
for the first time
o hal_hotplug is invoked by the kernel and sends usb.* and
Bus property to hald.
o hald finds a device (it matches on usb.* properties) and merges
a lot of properties including (but not limited to)
Type = Storage
KernelModules = usb-storage
RequireDisable = true
BootProgram = /some/handler/program
ShutdownProgram = /some/handler/program
Persistent = true
o usb-storage is successfully inserted into kernel
o BootProgram is invoked, it sets
ConfigureRequiredProperties = UnixMountpoint
and returns 1. It, ofcourse, needs input from the user where it
should mount the device.
o hald sets
State = enabled_req_user
and sends a notification to libhal users (the desktop environment)
o The gnome_hal_watcher (or kde_hal_watcher), a desktop application
using libhal, receives the notification and prompts the user for
a mount path. The user selects the location
hal_watcher sets the property (assuming that the user is david)
UnixMountPoint = /home/david/CompactFlash
The hal_watcher sends a message to hald to try to boot the device
o Again, BootProgram is invoked by hald; it successfully mounts the
device at at the specified location (note this is possible! hald
runs with root privileges). This time it returns 0
o hald sets
State = enabled
and broadcast a notification to libhal users that a device is now
in enabled state.
o The hal_watcher sees that State==enabled and RequireDisable==true
so it puts a "Stop Device" icon in the notification area.
If Nautilus links with libhal it can show the device (in the side pane
with different roots perhaps?) - the same goes for Konqueror etc.
The next time the device is inserted, the user doesn't have to go
through where to mount it because Persistent==true. The DE should just
notify him, through a balloon in the notification area, that the device
is now mounted.
I hope this clarifies the intentions with having a well-defined set of
properties to manage the process of handling devices. There are many
other use cases (no driver, driver doesn't work etc.) that should be
This I haven't worked on yet. My prototype simply has some C code in
hald that fills the appropriate properties for my USB devices:
// TODO: should use USB vendor and product info
"CF Card Reader");
// TODO: Change this to a program that will mount this disk
We can probably define some clever XML files that match different
devices and works over several versions of several operating systems.
This is really the killer - hardware vendors could ship a single .fdi
(free device information) file along with their windows drivers.
This would, for simple devices like CF readers (for which
OS-vendor-drivers are available), make the device work on many operating
The discover library from Progeny might be used for this - it looks
great, but I haven't looked too much into this.
I haven't thought much about this.
I suppose that we really need a specification about the well-know
properties for well-known device types like my attempt above with
For Type==Camera we might talk with the gphoto2 authors etc.
I agree with Havoc - someone should really work on this. 'Making
Hardware Just Work' seems, IMHO, to be one of the only real hindrances
for free desktops.
I'm prepared to work on it (disclaimer: I can only work on it in my
spare time). How should we proceed?
Comments are appreciated.
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- David Zeuthen pgp key: http://fubar.dk/pgpkey.asc
- david(at)fubar.dk pgp key id: b89bab82
"We are upping our standards ... so up yours." - Pat Paulsen
for President, 1988.
More information about the xdg