/*************************************************************************** * * 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; }