18a94683196406b83b14218d1beef66067f126a16keunyoung/* Copyright (C) 2011 The Android Open Source Project
28a94683196406b83b14218d1beef66067f126a16keunyoung *
38a94683196406b83b14218d1beef66067f126a16keunyoung * Original code licensed under the Apache License, Version 2.0 (the "License");
48a94683196406b83b14218d1beef66067f126a16keunyoung * you may not use this software except in compliance with the License.
58a94683196406b83b14218d1beef66067f126a16keunyoung * You may obtain a copy of the License at
68a94683196406b83b14218d1beef66067f126a16keunyoung *
78a94683196406b83b14218d1beef66067f126a16keunyoung *   http://www.apache.org/licenses/LICENSE-2.0
88a94683196406b83b14218d1beef66067f126a16keunyoung *
98a94683196406b83b14218d1beef66067f126a16keunyoung * Unless required by applicable law or agreed to in writing, software
108a94683196406b83b14218d1beef66067f126a16keunyoung * distributed under the License is distributed on an "AS IS" BASIS,
118a94683196406b83b14218d1beef66067f126a16keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128a94683196406b83b14218d1beef66067f126a16keunyoung * See the License for the specific language governing permissions and
138a94683196406b83b14218d1beef66067f126a16keunyoung * limitations under the License.
148a94683196406b83b14218d1beef66067f126a16keunyoung *
158a94683196406b83b14218d1beef66067f126a16keunyoung * This implements a lights hardware library for the Android emulator.
168a94683196406b83b14218d1beef66067f126a16keunyoung * the following code should be built as a shared library that will be
178a94683196406b83b14218d1beef66067f126a16keunyoung * placed into /system/lib/hw/lights.goldfish.so
188a94683196406b83b14218d1beef66067f126a16keunyoung *
198a94683196406b83b14218d1beef66067f126a16keunyoung * It will be loaded by the code in hardware/libhardware/hardware.c
208a94683196406b83b14218d1beef66067f126a16keunyoung * which is itself called from
218a94683196406b83b14218d1beef66067f126a16keunyoung * ./frameworks/base/services/jni/com_android_server_HardwareService.cpp
228a94683196406b83b14218d1beef66067f126a16keunyoung */
238a94683196406b83b14218d1beef66067f126a16keunyoung
248a94683196406b83b14218d1beef66067f126a16keunyoung#ifdef LOG_TAG
258a94683196406b83b14218d1beef66067f126a16keunyoung#undef LOG_TAG
268a94683196406b83b14218d1beef66067f126a16keunyoung#define LOG_TAG "Lights"
278a94683196406b83b14218d1beef66067f126a16keunyoung#endif
288a94683196406b83b14218d1beef66067f126a16keunyoung
298a94683196406b83b14218d1beef66067f126a16keunyoung/* we connect with the emulator through the "hw-control" qemud service */
308a94683196406b83b14218d1beef66067f126a16keunyoung#define  LIGHTS_SERVICE_NAME "hw-control"
318a94683196406b83b14218d1beef66067f126a16keunyoung
328a94683196406b83b14218d1beef66067f126a16keunyoung#include <cutils/log.h>
338a94683196406b83b14218d1beef66067f126a16keunyoung#include <stdint.h>
348a94683196406b83b14218d1beef66067f126a16keunyoung#include <string.h>
358a94683196406b83b14218d1beef66067f126a16keunyoung#include <unistd.h>
368a94683196406b83b14218d1beef66067f126a16keunyoung#include <errno.h>
378a94683196406b83b14218d1beef66067f126a16keunyoung#include <fcntl.h>
388a94683196406b83b14218d1beef66067f126a16keunyoung#include <pthread.h>
398a94683196406b83b14218d1beef66067f126a16keunyoung#include <sys/ioctl.h>
408a94683196406b83b14218d1beef66067f126a16keunyoung#include <sys/types.h>
418a94683196406b83b14218d1beef66067f126a16keunyoung#include <hardware/lights.h>
428a94683196406b83b14218d1beef66067f126a16keunyoung#include <hardware/qemud.h>
438a94683196406b83b14218d1beef66067f126a16keunyoung
448a94683196406b83b14218d1beef66067f126a16keunyoung/* Set to 1 to enable debug messages to the log */
458a94683196406b83b14218d1beef66067f126a16keunyoung#define DEBUG 0
468a94683196406b83b14218d1beef66067f126a16keunyoung#if DEBUG
478a94683196406b83b14218d1beef66067f126a16keunyoung# define D(...) ALOGD(__VA_ARGS__)
488a94683196406b83b14218d1beef66067f126a16keunyoung#else
498a94683196406b83b14218d1beef66067f126a16keunyoung# define D(...) do{}while(0)
508a94683196406b83b14218d1beef66067f126a16keunyoung#endif
518a94683196406b83b14218d1beef66067f126a16keunyoung
528a94683196406b83b14218d1beef66067f126a16keunyoung#define  E(...)  ALOGE(__VA_ARGS__)
538a94683196406b83b14218d1beef66067f126a16keunyoung
548a94683196406b83b14218d1beef66067f126a16keunyoung/* Get brightness(0~255) from state. */
558a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
568a94683196406b83b14218d1beef66067f126a16keunyoungrgb_to_brightness( struct light_state_t const* state )
578a94683196406b83b14218d1beef66067f126a16keunyoung{
588a94683196406b83b14218d1beef66067f126a16keunyoung    int color = state->color & 0x00ffffff;
598a94683196406b83b14218d1beef66067f126a16keunyoung    return ((77 * ((color >> 16) & 0x00ff))
608a94683196406b83b14218d1beef66067f126a16keunyoung            + (150 * ((color >> 8) & 0x00ff)) + (29 * (color & 0x00ff))) >> 8;
618a94683196406b83b14218d1beef66067f126a16keunyoung}
628a94683196406b83b14218d1beef66067f126a16keunyoung
638a94683196406b83b14218d1beef66067f126a16keunyoung/* set backlight brightness by LIGHTS_SERVICE_NAME service. */
648a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
658a94683196406b83b14218d1beef66067f126a16keunyoungset_light_backlight( struct light_device_t* dev, struct light_state_t const* state )
668a94683196406b83b14218d1beef66067f126a16keunyoung{
678a94683196406b83b14218d1beef66067f126a16keunyoung    /* Get Lights service. */
688a94683196406b83b14218d1beef66067f126a16keunyoung    int  fd = qemud_channel_open( LIGHTS_SERVICE_NAME );
698a94683196406b83b14218d1beef66067f126a16keunyoung
708a94683196406b83b14218d1beef66067f126a16keunyoung    if (fd < 0) {
718a94683196406b83b14218d1beef66067f126a16keunyoung        E( "%s: no qemud connection", __FUNCTION__ );
728a94683196406b83b14218d1beef66067f126a16keunyoung        return -1;
738a94683196406b83b14218d1beef66067f126a16keunyoung    }
748a94683196406b83b14218d1beef66067f126a16keunyoung
758a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: On/Off %d/%d flashMode %d brightnessMode %d"
768a94683196406b83b14218d1beef66067f126a16keunyoung       " RGB = 0x%08x", __func__,
778a94683196406b83b14218d1beef66067f126a16keunyoung       state->flashOnMS,
788a94683196406b83b14218d1beef66067f126a16keunyoung       state->flashOffMS,
798a94683196406b83b14218d1beef66067f126a16keunyoung       state->flashMode,
808a94683196406b83b14218d1beef66067f126a16keunyoung       state->brightnessMode,
818a94683196406b83b14218d1beef66067f126a16keunyoung       state->color );
828a94683196406b83b14218d1beef66067f126a16keunyoung
838a94683196406b83b14218d1beef66067f126a16keunyoung    int brightness = rgb_to_brightness( state );
848a94683196406b83b14218d1beef66067f126a16keunyoung
858a94683196406b83b14218d1beef66067f126a16keunyoung    char buffer[64];
868a94683196406b83b14218d1beef66067f126a16keunyoung    snprintf( buffer, sizeof(buffer), "power:light:brightness:lcd_backlight:%d", brightness );
878a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: lcd_backlight command: %s", __FUNCTION__, buffer );
888a94683196406b83b14218d1beef66067f126a16keunyoung
898a94683196406b83b14218d1beef66067f126a16keunyoung    /* send backlight command to perform the backlight setting. */
908a94683196406b83b14218d1beef66067f126a16keunyoung    if (qemud_channel_send( fd, buffer, -1 ) < 0) {
918a94683196406b83b14218d1beef66067f126a16keunyoung        E( "%s: could not query lcd_backlight: %s", __FUNCTION__, strerror(errno) );
928a94683196406b83b14218d1beef66067f126a16keunyoung        close( fd );
938a94683196406b83b14218d1beef66067f126a16keunyoung        return -1;
948a94683196406b83b14218d1beef66067f126a16keunyoung    }
958a94683196406b83b14218d1beef66067f126a16keunyoung
968a94683196406b83b14218d1beef66067f126a16keunyoung    close( fd );
978a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
988a94683196406b83b14218d1beef66067f126a16keunyoung}
998a94683196406b83b14218d1beef66067f126a16keunyoung
1008a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1018a94683196406b83b14218d1beef66067f126a16keunyoungset_light_buttons( struct light_device_t* dev, struct light_state_t const* state )
1028a94683196406b83b14218d1beef66067f126a16keunyoung{
1038a94683196406b83b14218d1beef66067f126a16keunyoung    /* @Waiting for later implementation. */
1048a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: Not implemented.", __FUNCTION__ );
1058a94683196406b83b14218d1beef66067f126a16keunyoung
1068a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1078a94683196406b83b14218d1beef66067f126a16keunyoung}
1088a94683196406b83b14218d1beef66067f126a16keunyoung
1098a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1108a94683196406b83b14218d1beef66067f126a16keunyoungset_light_battery( struct light_device_t* dev, struct light_state_t const* state )
1118a94683196406b83b14218d1beef66067f126a16keunyoung{
1128a94683196406b83b14218d1beef66067f126a16keunyoung    /* @Waiting for later implementation. */
1138a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: Not implemented.", __FUNCTION__ );
1148a94683196406b83b14218d1beef66067f126a16keunyoung
1158a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1168a94683196406b83b14218d1beef66067f126a16keunyoung}
1178a94683196406b83b14218d1beef66067f126a16keunyoung
1188a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1198a94683196406b83b14218d1beef66067f126a16keunyoungset_light_keyboard( struct light_device_t* dev, struct light_state_t const* state )
1208a94683196406b83b14218d1beef66067f126a16keunyoung{
1218a94683196406b83b14218d1beef66067f126a16keunyoung    /* @Waiting for later implementation. */
1228a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: Not implemented.", __FUNCTION__ );
1238a94683196406b83b14218d1beef66067f126a16keunyoung
1248a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1258a94683196406b83b14218d1beef66067f126a16keunyoung}
1268a94683196406b83b14218d1beef66067f126a16keunyoung
1278a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1288a94683196406b83b14218d1beef66067f126a16keunyoungset_light_notifications( struct light_device_t* dev, struct light_state_t const* state )
1298a94683196406b83b14218d1beef66067f126a16keunyoung{
1308a94683196406b83b14218d1beef66067f126a16keunyoung    /* @Waiting for later implementation. */
1318a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: Not implemented.", __FUNCTION__ );
1328a94683196406b83b14218d1beef66067f126a16keunyoung
1338a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1348a94683196406b83b14218d1beef66067f126a16keunyoung}
1358a94683196406b83b14218d1beef66067f126a16keunyoung
1368a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1378a94683196406b83b14218d1beef66067f126a16keunyoungset_light_attention( struct light_device_t* dev, struct light_state_t const* state )
1388a94683196406b83b14218d1beef66067f126a16keunyoung{
1398a94683196406b83b14218d1beef66067f126a16keunyoung    /* @Waiting for later implementation. */
1408a94683196406b83b14218d1beef66067f126a16keunyoung    D( "%s: Not implemented.", __FUNCTION__ );
1418a94683196406b83b14218d1beef66067f126a16keunyoung
1428a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1438a94683196406b83b14218d1beef66067f126a16keunyoung}
1448a94683196406b83b14218d1beef66067f126a16keunyoung
1458a94683196406b83b14218d1beef66067f126a16keunyoung/** Close the lights device */
1468a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1478a94683196406b83b14218d1beef66067f126a16keunyoungclose_lights( struct light_device_t *dev )
1488a94683196406b83b14218d1beef66067f126a16keunyoung{
1498a94683196406b83b14218d1beef66067f126a16keunyoung    free( dev );
1508a94683196406b83b14218d1beef66067f126a16keunyoung
1518a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1528a94683196406b83b14218d1beef66067f126a16keunyoung}
1538a94683196406b83b14218d1beef66067f126a16keunyoung
1548a94683196406b83b14218d1beef66067f126a16keunyoung/**
1558a94683196406b83b14218d1beef66067f126a16keunyoung * module methods
1568a94683196406b83b14218d1beef66067f126a16keunyoung */
1578a94683196406b83b14218d1beef66067f126a16keunyoung
1588a94683196406b83b14218d1beef66067f126a16keunyoung/** Open a new instance of a lights device using name */
1598a94683196406b83b14218d1beef66067f126a16keunyoungstatic int
1608a94683196406b83b14218d1beef66067f126a16keunyoungopen_lights( const struct hw_module_t* module, char const *name,
1618a94683196406b83b14218d1beef66067f126a16keunyoung        struct hw_device_t **device )
1628a94683196406b83b14218d1beef66067f126a16keunyoung{
1638a94683196406b83b14218d1beef66067f126a16keunyoung    void* set_light;
1648a94683196406b83b14218d1beef66067f126a16keunyoung
1658a94683196406b83b14218d1beef66067f126a16keunyoung    if (0 == strcmp( LIGHT_ID_BACKLIGHT, name )) {
1668a94683196406b83b14218d1beef66067f126a16keunyoung        set_light = set_light_backlight;
1678a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (0 == strcmp( LIGHT_ID_KEYBOARD, name )) {
1688a94683196406b83b14218d1beef66067f126a16keunyoung        set_light = set_light_keyboard;
1698a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (0 == strcmp( LIGHT_ID_BUTTONS, name )) {
1708a94683196406b83b14218d1beef66067f126a16keunyoung        set_light = set_light_buttons;
1718a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (0 == strcmp( LIGHT_ID_BATTERY, name )) {
1728a94683196406b83b14218d1beef66067f126a16keunyoung        set_light = set_light_battery;
1738a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (0 == strcmp( LIGHT_ID_NOTIFICATIONS, name )) {
1748a94683196406b83b14218d1beef66067f126a16keunyoung        set_light = set_light_notifications;
1758a94683196406b83b14218d1beef66067f126a16keunyoung    } else if (0 == strcmp( LIGHT_ID_ATTENTION, name )) {
1768a94683196406b83b14218d1beef66067f126a16keunyoung        set_light = set_light_attention;
1778a94683196406b83b14218d1beef66067f126a16keunyoung    } else {
1788a94683196406b83b14218d1beef66067f126a16keunyoung        D( "%s: %s light isn't supported yet.", __FUNCTION__, name );
1798a94683196406b83b14218d1beef66067f126a16keunyoung        return -EINVAL;
1808a94683196406b83b14218d1beef66067f126a16keunyoung    }
1818a94683196406b83b14218d1beef66067f126a16keunyoung
1828a94683196406b83b14218d1beef66067f126a16keunyoung    struct light_device_t *dev = malloc( sizeof(struct light_device_t) );
1838a94683196406b83b14218d1beef66067f126a16keunyoung    if (dev == NULL) {
1848a94683196406b83b14218d1beef66067f126a16keunyoung        return -EINVAL;
1858a94683196406b83b14218d1beef66067f126a16keunyoung    }
1868a94683196406b83b14218d1beef66067f126a16keunyoung    memset( dev, 0, sizeof(*dev) );
1878a94683196406b83b14218d1beef66067f126a16keunyoung
1888a94683196406b83b14218d1beef66067f126a16keunyoung    dev->common.tag = HARDWARE_DEVICE_TAG;
1898a94683196406b83b14218d1beef66067f126a16keunyoung    dev->common.version = 0;
1908a94683196406b83b14218d1beef66067f126a16keunyoung    dev->common.module = (struct hw_module_t*)module;
1918a94683196406b83b14218d1beef66067f126a16keunyoung    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
1928a94683196406b83b14218d1beef66067f126a16keunyoung    dev->set_light = set_light;
1938a94683196406b83b14218d1beef66067f126a16keunyoung
1948a94683196406b83b14218d1beef66067f126a16keunyoung    *device = (struct hw_device_t*)dev;
1958a94683196406b83b14218d1beef66067f126a16keunyoung    return 0;
1968a94683196406b83b14218d1beef66067f126a16keunyoung}
1978a94683196406b83b14218d1beef66067f126a16keunyoung
1988a94683196406b83b14218d1beef66067f126a16keunyoungstatic struct hw_module_methods_t lights_module_methods = {
1998a94683196406b83b14218d1beef66067f126a16keunyoung    .open =  open_lights,
2008a94683196406b83b14218d1beef66067f126a16keunyoung};
2018a94683196406b83b14218d1beef66067f126a16keunyoung
2028a94683196406b83b14218d1beef66067f126a16keunyoung/*
2038a94683196406b83b14218d1beef66067f126a16keunyoung * The emulator lights Module
2048a94683196406b83b14218d1beef66067f126a16keunyoung */
2058a94683196406b83b14218d1beef66067f126a16keunyoungstruct hw_module_t HAL_MODULE_INFO_SYM = {
2068a94683196406b83b14218d1beef66067f126a16keunyoung    .tag = HARDWARE_MODULE_TAG,
2078a94683196406b83b14218d1beef66067f126a16keunyoung    .version_major = 1,
2088a94683196406b83b14218d1beef66067f126a16keunyoung    .version_minor = 0,
2098a94683196406b83b14218d1beef66067f126a16keunyoung    .id = LIGHTS_HARDWARE_MODULE_ID,
2108a94683196406b83b14218d1beef66067f126a16keunyoung    .name = "Goldfish lights Module",
2118a94683196406b83b14218d1beef66067f126a16keunyoung    .author = "The Android Open Source Project",
2128a94683196406b83b14218d1beef66067f126a16keunyoung    .methods = &lights_module_methods,
2138a94683196406b83b14218d1beef66067f126a16keunyoung};
214