summaryrefslogtreecommitdiff
path: root/docs/plugins.xml
blob: c24ba7cfa43c058eb333d152b568118c7db8bac1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">

<chapter id="plugins">
  <title>Plugins</title>

  <sect1 id="plugins-introduction">
    <title>Introduction</title>
    <para>
      Plugins are external modules that are loaded at runtime.
      Plugins have preference data and internal state known as keys and policy,
      and also install a default system preferences file.
    </para>

    <sect2 id="plugins-key-defaults">
      <title>Plugin Key Defaults</title>
      <para>
        We need to set system preferences when there is no user logged in or we
        are very early in the boot sequence.
        We do this with each plugin installing a text file with the plugin key
        name, the value, and if the key is modifiable from the user sesison.
      </para>
      <para>
        The plugin preferences are read from <filename>/etc/ohm/plugins/{name}</filename>
        Comments are lines with first character <literal>#</literal> and then the
        rest of the line is ignored.
        Files are flat text with the following formal description, 
        <literal>plugin_prefix.key value public</literal>
        There is a single space between the values, and all values are signed ints.
        By making a key public, all the session users are allowed to change the
        preference value, for instance the brightness on AC.
        If a key is private then the public keyword is omitted, and any attempt
        to change the key from the session will fail.
      </para>
      <note>
        <para>
          The public and private key concept is a way to enforce fine-grained
          specific system policy on users when using PolicyKit rules for every
          action would be too great an overhead.
        </para>
      </note>
      <important>
        <para>
          Do not set internal state keys with their initial value here.
          These should be added using <literal>ohm_plugin_conf_provide()</literal>
          during <literal>load()</literal> and then the values populated in the
          <literal>coldplug()</literal> method.
          This ensures the correct ordering of coldplug.
        </para>
      </important>
    </sect2>
  
    <sect2 id="plugins-system-start">
      <title>System Start</title>
      <para>
        The file <filename>/etc/ohm/modules.ini</filename> allows the system
        builder to set the modules to be loaded at startup.
        For instance, on a fast PC we may want to suggest different modules
        to a embedded ARM.
      </para>
    </sect2>
  
    <sect2 id="plugins-other-plugins">
      <title>Plugin Dependencies</title>
      <para>
        Plugins can tell <literal>ohmd</literal> that other plugins are required
        for certain functionality, for instance, the backlight unit on a mobile
        phone may require the temperature module to be present, so it can do the
        temperature shutdown checks.
        This is done with <literal>ohm_plugin_require()</literal>.
        <literal>ohmd</literal> daemon will fail to load if any required plugin
        is not present after the plugins have finished initializing.
      </para>
      <para>
        Plugins can also tell <literal>ohmd</literal> that other plugins are suggested for certain
        functionality, for instance, the backlight unit may work best when the
        battery plugin is loaded so we can dim when we are low on power.
        This is done with <literal>ohm_plugin_suggest()</literal>.
        <literal>ohmd</literal> daemon will print a message to the console if any
        suggested plugin is not present.
      </para>
      <para>
        Plugins can also tell <literal>ohmd</literal> that other plugins are
        banned, for instance, a proprietary battery discharge plugin maybe
        incompatible with the standard battery plugin.
        This is done with <literal>ohm_plugin_prevent()</literal>.
        <literal>ohmd</literal> will fail to load if any prevented plugin is
        manually loaded or loaded through a dependency of another plugin.
      </para>
      <para>
        Plugins must also tell OHM that they will provide certain keys.
        This is done using <literal>ohm_plugin_conf_provide()</literal> and
        then OHM can check to see if the plugin is trying to provide keys
        that are managed by another plugin.
        This will stop the system doing odd things when two plugins try to write
        to one key and is a good check when building policy.
        In production code this check should be turned off using the command
        line argument <literal>--no-checks</literal> as this speeds up the
        initial coldplug considerably.
      </para>
    </sect2>
  
    <sect2 id="plugins-acccess-to-keys">
      <title>Plugin access to keys</title>
      <para>
        To get key values from the global keystore, a plugin must use
        <literal>ohm_plugin_conf_get_key()</literal> which will return false
        if the key is not available.
        Keys can be set using <literal>ohm_plugin_conf_set_key</literal>.
      </para>
      <para>
        A plugin may want to be notified when a key changes.
        In typical code, the key and the value would be passed to the plugin
        and then the key name compared against a fixed list.
        This is too slow for the plugin system in OHM, as many plugins may
        have to be chained together for a policy action.
        It was found that repeated <literal>strcmp()</literal>'s on all the
        changed value keys was causing high load on embedded machines.
      </para>
      <para>
        To register interest in a key change, a plugin must call
        <literal>ohm_plugin_conf_interested()</literal> along with an integer ID
        unique to the plugin.
        The integer ID does not have to be unique among the other plugins.
        When the key is changed in OHM by another plugin of the session user,
        this is matched against a hash table for O(1) complexity, and then
        a list iterated over sending the indervidual ID's to the plugins.
        Matching integer ID's in plugins is much faster than matching strings,
        for a small coldplug overhead.
        See the example plugin code for more details.
      </para>
    </sect2>
  
    <sect2 id="plugins-session-access">
      <title>Session Access to keys</title>
      <para>
        Plugins have direct access to the keystore and can read and write any key
        even if private.
        The DBUS interface to the keystore is however limited to only setting
        public keys to enforce security policy.
        The DBUS interface should only be used to set preferences, it should
        never be used to set or change policy - this is the job for the plugin.
      </para>
      <mediaobject id="plugins-dbus">
        <imageobject>
          <imagedata format="PNG" fileref="ohm-dbus-access.png" align="center"/>
        </imageobject>
      </mediaobject>
      <para>
        The DBUS interface is protected from setting or creating keys to prevent
        malicious users overwriting system prefrences that are not to be changed.
        Session software can not load or unload plugins, as this would be a
        system and security risk.
      </para>
    </sect2>

  </sect1>

  <sect1 id="plugins-defaults">
    <title>Default plugins</title>
    <para>
      Some plugins are shipped by default and provide typical use cases.
    </para>

    <sect2 id="plugins-backlight">
      <title>Backlight Adjustment</title>
      <para>
        Backlight brightness and state can be changed on most backlight hardware.
        These are the optional DBUS methods for controlling the brightness of
        the backlight.
      </para>

      <sect3 id="plugins-backlight-keys">
        <title>
          <literal>Exported keys</literal>
        </title>
        <para>
          Keys exported by this plugin:
        </para>
        <informaltable>
          <tgroup cols="2">
            <thead>
              <row>
                <entry>Key</entry>
                <entry>Description</entry>
              </row>
            </thead>
            <tbody>
              <row>
                <entry><literal>backlight.value_ac</literal></entry>
                <entry>Brightness in percentage when on AC</entry>
              </row>
              <row>
                <entry><literal>backlight.value_battery</literal></entry>
                <entry>Brightness in percentage when on battery</entry>
              </row>
              <row>
                <entry><literal>backlight.value_idle</literal></entry>
                <entry>Brightness in percentage when idle</entry>
              </row>
              <row>
                <entry><literal>backlight.time_idle</literal></entry>
                <entry>
                  The amount of time in seconds before the backlight is put
                  into idle mode, or zero to disable.
                  Idle mode is typically dimming for most backlight devices.
                </entry>
              </row>
              <row>
                <entry><literal>backlight.time_off</literal></entry>
                <entry>
                  The amount of time in seconds before the backlight is turned
                  off, or zero to disable.
                </entry>
              </row>
            </tbody>
          </tgroup>
        </informaltable>
      </sect3>
    </sect2>

  </sect1>

</chapter>