hal/hald/linux2/addons Makefile.am, 1.3, 1.4 addon-usb-csr.c, NONE,
1.1
David Zeuthen
david at freedesktop.org
Wed Mar 23 17:15:33 PST 2005
Update of /cvs/hal/hal/hald/linux2/addons
In directory gabe:/tmp/cvs-serv26125/hald/linux2/addons
Modified Files:
Makefile.am
Added Files:
addon-usb-csr.c
Log Message:
2005-03-23 David Zeuthen <davidz at redhat.com>
Patch from Sergey Udaltsov <sergey.udaltsov at gmail.com>, slightly
tweaked to be in line with the spec
* hald/linux2/addons/addon-usb-csr.c: New file
* fdi/information/10freedesktop/10-wireless-mice.fdi: New file
* doc/spec/hal-spec.xml.in: Add keyboard_mouse as allowed value for
battery.type
Index: Makefile.am
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/addons/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Makefile.am 10 Feb 2005 17:03:57 -0000 1.3
+++ Makefile.am 24 Mar 2005 01:15:31 -0000 1.4
@@ -8,7 +8,7 @@
-I$(top_srcdir) \
@PACKAGE_CFLAGS@
-libexec_PROGRAMS = hald-addon-hid-ups hald-addon-acpi hald-addon-storage
+libexec_PROGRAMS = hald-addon-hid-ups hald-addon-acpi hald-addon-storage hald-addon-usb-csr
hald_addon_hid_ups_SOURCES = addon-hid-ups.c
hald_addon_hid_ups_LDADD = $(top_builddir)/libhal/libhal.la
@@ -19,9 +19,5 @@
hald_addon_storage_SOURCES = addon-storage.c
hald_addon_storage_LDADD = $(top_builddir)/libhal/libhal.la
-
-
-
-
-
-
+hald_addon_usb_csr_SOURCES = addon-usb-csr.c
+hald_addon_usb_csr_LDADD = $(top_builddir)/libhal/libhal.la -lusb @PACKAGE_LIBS@
--- NEW FILE: addon-usb-csr.c ---
/***************************************************************************
* CVSID: $Id: addon-usb-csr.c,v 1.1 2005/03/24 01:15:31 david Exp $
*
* hal_addon_usb_csr.c : daemon handling CSR-based wireless mice
*
* Copyright (C) 2004 Sergey V. Udaltsov <svu at gnome.org>
*
* Licensed under the Academic Free License version 2.0
*
* 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
*
**************************************************************************/
#include <config.h>
#include <stdio.h>
#include <usb.h>
#include <glib/gmain.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "libhal/libhal.h"
#include "../probing/shared.h"
#define CMD_IFACE_PROPERTY "battery.command_interface"
#define BUS_NO_PROPERTY "usb_device.bus_number"
/* linux!!! */
#define PORT_NO_PROPERTY "usb_device.linux.device_number"
#define CSR_IS_DUAL_PROPERTY "battery.csr.is_dual"
#define CURRENT_CHARGE_PROPERTY "battery.charge_level.current"
typedef struct _PropertyCacheItem
{
gboolean bus_no_present;
int bus_no;
gboolean port_no_present;
int port_no;
gboolean csr_is_dual_present;
gboolean csr_is_dual;
gboolean current_charge_present;
int current_charge;
} PropertyCacheItem;
static PropertyCacheItem * dev_props = NULL;
static LibHalContext * hal_context = NULL;
static GMainLoop* main_loop;
static const char* the_device_udi;
#define TIMEOUT 0x1000
static void update_properties (void)
{
#if 0
<merge key="info.category" type="string">battery</merge>
<merge key="info.capabilities" type="string">battery</merge>
<merge key="battery.charge_level.maximum.specified" type="int">7</merge>
<merge key="battery.is_rechargeable" type="bool">false</merge>
#endif
DBusError err;
dbus_error_init (&err);
libhal_device_set_property_bool (hal_context,
the_device_udi,
"battery.present", TRUE,
&err);
if (!libhal_device_property_exists (hal_context,
the_device_udi,
"battery.is_rechargeable",
&err)) {
libhal_device_set_property_bool (hal_context,
the_device_udi,
"battery.is_rechargeable", FALSE,
&err);
}
libhal_device_set_property_int (hal_context,
the_device_udi,
"battery.charge_level.design", 7,
&err);
libhal_device_set_property_int (hal_context,
the_device_udi,
"battery.charge_level.last_full", 7,
&err);
libhal_device_set_property_string (hal_context,
the_device_udi,
"info.category", "battery",
&err);
libhal_device_set_property_string (hal_context,
the_device_udi,
"battery.command_interface", "csr",
&err);
libhal_device_add_capability (hal_context,
the_device_udi,
"battery",
&err);
}
static PropertyCacheItem*
property_cache_item_get (const char * hal_device_udi)
{
PropertyCacheItem * pci = g_new0 (PropertyCacheItem,1);
DBusError err;
dbus_error_init (&err);
pci->bus_no_present = libhal_device_property_exists (hal_context,
hal_device_udi,
BUS_NO_PROPERTY,
&err);
if (dbus_error_is_set (&err))
{
fprintf (stderr, "Error: [%s]/[%s]\n", err.name, err.message);
}
if (pci->bus_no_present)
pci->bus_no = libhal_device_get_property_int (hal_context,
hal_device_udi,
BUS_NO_PROPERTY,
&err);
pci->port_no_present = libhal_device_property_exists (hal_context,
hal_device_udi,
PORT_NO_PROPERTY,
&err);
if (pci->port_no_present)
pci->port_no = libhal_device_get_property_int (hal_context,
hal_device_udi,
PORT_NO_PROPERTY,
&err);
pci->csr_is_dual_present = libhal_device_property_exists (hal_context,
hal_device_udi,
CSR_IS_DUAL_PROPERTY,
&err);
if (pci->csr_is_dual_present)
pci->csr_is_dual = libhal_device_get_property_bool (hal_context,
hal_device_udi,
CSR_IS_DUAL_PROPERTY,
&err);
pci->current_charge_present = libhal_device_property_exists (hal_context,
hal_device_udi,
CURRENT_CHARGE_PROPERTY,
&err);
if (pci->current_charge_present)
pci->current_charge = libhal_device_get_property_int (hal_context,
hal_device_udi,
CURRENT_CHARGE_PROPERTY,
&err);
return pci;
}
static void
property_cache_item_free (PropertyCacheItem* pci)
{
if (pci == NULL)
return;
g_free (pci);
}
static struct usb_device*
find_device (const char * hal_device_udi, PropertyCacheItem * pci);
/* Thanks to lmctl code. I'd LOVE, REALLY LOVE to see some docs though... */
static void
check_battery (const char * hal_device_udi, PropertyCacheItem * pci)
{
struct usb_device *current_usb_device;
usb_dev_handle * handle;
unsigned char buf[80];
DBusError err;
/* Internal CSR registered, I presume - for some reason not addressed directly */
#define P6 (buf[0])
#define P0 (buf[1])
#define P4 (buf[2])
#define P5 (buf[3])
#define P8 (buf[4])
#define P9 (buf[5])
#define PB0 (buf[6])
#define PB1 (buf[7])
unsigned int addr;
int is_dual = 0;
if (pci == NULL)
return;
dbg ("CSR device: [%s]\n", hal_device_udi);
is_dual = pci->csr_is_dual;
/* Which of subdevices to address */
dbg ("Is dual: %d\n", is_dual);
addr = is_dual? 1<<8 : 0;
current_usb_device = find_device (hal_device_udi, pci);
if (current_usb_device == NULL)
{
fprintf (stderr, "Device %s not found\n", hal_device_udi);
return;
}
handle = usb_open (current_usb_device);
if (handle == NULL)
{
perror ("Could not open usb device\n");
return;
}
if (!usb_control_msg (handle, 0xc0, 0x09, 0x03|addr, 0x00|addr,
buf, 8, TIMEOUT) != 8)
{
if ((P0 == 0x3b) && (P4 == 0))
{
dbg ("Receiver busy, trying again later\n");
} else
{
int current_charge = P5 & 0x07;
dbg ("Charge level: %d->%d\n",
pci->current_charge, current_charge);
if (current_charge != pci->current_charge)
{
pci->current_charge = current_charge;
dbus_error_init (&err);
libhal_device_set_property_int (hal_context,
hal_device_udi,
CURRENT_CHARGE_PROPERTY,
current_charge,
&err);
}
}
} else
{
perror ("Writing to USB device");
}
usb_close (handle);
}
/* TODO: Is it linux-specific way to find the device? */
static struct usb_device*
find_device (const char * hal_device_udi, PropertyCacheItem * pci)
{
struct usb_bus* current_usb_bus;
char LUdirname[5];
char LUfname[5];
if (!(pci->bus_no_present && pci->port_no_present))
{
/* no sysfs path */
fprintf (stderr, "No hal bus number and/or port number\n");
return NULL;
}
snprintf (LUdirname, sizeof (LUdirname), "%03d", pci->bus_no);
snprintf (LUfname, sizeof (LUfname), "%03d",pci->port_no);
dbg ("Looking for: [%s][%s]\n", LUdirname, LUfname);
for (current_usb_bus = usb_busses;
current_usb_bus != NULL;
current_usb_bus = current_usb_bus->next)
{
struct usb_device *current_usb_device;
/* dbg ("Checking bus: [%s]\n", current_usb_bus->dirname); */
if (g_strcasecmp (LUdirname, current_usb_bus->dirname))
continue;
for (current_usb_device = current_usb_bus->devices;
current_usb_device != NULL;
current_usb_device = current_usb_device->next)
{
/* dbg ("Checking port: [%s]\n", current_usb_device->filename); */
if (g_strcasecmp (LUfname, current_usb_device->filename))
continue;
dbg ("Matched device: [%s][%s][%04X:%04X]\n",
current_usb_bus->dirname,
current_usb_device->filename,
current_usb_device->descriptor.idVendor,
current_usb_device->descriptor.idProduct);
return current_usb_device;
}
}
return NULL;
}
static gboolean
check_all_batteries (gpointer data)
{
dbg ("** Check batteries\n");
/* TODO: make it configurable (not to rescan every time) */
usb_find_busses ();
usb_find_devices ();
check_battery (the_device_udi, dev_props);
return TRUE;
}
static gboolean
is_the_device (const char *hal_device_udi)
{
return !g_ascii_strcasecmp (the_device_udi, hal_device_udi);
}
static void
device_removed (LibHalContext *ctx, const char *hal_device_udi)
{
/* this device is removed */
if (is_the_device (hal_device_udi))
{
dbg ("** The device %s removed, exit\n", the_device_udi);
g_main_loop_quit (main_loop);
}
}
static void
property_modified (LibHalContext *ctx,
const char *hal_device_udi,
const char *key,
dbus_bool_t is_removed,
dbus_bool_t is_added)
{
/* "Key" property modified */
if (!g_ascii_strcasecmp (key, CMD_IFACE_PROPERTY))
{
if (is_removed)
{
dbg ("** Main Property %s removed: %s\n", key, hal_device_udi);
/* probably we'll have to exit if this is our device */
device_removed (ctx, hal_device_udi);
}
} else
/* "Secondary" property modified */
if (is_the_device (hal_device_udi))
{
if (!(g_ascii_strcasecmp (key, BUS_NO_PROPERTY) &&
g_ascii_strcasecmp (key, PORT_NO_PROPERTY) &&
g_ascii_strcasecmp (key, CSR_IS_DUAL_PROPERTY)))
{
dbg ("** Property %s added/changed: %s\n",
key, hal_device_udi);
property_cache_item_free (dev_props);
dev_props = property_cache_item_get (hal_device_udi);
}
}
}
static void
initial_fillup (void)
{
dbg ("** Initial fillup\n");
dev_props = property_cache_item_get (the_device_udi);
dbg ("** Initial fillup done\n");
}
int
main (int argc, char *argv[])
{
/* TODO: make it configurable*/
long check_interval = 10L;
DBusConnection *conn;
DBusError err;
if ((getenv ("HALD_VERBOSE")) != NULL)
is_verbose = TRUE;
the_device_udi = getenv ("UDI");
dbg ("device:[%s]\n", the_device_udi);
if (the_device_udi == NULL)
{
fprintf (stderr, "No device specified\n");
return -2;
}
dbus_error_init (&err);
if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err)) == NULL)
{
fprintf (stderr, "Could not obtain dbus connection\n");
return -3;
}
dbg ("DBUS connection: %p\n", conn);
hal_context = libhal_ctx_new ();
if (!libhal_ctx_set_dbus_connection (hal_context, conn))
{
fprintf (stderr, "Could not bind to DBUS\n");
return -4;
}
dbg ("New context: %p\n", hal_context);
libhal_ctx_init (hal_context, &err);
libhal_ctx_set_device_removed (hal_context, device_removed);
update_properties ();
libhal_ctx_set_device_property_modified (hal_context, property_modified);
initial_fillup ();
usb_init ();
dbg ("** Addon started\n");
main_loop = g_main_loop_new (NULL, FALSE);
g_timeout_add (1000L * check_interval, check_all_batteries, NULL);
check_all_batteries (NULL);
g_main_loop_run (main_loop);
libhal_ctx_shutdown (hal_context, &err);
dbg ("** Addon exits normally\n");
return 0;
}
More information about the hal-commit
mailing list