hal/hald/linux2/addons Makefile.am, NONE, 1.1 addon-hid-ups.c, NONE,
1.1
David Zeuthen
david at freedesktop.org
Thu Feb 3 21:24:27 PST 2005
Update of /cvs/hal/hal/hald/linux2/addons
In directory gabe:/tmp/cvs-serv10538/hald/linux2/addons
Added Files:
Makefile.am addon-hid-ups.c
Log Message:
2005-02-04 David Zeuthen <david at fubar.dk>
* doc/spec/hal-spec.xml.in: Added docs for battery.remaining_time
* hald/linux2/classdev.c (input_get_prober): New function
(usbclass_add): New function
(usbclass_get_prober): New function
(usbclass_compute_udi): New function
(add_classdev_probing_helper_done): Check if post_probing is NULL
(hotplug_event_begin_add_classdev): Use function to get prober since
e.g. class usb covers multiple devices, e.g. hiddev, printers etc.
* hald/linux2/probing/probe-hiddev.c: New file; probe for application
pages a HIDDEV supports and add to hiddev.application_pages strlist
* hald/linux2/addons/addon-hid-ups.c: Detect UPS's on USB HID
interfaces and create plus maintain battery.* properties.
* hald/linux2/addons/Makefile.am: New file
* hald/linux2/Makefile.am (SUBDIRS): Add addons directory
* configure.in: Add hald2/linux2/addons/Makefile.am to AC_OUTPUT
--- NEW FILE: Makefile.am ---
INCLUDES = \
-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
-I$(top_srcdir) \
@PACKAGE_CFLAGS@
libexec_PROGRAMS = hald-addon-hid-ups
hald_addon_hid_ups_SOURCES = addon-hid-ups.c
hald_addon_hid_ups_LDADD = $(top_builddir)/libhal/libhal.la
--- NEW FILE: addon-hid-ups.c ---
/***************************************************************************
* CVSID: $Id: addon-hid-ups.c,v 1.1 2005/02/04 05:24:25 david Exp $
*
* addon-hid-ups.c : Detect UPS'es using the USB HID interface and
* add and maintain battery.* properties
*
* Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
*
* Based on hid-ups.c: Copyright (c) 2001 Vojtech Pavlik
* <vojtech at ucw.cz>, Copyright (c) 2001 Paul
* Stewart <hiddev at wetlogic.net>, Tweaked by Kern
* Sibbald <kern at sibbald.com> to learn about USB
* UPSes. hid-ups.c is GPLv2 and available from
* examples directory of version 3.10.16 of the
* acpupsd project; see http://www.apcupsd.com.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/hiddev.h>
#include "libhal/libhal.h"
#define UPS_USAGE 0x840000
#define UPS_SERIAL 0x8400fe
#define BAT_CHEMISTRY 0x850089
#define UPS_CAPACITY_MODE 0x85002c
#define UPS_SHUTDOWN_IMMINENT 0x840069
#define UPS_BATTERY_VOLTAGE 0x840030
#define UPS_BELOW_RCL 0x840042
#define UPS_CHARING 0x840044
#define UPS_DISCHARGING 0x850045
#define UPS_REMAINING_CAPACITY 0x850066
#define UPS_RUNTIME_TO_EMPTY 0x850068
#define UPS_AC_PRESENT 0x8500d0
#define STATE_NORMAL 0 /* unit powered */
#define STATE_DEBOUNCE 1 /* power failure */
#define STATE_BATTERY 2 /* power failure confirmed */
static dbus_bool_t
is_ups (int fd)
{
unsigned int i;
dbus_bool_t ret;
struct hiddev_devinfo device_info;
ret = FALSE;
if (ioctl (fd, HIDIOCGDEVINFO, &device_info) < 0)
goto out;
for (i = 0; i < device_info.num_applications; i++) {
if ((ioctl(fd, HIDIOCAPPLICATION, i) & 0xff0000) == UPS_USAGE) {
ret = TRUE;
goto out;
}
}
out:
return ret;
}
static char *
ups_get_string (int fd, int sindex)
{
static struct hiddev_string_descriptor sdesc;
if (sindex == 0) {
return "";
}
sdesc.index = sindex;
if (ioctl (fd, HIDIOCGSTRING, &sdesc) < 0) {
return "";
}
fprintf (stderr, "foo: '%s'\n", sdesc.value);
return sdesc.value;
}
static dbus_bool_t
ups_get_static (LibHalContext *ctx, const char *udi, int fd)
{
int ret;
struct hiddev_report_info rinfo;
struct hiddev_field_info finfo;
struct hiddev_usage_ref uref;
int rtype;
unsigned int i, j;
DBusError error;
/* set to failure */
ret = FALSE;
/* first check that we are an UPS */
if (!is_ups (fd))
goto out;
for (rtype = HID_REPORT_TYPE_MIN; rtype <= HID_REPORT_TYPE_MAX; rtype++) {
rinfo.report_type = rtype;
rinfo.report_id = HID_REPORT_ID_FIRST;
while (ioctl (fd, HIDIOCGREPORTINFO, &rinfo) >= 0) {
for (i = 0; i < rinfo.num_fields; i++) {
memset (&finfo, 0, sizeof (finfo));
finfo.report_type = rinfo.report_type;
finfo.report_id = rinfo.report_id;
finfo.field_index = i;
ioctl (fd, HIDIOCGFIELDINFO, &finfo);
memset (&uref, 0, sizeof (uref));
for (j = 0; j < finfo.maxusage; j++) {
uref.report_type = finfo.report_type;
uref.report_id = finfo.report_id;
uref.field_index = i;
uref.usage_index = j;
ioctl (fd, HIDIOCGUCODE, &uref);
ioctl (fd, HIDIOCGUSAGE, &uref);
dbus_error_init (&error);
switch (uref.usage_code) {
case 0x850066: /* RemainingCapacity */
libhal_device_set_property_int (
ctx, udi, "battery.charge_level.current", uref.value, &error);
libhal_device_set_property_string (
ctx, udi, "battery.charge_level.unit", "percent", &error);
break;
case 0x850068: /* RunTimeToEmpty */
libhal_device_set_property_int (
ctx, udi, "battery.remaining_time", uref.value, &error);
break;
case 0x850044: /* Charging */
libhal_device_set_property_bool (
ctx, udi, "battery.is_charging", uref.value != 0, &error);
break;
case 0x850045: /* Discharging */
libhal_device_set_property_bool (
ctx, udi, "battery.is_discharging", uref.value != 0, &error);
break;
case 0x8500d1: /* BatteryPresent */
libhal_device_set_property_bool (
ctx, udi, "battery.present", uref.value != 0, &error);
break;
case 0x850088: /* iDeviceName */
libhal_device_set_property_string (
ctx, udi, "foo",
ups_get_string (fd, uref.value), &error);
break;
case 0x850089: /* iDeviceChemistry */
libhal_device_set_property_string (
ctx, udi, "battery.technology",
ups_get_string (fd, uref.value), &error);
break;
case 0x85008b: /* Rechargeable */
libhal_device_set_property_bool (
ctx, udi, "battery.is_rechargeable", uref.value != 0, &error);
break;
case 0x85008f: /* iOEMInformation */
libhal_device_set_property_string (
ctx, udi, "battery.vendor",
ups_get_string (fd, uref.value), &error);
break;
case 0x8400fe: /* iProduct */
libhal_device_set_property_string (
ctx, udi, "battery.model",
ups_get_string (fd, uref.value), &error);
break;
case 0x8400ff: /* iSerialNumber */
libhal_device_set_property_string (
ctx, udi, "battery.serial",
ups_get_string (fd, uref.value), &error);
break;
case 0x850083: /* DesignCapacity */
libhal_device_set_property_int (
ctx, udi, "battery.charge_level.maximum", uref.value, &error);
break;
default:
break;
}
}
}
rinfo.report_id |= HID_REPORT_ID_NEXT;
}
}
libhal_device_set_property_string (ctx, udi, "battery.type", "ups", &error);
libhal_device_add_capability (ctx, udi, "battery", &error);
ret = TRUE;
out:
return ret;
}
int
main (int argc, char *argv[])
{
int fd;
char *udi;
char *device_file;
LibHalContext *ctx = NULL;
DBusError error;
DBusConnection *conn;
unsigned int i;
fd_set fdset;
struct hiddev_event ev[64];
int rd;
udi = getenv ("UDI");
if (udi == NULL)
goto out;
dbus_error_init (&error);
if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
goto out;
if ((ctx = libhal_ctx_new ()) == NULL)
goto out;
if (!libhal_ctx_set_dbus_connection (ctx, conn))
goto out;
if (!libhal_ctx_init (ctx, &error))
goto out;
device_file = getenv ("HAL_PROP_HIDDEV_DEVICE");
if (device_file == NULL)
goto out;
fd = open (device_file, O_RDONLY);
if (fd < 0)
goto out;
if (!ups_get_static (ctx, udi, fd))
goto out;
FD_ZERO(&fdset);
while (1) {
FD_SET(fd, &fdset);
rd = select(fd+1, &fdset, NULL, NULL, NULL);
if (rd > 0) {
rd = read(fd, ev, sizeof(ev));
if (rd < (int) sizeof(ev[0])) {
close(fd);
goto out;
}
for (i = 0; i < rd / sizeof(ev[0]); i++) {
DBusError error;
dbus_error_init (&error);
switch (ev[i].hid) {
case 0x850066: /* RemainingCapacity */
libhal_device_set_property_int (
ctx, udi, "battery.charge_level.current", ev[i].value, &error);
break;
case 0x850068: /* RunTimeToEmpty */
libhal_device_set_property_int (
ctx, udi, "battery.remaining_time", ev[i].value, &error);
break;
case 0x850044: /* Charging */
libhal_device_set_property_bool (
ctx, udi, "battery.is_charging", ev[i].value != 0, &error);
break;
case 0x850045: /* Discharging */
libhal_device_set_property_bool (
ctx, udi, "battery.is_discharging", ev[i].value != 0, &error);
break;
default:
break;
}
}
}
}
out:
return 0;
}
More information about the hal-commit
mailing list