Ticket #2841: acpi-battery.diff

File acpi-battery.diff, 20.9 KB (added by nopper, 15 years ago)

Typo fix

  • build/jam/HaikuImage

     
    205205AddNewDriversToHaikuImage disk scsi : scsi_cd scsi_disk ;
    206206AddNewDriversToHaikuImage power : $(X86_ONLY)enhanced_speedstep ;
    207207AddNewDriversToHaikuImage power : $(X86_ONLY)acpi_embedded_controller ;
     208AddNewDriversToHaikuImage power : $(X86_ONLY)acpi_battery ;
    208209
    209210# legacy drivers
    210211AddDriversToHaikuImage              : console dprintf $(X86_ONLY)keyboard null
  • src/add-ons/kernel/drivers/power/acpi_battery/Jamfile

     
     1SubDir HAIKU_TOP src add-ons kernel drivers power acpi_battery ;
     2
     3SetSubDirSupportedPlatformsBeOSCompatible ;
     4
     5if $(TARGET_PLATFORM) != haiku {
     6    # Needed for <ACPI.h>. Unfortunately we also get the other headers there,
     7    # that we don't really want.
     8    UsePublicHeaders drivers ;
     9}
     10
     11KernelAddon acpi_battery :
     12    acpi_battery.c
     13    ;
     14
     15Depends acpi_battery : acpi ;
  • src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.c

     
     1/*
     2 * Copyright 2009 Francesco Piccinno <stack.box@gmail.com>
     3 *
     4 * Simple acpi_battery implementation for haiku ported from Linux.
     5 *
     6 * Distributed under the terms of the MIT License.
     7 */
     8
     9#include <KernelExport.h>
     10#include <Drivers.h>
     11#include <Errors.h>
     12#include <string.h>
     13
     14#include <stdio.h>
     15#include <stdlib.h>
     16
     17#include <ACPI.h>
     18#include "acpi_battery.h"
     19
     20#define ACPI_BATTERY_MODULE_NAME "drivers/power/acpi_battery/driver_v1"
     21
     22#define ACPI_BATTERY_DEVICE_MODULE_NAME "drivers/power/acpi_battery/device_v1"
     23
     24/* Base Namespace devices are published to */
     25#define ACPI_BATTERY_BASENAME "power/acpi_battery/%d"
     26
     27// name of pnp generator of path ids
     28#define ACPI_BATTERY_PATHID_GENERATOR "acpi_battery/path_id"
     29
     30#define TRACE_ACPI_BATTERY
     31
     32#ifdef TRACE_ACPI_BATTERY
     33#   define TRACE(x...) dprintf("acpi_battery: " x)
     34#else
     35#   define TRACE(x...)
     36#endif
     37
     38static device_manager_info *sDeviceManager;
     39
     40typedef struct acpi_ns_device_info {
     41    device_node *node;
     42    acpi_device_module_info *acpi;
     43    acpi_device acpi_cookie;
     44    acpi_battery_type *battery;
     45} acpi_battery_device_info;
     46
     47/* Proto */
     48static status_t acpi_battery_control(void*, uint32, void*, size_t);
     49
     50inline int
     51acpi_battery_present(acpi_battery_device_info *device)
     52{
     53    return device->battery->status.battery_present;
     54}
     55
     56static inline char *acpi_battery_units(struct acpi_battery_type *battery)
     57{
     58    return (battery->power_unit) ? "mA" : "mW";
     59}
     60
     61static int acpi_extract_package(struct acpi_battery_type *battery,
     62                                 acpi_object_type *package,
     63                                 struct acpi_offsets *offsets, int num)
     64{
     65    int i;
     66    acpi_object_type *element;
     67
     68    if (package->object_type != ACPI_TYPE_PACKAGE)
     69        return B_ERROR;
     70
     71    for (i = 0; i < num; ++i) {
     72        if (package->data.package.count <= i)
     73            return B_ERROR;
     74
     75        element = &package->data.package.objects[i];
     76
     77        if (offsets[i].mode) {
     78            uint8 *ptr = (uint8 *)battery + offsets[i].offset;
     79
     80            if (element->object_type == ACPI_TYPE_STRING ||
     81                element->object_type == ACPI_TYPE_BUFFER)
     82                    strncpy((char *)ptr, element->data.string.string, 32);
     83
     84            else if (element->object_type == ACPI_TYPE_INTEGER) {
     85                strncpy((char *)ptr, (char *)&element->data.integer,
     86                        sizeof(uint32));
     87                ptr[sizeof(uint32)] = 0;
     88            } else
     89                *ptr = 0; /* don't have value */
     90        } else {
     91            int *x = (int *)((uint8 *)battery + offsets[i].offset);
     92            *x = (element->object_type == ACPI_TYPE_INTEGER) ?
     93                    element->data.integer : -1;
     94        }
     95    }
     96    return B_OK;
     97}
     98
     99static int
     100acpi_bus_get_status (acpi_battery_device_info *device, acpi_battery_type *batt)
     101{
     102    acpi_data buf;
     103    acpi_object_type object;
     104    buf.pointer = &object;
     105    buf.length = sizeof(acpi_object_type);
     106
     107    status_t status = B_OK;
     108
     109    if (!device)
     110        return B_ERROR;
     111
     112    status = device->acpi->evaluate_method(device->acpi_cookie, "_STA",
     113                                           NULL, &buf);
     114
     115    if (status == B_OK) {
     116        if (object.object_type == ACPI_TYPE_INTEGER)
     117            (*((int*)&batt->status)) = (int)object.data.integer;
     118        else
     119            status = B_ERROR;
     120    }
     121
     122    if (status == B_ERROR)
     123        (*((int*)&batt->status)) = 0x0F;
     124
     125    return B_ERROR;
     126}
     127
     128static status_t
     129acpi_battery_init_device(void *_cookie, void **cookie)
     130{
     131    device_node *node = (device_node *)_cookie;
     132    acpi_battery_device_info *device;
     133    device_node *parent;
     134
     135    device = \
     136        (acpi_battery_device_info *)malloc(sizeof(acpi_battery_device_info));
     137
     138    if (device == NULL)
     139        return B_NO_MEMORY;
     140
     141    memset(device, 0, sizeof(acpi_battery_device_info));
     142
     143    device->battery = (acpi_battery_type *)malloc(sizeof(acpi_battery_type));
     144
     145    if (device->battery == NULL)
     146        return B_NO_MEMORY;
     147
     148    memset(device->battery, 0, sizeof(acpi_battery_type));
     149
     150    device->node = node;
     151
     152    parent = sDeviceManager->get_parent_node(node);
     153    sDeviceManager->get_driver(parent, (driver_module_info **)&device->acpi,
     154        (void **)&device->acpi_cookie);
     155    sDeviceManager->put_node(parent);
     156
     157    *cookie = device;
     158
     159    return B_OK;
     160}
     161
     162static void
     163acpi_battery_uninit_device(void *_cookie)
     164{
     165    acpi_battery_device_info *device = (acpi_battery_device_info *)_cookie;
     166
     167    if (device) {
     168        if (device->battery)
     169            free(device->battery);
     170        free(device);
     171    }
     172}
     173
     174static status_t
     175acpi_battery_open(void *_cookie, const char *path, int flags, void** cookie)
     176{
     177    acpi_battery_device_info *device = (acpi_battery_device_info *)_cookie;
     178    *cookie = device;
     179    return B_OK;
     180}
     181
     182static status_t
     183acpi_battery_control(void* _cookie, uint32 op, void* arg, size_t len)
     184{
     185    acpi_battery_device_info* device = (acpi_battery_device_info*)_cookie;
     186    status_t err = B_ERROR;
     187
     188    acpi_data buf;
     189    buf.pointer = NULL;
     190    buf.length = ACPI_ALLOCATE_BUFFER;
     191
     192    acpi_battery_type *att;
     193
     194    if (arg == NULL)
     195        att = (acpi_battery_type *)device->battery;
     196    else
     197        att = (acpi_battery_type *)arg;
     198
     199    if (att == NULL) {
     200        TRACE("NULL pointer\n");
     201        return B_ERROR;
     202    }
     203
     204    switch (op) {
     205        case drvOpGetBatteryState: {
     206            TRACE("evaluating _BST to get battery state: ");
     207
     208            err = device->acpi->evaluate_method(device->acpi_cookie, "_BST",
     209                                                NULL, &buf);
     210
     211            if (err != B_OK)
     212                break;
     213
     214            err = acpi_extract_package(att, buf.pointer, state_offsets,
     215                                       ARRAY_SIZE(state_offsets));
     216            break;
     217        }
     218        case drvOpGetBatteryInfo: {
     219            TRACE("evaluating _BIF to get battery informations: ");
     220
     221            err = device->acpi->evaluate_method(device->acpi_cookie, "_BIF",
     222                                                NULL, &buf);
     223
     224            if (err != B_OK)
     225                break;
     226
     227            err = acpi_extract_package(att, buf.pointer, info_offsets,
     228                                       ARRAY_SIZE(info_offsets));
     229            break;
     230        }
     231        case drvOpGetBatteryPresent: {
     232            TRACE("evaluating _STA to check for battery presence: ");
     233            err = acpi_bus_get_status(device, att);
     234            break;
     235        }
     236    }
     237
     238    if (buf.pointer)
     239        free(buf.pointer);
     240
     241    if (err == B_OK)
     242        TRACE("ok :)\n");
     243    else
     244        TRACE("argh. error!\n");
     245
     246    return err;
     247}
     248
     249
     250static status_t
     251acpi_battery_read(void* _cookie, off_t position, void *buf, size_t* num_bytes)
     252{
     253    acpi_battery_device_info* device = (acpi_battery_device_info*)_cookie;
     254
     255    if (*num_bytes < 1)
     256        return B_IO_ERROR;
     257
     258    if (device == NULL) {
     259        TRACE("are you kidding me man? cookie is NULL\n");
     260        return B_ERROR;
     261    }
     262
     263    if (position == 0) {
     264        size_t ret;
     265        size_t max_len = *num_bytes;
     266        char *str = (char *)buf;
     267
     268        TRACE("reading battery state via ioctl()\n");
     269
     270        acpi_battery_control(device, drvOpGetBatteryPresent, NULL, 0);
     271        acpi_battery_control(device, drvOpGetBatteryInfo, NULL, 0);
     272        acpi_battery_control(device, drvOpGetBatteryState, NULL, 0);
     273
     274        ret = snprintf(str, max_len, "Present: %s\n",
     275                       acpi_battery_present(device) ? "yes" : "no");
     276
     277        max_len -= ret;
     278        str += ret;
     279
     280        if (!acpi_battery_present(device))
     281            goto end;
     282
     283        ret = snprintf(str, max_len, "Capacity state: %s\n",
     284                       (device->battery->state & 0x04) ? "critical" : "ok");
     285
     286        max_len -= ret;
     287        str += ret;
     288
     289        if ((device->battery->state & 0x01) && (device->battery->state & 0x02))
     290            ret = snprintf(str, max_len,
     291                           "Charging state: charging/discharging\n");
     292        else if (device->battery->state & 0x01)
     293            ret = snprintf(str, max_len, "Charging state: discharging\n");
     294        else if (device->battery->state & 0x02)
     295            ret = snprintf(str, max_len, "Charging state: charging\n");
     296        else
     297            ret = snprintf(str, max_len, "Charging state: charged\n");
     298
     299        max_len -= ret;
     300        str += ret;
     301
     302        if (device->battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN)
     303            ret = snprintf(str, max_len, "Present rate: unknown\n");
     304        else
     305            ret = snprintf(str, max_len, "Present rate: %d %s\n",
     306                           device->battery->current_now,
     307                           acpi_battery_units(device->battery));
     308
     309        max_len -= ret;
     310        str += ret;
     311
     312        if (device->battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
     313            ret = snprintf(str, max_len, "Remaining capacity: unknown\n");
     314        else
     315            ret = snprintf(str, max_len, "Remaining capacity: %d %sh\n",
     316                           device->battery->capacity_now,
     317                           acpi_battery_units(device->battery));
     318
     319        max_len -= ret;
     320        str += ret;
     321
     322        if (device->battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
     323            ret = snprintf(str, max_len, "Present voltage: unknown\n");
     324        else
     325            ret = snprintf(str, max_len, "Present voltage: %d mV\n",
     326                           device->battery->voltage_now);
     327
     328        max_len -= ret;
     329        str += ret;
     330
     331        if (device->battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
     332            ret = snprintf(str, max_len, "Design capacity: unknown\n");
     333        else
     334            ret = snprintf(str, max_len, "Design capacity: %d %sh\n",
     335                           device->battery->design_capacity,
     336                           acpi_battery_units(device->battery));
     337
     338        max_len -= ret;
     339        str += ret;
     340
     341        if (device->battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
     342            ret = snprintf(str, max_len, "Last full capacity: unknown\n");
     343        else
     344            ret = snprintf(str, max_len, "Last full capacity: %d %sh\n",
     345                           device->battery->full_charge_capacity,
     346                           acpi_battery_units(device->battery));
     347
     348        max_len -= ret;
     349        str += ret;
     350
     351        ret = snprintf(str, max_len, "Battery technology: %srechargeable\n",
     352                       (!device->battery->technology)?"non-":"");
     353
     354        max_len -= ret;
     355        str += ret;
     356
     357        if (device->battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
     358            ret = snprintf(str, max_len, "Design voltage: unknown\n");
     359        else
     360            ret = snprintf(str, max_len, "Design voltage: %d mV\n",
     361                           device->battery->design_voltage);
     362
     363        max_len -= ret;
     364        str += ret;
     365
     366        ret = snprintf(str, max_len, "Design capacity warning: %d %sh\n",
     367                       device->battery->design_capacity_warning,
     368                       acpi_battery_units(device->battery));
     369
     370        max_len -= ret;
     371        str += ret;
     372
     373        ret = snprintf(str, max_len, "Design capacity low: %d %sh\n",
     374                       device->battery->design_capacity_low,
     375                       acpi_battery_units(device->battery));
     376
     377        max_len -= ret;
     378        str += ret;
     379
     380        ret = snprintf(str, max_len, "Capacity granularity 1: %d %sh\n",
     381                 device->battery->capacity_granularity_1,
     382                 acpi_battery_units(device->battery));
     383
     384        max_len -= ret;
     385        str += ret;
     386
     387        ret = snprintf(str, max_len, "Capacity granularity 2: %d %sh\n",
     388                       device->battery->capacity_granularity_2,
     389                       acpi_battery_units(device->battery));
     390
     391        max_len -= ret;
     392        str += ret;
     393
     394        ret = snprintf(str, max_len, "Model number: %s\n",
     395                       device->battery->model_number);
     396
     397        max_len -= ret;
     398        str += ret;
     399
     400        ret = snprintf(str, max_len, "Serial number: %s\n",
     401                       device->battery->serial_number);
     402
     403        max_len -= ret;
     404        str += ret;
     405
     406        ret = snprintf(str, max_len, "Battery type: %s\n",
     407                       device->battery->type);
     408
     409        max_len -= ret;
     410        str += ret;
     411
     412        ret = snprintf(str, max_len, "OEM info: %s\n",
     413                       device->battery->oem_info);
     414
     415end:
     416        *num_bytes = strlen((char *)buf);
     417
     418    } else {
     419        *num_bytes = 0;
     420    }
     421
     422    return B_OK;
     423}
     424
     425
     426static status_t
     427acpi_battery_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
     428{
     429    return B_ERROR;
     430}
     431
     432
     433static status_t
     434acpi_battery_close (void* cookie)
     435{
     436    return B_OK;
     437}
     438
     439
     440static status_t
     441acpi_battery_free (void* cookie)
     442{
     443    return B_OK;
     444}
     445
     446//    #pragma mark - driver module API
     447
     448static int32
     449acpi_get_type(device_node* dev)
     450{
     451    const char *bus;
     452    if (sDeviceManager->get_attr_string(dev, B_DEVICE_BUS, &bus, false))
     453        return -1;
     454
     455    if (strcmp(bus, "acpi"))
     456        return -1;
     457
     458    uint32 deviceType;
     459    if (sDeviceManager->get_attr_uint32(dev, ACPI_DEVICE_TYPE_ITEM,
     460        &deviceType, false) != B_OK)
     461        return -1;
     462
     463    return deviceType;
     464}
     465
     466static float
     467acpi_battery_support(device_node *dev)
     468{
     469    static char *bat_ids[] = { "PNP0C0A", NULL };
     470
     471    if (acpi_get_type(dev) != ACPI_TYPE_DEVICE)
     472        return 0.0;
     473
     474    const char *name;
     475    if (sDeviceManager->get_attr_string(dev, ACPI_DEVICE_HID_ITEM, &name,
     476        false) != B_OK || strcmp(name, bat_ids[0]))
     477        return 0.0;
     478
     479    TRACE("acpi_battery: got it man!\n");
     480
     481    return 0.6;
     482}
     483
     484
     485static status_t
     486acpi_battery_register_device(device_node *node)
     487{
     488    device_attr attrs[] = {
     489        { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "ACPI Battery" }},
     490        { NULL }
     491    };
     492
     493    return sDeviceManager->register_node(node, ACPI_BATTERY_MODULE_NAME, attrs,
     494                                          NULL, NULL);
     495}
     496
     497
     498static status_t
     499acpi_battery_init_driver(device_node *node, void **cookie)
     500{
     501    TRACE("(C) 2009 - Francesco Piccinno <stack.box@gmail.com>\n");
     502    *cookie = node;
     503    return B_OK;
     504}
     505
     506
     507static void
     508acpi_battery_uninit_driver(void *driverCookie)
     509{
     510}
     511
     512
     513static status_t
     514acpi_battery_register_child_devices(void *_cookie)
     515{
     516    device_node *node = _cookie;
     517    int path_id;
     518    char name[128];
     519
     520    TRACE("acpi_battery_register_child_devices\n");
     521
     522    path_id = sDeviceManager->create_id(ACPI_BATTERY_PATHID_GENERATOR);
     523    if (path_id < 0) {
     524        TRACE("register_child_devices: couldn't create a path_id\n");
     525        return B_ERROR;
     526    }
     527
     528    snprintf(name, sizeof(name), ACPI_BATTERY_BASENAME, path_id);
     529
     530    return sDeviceManager->publish_device(node, name,
     531                                           ACPI_BATTERY_DEVICE_MODULE_NAME);
     532}
     533
     534
     535module_dependency module_dependencies[] = {
     536    { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
     537    {}
     538};
     539
     540
     541driver_module_info acpi_battery_driver_module = {
     542    {
     543        ACPI_BATTERY_MODULE_NAME,
     544        0,
     545        NULL
     546    },
     547
     548    acpi_battery_support,
     549    acpi_battery_register_device,
     550    acpi_battery_init_driver,
     551    acpi_battery_uninit_driver,
     552    acpi_battery_register_child_devices,
     553    NULL,    // rescan
     554    NULL,    // removed
     555};
     556
     557
     558struct device_module_info acpi_battery_device_module = {
     559    {
     560        ACPI_BATTERY_DEVICE_MODULE_NAME,
     561        0,
     562        NULL
     563    },
     564
     565    acpi_battery_init_device,
     566    acpi_battery_uninit_device,
     567    NULL,
     568
     569    acpi_battery_open,
     570    acpi_battery_close,
     571    acpi_battery_free,
     572    acpi_battery_read,
     573    acpi_battery_write,
     574    NULL,
     575    acpi_battery_control,
     576
     577    NULL,
     578    NULL
     579};
     580
     581module_info *modules[] = {
     582    (module_info *)&acpi_battery_driver_module,
     583    (module_info *)&acpi_battery_device_module,
     584    NULL
     585};
  • src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.h

     
     1/*
     2 * Copyright 2009 Francesco Piccinno <stack.box@gmail.com>
     3 *
     4 * Simple acpi_battery implementation for haiku ported from Linux.
     5 *
     6 * Distributed under the terms of the MIT License.
     7 */
     8
     9#ifndef _ACPI_BATTERY_H
     10#define _ACPI_BATTERY_H
     11
     12#include <KernelExport.h>
     13#include <ACPI.h>
     14
     15enum { /* ioctl op-codes */
     16    drvOpGetBatteryState   = B_DEVICE_OP_CODES_END + 1001,
     17    drvOpGetBatteryInfo    = B_DEVICE_OP_CODES_END + 1002,
     18    drvOpGetBatteryPresent = B_DEVICE_OP_CODES_END + 1003,
     19};
     20
     21typedef struct acpi_battery_type acpi_battery_type;
     22
     23/* Status (_STA) */
     24struct acpi_device_status {
     25    unsigned long present:1;
     26    unsigned long enabled:1;
     27    unsigned long show_in_ui:1;
     28    unsigned long functional:1;
     29    unsigned long battery_present:1;
     30    unsigned long reserved:27;
     31};
     32
     33struct acpi_battery_type {
     34    struct acpi_device_status status;
     35    int current_now;
     36    int capacity_now;
     37    int voltage_now;
     38    int design_capacity;
     39    int full_charge_capacity;
     40    int technology;
     41    int design_voltage;
     42    int design_capacity_warning;
     43    int design_capacity_low;
     44    int capacity_granularity_1;
     45    int capacity_granularity_2;
     46    char model_number[32];
     47    char serial_number[32];
     48    char type[32];
     49    char oem_info[32];
     50    int state;
     51    int power_unit;
     52};
     53
     54struct acpi_offsets {
     55    size_t offset;          /* offset inside struct acpi_sbs_battery */
     56    uint8 mode;             /* int or string? */
     57};
     58
     59static struct acpi_offsets state_offsets[] = {
     60    {offsetof(struct acpi_battery_type, state), 0},
     61    {offsetof(struct acpi_battery_type, current_now), 0},
     62    {offsetof(struct acpi_battery_type, capacity_now), 0},
     63    {offsetof(struct acpi_battery_type, voltage_now), 0},
     64};
     65
     66static struct acpi_offsets info_offsets[] = {
     67    {offsetof(struct acpi_battery_type, power_unit), 0},
     68    {offsetof(struct acpi_battery_type, design_capacity), 0},
     69    {offsetof(struct acpi_battery_type, full_charge_capacity), 0},
     70    {offsetof(struct acpi_battery_type, technology), 0},
     71    {offsetof(struct acpi_battery_type, design_voltage), 0},
     72    {offsetof(struct acpi_battery_type, design_capacity_warning), 0},
     73    {offsetof(struct acpi_battery_type, design_capacity_low), 0},
     74    {offsetof(struct acpi_battery_type, capacity_granularity_1), 0},
     75    {offsetof(struct acpi_battery_type, capacity_granularity_2), 0},
     76    {offsetof(struct acpi_battery_type, model_number), 1},
     77    {offsetof(struct acpi_battery_type, serial_number), 1},
     78    {offsetof(struct acpi_battery_type, type), 1},
     79    {offsetof(struct acpi_battery_type, oem_info), 1},
     80};
     81
     82#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
     83#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
     84
     85#endif /* _ACPI_BATTERY_H */
  • src/add-ons/kernel/drivers/power/Jamfile

     
    44SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_embedded_controller ;
    55SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_lid ;
    66SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ;
     7SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_battery ;
    78SubInclude HAIKU_TOP src add-ons kernel drivers power enhanced_speedstep ;