Advanced Topics and Tips

This document is part of the Driver Development Kit tutorial documentation.

Taking a long time to initialize

What if your device takes a long time to initialize? When we discussed the null_bind() function above, we indicated that a successful return told the device manager that the driver is now associated with the device. We can't spend a lot of time in the bind function; we're basically expected to initialize our device, publish it, and be done.

But your device might need to perform a lengthy initialization operation, such as:

  • enumerate hardware points
  • load firmware
  • negotiate a protocol

and so on, which might take a long time to do.

You can publish your device as "invisible" using the DEVICE_ADD_INVISIBLE flag. This meets the requirements for the binding function, but nobody is able to use your device (because nobody knows about it yet, because it's not visible). Now your device can perform the long operations via a background thread.

When your device is ready to service client requests, call device_make_visible() which will cause it to appear in the pathname space.

Power savings

Two callouts, suspend() and resume(), are available for your device in order to support power or other resource saving features.

Both take a device context pointer and a flags argument, but the flags argument is used only in the suspend case.

Flag Meaning
DEVICE_SUSPEND_FLAG_REBOOT The driver should shut itself down in preparation for a reboot or shutdown of the machine
DEVICE_SUSPEND_FLAG_REBOOT_BOOTLOADER ?
DEVICE_SUSPEND_FLAG_REBOOT_RECOVERY ?
DEVICE_SUSPEND_FLAG_POWEROFF The driver should shut itself down in preparation for power off
DEVICE_SUSPEND_FLAG_MEXEC @@@ almost nobody uses this except for a graphics controller, what does it do? @@@
DEVICE_SUSPEND_FLAG_SUSPEND_RAM The driver should arrange so that it can be restarted from RAM

@@@ Yeah, I'm just guessing on the flags; they're used so little...

For documentation purposes, what should I write? That they are just hints, or that you must do something because of a given flag, or ... ?

Reference: Support functions

This section lists support functions that are provided for your driver to use.

Accessor functions

The context block that's passed as the first argument to your driver's protocol functions is an opaque data structure. This means that in order to access the data elements, you need to call an accessor function:

Function Purpose
device_get_name() Retrieves the name of the device
device_get_parent() Retrieves the parent device of the device

Administrative functions

The following functions are used to administer the device:

Function Purpose
device_add() Adds a device to a parent
device_make_visible() Makes a device visible
device_async_remove() Schedules the removal of a device and all its children

Signalling

The following functions are used to set the state of a device:

Function Purpose
device_state_set() sets the given signal(s) on the device
device_state_clr() clears the given signal(s) on the device

We saw these in the /dev/misc/demo-fifo handler above.

@@@ Notes only @@@

This section is great for things like talking about buffer management, threading, best practices, advanced options for device_add(), and so on. I think it can be somewhere between the man page ("printf is used to print a string and takes the following parameters") and an application note — I want to see examples of how to use the functions, what the arguments mean, what the impact of various design decisions is, that kind of thing.