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.
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers power acpi_button ;
|
SubDir HAIKU_TOP src add-ons kernel drivers power acpi_button ;
|
||||||
|
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
KernelAddon acpi_button :
|
KernelAddon acpi_button :
|
||||||
acpi_button.cpp
|
acpi_button.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include <ACPI.h>
|
#include <ACPI.h>
|
||||||
|
|
||||||
|
#include <fs/select_sync_pool.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@ typedef struct acpi_ns_device_info {
|
|||||||
uint32 type;
|
uint32 type;
|
||||||
bool fixed;
|
bool fixed;
|
||||||
uint8 last_status;
|
uint8 last_status;
|
||||||
|
select_sync_pool* select_pool;
|
||||||
} acpi_button_device_info;
|
} 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) {
|
if (value == ACPI_NOTIFY_BUTTON_SLEEP) {
|
||||||
TRACE("sleep\n");
|
TRACE("sleep\n");
|
||||||
device->last_status = 1;
|
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) {
|
} else if (value == ACPI_NOTIFY_BUTTON_WAKEUP) {
|
||||||
TRACE("wakeup\n");
|
TRACE("wakeup\n");
|
||||||
} else {
|
} else {
|
||||||
@@ -65,6 +70,8 @@ acpi_button_fixed_handler(void *context)
|
|||||||
acpi_button_device_info *device = (acpi_button_device_info *)context;
|
acpi_button_device_info *device = (acpi_button_device_info *)context;
|
||||||
TRACE("sleep\n");
|
TRACE("sleep\n");
|
||||||
device->last_status = 1;
|
device->last_status = 1;
|
||||||
|
if (device->select_pool != NULL)
|
||||||
|
notify_select_event_pool(device->select_pool, B_SELECT_READ);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +113,7 @@ acpi_button_init_device(void *_cookie, void **cookie)
|
|||||||
else
|
else
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
device->last_status = 0;
|
device->last_status = 0;
|
||||||
|
device->select_pool = NULL;
|
||||||
|
|
||||||
if (device->fixed) {
|
if (device->fixed) {
|
||||||
sAcpi->reset_fixed_event(device->type);
|
sAcpi->reset_fixed_event(device->type);
|
||||||
@@ -183,6 +191,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
|
static status_t
|
||||||
acpi_button_close (void* cookie)
|
acpi_button_close (void* cookie)
|
||||||
{
|
{
|
||||||
@@ -330,9 +373,8 @@ struct device_module_info acpi_button_device_module = {
|
|||||||
acpi_button_write,
|
acpi_button_write,
|
||||||
NULL,
|
NULL,
|
||||||
acpi_button_control,
|
acpi_button_control,
|
||||||
|
acpi_button_select,
|
||||||
NULL,
|
acpi_button_deselect
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info *modules[] = {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers power acpi_lid ;
|
SubDir HAIKU_TOP src add-ons kernel drivers power acpi_lid ;
|
||||||
|
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
KernelAddon acpi_lid :
|
KernelAddon acpi_lid :
|
||||||
acpi_lid.cpp
|
acpi_lid.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <ACPI.h>
|
#include <ACPI.h>
|
||||||
|
|
||||||
|
#include <fs/select_sync_pool.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -16,13 +18,15 @@
|
|||||||
|
|
||||||
#define ACPI_LID_DEVICE_MODULE_NAME "drivers/power/acpi_lid/device_v1"
|
#define ACPI_LID_DEVICE_MODULE_NAME "drivers/power/acpi_lid/device_v1"
|
||||||
|
|
||||||
|
#define ACPI_NOTIFY_STATUS_CHANGED 0x80
|
||||||
|
|
||||||
/* Base Namespace devices are published to */
|
/* Base Namespace devices are published to */
|
||||||
#define ACPI_LID_BASENAME "power/acpi_lid/%d"
|
#define ACPI_LID_BASENAME "power/acpi_lid/%d"
|
||||||
|
|
||||||
// name of pnp generator of path ids
|
// name of pnp generator of path ids
|
||||||
#define ACPI_LID_PATHID_GENERATOR "acpi_lid/path_id"
|
#define ACPI_LID_PATHID_GENERATOR "acpi_lid/path_id"
|
||||||
|
|
||||||
#define TRACE_LID
|
//#define TRACE_LID
|
||||||
#ifdef TRACE_LID
|
#ifdef TRACE_LID
|
||||||
# define TRACE(x...) dprintf("acpi_lid: "x)
|
# define TRACE(x...) dprintf("acpi_lid: "x)
|
||||||
#else
|
#else
|
||||||
@@ -30,6 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define ERROR(x...) dprintf("acpi_lid: "x)
|
#define ERROR(x...) dprintf("acpi_lid: "x)
|
||||||
|
|
||||||
|
|
||||||
static device_manager_info *sDeviceManager;
|
static device_manager_info *sDeviceManager;
|
||||||
|
|
||||||
|
|
||||||
@@ -38,16 +43,43 @@ typedef struct acpi_ns_device_info {
|
|||||||
acpi_device_module_info *acpi;
|
acpi_device_module_info *acpi;
|
||||||
acpi_device acpi_cookie;
|
acpi_device acpi_cookie;
|
||||||
uint8 last_status;
|
uint8 last_status;
|
||||||
|
bool updated;
|
||||||
|
select_sync_pool* select_pool;
|
||||||
} acpi_lid_device_info;
|
} acpi_lid_device_info;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acpi_lid_notify_handler(acpi_handle device, uint32 value, void *context)
|
acpi_lid_read_status(acpi_lid_device_info *device)
|
||||||
{
|
{
|
||||||
if (value == 0x80) {
|
acpi_data buf;
|
||||||
dprintf("acpi_lid: status changed\n");
|
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 {
|
} else {
|
||||||
dprintf("acpi_lid: unknown notification\n");
|
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)
|
||||||
|
{
|
||||||
|
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 {
|
||||||
|
ERROR("unknown notification\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -83,7 +115,14 @@ acpi_lid_open(void *_cookie, const char *path, int flags, void** cookie)
|
|||||||
static status_t
|
static status_t
|
||||||
acpi_lid_read(void* _cookie, off_t position, void *buf, size_t* num_bytes)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -101,6 +140,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
|
static status_t
|
||||||
acpi_lid_close (void* cookie)
|
acpi_lid_close (void* cookie)
|
||||||
{
|
{
|
||||||
@@ -189,20 +263,8 @@ acpi_lid_init_driver(device_node *node, void **_driverCookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
device->last_status = 0;
|
device->last_status = 0;
|
||||||
acpi_data buf;
|
device->updated = false;
|
||||||
buf.pointer = NULL;
|
device->select_pool = 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
*_driverCookie = device;
|
*_driverCookie = device;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -282,9 +344,8 @@ struct device_module_info acpi_lid_device_module = {
|
|||||||
acpi_lid_write,
|
acpi_lid_write,
|
||||||
NULL,
|
NULL,
|
||||||
acpi_lid_control,
|
acpi_lid_control,
|
||||||
|
acpi_lid_select,
|
||||||
NULL,
|
acpi_lid_deselect
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info *modules[] = {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ UsePrivateHeaders app ;
|
|||||||
AddResources power_daemon : power_daemon.rdef ;
|
AddResources power_daemon : power_daemon.rdef ;
|
||||||
|
|
||||||
Server power_daemon :
|
Server power_daemon :
|
||||||
|
lid_monitor.cpp
|
||||||
power_daemon.cpp
|
power_daemon.cpp
|
||||||
power_button_monitor.cpp
|
power_button_monitor.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -16,31 +16,26 @@
|
|||||||
|
|
||||||
|
|
||||||
PowerButtonMonitor::PowerButtonMonitor()
|
PowerButtonMonitor::PowerButtonMonitor()
|
||||||
:
|
|
||||||
BHandler ("power_button_monitor")
|
|
||||||
{
|
{
|
||||||
fPowerButtonFD = open("/dev/power/button/power", O_RDONLY);
|
fFD = open("/dev/power/button/power", O_RDONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PowerButtonMonitor::~PowerButtonMonitor()
|
PowerButtonMonitor::~PowerButtonMonitor()
|
||||||
{
|
{
|
||||||
if (fPowerButtonFD > 0)
|
if (fFD > 0)
|
||||||
close(fPowerButtonFD);
|
close(fFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PowerButtonMonitor::MessageReceived(BMessage *msg)
|
PowerButtonMonitor::HandleEvent()
|
||||||
{
|
{
|
||||||
if (msg->what != POLL_POWER_BUTTON_STATUS)
|
if (fFD <= 0)
|
||||||
return;
|
|
||||||
|
|
||||||
if (fPowerButtonFD <= 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8 button_pressed;
|
uint8 button_pressed;
|
||||||
read(fPowerButtonFD, &button_pressed, 1);
|
read(fFD, &button_pressed, 1);
|
||||||
|
|
||||||
if (button_pressed) {
|
if (button_pressed) {
|
||||||
BRoster roster;
|
BRoster roster;
|
||||||
|
|||||||
@@ -9,21 +9,16 @@
|
|||||||
#define _POWER_BUTTON_MONITOR_H
|
#define _POWER_BUTTON_MONITOR_H
|
||||||
|
|
||||||
|
|
||||||
#include <Handler.h>
|
class PowerButtonMonitor {
|
||||||
|
|
||||||
|
|
||||||
#define POLL_POWER_BUTTON_STATUS 'ppbs'
|
|
||||||
|
|
||||||
|
|
||||||
class PowerButtonMonitor : public BHandler {
|
|
||||||
public:
|
public:
|
||||||
PowerButtonMonitor();
|
PowerButtonMonitor();
|
||||||
virtual ~PowerButtonMonitor();
|
~PowerButtonMonitor();
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage *msg);
|
void HandleEvent();
|
||||||
|
|
||||||
|
int FD() const { return fFD; }
|
||||||
private:
|
private:
|
||||||
int fPowerButtonFD;
|
int fFD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2013, Haiku, Inc.
|
* Copyright 2013, Jérôme Duval, [email protected].
|
||||||
* Distributed under the terms of the MIT license.
|
* Copyright 2005, Nathan Whitehorn.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Distributed under the terms of the MIT License.
|
||||||
* Nathan Whitehorn
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "lid_monitor.h"
|
||||||
#include "power_button_monitor.h"
|
#include "power_button_monitor.h"
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <MessageRunner.h>
|
|
||||||
|
|
||||||
|
|
||||||
class PowerManagementDaemon : public BApplication {
|
class PowerManagementDaemon : public BApplication {
|
||||||
public:
|
public:
|
||||||
PowerManagementDaemon();
|
PowerManagementDaemon();
|
||||||
virtual ~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()
|
PowerManagementDaemon::PowerManagementDaemon()
|
||||||
:
|
:
|
||||||
BApplication("application/x-vnd.Haiku-powermanagement")
|
BApplication("application/x-vnd.Haiku-powermanagement"),
|
||||||
|
fPowerButtonMonitor(NULL),
|
||||||
|
fQuitRequested(false)
|
||||||
{
|
{
|
||||||
PowerButtonMonitor *powerButtonMonitor = new PowerButtonMonitor();
|
fPowerButtonMonitor = new PowerButtonMonitor;
|
||||||
AddHandler(powerButtonMonitor);
|
fLidMonitor = new LidMonitor;
|
||||||
|
fEventThread = spawn_thread(_EventLooper, "_power_daemon_event_loop_",
|
||||||
new BMessageRunner(BMessenger(powerButtonMonitor,this),
|
B_NORMAL_PRIORITY, this);
|
||||||
new BMessage(POLL_POWER_BUTTON_STATUS), 5e5 /* twice a second */);
|
if (fEventThread < B_OK)
|
||||||
|
return;
|
||||||
|
if (resume_thread(fEventThread) < B_OK) {
|
||||||
|
kill_thread(fEventThread);
|
||||||
|
fEventThread = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PowerManagementDaemon::~PowerManagementDaemon()
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user