hrev46364 adds 2 changesets to branch 'master' old head: ab3b931b14890034e05ab8ab7604394077481b2d new head: c9db30cd7f922e7a828f55c2f234d21e6bfa585a overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=c9db30c+%5Eab3b931 ---------------------------------------------------------------------------- 28fd553: power_daemon: code cleanup, added copyright header. c9db30c: power_daemon: use wait_for_objects() instead of polling. * acpi_button and acpi_lid support select/deselect hooks. * power_daemon now uses a thread waiting for lid or power button events. * a power button event is still hardcoded to a shutdown. * a lid event only displays a message. [ Jérôme Duval <jerome.duval@xxxxxxxxx> ] ---------------------------------------------------------------------------- 8 files changed, 260 insertions(+), 64 deletions(-) .../kernel/drivers/power/acpi_button/Jamfile | 2 + .../drivers/power/acpi_button/acpi_button.cpp | 48 ++++++++- .../kernel/drivers/power/acpi_lid/Jamfile | 2 + .../kernel/drivers/power/acpi_lid/acpi_lid.cpp | 107 +++++++++++++++---- src/servers/power/Jamfile | 1 + src/servers/power/power_button_monitor.cpp | 42 +++++--- src/servers/power/power_button_monitor.h | 28 +++-- src/servers/power/power_daemon.cpp | 94 +++++++++++++--- ############################################################################ Commit: 28fd553722599b20aed5fdf2d704b6a30ea126c9 URL: http://cgit.haiku-os.org/haiku/commit/?id=28fd553 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Wed Nov 13 16:25:07 2013 UTC power_daemon: code cleanup, added copyright header. ---------------------------------------------------------------------------- diff --git a/src/servers/power/power_button_monitor.cpp b/src/servers/power/power_button_monitor.cpp index 5fb6d91..ab1ae19 100644 --- a/src/servers/power/power_button_monitor.cpp +++ b/src/servers/power/power_button_monitor.cpp @@ -1,30 +1,47 @@ +/* + * Copyright 2005-2013, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Nathan Whitehorn + */ + + +#include "power_button_monitor.h" + #include <Messenger.h> #include <Roster.h> #include <RosterPrivate.h> -#include "power_button_monitor.h" - -PowerButtonMonitor::PowerButtonMonitor() : BHandler ("power_button_monitor") { - power_button_fd = open("/dev/power/button/power",O_RDONLY); +PowerButtonMonitor::PowerButtonMonitor() + : + BHandler ("power_button_monitor") +{ + fPowerButtonFD = open("/dev/power/button/power", O_RDONLY); } -PowerButtonMonitor::~PowerButtonMonitor() { - if (power_button_fd > 0) - close(power_button_fd); + +PowerButtonMonitor::~PowerButtonMonitor() +{ + if (fPowerButtonFD > 0) + close(fPowerButtonFD); } -void PowerButtonMonitor::MessageReceived(BMessage *msg) { + +void +PowerButtonMonitor::MessageReceived(BMessage *msg) +{ if (msg->what != POLL_POWER_BUTTON_STATUS) return; - - if (power_button_fd <= 0) + + if (fPowerButtonFD <= 0) return; - + uint8 button_pressed; - read(power_button_fd,&button_pressed,1); - + read(fPowerButtonFD, &button_pressed, 1); + if (button_pressed) { BRoster roster; BRoster::Private rosterPrivate(roster); diff --git a/src/servers/power/power_button_monitor.h b/src/servers/power/power_button_monitor.h index b117387..9313289 100644 --- a/src/servers/power/power_button_monitor.h +++ b/src/servers/power/power_button_monitor.h @@ -1,19 +1,30 @@ +/* + * Copyright 2005-2013, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Nathan Whitehorn + */ #ifndef _POWER_BUTTON_MONITOR_H #define _POWER_BUTTON_MONITOR_H + #include <Handler.h> + #define POLL_POWER_BUTTON_STATUS 'ppbs' + class PowerButtonMonitor : public BHandler { - public: - PowerButtonMonitor(); - virtual ~PowerButtonMonitor(); - - virtual void MessageReceived(BMessage *msg); - - private: - int power_button_fd; +public: + PowerButtonMonitor(); + virtual ~PowerButtonMonitor(); + + virtual void MessageReceived(BMessage *msg); + +private: + int fPowerButtonFD; }; + #endif // _POWER_BUTTON_MONITOR_H diff --git a/src/servers/power/power_daemon.cpp b/src/servers/power/power_daemon.cpp index d9611df..a2aa23a 100644 --- a/src/servers/power/power_daemon.cpp +++ b/src/servers/power/power_daemon.cpp @@ -1,7 +1,17 @@ +/* + * Copyright 2005-2013, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Nathan Whitehorn + */ + + +#include "power_button_monitor.h" + #include <Application.h> #include <MessageRunner.h> -#include "power_button_monitor.h" class PowerManagementDaemon : public BApplication { public: @@ -9,18 +19,29 @@ class PowerManagementDaemon : public BApplication { virtual ~PowerManagementDaemon(); }; -int main(void) { + +int +main(void) +{ new PowerManagementDaemon(); be_app->Run(); delete be_app; return 0; } -PowerManagementDaemon::PowerManagementDaemon() : BApplication("application/x-vnd.Haiku-powermanagement") { - PowerButtonMonitor *pb_mon = new PowerButtonMonitor(); - AddHandler(pb_mon); - - new BMessageRunner(BMessenger(pb_mon,this),new BMessage(POLL_POWER_BUTTON_STATUS),5e5 /* twice a second */); + +PowerManagementDaemon::PowerManagementDaemon() + : + BApplication("application/x-vnd.Haiku-powermanagement") +{ + PowerButtonMonitor *powerButtonMonitor = new PowerButtonMonitor(); + AddHandler(powerButtonMonitor); + + new BMessageRunner(BMessenger(powerButtonMonitor,this), + new BMessage(POLL_POWER_BUTTON_STATUS), 5e5 /* twice a second */); } -PowerManagementDaemon::~PowerManagementDaemon() {} + +PowerManagementDaemon::~PowerManagementDaemon() +{ +} ############################################################################ Revision: hrev46364 Commit: c9db30cd7f922e7a828f55c2f234d21e6bfa585a URL: http://cgit.haiku-os.org/haiku/commit/?id=c9db30c Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Wed Nov 13 23:29:20 2013 UTC power_daemon: use wait_for_objects() instead of polling. * acpi_button and acpi_lid support select/deselect hooks. * power_daemon now uses a thread waiting for lid or power button events. * a power button event is still hardcoded to a shutdown. * a lid event only displays a message. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/drivers/power/acpi_button/Jamfile b/src/add-ons/kernel/drivers/power/acpi_button/Jamfile index 74c71c6..bd3bc83 100644 --- a/src/add-ons/kernel/drivers/power/acpi_button/Jamfile +++ b/src/add-ons/kernel/drivers/power/acpi_button/Jamfile @@ -1,5 +1,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers power acpi_button ; +UsePrivateKernelHeaders ; + KernelAddon acpi_button : acpi_button.cpp ; diff --git a/src/add-ons/kernel/drivers/power/acpi_button/acpi_button.cpp b/src/add-ons/kernel/drivers/power/acpi_button/acpi_button.cpp index c0cf44a..a14ce83 100644 --- a/src/add-ons/kernel/drivers/power/acpi_button/acpi_button.cpp +++ b/src/add-ons/kernel/drivers/power/acpi_button/acpi_button.cpp @@ -10,6 +10,8 @@ #include <ACPI.h> +#include <fs/select_sync_pool.h> + #include <stdlib.h> #include <string.h> @@ -40,6 +42,7 @@ typedef struct acpi_ns_device_info { uint32 type; bool fixed; uint8 last_status; + select_sync_pool* select_pool; } acpi_button_device_info; @@ -50,6 +53,8 @@ acpi_button_notify_handler(acpi_handle _device, uint32 value, void *context) if (value == ACPI_NOTIFY_BUTTON_SLEEP) { TRACE("sleep\n"); device->last_status = 1; + if (device->select_pool != NULL) + notify_select_event_pool(device->select_pool, B_SELECT_READ); } else if (value == ACPI_NOTIFY_BUTTON_WAKEUP) { TRACE("wakeup\n"); } else { @@ -65,6 +70,8 @@ acpi_button_fixed_handler(void *context) acpi_button_device_info *device = (acpi_button_device_info *)context; TRACE("sleep\n"); device->last_status = 1; + if (device->select_pool != NULL) + notify_select_event_pool(device->select_pool, B_SELECT_READ); return B_OK; } @@ -106,6 +113,7 @@ acpi_button_init_device(void *_cookie, void **cookie) else return B_ERROR; device->last_status = 0; + device->select_pool = NULL; if (device->fixed) { sAcpi->reset_fixed_event(device->type); @@ -184,6 +192,41 @@ acpi_button_control(void* _cookie, uint32 op, void* arg, size_t len) static status_t +acpi_button_select(void *_cookie, uint8 event, selectsync *sync) +{ + acpi_button_device_info* device = (acpi_button_device_info*)_cookie; + + if (event != B_SELECT_READ) + return B_BAD_VALUE; + + // add the event to the pool + status_t error = add_select_sync_pool_entry(&device->select_pool, sync, + event); + if (error != B_OK) { + ERROR("add_select_sync_pool_entry() failed: %#lx\n", error); + return error; + } + + if (device->last_status != 0) + notify_select_event(sync, event); + + return B_OK; +} + + +static status_t +acpi_button_deselect(void *_cookie, uint8 event, selectsync *sync) +{ + acpi_button_device_info* device = (acpi_button_device_info*)_cookie; + + if (event != B_SELECT_READ) + return B_BAD_VALUE; + + return remove_select_sync_pool_entry(&device->select_pool, sync, event); +} + + +static status_t acpi_button_close (void* cookie) { return B_OK; @@ -330,9 +373,8 @@ struct device_module_info acpi_button_device_module = { acpi_button_write, NULL, acpi_button_control, - - NULL, - NULL + acpi_button_select, + acpi_button_deselect }; module_info *modules[] = { diff --git a/src/add-ons/kernel/drivers/power/acpi_lid/Jamfile b/src/add-ons/kernel/drivers/power/acpi_lid/Jamfile index e104f9a..8d4ed41 100644 --- a/src/add-ons/kernel/drivers/power/acpi_lid/Jamfile +++ b/src/add-ons/kernel/drivers/power/acpi_lid/Jamfile @@ -1,5 +1,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers power acpi_lid ; +UsePrivateKernelHeaders ; + KernelAddon acpi_lid : acpi_lid.cpp ; diff --git a/src/add-ons/kernel/drivers/power/acpi_lid/acpi_lid.cpp b/src/add-ons/kernel/drivers/power/acpi_lid/acpi_lid.cpp index f8f5db8..e6ee5e2 100644 --- a/src/add-ons/kernel/drivers/power/acpi_lid/acpi_lid.cpp +++ b/src/add-ons/kernel/drivers/power/acpi_lid/acpi_lid.cpp @@ -7,6 +7,8 @@ #include <ACPI.h> +#include <fs/select_sync_pool.h> + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -16,13 +18,15 @@ #define ACPI_LID_DEVICE_MODULE_NAME "drivers/power/acpi_lid/device_v1" +#define ACPI_NOTIFY_STATUS_CHANGED 0x80 + /* Base Namespace devices are published to */ #define ACPI_LID_BASENAME "power/acpi_lid/%d" // name of pnp generator of path ids #define ACPI_LID_PATHID_GENERATOR "acpi_lid/path_id" -#define TRACE_LID +//#define TRACE_LID #ifdef TRACE_LID # define TRACE(x...) dprintf("acpi_lid: "x) #else @@ -30,6 +34,7 @@ #endif #define ERROR(x...) dprintf("acpi_lid: "x) + static device_manager_info *sDeviceManager; @@ -38,16 +43,43 @@ typedef struct acpi_ns_device_info { acpi_device_module_info *acpi; acpi_device acpi_cookie; uint8 last_status; + bool updated; + select_sync_pool* select_pool; } acpi_lid_device_info; static void -acpi_lid_notify_handler(acpi_handle device, uint32 value, void *context) +acpi_lid_read_status(acpi_lid_device_info *device) +{ + acpi_data buf; + buf.pointer = NULL; + buf.length = ACPI_ALLOCATE_BUFFER; + if (device->acpi->evaluate_method(device->acpi_cookie, "_LID", NULL, + &buf) != B_OK + || buf.pointer == NULL + || ((acpi_object_type*)buf.pointer)->object_type != ACPI_TYPE_INTEGER) { + ERROR("couldn't get status\n"); + } else { + acpi_object_type* object = (acpi_object_type*)buf.pointer; + device->last_status = object->integer.integer; + device->updated = true; + free(buf.pointer); + TRACE("status %d\n", device->last_status); + } +} + + +static void +acpi_lid_notify_handler(acpi_handle _device, uint32 value, void *context) { - if (value == 0x80) { - dprintf("acpi_lid: status changed\n"); + acpi_lid_device_info *device = (acpi_lid_device_info *)context; + if (value == ACPI_NOTIFY_STATUS_CHANGED) { + TRACE("status changed\n"); + acpi_lid_read_status(device); + if (device->select_pool != NULL) + notify_select_event_pool(device->select_pool, B_SELECT_READ); } else { - dprintf("acpi_lid: unknown notification\n"); + ERROR("unknown notification\n"); } } @@ -83,7 +115,14 @@ acpi_lid_open(void *_cookie, const char *path, int flags, void** cookie) static status_t acpi_lid_read(void* _cookie, off_t position, void *buf, size_t* num_bytes) { - return B_ERROR; + acpi_lid_device_info* device = (acpi_lid_device_info*)_cookie; + if (*num_bytes < 1) + return B_IO_ERROR; + + *((uint8 *)(buf)) = device->last_status; + *num_bytes = 1; + device->updated = false; + return B_OK; } @@ -102,6 +141,41 @@ acpi_lid_control(void* _cookie, uint32 op, void* arg, size_t len) static status_t +acpi_lid_select(void *_cookie, uint8 event, selectsync *sync) +{ + acpi_lid_device_info* device = (acpi_lid_device_info*)_cookie; + + if (event != B_SELECT_READ) + return B_BAD_VALUE; + + // add the event to the pool + status_t error = add_select_sync_pool_entry(&device->select_pool, sync, + event); + if (error != B_OK) { + ERROR("add_select_sync_pool_entry() failed: %#lx\n", error); + return error; + } + + if (device->updated) + notify_select_event(sync, event); + + return B_OK; +} + + +static status_t +acpi_lid_deselect(void *_cookie, uint8 event, selectsync *sync) +{ + acpi_lid_device_info* device = (acpi_lid_device_info*)_cookie; + + if (event != B_SELECT_READ) + return B_BAD_VALUE; + + return remove_select_sync_pool_entry(&device->select_pool, sync, event); +} + + +static status_t acpi_lid_close (void* cookie) { return B_OK; @@ -189,20 +263,8 @@ acpi_lid_init_driver(device_node *node, void **_driverCookie) } device->last_status = 0; - acpi_data buf; - buf.pointer = NULL; - buf.length = ACPI_ALLOCATE_BUFFER; - if (device->acpi->evaluate_method(device->acpi_cookie, "_LID", NULL, - &buf) != B_OK - || buf.pointer == NULL - || ((acpi_object_type*)buf.pointer)->object_type != ACPI_TYPE_INTEGER) { - ERROR("couldn't get status\n"); - } else { - acpi_object_type* object = (acpi_object_type*)buf.pointer; - device->last_status = object->integer.integer; - free(buf.pointer); - TRACE("status %d\n", device->last_status); - } + device->updated = false; + device->select_pool = NULL; *_driverCookie = device; return B_OK; @@ -282,9 +344,8 @@ struct device_module_info acpi_lid_device_module = { acpi_lid_write, NULL, acpi_lid_control, - - NULL, - NULL + acpi_lid_select, + acpi_lid_deselect }; module_info *modules[] = { diff --git a/src/servers/power/Jamfile b/src/servers/power/Jamfile index 8e94eb9..9ab72a5 100644 --- a/src/servers/power/Jamfile +++ b/src/servers/power/Jamfile @@ -5,6 +5,7 @@ UsePrivateHeaders app ; AddResources power_daemon : power_daemon.rdef ; Server power_daemon : + lid_monitor.cpp power_daemon.cpp power_button_monitor.cpp ; diff --git a/src/servers/power/power_button_monitor.cpp b/src/servers/power/power_button_monitor.cpp index ab1ae19..a5da6eb 100644 --- a/src/servers/power/power_button_monitor.cpp +++ b/src/servers/power/power_button_monitor.cpp @@ -16,31 +16,26 @@ PowerButtonMonitor::PowerButtonMonitor() - : - BHandler ("power_button_monitor") { - fPowerButtonFD = open("/dev/power/button/power", O_RDONLY); + fFD = open("/dev/power/button/power", O_RDONLY); } PowerButtonMonitor::~PowerButtonMonitor() { - if (fPowerButtonFD > 0) - close(fPowerButtonFD); + if (fFD > 0) + close(fFD); } void -PowerButtonMonitor::MessageReceived(BMessage *msg) +PowerButtonMonitor::HandleEvent() { - if (msg->what != POLL_POWER_BUTTON_STATUS) - return; - - if (fPowerButtonFD <= 0) + if (fFD <= 0) return; uint8 button_pressed; - read(fPowerButtonFD, &button_pressed, 1); + read(fFD, &button_pressed, 1); if (button_pressed) { BRoster roster; diff --git a/src/servers/power/power_button_monitor.h b/src/servers/power/power_button_monitor.h index 9313289..92f87d9 100644 --- a/src/servers/power/power_button_monitor.h +++ b/src/servers/power/power_button_monitor.h @@ -9,21 +9,16 @@ #define _POWER_BUTTON_MONITOR_H -#include <Handler.h> - - -#define POLL_POWER_BUTTON_STATUS 'ppbs' - - -class PowerButtonMonitor : public BHandler { +class PowerButtonMonitor { public: PowerButtonMonitor(); - virtual ~PowerButtonMonitor(); + ~PowerButtonMonitor(); - virtual void MessageReceived(BMessage *msg); + void HandleEvent(); + int FD() const { return fFD; } private: - int fPowerButtonFD; + int fFD; }; diff --git a/src/servers/power/power_daemon.cpp b/src/servers/power/power_daemon.cpp index a2aa23a..d13e007 100644 --- a/src/servers/power/power_daemon.cpp +++ b/src/servers/power/power_daemon.cpp @@ -1,22 +1,30 @@ /* - * Copyright 2005-2013, Haiku, Inc. - * Distributed under the terms of the MIT license. + * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx. + * Copyright 2005, Nathan Whitehorn. * - * Authors: - * Nathan Whitehorn + * Distributed under the terms of the MIT License. */ +#include "lid_monitor.h" #include "power_button_monitor.h" #include <Application.h> -#include <MessageRunner.h> class PowerManagementDaemon : public BApplication { - public: - PowerManagementDaemon(); - virtual ~PowerManagementDaemon(); +public: + PowerManagementDaemon(); + virtual ~PowerManagementDaemon(); +private: + void _EventLoop(); + static status_t _EventLooper(void *arg); + + thread_id fEventThread; + PowerButtonMonitor* fPowerButtonMonitor; + LidMonitor* fLidMonitor; + + bool fQuitRequested; }; @@ -32,16 +40,57 @@ main(void) PowerManagementDaemon::PowerManagementDaemon() : - BApplication("application/x-vnd.Haiku-powermanagement") + BApplication("application/x-vnd.Haiku-powermanagement"), + fPowerButtonMonitor(NULL), + fQuitRequested(false) { - PowerButtonMonitor *powerButtonMonitor = new PowerButtonMonitor(); - AddHandler(powerButtonMonitor); - - new BMessageRunner(BMessenger(powerButtonMonitor,this), - new BMessage(POLL_POWER_BUTTON_STATUS), 5e5 /* twice a second */); + fPowerButtonMonitor = new PowerButtonMonitor; + fLidMonitor = new LidMonitor; + fEventThread = spawn_thread(_EventLooper, "_power_daemon_event_loop_", + B_NORMAL_PRIORITY, this); + if (fEventThread < B_OK) + return; + if (resume_thread(fEventThread) < B_OK) { + kill_thread(fEventThread); + fEventThread = -1; + return; + } } PowerManagementDaemon::~PowerManagementDaemon() { + fQuitRequested = true; + delete fPowerButtonMonitor; + delete fLidMonitor; + status_t status; + wait_for_thread(fEventThread, &status); +} + + +status_t +PowerManagementDaemon::_EventLooper(void* arg) +{ + PowerManagementDaemon* self = (PowerManagementDaemon*)arg; + self->_EventLoop(); + return B_OK; +} + + +void +PowerManagementDaemon::_EventLoop() +{ + while (!fQuitRequested) { + object_wait_info info[] = { + { fPowerButtonMonitor->FD(), B_OBJECT_TYPE_FD, B_EVENT_READ }, + { fLidMonitor->FD(), B_OBJECT_TYPE_FD, B_EVENT_READ } + }; + + if (wait_for_objects_etc(info, 2, 0, 1000000LL) < B_OK) + continue; + if (info[0].events & B_EVENT_READ) + fPowerButtonMonitor->HandleEvent(); + if (info[1].events & B_EVENT_READ) + fLidMonitor->HandleEvent(); + } }