From d0a75d2c3a167a4a91d1c1751eff576e49c19d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 1 Nov 2013 20:27:22 +0100 Subject: [PATCH] acpi: added driver for AC Adapter devices. * correctly report the AC status * notify handler not called --- src/add-ons/kernel/drivers/power/Jamfile | 1 + .../kernel/drivers/power/acpi_ac/Jamfile | 5 + .../kernel/drivers/power/acpi_ac/acpi_ac.cpp | 300 ++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 src/add-ons/kernel/drivers/power/acpi_ac/Jamfile create mode 100644 src/add-ons/kernel/drivers/power/acpi_ac/acpi_ac.cpp diff --git a/src/add-ons/kernel/drivers/power/Jamfile b/src/add-ons/kernel/drivers/power/Jamfile index 45feced8e9..01c7932d19 100644 --- a/src/add-ons/kernel/drivers/power/Jamfile +++ b/src/add-ons/kernel/drivers/power/Jamfile @@ -1,5 +1,6 @@ SubDir HAIKU_TOP src add-ons kernel drivers power ; +SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_ac ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_battery ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_button ; SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ; diff --git a/src/add-ons/kernel/drivers/power/acpi_ac/Jamfile b/src/add-ons/kernel/drivers/power/acpi_ac/Jamfile new file mode 100644 index 0000000000..9d36385765 --- /dev/null +++ b/src/add-ons/kernel/drivers/power/acpi_ac/Jamfile @@ -0,0 +1,5 @@ +SubDir HAIKU_TOP src add-ons kernel drivers power acpi_ac ; + +KernelAddon acpi_ac : + acpi_ac.cpp + ; diff --git a/src/add-ons/kernel/drivers/power/acpi_ac/acpi_ac.cpp b/src/add-ons/kernel/drivers/power/acpi_ac/acpi_ac.cpp new file mode 100644 index 0000000000..009aba1a6e --- /dev/null +++ b/src/add-ons/kernel/drivers/power/acpi_ac/acpi_ac.cpp @@ -0,0 +1,300 @@ +/* + * Copyright 2013, Jérôme Duval, korli@users.berlios.de. + * + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include +#include + + +#define ACPI_AC_MODULE_NAME "drivers/power/acpi_ac/driver_v1" + +#define ACPI_AC_DEVICE_MODULE_NAME "drivers/power/acpi_ac/device_v1" + +/* Base Namespace devices are published to */ +#define ACPI_AC_BASENAME "power/acpi_ac/%d" + +// name of pnp generator of path ids +#define ACPI_AC_PATHID_GENERATOR "acpi_ac/path_id" + +#define TRACE_AC +#ifdef TRACE_AC +# define TRACE(x...) dprintf("acpi_ac: "x) +#else +# define TRACE(x...) +#endif +#define ERROR(x...) dprintf("acpi_ac: "x) + +static device_manager_info *sDeviceManager; + + +typedef struct acpi_ns_device_info { + device_node *node; + acpi_device_module_info *acpi; + acpi_device acpi_cookie; + uint8 last_status; +} acpi_ac_device_info; + + +static void +acpi_ac_notify_handler(acpi_handle device, uint32 value, void *context) +{ + if (value == 0x80) { + dprintf("acpi_ac: status changed\n"); + } else { + dprintf("acpi_ac: unknown notification\n"); + } + +} + + +// #pragma mark - device module API + + +static status_t +acpi_ac_init_device(void *_cookie, void **cookie) +{ + device_node *node = (device_node *)_cookie; + acpi_ac_device_info *device; + device_node *parent; + status_t status; + + device = (acpi_ac_device_info *)calloc(1, sizeof(*device)); + if (device == NULL) + return B_NO_MEMORY; + + device->node = node; + + parent = sDeviceManager->get_parent_node(node); + sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi, + (void **)&device->acpi_cookie); + sDeviceManager->put_node(parent); + + status = device->acpi->install_notify_handler(device->acpi_cookie, + ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, device); + if (status != B_OK) { + ERROR("can't install notify handler\n"); + } + + device->last_status = 0; + acpi_data buf; + buf.pointer = NULL; + buf.length = ACPI_ALLOCATE_BUFFER; + if (device->acpi->evaluate_method(device->acpi_cookie, "_PSR", 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); + } + + *cookie = device; + return B_OK; +} + + +static void +acpi_ac_uninit_device(void *_cookie) +{ + acpi_ac_device_info *device = (acpi_ac_device_info *)_cookie; + + device->acpi->remove_notify_handler(device->acpi_cookie, + ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler); + + free(device); +} + + +static status_t +acpi_ac_open(void *_cookie, const char *path, int flags, void** cookie) +{ + acpi_ac_device_info *device = (acpi_ac_device_info *)_cookie; + *cookie = device; + return B_OK; +} + + +static status_t +acpi_ac_read(void* _cookie, off_t position, void *buf, size_t* num_bytes) +{ + acpi_ac_device_info* device = (acpi_ac_device_info*)_cookie; + if (*num_bytes < 1) + return B_IO_ERROR; + + *((uint8 *)(buf)) = device->last_status; + + *num_bytes = 1; + return B_OK; +} + + +static status_t +acpi_ac_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) +{ + return B_ERROR; +} + + +static status_t +acpi_ac_control(void* _cookie, uint32 op, void* arg, size_t len) +{ + return B_ERROR; +} + + +static status_t +acpi_ac_close (void* cookie) +{ + return B_OK; +} + + +static status_t +acpi_ac_free (void* cookie) +{ + return B_OK; +} + + +// #pragma mark - driver module API + + +static float +acpi_ac_support(device_node *parent) +{ + const char *bus; + uint32 device_type; + const char *hid; + + // make sure parent is really the ACPI bus manager + if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) + return -1; + + if (strcmp(bus, "acpi")) + return 0.0; + + // check whether it's really a device + if (sDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, + &device_type, false) != B_OK + || device_type != ACPI_TYPE_DEVICE) { + return 0.0; + } + + // check whether it's an ac device + if (sDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &hid, + false) != B_OK || strcmp(hid, "ACPI0003")) { + return 0.0; + } + + dprintf("acpi_ac_support ac device found\n"); + + return 0.6; +} + + +static status_t +acpi_ac_register_device(device_node *node) +{ + device_attr attrs[] = { + { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI AC" }}, + { NULL } + }; + + return sDeviceManager->register_node(node, ACPI_AC_MODULE_NAME, attrs, + NULL, NULL); +} + + +static status_t +acpi_ac_init_driver(device_node *node, void **_driverCookie) +{ + *_driverCookie = node; + return B_OK; +} + + +static void +acpi_ac_uninit_driver(void *driverCookie) +{ +} + + +static status_t +acpi_ac_register_child_devices(void *_cookie) +{ + device_node *node = (device_node *)_cookie; + int path_id; + char name[128]; + + path_id = sDeviceManager->create_id(ACPI_AC_PATHID_GENERATOR); + if (path_id < 0) { + dprintf("acpi_ac_register_child_devices: couldn't create a path_id\n"); + return B_ERROR; + } + + snprintf(name, sizeof(name), ACPI_AC_BASENAME, path_id); + + return sDeviceManager->publish_device(node, name, ACPI_AC_DEVICE_MODULE_NAME); +} + + +module_dependency module_dependencies[] = { + { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager }, + {} +}; + + +driver_module_info acpi_ac_driver_module = { + { + ACPI_AC_MODULE_NAME, + 0, + NULL + }, + + acpi_ac_support, + acpi_ac_register_device, + acpi_ac_init_driver, + acpi_ac_uninit_driver, + acpi_ac_register_child_devices, + NULL, // rescan + NULL, // removed +}; + + +struct device_module_info acpi_ac_device_module = { + { + ACPI_AC_DEVICE_MODULE_NAME, + 0, + NULL + }, + + acpi_ac_init_device, + acpi_ac_uninit_device, + NULL, + + acpi_ac_open, + acpi_ac_close, + acpi_ac_free, + acpi_ac_read, + acpi_ac_write, + NULL, + acpi_ac_control, + + NULL, + NULL +}; + +module_info *modules[] = { + (module_info *)&acpi_ac_driver_module, + (module_info *)&acpi_ac_device_module, + NULL +};