Specifications
CHAPTER 5. IMPLEMENTATION 53
default the module is enabled. Further, the loading function initializes the user space interface
of the ACPI subsystem if disable equals false. This initialization routine first tries to access
the user space interface /proc/acpi/event directly. If this approach fails, it is most likely
that another process has already acquired the interface. If this process is the ACPI daemon
acpid, another user space interface is available to receive the ACPI events. The ACPI daemon
creates the socket /var/run/acpid.socket to which it directly passes all ACPI events.
If the module is able to access either of the two interfaces, it subsequently creates a
GIOChannel and adds a watch to the event loop. The watch is added with the conditions
G IO IN and G IO ERR. The callback function of the watch is acpi event callback(). Once
an ACPI event occurs, the callback is invoked and gathers information about the ACPI event
using the GIOChannel. It does not matter whether the GIOChannel is associated with a file
descriptor of /proc/acpi/event or with the socket of the ACPI daemon. The GIOChannel
provides transparent access to the associated data source by using functions of the GLib li-
brary. The ACPI module uses the GLib function g io channel read line string() to read
data from the module’s GIOChannel. The function g io channel read line string() stores
the read data as a string. This string contains the complete ACPI event.
The module has to parse the string of the ACPI event to verify whether the event actually
is an ACPI input event from one of the buttons or the lid switch. First, the string is examined
to determine if it contains the substring button. As previously discussed, all ACPI input
events are prepended with this substring (Chapter 2, §2.6). If the string does contain button,
the parsing continues. Otherwise, the ACPI event is not a button event. To determine which
button was actually pressed, the string is further examined to see if it contains one of the three
substrings: PWRF (power button), SLPF (sleep button) or LID (lid switch). In case of the power
button and the sleep button, the module calls the module’s function acpi event send() which
performs the abstraction of the concrete event.
Otherwise—in case of the lid switch—another function of the module (acpi lid state())
is invoked before sending the input event. Since the ACPI input events for opening and clos-
ing the lid are equal, it is not possible to determine whether the lid was opened or closed.
However, this information can be obtained through the ACPI button driver’s user space in-
terface. The function acpi lid state() evaluates the lid state by reading the proc entry
/proc/acpi/button/lid/LID/state. If the read value is 0 the lid is closed. Correspondingly,
if the value equals 1, the lid is open. Once the function has gathered this information, it
invokes the creation of the corresponding abstract input event by calling acpi event send().
The function acpi event send() requires a string argument (char *button) which rep-
resents the button evaluated by the parser. The argument button is set to Power Button for
the power button, and it is correspondingly set to Sleep Button for the sleep button. A lid
switch event is reported by setting button to Lid Switch (open) if the lid was opened and to
Lid Switch (close) if the lid was closed.
The creation of the abstract input event is performed by acpi event send() using the
structure IalEvent. The members of the structure are set up as follows:
– event.sender is set to the module’s token (acpi)
– event.source is set to /proc/acpi/event
– event.name is set to the value of button
– event.raw is set to -1