Merge lp:~charlesk/powerd/add-hardware-alarms into lp:powerd

Proposed by Charles Kerr
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 143
Merged at revision: 139
Proposed branch: lp:~charlesk/powerd/add-hardware-alarms
Merge into: lp:powerd
Diff against target: 658 lines (+439/-12)
9 files modified
CMakeLists.txt (+3/-1)
cli/powerd-cli.c (+99/-0)
data/com.canonical.powerd.xml (+13/-0)
debian/control (+2/-0)
src/log.h (+23/-0)
src/powerd-internal.h (+8/-1)
src/powerd-object.c (+101/-10)
src/powerd.cpp (+2/-0)
src/wakeup.cpp (+188/-0)
To merge this branch: bzr merge lp:~charlesk/powerd/add-hardware-alarms
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+231302@code.launchpad.net

Commit message

Add hardware wakeup support.

Description of the change

Add hardware wakeup support. As discussed in #phablet, the u_hardware_alarm_*() API basically only allows one client, so powerd will be that one client and will act as a gatekeeper for hardware wakeups.

This adds a little new public API: two methods (requestWakeup() and clearWakeup()) and a broadcast signal (Wakeup).

Also added are wakeup and clear-wakeup commands in powerd-cli.

The wakeup.cpp implementation is fairly straightforward. One point that might be contentious is the new logging functions in log.h. I think they're pretty useful but don't mind removing them if they're too un-powerd-like.

See related MP for indicator-datetime to make use of this: <https://code.launchpad.net/~charlesk/indicator-datetime/add-powerd-alarm-support/+merge/231303>

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Code looks fine, just one inline comment for the packaging. Will do some further tests and then approve with the proper feedback.

Revision history for this message
Charles Kerr (charlesk) :
143. By Charles Kerr

in debian/control, remove [armhf i386 amd64] arch restrictions for libubuntu-platform-hardware-api-*

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Looks good, works as expected.

Would be nice for powerd-cli list to also show the current list of the pending wakeup events, but that can be done later on.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-05-21 03:17:03 +0000
3+++ CMakeLists.txt 2014-08-19 19:23:22 +0000
4@@ -9,7 +9,7 @@
5 endif()
6
7 set(CMAKE_C_FLAGS "-Wall")
8-set(CMAKE_CXX_FLAGS "-Wall")
9+set(CMAKE_CXX_FLAGS "-Wall -std=c++11")
10 set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb -g")
11 set(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb -g")
12 set(CMAKE_C_FLAGS_RELEASE "-O3")
13@@ -56,6 +56,7 @@
14 src/spline.c
15 src/stats.c
16 src/util.c
17+ src/wakeup.cpp
18 src/${GDBUS_NAME}.c
19 )
20
21@@ -103,6 +104,7 @@
22 ${GIO_LIBRARIES}
23 ${GIO-UNIX_LIBRARIES}
24 ${PHABLET_LIBRARIES}
25+ "-lubuntu_platform_hardware_api"
26 "-lubuntu_application_api"
27 "-landroid-properties"
28 "-lhardware"
29
30=== modified file 'cli/powerd-cli.c'
31--- cli/powerd-cli.c 2014-06-18 18:06:10 +0000
32+++ cli/powerd-cli.c 2014-08-19 19:23:22 +0000
33@@ -141,6 +141,55 @@
34 }
35
36 static gboolean
37+requestWakeup(const char *name,
38+ uint64_t wakeup_time,
39+ powerd_cookie_t setme_cookie)
40+{
41+ GVariant *ret;
42+ GError *error;
43+ gboolean success;
44+
45+ g_return_val_if_fail (setme_cookie != NULL, FALSE);
46+
47+ error = NULL;
48+ ret = g_dbus_proxy_call_sync(powerd_proxy,
49+ "requestWakeup",
50+ g_variant_new("(st)", name, wakeup_time),
51+ G_DBUS_CALL_FLAGS_NONE,
52+ -1, /* use default timeout */
53+ NULL, /* cancellable */
54+ &error);
55+
56+ if (ret == NULL) {
57+ cli_warn("%s failed: %s", G_STRFUNC, error->message);
58+ success = FALSE;
59+ }
60+ else if (!g_variant_is_of_type(ret, G_VARIANT_TYPE("(s)"))) {
61+ char * s = g_variant_print(ret, TRUE);
62+ cli_warn("Unexpected response: %s", s);
63+ g_free(s);
64+ success = FALSE;
65+ }
66+ else {
67+ const char* s = NULL;
68+ g_variant_get(ret, "(&s)", &s);
69+ if (strlen(s) != sizeof(powerd_cookie_t) - 1) {
70+ cli_warn("Returned cookie has incorrect size");
71+ success = FALSE;
72+ }
73+ else {
74+ memcpy(setme_cookie, s, sizeof(powerd_cookie_t));
75+ cli_debug("Got cookie: %s", setme_cookie);
76+ success = TRUE;
77+ }
78+ }
79+
80+ g_clear_error(&error);
81+ g_clear_pointer(&ret, g_variant_unref);
82+ return success;
83+}
84+
85+static gboolean
86 requestDisplayState(int *cookie)
87 {
88 GVariant *ret = NULL;
89@@ -286,6 +335,35 @@
90 }
91 }
92
93+static gboolean
94+clearWakeup(const char* cookie_str)
95+{
96+ GVariant *ret;
97+ GError *error;
98+ gboolean success;
99+
100+ error = NULL;
101+ ret = g_dbus_proxy_call_sync(powerd_proxy,
102+ "clearWakeup",
103+ g_variant_new("(s)", cookie_str),
104+ G_DBUS_CALL_FLAGS_NONE,
105+ -1, /* default timeout */
106+ NULL, /* cancellable */
107+ &error);
108+
109+ if (ret == NULL) {
110+ cli_warn("%s failed: %s", G_STRFUNC, error->message);
111+ success = FALSE;
112+ } else {
113+ cli_debug("%s success", G_STRFUNC);
114+ success = TRUE;
115+ }
116+
117+ g_clear_error(&error);
118+ g_clear_pointer(&ret, g_variant_unref);
119+ return success;
120+}
121+
122 gboolean
123 clearSysState(powerd_cookie_t cookie)
124 {
125@@ -618,6 +696,8 @@
126 printf("listen\t- listen for signals from powerd. This runs a\n"\
127 "\t gmainloop and must be manually killed.\n");
128 printf("stats\t- print request statistics.\n");
129+ printf("wakeup <n>\t- request a hardware wakeup n seconds from now.\n");
130+ printf("clear-wakeup <cookie>\t- clear a hardware wakeup request given a cookie.\n");
131 printf("test\t- runs tests.\n");
132 }
133
134@@ -646,6 +726,8 @@
135 (strcmp(argv[1],"stats")) &&
136 (strcmp(argv[1],"active")) &&
137 (strcmp(argv[1],"active-nc")) &&
138+ (strcmp(argv[1],"wakeup")) &&
139+ (strcmp(argv[1],"clear-wakeup")) &&
140 (strcmp(argv[1],"test")) &&
141 (strcmp(argv[1],"dbusnametest")) &&
142 (strcmp(argv[1],"listen")) &&
143@@ -751,6 +833,9 @@
144 if (!strcmp(argv[1],"clear-sys")) {
145 clearSysState(argv[2]);
146 }
147+ else if (!g_strcmp0(argv[1], "clear-wakeup")) {
148+ clearWakeup(argv[2]);
149+ }
150 else {
151 // Note: We should never get here due to earlier checks
152 fprintf(stderr,"Invalid option %s\n",argv[1]);
153@@ -844,6 +929,20 @@
154 exit(-1);
155 }
156 setUserBrightness((int)brightness);
157+ } else if (!g_strcmp0(argv[1], "wakeup")) {
158+ int n_seconds;
159+ powerd_cookie_t cookie;
160+ if (argc != 3) {
161+ usage(argv[0]);
162+ exit(-1);
163+ }
164+ n_seconds = atoi(argv[2]);
165+ if (n_seconds < 1) {
166+ fprintf(stderr, "Invalid number of seconds %s\n", argv[2]);
167+ usage(argv[0]);
168+ exit(-1);
169+ }
170+ requestWakeup(argv[0], time(NULL)+n_seconds, cookie);
171 }
172 return 0;
173 }
174
175=== modified file 'data/com.canonical.powerd.xml'
176--- data/com.canonical.powerd.xml 2014-05-13 22:05:20 +0000
177+++ data/com.canonical.powerd.xml 2014-08-19 19:23:22 +0000
178@@ -14,6 +14,16 @@
179 <arg type="s" name="cookie" direction="in" />
180 </method>
181
182+ <method name="requestWakeup">
183+ <arg type="s" name="name" direction="in" />
184+ <arg type="t" name="time" direction="in" />
185+ <arg type="s" name="cookie" direction="out" />
186+ </method>
187+
188+ <method name="clearWakeup">
189+ <arg type="s" name="cookie" direction="in" />
190+ </method>
191+
192 <method name="registerClient">
193 <arg type="s" name="name" direction="in" />
194 </method>
195@@ -55,5 +65,8 @@
196 <arg type="i" name="sysState" direction="out" />
197 </signal>
198
199+ <signal name="Wakeup">
200+ </signal>
201+
202 </interface>
203 </node>
204
205=== modified file 'debian/control'
206--- debian/control 2014-06-13 15:56:20 +0000
207+++ debian/control 2014-08-19 19:23:22 +0000
208@@ -10,6 +10,8 @@
209 python:any,
210 libandroid-properties-dev,
211 libubuntu-application-api-dev,
212+ libubuntu-platform-hardware-api-headers,
213+ libubuntu-platform-hardware-api-dev,
214 libupower-glib-dev,
215 uuid-dev,
216 libhardware-dev (>= 0.1.0+git20131207+e452e83-0ubuntu12),
217
218=== modified file 'src/log.h'
219--- src/log.h 2013-07-10 21:28:20 +0000
220+++ src/log.h 2014-08-19 19:23:22 +0000
221@@ -39,6 +39,29 @@
222 __attribute__ ((format (printf, 2, 3)));
223 void powerd_log_init(void);
224
225+#define powerd_warn_if_fail(expr) \
226+ do { \
227+ if (!(expr)) \
228+ powerd_warn("%s", #expr); \
229+ } while (0)
230+
231+#define powerd_return_if_fail(expr) \
232+ do { \
233+ if (!(expr)) { \
234+ powerd_warn("%s: assertion '%s' failed", __func__, #expr); \
235+ return; \
236+ } \
237+ } while (0)
238+
239+#define powerd_return_val_if_fail(expr,val) \
240+ do { \
241+ if (!(expr)) { \
242+ powerd_warn("%s: assertion '%s' failed", __func__, #expr); \
243+ return val; \
244+ } \
245+ } while (0)
246+
247+
248 #ifdef __cplusplus
249 }
250 #endif
251
252=== modified file 'src/powerd-internal.h'
253--- src/powerd-internal.h 2014-07-02 16:24:51 +0000
254+++ src/powerd-internal.h 2014-08-19 19:23:22 +0000
255@@ -19,8 +19,8 @@
256 #ifndef __POWERD_INTERNAL_H__
257 #define __POWERD_INTERNAL_H__
258
259+#include <time.h> /* time_t */
260 #include <uuid/uuid.h>
261-#include <glib.h>
262 #include <gio/gio.h>
263
264 #include "powerd-object.h"
265@@ -107,6 +107,7 @@
266 enum SysPowerStates current_system_power_state(void);
267 const gchar * state_to_string(int state);
268 void powerd_sys_state_signal_emit(enum SysPowerStates state);
269+void powerd_wakeup_signal_emit(void);
270 void clear_sys_state_by_owner(const char *owner);
271 gboolean powerd_suspend_active(void);
272
273@@ -164,6 +165,12 @@
274 int powerd_ps_init(void);
275 void powerd_ps_deinit(void);
276
277+/* Hardware alarm functions */
278+void wakeup_init(void);
279+void wakeup_deinit(void);
280+int wakeup_request(const char *name, time_t time, powerd_cookie_t setme_cookie);
281+int wakeup_clear(const powerd_cookie_t cookie);
282+
283 /* Client functions */
284 int powerd_client_register(const char *dbus_name, const char *name);
285 void powerd_client_unregister(const char *dbus_name);
286
287=== modified file 'src/powerd-object.c'
288--- src/powerd-object.c 2014-07-02 16:24:51 +0000
289+++ src/powerd-object.c 2014-08-19 19:23:22 +0000
290@@ -19,6 +19,7 @@
291 #include <glib.h>
292 #include <glib-object.h>
293 #include <gio/gio.h>
294+#include <inttypes.h>
295 #include <string.h>
296 #include <stdio.h>
297 #include <errno.h>
298@@ -135,11 +136,69 @@
299 return TRUE;
300 }
301
302+static gboolean
303+handle_request_wakeup(PowerdSource *obj,
304+ GDBusMethodInvocation *invocation,
305+ const char *name,
306+ uint64_t wakeup_time)
307+{
308+ int err;
309+ powerd_cookie_t cookie;
310+
311+ powerd_debug("handle_requestWakeup from %s - %s, %zu",
312+ g_dbus_method_invocation_get_sender(invocation),
313+ name,
314+ (size_t)wakeup_time);
315+
316+ if ((err = wakeup_request(name, wakeup_time, cookie)))
317+ {
318+ g_dbus_method_invocation_return_error_literal(invocation,
319+ G_DBUS_ERROR,
320+ G_DBUS_ERROR_FAILED,
321+ strerror(err));
322+ }
323+ else
324+ {
325+ g_dbus_method_invocation_return_value(invocation,
326+ g_variant_new("(s)", cookie));
327+ }
328+
329+ return TRUE;
330+}
331+
332+static gboolean
333+handle_clear_wakeup(PowerdSource *obj,
334+ GDBusMethodInvocation *invocation,
335+ const char* cookie)
336+{
337+ int err;
338+
339+ powerd_debug("handle_clearWakeup from %s, cookie: %s",
340+ g_dbus_method_invocation_get_sender(invocation),
341+ cookie);
342+
343+ if ((err = wakeup_clear(cookie)))
344+ {
345+ g_dbus_method_invocation_return_error_literal(invocation,
346+ G_DBUS_ERROR,
347+ G_DBUS_ERROR_FAILED,
348+ strerror(err));
349+ }
350+ else
351+ {
352+ g_dbus_method_invocation_return_value(invocation, NULL);
353+ }
354+
355+ return TRUE;
356+}
357+
358+
359 void
360 powerd_bus_acquired_cb (GDBusConnection *connection,
361 const gchar *name,
362 gpointer user_data)
363 {
364+ GObject * oskel;
365 GError *error = NULL;
366
367 powerd_debug("Bus acquired (guid %s)", g_dbus_connection_get_guid (connection));
368@@ -156,28 +215,35 @@
369 powerd_exit(-1);
370 }
371
372- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-request-sys-state",
373+ oskel = G_OBJECT(powerd_source->priv->skel);
374+
375+ g_signal_connect(oskel, "handle-request-sys-state",
376 G_CALLBACK(handle_request_sys_state), powerd_source);
377- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-clear-sys-state",
378+ g_signal_connect(oskel, "handle-clear-sys-state",
379 G_CALLBACK(handle_clear_sys_state), powerd_source);
380- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-list-sys-requests",
381+ g_signal_connect(oskel, "handle-list-sys-requests",
382 G_CALLBACK(handle_list_sys_requests), powerd_source);
383
384- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-register-client",
385+ g_signal_connect(oskel, "handle-register-client",
386 G_CALLBACK(handle_register_client), powerd_source);
387- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-unregister-client",
388+ g_signal_connect(oskel, "handle-unregister-client",
389 G_CALLBACK(handle_unregister_client), powerd_source);
390- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-ack-state-change",
391+ g_signal_connect(oskel, "handle-ack-state-change",
392 G_CALLBACK(handle_ack_state_change), powerd_source);
393- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-get-sys-request-stats",
394+ g_signal_connect(oskel, "handle-get-sys-request-stats",
395 G_CALLBACK(handle_get_sys_request_stats), powerd_source);
396- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-user-autobrightness-enable",
397+ g_signal_connect(oskel, "handle-user-autobrightness-enable",
398 G_CALLBACK(handle_user_autobrightness_enable), powerd_source);
399- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-get-brightness-params",
400+ g_signal_connect(oskel, "handle-get-brightness-params",
401 G_CALLBACK(handle_get_brightness_params), powerd_source);
402- g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-set-user-brightness",
403+ g_signal_connect(oskel, "handle-set-user-brightness",
404 G_CALLBACK(handle_set_user_brightness), powerd_source);
405
406+ g_signal_connect(oskel, "handle-request-wakeup",
407+ G_CALLBACK(handle_request_wakeup), powerd_source);
408+ g_signal_connect(oskel, "handle-clear-wakeup",
409+ G_CALLBACK(handle_clear_wakeup), powerd_source);
410+
411 powerd_dbus_init_complete();
412 }
413
414@@ -224,6 +290,31 @@
415 }
416
417 void
418+powerd_wakeup_signal_emit (void)
419+{
420+ GError *error = NULL;
421+
422+ /* Make sure dbus has been set up */
423+ if (!powerd_source)
424+ return;
425+
426+ powerd_debug("Emitting wakeup signal");
427+
428+ g_dbus_connection_emit_signal(
429+ POWERD_SOURCE_GET_PRIVATE(powerd_source)->system_bus,
430+ NULL, /* destination */
431+ "/com/canonical/powerd",
432+ "com.canonical.powerd",
433+ "Wakeup",
434+ NULL,
435+ &error);
436+ if (error) {
437+ powerd_warn("Unable to emit wakeup signal: %s", error->message);
438+ g_error_free(error);
439+ }
440+}
441+
442+void
443 ofono_manager_proxy_connect_cb(GObject *source_object,
444 GAsyncResult *res,
445 gpointer user_data)
446
447=== modified file 'src/powerd.cpp'
448--- src/powerd.cpp 2014-08-12 07:23:07 +0000
449+++ src/powerd.cpp 2014-08-19 19:23:22 +0000
450@@ -577,6 +577,7 @@
451 powerd_autobrightness_init();
452 powerd_sensors_init();
453 powerd_ps_init();
454+ wakeup_init();
455
456 main_loop = g_main_loop_new (NULL, FALSE);
457 signal(SIGTERM, sigterm_quit);
458@@ -598,6 +599,7 @@
459 g_bus_unown_name(name_id);
460 g_main_loop_unref(main_loop);
461
462+ wakeup_deinit();
463 powerd_ps_deinit();
464 dbus_name_watch_deinit();
465 powerd_autobrightness_deinit();
466
467=== added file 'src/wakeup.cpp'
468--- src/wakeup.cpp 1970-01-01 00:00:00 +0000
469+++ src/wakeup.cpp 2014-08-19 19:23:22 +0000
470@@ -0,0 +1,188 @@
471+/*
472+ * Copyright 2014 Canonical Ltd.
473+ *
474+ * Authors:
475+ * Charles Kerr: charles.kerr@canonical.com
476+ *
477+ * This file is part of powerd.
478+ *
479+ * powerd is free software; you can redistribute it and/or modify
480+ * it under the terms of the GNU General Public License as published by
481+ * the Free Software Foundation; version 3.
482+ *
483+ * powerd is distributed in the hope that it will be useful,
484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
486+ * GNU General Public License for more details.
487+ *
488+ * You should have received a copy of the GNU General Public License
489+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
490+ */
491+
492+
493+#include <ctime>
494+#include <map>
495+#include <memory> // std::unique_ptr
496+#include <string>
497+#include <thread>
498+
499+#include <glib.h>
500+
501+#include <ubuntu/hardware/alarm.h>
502+
503+#include "powerd-internal.h"
504+#include "log.h"
505+
506+namespace
507+{
508+
509+struct Request
510+{
511+ std::string name;
512+ time_t time;
513+};
514+
515+std::map<std::string,Request> requests;
516+
517+UHardwareAlarm hardware_alarm = nullptr;
518+
519+// NB: only the main thread accesses 'worker'
520+std::unique_ptr<std::thread> worker;
521+
522+void start_worker_thread();
523+
524+void set_wakeup_time(time_t wakeup_time, const std::string& name)
525+{
526+ powerd_return_if_fail(hardware_alarm != nullptr);
527+ powerd_return_if_fail(wakeup_time >= time(nullptr));
528+
529+ struct tm tm;
530+ char buf[32];
531+ localtime_r(&wakeup_time, &tm);
532+ strftime(buf, sizeof(buf), "%F %T", &tm);
533+ powerd_debug("setting hardware wakeup time to %s for %s", buf, name.c_str());
534+
535+ struct timespec sleep_interval;
536+ sleep_interval.tv_sec = wakeup_time;
537+ sleep_interval.tv_nsec = 0;
538+ u_hardware_alarm_set_relative_to_with_behavior(
539+ hardware_alarm,
540+ U_HARDWARE_ALARM_TIME_REFERENCE_RTC,
541+ U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE,
542+ &sleep_interval);
543+}
544+
545+void reset_alarm_clock()
546+{
547+ // find request that will occur next
548+ const time_t now = time(nullptr);
549+ const Request* next = nullptr;
550+ size_t n_left = 0;
551+ for (const auto& it : requests) {
552+ if (now < it.second.time) {
553+ ++n_left;
554+ if (!next || (it.second.time < next->time))
555+ next = &it.second;
556+ }
557+ }
558+
559+ if (next != nullptr)
560+ {
561+ powerd_debug("%s found %zu remaining wakeup requests", G_STRFUNC, n_left);
562+ set_wakeup_time(next->time, next->name);
563+ if (!worker)
564+ start_worker_thread();
565+ }
566+ else if (worker) // no pending requests...
567+ {
568+ powerd_debug("shortening wakeup_time so worker thread will finish soon");
569+ set_wakeup_time(time(nullptr)+1, G_STRFUNC);
570+ }
571+}
572+
573+gboolean on_worker_thread_finished(gpointer /*unused*/)
574+{
575+ // tell the world that we woke up
576+ powerd_wakeup_signal_emit();
577+
578+ // worker thread is done, so clean up our 'worker' variable
579+ powerd_debug("worker thread is finished working; calling join()");
580+ worker->join();
581+ worker.reset();
582+ powerd_debug("worker thread is destroyed.");
583+
584+ reset_alarm_clock();
585+
586+ return G_SOURCE_REMOVE;
587+}
588+
589+void threadfunc(UHardwareAlarm hw_alarm)
590+{
591+ // wait for the next alarm
592+ powerd_debug("calling wait_for_next_alarm");
593+ UHardwareAlarmWaitResult wait_result;
594+ auto rc = u_hardware_alarm_wait_for_next_alarm(hw_alarm, &wait_result);
595+ powerd_debug("worker thread finished waiting for hw alarm");
596+ powerd_warn_if_fail(rc == U_STATUS_SUCCESS);
597+ u_hardware_alarm_unref(hw_alarm);
598+
599+ // kick back to the main loop
600+ g_idle_add(on_worker_thread_finished, nullptr);
601+}
602+
603+void start_worker_thread()
604+{
605+ powerd_return_if_fail(hardware_alarm != nullptr);
606+
607+ powerd_debug("starting hardware alarm worker thread");
608+ u_hardware_alarm_ref(hardware_alarm);
609+ worker.reset(new std::thread(threadfunc, hardware_alarm));
610+}
611+
612+} // private impl in unnamed namespace
613+
614+void
615+wakeup_init(void)
616+{
617+ hardware_alarm = u_hardware_alarm_create();
618+}
619+
620+void
621+wakeup_deinit(void)
622+{
623+ requests.clear();
624+ reset_alarm_clock();
625+ g_clear_pointer(&hardware_alarm, u_hardware_alarm_unref);
626+}
627+
628+int
629+wakeup_request(const char* name, time_t wakeup_time, powerd_cookie_t cookie)
630+{
631+ powerd_return_val_if_fail(hardware_alarm, ENOTSUP);
632+ powerd_return_val_if_fail(wakeup_time > time(nullptr), EINVAL);
633+ powerd_return_val_if_fail(cookie != NULL, EINVAL);
634+
635+ // generate a new uuid string
636+ uuid_t tmp;
637+ uuid_generate(tmp);
638+ uuid_unparse(tmp, cookie);
639+
640+ requests[cookie] = { name, wakeup_time };
641+
642+ reset_alarm_clock();
643+ return 0;
644+}
645+
646+int
647+wakeup_clear(const powerd_cookie_t cookie)
648+{
649+ powerd_return_val_if_fail(hardware_alarm, ENOTSUP);
650+ auto it = requests.find(cookie);
651+ powerd_return_val_if_fail(it != requests.end(), EINVAL);
652+
653+ requests.erase(it);
654+
655+ reset_alarm_clock();
656+ return 0;
657+}
658+

Subscribers

People subscribed via source and target branches