From 49680952052582ff3dd11bc413b6287b65063b2a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 13 Nov 2008 03:05:38 +0100 Subject: Initial GIT version: hal-applesmc-0.14 Signed-off-by: Henrik Rydberg --- hald-addon-generic-light-sensor.c | 212 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 hald-addon-generic-light-sensor.c (limited to 'hald-addon-generic-light-sensor.c') diff --git a/hald-addon-generic-light-sensor.c b/hald-addon-generic-light-sensor.c new file mode 100644 index 0000000..e724290 --- /dev/null +++ b/hald-addon-generic-light-sensor.c @@ -0,0 +1,212 @@ +/*************************************************************************** + * + * addon-generic-light.c: + * Copyright (C) 2008 Henrik Rydberg + * + * Based on addon-generic-backlight.c: + * Copyright (C) 2008 Danny Kukawka + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "glib-abi.h" +#include "dbus-abi.h" +#include "hal-abi.h" + +#define HAL_PROPERTY "org.freedesktop.Hal.Device.LightSensor" +#define MAX_SENSORS 16 + +static const char prop_name[] = HAL_PROPERTY; +static const char prop_invalid[] = HAL_PROPERTY ".Invalid"; +static const char prop_get[] = "GetBrightness"; + +static struct GMainLoop *main_loop; +static struct LibHalContext *halctx; +static struct DBusConnection *conn; + +static char sysfs_path[512]; +static int sensors, levels; + +/** + * Get keyboard backlight level + * + * Tries to read from the specified sysfs device, and if successful, + * updates the internal keyboard backlight state. Warns if the device + * cannot be opened or be read from. Always returns the last succesful + * read. + */ +static void get_light_sensor(int *level, int nlevel) +{ + static const char delim[] = " ,()"; + static int sensor[MAX_SENSORS]; + int fd, i; + char buf[64], *p; + + fd = open(sysfs_path, O_RDONLY); + if (fd < 0) { + HAL_WARNING(("Could not open '%s'", sysfs_path)); + goto err; + } + + memset(buf, 0, sizeof(buf)); + if (read(fd, buf, sizeof(buf)) < 0) { + HAL_WARNING(("Could not read from '%s'", sysfs_path)); + goto close; + } + + p = strtok(buf, delim); + for (i = 0; p && i < nlevel; i++) { + sensor[i] = atoi(p); + p = strtok(NULL, delim); + HAL_DEBUG(("light_sensor[%d]=%d", i, sensor[i])); + } + +close: + close(fd); +err: + for (i = 0; i < nlevel; i++) + level[i] = sensor[i] < levels ? sensor[i]: levels - 1; +} + +/* DBus set keyboard backlight level */ +static struct DBusMessage *dbus_get_light_sensor(struct DBusMessage *msg) +{ + struct DBusError err; + struct DBusMessage *reply; + int level[MAX_SENSORS]; + + dbus_error_init(&err); + if (!dbus_message_get_args(msg, &err, DBUS_TYPE_INVALID)) + return dbus_message_new_error(msg, prop_invalid, + "Invalid message"); + + get_light_sensor(level, sensors); + + reply = dbus_message_new_method_return(msg); + if (reply) { + int *pb = level; + dbus_message_append_args(reply, DBUS_TYPE_ARRAY, + DBUS_TYPE_INT32, &pb, sensors, DBUS_TYPE_INVALID); + } + + return reply; +} + +/* DBus filter function */ +static DBusHandlerResult filter_function(struct DBusConnection *connection, + struct DBusMessage *message, + void *userdata) +{ + struct DBusMessage *reply = NULL; + + if (dbus_message_is_method_call(message, prop_name, prop_get)) + reply = dbus_get_light_sensor(message); + + if (reply) { + dbus_connection_send(connection, reply, NULL); + dbus_message_unref(reply); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +int main(int argc, char *argv[]) +{ + struct DBusError err; + struct stat fs; + + char *udi = getenv("UDI"); + char *path = getenv("HAL_PROP_LINUX_SYSFS_PATH"); + char *sensor_str = getenv("HAL_PROP_LIGHT_SENSOR_NUM_SENSORS"); + char *level_str = getenv("HAL_PROP_LIGHT_SENSOR_NUM_LEVELS"); + + setup_logger(); + + if (udi == NULL) { + HAL_ERROR(("No device specified")); + return -2; + } + if (path == NULL) { + HAL_ERROR(("No sysfs path specified")); + return -2; + } + if (sensor_str == NULL) { + HAL_ERROR(("No light_sensor.num_sensors defined")); + return -2; + } + if (level_str == NULL) { + HAL_ERROR(("No light_sensor.num_levels defined")); + return -2; + } + + sensors = atoi(sensor_str); + levels = atoi(level_str); + snprintf(sysfs_path, sizeof(sysfs_path), "%s", path); + + HAL_DEBUG(("udi='%s', path='%s', sensors='%d', levels='%d'", + udi, path, sensors, levels)); + + if (sensors >= MAX_SENSORS) { + HAL_ERROR(("light_sensor.num_sensors is too large")); + return -2; + } + if (stat(sysfs_path, &fs)) { + HAL_ERROR(("The sysfs property path does not exist")); + return -2; + } + + dbus_error_init(&err); + halctx = libhal_ctx_init_direct(&err); + + if (halctx == NULL) { + HAL_ERROR(("Cannot connect to hald")); + return -3; + } + + conn = libhal_ctx_get_dbus_connection(halctx); + dbus_connection_setup_with_g_main(conn, NULL); + + dbus_connection_add_filter(conn, filter_function, NULL, NULL); + + if (!libhal_device_claim_interface(halctx, udi, prop_name, + " \n" + " \n" + " \n", + &err)) { + HAL_ERROR(("Cannot claim interface '" HAL_PROPERTY "'")); + return -4; + } + + dbus_error_init(&err); + if (!libhal_device_addon_is_ready(halctx, udi, &err)) + return -4; + + main_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(main_loop); + + return 0; +} + -- cgit v1.2.3