diff --git a/board-info.txt b/board-info.txt new file mode 100644 index 0000000..1b03c30 --- /dev/null +++ b/board-info.txt @@ -0,0 +1,3 @@ +require mid=P* +require board=bravo | leo | htcleo +require version-microp=031d diff --git a/liblights/Android.mk b/liblights/Android.mk old mode 100644 new mode 100755 index 09857ad..1b3a4b4 --- a/liblights/Android.mk +++ b/liblights/Android.mk @@ -12,24 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. + LOCAL_PATH:= $(call my-dir) - -ifneq ($(TARGET_SIMULATOR),true) - +# HAL module implemenation, not prelinked and stored in +# hw/..so include $(CLEAR_VARS) -LOCAL_MODULE := lights.htcleo +LOCAL_SRC_FILES := lights.c +LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_MODULE_TAGS := optional +LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SRC_FILES := lights_leo.c \ - events.c - -LOCAL_SHARED_LIBRARIES := liblog libcutils -LOCAL_PRELINK_MODULE := false +##LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE := lights.htcleo include $(BUILD_SHARED_LIBRARY) - -endif # !TARGET_SIMULATOR diff --git a/liblights/MODULE_LICENSE_APACHE2 b/liblights/MODULE_LICENSE_APACHE2 old mode 100644 new mode 100755 diff --git a/liblights/NOTICE b/liblights/NOTICE old mode 100644 new mode 100755 index c5b1efa..7340b9e --- a/liblights/NOTICE +++ b/liblights/NOTICE @@ -1,5 +1,5 @@ - Copyright (c) 2005-2008, The Android Open Source Project + Copyright (c) 2008, The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/liblights/events.c b/liblights/events.c deleted file mode 100644 index 28e027b..0000000 --- a/liblights/events.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include - -#include "events.h" - -#define MAX_DEVICES 16 - -static struct pollfd ev_fds[MAX_DEVICES]; -static unsigned ev_count = 0; - -int ev_init(void) -{ - DIR *dir; - struct dirent *de; - int fd; - - dir = opendir("/dev/input"); - if(dir != 0) { - while((de = readdir(dir))) { -// fprintf(stderr,"/dev/input/%s\n", de->d_name); - if(strncmp(de->d_name,"event",5)) continue; - fd = openat(dirfd(dir), de->d_name, O_RDONLY); - if(fd < 0) continue; - - ev_fds[ev_count].fd = fd; - ev_fds[ev_count].events = POLLIN; - ev_count++; - if(ev_count == MAX_DEVICES) break; - } - } - - return 0; -} - -void ev_exit(void) -{ - while (ev_count > 0) { - close(ev_fds[--ev_count].fd); - } -} - -int ev_get(struct input_event *ev, unsigned dont_wait) -{ - int r; - unsigned n; - - do { - r = poll(ev_fds, ev_count, dont_wait ? 0 : -1); - - if(r > 0) { - for(n = 0; n < ev_count; n++) { - if(ev_fds[n].revents & POLLIN) { - r = read(ev_fds[n].fd, ev, sizeof(*ev)); - if(r == sizeof(*ev)) return 0; - } - } - } - } while(dont_wait == 0); - - return -1; -} diff --git a/liblights/events.h b/liblights/events.h deleted file mode 100644 index 4bcba3a..0000000 --- a/liblights/events.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _EVENTS_H_ -#define _EVENTS_H_ - - -// input event structure, include for the definition. -// see http://www.mjmwired.net/kernel/Documentation/input/ for info. -struct input_event; - -int ev_init(void); -int ev_get(struct input_event *ev, unsigned dont_wait); -void ev_exit(void); - -#endif diff --git a/liblights/lights.c b/liblights/lights.c old mode 100644 new mode 100755 index 86118f4..436402c --- a/liblights/lights.c +++ b/liblights/lights.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Danijel Posilovic aka dan1j3l * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,54 +30,80 @@ #include #include - #include +#include +#include +#include + /******************************************************************************/ + static pthread_once_t g_init = PTHREAD_ONCE_INIT; static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; + static struct light_state_t g_notification; static struct light_state_t g_battery; -static int g_backlight = 255; -static int g_buttons = 0; -static int g_attention = 0; +static int g_backlight = 255; +static int g_buttons = 0; +static int g_attention = 0; +static int button_state = 0; +static int screen_suspended = 1; +static int last_battery_state = 0; + +static time_t time_to_off; + +// working threads +static pthread_t t_timed_off = 0; +static pthread_t t_button_checker = 0; +static pthread_t t_battery_checker = 0; + +static pthread_t t_blink_button_backlight = 0; + +static int blink_button = 1; +static int battery_thread_led = 1; +static int was_blinking_notification = 0; +static int g_brightnessMode = 0; + + + +// HTC LEO LEDS char const*const GREEN_LED_FILE = "/sys/class/leds/green/brightness"; +char const*const GREEN_BLINK_FILE + = "/sys/class/leds/green/blink"; char const*const AMBER_LED_FILE = "/sys/class/leds/amber/brightness"; +char const*const AMBER_BLINK_FILE + = "/sys/class/leds/amber/blink"; char const*const LCD_FILE = "/sys/class/leds/lcd-backlight/brightness"; -char const*const AMBER_BLINK_FILE - = "/sys/class/leds/amber/blink"; - -char const*const GREEN_BLINK_FILE - = "/sys/class/leds/green/blink"; - char const*const BUTTON_FILE = "/sys/class/leds/button-backlight/brightness"; -char const*const WIMAX_FILE - = "/sys/class/leds/wimax/brightness"; +char const*const BUTTON_STATE_DEV + = "/dev/input/event3"; +char const*const BATTERY_STATUS_FILE + = "/sys/class/power_supply/battery/status"; + +char const*const LS_FILE + = "/sys/devices/platform/htcleo-backlight/auto_bl"; /** - * device methods - */ +device methods +*/ -void init_globals(void) -{ +void init_globals(void){ // init the mutex pthread_mutex_init(&g_lock, NULL); } -static int -write_int(char const* path, int value) -{ +static int write_int(char const* path, int value){ int fd; static int already_warned = 0; @@ -96,204 +123,485 @@ write_int(char const* path, int value) } } -static int -is_lit(struct light_state_t const* state) -{ +static int is_lit(struct light_state_t const* state){ return state->color & 0x00ffffff; } -static int -handle_trackball_light_locked(struct light_device_t* dev) -{ - //no trackball light for inc +static int rgb_to_brightness(struct light_state_t const* state){ + int color = state->color & 0x00ffffff; + return ((77*((color>>16)&0x00ff))+ (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; +} + + + +// dan1j3l EXPERIMENTAL - ONLY FOR SENSE BUILDS !!! +// TODO: Add sense detection and start this thread only in sense builds !!! +// Battery checking service ! +void *battery_state_checker(void *arg){ + int fd,size, rs; + char state[20]; + struct timespec t; + t.tv_nsec = 0; + t.tv_sec = 5; + + struct timespec t2; + t.tv_nsec = 0; + t.tv_sec = 1; + + + while (battery_thread_led){ + + memset(&state[0], 0, sizeof(state)); + + fd = open(BATTERY_STATUS_FILE,O_RDONLY); + read(fd, state,20); + close(fd); + + rs=0; + rs = sprintf(state,"%s",state); + + if ( !was_blinking_notification && last_battery_state != rs){ + last_battery_state=rs; + + if ( rs == 9){ // Charging + write_int(GREEN_LED_FILE, 0); + write_int(AMBER_BLINK_FILE, 0); + nanosleep(&t2,NULL); + write_int(AMBER_LED_FILE, 1); + }else if(rs == 5){ // FULL + write_int(AMBER_LED_FILE, 0); + write_int(GREEN_BLINK_FILE, 0); + nanosleep(&t2,NULL); + write_int(GREEN_LED_FILE, 1); + }else{ + write_int(AMBER_LED_FILE, 0); + write_int(GREEN_LED_FILE, 0); + } + + } + + nanosleep(&t,NULL); + } + + t_battery_checker = 0; + return 0; } - -static int -rgb_to_brightness(struct light_state_t const* state) -{ - int color = state->color & 0x00ffffff; - return ((77*((color>>16)&0x00ff)) - + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; +void start_battery_checker(){ + if (t_button_checker == 0) + pthread_create(&t_battery_checker, NULL, battery_state_checker, NULL); } -static int -set_light_backlight(struct light_device_t* dev, - struct light_state_t const* state) -{ + + +// Functions for timed powering on buttons +void *button_state_checker(void *arg) { + struct input_event ev[64]; + struct timespec t; + int fd, size = sizeof (struct input_event); + t.tv_nsec= 0; + t.tv_sec = 1; + + fd = open(BUTTON_STATE_DEV,O_RDONLY); + + while (1){ + + if (screen_suspended == 1 ){ + write_int(BUTTON_FILE,0); + button_state = 0; + break; + } + + read (fd, ev, size * 64); + + if (ev[0].value == 1){ + write_int(BUTTON_FILE,1); + button_state = 1; + button_timed_off(); + nanosleep(&t,NULL); + } + } + + close(fd); + t_button_checker = 0; // reset thread so we can recreate it later + + return 0; +} +int do_check_button_state() { + + if (t_button_checker == 0) // create thread only if does not exist + pthread_create(&t_button_checker, NULL, button_state_checker, NULL); + + return 0; +} + +void *blink_button_backlight(void *arg) { + struct timespec t; + t.tv_nsec= 0; + t.tv_sec = 1; + + blink_button = 1; + + while (blink_button){ + write_int(BUTTON_FILE,1); + nanosleep(&t,NULL); + write_int(BUTTON_FILE,0); + nanosleep(&t,NULL); + } + + t_blink_button_backlight = 0; // reset thread so we can recreate it later + + return 0; +} +int do_blink_button_backlight() { + + if (t_blink_button_backlight == 0) // create thread only if does not exist + pthread_create(&t_blink_button_backlight, NULL, blink_button_backlight, NULL); + + return 0; +} + + +// Functions for timed powering off buttons +void *timer_button_off(void *arg) { + struct timespec t; + time_t secs; + + t.tv_nsec = 0; + t.tv_sec = 1; + secs = time(NULL); + + // wait untill is time for power off buttons + while (secs < time_to_off){ + secs = time(NULL); + nanosleep(&t, NULL); + }; + + // if screen is suspended and buttons already turned off we exit thread + if (screen_suspended == 1 && button_state == 0) { + t_timed_off = 0; // reset thread + return 0; + } + + // turn off button lights + write_int(BUTTON_FILE,0); + button_state=0; + + // we check button states only if screen is active, else we close both threads + if (screen_suspended == 0) do_check_button_state(); + + t_timed_off = 0; // reset thread + return 0; +} +int button_timed_off() { + // we set time for power off (time now + 10 secs) + time_to_off = time(NULL) + 10; + + if (t_timed_off == 0) // if thread does not exist, we crate it + pthread_create(&t_timed_off, NULL, timer_button_off, NULL); + + return 0; +} + + +static int set_light_buttons(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_buttons"); + int err = 0; + /*int on = is_lit(state); + pthread_mutex_lock(&g_lock); + g_buttons = on; + err = write_int(BUTTON_FILE, on?255:0); + pthread_mutex_unlock(&g_lock); +*/ + return err; +} + + +static int set_light_backlight(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_backlight"); int err = 0; int brightness = rgb_to_brightness(state); pthread_mutex_lock(&g_lock); - g_backlight = brightness; - err = write_int(LCD_FILE, brightness); + + // On/Off Buttons + + if (g_brightnessMode != state->brightnessMode) { + g_brightnessMode = state->brightnessMode; + LOGD("Switched brightnessMode=%d brightness=%d\n",g_brightnessMode, + brightness); + write_int(LS_FILE, state->brightnessMode); + } + // if we switched to user mode, allow for setting the backlight immedeately + if (g_brightnessMode == BRIGHTNESS_MODE_USER || brightness==0 || g_backlight==0){ + LOGD("Setting brightnessMode=%d brightness=%d\n", g_brightnessMode, + brightness); + err = write_int(LCD_FILE, brightness); + } + + + + if (brightness == 0 && button_state == 1) { +// LOGD("button off"); + if(g_backlight) err = write_int(BUTTON_FILE,0); + button_state=0; + screen_suspended = 1; + }else if (brightness > 0 && button_state == 0){ +// LOGD("button on"); + if(!g_backlight) err = write_int(BUTTON_FILE,1); + button_state=1; + screen_suspended = 0; + // after powering buttons off, it's time to shut them down after declared amount of time (for now 10 sec) + button_timed_off(); + } + g_backlight = brightness; pthread_mutex_unlock(&g_lock); return err; } -static int -set_light_buttons(struct light_device_t* dev, - struct light_state_t const* state) -{ - int err = 0; - int on = is_lit(state); - pthread_mutex_lock(&g_lock); - g_buttons = on; - err = write_int(BUTTON_FILE, on?255:0); - pthread_mutex_unlock(&g_lock); - return err; -} - -static int -set_wimax_light_locked(struct light_device_t* dev, - struct light_state_t const* state) -{ - int blink; - int green, amber, blue; - unsigned int colorRGB; - - switch (state->flashMode) { - case LIGHT_FLASH_NONE: - blink = 0; - break; - default: - blink = 1; - break; - } - - colorRGB = state->color; - - amber = (colorRGB >> 16) & 0xFF; - green = (colorRGB >> 8) & 0xFF; - blue = colorRGB & 0xFF; - - LOGD("set_wimax_light_locked colorRGB=%08X, green=%d, amber=%d blue=%d flashMode=%d\n", - colorRGB, green, amber, blue, state->flashMode); - - if ((green || blue) && blink) { - write_int(WIMAX_FILE, 3); - } else if (amber && blink) { - write_int(WIMAX_FILE, 5); - } else { - write_int(WIMAX_FILE, 0); - } - +// dan1j3l: maybe remove this funct +static int set_light_keyboard(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_keyboard"); + // Nothing to do in leo return 0; } -static int -set_speaker_light_locked(struct light_device_t* dev, - struct light_state_t const* state) -{ - int len; - int alpha, red, green, blue; - int blink, freq, pwm; - int onMS, offMS; - unsigned int colorRGB; +static void blinkLed(unsigned int color, int blink){ + struct timespec t; + int red, green, blue; + + t.tv_nsec = 0; + t.tv_sec = 1; + + + red = (color >> 16) & 0xFF; + green = (color >> 8) & 0xFF; + blue = color & 0xFF; + + + if (red) { // Amber on / blink + //if(blink){ + // battery_thread_led = 0; // turn off battery thread for a while + //} + write_int(GREEN_LED_FILE, 0); + write_int(AMBER_LED_FILE, 1); + nanosleep(&t, NULL); + if(blink) write_int(AMBER_BLINK_FILE, blink); + LOGD("amber on, blink:%d",blink); + } else if (green || blue || color == 0x1) { // Green on / blink + write_int(AMBER_LED_FILE, 0); + write_int(GREEN_LED_FILE, 1); + nanosleep(&t, NULL); + if(blink) write_int(GREEN_BLINK_FILE, blink); + LOGD("green on, blink:%d",blink); + } else { // Leds off + write_int(GREEN_LED_FILE, 0); + write_int(AMBER_LED_FILE, 0); + write_int(AMBER_BLINK_FILE, 0); + write_int(GREEN_BLINK_FILE, 0); + //start_battery_checker(); + LOGD("leds off"); + } + + LOGD("light-colors red:%d green:%d blue:%d",red,green,blue); +} +// dan1j3l TODO: Refactor, and simplify this funct +static int set_speaker_light_locked(struct light_device_t* dev,struct light_state_t const* state){ + int blink; + + unsigned int colorRGB; + + LOGD("set_speaker_light_locked"); + + // Blink or solid switch (state->flashMode) { case LIGHT_FLASH_TIMED: blink = 1; - onMS = state->flashOnMS; - offMS = state->flashOffMS; - break; - case LIGHT_FLASH_HARDWARE: - blink = 1; - onMS = state->flashOnMS; - offMS = state->flashOffMS; break; case LIGHT_FLASH_NONE: blink = 0; - onMS = 0; - offMS = 0; break; default: - blink = 1; - onMS = 0; - offMS = 0; + blink = 0; break; } + // dan1j3l: TODO: simplify color detection colorRGB = state->color; - LOGD("set_speaker_light_locked colorRGB=%08X, onMS=%d, offMS=%d\n", - colorRGB, onMS, offMS); + // dan1j3l BUG: on some android releases leds needs to be reseted by putting blink & brightness to 0 before enabling them + + blinkLed(colorRGB, blink); + + return 0; +} +// dan1j3l TODO: Refactor this funct +static void handle_speaker_battery_locked(struct light_device_t* dev){ + + LOGD("handle_speaker_battery_locked"); + + if (is_lit(&g_battery)) { + set_speaker_light_locked(dev, &g_battery); + } else { + set_speaker_light_locked(dev, &g_notification); + } +} + +static int set_light_battery(struct light_device_t* dev,struct light_state_t const* state){ + + LOGD("set_light_battery"); + + pthread_mutex_lock(&g_lock); + g_battery = *state; + + handle_speaker_battery_locked(dev); + + pthread_mutex_unlock(&g_lock); + return 0; +} + +static int set_light_notifications(struct light_device_t* dev,struct light_state_t const* state){ + + LOGD("set_light_notifications"); + pthread_mutex_lock(&g_lock); + g_notification = *state; + + handle_speaker_battery_locked(dev); + + pthread_mutex_unlock(&g_lock); + return 0; +} + + +// dan1j3l BUG: Button lights ? +static int set_light_attention(struct light_device_t* dev,struct light_state_t const* state){ + pthread_mutex_lock(&g_lock); + +/* if (state->flashMode == LIGHT_FLASH_HARDWARE) { + g_attention = state->flashOnMS; + } else if (state->flashMode == LIGHT_FLASH_NONE) { + g_attention = 0; + } + + int mode = g_attention;*/ + + if(is_lit(state) && state->flashOnMS) { + do_blink_button_backlight(); + } else { + blink_button = 0; + } + LOGD("set_light_attention: %p(%d,%d,%d)\n", state->color, state->flashMode, state->flashOnMS, state->flashOffMS); + +/* if (mode == 7 && g_backlight) { + mode = 0; + }*/ + + pthread_mutex_unlock(&g_lock); + return 0; +} + +/** New stuff */ +// dan1j3l TODO: Verify each device and create led detection + +static int set_light_bluetooth(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_bluetooth"); + return 0; +} + +static int set_light_wifi(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_wifi"); + return 0; +} + +static int set_light_dualled(struct light_device_t* dev,struct light_state_t const* state){ + + pthread_mutex_lock(&g_lock); + + // we only care for blinking states atm + if(is_lit(state) && state->flashOnMS) { + blinkLed(state->color,1); + was_blinking_notification = 1; + } else if(was_blinking_notification && !is_lit(state)) { + blinkLed(0,0); + was_blinking_notification = 0; + } + LOGD("set_light_dualled: %p(%d,%d,%d)\n", state->color, state->flashMode, state->flashOnMS, state->flashOffMS); + + pthread_mutex_unlock(&g_lock); + return 0; + + + /* + // Blink or solid + switch (state->flashMode) { + case LIGHT_FLASH_TIMED: + blink = 1; + break; + case LIGHT_FLASH_HARDWARE: + blink = 1; + break; + case LIGHT_FLASH_NONE: + blink = 0; + break; + default: + blink = 0; + break; + } + + + LOGD("dl mode:%d, offMS:%d, OnMS:%d, brightness:%d",state->flashMode,state->flashOffMS,state->flashOnMS,state->brightnessMode); + + + // dan1j3l: TODO: simplify color detection + colorRGB = state->color; red = (colorRGB >> 16) & 0xFF; green = (colorRGB >> 8) & 0xFF; blue = colorRGB & 0xFF; - if (red) { - write_int(GREEN_LED_FILE, 0); - write_int(AMBER_LED_FILE, 1); - if (blink) { - //blink must come after brightness change - write_int(AMBER_BLINK_FILE, 1); - } - } else if (green || blue) { - write_int(AMBER_LED_FILE, 0); - write_int(GREEN_LED_FILE, 1); - if (blink) { - write_int(GREEN_BLINK_FILE, 1); - } - } else { - write_int(GREEN_LED_FILE, 0); - write_int(AMBER_LED_FILE, 0); + // dan1j3l TEST ON DIFFERENT BUILDS !!! + if (state->flashMode == LIGHT_FLASH_NONE && red == 0 && green == 0 && blue == 0){ + // turn amber on + LOGD("amber on"); + write_int(AMBER_BLINK_FILE,0); + write_int(AMBER_LED_FILE,1); + }else{ + //turn amber off + LOGD("amber off"); + write_int(AMBER_LED_FILE,0); } + + + + LOGD("dl fullcolor:%d",state->color); + LOGD("dl-color red:%d green:%d blue:%d",red,green,blue); - return 0; -} - -static void -handle_speaker_light_locked(struct light_device_t* dev) -{ - set_speaker_light_locked(dev, &g_battery); -} - -static void -handle_notification_light_locked(struct light_device_t* dev) -{ - set_wimax_light_locked(dev, &g_notification); -} - -static int -set_light_battery(struct light_device_t* dev, - struct light_state_t const* state) -{ - pthread_mutex_lock(&g_lock); - g_battery = *state; - handle_speaker_light_locked(dev); + */ + pthread_mutex_unlock(&g_lock); return 0; } -static int -set_light_notifications(struct light_device_t* dev, - struct light_state_t const* state) -{ - pthread_mutex_lock(&g_lock); - g_notification = *state; - handle_notification_light_locked(dev); - pthread_mutex_unlock(&g_lock); +// dan1j3l ??? +static int set_light_capsfunc(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_capsfunc"); return 0; } -static int -set_light_attention(struct light_device_t* dev, - struct light_state_t const* state) -{ - //no attention light for supersonic +// dan1j3l - Nothing interesting for leo +static int set_light_jogball(struct light_device_t* dev,struct light_state_t const* state){ + LOGD("set_light_jogball"); return 0; } +/** ****************************************************/ + /** Close the lights device */ -static int -close_lights(struct light_device_t *dev) -{ +static int close_lights(struct light_device_t *dev){ if (dev) { free(dev); } - return 0; } @@ -305,33 +613,63 @@ close_lights(struct light_device_t *dev) */ /** Open a new instance of a lights device using name */ -static int open_lights(const struct hw_module_t* module, char const* name, - struct hw_device_t** device) -{ - int (*set_light)(struct light_device_t* dev, - struct light_state_t const* state); +static int open_lights(const struct hw_module_t* module, char const* name,struct hw_device_t** device){ + + int (*set_light)(struct light_device_t* dev,struct light_state_t const* state); if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) { set_light = set_light_backlight; + LOGD("init backlight, id:%s",name); + } + else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) { //dan1j3l: Ignored on leo + set_light = set_light_keyboard; + LOGD("init keyboard, id:%s",name); } else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) { set_light = set_light_buttons; + LOGD("init buttons, id:%s",name); } else if (0 == strcmp(LIGHT_ID_BATTERY, name)) { set_light = set_light_battery; + start_battery_checker(); // needed for sense builds + LOGD("init battery, id:%s",name); } else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) { set_light = set_light_notifications; + LOGD("init notifications, id:%s",name); } else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) { set_light = set_light_attention; + LOGD("init attention, id:%s",name); + } + else if (0 == strcmp(LIGHT_ID_BLUETOOTH, name)) { + set_light = set_light_bluetooth; + LOGD("init bluetooth, id:%s",name); + } + else if (0 == strcmp(LIGHT_ID_WIFI, name)) { + set_light = set_light_wifi; + LOGD("init wifi, id:%s",name); + } + else if (0 == strcmp(LIGHT_ID_DUALLED, name)) { + set_light = set_light_dualled; + LOGD("init dualled, id:%s",name); + } + else if (0 == strcmp(LIGHT_ID_CAPSFUNC, name)) { // dan1j3l: what is capsfunc ? + set_light = set_light_capsfunc; + LOGD("init capsfunc, id:%s",name); + } + else if (0 == strcmp(LIGHT_ID_JOGBALL, name)) { // dan1j3l: is needed in leo ? + set_light = set_light_jogball; + LOGD("init jogball, id:%s",name); } else { + LOGD("Undefined device, id:%s",name); return -EINVAL; } - pthread_once(&g_init, init_globals); + pthread_once(&g_init, init_globals); + struct light_device_t *dev = malloc(sizeof(struct light_device_t)); memset(dev, 0, sizeof(*dev)); @@ -358,7 +696,7 @@ const struct hw_module_t HAL_MODULE_INFO_SYM = { .version_major = 1, .version_minor = 0, .id = LIGHTS_HARDWARE_MODULE_ID, - .name = "Supersonic lights module", - .author = "CyanogenMod", + .name = "HTC Leo Lights module", + .author = "dan1j3l", .methods = &lights_module_methods, }; diff --git a/liblights/lights.c-mahimahi b/liblights/lights.c-mahimahi new file mode 100755 index 0000000..bec21e0 --- /dev/null +++ b/liblights/lights.c-mahimahi @@ -0,0 +1,635 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "lights" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define LIGHT_ATTENTION 1 +#define LIGHT_NOTIFY 2 + +/******************************************************************************/ +static struct light_state_t *g_notify; +static struct light_state_t *g_attention; + +static pthread_once_t g_init = PTHREAD_ONCE_INIT; +static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; + +static int g_backlight = 255; +static int g_buttons = 0; + +struct led_prop { + const char *filename; + int fd; +}; + +struct led { + struct led_prop mode; + struct led_prop brightness; + struct led_prop blink; + struct led_prop color; + struct led_prop period; +}; + +enum { + JOGBALL_LED, + BUTTONS_LED, + AMBER_LED, + GREEN_LED, + BLUE_LED, + RED_LED, + LCD_BACKLIGHT, + NUM_LEDS, +}; + +struct led leds[NUM_LEDS] = { +// [JOGBALL_LED] = { +// .brightness = { "/sys/class/leds/jogball-backlight/brightness", 0}, +// .color = { "/sys/class/leds/jogball-backlight/color", 0}, +// .period = { "/sys/class/leds/jogball-backlight/period", 0}, +// }, + [BUTTONS_LED] = { + .brightness = { "/sys/class/leds/button-backlight/brightness", 0}, + }, +// [RED_LED] = { +// .brightness = { "/sys/class/leds/red/brightness", 0}, +// .blink = { "/sys/class/leds/red/blink", 0}, +// }, + [GREEN_LED] = { + .brightness = { "/sys/class/leds/green/brightness", 0}, + .blink = { "/sys/class/leds/green/blink", 0}, + }, +// [BLUE_LED] = { +// .brightness = { "/sys/class/leds/blue/brightness", 0}, +// .blink = { "/sys/class/leds/blue/blink", 0}, +// }, + [AMBER_LED] = { + .brightness = { "/sys/class/leds/amber/brightness", 0}, + .blink = { "/sys/class/leds/amber/blink", 0}, + }, + [LCD_BACKLIGHT] = { + .brightness = { "/sys/class/leds/lcd-backlight/brightness", 0}, + }, +}; + +enum { + RGB_BLACK = 0x000000, + RGB_RED = 0xFF0000, + RGB_AMBER = 0xFFFF00, /* note this is actually RGB yellow */ + RGB_GREEN = 0x00FF00, + RGB_BLUE = 0x0000FF, + RGB_WHITE = 0xFFFFFF, + RGB_PINK = 0xFFC0CB, + RGB_ORANGE = 0xFFA500, + RGB_YELLOW = 0xFFFF00, + RGB_PURPLE = 0x800080, + RGB_LT_BLUE = 0xADD8E6, +}; + +/** + * device methods + */ + +static int init_prop(struct led_prop *prop) +{ + int fd; + + prop->fd = -1; + if (!prop->filename) + return 0; + fd = open(prop->filename, O_RDWR); + if (fd < 0) { + LOGE("init_prop: %s cannot be opened (%s)\n", prop->filename, + strerror(errno)); + return -errno; + } + + prop->fd = fd; + return 0; +} + +static void close_prop(struct led_prop *prop) +{ + int fd; + + if (prop->fd > 0) + close(prop->fd); + return; +} + +void init_globals(void) +{ + int i; + pthread_mutex_init(&g_lock, NULL); + + for (i = 0; i < NUM_LEDS; ++i) { + init_prop(&leds[i].brightness); + init_prop(&leds[i].blink); +// init_prop(&leds[i].mode); +// init_prop(&leds[i].color); +// init_prop(&leds[i].period); + } + g_attention = malloc(sizeof(struct light_state_t)); + memset(g_attention, 0, sizeof(*g_attention)); + g_notify = malloc(sizeof(struct light_state_t)); + memset(g_notify, 0, sizeof(*g_notify)); +} + +static int +write_int(struct led_prop *prop, int value) +{ + char buffer[20]; + int bytes; + int amt; + + if (prop->fd < 0) + return 0; + + LOGV("%s %s: 0x%x\n", __func__, prop->filename, value); + + bytes = snprintf(buffer, sizeof(buffer), "%d\n", value); + while (bytes > 0) { + amt = write(prop->fd, buffer, bytes); + if (amt < 0) { + if (errno == EINTR) + continue; + return -errno; + } + bytes -= amt; + } + + return 0; +} + +static int +write_rgb(struct led_prop *prop, int red, int green, int blue) +{ + char buffer[20]; + int bytes; + int amt; + + if (prop->fd < 0) + return 0; + + LOGV("%s %s: red:%d green:%d blue:%d\n", + __func__, prop->filename, red, green, blue); + + bytes = snprintf(buffer, sizeof(buffer), "%d %d %d\n", red, green, blue); + while (bytes > 0) { + amt = write(prop->fd, buffer, bytes); + if (amt < 0) { + if (errno == EINTR) + continue; + return -errno; + } + bytes -= amt; + } + + return 0; +} + +static unsigned int +set_rgb(int red, int green, int blue) +{ + return(((red << 16) & 0x00ff0000) | + ((green << 8) & 0x0000ff00) | + (blue & 0x000000ff)); +} + +static int +is_lit(struct light_state_t const* state) +{ + return state->color & 0x00ffffff; +} + +static int +set_button_light(struct light_state_t const* state) +{ + static int button_mode = 0; + int rc = 0; + int mode = state->flashMode; + int red, blue, green; + int period = 0; + + if (state->flashMode == LIGHT_FLASH_HARDWARE) { + mode = state->flashOnMS; + period = state->flashOffMS; + } + +// LOGD("%s color=%08x mode=%d period %d\n", __func__,state->color, mode, period); + + if (mode != 0) { + write_int(&leds[BUTTONS_LED].brightness,1); + } + // If the value isn't changing, don't set it, because this + // can reset the timer on the breathing mode, which looks bad. + if (button_mode == mode) { + return 0; + } + button_mode = mode; + + LOGD("set_button_light mode:%d",mode); + + + return write_int(&leds[BUTTONS_LED].brightness, mode); +} + +static void +handle_button_light_locked(int type) +{ + LOGD("handle_button_light_locked"); + + struct light_state_t *new_state = 0; + int attn_mode = 0; + + if (g_attention->flashMode == LIGHT_FLASH_HARDWARE) + attn_mode = g_attention->flashOnMS; + + //LOGD("%s type %d attention %p notify %p\n",__func__, type, g_attention, g_notify); + + switch (type) { + case LIGHT_ATTENTION: { + if (attn_mode == 0) { + /* go back to notify state */ + new_state = g_notify; + } else { + new_state = g_attention; + } + break; + } + case LIGHT_NOTIFY: { + if (attn_mode != 0) { + /* attention takes priority over notify state */ + new_state = g_attention; + } else { + new_state = g_notify; + } + break; + } + } + if (new_state == 0) { + LOGD("%s: unknown type (%d)\n", __func__, type); + return; + } + LOGD("%s new state %p\n", __func__, new_state); + + set_button_light(new_state); + return; +} + +static int +rgb_to_brightness(struct light_state_t const* state) +{ + int color = state->color & 0x00ffffff; + return ((77*((color>>16)&0x00ff)) + + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; +} + +static int +set_light_backlight(struct light_device_t* dev, + struct light_state_t const* state) +{ + LOGD("set_light_backlight"); + int err = 0; + int brightness = rgb_to_brightness(state); + //LOGD("%s brightness=%d color=0x%08x",__func__,brightness, state->color); + pthread_mutex_lock(&g_lock); + g_backlight = brightness; + err = write_int(&leds[LCD_BACKLIGHT].brightness, brightness); + pthread_mutex_unlock(&g_lock); + return err; +} + +static int +set_light_keyboard(struct light_device_t* dev, + struct light_state_t const* state) +{ + /* nothing to do on mahimahi*/ + return 0; +} + +static int +set_light_buttons(struct light_device_t* dev, + struct light_state_t const* state) +{ + LOGD("set_light_buttons"); + int err = 0; + int on = is_lit(state); + pthread_mutex_lock(&g_lock); + g_buttons = on; + err = write_int(&leds[BUTTONS_LED].brightness, on?255:0); + pthread_mutex_unlock(&g_lock); + return err; +} + +static int +set_speaker_light_locked(struct light_device_t* dev, + struct light_state_t const* state) +{ + LOGD("set_speaker_light_locked"); + int len; + unsigned int colorRGB; + + /* Red = amber_led, blue or green = green_led */ + colorRGB = state->color & 0xFFFFFF; + + + switch (state->flashMode) { + case LIGHT_FLASH_TIMED: + switch (colorRGB) { + case RGB_RED: + LOGD("flash red"); + write_int(&leds[RED_LED].blink, 1); + break; + case RGB_AMBER: + LOGD("flash amber"); + write_int(&leds[AMBER_LED].blink, 2); + break; + case RGB_GREEN: + LOGD("flash green"); + write_int(&leds[GREEN_LED].blink, 1); + break; + case RGB_BLUE: + LOGD("flash blue"); + write_int(&leds[BLUE_LED].blink, 1); + break; + case RGB_BLACK: /*off*/ + LOGD("flash off"); + write_int(&leds[GREEN_LED].blink, 0); + write_int(&leds[AMBER_LED].blink, 0); + break; + default: + break; + } + break; + + case LIGHT_FLASH_NONE: + switch (colorRGB) { + case RGB_AMBER: + LOGD("solid amber"); + write_int(&leds[GREEN_LED].brightness, 0); + write_int(&leds[AMBER_LED].blink, 0); + write_int(&leds[AMBER_LED].brightness, 1); + break; + case RGB_GREEN: + LOGD("solid green"); + write_int(&leds[AMBER_LED].brightness, 0); + write_int(&leds[GREEN_LED].blink, 0); + write_int(&leds[GREEN_LED].brightness, 1); + break; + case RGB_BLACK: /*off*/ + LOGD("all off"); + write_int(&leds[GREEN_LED].brightness, 0); + write_int(&leds[AMBER_LED].brightness, 0); + break; + default: + break; + } + break; + default: + break; + } + return 0; +} + +static int +set_light_battery(struct light_device_t* dev, + struct light_state_t const* state) +{ + pthread_mutex_lock(&g_lock); + LOGD("set_light_battery"); + LOGD("%s mode=%d color=0x%08x", + __func__,state->flashMode, state->color); + + set_speaker_light_locked(dev, state); + + pthread_mutex_unlock(&g_lock); + return 0; +} + +static int +set_light_notifications(struct light_device_t* dev, + struct light_state_t const* state) +{ + pthread_mutex_lock(&g_lock); + + LOGD("set_light_notification"); + + LOGD("%s mode=%d color=0x%08x On=%d Off=%d\n", + __func__,state->flashMode, state->color, + state->flashOnMS, state->flashOffMS); + /* + ** TODO Allow for user settings of color and interval + ** Setting 60% brightness + */ + switch (state->color & 0x00FFFFFF) { + case RGB_BLACK: + g_notify->color = set_rgb(0, 0, 0); + break; + case RGB_WHITE: + g_notify->color = set_rgb(50, 127, 48); + break; + case RGB_RED: + g_notify->color = set_rgb(141, 0, 0); + break; + case RGB_GREEN: + g_notify->color = set_rgb(0, 141, 0); + break; + case RGB_BLUE: + g_notify->color = set_rgb(0, 0, 141); + break; + case RGB_PINK: + g_notify->color = set_rgb(141, 52, 58); + break; + case RGB_PURPLE: + g_notify->color = set_rgb(70, 0, 70); + break; + case RGB_ORANGE: + g_notify->color = set_rgb(141, 99, 0); + break; + case RGB_YELLOW: + g_notify->color = set_rgb(100, 141, 0); + break; + case RGB_LT_BLUE: + g_notify->color = set_rgb(35, 55, 98); + break; + default: + g_notify->color = state->color; + break; + } + + if (state->flashMode != LIGHT_FLASH_NONE) { + g_notify->flashMode = LIGHT_FLASH_HARDWARE; + g_notify->flashOnMS = 7; + g_notify->flashOffMS = (state->flashOnMS + state->flashOffMS)/1000; + } else { + g_notify->flashOnMS = 0; + g_notify->flashOffMS = 0; + } + handle_button_light_locked(LIGHT_NOTIFY); + + pthread_mutex_unlock(&g_lock); + return 0; +} + +static int +set_light_attention(struct light_device_t* dev, + struct light_state_t const* state) +{ + unsigned int colorRGB; + + + LOGD("set_light_attention"); + LOGD("%s color=0x%08x mode=0x%08x submode=0x%08x", + __func__, state->color, state->flashMode, state->flashOnMS); + + pthread_mutex_lock(&g_lock); + /* tune color for hardware*/ + switch (state->color & 0x00FFFFFF) { + case RGB_WHITE: + colorRGB = set_rgb(101, 255, 96); + break; + case RGB_BLUE: + colorRGB = set_rgb(0, 0, 235); + break; + case RGB_BLACK: + colorRGB = set_rgb(0, 0, 0); + break; + default: + LOGD("%s colorRGB=%08X, unknown color\n", + __func__, state->color); + colorRGB = set_rgb(101, 255, 96); + break; + } + + g_attention->flashMode = state->flashMode; + g_attention->flashOnMS = state->flashOnMS; + g_attention->color = colorRGB; + g_attention->flashOffMS = 0; + handle_button_light_locked(LIGHT_ATTENTION); + + pthread_mutex_unlock(&g_lock); + return 0; +} + + +/** Close the lights device */ +static int +close_lights(struct light_device_t *dev) +{ + int i; + + LOGD("close_lights"); + for (i = 0; i < NUM_LEDS; ++i) { + close_prop(&leds[i].brightness); + close_prop(&leds[i].blink); + close_prop(&leds[i].mode); + } + + if (dev) { + free(dev); + } + return 0; +} + + +/******************************************************************************/ + +/** + * module methods + */ + +/** Open a new instance of a lights device using name */ +static int open_lights(const struct hw_module_t* module, char const* name, + struct hw_device_t** device) +{ + int (*set_light)(struct light_device_t* dev, + struct light_state_t const* state); + + if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) { + set_light = set_light_backlight; + LOGD("init backlight"); + } + else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) { + set_light = set_light_keyboard; + LOGD("init keyboard"); + } + else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) { + set_light = set_light_buttons; + LOGD("init buttons"); + } + else if (0 == strcmp(LIGHT_ID_BATTERY, name)) { + set_light = set_light_battery; + LOGD("init battery"); + } + else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) { + set_light = set_light_notifications; + LOGD("init notifications"); + } + else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) { + set_light = set_light_attention; + LOGD("init attention"); + } + else { + return -EINVAL; + } + + pthread_once(&g_init, init_globals); + + struct light_device_t *dev = malloc(sizeof(struct light_device_t)); + memset(dev, 0, sizeof(*dev)); + + LOGD("hw device tag:%d",HARDWARE_DEVICE_TAG); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*)module; + dev->common.close = (int (*)(struct hw_device_t*))close_lights; + dev->set_light = set_light; + + *device = (struct hw_device_t*)dev; + return 0; +} + + +static struct hw_module_methods_t lights_module_methods = { + .open = open_lights, +}; + +/* + * The lights Module + */ +const struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = LIGHTS_HARDWARE_MODULE_ID, + .name = "mahimahi lights Module", + .author = "Google, Inc.", + .methods = &lights_module_methods, +}; diff --git a/liblights/lights_leo.c b/liblights/lights_leo.c deleted file mode 100644 index 373f443..0000000 --- a/liblights/lights_leo.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "lights_leo" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#include "events.h" - -#define LIGHT_ATTENTION 1 -#define LIGHT_NOTIFY 2 - -//#define ENABLE_LCDSAVE -//#define ENABLE_BATTERY_POOL - -#define ENABLE_RADIO_POOL - -#define LED_DEBUG 1 - -#if LED_DEBUG -# define D(...) LOGD(__VA_ARGS__) -#else -# define D(...) ((void)0) -#endif - -/******************************************************************************/ -static struct light_state_t *g_notify; -static struct light_state_t *g_attention; -static pthread_once_t g_init = PTHREAD_ONCE_INIT; -static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; - -#ifdef ENABLE_LCDSAVE -static int g_current_backlight = 0; -#endif - -static int g_ts = 0; -static int g_backlight = 255; -static int g_buttons = 0; - -struct led_prop { - const char *filename; - int fd; - int value; -}; - -struct led { - struct led_prop brightness; - struct led_prop blink; -}; - -enum { - BUTTONS_LED, - GREEN_LED, - AMBER_LED, - LCD_BACKLIGHT, - NUM_LEDS, -}; - -struct led leds[NUM_LEDS] = { - [BUTTONS_LED] = { - .brightness = { "/sys/class/leds/button-backlight/brightness", 0, 0}, - .blink = {NULL, 0, 0}, - }, - [GREEN_LED] = { - .brightness = { "/sys/class/leds/green/brightness", 0, 0}, - .blink = { "/sys/class/leds/green/blink", 0, 0}, - }, - [AMBER_LED] = { - .brightness = { "/sys/class/leds/amber/brightness", 0, 0}, - .blink = { "/sys/class/leds/amber/blink", 0, 0}, - }, - [LCD_BACKLIGHT] = { - .brightness = { "/sys/class/leds/lcd-backlight/brightness", 0, 0}, - .blink = {NULL, 0, 0}, - }, -}; - -/** - * device methods - */ - -static int init_prop(struct led_prop *prop) -{ - int fd; - - prop->fd = -1; - if (!prop->filename) - return 0; - fd = open(prop->filename, O_RDWR); - if (fd < 0) { - LOGE("init_prop: %s cannot be opened (%s)\n", prop->filename, - strerror(errno)); - return -errno; - } - - prop->fd = fd; - return 0; -} - -static void close_prop(struct led_prop *prop) -{ - int fd; - - if (prop->fd > 0) - close(prop->fd); - return; -} - -void init_globals(void) -{ - int i; - pthread_mutex_init(&g_lock, NULL); - - for (i = 0; i < NUM_LEDS; ++i) { - init_prop(&leds[i].brightness); - if (leds[i].blink.filename) { - init_prop(&leds[i].blink); - } - } - g_attention = malloc(sizeof(struct light_state_t)); - memset(g_attention, 0, sizeof(*g_attention)); - g_notify = malloc(sizeof(struct light_state_t)); - memset(g_notify, 0, sizeof(*g_notify)); -} - -static int -write_int(struct led_prop *prop, int value) -{ - char buffer[20]; - int bytes; - int amt; - - if (prop->fd < 0) - return 0; - if (prop->value != value) { - //LOGV("%s %s: 0x%x\n", __func__, prop->filename, value); - bytes = snprintf(buffer, sizeof(buffer), "%d\n", value); - while (bytes > 0) { - amt = write(prop->fd, buffer, bytes); - if (amt < 0) { - if (errno == EINTR) - continue; - return -errno; - } - bytes -= amt; - } - prop->value = value; - } - return 0; -} - -static int -is_lit(struct light_state_t const* state) -{ - return state->color & 0x00ffffff; -} - -static int -rgb_to_brightness(struct light_state_t const* state) -{ - int color = state->color & 0x00ffffff; - return ((77*((color>>16)&0x00ff)) - + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; -} - -//===================================================================================== -#ifdef ENABLE_BATTERY_POLL -static pthread_t battery_check_t = 0; -static int last_battery_state = 0; - -void *battery_state_thread(void *arg){ - int fd,size, rs; - char state[20]; - struct timespec t; - t.tv_nsec = 0; - t.tv_sec = 5; - - fd = open("/sys/class/power_supply/battery/status",O_RDONLY | O_NDELAY); - if(fd < 0) { - LOGE("Couldn't open /sys/class/power_supply/battery/status\n"); - return 0; - } - - for (;;) { - memset(&state[0], 0, sizeof(state)); - - read(fd, state,20); - close(fd); - - rs=0; - rs = sprintf(state,"%s",state); - - if ( last_battery_state != rs){ - last_battery_state=rs; - - if ( rs == 9){ // Charging - write_int(&leds[GREEN_LED].brightness, 0); - write_int(&leds[AMBER_LED].brightness, 1); - write_int(&leds[AMBER_LED].blink, 0); - }else if(rs == 5){ // FULL - write_int(&leds[GREEN_LED].brightness, 1); - write_int(&leds[AMBER_LED].brightness, 0); - write_int(&leds[GREEN_LED].blink, 0); - } - - } - - nanosleep(&t,NULL); - } - - close(fd); - return 0; -} - -void start_battery_thread(){ - if (battery_check_t == 0) //ensure only 1 thread - pthread_create(&battery_check_t, NULL, battery_state_thread, NULL); - return; -} -#endif -//===================================================================================== -#ifdef ENABLE_RADIO_POOL -static int last_radio_state = 0; -#endif - -static pthread_t events_ct = 0; -static time_t keys_tm; -#ifdef ENABLE_LCDSAVE -static time_t abs_tm; -static time_t last_activity_tm; - -static int user_activity_idle() { - int fd; - int ret =0; - char tmp[20]; - - fd= open("/sys/android_power/auto_off_timeout",O_RDONLY); - if(fd < 0) { - LOGE("Couldn't open /sys/android_power/auto_off_timeout\n"); - return 0; - } - - memset(&tmp[0], 0, sizeof(tmp)); - read(fd, tmp,20); - - D("@@ %s->%s\n", __func__, tmp); - - close(fd); - return (ret); -} -#endif - -static int -switch_led_button(int on) { - int err = 0; - if (g_buttons!=on) { - //D("@@ %s->%s\n", __func__, g_buttons?"ON":"OFF"); - err = write_int(&leds[BUTTONS_LED].brightness, on); - keys_tm = time(NULL) + (8*on); // switch off button keypad after 8 seconds - g_buttons = on; - } - return err; -} - -static int -set_led_backlight(int level) { - int err = 0; - //D("%s: [%d %d %d]\n", __func__, level, g_backlight, g_current_backlight); - if (g_backlight != level ){ - err = write_int(&leds[LCD_BACKLIGHT].brightness, level); - g_backlight = level; - } -#ifdef ENABLE_LCDSAVE - if (level>=g_current_backlight){ - g_current_backlight=level; - abs_tm = time(NULL) + (10); - } -#endif - return err; -} - -void *events_cthread(void *arg) { -#ifdef ENABLE_RADIO_POOL - int radio_state = 0; - char sim_state[PROPERTY_VALUE_MAX]; -#endif - struct input_event ev; - struct timespec t; - time_t a_tm, k_tm; - //int fd; - t.tv_nsec= 10000*1000; - t.tv_sec = 0; - - ev_init(); - - for (;;) { - /* radio events tracking */ -#ifdef ENABLE_RADIO_POOL - radio_state = 0; - if (property_get("gsm.sim.state", sim_state, NULL) && (strcmp(sim_state, "READY")==0)) { - radio_state = 1; - } - //radio state changed - if ( last_radio_state != radio_state){ - D("@@ %s: |%s| %d->%d\n", __func__, sim_state, last_radio_state, radio_state ); - //green blink if radio is on - write_int(&leds[AMBER_LED].brightness, radio_state?0:1); - write_int(&leds[GREEN_LED].brightness, radio_state?1:0); - write_int(&leds[GREEN_LED].blink, radio_state?1:0); - last_radio_state=radio_state; - } -#endif - /* battery events tracking */ - - /* button events tracking */ - ev_get(&ev, 1); - if (ev.type==EV_KEY) { - if (ev.value == 1){ - switch (ev.code) { - case BTN_TOUCH: -#ifdef ENABLE_LCDSAVE - if (g_backlight > 0) && (abs_tm==0) - set_led_backlight(g_current_backlight); - } -#endif - break; - case KEY_SEND: - case KEY_MENU: - case KEY_HOME: - case KEY_BACK: - case KEY_END: - case KEY_POWER: -#ifdef ENABLE_LCDSAVE - if (abs_tm==0) {set_led_backlight(g_current_backlight);} -#endif - switch_led_button(1); - sleep(1); - break; -#ifdef ENABLE_LCDSAVE - case KEY_VOLUMEUP: - case KEY_VOLUMEDOWN: - if (abs_tm==0) { set_led_backlight(g_current_backlight);} - break; -#endif - default: - /*LOGD("keys: code %d, value %d\n", ev.code, ev.value);*/ - sleep(1); - break; - } - } - } -//========================= -#ifdef ENABLE_LCDSAVE - if (g_backlight > 0) { - a_tm = time(NULL); - //D("%ld %ld\n", a_tm, abs_tm); - if ((abs_tm>0) && (a_tm >= abs_tm) && (user_activity_idle())) { - //D("LCD_BACKLIGHT->down brightness\n"); - set_led_backlight(50); - //write_int(&leds[LCD_BACKLIGHT].brightness, 50); - abs_tm = 0; - } - } -#endif - k_tm = time(NULL); - //D("[%ld][%ld][%d][%d %d %d][%d]\n", tm, keys_tm, ev.type, ev.code, ev.value, g_buttons, g_backlight); - if (g_buttons==1) { - if (k_tm == keys_tm || g_backlight == 0){ - switch_led_button(0); - sleep(1); - } - } -//========================= - nanosleep(&t,NULL); //avoid 100% CPU usage by system_server - } - - ev_exit(); - events_ct = 0; - return 0; -} - -void start_events_thread() { - if (events_ct == 0) //ensure only 1 thread - pthread_create(&events_ct, NULL, events_cthread, NULL); - return; -} -//================================================================================================= -static int -set_light_backlight(struct light_device_t* dev, - struct light_state_t const* state) { - int err = 0; - int brightness = rgb_to_brightness(state); - LOGV("%s brightness=%d color=0x%08x", - __func__,brightness, state->color); - pthread_mutex_lock(&g_lock); - set_led_backlight(brightness); - pthread_mutex_unlock(&g_lock); - return err; -} - -static int -set_light_buttons(struct light_device_t* dev, - struct light_state_t const* state) { - int err = 0; - int on = is_lit(state); - pthread_mutex_lock(&g_lock); - LOGV("%s mode=%d color=0x%08x", - __func__,state->flashMode, state->color); - switch_led_button(on); - pthread_mutex_unlock(&g_lock); - return err; -} - -static int -set_speaker_light_locked(struct light_device_t* dev, - struct light_state_t const* state) { - int len; - unsigned int colorRGB; - - colorRGB = state->color & 0xFFFFFF; - - D("@@ %s colorRGB=%08X, state->flashMode:%d\n", __func__, colorRGB, state->flashMode); - - /*if (colorRGB ==0) return 0;*/ - - int red = (colorRGB >> 16)&0xFF; - int green = (colorRGB >> 8)&0xFF; - int blue = (colorRGB) & 0xFF; - int g_blink = 0; - - switch (state->flashMode) { - case LIGHT_FLASH_HARDWARE: - g_blink = 3; - break; - case LIGHT_FLASH_TIMED: - g_blink = 1; - break; - case LIGHT_FLASH_NONE: - g_blink = 0; - break; - default: - LOGE("set_led_state colorRGB=%08X, unknown mode %d\n", - colorRGB, state->flashMode); - break; - } - - if (red) { - D("@@ %s AMBER, blink: %d\n", __func__, g_blink); - write_int(&leds[GREEN_LED].brightness, 0); - write_int(&leds[AMBER_LED].brightness, 1); - write_int(&leds[AMBER_LED].blink, g_blink); - } else if (green) { - D("@@ %s GREEN, blink: %d\n", __func__, g_blink); - write_int(&leds[AMBER_LED].brightness, 0); - write_int(&leds[GREEN_LED].brightness, 1); - write_int(&leds[GREEN_LED].blink, g_blink); - } else { - write_int(&leds[GREEN_LED].brightness, 0); - write_int(&leds[GREEN_LED].blink, 0); - write_int(&leds[AMBER_LED].brightness, 0); - write_int(&leds[AMBER_LED].blink, 0); - } - - return 0; -} - -static int -set_light_battery(struct light_device_t* dev, - struct light_state_t const* state) { - pthread_mutex_lock(&g_lock); - LOGV("%s mode=%d color=0x%08x", - __func__,state->flashMode, state->color); - set_speaker_light_locked(dev, state); - pthread_mutex_unlock(&g_lock); - return 0; -} - -static int -set_light_notifications(struct light_device_t* dev, - struct light_state_t const* state) { - pthread_mutex_lock(&g_lock); - LOGV("%s mode=%d color=0x%08x", - __func__,state->flashMode, state->color); - pthread_mutex_unlock(&g_lock); - return 0; -} - -static int -set_light_attention(struct light_device_t* dev, - struct light_state_t const* state) { - LOGV("%s color=0x%08x mode=0x%08x submode=0x%08x", - __func__, state->color, state->flashMode, state->flashOnMS); - pthread_mutex_lock(&g_lock); -/* -/lights_leo( 252): set_light_attention color=0x00ffffff mode=0x00000002 submode=0x00000003 -/lights_leo( 252): set_light_attention color=0x00000000 mode=0x00000002 submode=0x00000000 -/lights_leo( 252): set_light_attention color=0x00ffffff mode=0x00000002 submode=0x00000007 -/lights_leo( 252): set_light_attention color=0x00ffffff mode=0x00000000 submode=0x00000000 -*/ -#if 0 - if (state->flashMode==2 && state->flashOnMS==7){ - write_int(&leds[GREEN_LED].brightness, 0); - write_int(&leds[AMBER_LED].brightness, 1); - write_int(&leds[AMBER_LED].blink, 2); - } else { - write_int(&leds[AMBER_LED].brightness, 0); - write_int(&leds[GREEN_LED].brightness, 1); - write_int(&leds[GREEN_LED].blink, 4); - } -#endif - pthread_mutex_unlock(&g_lock); - return 0; -} - -static int -set_light_flashlight(struct light_device_t* dev, - struct light_state_t const* state) { - LOGV("%s color=0x%08x mode=0x%08x submode=0x%08x", - __func__, state->color, state->flashMode, state->flashOnMS); - - return 0; -} - -static int -set_light_function(struct light_device_t* dev, - struct light_state_t const* state) { - LOGV("%s color=0x%08x mode=0x%08x submode=0x%08x", - __func__, state->color, state->flashMode, state->flashOnMS); - - return 0; -} - -/** Close the lights device */ -static int -close_lights(struct light_device_t *dev) -{ - int i; - - for (i = 0; i < NUM_LEDS; ++i) { - close_prop(&leds[i].brightness); - close_prop(&leds[i].blink); - } - - if (dev) { - free(dev); - } - return 0; -} - - -/******************************************************************************/ - -/** - * module methods - */ - -/** Open a new instance of a lights device using name */ -static int open_lights(const struct hw_module_t* module, char const* name, - struct hw_device_t** device) -{ - int (*set_light)(struct light_device_t* dev, - struct light_state_t const* state); - - LOGV("%s name=%s", __func__, name); - - if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) { - set_light = set_light_backlight; - } - else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) { - set_light = set_light_buttons; - start_events_thread(); - } - else if (0 == strcmp(LIGHT_ID_BATTERY, name)) { - set_light = set_light_battery; -#ifdef ENABLE_BATTERY_POLL - start_battery_thread(); -#endif - } - else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) { - set_light = set_light_notifications; - } - else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) { - set_light = set_light_attention; - } - else if (0 == strcmp(LIGHT_ID_FLASHLIGHT, name)) { - set_light = set_light_flashlight; - } - else if (0 == strcmp(LIGHT_ID_FUNC, name)) { - set_light = set_light_function; - } - else { - return -EINVAL; - } - - pthread_once(&g_init, init_globals); - - struct light_device_t *dev = malloc(sizeof(struct light_device_t)); - memset(dev, 0, sizeof(*dev)); - - dev->common.tag = HARDWARE_DEVICE_TAG; - dev->common.version = 0; - dev->common.module = (struct hw_module_t*)module; - dev->common.close = (int (*)(struct hw_device_t*))close_lights; - dev->set_light = set_light; - - *device = (struct hw_device_t*)dev; - return 0; -} - - -static struct hw_module_methods_t lights_module_methods = { - .open = open_lights, -}; - -/* - * The lights Module - */ -const struct hw_module_t HAL_MODULE_INFO_SYM = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 1, - .version_minor = 0, - .id = LIGHTS_HARDWARE_MODULE_ID, - .name = "htcleo lights Module", - .author = "Google, Inc.", - .methods = &lights_module_methods, -}; diff --git a/libsensors/AkmSensor.cpp b/libsensors/AkmSensor.cpp deleted file mode 100644 index 6abfca2..0000000 --- a/libsensors/AkmSensor.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "AkmSensor.h" - -/*****************************************************************************/ - -AkmSensor::AkmSensor() -: SensorBase(AKM_DEVICE_NAME, "compass"), - mEnabled(0), - mPendingMask(0), - mInputReader(32) -{ - memset(mPendingEvents, 0, sizeof(mPendingEvents)); - - mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); - mPendingEvents[Accelerometer].sensor = ID_A; - mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; - mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; - - mPendingEvents[MagneticField].version = sizeof(sensors_event_t); - mPendingEvents[MagneticField].sensor = ID_M; - mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD; - mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; - - mPendingEvents[Orientation ].version = sizeof(sensors_event_t); - mPendingEvents[Orientation ].sensor = ID_O; - mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION; - mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH; - - for (int i=0 ; i= numSensors) - return -EINVAL; - - int newState = en ? 1 : 0; - int err = 0; - - if ((uint32_t(newState)<= numSensors) - return -EINVAL; - - if (ns < 0) - return -EINVAL; - - mDelays[what] = ns; - return update_delay(); -#else - return -1; -#endif -} - -int AkmSensor::update_delay() -{ - if (mEnabled) { - uint64_t wanted = -1LLU; - for (int i=0 ; itype; - if (type == EV_ABS) { - processEvent(event->code, event->value); - mInputReader.next(); - } else if (type == EV_SYN) { - int64_t time = timevalToNano(event->time); - for (int j=0 ; count && mPendingMask && jcode); - mInputReader.next(); - } - } - - return numEventReceived; -} - -void AkmSensor::processEvent(int code, int value) -{ - switch (code) { - case EVENT_TYPE_ACCEL_X: - mPendingMask |= 1< -#include -#include -#include - - -#include "nusensors.h" -#include "SensorBase.h" -#include "InputEventReader.h" - -/*****************************************************************************/ - -struct input_event; - -class AkmSensor : public SensorBase { -public: - AkmSensor(); - virtual ~AkmSensor(); - - enum { - Accelerometer = 0, - MagneticField = 1, - Orientation = 2, - numSensors - }; - - virtual int setDelay(int32_t handle, int64_t ns); - virtual int enable(int32_t handle, int enabled); - virtual int readEvents(sensors_event_t* data, int count); - void processEvent(int code, int value); - -private: - int update_delay(); - uint32_t mEnabled; - uint32_t mPendingMask; - InputEventCircularReader mInputReader; - sensors_event_t mPendingEvents[numSensors]; - uint64_t mDelays[numSensors]; -}; - -/*****************************************************************************/ - -#endif // ANDROID_AKM_SENSOR_H diff --git a/libsensors/Android.mk b/libsensors/Android.mk old mode 100644 new mode 100755 index 819929a..1539617 --- a/libsensors/Android.mk +++ b/libsensors/Android.mk @@ -21,22 +21,13 @@ ifneq ($(TARGET_SIMULATOR),true) # hw/..so include $(CLEAR_VARS) -LOCAL_MODULE := sensors.leo +LOCAL_MODULE := sensors.htcleo LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_MODULE_TAGS := optional -LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\" -LOCAL_SRC_FILES := \ - sensors.c \ - nusensors.cpp \ - InputEventReader.cpp \ - SensorBase.cpp \ - LightSensor.cpp \ - ProximitySensor.cpp \ - AkmSensor.cpp - +LOCAL_SRC_FILES := sensors.c LOCAL_SHARED_LIBRARIES := liblog libcutils LOCAL_PRELINK_MODULE := false diff --git a/libsensors/InputEventReader.cpp b/libsensors/InputEventReader.cpp deleted file mode 100644 index 1014f29..0000000 --- a/libsensors/InputEventReader.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include "InputEventReader.h" - -/*****************************************************************************/ - -struct input_event; - -InputEventCircularReader::InputEventCircularReader(size_t numEvents) - : mBuffer(new input_event[numEvents * 2]), - mBufferEnd(mBuffer + numEvents), - mHead(mBuffer), - mCurr(mBuffer), - mFreeSpace(numEvents) -{ -} - -InputEventCircularReader::~InputEventCircularReader() -{ - delete [] mBuffer; -} - -ssize_t InputEventCircularReader::fill(int fd) -{ - size_t numEventsRead = 0; - if (mFreeSpace) { - const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event)); - if (nread<0 || nread % sizeof(input_event)) { - // we got a partial event!! - return nread<0 ? -errno : -EINVAL; - } - - numEventsRead = nread / sizeof(input_event); - if (numEventsRead) { - mHead += numEventsRead; - mFreeSpace -= numEventsRead; - if (mHead > mBufferEnd) { - size_t s = mHead - mBufferEnd; - memcpy(mBuffer, mBufferEnd, s * sizeof(input_event)); - mHead = mBuffer + s; - } - } - } - - return numEventsRead; -} - -ssize_t InputEventCircularReader::readEvent(input_event const** events) -{ - *events = mCurr; - ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace; - return available ? 1 : 0; -} - -void InputEventCircularReader::next() -{ - mCurr++; - mFreeSpace++; - if (mCurr >= mBufferEnd) { - mCurr = mBuffer; - } -} diff --git a/libsensors/InputEventReader.h b/libsensors/InputEventReader.h deleted file mode 100644 index 180aade..0000000 --- a/libsensors/InputEventReader.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_INPUT_EVENT_READER_H -#define ANDROID_INPUT_EVENT_READER_H - -#include -#include -#include -#include - -/*****************************************************************************/ - -struct input_event; - -class InputEventCircularReader -{ - struct input_event* const mBuffer; - struct input_event* const mBufferEnd; - struct input_event* mHead; - struct input_event* mCurr; - ssize_t mFreeSpace; - -public: - InputEventCircularReader(size_t numEvents); - ~InputEventCircularReader(); - ssize_t fill(int fd); - ssize_t readEvent(input_event const** events); - void next(); -}; - -/*****************************************************************************/ - -#endif // ANDROID_INPUT_EVENT_READER_H diff --git a/libsensors/LightSensor.cpp b/libsensors/LightSensor.cpp deleted file mode 100644 index 119978e..0000000 --- a/libsensors/LightSensor.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "LightSensor.h" - -/*****************************************************************************/ - -LightSensor::LightSensor() - : SensorBase(LS_DEVICE_NAME, "lightsensor-level"), - mEnabled(0), - mInputReader(4), - mHasPendingEvent(false) -{ - mPendingEvent.version = sizeof(sensors_event_t); - mPendingEvent.sensor = ID_L; - mPendingEvent.type = SENSOR_TYPE_LIGHT; - memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); - - open_device(); - - int flags = 0; - if (!ioctl(dev_fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) { - if (flags) { - mEnabled = 1; - setInitialState(); - } - } - - if (!mEnabled) { - close_device(); - } -} - -LightSensor::~LightSensor() { -} - -int LightSensor::setInitialState() { - struct input_absinfo absinfo; - if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_LIGHT), &absinfo)) { - mPendingEvent.light = indexToValue(absinfo.value); - mHasPendingEvent = true; - } - return 0; -} - -int LightSensor::enable(int32_t, int en) { - int flags = en ? 1 : 0; - int err = 0; - if (flags != mEnabled) { - if (!mEnabled) { - open_device(); - } - err = ioctl(dev_fd, LIGHTSENSOR_IOCTL_ENABLE, &flags); - err = err<0 ? -errno : 0; - LOGE_IF(err, "LIGHTSENSOR_IOCTL_ENABLE failed (%s)", strerror(-err)); - if (!err) { - mEnabled = en ? 1 : 0; - if (en) { - setInitialState(); - } - } - if (!mEnabled) { - close_device(); - } - } - return err; -} - -bool LightSensor::hasPendingEvents() const { - return mHasPendingEvent; -} - -int LightSensor::readEvents(sensors_event_t* data, int count) -{ - if (count < 1) - return -EINVAL; - - if (mHasPendingEvent) { - mHasPendingEvent = false; - mPendingEvent.timestamp = getTimestamp(); - *data = mPendingEvent; - return mEnabled ? 1 : 0; - } - - ssize_t n = mInputReader.fill(data_fd); - if (n < 0) - return n; - - int numEventReceived = 0; - input_event const* event; - - while (count && mInputReader.readEvent(&event)) { - int type = event->type; - if (type == EV_ABS) { - if (event->code == EVENT_TYPE_LIGHT) { - if (event->value != -1) { - // FIXME: not sure why we're getting -1 sometimes - mPendingEvent.light = indexToValue(event->value); - } - } - } else if (type == EV_SYN) { - mPendingEvent.timestamp = timevalToNano(event->time); - if (mEnabled) { - *data++ = mPendingEvent; - count--; - numEventReceived++; - } - } else { - LOGE("LightSensor: unknown event (type=%d, code=%d)", - type, event->code); - } - mInputReader.next(); - } - - return numEventReceived; -} - -float LightSensor::indexToValue(size_t index) const -{ - static const float luxValues[8] = { - 10.0, 160.0, 225.0, 320.0, - 640.0, 1280.0, 2600.0, 10240.0 - }; - - const size_t maxIndex = sizeof(luxValues)/sizeof(*luxValues) - 1; - if (index > maxIndex) - index = maxIndex; - return luxValues[index]; -} diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h deleted file mode 100644 index 13591a3..0000000 --- a/libsensors/LightSensor.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LIGHT_SENSOR_H -#define ANDROID_LIGHT_SENSOR_H - -#include -#include -#include -#include - -#include "nusensors.h" -#include "SensorBase.h" -#include "InputEventReader.h" - -/*****************************************************************************/ - -struct input_event; - -class LightSensor : public SensorBase { - int mEnabled; - InputEventCircularReader mInputReader; - sensors_event_t mPendingEvent; - bool mHasPendingEvent; - - float indexToValue(size_t index) const; - int setInitialState(); - -public: - LightSensor(); - virtual ~LightSensor(); - virtual int readEvents(sensors_event_t* data, int count); - virtual bool hasPendingEvents() const; - virtual int enable(int32_t handle, int enabled); -}; - -/*****************************************************************************/ - -#endif // ANDROID_LIGHT_SENSOR_H diff --git a/libsensors/MODULE_LICENSE_APACHE2 b/libsensors/MODULE_LICENSE_APACHE2 old mode 100644 new mode 100755 diff --git a/libsensors/NOTICE b/libsensors/NOTICE old mode 100644 new mode 100755 diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp deleted file mode 100644 index abd8e6b..0000000 --- a/libsensors/ProximitySensor.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "ProximitySensor.h" - -/*****************************************************************************/ - -ProximitySensor::ProximitySensor() - : SensorBase(CM_DEVICE_NAME, "proximity"), - mEnabled(0), - mInputReader(4), - mHasPendingEvent(false) -{ - mPendingEvent.version = sizeof(sensors_event_t); - mPendingEvent.sensor = ID_P; - mPendingEvent.type = SENSOR_TYPE_PROXIMITY; - memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); - - open_device(); - - int flags = 0; - if (!ioctl(dev_fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) { - mEnabled = 1; - if (flags) { - setInitialState(); - } - } - if (!mEnabled) { - close_device(); - } -} - -ProximitySensor::~ProximitySensor() { -} - -int ProximitySensor::setInitialState() { - struct input_absinfo absinfo; - if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PROXIMITY), &absinfo)) { - // make sure to report an event immediately - mHasPendingEvent = true; - mPendingEvent.distance = indexToValue(absinfo.value); - } - return 0; -} - -int ProximitySensor::enable(int32_t, int en) { - int newState = en ? 1 : 0; - int err = 0; - if (newState != mEnabled) { - if (!mEnabled) { - open_device(); - } - int flags = newState; - err = ioctl(dev_fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags); - err = err<0 ? -errno : 0; - LOGE_IF(err, "CAPELLA_CM3602_IOCTL_ENABLE failed (%s)", strerror(-err)); - if (!err) { - mEnabled = newState; - if (en) { - setInitialState(); - } - } - if (!mEnabled) { - close_device(); - } - } - return err; -} - -bool ProximitySensor::hasPendingEvents() const { - return mHasPendingEvent; -} - -int ProximitySensor::readEvents(sensors_event_t* data, int count) -{ - if (count < 1) - return -EINVAL; - - if (mHasPendingEvent) { - mHasPendingEvent = false; - mPendingEvent.timestamp = getTimestamp(); - *data = mPendingEvent; - return mEnabled ? 1 : 0; - } - - ssize_t n = mInputReader.fill(data_fd); - if (n < 0) - return n; - - int numEventReceived = 0; - input_event const* event; - - while (count && mInputReader.readEvent(&event)) { - int type = event->type; - if (type == EV_ABS) { - if (event->code == EVENT_TYPE_PROXIMITY) { - mPendingEvent.distance = indexToValue(event->value); - } - } else if (type == EV_SYN) { - mPendingEvent.timestamp = timevalToNano(event->time); - if (mEnabled) { - *data++ = mPendingEvent; - count--; - numEventReceived++; - } - } else { - LOGE("ProximitySensor: unknown event (type=%d, code=%d)", - type, event->code); - } - mInputReader.next(); - } - - return numEventReceived; -} - -float ProximitySensor::indexToValue(size_t index) const -{ - return index * PROXIMITY_THRESHOLD_CM; -} diff --git a/libsensors/ProximitySensor.h b/libsensors/ProximitySensor.h deleted file mode 100644 index 650035a..0000000 --- a/libsensors/ProximitySensor.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_PROXIMITY_SENSOR_H -#define ANDROID_PROXIMITY_SENSOR_H - -#include -#include -#include -#include - -#include "nusensors.h" -#include "SensorBase.h" -#include "InputEventReader.h" - -/*****************************************************************************/ - -struct input_event; - -class ProximitySensor : public SensorBase { - int mEnabled; - InputEventCircularReader mInputReader; - sensors_event_t mPendingEvent; - bool mHasPendingEvent; - - int setInitialState(); - float indexToValue(size_t index) const; - -public: - ProximitySensor(); - virtual ~ProximitySensor(); - virtual int readEvents(sensors_event_t* data, int count); - virtual bool hasPendingEvents() const; - virtual int enable(int32_t handle, int enabled); -}; - -/*****************************************************************************/ - -#endif // ANDROID_PROXIMITY_SENSOR_H diff --git a/libsensors/SensorBase.cpp b/libsensors/SensorBase.cpp deleted file mode 100644 index e0554e4..0000000 --- a/libsensors/SensorBase.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "SensorBase.h" - -/*****************************************************************************/ - -SensorBase::SensorBase( - const char* dev_name, - const char* data_name) - : dev_name(dev_name), data_name(data_name), - dev_fd(-1), data_fd(-1) -{ - data_fd = openInput(data_name); -} - -SensorBase::~SensorBase() { - if (data_fd >= 0) { - close(data_fd); - } - if (dev_fd >= 0) { - close(dev_fd); - } -} - -int SensorBase::open_device() { - if (dev_fd<0 && dev_name) { - dev_fd = open(dev_name, O_RDONLY); - LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno)); - } - return 0; -} - -int SensorBase::close_device() { - if (dev_fd >= 0) { - close(dev_fd); - dev_fd = -1; - } - return 0; -} - -int SensorBase::getFd() const { - return data_fd; -} - -int SensorBase::setDelay(int32_t handle, int64_t ns) { - return 0; -} - -bool SensorBase::hasPendingEvents() const { - return false; -} - -int64_t SensorBase::getTimestamp() { - struct timespec t; - t.tv_sec = t.tv_nsec = 0; - clock_gettime(CLOCK_MONOTONIC, &t); - return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec; -} - -int SensorBase::openInput(const char* inputName) { - int fd = -1; - const char *dirname = "/dev/input"; - char devname[PATH_MAX]; - char *filename; - DIR *dir; - struct dirent *de; - dir = opendir(dirname); - if(dir == NULL) - return -1; - strcpy(devname, dirname); - filename = devname + strlen(devname); - *filename++ = '/'; - while((de = readdir(dir))) { - if(de->d_name[0] == '.' && - (de->d_name[1] == '\0' || - (de->d_name[1] == '.' && de->d_name[2] == '\0'))) - continue; - strcpy(filename, de->d_name); - fd = open(devname, O_RDONLY); - if (fd>=0) { - char name[80]; - if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { - name[0] = '\0'; - } - if (!strcmp(name, inputName)) { - break; - } else { - close(fd); - fd = -1; - } - } - } - closedir(dir); - LOGE_IF(fd<0, "couldn't find '%s' input device", inputName); - return fd; -} diff --git a/libsensors/SensorBase.h b/libsensors/SensorBase.h deleted file mode 100644 index c8cc276..0000000 --- a/libsensors/SensorBase.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SENSOR_BASE_H -#define ANDROID_SENSOR_BASE_H - -#include -#include -#include -#include - - -/*****************************************************************************/ - -struct sensors_event_t; - -class SensorBase { -protected: - const char* dev_name; - const char* data_name; - int dev_fd; - int data_fd; - - static int openInput(const char* inputName); - static int64_t getTimestamp(); - - - static int64_t timevalToNano(timeval const& t) { - return t.tv_sec*1000000000LL + t.tv_usec*1000; - } - - int open_device(); - int close_device(); - -public: - SensorBase( - const char* dev_name, - const char* data_name); - - virtual ~SensorBase(); - - virtual int readEvents(sensors_event_t* data, int count) = 0; - virtual bool hasPendingEvents() const; - virtual int getFd() const; - virtual int setDelay(int32_t handle, int64_t ns); - virtual int enable(int32_t handle, int enabled) = 0; -}; - -/*****************************************************************************/ - -#endif // ANDROID_SENSOR_BASE_H diff --git a/libsensors/nusensors.cpp b/libsensors/nusensors.cpp deleted file mode 100644 index 248acc5..0000000 --- a/libsensors/nusensors.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include "nusensors.h" -#include "LightSensor.h" -#include "ProximitySensor.h" -#include "AkmSensor.h" - -/*****************************************************************************/ - -struct sensors_poll_context_t { - struct sensors_poll_device_t device; // must be first - - sensors_poll_context_t(); - ~sensors_poll_context_t(); - int activate(int handle, int enabled); - int setDelay(int handle, int64_t ns); - int pollEvents(sensors_event_t* data, int count); - -private: - enum { - light = 0, - proximity = 1, - akm = 2, - numSensorDrivers, - numFds, - }; - - static const size_t wake = numFds - 1; - static const char WAKE_MESSAGE = 'W'; - struct pollfd mPollFds[numFds]; - int mWritePipeFd; - SensorBase* mSensors[numSensorDrivers]; - - int handleToDriver(int handle) const { - switch (handle) { - case ID_A: - case ID_M: - case ID_O: - return akm; - case ID_P: - return proximity; - case ID_L: - return light; - } - return -EINVAL; - } -}; - -/*****************************************************************************/ - -sensors_poll_context_t::sensors_poll_context_t() -{ - mSensors[light] = new LightSensor(); - mPollFds[light].fd = mSensors[light]->getFd(); - mPollFds[light].events = POLLIN; - mPollFds[light].revents = 0; - - mSensors[proximity] = new ProximitySensor(); - mPollFds[proximity].fd = mSensors[proximity]->getFd(); - mPollFds[proximity].events = POLLIN; - mPollFds[proximity].revents = 0; - - mSensors[akm] = new AkmSensor(); - mPollFds[akm].fd = mSensors[akm]->getFd(); - mPollFds[akm].events = POLLIN; - mPollFds[akm].revents = 0; - - int wakeFds[2]; - int result = pipe(wakeFds); - LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno)); - fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); - fcntl(wakeFds[1], F_SETFL, O_NONBLOCK); - mWritePipeFd = wakeFds[1]; - - mPollFds[wake].fd = wakeFds[0]; - mPollFds[wake].events = POLLIN; - mPollFds[wake].revents = 0; -} - -sensors_poll_context_t::~sensors_poll_context_t() { - for (int i=0 ; ienable(handle, enabled); - if (enabled && !err) { - const char wakeMessage(WAKE_MESSAGE); - int result = write(mWritePipeFd, &wakeMessage, 1); - LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno)); - } - return err; -} - -int sensors_poll_context_t::setDelay(int handle, int64_t ns) { - - int index = handleToDriver(handle); - if (index < 0) return index; - return mSensors[index]->setDelay(handle, ns); -} - -int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count) -{ - int nbEvents = 0; - int n = 0; - - do { - // see if we have some leftover from the last poll() - for (int i=0 ; count && ihasPendingEvents())) { - int nb = sensor->readEvents(data, count); - if (nb < count) { - // no more data for this sensor - mPollFds[i].revents = 0; - } - count -= nb; - nbEvents += nb; - data += nb; - } - } - - if (count) { - // we still have some room, so try to see if we can get - // some events immediately or just wait if we don't have - // anything to return - n = poll(mPollFds, numFds, nbEvents ? 0 : -1); - if (n<0) { - LOGE("poll() failed (%s)", strerror(errno)); - return -errno; - } - if (mPollFds[wake].revents & POLLIN) { - char msg; - int result = read(mPollFds[wake].fd, &msg, 1); - LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno)); - LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg)); - mPollFds[wake].revents = 0; - } - } - // if we have events and space, go read them - } while (n && count); - - return nbEvents; -} - -/*****************************************************************************/ - -static int poll__close(struct hw_device_t *dev) -{ - sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; - if (ctx) { - delete ctx; - } - return 0; -} - -static int poll__activate(struct sensors_poll_device_t *dev, - int handle, int enabled) { - sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; - return ctx->activate(handle, enabled); -} - -static int poll__setDelay(struct sensors_poll_device_t *dev, - int handle, int64_t ns) { - sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; - return ctx->setDelay(handle, ns); -} - -static int poll__poll(struct sensors_poll_device_t *dev, - sensors_event_t* data, int count) { - sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; - return ctx->pollEvents(data, count); -} - -/*****************************************************************************/ - -int init_nusensors(hw_module_t const* module, hw_device_t** device) -{ - int status = -EINVAL; - - sensors_poll_context_t *dev = new sensors_poll_context_t(); - memset(&dev->device, 0, sizeof(sensors_poll_device_t)); - - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; - dev->device.common.module = const_cast(module); - dev->device.common.close = poll__close; - dev->device.activate = poll__activate; - dev->device.setDelay = poll__setDelay; - dev->device.poll = poll__poll; - - *device = &dev->device.common; - status = 0; - return status; -} diff --git a/libsensors/nusensors.h b/libsensors/nusensors.h deleted file mode 100644 index f1de58d..0000000 --- a/libsensors/nusensors.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SENSORS_H -#define ANDROID_SENSORS_H - -#include -#include -#include -#include - -#include - -#include -#include - -__BEGIN_DECLS - -/*****************************************************************************/ - -int init_nusensors(hw_module_t const* module, hw_device_t** device); - -/*****************************************************************************/ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) - -#define ID_A (0) -#define ID_M (1) -#define ID_O (2) -#define ID_P (3) -#define ID_L (4) - -/*****************************************************************************/ - -/* - * The SENSORS Module - */ - -/* the CM3602 is a binary proximity sensor that triggers around 9 cm on - * this hardware */ -#define PROXIMITY_THRESHOLD_CM 9.0f - -/*****************************************************************************/ - -#define AKM_DEVICE_NAME "/dev/akm8973_aot" -#define CM_DEVICE_NAME "/dev/cm3602" -#define LS_DEVICE_NAME "/dev/lightsensor" - -#define EVENT_TYPE_ACCEL_X ABS_X -#define EVENT_TYPE_ACCEL_Y ABS_Z -#define EVENT_TYPE_ACCEL_Z ABS_Y -#define EVENT_TYPE_ACCEL_STATUS ABS_WHEEL - -#define EVENT_TYPE_YAW ABS_RX -#define EVENT_TYPE_PITCH ABS_RY -#define EVENT_TYPE_ROLL ABS_RZ -#define EVENT_TYPE_ORIENT_STATUS ABS_RUDDER - -#define EVENT_TYPE_MAGV_X ABS_HAT0X -#define EVENT_TYPE_MAGV_Y ABS_HAT0Y -#define EVENT_TYPE_MAGV_Z ABS_BRAKE - -#define EVENT_TYPE_TEMPERATURE ABS_THROTTLE -#define EVENT_TYPE_STEP_COUNT ABS_GAS -#define EVENT_TYPE_PROXIMITY ABS_DISTANCE -#define EVENT_TYPE_LIGHT ABS_MISC - -// 720 LSG = 1G -#define LSG (720.0f) - - -// conversion of acceleration data to SI units (m/s^2) -#define CONVERT_A (GRAVITY_EARTH / LSG) -#define CONVERT_A_X (-CONVERT_A) -#define CONVERT_A_Y (CONVERT_A) -#define CONVERT_A_Z (-CONVERT_A) - -// conversion of magnetic data to uT units -#define CONVERT_M (1.0f/16.0f) -#define CONVERT_M_X (-CONVERT_M) -#define CONVERT_M_Y (-CONVERT_M) -#define CONVERT_M_Z (CONVERT_M) - -#define CONVERT_O (1.0f) -#define CONVERT_O_Y (CONVERT_O) -#define CONVERT_O_P (CONVERT_O) -#define CONVERT_O_R (-CONVERT_O) - -#define SENSOR_STATE_MASK (0x7FFF) - -/*****************************************************************************/ - -__END_DECLS - -#endif // ANDROID_SENSORS_H diff --git a/libsensors/sensors.c b/libsensors/sensors.c old mode 100644 new mode 100755 index 12a9368..a39b457 --- a/libsensors/sensors.c +++ b/libsensors/sensors.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Danijel Posilovic - dan1j3l * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,16 +15,91 @@ * limitations under the License. */ -#include +#define LOG_TAG "Sensors" -#include "nusensors.h" +#define LOG_NDEBUG 1 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#define __MAX(a,b) ((a)>=(b)?(a):(b)) /*****************************************************************************/ +#define MAX_NUM_SENSORS 6 + +#define SUPPORTED_SENSORS ((1<d_name[0] == '.' && + (de->d_name[1] == '\0' || + (de->d_name[1] == '.' && de->d_name[2] == '\0'))) + continue; + strcpy(filename, de->d_name); + fd = open(devname, mode); + if (fd>=0) { + char name[80]; + if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { + name[0] = '\0'; + } + if (!strcmp(name, "compass")) { + LOGV("using %s (name=%s)", devname, name); + *akm_fd = fd; + } + else if (!strcmp(name, "proximity")) { + LOGV("using %s (name=%s)", devname, name); + *p_fd = fd; + } + else if (!strcmp(name, "lightsensor-level")) { + LOGV("using %s (name=%s)", devname, name); + *l_fd = fd; + } + else + close(fd); + } + } + closedir(dir); + + fd = 0; + if (*akm_fd < 0) { + LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno)); + fd = -1; + } + if (*p_fd < 0) { + LOGE("Couldn't find or open 'proximity' driver (%s)", strerror(errno)); + fd = -1; + } + if (*l_fd < 0) { + LOGE("Couldn't find or open 'light' driver (%s)", strerror(errno)); + fd = -1; + } + return fd; +} + +static int open_akm(struct sensors_control_context_t* dev) +{ + if (dev->akmd_fd < 0) { + dev->akmd_fd = open(AKM_DEVICE_NAME, O_RDONLY); + LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd); + LOGE_IF(dev->akmd_fd<0, "Couldn't open %s (%s)", + AKM_DEVICE_NAME, strerror(errno)); + if (dev->akmd_fd >= 0) { + dev->active_sensors &= ~SENSORS_AKM_GROUP; + } + } + return dev->akmd_fd; +} + +static void close_akm(struct sensors_control_context_t* dev) +{ + if (dev->akmd_fd >= 0) { + LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd); + close(dev->akmd_fd); + dev->akmd_fd = -1; + } +} + +static uint32_t read_akm_sensors_state(int fd) +{ + short flags; + uint32_t sensors = 0; + // read the actual value of all sensors + if (!ioctl(fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) { + if (flags) sensors |= SENSORS_AKM_ORIENTATION; + else sensors &= ~SENSORS_AKM_ORIENTATION; + } + if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) { + if (flags) sensors |= SENSORS_AKM_ACCELERATION; + else sensors &= ~SENSORS_AKM_ACCELERATION; + } + if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) { + if (flags) sensors |= SENSORS_AKM_TEMPERATURE; + else sensors &= ~SENSORS_AKM_TEMPERATURE; + } + if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) { + if (flags) sensors |= SENSORS_AKM_MAGNETIC_FIELD; + else sensors &= ~SENSORS_AKM_MAGNETIC_FIELD; + } + return sensors; +} + +static uint32_t enable_disable_akm(struct sensors_control_context_t *dev, + uint32_t active, uint32_t sensors, + uint32_t mask) +{ + uint32_t now_active_akm_sensors; + + int fd = open_akm(dev); + if (fd < 0) + return 0; + + LOGV("(before) akm sensors = %08x, real = %08x", + sensors, read_akm_sensors_state(fd)); + + short flags; + if (mask & SENSORS_AKM_ORIENTATION) { + flags = (sensors & SENSORS_AKM_ORIENTATION) ? 1 : 0; + if (ioctl(fd, ECS_IOCTL_APP_SET_MFLAG, &flags) < 0) { + LOGE("ECS_IOCTL_APP_SET_MFLAG error (%s)", strerror(errno)); + } + } + if (mask & SENSORS_AKM_ACCELERATION) { + flags = (sensors & SENSORS_AKM_ACCELERATION) ? 1 : 0; + if (ioctl(fd, ECS_IOCTL_APP_SET_AFLAG, &flags) < 0) { + LOGE("ECS_IOCTL_APP_SET_AFLAG error (%s)", strerror(errno)); + } + } + if (mask & SENSORS_AKM_TEMPERATURE) { + flags = (sensors & SENSORS_AKM_TEMPERATURE) ? 1 : 0; + if (ioctl(fd, ECS_IOCTL_APP_SET_TFLAG, &flags) < 0) { + LOGE("ECS_IOCTL_APP_SET_TFLAG error (%s)", strerror(errno)); + } + } + if (mask & SENSORS_AKM_MAGNETIC_FIELD) { + flags = (sensors & SENSORS_AKM_MAGNETIC_FIELD) ? 1 : 0; + if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) { + LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno)); + } + } + + now_active_akm_sensors = read_akm_sensors_state(fd); + + LOGV("(after) akm sensors = %08x, real = %08x", + sensors, now_active_akm_sensors); + + if (!sensors) + close_akm(dev); + + return now_active_akm_sensors; +} + +static uint32_t read_cm_sensors_state(int fd) +{ + int flags; + uint32_t sensors = 0; + // read the actual value of all sensors + if (!ioctl(fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) { + if (flags) sensors |= SENSORS_CM_PROXIMITY; + else sensors &= ~SENSORS_CM_PROXIMITY; + } + + return sensors; +} + +static int open_cm(struct sensors_control_context_t* dev) +{ + if (dev->cmd_fd < 0) { + dev->cmd_fd = open(CM_DEVICE_NAME, O_RDONLY); + LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd); + LOGE_IF(dev->cmd_fd<0, "Couldn't open %s (%s)", + CM_DEVICE_NAME, strerror(errno)); + if (dev->cmd_fd >= 0) { + dev->active_sensors &= ~SENSORS_CM_GROUP; + } + } + return dev->cmd_fd; +} + +static void close_cm(struct sensors_control_context_t* dev) +{ + if (dev->cmd_fd >= 0) { + LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd); + close(dev->cmd_fd); + dev->cmd_fd = -1; + } +} + +static int enable_disable_cm(struct sensors_control_context_t *dev, + uint32_t active, uint32_t sensors, uint32_t mask) +{ + int rc = 0; + uint32_t now_active_cm_sensors; + int fd = open_cm(dev); + + if (fd < 0) { + LOGE("Couldn't open %s (%s)", CM_DEVICE_NAME, strerror(errno)); + return 0; + } + + LOGV("(before) cm sensors = %08x, real = %08x", + sensors, read_cm_sensors_state(fd)); + + if (mask & SENSORS_CM_PROXIMITY) { + int flags = (sensors & SENSORS_CM_PROXIMITY) ? 1 : 0; + rc = ioctl(fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags); + if (rc < 0) + LOGE("CAPELLA_CM3602_IOCTL_ENABLE error (%s)", strerror(errno)); + } + + now_active_cm_sensors = read_cm_sensors_state(fd); + + LOGV("(after) cm sensors = %08x, real = %08x", + sensors, now_active_cm_sensors); + + return now_active_cm_sensors; +} + +static uint32_t read_ls_sensors_state(int fd) +{ + int flags; + uint32_t sensors = 0; + // read the actual value of all sensors + if (!ioctl(fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) { + if (flags) sensors |= SENSORS_LIGHT; + else sensors &= ~SENSORS_LIGHT; + } + + return sensors; +} + +static int open_ls(struct sensors_control_context_t* dev) +{ + if (dev->lsd_fd < 0) { + dev->lsd_fd = open(LS_DEVICE_NAME, O_RDONLY); + LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd); + LOGE_IF(dev->lsd_fd<0, "Couldn't open %s (%s)", + LS_DEVICE_NAME, strerror(errno)); + if (dev->lsd_fd >= 0) { + dev->active_sensors &= ~SENSORS_LIGHT_GROUP; + } + } + return dev->lsd_fd; +} + +static void close_ls(struct sensors_control_context_t* dev) +{ + if (dev->lsd_fd >= 0) { + LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd); + close(dev->lsd_fd); + dev->lsd_fd = -1; + } +} + +static int enable_disable_ls(struct sensors_control_context_t *dev, + uint32_t active, uint32_t sensors, uint32_t mask) +{ + int rc = 0; + uint32_t now_active_ls_sensors; + int fd = open_ls(dev); + + if (fd < 0) { + LOGE("Couldn't open %s (%s)", LS_DEVICE_NAME, strerror(errno)); + return 0; + } + + LOGV("(before) ls sensors = %08x, real = %08x", + sensors, read_ls_sensors_state(fd)); + + if (mask & SENSORS_LIGHT) { + int flags = (sensors & SENSORS_LIGHT) ? 1 : 0; + rc = ioctl(fd, LIGHTSENSOR_IOCTL_ENABLE, &flags); + if (rc < 0) + LOGE("LIGHTSENSOR_IOCTL_ENABLE error (%s)", strerror(errno)); + } + + now_active_ls_sensors = read_ls_sensors_state(fd); + + LOGV("(after) ls sensors = %08x, real = %08x", + sensors, now_active_ls_sensors); + + return now_active_ls_sensors; +} + +/*****************************************************************************/ + +static native_handle_t* control__open_data_source(struct sensors_control_context_t *dev) +{ + native_handle_t* handle; + int akm_fd, p_fd, l_fd; + + if (open_inputs(O_RDONLY, &akm_fd, &p_fd, &l_fd) < 0 || + akm_fd < 0 || p_fd < 0 || l_fd < 0) { + return NULL; + } + + handle = native_handle_create(3, 0); + handle->data[0] = akm_fd; + handle->data[1] = p_fd; + handle->data[2] = l_fd; + + return handle; +} + +static int control__activate(struct sensors_control_context_t *dev, + int handle, int enabled) +{ + if ((handle < SENSORS_HANDLE_BASE) || + (handle >= SENSORS_HANDLE_BASE+MAX_NUM_SENSORS)) + return -1; + + uint32_t mask = (1 << handle); + uint32_t sensors = enabled ? mask : 0; + + uint32_t active = dev->active_sensors; + uint32_t new_sensors = (active & ~mask) | (sensors & mask); + uint32_t changed = active ^ new_sensors; + + if (changed) { + if (!active && new_sensors) + // force all sensors to be updated + changed = SUPPORTED_SENSORS; + + dev->active_sensors = + enable_disable_akm(dev, + active & SENSORS_AKM_GROUP, + new_sensors & SENSORS_AKM_GROUP, + changed & SENSORS_AKM_GROUP) | + enable_disable_cm(dev, + active & SENSORS_CM_GROUP, + new_sensors & SENSORS_CM_GROUP, + changed & SENSORS_CM_GROUP) | + enable_disable_ls(dev, + active & SENSORS_LIGHT_GROUP, + new_sensors & SENSORS_LIGHT_GROUP, + changed & SENSORS_LIGHT_GROUP); + } + + return 0; +} + +static int control__set_delay(struct sensors_control_context_t *dev, int32_t ms) +{ +#ifdef ECS_IOCTL_APP_SET_DELAY + if (dev->akmd_fd <= 0) { + return -1; + } + short delay = ms; + if (!ioctl(dev->akmd_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) { + return -errno; + } + return 0; +#else + return -1; +#endif +} + +static int control__wake(struct sensors_control_context_t *dev) +{ + int err = 0; + int akm_fd, p_fd, l_fd; + if (open_inputs(O_RDWR, &akm_fd, &p_fd, &l_fd) < 0 || + akm_fd < 0 || p_fd < 0 || l_fd < 0) { + return -1; + } + + struct input_event event[1]; + event[0].type = EV_SYN; + event[0].code = SYN_CONFIG; + event[0].value = 0; + + err = write(akm_fd, event, sizeof(event)); + LOGV_IF(err<0, "control__wake(compass), fd=%d (%s)", + akm_fd, strerror(errno)); + close(akm_fd); + + err = write(p_fd, event, sizeof(event)); + LOGV_IF(err<0, "control__wake(proximity), fd=%d (%s)", + p_fd, strerror(errno)); + close(p_fd); + + err = write(l_fd, event, sizeof(event)); + LOGV_IF(err<0, "control__wake(light), fd=%d (%s)", + l_fd, strerror(errno)); + close(l_fd); + + return err; +} + +/*****************************************************************************/ + +static int data__data_open(struct sensors_data_context_t *dev, native_handle_t* handle) +{ + int i; + struct input_absinfo absinfo; + memset(&dev->sensors, 0, sizeof(dev->sensors)); + + for (i = 0; i < MAX_NUM_SENSORS; i++) { + // by default all sensors have high accuracy + // (we do this because we don't get an update if the value doesn't + // change). + dev->sensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH; + } + + dev->sensors[ID_A].sensor = SENSOR_TYPE_ACCELEROMETER; + dev->sensors[ID_M].sensor = SENSOR_TYPE_MAGNETIC_FIELD; + dev->sensors[ID_O].sensor = SENSOR_TYPE_ORIENTATION; + dev->sensors[ID_T].sensor = SENSOR_TYPE_TEMPERATURE; + dev->sensors[ID_P].sensor = SENSOR_TYPE_PROXIMITY; + dev->sensors[ID_L].sensor = SENSOR_TYPE_LIGHT; + + dev->events_fd[0] = dup(handle->data[0]); + dev->events_fd[1] = dup(handle->data[1]); + dev->events_fd[2] = dup(handle->data[2]); + LOGV("data__data_open: compass fd = %d", handle->data[0]); + LOGV("data__data_open: proximity fd = %d", handle->data[1]); + LOGV("data__data_open: light fd = %d", handle->data[2]); + // Framework will close the handle + native_handle_delete(handle); + + dev->pendingSensors = 0; + if (!ioctl(dev->events_fd[1], EVIOCGABS(ABS_DISTANCE), &absinfo)) { + LOGV("proximity sensor initial value %d\n", absinfo.value); + dev->pendingSensors |= SENSORS_CM_PROXIMITY; + // FIXME: we should save here absinfo.{minimum, maximum, etc} + // and use them to scale the return value according to + // the sensor description. + dev->sensors[ID_P].distance = (float)absinfo.value; + } + else LOGE("Cannot get proximity sensor initial value: %s\n", + strerror(errno)); + + return 0; +} + +static int data__data_close(struct sensors_data_context_t *dev) +{ + if (dev->events_fd[0] >= 0) { + //LOGV("(data close) about to close compass fd=%d", dev->events_fd[0]); + close(dev->events_fd[0]); + dev->events_fd[0] = -1; + } + if (dev->events_fd[1] >= 0) { + //LOGV("(data close) about to close proximity fd=%d", dev->events_fd[1]); + close(dev->events_fd[1]); + dev->events_fd[1] = -1; + } + if (dev->events_fd[2] >= 0) { + //LOGV("(data close) about to close light fd=%d", dev->events_fd[1]); + close(dev->events_fd[2]); + dev->events_fd[2] = -1; + } + return 0; +} + +static int pick_sensor(struct sensors_data_context_t *dev, + sensors_data_t* values) +{ + uint32_t mask = SUPPORTED_SENSORS; + while (mask) { + uint32_t i = 31 - __builtin_clz(mask); + mask &= ~(1<pendingSensors & (1<pendingSensors &= ~(1<sensors[i]; + values->sensor = id_to_sensor[i]; + LOGV_IF(0, "%d [%f, %f, %f]", + values->sensor, + values->vector.x, + values->vector.y, + values->vector.z); + return i; + } + } + + LOGE("no sensor to return: pendingSensors = %08x", dev->pendingSensors); + return -1; +} + +static uint32_t data__poll_process_akm_abs(struct sensors_data_context_t *dev, + int fd __attribute__((unused)), + struct input_event *event) +{ + uint32_t new_sensors = 0; + if (event->type == EV_ABS) { + LOGV("compass type: %d code: %d value: %-5d time: %ds", + event->type, event->code, event->value, + (int)event->time.tv_sec); + switch (event->code) { + case EVENT_TYPE_ACCEL_X: + new_sensors |= SENSORS_AKM_ACCELERATION; + dev->sensors[ID_A].acceleration.x = event->value * CONVERT_A_X; + break; + case EVENT_TYPE_ACCEL_Y: + new_sensors |= SENSORS_AKM_ACCELERATION; + dev->sensors[ID_A].acceleration.y = event->value * CONVERT_A_Y; + break; + case EVENT_TYPE_ACCEL_Z: + new_sensors |= SENSORS_AKM_ACCELERATION; + dev->sensors[ID_A].acceleration.z = event->value * CONVERT_A_Z; + break; + case EVENT_TYPE_MAGV_X: + new_sensors |= SENSORS_AKM_MAGNETIC_FIELD; + dev->sensors[ID_M].magnetic.x = event->value * CONVERT_M_X; + break; + case EVENT_TYPE_MAGV_Y: + new_sensors |= SENSORS_AKM_MAGNETIC_FIELD; + dev->sensors[ID_M].magnetic.y = event->value * CONVERT_M_Y; + break; + case EVENT_TYPE_MAGV_Z: + new_sensors |= SENSORS_AKM_MAGNETIC_FIELD; + dev->sensors[ID_M].magnetic.z = event->value * CONVERT_M_Z; + break; + case EVENT_TYPE_YAW: + new_sensors |= SENSORS_AKM_ORIENTATION; + dev->sensors[ID_O].orientation.azimuth = event->value; + break; + case EVENT_TYPE_PITCH: + new_sensors |= SENSORS_AKM_ORIENTATION; + dev->sensors[ID_O].orientation.pitch = event->value; + break; + case EVENT_TYPE_ROLL: + new_sensors |= SENSORS_AKM_ORIENTATION; + dev->sensors[ID_O].orientation.roll = -event->value; + break; + case EVENT_TYPE_TEMPERATURE: + new_sensors |= SENSORS_AKM_TEMPERATURE; + dev->sensors[ID_T].temperature = event->value; + break; + case EVENT_TYPE_STEP_COUNT: + // step count (only reported in MODE_FFD) + // we do nothing with it for now. + break; + case EVENT_TYPE_ACCEL_STATUS: + // accuracy of the calibration (never returned!) + //LOGV("G-Sensor status %d", event->value); + break; + case EVENT_TYPE_ORIENT_STATUS: { + // accuracy of the calibration + uint32_t v = (uint32_t)(event->value & SENSOR_STATE_MASK); + LOGV_IF(dev->sensors[ID_O].orientation.status != (uint8_t)v, + "M-Sensor status %d", v); + dev->sensors[ID_O].orientation.status = (uint8_t)v; + } + break; + } + } + + return new_sensors; +} + +static uint32_t data__poll_process_cm_abs(struct sensors_data_context_t *dev, + int fd __attribute__((unused)), + struct input_event *event) +{ + uint32_t new_sensors = 0; + if (event->type == EV_ABS) { + LOGV("proximity type: %d code: %d value: %-5d time: %ds", + event->type, event->code, event->value, + (int)event->time.tv_sec); + if (event->code == EVENT_TYPE_PROXIMITY) { + new_sensors |= SENSORS_CM_PROXIMITY; + /* event->value seems to be 0 or 1, scale it to the threshold */ + dev->sensors[ID_P].distance = event->value * PROXIMITY_THRESHOLD_CM; + } + } + return new_sensors; +} + +static uint32_t data__poll_process_ls_abs(struct sensors_data_context_t *dev, + int fd __attribute__((unused)), + struct input_event *event) +{ + uint32_t new_sensors = 0; + if (event->type == EV_ABS) { + LOGV("light-level type: %d code: %d value: %-5d time: %ds", + event->type, event->code, event->value, + (int)event->time.tv_sec); + if (event->code == EVENT_TYPE_LIGHT) { + struct input_absinfo absinfo; + int index; + if (!ioctl(fd, EVIOCGABS(ABS_DISTANCE), &absinfo)) { + index = event->value; + if (index >= 0) { + new_sensors |= SENSORS_LIGHT; + if (index >= ARRAY_SIZE(sLuxValues)) { + index = ARRAY_SIZE(sLuxValues) - 1; + } + dev->sensors[ID_L].light = sLuxValues[index]; + } + } + } + } + return new_sensors; +} + +static void data__poll_process_syn(struct sensors_data_context_t *dev, + struct input_event *event, + uint32_t new_sensors) +{ + if (new_sensors) { + dev->pendingSensors |= new_sensors; + int64_t t = event->time.tv_sec*1000000000LL + + event->time.tv_usec*1000; + while (new_sensors) { + uint32_t i = 31 - __builtin_clz(new_sensors); + new_sensors &= ~(1<sensors[i].time = t; + } + } +} + +static int data__poll(struct sensors_data_context_t *dev, sensors_data_t* values) +{ + int akm_fd = dev->events_fd[0]; + int cm_fd = dev->events_fd[1]; + int ls_fd = dev->events_fd[2]; + + if (akm_fd < 0) { + LOGE("invalid compass file descriptor, fd=%d", akm_fd); + return -1; + } + + if (cm_fd < 0) { + LOGE("invalid proximity-sensor file descriptor, fd=%d", cm_fd); + return -1; + } + + if (ls_fd < 0) { + LOGE("invalid light-sensor file descriptor, fd=%d", ls_fd); + return -1; + } + + // there are pending sensors, returns them now... + if (dev->pendingSensors) { + LOGV("pending sensors 0x%08x", dev->pendingSensors); + return pick_sensor(dev, values); + } + + // wait until we get a complete event for an enabled sensor + uint32_t new_sensors = 0; + while (1) { + /* read the next event; first, read the compass event, then the + proximity event */ + struct input_event event; + int got_syn = 0; + int exit = 0; + int nread; + fd_set rfds; + int n; + + FD_ZERO(&rfds); + FD_SET(akm_fd, &rfds); + FD_SET(cm_fd, &rfds); + FD_SET(ls_fd, &rfds); + n = select(__MAX(akm_fd, __MAX(cm_fd, ls_fd)) + 1, &rfds, + NULL, NULL, NULL); + LOGV("return from select: %d\n", n); + if (n < 0) { + LOGE("%s: error from select(%d, %d): %s", + __FUNCTION__, + akm_fd, cm_fd, strerror(errno)); + return -1; + } + + if (FD_ISSET(akm_fd, &rfds)) { + nread = read(akm_fd, &event, sizeof(event)); + if (nread == sizeof(event)) { + new_sensors |= data__poll_process_akm_abs(dev, akm_fd, &event); + LOGV("akm abs %08x", new_sensors); + got_syn = event.type == EV_SYN; + exit = got_syn && event.code == SYN_CONFIG; + if (got_syn) { + LOGV("akm syn %08x", new_sensors); + data__poll_process_syn(dev, &event, new_sensors); + new_sensors = 0; + } + } + else LOGE("akm read too small %d", nread); + } + else LOGV("akm fd is not set"); + + if (FD_ISSET(cm_fd, &rfds)) { + nread = read(cm_fd, &event, sizeof(event)); + if (nread == sizeof(event)) { + new_sensors |= data__poll_process_cm_abs(dev, cm_fd, &event); + LOGV("cm abs %08x", new_sensors); + got_syn |= event.type == EV_SYN; + exit |= got_syn && event.code == SYN_CONFIG; + if (got_syn) { + LOGV("cm syn %08x", new_sensors); + data__poll_process_syn(dev, &event, new_sensors); + new_sensors = 0; + } + } + else LOGE("cm read too small %d", nread); + } + else LOGV("cm fd is not set"); + + if (FD_ISSET(ls_fd, &rfds)) { + nread = read(ls_fd, &event, sizeof(event)); + if (nread == sizeof(event)) { + new_sensors |= data__poll_process_ls_abs(dev, ls_fd, &event); + LOGV("ls abs %08x", new_sensors); + got_syn |= event.type == EV_SYN; + exit |= got_syn && event.code == SYN_CONFIG; + if (got_syn) { + LOGV("ls syn %08x", new_sensors); + data__poll_process_syn(dev, &event, new_sensors); + new_sensors = 0; + } + } + else LOGE("ls read too small %d", nread); + } + else LOGV("ls fd is not set"); + + if (exit) { + // we use SYN_CONFIG to signal that we need to exit the + // main loop. + //LOGV("got empty message: value=%d", event->value); + LOGV("exit"); + return 0x7FFFFFFF; + } + + if (got_syn && dev->pendingSensors) { + LOGV("got syn, picking sensor"); + return pick_sensor(dev, values); + } + } +} + +/*****************************************************************************/ + +static int control__close(struct hw_device_t *dev) +{ + struct sensors_control_context_t* ctx = + (struct sensors_control_context_t*)dev; + if (ctx) { + close_akm(ctx); + close_cm(ctx); + close_ls(ctx); + free(ctx); + } + return 0; +} + +static int data__close(struct hw_device_t *dev) +{ + struct sensors_data_context_t* ctx = (struct sensors_data_context_t*)dev; + if (ctx) { + data__data_close(ctx); + free(ctx); + } + return 0; +} + + +/** Open a new instance of a sensor device using name */ static int open_sensors(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { - return init_nusensors(module, device); + int status = -EINVAL; + if (!strcmp(name, SENSORS_HARDWARE_CONTROL)) { + struct sensors_control_context_t *dev; + dev = malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + dev->akmd_fd = -1; + dev->cmd_fd = -1; + dev->lsd_fd = -1; + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = module; + dev->device.common.close = control__close; + dev->device.open_data_source = control__open_data_source; + dev->device.activate = control__activate; + dev->device.set_delay= control__set_delay; + dev->device.wake = control__wake; + *device = &dev->device.common; + } else if (!strcmp(name, SENSORS_HARDWARE_DATA)) { + struct sensors_data_context_t *dev; + dev = malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + dev->events_fd[0] = -1; + dev->events_fd[1] = -1; + dev->events_fd[2] = -1; + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = module; + dev->device.common.close = data__close; + dev->device.data_open = data__data_open; + dev->device.data_close = data__data_close; + dev->device.poll = data__poll; + *device = &dev->device.common; + } + return status; }