blob: ee590539cd5e2da12f1d36ea35cfea92a64de03d [file] [log] [blame]
David Warreneb981332009-05-13 12:00:07 -07001page.title=Wakelocks
2pdk.version=1.0
3@jd:body
4
5
David Warren5c40a482009-06-05 15:11:21 -07006<div id="qv-wrapper">
7<div id="qv">
8<h2>In this document</h2>
David Warreneb981332009-05-13 12:00:07 -07009<a name="toc"/>
David Warren5c40a482009-06-05 15:11:21 -070010<ul>
11<li><a href="#driverAPI">Driver API</a></li>
12<li><a href="#userspaceAPI">User Space API</a></li>
13</ul>
14</div>
David Warreneb981332009-05-13 12:00:07 -070015</div>
16
David Warreneb981332009-05-13 12:00:07 -070017<p>A locked wakelock, depending on its type, prevents the system from entering suspend or other low-power states. This document describes how to employ wakelocks. </p>
18<p>There are two settings for a wakelock:</p>
19<ul>
20 <li><code>WAKE_LOCK_SUSPEND</code>: prevents a full system suspend. </li>
21 <li><code></code><code>WAKE_LOCK_IDLE</code>: low-power states, which often cause large interrupt latencies or that disable a set of interrupts, will not be entered from idle until the wakelocks are released. </li>
22</ul>
23<p>Unless the type is specified, this document refers to wakelocks of type <code>WAKE_LOCK_SUSPEND</code>. </p>
24<p>If the suspend operation has already started when locking a wakelock, the system will abort the suspend operation as long it has not already reached the <code>suspend_late</code> stage. This means that locking a wakelock from an interrupt handler or a freezeable thread always works, but if you lock a wakelock from a <code>suspend_late</code> handler, you must also return an error from that handler to abort suspend. You can use wakelocks to allow the user-space to decide which keys should wake the full system and turn on the screen. Use <code>set_irq_wake</code> or a platform-specific API to ensure that the keypad interrupt wakes up the CPU. Once the keypad driver has resumed, the sequence of events can look like this:</p>
25<ol>
26 <li> The Keypad driver receives an interrupt, locks the keypad-scan wakelock,
27 and starts scanning the keypad matrix. </li>
28 <li>The keypad-scan code detects a key change and reports it to the input-event
29 driver. </li>
30 <li>The input-event driver sees the key change, enqueues an event, and locks
31 the input-event-queue wakelock. </li>
32 <li>The keypad-scan code detects that no keys are held and unlocks the
33 keypad-scan wakelock. </li>
34 <li>The user-space input-event thread returns from select/poll, locks the
35 process-input-events wakelock, and calls read in the input-event device. </li>
36 <li>The input-event driver dequeues the key-event and, since the queue is now
37 empty, unlocks the input-event-queue wakelock. </li>
38 <li>The user-space input-event thread returns from read. It determines that the
39 key should not wake up the full system, releases the process-input-events
40 wakelock, and calls select or poll. </li>
41</ol>
42<p>The simple sequence diagram below illustrates these steps:</p>
43 <pre>
44 Key pressed Key released
45 | |
46 keypad-scan ++++++++++++++++++++++
47 input-event-queue +++ +++
48 process-input-events +++ +++
49 </pre>
50
David Warren5c40a482009-06-05 15:11:21 -070051<a name="driverAPI"></a><h3>Driver API</h3>
David Warreneb981332009-05-13 12:00:07 -070052<p>A driver can use the wakelock API by adding a wakelock variable to its state and calling <code>wake_lock_init</code>, as illustrated in the snippet below:</p>
David Warren5c40a482009-06-05 15:11:21 -070053<pre>
David Warreneb981332009-05-13 12:00:07 -070054 struct state {
55 struct wakelock wakelock;
56 }
57 init() {
58 wake_lock_init(&amp;state-&gt;wakelock, WAKE_LOCK_SUSPEND, &quot;wakelockname&quot;);
59 }
60 Before freeing the memory, wake_lock_destroy must be called:
61 uninit() {
62 wake_lock_destroy(&amp;state-&gt;wakelock);
63 }
64 </pre>
65<p> When the driver determines that it needs to run (usually in an interrupt handler), it calls <code>wake_lock</code>:</p>
David Warren5c40a482009-06-05 15:11:21 -070066<pre>
David Warreneb981332009-05-13 12:00:07 -070067 wake_lock(&amp;state-&gt;wakelock);
68 </pre>
69<p>When it no longer needs to run, it calls <code>wake_unlock</code>:</p>
David Warren5c40a482009-06-05 15:11:21 -070070<pre>
David Warreneb981332009-05-13 12:00:07 -070071 wake_unlock(&amp;state-&gt;wakelock);
72 </pre>
73<p> It can also call <code>wake_lock_timeout</code> to release the wakelock after a delay:</p>
David Warren5c40a482009-06-05 15:11:21 -070074<pre>
David Warreneb981332009-05-13 12:00:07 -070075 wake_lock_timeout(&amp;state-&gt;wakelock, HZ);
76</pre>
77<p> This works whether or not the wakelock is already held. It is useful if the driver woke up other parts of the system that do not use wakelocks but still need to run. Avoid this when possible, since it will waste power if the timeout is long or may fail to finish needed work if the timeout is short.</p>
David Warren5c40a482009-06-05 15:11:21 -070078<a name="userspaceAPI"></a><h3>User-space API</h3>
David Warreneb981332009-05-13 12:00:07 -070079<p>Write <code>lockname</code> or <code>lockname timeout</code> to <code>/sys/power/wake_lock</code> lock and, if needed, create a wakelock. The timeout here is specified in nanoseconds. Write <code>lockname</code> to <code>/sys/power/wake_unlock</code> to unlock a user wakelock.</p>
80<p> Do not use randomly generated wakelock names as there is no API to free a user-space wakelock.</p>