[-]
[+]
|
Changed |
_service:tar_git:mce-plugin-libhybris.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:mce-plugin-libhybris.spec
^
|
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/.depend
^
|
@@ -0,0 +1,290 @@
+hybris-fb.o:\
+ hybris-fb.c\
+ hybris-fb.h\
+ plugin-api.h\
+ plugin-logging.h\
+
+hybris-fb.pic.o:\
+ hybris-fb.c\
+ hybris-fb.h\
+ plugin-api.h\
+ plugin-logging.h\
+
+hybris-lights.o:\
+ hybris-lights.c\
+ hybris-lights.h\
+ plugin-api.h\
+ plugin-logging.h\
+
+hybris-lights.pic.o:\
+ hybris-lights.c\
+ hybris-lights.h\
+ plugin-api.h\
+ plugin-logging.h\
+
+hybris-sensors.o:\
+ hybris-sensors.c\
+ hybris-sensors.h\
+ hybris-thread.h\
+ plugin-api.h\
+ plugin-logging.h\
+
+hybris-sensors.pic.o:\
+ hybris-sensors.c\
+ hybris-sensors.h\
+ hybris-thread.h\
+ plugin-api.h\
+ plugin-logging.h\
+
+hybris-thread.o:\
+ hybris-thread.c\
+ hybris-thread.h\
+ plugin-logging.h\
+
+hybris-thread.pic.o:\
+ hybris-thread.c\
+ hybris-thread.h\
+ plugin-logging.h\
+
+plugin-api.o:\
+ plugin-api.c\
+ hybris-fb.h\
+ hybris-lights.h\
+ hybris-sensors.h\
+ plugin-api.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+
+plugin-api.pic.o:\
+ plugin-api.c\
+ hybris-fb.h\
+ hybris-lights.h\
+ hybris-sensors.h\
+ plugin-api.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+
+plugin-config.o:\
+ plugin-config.c\
+ plugin-config.h\
+ plugin-logging.h\
+
+plugin-config.pic.o:\
+ plugin-config.c\
+ plugin-config.h\
+ plugin-logging.h\
+
+plugin-logging.o:\
+ plugin-logging.c\
+ plugin-api.h\
+ plugin-logging.h\
+
+plugin-logging.pic.o:\
+ plugin-logging.c\
+ plugin-api.h\
+ plugin-logging.h\
+
+plugin-quirks.o:\
+ plugin-quirks.c\
+ plugin-config.h\
+ plugin-logging.h\
+ plugin-quirks.h\
+
+plugin-quirks.pic.o:\
+ plugin-quirks.c\
+ plugin-config.h\
+ plugin-logging.h\
+ plugin-quirks.h\
+
+sysfs-led-bacon.o:\
+ sysfs-led-bacon.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-bacon.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+
+sysfs-led-bacon.pic.o:\
+ sysfs-led-bacon.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-bacon.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+
+sysfs-led-binary.o:\
+ sysfs-led-binary.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-binary.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-binary.pic.o:\
+ sysfs-led-binary.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-binary.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-f5121.o:\
+ sysfs-led-f5121.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-f5121.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-f5121.pic.o:\
+ sysfs-led-f5121.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-f5121.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-hammerhead.o:\
+ sysfs-led-hammerhead.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-hammerhead.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+
+sysfs-led-hammerhead.pic.o:\
+ sysfs-led-hammerhead.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-hammerhead.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+
+sysfs-led-htcvision.o:\
+ sysfs-led-htcvision.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-htcvision.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-htcvision.pic.o:\
+ sysfs-led-htcvision.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-htcvision.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-main.o:\
+ sysfs-led-main.c\
+ plugin-config.h\
+ plugin-logging.h\
+ plugin-quirks.h\
+ sysfs-led-bacon.h\
+ sysfs-led-binary.h\
+ sysfs-led-f5121.h\
+ sysfs-led-hammerhead.h\
+ sysfs-led-htcvision.h\
+ sysfs-led-main.h\
+ sysfs-led-redgreen.h\
+ sysfs-led-util.h\
+ sysfs-led-vanilla.h\
+ sysfs-led-white.h\
+
+sysfs-led-main.pic.o:\
+ sysfs-led-main.c\
+ plugin-config.h\
+ plugin-logging.h\
+ plugin-quirks.h\
+ sysfs-led-bacon.h\
+ sysfs-led-binary.h\
+ sysfs-led-f5121.h\
+ sysfs-led-hammerhead.h\
+ sysfs-led-htcvision.h\
+ sysfs-led-main.h\
+ sysfs-led-redgreen.h\
+ sysfs-led-util.h\
+ sysfs-led-vanilla.h\
+ sysfs-led-white.h\
+
+sysfs-led-redgreen.o:\
+ sysfs-led-redgreen.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+ sysfs-led-redgreen.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-redgreen.pic.o:\
+ sysfs-led-redgreen.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+ sysfs-led-redgreen.h\
+ sysfs-led-util.h\
+ sysfs-val.h\
+
+sysfs-led-util.o:\
+ sysfs-led-util.c\
+ plugin-logging.h\
+ sysfs-led-util.h\
+
+sysfs-led-util.pic.o:\
+ sysfs-led-util.c\
+ plugin-logging.h\
+ sysfs-led-util.h\
+
+sysfs-led-vanilla.o:\
+ sysfs-led-vanilla.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-led-vanilla.h\
+ sysfs-val.h\
+
+sysfs-led-vanilla.pic.o:\
+ sysfs-led-vanilla.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-led-vanilla.h\
+ sysfs-val.h\
+
+sysfs-led-white.o:\
+ sysfs-led-white.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-led-white.h\
+ sysfs-val.h\
+
+sysfs-led-white.pic.o:\
+ sysfs-led-white.c\
+ plugin-config.h\
+ plugin-logging.h\
+ sysfs-led-main.h\
+ sysfs-led-util.h\
+ sysfs-led-white.h\
+ sysfs-val.h\
+
+sysfs-val.o:\
+ sysfs-val.c\
+ plugin-logging.h\
+ sysfs-val.h\
+
+sysfs-val.pic.o:\
+ sysfs-val.c\
+ plugin-logging.h\
+ sysfs-val.h\
+
|
[-]
[+]
|
Changed |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/Makefile
^
|
@@ -28,7 +28,7 @@
$(RM) $(TARGETS)
distclean:: clean
- $(RM) *.so *.p *.q
+ $(RM) *.so *.p *.q *.i
mostlyclean::
$(RM) *.o *~ *.bak
@@ -40,12 +40,14 @@
CPPFLAGS += -D_GNU_SOURCE
CPPFLAGS += -D_FILE_OFFSET_BITS=64
CPPFLAGS += -D_THREAD_SAFE
+CPPFLAGS += -DMCE_HYBRIS_INTERNAL=2
COMMON += -Wall
-COMMON += -W
+COMMON += -Wextra
COMMON += -Wmissing-prototypes
COMMON += -Os
COMMON += -g
+COMMON += -fvisibility=hidden
CFLAGS += $(COMMON)
CFLAGS += -std=c99
@@ -90,25 +92,50 @@
.SUFFIXES: %.pic.o
.PRECIOUS: %.pic.o
-%.so : %.pic.o
+%.so :
$(CC) -o $@ -shared $^ $(LDFLAGS) $(LDLIBS)
%.pic.o : %.c
$(CC) -c -o $@ $< -fPIC $(CPPFLAGS) $(CFLAGS)
%.q : %.c
- $(CC) -E -o $@ $<
+ $(CC) -E -o $@ $(CPPFLAGS) $<
%.p : %.q
- cat $< | cproto | sed -e 's/_Bool/bool/g' > $@
-# cat $< | cproto -S | sed -e 's/_Bool/bool/g' > $@
+ cat $< | cproto | prettyproto.py > $@
+%.i : %.q
+ cat $< | cproto -s | prettyproto.py > $@
+
+preprocess: $(patsubst %.c,%.q,$(wildcard *.c))
+prototypes: $(patsubst %.c,%.p,$(wildcard *.c))
+locals: $(patsubst %.c,%.i,$(wildcard *.c))
# ----------------------------------------------------------------------------
# Explicit dependencies
# ----------------------------------------------------------------------------
+hybris_OBJS += hybris-fb.pic.o
+hybris_OBJS += hybris-lights.pic.o
+hybris_OBJS += hybris-sensors.pic.o
+hybris_OBJS += hybris-thread.pic.o
+hybris_OBJS += plugin-api.pic.o
+hybris_OBJS += plugin-config.pic.o
+hybris_OBJS += plugin-logging.pic.o
+hybris_OBJS += plugin-quirks.pic.o
+hybris_OBJS += sysfs-led-bacon.pic.o
+hybris_OBJS += sysfs-led-binary.pic.o
+hybris_OBJS += sysfs-led-f5121.pic.o
+hybris_OBJS += sysfs-led-hammerhead.pic.o
+hybris_OBJS += sysfs-led-htcvision.pic.o
+hybris_OBJS += sysfs-led-main.pic.o
+hybris_OBJS += sysfs-led-redgreen.pic.o
+hybris_OBJS += sysfs-led-util.pic.o
+hybris_OBJS += sysfs-led-vanilla.pic.o
+hybris_OBJS += sysfs-led-white.pic.o
+hybris_OBJS += sysfs-val.pic.o
+
hybris.so : LDLIBS += -lhardware -lm
-hybris.so : hybris.pic.o
+hybris.so : $(hybris_OBJS)
install:: hybris.so
install -d -m755 $(DESTDIR)$(_LIBDIR)/mce/modules
@@ -122,3 +149,41 @@
normalize::
normalize_whitespace -M Makefile
normalize_whitespace -a $(wildcard *.[ch] *.cc *.cpp)
+
+# ----------------------------------------------------------------------------
+# AUTOMATIC HEADER DEPENDENCIES
+# ----------------------------------------------------------------------------
+
+.PHONY: depend
+depend::
+ @echo "Updating .depend"
+ $(CC) -MM $(CPPFLAGS) $(MCE_CFLAGS) $(wildcard *.c) |\
+ ./depend_filter.py > .depend
+
+ifneq ($(MAKECMDGOALS),depend) # not while: make depend
+ifneq (,$(wildcard .depend)) # not if .depend does not exist
+include .depend
+endif
+endif
+
+# ----------------------------------------------------------------------------
+# Hunt for excess include statements
+# ----------------------------------------------------------------------------
+
+.PHONY: headers
+.SUFFIXES: %.checked
+
+headers:: c_headers c_sources
+
+%.checked : %
+ find_unneeded_includes.py $(CPPFLAGS) $(CFLAGS) -- $<
+ @touch $@
+
+clean::
+ $(RM) *.checked *.order
+
+c_headers:: $(patsubst %,%.checked,$(wildcard *.h))
+c_sources:: $(patsubst %,%.checked,$(wildcard *.c))
+
+order::
+ find_unneeded_includes.py -- $(wildcard *.h) $(wildcard *.c)
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/depend_filter.py
^
|
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- encoding: utf8 -*-
+
+# ----------------------------------------------------------------------------
+# Copyright (C) 2012-2017 Jolla Ltd.
+# Contact: Simo Piiroinen <simo.piiroinen@jollamobile.com>
+# License: GPLv2
+# ----------------------------------------------------------------------------
+
+import sys,os
+
+def is_local(path):
+ return not path.startswith("/")
+
+def print_rule(dest, srce):
+ print "%s\\\n" % "\\\n\t".join(["%s:" % dest] + srce)
+
+def set_extension(path, ext):
+ return os.path.splitext(path)[0] + ext
+
+def normalize_path(srce):
+ return os.path.normpath(srce)
+
+def fix_directory(dest, srce):
+ srce = os.path.dirname(srce)
+ dest = os.path.basename(dest)
+ return os.path.join(srce, dest)
+
+if __name__ == "__main__":
+
+ data = sys.stdin.readlines()
+ data = map(lambda x:x.rstrip(), data)
+ data.reverse()
+
+ deps = []
+
+ # Note: dependencies are sorted only to keep
+ # future diffs cleaner
+
+ while data:
+ line = data.pop()
+ while line.endswith('\\'):
+ line = line[:-1] + data.pop()
+ if not ':' in line:
+ continue
+
+ dest,srce = line.split(":",1)
+ srce = srce.split()
+ srce,temp = srce[0],srce[1:]
+
+ # take dest path primary srce
+ dest = fix_directory(dest, srce)
+
+ # remove secondary deps with absolute path
+ temp = filter(is_local, temp)
+
+ # sort secondary sources
+ temp.sort()
+
+ srce = [srce] + temp
+ srce = map(normalize_path, srce)
+
+ deps.append((dest,srce))
+
+ for dest,srce in sorted(deps):
+ # emit normal compilation dependencies
+ print_rule(dest, srce)
+ # and for -fPIC in case it is needed
+ dest = set_extension(dest, ".pic.o")
+ print_rule(dest, srce)
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-fb.c
^
|
@@ -0,0 +1,216 @@
+/** @file hybris-fb.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hybris-fb.h"
+#include "plugin-logging.h"
+
+#include "plugin-api.h"
+
+#include <system/window.h>
+#include <hardware/fb.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+/* ------------------------------------------------------------------------- *
+ * FRAMEBUFFER_PLUGIN
+ * ------------------------------------------------------------------------- */
+
+bool hybris_plugin_fb_load (void);
+void hybris_plugin_fb_unload (void);
+
+static int hybris_plugin_fb_open_device (struct framebuffer_device_t **pdevice);
+static void hybris_plugin_fb_close_device (struct framebuffer_device_t **pdevice);
+
+/* ------------------------------------------------------------------------- *
+ * FRAMEBUFFER_DEVICE
+ * ------------------------------------------------------------------------- */
+
+bool hybris_device_fb_init (void);
+void hybris_device_fb_quit (void);
+bool hybris_device_fb_set_power (bool state);
+
+/* ========================================================================= *
+ * FRAMEBUFFER_PLUGIN
+ * ========================================================================= */
+
+/** Handle for libhybris framebuffer plugin */
+static const struct hw_module_t *hybris_plugin_fb_handle = 0;
+
+/** Load libhybris framebuffer plugin
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_plugin_fb_load(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ hw_get_module(GRALLOC_HARDWARE_FB0, &hybris_plugin_fb_handle);
+
+ if( !hybris_plugin_fb_handle ) {
+ mce_log(LL_WARN, "failed to open frame buffer module");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_plugin_fb_handle = %p",
+ hybris_plugin_fb_handle);
+
+cleanup:
+
+ return hybris_plugin_fb_handle != 0;
+}
+
+/** Unload libhybris framebuffer plugin
+ */
+void
+hybris_plugin_fb_unload(void)
+{
+ /* Close devices related to the plugin */
+ hybris_device_fb_quit();
+
+ /* actually unload the module */
+ // FIXME: how to unload libhybris modules?
+}
+
+/** Convenience function for opening frame buffer device
+ *
+ * Similar to what we might or might not have available from hardware/fb.h
+ */
+static int
+hybris_plugin_fb_open_device(struct framebuffer_device_t ** pdevice)
+{
+ int ack = false;
+
+ if( !hybris_plugin_fb_load() ) {
+ goto cleanup;
+ }
+
+ const struct hw_module_t *mod = hybris_plugin_fb_handle;
+ const char *id = GRALLOC_HARDWARE_FB0;
+ struct hw_device_t *dev = 0;
+
+ if( !mod->methods->open(mod, id, &dev) ) {
+ goto cleanup;
+ }
+
+ *pdevice = (struct framebuffer_device_t*)dev;
+
+ ack = true;
+
+cleanup:
+
+ return ack;
+}
+
+/** Convenience function for closing frame buffer device
+ *
+ * Similar to what we might or might not have available from hardware/fb.h
+ */
+static void
+hybris_plugin_fb_close_device(struct framebuffer_device_t **pdevice)
+{
+ struct framebuffer_device_t *device;
+
+ if( (device = *pdevice) ) {
+ *pdevice = 0, device->common.close(&device->common);
+ }
+}
+
+/* ========================================================================= *
+ * FRAMEBUFFER_DEVICE
+ * ========================================================================= */
+
+/** Pointer to libhybris frame buffer device object */
+static struct framebuffer_device_t *hybris_device_fb_handle = 0;
+
+/** Initialize libhybris frame buffer device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_fb_init(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ hybris_plugin_fb_open_device(&hybris_device_fb_handle);
+
+ if( !hybris_device_fb_handle ) {
+ mce_log(LL_ERR, "failed to open framebuffer device");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_device_fb_handle = %p",
+ hybris_device_fb_handle);
+
+cleanup:
+
+ return hybris_device_fb_handle != 0;
+}
+
+/** Release libhybris frame buffer device object
+ */
+void
+hybris_device_fb_quit(void)
+{
+ hybris_plugin_fb_close_device(&hybris_device_fb_handle);
+}
+
+/** Set frame buffer power state via libhybris
+ *
+ * @param state true to power on, false to power off
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_fb_set_power(bool state)
+{
+ bool ack = false;
+
+ if( !hybris_device_fb_init() ) {
+ goto cleanup;
+ }
+
+ if( hybris_device_fb_handle->enableScreen(hybris_device_fb_handle, state) < 0 ) {
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ return ack;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-fb.h
^
|
@@ -0,0 +1,36 @@
+/** @file hybris-fb.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HYBRIS_FB_H_
+# define HYBRIS_FB_H_
+
+# include <stdbool.h>
+
+bool hybris_plugin_fb_load (void);
+void hybris_plugin_fb_unload (void);
+
+bool hybris_device_fb_init (void);
+void hybris_device_fb_quit (void);
+bool hybris_device_fb_set_power (bool state);
+
+#endif /* HYBRIS_FB_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-lights.c
^
|
@@ -0,0 +1,466 @@
+/** @file hybris-lights.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hybris-lights.h"
+#include "plugin-logging.h"
+
+#include "plugin-api.h"
+
+#include <system/window.h>
+#include <hardware/lights.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+/* ------------------------------------------------------------------------- *
+ * UTILITIES
+ * ------------------------------------------------------------------------- */
+
+static int clamp_to_range (int lo, int hi, int val);
+
+/* ------------------------------------------------------------------------- *
+ * LIGHTS_PLUGIN
+ * ------------------------------------------------------------------------- */
+
+bool hybris_plugin_lights_load (void);
+void hybris_plugin_lights_unload (void);
+
+static int hybris_plugin_lights_open_device (const char *id, struct light_device_t **pdevice);
+static void hybris_plugin_lights_close_device (struct light_device_t **pdevice);
+
+/* ------------------------------------------------------------------------- *
+ * DISPLAY_BACKLIGHT
+ * ------------------------------------------------------------------------- */
+
+bool hybris_device_backlight_init (void);
+void hybris_device_backlight_quit (void);
+bool hybris_device_backlight_set_brightness(int level);
+
+/* ------------------------------------------------------------------------- *
+ * KEYBOARD_BACKLIGHT
+ * ------------------------------------------------------------------------- */
+
+bool hybris_device_keypad_init (void);
+void hybris_device_keypad_quit (void);
+bool hybris_device_keypad_set_brightness (int level);
+
+/* ------------------------------------------------------------------------- *
+ * INDICATOR_LED
+ * ------------------------------------------------------------------------- */
+
+bool hybris_device_indicator_init (void);
+void hybris_device_indicator_quit (void);
+bool hybris_device_indicator_set_pattern (int r, int g, int b, int ms_on, int ms_off);
+
+/* ========================================================================= *
+ * UTILITIES
+ * ========================================================================= */
+
+/** Clamp integer values to given range
+ *
+ * @param lo minimum value allowed
+ * @param hi maximum value allowed
+ * @param val value to clamp
+ *
+ * @return val clamped to [lo, hi]
+ */
+static int
+clamp_to_range(int lo, int hi, int val)
+{
+ return val <= lo ? lo : val <= hi ? val : hi;
+}
+
+/* ========================================================================= *
+ * LIGHTS_PLUGIN
+ * ========================================================================= */
+
+/** Handle for libhybris lights plugin */
+static const struct hw_module_t *hybris_plugin_lights_handle = 0;
+
+/** Load libhybris lights plugin
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_plugin_lights_load(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ hw_get_module(LIGHTS_HARDWARE_MODULE_ID, &hybris_plugin_lights_handle);
+ if( !hybris_plugin_lights_handle ) {
+ mce_log(LL_WARN, "failed to open lights module");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_plugin_lights_handle = %p",
+ hybris_plugin_lights_handle);
+
+cleanup:
+
+ return hybris_plugin_lights_handle != 0;
+}
+
+/** Unload libhybris lights plugin
+ */
+void
+hybris_plugin_lights_unload(void)
+{
+ /* cleanup dependencies */
+ hybris_device_backlight_quit();
+ hybris_device_keypad_quit();
+ hybris_device_indicator_quit();
+
+ /* actually unload the module */
+ // FIXME: how to unload libhybris modules?
+}
+
+/** Convenience function for opening a light device
+ *
+ * Similar to what we might or might not have available from hardware/lights.h
+ */
+static int
+hybris_plugin_lights_open_device(const char *id, struct light_device_t **pdevice)
+{
+ int ack = false;
+
+ if( !id || !pdevice ) {
+ goto cleanup;
+ }
+
+ if( !hybris_plugin_lights_load() ) {
+ goto cleanup;
+ }
+
+ const struct hw_module_t *module = hybris_plugin_lights_handle;
+
+ if( !module->methods->open(module, id, (struct hw_device_t**)pdevice) ) {
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ return ack;
+}
+
+/** Convenience function for closing a light device
+ *
+ * Similar to what we might or might not have available from hardware/lights.h
+ */
+static void
+hybris_plugin_lights_close_device(struct light_device_t **pdevice)
+{
+ struct light_device_t *device;
+
+ if( (device = *pdevice) ) {
+ *pdevice = 0, device->common.close(&device->common);
+ }
+}
+
+/* ========================================================================= *
+ * DISPLAY_BACKLIGHT
+ * ========================================================================= */
+
+/** Pointer to libhybris frame display backlight device object */
+static struct light_device_t *hybris_device_backlight_handle = 0;
+
+/** Initialize libhybris display backlight device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_backlight_init(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ hybris_plugin_lights_open_device(LIGHT_ID_BACKLIGHT,
+ &hybris_device_backlight_handle);
+
+ if( !hybris_device_backlight_handle ) {
+ mce_log(LL_WARN, "failed to open backlight device");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_device_backlight_handle -> %p",
+ hybris_device_backlight_handle);
+
+cleanup:
+ return hybris_device_backlight_handle != 0;
+}
+
+/** Release libhybris display backlight device object
+ */
+void
+hybris_device_backlight_quit(void)
+{
+ hybris_plugin_lights_close_device(&hybris_device_backlight_handle);
+}
+
+/** Set display backlight brightness via libhybris
+ *
+ * @param level 0=off ... 255=maximum brightness
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_backlight_set_brightness(int level)
+{
+ bool ack = false;
+
+ if( !hybris_device_backlight_init() ) {
+ goto cleanup;
+ }
+
+ unsigned lev = clamp_to_range(0, 255, level);
+
+ struct light_state_t lst;
+
+ memset(&lst, 0, sizeof lst);
+
+ lst.color = (0xff << 24) | (lev << 16) | (lev << 8) | (lev << 0);
+ lst.flashMode = LIGHT_FLASH_NONE;
+ lst.flashOnMS = 0;
+ lst.flashOffMS = 0;
+ lst.brightnessMode = BRIGHTNESS_MODE_USER;
+
+ if( hybris_device_backlight_handle->set_light(hybris_device_backlight_handle, &lst) < 0 ) {
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ mce_log(LL_DEBUG, "brightness(%d) -> %s",
+ level, ack ? "success" : "failure");
+
+ return ack;
+}
+
+/* ========================================================================= *
+ * KEYBOARD_BACKLIGHT
+ * ========================================================================= */
+
+/** Pointer to libhybris frame keypad backlight device object */
+static struct light_device_t *hybris_device_keypad_handle = 0;
+
+/** Initialize libhybris keypad backlight device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_keypad_init(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ hybris_plugin_lights_open_device(LIGHT_ID_KEYBOARD, &hybris_device_keypad_handle);
+
+ if( !hybris_device_keypad_handle ) {
+ mce_log(LL_WARN, "failed to open keypad backlight device");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_device_keypad_handle -> %p",
+ hybris_device_keypad_handle);
+
+cleanup:
+
+ return hybris_device_keypad_handle != 0;
+}
+
+/** Release libhybris keypad backlight device object
+ */
+void
+hybris_device_keypad_quit(void)
+{
+ hybris_plugin_lights_close_device(&hybris_device_keypad_handle);
+}
+
+/** Set display keypad brightness via libhybris
+ *
+ * @param level 0=off ... 255=maximum brightness
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_keypad_set_brightness(int level)
+{
+ bool ack = false;
+
+ if( !hybris_device_keypad_init() ) {
+ goto cleanup;
+ }
+
+ unsigned lev = clamp_to_range(0, 255, level);
+
+ struct light_state_t lst;
+
+ memset(&lst, 0, sizeof lst);
+
+ lst.color = (0xff << 24) | (lev << 16) | (lev << 8) | (lev << 0);
+ lst.flashMode = LIGHT_FLASH_NONE;
+ lst.flashOnMS = 0;
+ lst.flashOffMS = 0;
+ lst.brightnessMode = BRIGHTNESS_MODE_USER;
+
+ if( hybris_device_keypad_handle->set_light(hybris_device_keypad_handle, &lst) < 0 ) {
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ mce_log(LL_DEBUG, "brightness(%d) -> %s",
+ level, ack ? "success" : "failure");
+
+ return ack;
+}
+
+/* ========================================================================= *
+ * INDICATOR_LED
+ * ========================================================================= */
+
+/** Pointer to libhybris frame indicator led device object */
+static struct light_device_t *hybris_device_indicator_handle = 0;
+
+/** Initialize libhybris indicator led device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_indicator_init(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ hybris_plugin_lights_open_device(LIGHT_ID_NOTIFICATIONS,
+ &hybris_device_indicator_handle);
+
+ if( !hybris_device_indicator_handle ) {
+ mce_log(LL_WARN, "failed to open indicator led device");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_device_indicator_handle -> %p",
+ hybris_device_indicator_handle);
+
+cleanup:
+
+ return hybris_device_indicator_handle != 0;
+}
+
+/** Release libhybris indicator led device object
+ */
+void
+hybris_device_indicator_quit(void)
+{
+ hybris_plugin_lights_close_device(&hybris_device_indicator_handle);
+}
+
+/** Set indicator led pattern via libhybris
+ *
+ * @param r red intensity 0 ... 255
+ * @param g green intensity 0 ... 255
+ * @param b blue intensity 0 ... 255
+ * @param ms_on milliseconds to keep the led on, or 0 for no flashing
+ * @param ms_on milliseconds to keep the led off, or 0 for no flashing
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_indicator_set_pattern(int r, int g, int b, int ms_on, int ms_off)
+{
+ bool ack = false;
+
+ if( !hybris_device_indicator_init() ) {
+ goto cleanup;
+ }
+
+ r = clamp_to_range(0, 255, r);
+ g = clamp_to_range(0, 255, g);
+ b = clamp_to_range(0, 255, b);
+
+ ms_on = clamp_to_range(0, 60000, ms_on);
+ ms_off = clamp_to_range(0, 60000, ms_off);
+
+ if( ms_on < 50 || ms_off < 50 ) {
+ ms_on = ms_off = 0;
+ }
+
+ struct light_state_t lst;
+
+ memset(&lst, 0, sizeof lst);
+
+ lst.color = (0xff << 24) | (r << 16) | (g << 8) | (b << 0);
+ lst.brightnessMode = BRIGHTNESS_MODE_USER;
+
+ if( ms_on > 0 && ms_off > 0 ) {
+ lst.flashMode = LIGHT_FLASH_HARDWARE;
+ lst.flashOnMS = ms_on;
+ lst.flashOffMS = ms_off;
+ }
+ else {
+ lst.flashMode = LIGHT_FLASH_NONE;
+ lst.flashOnMS = 0;
+ lst.flashOffMS = 0;
+ }
+
+ if( hybris_device_indicator_handle->set_light(hybris_device_indicator_handle, &lst) < 0 ) {
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ mce_log(LL_DEBUG, "pattern(%d,%d,%d,%d,%d) -> %s",
+ r,g,b, ms_on, ms_off , ack ? "success" : "failure");
+
+ return ack;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-lights.h
^
|
@@ -0,0 +1,44 @@
+/** @file hybris-lights.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HYBRIS_LIGHTS_H_
+# define HYBRIS_LIGHTS_H_
+
+# include <stdbool.h>
+
+bool hybris_plugin_lights_load (void);
+void hybris_plugin_lights_unload (void);
+
+bool hybris_device_backlight_init (void);
+void hybris_device_backlight_quit (void);
+bool hybris_device_backlight_set_brightness (int level);
+
+bool hybris_device_keypad_init (void);
+void hybris_device_keypad_quit (void);
+bool hybris_device_keypad_set_brightness (int level);
+
+bool hybris_device_indicator_init (void);
+void hybris_device_indicator_quit (void);
+bool hybris_device_indicator_set_pattern (int r, int g, int b, int ms_on, int ms_off);
+
+#endif /* HYBRIS_LIGHTS_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-sensors.c
^
|
@@ -0,0 +1,497 @@
+/** @file hybris-sensors.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hybris-sensors.h"
+#include "plugin-logging.h"
+#include "hybris-thread.h"
+
+#include <hardware/sensors.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+/* ------------------------------------------------------------------------- *
+ * SENSORS_PLUGIN
+ * ------------------------------------------------------------------------- */
+
+static const struct sensor_t *hybris_plugin_sensors_get_sensor (int type);
+
+bool hybris_plugin_sensors_load (void);
+void hybris_plugin_sensors_unload (void);
+
+static bool hybris_plugin_sensors_open_device (struct sensors_poll_device_t **pdevice);
+static void hybris_plugin_sensors_close_device (struct sensors_poll_device_t **pdevice);
+
+/* ------------------------------------------------------------------------- *
+ * SENSORS_DEVICE
+ * ------------------------------------------------------------------------- */
+
+static void hybris_device_sensors_thread_cb (void *aptr);
+
+static bool hybris_device_sensors_init (void);
+static void hybris_device_sensors_quit (void);
+
+/* ------------------------------------------------------------------------- *
+ * PROXIMITY_SENSOR
+ * ------------------------------------------------------------------------- */
+
+bool hybris_sensor_ps_init (void);
+void hybris_sensor_ps_quit (void);
+void hybris_sensor_ps_set_hook (mce_hybris_ps_fn cb);
+bool hybris_sensor_ps_set_active (bool state);
+
+/* ------------------------------------------------------------------------- *
+ * AMBIENT_LIGHT_SENSOR
+ * ------------------------------------------------------------------------- */
+
+bool hybris_device_als_init (void);
+void hybris_device_als_quit (void);
+void hybris_device_als_set_hook (mce_hybris_als_fn cb);
+bool hybris_device_als_set_active (bool state);
+
+/* ========================================================================= *
+ * SENSORS_PLUGIN
+ * ========================================================================= */
+
+/** Handle for libhybris sensors plugin */
+static struct sensors_module_t *hybris_plugin_sensors_handle = 0;
+
+/** Array of sensors available via hybris_plugin_sensors_handle */
+static const struct sensor_t *hybris_plugin_sensors_lut = 0;
+
+/** Number of sensors available via hybris_plugin_sensors_handle */
+static int hybris_plugin_sensors_cnt = 0;
+
+/** Pointer to libhybris proximity sensor object */
+static const struct sensor_t *hybris_plugin_sensors_ps_sensor = 0;
+
+/** Pointer to libhybris ambient light sensor object */
+static const struct sensor_t *hybris_plugin_sensors_als_sensor = 0;
+
+/** Helper for locating sensor objects by type
+ *
+ * @param type SENSOR_TYPE_LIGHT etc
+ *
+ * @return sensor pointer, or NULL if not available
+ */
+static const struct sensor_t *
+hybris_plugin_sensors_get_sensor(int type)
+{
+ const struct sensor_t *res = 0;
+
+ for( int i = 0; i < hybris_plugin_sensors_cnt; ++i ) {
+
+ if( hybris_plugin_sensors_lut[i].type == type ) {
+ res = &hybris_plugin_sensors_lut[i];
+ break;
+ }
+ }
+
+ return res;
+}
+
+/** Load libhybris sensors plugin
+ *
+ * Also initializes look up table for supported sensors.
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_plugin_sensors_load(void)
+{
+ static bool done = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ {
+ const struct hw_module_t *mod = 0;
+ hw_get_module(SENSORS_HARDWARE_MODULE_ID, &mod);
+ hybris_plugin_sensors_handle = (struct sensors_module_t *)mod;
+ }
+
+ if( !hybris_plugin_sensors_handle ) {
+ mce_log(LL_WARN, "failed top open sensors module");
+ }
+ else {
+ mce_log(LL_DEBUG, "hybris_plugin_sensors_handle = %p",
+ hybris_plugin_sensors_handle);
+ }
+
+ if( !hybris_plugin_sensors_handle ) {
+ goto cleanup;
+ }
+
+ hybris_plugin_sensors_cnt = hybris_plugin_sensors_handle->get_sensors_list(hybris_plugin_sensors_handle,
+ &hybris_plugin_sensors_lut);
+
+ hybris_plugin_sensors_als_sensor = hybris_plugin_sensors_get_sensor(SENSOR_TYPE_LIGHT);
+ hybris_plugin_sensors_ps_sensor = hybris_plugin_sensors_get_sensor(SENSOR_TYPE_PROXIMITY);
+
+cleanup:
+
+ return hybris_plugin_sensors_handle != 0;
+}
+
+/** Unload libhybris sensors plugin
+ */
+void
+hybris_plugin_sensors_unload(void)
+{
+ /* cleanup dependencies */
+ hybris_device_sensors_quit();
+
+ /* actually unload the module */
+ // FIXME: how to unload libhybris modules?
+}
+
+/** Convenience function for opening sensors device
+ *
+ * Similar to what we might or might not have available from hardware/sensors.h
+ */
+static bool
+hybris_plugin_sensors_open_device(struct sensors_poll_device_t **pdevice)
+{
+ bool ack = false;
+
+ if( !hybris_plugin_sensors_load() ) {
+ goto cleanup;
+ }
+
+ const struct hw_module_t *mod = &hybris_plugin_sensors_handle->common;
+ const char *id = SENSORS_HARDWARE_POLL;
+ struct hw_device_t *dev = 0;
+
+ if( !mod->methods->open(mod, id, &dev) ) {
+ goto cleanup;
+ }
+
+ *pdevice = (struct sensors_poll_device_t *)dev;
+
+ ack = true;
+
+cleanup:
+
+ return ack;
+}
+
+/** Convenience function for closing sensors device
+ *
+ * Similar to what we might or might not have available from hardware/sensors.h
+ */
+static void
+hybris_plugin_sensors_close_device(struct sensors_poll_device_t **pdevice)
+{
+ struct sensors_poll_device_t *device;
+
+ if( (device = *pdevice) ) {
+ *pdevice = 0, device->common.close(&device->common);
+ }
+}
+
+/* ========================================================================= *
+ * SENSORS_DEVICE
+ * ========================================================================= */
+
+/** Pointer to libhybris sensor poll device object */
+static struct sensors_poll_device_t *hybris_device_sensors_handle = 0;
+
+/** Callback for forwarding proximity sensor events */
+static mce_hybris_ps_fn hybris_device_sensors_ps_cb = 0;
+
+/** Callback for forwarding ambient light sensor events */
+static mce_hybris_als_fn hybris_device_sensors_als_cb = 0;
+
+/** Worker thread id */
+static pthread_t hybris_device_sensors_thread_id = 0;
+
+/** Worker thread for reading sensor events via blocking libhybris interface
+ *
+ * Note: no mce_log() calls from this function - they are not thread safe
+ *
+ * @param aptr (thread parameter, not used)
+ */
+static void
+hybris_device_sensors_thread_cb(void *aptr)
+{
+ (void)aptr;
+
+ sensors_event_t eve[32];
+
+ while( hybris_device_sensors_handle ) {
+ /* This blocks until there are events available, or possibly sooner
+ * if enabling/disabling sensors changes something. Since we can't
+ * guarantee that we ever return from the call, the thread is cancelled
+ * asynchronously on cleanup - and any resources possibly reserved by
+ * the hybris_device_sensors_handle->poll() are lost. */
+ int n = hybris_device_sensors_handle->poll(hybris_device_sensors_handle, eve, G_N_ELEMENTS(eve));
+
+ for( int i = 0; i < n; ++i ) {
+ sensors_event_t *e = &eve[i];
+
+ /* Forward data via per sensor callback routines. The callbacks must
+ * handle the fact that they get called from the context of the worker
+ * thread. */
+ switch( e->type ) {
+ case SENSOR_TYPE_LIGHT:
+ if( hybris_device_sensors_als_cb ) {
+ hybris_device_sensors_als_cb(e->timestamp, e->distance);
+ }
+ break;
+ case SENSOR_TYPE_PROXIMITY:
+ if( hybris_device_sensors_ps_cb ) {
+ hybris_device_sensors_ps_cb(e->timestamp, e->light);
+ }
+ break;
+
+ case SENSOR_TYPE_ACCELEROMETER:
+ case SENSOR_TYPE_MAGNETIC_FIELD:
+ case SENSOR_TYPE_ORIENTATION:
+ case SENSOR_TYPE_GYROSCOPE:
+ case SENSOR_TYPE_PRESSURE:
+ case SENSOR_TYPE_TEMPERATURE:
+ case SENSOR_TYPE_GRAVITY:
+ case SENSOR_TYPE_LINEAR_ACCELERATION:
+ case SENSOR_TYPE_ROTATION_VECTOR:
+ case SENSOR_TYPE_RELATIVE_HUMIDITY:
+ case SENSOR_TYPE_AMBIENT_TEMPERATURE:
+ break;
+ }
+ }
+ }
+}
+
+/** Initialize libhybris sensor poll device object
+ *
+ * Also:
+ * - disables ALS and PS sensor inputs if possible
+ * - starts worker thread to handle sensor input events
+ *
+ * @return true on success, false on failure
+ */
+static bool
+hybris_device_sensors_init(void)
+{
+ if( hybris_device_sensors_handle ) {
+ goto cleanup;
+ }
+
+ if( !hybris_plugin_sensors_open_device(&hybris_device_sensors_handle) ) {
+ mce_log(LL_WARN, "failed to open sensor poll device");
+ goto cleanup;
+ }
+
+ mce_log(LL_DEBUG, "hybris_device_sensors_handle = %p",
+ hybris_device_sensors_handle);
+
+ if( hybris_plugin_sensors_ps_sensor ) {
+ hybris_device_sensors_handle->activate(hybris_device_sensors_handle, hybris_plugin_sensors_ps_sensor->handle, false);
+ }
+
+ if( hybris_plugin_sensors_als_sensor ) {
+ hybris_device_sensors_handle->activate(hybris_device_sensors_handle, hybris_plugin_sensors_als_sensor->handle, false);
+ }
+
+ hybris_device_sensors_thread_id = hybris_thread_start(hybris_device_sensors_thread_cb, 0);
+
+cleanup:
+
+ return hybris_device_sensors_handle != 0;
+}
+
+/** Release libhybris display backlight device object
+ *
+ * Also:
+ * - stops the sensor input worker thread
+ * - disables ALS and PS sensor inputs if possible
+ */
+static void
+hybris_device_sensors_quit(void)
+{
+ if( hybris_device_sensors_handle ) {
+ if( hybris_device_sensors_thread_id ) {
+ hybris_thread_stop(hybris_device_sensors_thread_id),
+ hybris_device_sensors_thread_id = 0;
+ }
+
+ if( hybris_plugin_sensors_ps_sensor ) {
+ hybris_device_sensors_handle->activate(hybris_device_sensors_handle, hybris_plugin_sensors_ps_sensor->handle, false);
+ }
+
+ if( hybris_plugin_sensors_als_sensor ) {
+ hybris_device_sensors_handle->activate(hybris_device_sensors_handle, hybris_plugin_sensors_als_sensor->handle, false);
+ }
+
+ hybris_plugin_sensors_close_device(&hybris_device_sensors_handle);
+ }
+}
+
+/* ========================================================================= *
+ * PROXIMITY_SENSOR
+ * ========================================================================= */
+
+/** Start using proximity sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_sensor_ps_init(void)
+{
+ bool res = false;
+
+ if( !hybris_device_sensors_init() ) {
+ goto cleanup;
+ }
+
+ if( !hybris_plugin_sensors_ps_sensor ) {
+ goto cleanup;
+ }
+
+ res = true;
+
+cleanup:
+
+ return res;
+}
+
+/** Stop using proximity sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+void
+hybris_sensor_ps_quit(void)
+{
+ hybris_device_sensors_ps_cb = 0;
+}
+
+/** Set callback function for handling proximity sensor events
+ *
+ * Note: the callback function will be called from worker thread.
+ */
+void
+hybris_sensor_ps_set_hook(mce_hybris_ps_fn cb)
+{
+ hybris_device_sensors_ps_cb = cb;
+}
+
+/** Set proximity sensort input enabled state
+ *
+ * @param state true to enable input, or false to disable input
+ */
+bool
+hybris_sensor_ps_set_active(bool state)
+{
+ bool res = false;
+
+ if( !hybris_sensor_ps_init() ) {
+ goto cleanup;
+ }
+
+ if( hybris_device_sensors_handle->activate(hybris_device_sensors_handle, hybris_plugin_sensors_ps_sensor->handle, state) < 0 ) {
+ goto cleanup;
+ }
+
+ res = true;
+
+cleanup:
+
+ return res;
+}
+
+/* ========================================================================= *
+ * AMBIENT_LIGHT_SENSOR
+ * ========================================================================= */
+
+/** Start using ambient light sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+bool
+hybris_device_als_init(void)
+{
+ bool res = false;
+
+ if( !hybris_device_sensors_init() ) {
+ goto cleanup;
+ }
+
+ if( !hybris_plugin_sensors_als_sensor ) {
+ goto cleanup;
+ }
+
+ res = true;
+
+cleanup:
+
+ return res;
+}
+
+/** Stop using ambient light sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+void
+hybris_device_als_quit(void)
+{
+ hybris_device_sensors_als_cb = 0;
+}
+
+/** Set callback function for handling ambient light sensor events
+ *
+ * Note: the callback function will be called from worker thread.
+ */
+void
+hybris_device_als_set_hook(mce_hybris_als_fn cb)
+{
+ hybris_device_sensors_als_cb = cb;
+}
+
+/** Set ambient light sensor input enabled state
+ *
+ * @param state true to enable input, or false to disable input
+ */
+bool
+hybris_device_als_set_active(bool state)
+{
+ bool res = false;
+
+ if( !hybris_device_als_init() ) {
+ goto cleanup;
+ }
+
+ if( hybris_device_sensors_handle->activate(hybris_device_sensors_handle, hybris_plugin_sensors_als_sensor->handle, state) < 0 ) {
+ goto cleanup;
+ }
+
+ res = true;
+
+cleanup:
+
+ return res;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-sensors.h
^
|
@@ -0,0 +1,42 @@
+/** @file hybris-sensors.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HYBRIS_SENSORS_H_
+# define HYBRIS_SENSORS_H_
+
+# include "plugin-api.h"
+
+bool hybris_plugin_sensors_load (void);
+void hybris_plugin_sensors_unload (void);
+
+bool hybris_sensor_ps_init (void);
+void hybris_sensor_ps_quit (void);
+bool hybris_sensor_ps_set_active (bool state);
+void hybris_sensor_ps_set_hook (mce_hybris_ps_fn cb);
+
+bool hybris_device_als_init (void);
+void hybris_device_als_quit (void);
+bool hybris_device_als_set_active (bool state);
+void hybris_device_als_set_hook (mce_hybris_als_fn cb);
+
+#endif /* HYBRIS_SENSORS_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-thread.c
^
|
@@ -0,0 +1,217 @@
+/** @file hybris-thread.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hybris-thread.h"
+#include "plugin-logging.h"
+
+#include <stdlib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+/* ------------------------------------------------------------------------- *
+ * THREAD_GATE
+ * ------------------------------------------------------------------------- */
+
+/** Thread start details; used for inserting custom thread setup code
+ */
+typedef struct
+{
+ /** Function to call from initialized thread */
+ void (*func)(void *);
+
+ /** Parameter to pass to the thread function */
+ void *data;
+} thread_gate_t;
+
+static void *thread_gate_start_cb (void *aptr);
+
+static thread_gate_t *thread_gate_create (void (*func)(void *), void *data);
+static void thread_gate_delete (thread_gate_t *self);
+
+/* ------------------------------------------------------------------------- *
+ * GENERIC
+ * ------------------------------------------------------------------------- */
+
+pthread_t hybris_thread_start (void (*start)(void *), void *arg);
+void hybris_thread_stop (pthread_t tid);
+
+/* ========================================================================= *
+ * DATA
+ * ========================================================================= */
+
+/** Mutex used for synchronous worker thread startup */
+static pthread_mutex_t hybris_thread_gate_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/** Condition used for signaling worker thread startup */
+static pthread_cond_t hybris_thread_gate_cond = PTHREAD_COND_INITIALIZER;
+
+/* ========================================================================= *
+ * THREAD_GATE
+ * ========================================================================= */
+
+/** Wrapper for starting new worker thread
+ *
+ * For use from hybris_thread_start().
+ *
+ * Before the actual thread start routine is called, the
+ * new thread is put in to asynchronously cancellabe state
+ * and the starter is woken up via condition.
+ *
+ * @param aptr wrapper data as void pointer
+ *
+ * @return 0 on thread exit - via pthread_join()
+ */
+static void *
+thread_gate_start_cb(void *aptr)
+{
+ thread_gate_t *gate = aptr;
+
+ void (*func)(void*);
+ void *data;
+
+ /* Allow quick and dirty cancellation */
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+
+ /* Tell thread gate we're up and running */
+ pthread_mutex_lock(&hybris_thread_gate_mutex);
+ pthread_cond_broadcast(&hybris_thread_gate_cond);
+ pthread_mutex_unlock(&hybris_thread_gate_mutex);
+
+ /* Collect data we need, release rest */
+ func = gate->func;
+ data = gate->data;
+
+ thread_gate_delete(gate),gate = 0;
+
+ /* Call the real thread start */
+ func(data);
+
+ return 0;
+}
+
+/** Construct a thread gate object
+ *
+ * @param func Thread function
+ * @param data Data to pass to the thread function
+ *
+ * @return gate object, or NULL
+ */
+static thread_gate_t *
+thread_gate_create(void (*func)(void *), void *data)
+{
+ thread_gate_t *self = calloc(1, sizeof *self);
+
+ if( self ) {
+ self->func = func;
+ self->data = data;
+ }
+
+ return self;
+}
+
+/** Destroy a thread gate object
+ *
+ * @param self Gate object, or NULL
+ */
+static void
+thread_gate_delete(thread_gate_t *self)
+{
+ if( self ) {
+ free(self);
+ }
+}
+
+/* ========================================================================= *
+ * GENERIC
+ * ========================================================================= */
+
+/** Helper for starting new worker thread
+ *
+ * @param start function to call from new thread
+ * @param arg data to pass to start function
+ *
+ * @return thread id on success, or 0 on error
+ */
+pthread_t
+hybris_thread_start(void (*start)(void *), void* arg)
+{
+ pthread_t tid = 0;
+ thread_gate_t *gate = 0;
+
+ if( !(gate = thread_gate_create(start, arg)) ) {
+ goto EXIT;
+ }
+
+ pthread_mutex_lock(&hybris_thread_gate_mutex);
+
+ if( pthread_create(&tid, 0, thread_gate_start_cb, gate) != 0 ) {
+ mce_log(LL_ERR, "could not start worker thread");
+
+ /* content of tid is undefined on failure, force to zero */
+ tid = 0;
+ }
+ else {
+ /* wait until thread has had time to start and set
+ * up the cancellation parameters */
+ mce_log(LL_DEBUG, "waiting worker to start ...");
+ pthread_cond_wait(&hybris_thread_gate_cond, &hybris_thread_gate_mutex);
+ mce_log(LL_DEBUG, "worker started");
+
+ /* the thread owns the gate now */
+ gate = 0;
+ }
+
+ pthread_mutex_unlock(&hybris_thread_gate_mutex);
+
+EXIT:
+
+ thread_gate_delete(gate);
+
+ return tid;
+}
+
+/** Helper for terminating worker thread
+ *
+ * @param tid Thread id from hybris_thread_start()
+ */
+void
+hybris_thread_stop(pthread_t tid)
+{
+ /* Looks like there is no nice way to get the thread to return from
+ * hybris_device_sensors_handle->poll(), so we need to just cancel the thread ... */
+
+ if( tid != 0 ) {
+ mce_log(LL_DEBUG, "stopping worker thread");
+ if( pthread_cancel(tid) != 0 ) {
+ mce_log(LL_ERR, "failed to stop worker thread");
+ }
+ else {
+ void *status = 0;
+ pthread_join(tid, &status);
+ mce_log(LL_DEBUG, "worker stopped, status = %p", status);
+ }
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/hybris-thread.h
^
|
@@ -0,0 +1,32 @@
+/** @file hybris-thread.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HYBRIS_THREAD_H_
+# define HYBRIS_THREAD_H_
+
+# include <pthread.h>
+
+pthread_t hybris_thread_start (void (*start)(void *), void* arg);
+void hybris_thread_stop (pthread_t tid);
+
+#endif /* HYBRIS_THREAD_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-bacon.ini
^
|
@@ -0,0 +1,24 @@
+[LEDConfigHybris]
+
+# Choose bacon backend
+BackEnd=bacon
+
+# Configure base directories for red/green/blue channels
+RedDirectory=/sys/class/leds/red
+GreenDirectory=/sys/class/leds/green
+BlueDirectory=/sys/class/leds/blue
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#GrpFreqFile=device/grpfreq
+#GrpPwmFile=device/grppwm
+#BlinkFile=device/blink
+#LedResetFile=device/ledreset
+
+# Optional channel specific overrides
+#RedBrightnessFile=/sys/class/leds/red/brightness
+#RedGrpFreqFile=/sys/class/leds/red/device/grpfreq
+#RedGrpPwmFile=/sys/class/leds/red/device/grppwm
+#RedBlinkFile=/sys/class/leds/red/device/blink
+#RedLedResetFile=/sys/class/leds/red/device/ledreset
+# ... and similarly for Green and Blue.
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-binary.ini
^
|
@@ -0,0 +1,15 @@
+[LEDConfigHybris]
+
+# Choose binary backend
+BackEnd=binary
+
+# Configure base directories for binary channel
+LedDirectory=/sys/class/leds/binary
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+
+# Optional channel specific overrides
+#LedBrightnessFile=/sys/class/leds/binary/brightness
+#LedMaxBrightnessFile=/sys/class/leds/binary/max_brightness
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-f5121.ini
^
|
@@ -0,0 +1,20 @@
+[LEDConfigHybris]
+
+# Choose f5121 backend
+BackEnd=f5121
+
+# Configure base directories for red/green/blue channels
+RedDirectory=/sys/class/leds/red
+GreenDirectory=/sys/class/leds/green
+BlueDirectory=/sys/class/leds/blue
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+#BlinkFile=blink
+
+# Optional channel specific overrides
+#RedBrightnessFile=/sys/class/leds/red/brightness
+#RedMaxBrightnessFile=/sys/class/leds/red/max_brightness
+#RedBlinkFile=/sys/class/leds/red/blink
+# ... and similarly for Green and Blue.
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-hammerhead.ini
^
|
@@ -0,0 +1,22 @@
+[LEDConfigHybris]
+
+# Choose hammerhead backend
+BackEnd=hammerhead
+
+# Configure base directories for red/green/blue channels
+RedDirectory=/sys/class/leds/red
+GreenDirectory=/sys/class/leds/green
+BlueDirectory=/sys/class/leds/blue
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+#OnOffMsFile=on_off_ms
+#RgbStartFile=rgb_start
+
+# Optional channel specific overrides
+#RedBrightnessFile=/sys/class/leds/red/brightness
+#RedMaxBrightnessFile=/sys/class/leds/red/max_brightness
+#RedOnOffMsFile=/sys/class/leds/red/on_off_ms
+#RedRgbStartFile=/sys/class/leds/red/rgb_start
+# ... and similarly for Green and Blue.
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-htcvision.ini
^
|
@@ -0,0 +1,19 @@
+[LEDConfigHybris]
+
+# Choose htcvision backend
+BackEnd=htcvision
+
+# Configure base directories for amber/green channels
+AmberDirectory=/sys/class/leds/amber
+GreenDirectory=/sys/class/leds/green
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+#BlinkFile=blink
+
+# Optional channel specific overrides
+#AmberBrightnessFile=/sys/class/leds/amber/brightness
+#AmberMaxBrightnessFile=/sys/class/leds/amber/max_brightness
+#AmberBlinkFile=/sys/class/leds/amber/blink
+# ... and similarly for Green.
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-redgreen.ini
^
|
@@ -0,0 +1,17 @@
+[LEDConfigHybris]
+
+# Choose redgreen backend
+BackEnd=redgreen
+
+# Configure base directories for red/green/blue channels
+RedDirectory=/sys/class/leds/red
+GreenDirectory=/sys/class/leds/green
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+
+# Optional channel specific overrides
+#RedBrightnessFile=/sys/class/leds/red/brightness
+#RedMaxBrightnessFile=/sys/class/leds/red/max_brightness
+# ... and similarly for Green.
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-vanilla.ini
^
|
@@ -0,0 +1,24 @@
+[LEDConfigHybris]
+
+# Choose vanilla backend
+BackEnd=vanilla
+
+# Configure base directories for red/green/blue channels
+RedDirectory=/sys/class/leds/red
+GreenDirectory=/sys/class/leds/green
+BlueDirectory=/sys/class/leds/blue
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+#BlinkDelayOnFile=blink_delay_on
+#BlinkDelayOffFile=blink_delay_off
+#BlinkFile=blink
+
+# Optional channel specific overrides
+#RedBrightnessFile=/sys/class/leds/red/brightness
+#RedMaxBrightnessFile=/sys/class/leds/red/max_brightness
+#RedBlinkDelayOnFile=/sys/class/leds/red/blink_delay_on
+#RedBlinkDelayOffFile=/sys/class/leds/red/blink_delay_off
+#RedBlinkFile=/sys/class/leds/red/blink
+# ... and similarly for Green and Blue.
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/inifiles/60-white.ini
^
|
@@ -0,0 +1,15 @@
+[LEDConfigHybris]
+
+# Choose white backend
+BackEnd=white
+
+# Configure base directories for white channel
+LedDirectory=/sys/class/leds/white
+
+# Built-in defaults for directory relative paths
+#BrightnessFile=brightness
+#MaxBrightnessFile=max_brightness
+
+# Optional channel specific overrides
+#LedBrightnessFile=/sys/class/leds/white/brightness
+#LedMaxBrightnessFile=/sys/class/leds/white/max_brightness
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-api.c
^
|
@@ -0,0 +1,512 @@
+/** @file plugin-api.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * This module implements "mce-libhybris-plugin" for use from
+ * "mce-libhybris-module" within mce.
+ *
+ * The idea of "hybris-plugin" is shortly:
+ * - it uses no mce functions or data types
+ * - it can be compiled independently from mce
+ * - it exposes no libhybris/android datatypes / functions
+ *
+ * And the idea of "hybris-module" is:
+ * - it contains functions with the same names as "hybris-plugin"
+ * - if called, the functions will load & call "hybris-plugin" code
+ * - if "hybris-plugin" is not present "hybris-module" functions
+ * still work, but return failures for everything
+ *
+ * Put together:
+ * - mce code can assume that libhybris code is always available and
+ * callable during hw probing activity
+ * - if hybris plugin is not installed (or if some hw is not supported
+ * by the underlying android code), failures will be reported and mce
+ * can try other existing ways to proble hw controls
+ * ========================================================================= */
+
+#include "plugin-api.h"
+
+#include "plugin-logging.h"
+#include "hybris-fb.h"
+#include "hybris-lights.h"
+#include "hybris-sensors.h"
+
+#include "sysfs-led-main.h"
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+/* ------------------------------------------------------------------------- *
+ * FRAME_BUFFER_POWER_STATE
+ * ------------------------------------------------------------------------- */
+
+bool mce_hybris_framebuffer_init (void);
+void mce_hybris_framebuffer_quit (void);
+bool mce_hybris_framebuffer_set_power (bool state);
+
+/* ------------------------------------------------------------------------- *
+ * DISPLAY_BACKLIGHT_BRIGHTNESS
+ * ------------------------------------------------------------------------- */
+
+bool mce_hybris_backlight_init (void);
+void mce_hybris_backlight_quit (void);
+bool mce_hybris_backlight_set_brightness (int level);
+
+/* ------------------------------------------------------------------------- *
+ * KEYPAD_BACKLIGHT_BRIGHTNESS
+ * ------------------------------------------------------------------------- */
+
+bool mce_hybris_keypad_init (void);
+void mce_hybris_keypad_quit (void);
+bool mce_hybris_keypad_set_brightness (int level);
+
+/* ------------------------------------------------------------------------- *
+ * INDICATOR_LED_PATTERN
+ * ------------------------------------------------------------------------- */
+
+bool mce_hybris_indicator_init (void);
+void mce_hybris_indicator_quit (void);
+bool mce_hybris_indicator_set_pattern (int r, int g, int b, int ms_on, int ms_off);
+bool mce_hybris_indicator_can_breathe (void);
+void mce_hybris_indicator_enable_breathing(bool enable);
+bool mce_hybris_indicator_set_brightness (int level);
+
+/* ------------------------------------------------------------------------- *
+ * PROXIMITY_SENSOR
+ * ------------------------------------------------------------------------- */
+
+bool mce_hybris_ps_init (void);
+void mce_hybris_ps_quit (void);
+bool mce_hybris_ps_set_active (bool state);
+void mce_hybris_ps_set_hook (mce_hybris_ps_fn cb);
+
+/* ------------------------------------------------------------------------- *
+ * AMBIENT_LIGHT_SENSOR
+ * ------------------------------------------------------------------------- */
+
+bool mce_hybris_als_init (void);
+void mce_hybris_als_quit (void);
+bool mce_hybris_als_set_active (bool state);
+void mce_hybris_als_set_hook (mce_hybris_als_fn cb);
+
+/* ------------------------------------------------------------------------- *
+ * GENERIC
+ * ------------------------------------------------------------------------- */
+
+void mce_hybris_quit (void);
+
+/* ========================================================================= *
+ * FRAME_BUFFER_POWER_STATE
+ * ========================================================================= */
+
+/** Initialize libhybris frame buffer device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_framebuffer_init(void)
+{
+ return hybris_device_fb_init();
+}
+
+/** Release libhybris frame buffer device object
+ */
+void
+mce_hybris_framebuffer_quit(void)
+{
+ hybris_device_fb_quit();
+}
+
+/** Set frame buffer power state via libhybris
+ *
+ * @param state true to power on, false to power off
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_framebuffer_set_power(bool state)
+{
+ return hybris_device_fb_set_power(state);
+}
+
+/* ========================================================================= *
+ * DISPLAY_BACKLIGHT_BRIGHTNESS
+ * ========================================================================= */
+
+/** Initialize libhybris display backlight device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_backlight_init(void)
+{
+ return hybris_device_backlight_init();
+}
+
+/** Release libhybris display backlight device object
+ */
+void
+mce_hybris_backlight_quit(void)
+{
+ hybris_device_backlight_quit();
+}
+
+/** Set display backlight brightness via libhybris
+ *
+ * @param level 0=off ... 255=maximum brightness
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_backlight_set_brightness(int level)
+{
+ return hybris_device_backlight_set_brightness(level);
+}
+
+/* ========================================================================= *
+ * KEYPAD_BACKLIGHT_BRIGHTNESS
+ * ========================================================================= */
+
+/** Initialize libhybris keypad backlight device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_keypad_init(void)
+{
+ return hybris_device_keypad_init();
+}
+
+/** Release libhybris keypad backlight device object
+ */
+void
+mce_hybris_keypad_quit(void)
+{
+ hybris_device_keypad_quit();
+}
+
+/** Set display keypad brightness via libhybris
+ *
+ * @param level 0=off ... 255=maximum brightness
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_keypad_set_brightness(int level)
+{
+ return hybris_device_keypad_set_brightness(level);
+}
+
+/* ========================================================================= *
+ * INDICATOR_LED_PATTERN
+ * ========================================================================= */
+
+/** Clamp integer values to given range
+ *
+ * @param lo minimum value allowed
+ * @param hi maximum value allowed
+ * @param val value to clamp
+ *
+ * @return val clamped to [lo, hi]
+ */
+static inline int
+clamp_to_range(int lo, int hi, int val)
+{
+ return val <= lo ? lo : val <= hi ? val : hi;
+}
+
+/** Flag for: controls for RGB leds exist in sysfs */
+static bool mce_hybris_indicator_uses_sysfs = false;
+
+/** Initialize libhybris indicator led device object
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_indicator_init(void)
+{
+ static bool done = false;
+ static bool ack = false;
+
+ if( done ) {
+ goto cleanup;
+ }
+
+ done = true;
+
+ if( sysfs_led_init() ) {
+ mce_hybris_indicator_uses_sysfs = true;
+ }
+ else if( !hybris_device_indicator_init() ) {
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ mce_log(LL_DEBUG, "res = %s", ack ? "true" : "false");
+
+ return ack;
+}
+
+/** Release libhybris indicator led device object
+ */
+void
+mce_hybris_indicator_quit(void)
+{
+ if( mce_hybris_indicator_uses_sysfs ) {
+ /* Release sysfs controls */
+ sysfs_led_quit();
+ }
+ else {
+ /* Release libhybris controls */
+ hybris_device_indicator_quit();
+ }
+}
+
+/** Set indicator led pattern via libhybris
+ *
+ * @param r red intensity 0 ... 255
+ * @param g green intensity 0 ... 255
+ * @param b blue intensity 0 ... 255
+ * @param ms_on milliseconds to keep the led on, or 0 for no flashing
+ * @param ms_on milliseconds to keep the led off, or 0 for no flashing
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_indicator_set_pattern(int r, int g, int b, int ms_on, int ms_off)
+{
+ bool ack = false;
+
+ /* Sanitize input values */
+
+ /* Clamp time periods to [0, 60] second range.
+ *
+ * While periods longer than few seconds might not count as "blinking",
+ * we need to leave some slack to allow beacon style patterns with
+ * relatively long off periods */
+ ms_on = clamp_to_range(0, 60000, ms_on);
+ ms_off = clamp_to_range(0, 60000, ms_off);
+
+ /* Both on and off periods need to be non-zero for the blinking
+ * to happen in the first place. And if the periods are too
+ * short it starts to look like led failure more than indication
+ * of something. */
+ if( ms_on < 50 || ms_off < 50 ) {
+ ms_on = ms_off = 0;
+ }
+
+ /* Clamp rgb values to [0, 255] range */
+ r = clamp_to_range(0, 255, r);
+ g = clamp_to_range(0, 255, g);
+ b = clamp_to_range(0, 255, b);
+
+ /* Use raw sysfs controls if possible */
+
+ if( mce_hybris_indicator_uses_sysfs ) {
+ ack = sysfs_led_set_pattern(r, g, b, ms_on, ms_off);
+ }
+ else {
+ ack = hybris_device_indicator_set_pattern(r, g, b, ms_on, ms_off);
+ }
+
+ mce_log(LL_DEBUG, "pattern(%d,%d,%d,%d,%d) -> %s",
+ r,g,b, ms_on, ms_off , ack ? "success" : "failure");
+
+ return ack;
+}
+
+/** Query if currently active led backend can support breathing
+ *
+ * @return true if breathing can be requested, false otherwise
+ */
+bool
+mce_hybris_indicator_can_breathe(void)
+{
+ bool ack = false;
+
+ /* Note: We can't know how access via hybris behaves, so err
+ * on the safe side and assume that breathing is not ok
+ * unless we have direct sysfs controls.
+ */
+
+ if( mce_hybris_indicator_uses_sysfs )
+ {
+ ack = sysfs_led_can_breathe();
+ }
+
+ /* The result does not change during runtime of mce, so
+ * log only once */
+
+ static bool logged = false;
+
+ if( !logged )
+ {
+ logged = true;
+ mce_log(LL_DEBUG, "res = %s", ack ? "true" : "false");
+ }
+
+ return ack;
+}
+
+/** Enable/disable sw breathing
+ *
+ * @param enable true to enable sw breathing, false to disable
+ */
+void
+mce_hybris_indicator_enable_breathing(bool enable)
+{
+ mce_log(LL_DEBUG, "enable = %s", enable ? "true" : "false");
+
+ if( mce_hybris_indicator_uses_sysfs ) {
+ sysfs_led_set_breathing(enable);
+ }
+}
+
+/** Set indicator led brightness
+ *
+ * @param level 1=minimum, 255=maximum
+ *
+ * @return true on success, or false on failure
+ */
+bool
+mce_hybris_indicator_set_brightness(int level)
+{
+ mce_log(LL_DEBUG, "level = %d", level);
+
+ if( mce_hybris_indicator_uses_sysfs ) {
+ /* Clamp brightness values to [1, 255] range */
+ level = clamp_to_range(1, 255, level);
+
+ sysfs_led_set_brightness(level);
+ }
+
+ /* Note: failure means this function is not available - which is
+ * handled at mce side stub. From this plugin we always return true */
+ return true;
+}
+
+/* ========================================================================= *
+ * PROXIMITY_SENSOR
+ * ========================================================================= */
+
+/** Start using proximity sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_ps_init(void)
+{
+ return hybris_sensor_ps_init();
+}
+
+/** Stop using proximity sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+void
+mce_hybris_ps_quit(void)
+{
+ hybris_sensor_ps_quit();
+}
+
+/** Set proximity sensort input enabled state
+ *
+ * @param state true to enable input, or false to disable input
+ */
+bool
+mce_hybris_ps_set_active(bool state)
+{
+ return hybris_sensor_ps_set_active(state);
+}
+
+/** Set callback function for handling proximity sensor events
+ *
+ * Note: the callback function will be called from worker thread.
+ */
+void
+mce_hybris_ps_set_hook(mce_hybris_ps_fn cb)
+{
+ hybris_sensor_ps_set_hook(cb);
+}
+
+/* ========================================================================= *
+ * AMBIENT_LIGHT_SENSOR
+ * ========================================================================= */
+
+/** Start using ambient light sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+bool
+mce_hybris_als_init(void)
+{
+ return hybris_device_als_init();
+}
+
+/** Stop using ambient light sensor via libhybris
+ *
+ * @return true on success, false on failure
+ */
+void
+mce_hybris_als_quit(void)
+{
+ hybris_device_als_quit();
+}
+
+/** Set ambient light sensor input enabled state
+ *
+ * @param state true to enable input, or false to disable input
+ */
+bool
+mce_hybris_als_set_active(bool state)
+{
+ return hybris_device_als_set_active(state);
+}
+
+/** Set callback function for handling ambient light sensor events
+ *
+ * Note: the callback function will be called from worker thread.
+ */
+void
+mce_hybris_als_set_hook(mce_hybris_als_fn cb)
+{
+ hybris_device_als_set_hook(cb);
+}
+
+/* ========================================================================= *
+ * GENERIC
+ * ========================================================================= */
+
+/** Release all resources allocated by this module
+ */
+void
+mce_hybris_quit(void)
+{
+ hybris_plugin_fb_unload();
+ hybris_plugin_lights_unload();
+ hybris_plugin_sensors_unload();
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-api.h
^
|
@@ -0,0 +1,131 @@
+/** @file plugin-api.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* FIXME: This header is included in sourcetrees of both mce and
+ * mce-plugin-libhybris. For now it must be kept in sync
+ * manually.
+ */
+
+#ifndef MCE_HYBRIS_H_
+# define MCE_HYBRIS_H_
+
+# ifndef MCE_HYBRIS_INTERNAL
+# define MCE_HYBRIS_INTERNAL 0
+# endif
+
+# include <stdint.h>
+# include <stdbool.h>
+
+# ifdef __cplusplus
+extern "C" {
+# elif 0
+} /* fool JED indentation ... */
+# endif
+
+# pragma GCC visibility push(default)
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * frame buffer power state
+ * - - - - - - - - - - - - - - - - - - - */
+
+bool mce_hybris_framebuffer_init(void);
+void mce_hybris_framebuffer_quit(void);
+bool mce_hybris_framebuffer_set_power(bool on);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * display backlight brightness
+ * - - - - - - - - - - - - - - - - - - - */
+
+bool mce_hybris_backlight_init(void);
+void mce_hybris_backlight_quit(void);
+bool mce_hybris_backlight_set_brightness(int level);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * keypad backlight brightness
+ * - - - - - - - - - - - - - - - - - - - */
+
+bool mce_hybris_keypad_set_brightness(int level);
+void mce_hybris_keypad_quit(void);
+bool mce_hybris_keypad_init(void);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * indicator led pattern
+ * - - - - - - - - - - - - - - - - - - - */
+
+bool mce_hybris_indicator_init(void);
+void mce_hybris_indicator_quit(void);
+bool mce_hybris_indicator_set_pattern(int r, int g, int b, int ms_on, int ms_off);
+void mce_hybris_indicator_enable_breathing(bool enable);
+bool mce_hybris_indicator_set_brightness(int level);
+bool mce_hybris_indicator_can_breathe(void);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * proximity sensor
+ * - - - - - - - - - - - - - - - - - - - */
+
+typedef void (*mce_hybris_ps_fn)(int64_t timestamp, float distance);
+
+bool mce_hybris_ps_init(void);
+void mce_hybris_ps_quit(void);
+bool mce_hybris_ps_set_active(bool active);
+bool mce_hybris_ps_set_callback(mce_hybris_ps_fn cb);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * ambient light sensor
+ * - - - - - - - - - - - - - - - - - - - */
+
+typedef void (*mce_hybris_als_fn)(int64_t timestamp, float light);
+
+bool mce_hybris_als_init(void);
+void mce_hybris_als_quit(void);
+bool mce_hybris_als_set_active(bool active);
+bool mce_hybris_als_set_callback(mce_hybris_als_fn cb);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * generic
+ * - - - - - - - - - - - - - - - - - - - */
+
+void mce_hybris_quit(void);
+
+/* - - - - - - - - - - - - - - - - - - - *
+ * internal to module <--> plugin
+ * - - - - - - - - - - - - - - - - - - - */
+
+# if MCE_HYBRIS_INTERNAL >= 1
+typedef void (*mce_hybris_log_fn)(int lev, const char *file, const char *func,
+ const char *text);
+# endif
+
+# if MCE_HYBRIS_INTERNAL >= 2
+void mce_hybris_set_log_hook(mce_hybris_log_fn cb);
+void mce_hybris_ps_set_hook(mce_hybris_ps_fn cb);
+void mce_hybris_als_set_hook(mce_hybris_als_fn cb);
+# endif
+
+# pragma GCC visibility pop
+
+# ifdef __cplusplus
+};
+# endif
+
+#endif /* MCE_HYBRIS_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-config.c
^
|
@@ -0,0 +1,162 @@
+/** @file plugin-config.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "plugin-config.h"
+
+#include "plugin-logging.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* ========================================================================= *
+ * SETTINGS
+ * ========================================================================= */
+
+gchar *
+plugin_config_get_string(const gchar *group,
+ const gchar *key,
+ const gchar *defaultval)
+{
+ extern gboolean mce_conf_has_key(const gchar *group,
+ const gchar *key);
+
+ extern gchar *mce_conf_get_string(const gchar *group,
+ const gchar *key,
+ const gchar *defaultval);
+
+ gchar *res = 0;
+
+ /* From MCE point of view it is suspicious if code tries to
+ * access settings that are not defined and warning is emitted
+ * in such cases. Whereas from this plugin point of view all
+ * settings are optional -> check that key actually exists before
+ * attempting to fetch the value to avoid unwanted logging. */
+ if( !mce_conf_has_key(group, key) )
+ res = defaultval ? g_strdup(defaultval) : 0;
+ else
+ res = mce_conf_get_string(group, key, defaultval);
+
+ mce_log(LOG_DEBUG, "[%s] %s = %s", group, key, res ?: "(null)");
+
+ return res;
+}
+
+static inline void *lea(const void *base, int offs)
+{
+ return ((char *)base)+offs;
+}
+
+/** Set all configurable dynamic data to null
+ *
+ * @param cfg configuration lookup table
+ * @param obj object to configure
+ */
+void
+objconf_init(const objconf_t *cfg, void *obj)
+{
+ for( size_t i = 0; cfg[i].key; ++i ) {
+ char **memb = lea(obj, cfg[i].off);
+ *memb = 0;
+ }
+}
+
+/** Release all configurable dynamic data
+ *
+ * @param cfg configuration lookup table
+ * @param obj object to configure
+ */
+void
+objconf_quit(const objconf_t *cfg, void *obj)
+{
+ for( size_t i = 0; cfg[i].key; ++i ) {
+ char **memb = lea(obj, cfg[i].off);
+ free(*memb), *memb = 0;
+ }
+}
+
+/** Parse all configurable dynamic data
+ *
+ * @param cfg configuration lookup table
+ * @param obj object to configure
+ *
+ * @return true if at least one member was set, false otherwise
+ */
+bool
+objconf_parse(const objconf_t *cfg, void *obj, const char *chn)
+{
+ int set = 0;
+ gchar *dir = 0;
+
+ char tmp[256];
+
+ /* Fetch channel/led directory in form of:
+ *
+ * <CHANNEL><Directory>=/sys/class/leds/red
+ *
+ * Where CHANNEL depends on backend but should be something
+ * like "Led" for single channel leds and "Red", "Green" etc
+ * for multichannel leds.
+ */
+ snprintf(tmp, sizeof tmp, "%sDirectory", chn);
+ dir = plugin_config_get_string(MCE_CONF_LED_CONFIG_HYBRIS_GROUP, tmp, 0);
+
+ for( size_t i = 0; cfg[i].key; ++i ) {
+ char **memb = lea(obj, cfg[i].off);
+
+ /* Fetch absolute control file path in form of
+ * <CHANNEL><MEMBER>File=sys/class/leds/red/brightness
+ *
+ * Where MEMBER is "Brightness", "MaxBrightness", etc
+ */
+ snprintf(tmp, sizeof tmp, "%s%sFile", chn, cfg[i].key);
+ gchar *val = plugin_config_get_string(MCE_CONF_LED_CONFIG_HYBRIS_GROUP,
+ tmp, 0);
+ if( val ) {
+ snprintf(tmp, sizeof tmp, "%s/%s", dir, val);
+ free(*memb), *memb = strdup(tmp);
+ g_free(val);
+ }
+ else if( dir ) {
+ /* Fetch control file path relative to directory
+ *
+ * <MEMBER>File=brightness
+ */
+ snprintf(tmp, sizeof tmp, "%sFile", cfg[i].key);
+ val = plugin_config_get_string(MCE_CONF_LED_CONFIG_HYBRIS_GROUP,
+ tmp, cfg[i].def);
+ if( val ) {
+ snprintf(tmp, sizeof tmp, "%s/%s", dir, val);
+ free(*memb), *memb = strdup(tmp);
+ g_free(val);
+ }
+ }
+ set += (*memb != 0);
+
+ mce_log(LOG_DEBUG, "%s:%s = %s", chn, cfg[i].key, *memb ?: "NA");
+ }
+
+ g_free(dir);
+
+ return set > 0;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-config.h
^
|
@@ -0,0 +1,93 @@
+/** @file plugin-config.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PLUGIN_CONFIG_H_
+# define PLUGIN_CONFIG_H_
+
+# include "plugin-logging.h"
+
+# include <stdbool.h>
+
+# include <glib.h>
+
+/* ========================================================================= *
+ * CONFIG
+ * ========================================================================= */
+
+/** Configuration group for mce-plugin-libhybris related values */
+#define MCE_CONF_LED_CONFIG_HYBRIS_GROUP "LEDConfigHybris"
+
+/** Name of the LED backend to use */
+#define MCE_CONF_LED_CONFIG_HYBRIS_BACKEND "BackEnd"
+
+/** Optional enable/disable sw breathing setting */
+#define MCE_CONF_LED_CONFIG_HYBRIS_BREATHING "QuirkBreathing"
+
+gchar * plugin_config_get_string(const gchar *group, const gchar *key, const gchar *defaultval);
+
+/** Inifile to object member mapping info */
+typedef struct
+{
+ /** Ini-file key */
+ const char *key;
+
+ /** Fallback value in case key is not defined */
+ const char *def;
+
+ /** Offset within object where to store string value */
+ off_t off;
+} objconf_t;
+
+/** Object configuration entry sentinel */
+#define OBJCONF_STOP \
+ {\
+ .key = 0,\
+ }
+
+/** Object configuration entry for file path
+ *
+ * For object->member matches /sys/dir/member
+ */
+#define OBJCONF_FILE(obj_,memb_,key_)\
+ {\
+ .key = #key_,\
+ .def = #memb_,\
+ .off = offsetof(obj_,memb_),\
+ }
+
+/** Object configuration entry for file path
+ *
+ * For object->member does not match /sys/dir/member
+ */
+#define OBJCONF_FILE_EX(obj_,memb_,key_,def_)\
+ {\
+ .key = #key_,\
+ .def = def_,\
+ .off = offsetof(obj_,memb_),\
+ }
+
+void objconf_init(const objconf_t *cfg, void *obj);
+void objconf_quit(const objconf_t *cfg, void *obj);
+bool objconf_parse(const objconf_t *cfg, void *obj, const char *chn);
+
+#endif /* PLUGIN_CONFIG_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-logging.c
^
|
@@ -0,0 +1,88 @@
+/** @file plugin-logging.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "plugin-logging.h"
+
+#include "plugin-api.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+void mce_hybris_set_log_hook(mce_hybris_log_fn cb);
+void mce_hybris_log (int lev, const char *file, const char *func, const char *fmt, ...);
+
+/* ========================================================================= *
+ * DATA
+ * ========================================================================= */
+
+/** Callback function for diagnostic output, or NULL for stderr output */
+static mce_hybris_log_fn mce_hybris_log_cb = 0;
+
+/* ========================================================================= *
+ * FUNCTIONS
+ * ========================================================================= */
+
+/** Set diagnostic output forwarding callback
+ *
+ * @param cb The callback function to use, or NULL for stderr output
+ */
+void
+mce_hybris_set_log_hook(mce_hybris_log_fn cb)
+{
+ mce_hybris_log_cb = cb;
+}
+
+/** Wrapper for diagnostic logging
+ *
+ * @param lev syslog priority (=mce_log level) i.e. LL_ERR etc
+ * @param file source code path
+ * @param func name of function within file
+ * @param fmt printf compatible format string
+ * @param ... parameters required by the format string
+ */
+void
+mce_hybris_log(int lev, const char *file, const char *func,
+ const char *fmt, ...)
+{
+ char *msg = 0;
+ va_list va;
+
+ va_start(va, fmt);
+ if( vasprintf(&msg, fmt, va) < 0 ) msg = 0;
+ va_end(va);
+
+ if( msg ) {
+ if( mce_hybris_log_cb ) {
+ mce_hybris_log_cb(lev, file, func, msg);
+ }
+ else {
+ fprintf(stderr, "%s: %s: %s\n", file, func, msg);
+ }
+ free(msg);
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-logging.h
^
|
@@ -0,0 +1,48 @@
+/** @file plugin-logging.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PLUGIN_LOGGING_H_
+# define PLUGIN_LOGGING_H_
+
+# include <syslog.h>
+
+/** MCE logging priorities
+ */
+enum
+{
+ LL_CRIT = LOG_CRIT, /**< Critical error */
+ LL_ERR = LOG_ERR, /**< Error */
+ LL_WARN = LOG_WARNING, /**< Warning */
+ LL_NOTICE = LOG_NOTICE, /**< Normal but noteworthy */
+ LL_INFO = LOG_INFO, /**< Informational message */
+ LL_DEBUG = LOG_DEBUG, /**< Useful when debugging */
+};
+
+void mce_hybris_log(int lev, const char *file, const char *func,
+ const char *fmt, ...) __attribute__ ((format (printf, 4, 5)));
+
+/** Logging from hybris plugin mimics mce-log.h API */
+# define mce_log(LEV,FMT,ARGS...) \
+ mce_hybris_log(LEV, __FILE__, __FUNCTION__ ,FMT, ## ARGS)
+
+#endif /* PLUGIN_LOGGING_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-quirks.c
^
|
@@ -0,0 +1,188 @@
+/** @file plugin-quirks.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "plugin-quirks.h"
+
+#include "plugin-config.h"
+#include "plugin-logging.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+/* ========================================================================= *
+ * QUIRKS
+ * ========================================================================= */
+
+/** Strings that should be treated as "1" when evaluating quirk settings */
+static const char * const quirk_true_lut[] =
+{
+ "true", "yes", "enabled", 0
+};
+
+/** Strings that should be treated as "0" when evaluating quirk settings */
+static const char * const quirk_false_lut[] =
+{
+ "false", "no", "disabled", 0
+};
+
+/** Quirk enum id to settings ini-file key lookup table */
+static const char * const quirk_name_lut[QUIRK_COUNT] =
+{
+ [QUIRK_BREATHING] = MCE_CONF_LED_CONFIG_HYBRIS_BREATHING,
+};
+
+/** Flag array for: quirk setting has been defined in mce config */
+static bool quirk_defined_lut[QUIRK_COUNT];
+
+/** Value array for: quirk settings defined in mce config */
+static int quirk_value_lut[QUIRK_COUNT];
+
+/** Helper for checking string exists in an array
+ *
+ * @param vec Array of strings
+ * @param str String to look for
+ *
+ * @return true if string exists in array, false otherwise
+ */
+static bool
+quirk_in_array(const char * const *vec, const char *str)
+{
+ for( ; *vec; ++vec )
+ if( !strcmp(*vec, str) )
+ return true;
+
+ return false;
+}
+
+/** Helper for parsing integer quirk setting values
+ *
+ * To allow improved readability, various aliases for boolean
+ * type values are converted to true/1 or false/0.
+ *
+ * @param str String value from ini-file
+ *
+ * @return Integer value, or zero as fallback value
+ */
+static int
+quirk_parse_value(const char *str)
+{
+ int val = false;
+
+ if( !str )
+ goto EXIT;
+
+ if( quirk_in_array(quirk_false_lut, str) )
+ goto EXIT;
+
+ val = true;
+
+ if( quirk_in_array(quirk_true_lut, str) )
+ goto EXIT;
+
+ val = strtol(str, 0, 0);
+
+EXIT:
+ return val;
+}
+
+/** Populate quirk value array using data from mce configuration files
+ */
+static void
+plugin_quirk_init(void)
+{
+ for( quirk_t id = 0; id < QUIRK_COUNT; ++id ) {
+ gchar *val = plugin_config_get_string(MCE_CONF_LED_CONFIG_HYBRIS_GROUP,
+ quirk_name_lut[id], 0);
+ if( !val )
+ continue;
+
+ quirk_defined_lut[id] = true;
+ quirk_value_lut[id] = quirk_parse_value(val);
+ mce_log(LOG_DEBUG, "set %s = %d",
+ quirk_name_lut[id],
+ quirk_value_lut[id]);
+ g_free(val);
+ }
+}
+
+/** Predicat for: numerical quirk id is valid
+ *
+ * @param id Quirk ID
+ *
+ * @return true if id is valid, false otherwise
+ */
+static bool
+quirk_is_valid(quirk_t id)
+{
+ return id > QUIRK_INVALID && id < QUIRK_COUNT && quirk_name_lut[id];
+}
+
+/** Predicat for: Value for quirk id has been defined in configuration
+ *
+ * @param id Quirk ID
+ *
+ * @return true if id is valid and defined, false otherwise
+ */
+static bool
+quirk_is_defined(quirk_t id)
+{
+ return quirk_is_valid(id) && quirk_defined_lut[id];
+}
+
+/** Get human readable name for a quirk id
+ *
+ * @param id Quirk ID
+ *
+ * @return quirk name used in setting ini-files, or "QuirkInvalid"
+ */
+const char *
+quirk_name(quirk_t id)
+{
+ const char *repr = 0;
+
+ if( quirk_is_valid(id) )
+ repr = quirk_name_lut[id];
+
+ return repr ?: "QuirkInvalid";
+}
+
+/* Get value associated with quirk id
+ *
+ * @param id Quirk ID
+ * @param def Fallback value
+ *
+ * @return Configured quirk value, or the caller provided default value
+ */
+int
+quirk_value(quirk_t id, int def)
+{
+ static bool done = false;
+
+ if( !done ) {
+ done = true;
+ plugin_quirk_init();
+ }
+
+ return quirk_is_defined(id) ? quirk_value_lut[id] : def;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/plugin-quirks.h
^
|
@@ -0,0 +1,64 @@
+/** @file plugin-quirks.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PLUGIN_QUIRKS_H_
+# define PLUGIN_QUIRKS_H_
+
+# include "plugin-logging.h"
+
+/* ========================================================================= *
+ * QUIRKS
+ * ========================================================================= */
+
+/** Quirk setting IDs */
+typedef enum
+{
+ /** Placeholder ID */
+ QUIRK_INVALID = -1,
+
+ /** Override sw breathing desicion made by led backend */
+ QUIRK_BREATHING,
+
+ /** Number of quirks */
+ QUIRK_COUNT
+} quirk_t;
+
+const char *quirk_name(quirk_t id);
+
+int quirk_value(quirk_t id, int def);
+
+/** Helper for caching quirk value locally and logging use for debug purposes
+ */
+#define QUIRK(id,def) ({\
+ static bool done = false;\
+ static int value = 0;\
+ if( !done ) {\
+ done = true;\
+ value = quirk_value((id),(def));\
+ mce_log(LOG_DEBUG, "use %s = %d",\
+ quirk_name((id)), value);\
+ }\
+ value;\
+})
+
+#endif /* PLUGIN_QUIRKS_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-bacon.c
^
|
@@ -0,0 +1,365 @@
+/** @file sysfs-led-bacon.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @Author Willem-Jan de Hoog <wdehoog@exalondelft.nl>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * RGB led control: bacon backend
+ *
+ * Three channels, all of which:
+ * - must have 'brightness' control file
+ * - must have 'grpfreq', 'grppwm' and 'blink' to blink delay control file
+ * - must have 'reset' control file
+ *
+ * Based on code from device/oneplus/bacon/liblight/lights.c
+ * ========================================================================= */
+
+#include "sysfs-led-bacon.h"
+
+#include "sysfs-led-util.h"
+#include "plugin-logging.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *brightness;
+ const char *grpfreq;
+ const char *grppwm;
+ const char *blink;
+ const char *ledreset;
+} led_paths_bacon_t;
+
+typedef struct
+{
+ int fd_brightness;
+ int fd_grpfreq;
+ int fd_grppwm;
+ int fd_blink;
+ int fd_ledreset;
+
+ int brightness;
+ int freq;
+ int pwm;
+ int blink;
+ int maxval;
+} led_channel_bacon_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_bacon_init (led_channel_bacon_t *self);
+static void led_channel_bacon_close (led_channel_bacon_t *self);
+static bool led_channel_bacon_probe (led_channel_bacon_t *self, const led_paths_bacon_t *path);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_bacon_enable_cb (void *data, bool enable);
+static void led_control_bacon_blink_cb (void *data, int on_ms, int off_ms);
+static void led_control_bacon_value_cb (void *data, int r, int g, int b);
+static void led_control_bacon_close_cb (void *data);
+
+bool led_control_bacon_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_bacon_init(led_channel_bacon_t *self)
+{
+ self->fd_brightness = -1;
+ self->fd_grpfreq = -1;
+ self->fd_grppwm = -1;
+ self->fd_blink = -1;
+ self->fd_ledreset = -1;
+
+ self->blink = 0;
+ self->maxval = 255; // load from max_brightness?
+}
+
+static void
+led_channel_bacon_close(led_channel_bacon_t *self)
+{
+ led_util_close_file(&self->fd_brightness);
+ led_util_close_file(&self->fd_grpfreq);
+ led_util_close_file(&self->fd_grppwm);
+ led_util_close_file(&self->fd_blink);
+ led_util_close_file(&self->fd_ledreset);
+}
+
+static bool
+led_channel_bacon_probe(led_channel_bacon_t *self,
+ const led_paths_bacon_t *path)
+{
+ bool res = false;
+
+ led_channel_bacon_close(self);
+
+ if( !led_util_open_file(&self->fd_brightness, path->brightness) ||
+ !led_util_open_file(&self->fd_grpfreq, path->grpfreq) ||
+ !led_util_open_file(&self->fd_grppwm, path->grppwm) ||
+ !led_util_open_file(&self->fd_blink, path->blink) ||
+ !led_util_open_file(&self->fd_ledreset, path->ledreset))
+ {
+ goto cleanup;
+ }
+
+ res = true;
+
+cleanup:
+
+ if( !res ) led_channel_bacon_close(self);
+
+ return res;
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define BACON_CHANNELS 3
+
+static void
+led_control_bacon_enable_cb(void *data, bool enable)
+{
+ const led_channel_bacon_t *channel = data;
+ mce_log(LL_INFO, "led_control_bacon_enable_cb(%d)", enable);
+
+ if(!enable)
+ dprintf(channel->fd_ledreset, "%d", 1);
+}
+
+static void
+led_control_bacon_blink_cb(void *data, int on_ms, int off_ms)
+{
+ led_channel_bacon_t *channel = data;
+ mce_log(LL_INFO, "led_control_bacon_blink_cb(%d,%d)", on_ms, off_ms);
+
+ if( on_ms > 0 && off_ms > 0 ) {
+ int totalMS = on_ms + off_ms;
+
+ // the LED appears to blink about once per second if freq is 20
+ // 1000ms / 20 = 50
+ channel->freq = totalMS / 50;
+
+ // pwm specifies the ratio of ON versus OFF
+ // pwm = 0 -> always off
+ // pwm = 255 => always on
+ channel->pwm = (on_ms * 255) / totalMS;
+
+ // the low 4 bits are ignored, so round up if necessary
+ if( channel->pwm > 0 && channel->pwm < 16 )
+ channel->pwm = 16;
+
+ channel->blink = 1;
+ } else {
+ channel->blink = 0;
+ channel->freq = 0;
+ channel->pwm = 0;
+ }
+
+ if( channel->blink ) {
+ dprintf(channel->fd_grpfreq, "%d", channel->freq);
+ dprintf(channel->fd_grppwm, "%d", channel->pwm);
+ }
+ dprintf(channel->fd_blink, "%d", channel->blink);
+}
+
+static void
+led_control_bacon_value_cb(void *data, int r, int g, int b)
+{
+ led_channel_bacon_t *channel = data;
+
+ mce_log(LL_INFO, "led_control_bacon_value_cb(%d,%d,%d), blink=%d", r, g, b, channel->blink);
+ if( channel->blink )
+ dprintf(channel->fd_ledreset, "%d", 0);
+
+ (channel+0)->brightness = led_util_scale_value(r, (channel+0)->maxval);
+ (channel+1)->brightness = led_util_scale_value(g, (channel+1)->maxval);
+ (channel+2)->brightness = led_util_scale_value(b, (channel+2)->maxval);
+
+ dprintf((channel+0)->fd_brightness, "%d", (channel+0)->brightness);
+ dprintf((channel+1)->fd_brightness, "%d", (channel+1)->brightness);
+ dprintf((channel+2)->fd_brightness, "%d", (channel+2)->brightness);
+
+ if( channel->blink ) {
+ // need to reset the blink when changing color (do we?)
+ dprintf(channel->fd_grpfreq, "%d", channel->freq); // 1s
+ dprintf(channel->fd_grppwm, "%d", channel->pwm); // 50%?
+ dprintf(channel->fd_blink, "%d", 1);
+ } else
+ dprintf(channel->fd_blink, "%d", 0);
+}
+
+static void
+led_control_bacon_close_cb(void *data)
+{
+ led_channel_bacon_t *channel = data;
+ led_channel_bacon_close(channel + 0);
+ led_channel_bacon_close(channel + 1);
+ led_channel_bacon_close(channel + 2);
+}
+
+static bool
+led_control_bacon_static_probe(led_channel_bacon_t *channel)
+{
+ /** Sysfs control paths for RGB leds */
+ static const led_paths_bacon_t paths[][BACON_CHANNELS] =
+ {
+ // bacon
+ {
+ {
+ .brightness = "/sys/class/leds/red/brightness",
+ .grpfreq = "/sys/class/leds/red/device/grpfreq",
+ .grppwm = "/sys/class/leds/red/device/grppwm",
+ .blink = "/sys/class/leds/red/device/blink",
+ .ledreset = "/sys/class/leds/red/device/ledreset",
+ },
+ {
+ .brightness = "/sys/class/leds/green/brightness",
+ .grpfreq = "/sys/class/leds/green/device/grpfreq",
+ .grppwm = "/sys/class/leds/green/device/grppwm",
+ .blink = "/sys/class/leds/green/device/blink",
+ .ledreset = "/sys/class/leds/green/device/ledreset",
+ },
+ {
+ .brightness = "/sys/class/leds/blue/brightness",
+ .grpfreq = "/sys/class/leds/blue/device/grpfreq",
+ .grppwm = "/sys/class/leds/blue/device/grppwm",
+ .blink = "/sys/class/leds/blue/device/blink",
+ .ledreset = "/sys/class/leds/blue/device/ledreset",
+ }
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( led_channel_bacon_probe(&channel[0], &paths[i][0]) &&
+ led_channel_bacon_probe(&channel[1], &paths[i][1]) &&
+ led_channel_bacon_probe(&channel[2], &paths[i][2]) ) {
+ ack = true;
+ break;
+ }
+ }
+
+ return ack;
+}
+
+static bool
+led_control_bacon_dynamic_probe(led_channel_bacon_t *channel)
+{
+ /* See inifiles/60-bacon.ini for example config file */
+ static const objconf_t bacon_conf[] =
+ {
+ OBJCONF_FILE(led_paths_bacon_t, brightness, Brightness),
+#if 0 // load from max_brightness?
+ OBJCONF_FILE(led_paths_bacon_t, max_brightness, MaxBrightness),
+#endif
+ OBJCONF_FILE_EX(led_paths_bacon_t, grpfreq, GrpFreq,
+ "device/grpfreq"),
+ OBJCONF_FILE_EX(led_paths_bacon_t, grppwm, GrpPwm,
+ "device/grppwm"),
+ OBJCONF_FILE_EX(led_paths_bacon_t, blink, Blink,
+ "device/blink"),
+ OBJCONF_FILE_EX(led_paths_bacon_t, ledreset, LedReset,
+ "device/ledreset"),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[BACON_CHANNELS] =
+ {
+ "Red", "Green", "Blue"
+ };
+
+ bool ack = false;
+
+ led_paths_bacon_t paths[BACON_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < BACON_CHANNELS; ++i )
+ objconf_init(bacon_conf, &paths[i]);
+
+ for( size_t i = 0; i < BACON_CHANNELS; ++i )
+ {
+ if( !objconf_parse(bacon_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_bacon_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < BACON_CHANNELS; ++i )
+ objconf_quit(bacon_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_bacon_probe(led_control_t *self)
+{
+
+ static led_channel_bacon_t channel[BACON_CHANNELS];
+
+ bool res = false;
+
+ led_channel_bacon_init(channel+0);
+ led_channel_bacon_init(channel+1);
+ led_channel_bacon_init(channel+2);
+
+ self->name = "bacon";
+ self->data = channel;
+ self->enable = led_control_bacon_enable_cb;
+ self->blink = led_control_bacon_blink_cb;
+ self->value = led_control_bacon_value_cb;
+ self->close = led_control_bacon_close_cb;
+
+ // need to check
+ self->can_breathe = false;
+
+ if( self->use_config )
+ res = led_control_bacon_dynamic_probe(channel);
+
+ if( !res )
+ res = led_control_bacon_static_probe(channel);
+
+ if( !res )
+ led_control_close(self);
+
+ return res;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-bacon.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-bacon.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_BACON_H_
+# define SYSFS_LED_BACON_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_bacon_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_BACON_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-binary.c
^
|
@@ -0,0 +1,268 @@
+/** @file sysfs-led-binary.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * Binary led control: Jolla C backend
+ *
+ * One channel, which:
+ * - must have 'brightness' control file
+ *
+ * Assumptions built into code:
+ * - Using zero brightness disables led, any non-zero value enables it -> If
+ * mce requests "black" rgb value, use brightness of zero - otherwise 255.
+ * ========================================================================= */
+
+#include "sysfs-led-binary.h"
+
+#include "sysfs-led-util.h"
+#include "sysfs-val.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *brightness;
+ const char *max_brightness;
+} led_paths_binary_t;
+
+typedef struct
+{
+ sysfsval_t *cached_max_brightness;
+ sysfsval_t *cached_brightness;
+} led_channel_binary_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_binary_init (led_channel_binary_t *self);
+static void led_channel_binary_close (led_channel_binary_t *self);
+static bool led_channel_binary_probe (led_channel_binary_t *self, const led_paths_binary_t *path);
+static void led_channel_binary_set_value (led_channel_binary_t *self, int value);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_binary_map_color (int r, int g, int b, int *mono);
+static void led_control_binary_value_cb (void *data, int r, int g, int b);
+static void led_control_binary_close_cb (void *data);
+
+bool led_control_binary_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_binary_init(led_channel_binary_t *self)
+{
+ self->cached_max_brightness = sysfsval_create();
+ self->cached_brightness = sysfsval_create();
+}
+
+static void
+led_channel_binary_close(led_channel_binary_t *self)
+{
+ sysfsval_delete(self->cached_max_brightness),
+ self->cached_max_brightness = 0;
+
+ sysfsval_delete(self->cached_brightness),
+ self->cached_brightness = 0;
+}
+
+static bool
+led_channel_binary_probe(led_channel_binary_t *self,
+ const led_paths_binary_t *path)
+{
+ bool res = false;
+
+ if( !sysfsval_open_rw(self->cached_brightness, path->brightness) )
+ goto cleanup;
+
+ if( sysfsval_open_ro(self->cached_max_brightness, path->max_brightness) )
+ sysfsval_refresh(self->cached_max_brightness);
+
+ if( sysfsval_get(self->cached_max_brightness) <= 0 )
+ sysfsval_assume(self->cached_max_brightness, 1);
+
+ res = true;
+
+cleanup:
+
+ /* Always close the max_brightness file */
+ sysfsval_close(self->cached_max_brightness);
+
+ /* On failure close the other files too */
+ if( !res ) {
+ sysfsval_close(self->cached_brightness);
+ }
+
+ return res;
+}
+
+static void
+led_channel_binary_set_value(led_channel_binary_t *self, int value)
+{
+ value = led_util_scale_value(value,
+ sysfsval_get(self->cached_max_brightness));
+ sysfsval_set(self->cached_brightness, value);
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define BINARY_CHANNELS 1
+
+static void
+led_control_binary_map_color(int r, int g, int b, int *mono)
+{
+ /* Only binary on/off control is available, use
+ * 255 as logical level if nonzero rgb value has
+ * been requested.
+ */
+ *mono = (r || g || b) ? 255 : 0;
+}
+
+static void
+led_control_binary_value_cb(void *data, int r, int g, int b)
+{
+ led_channel_binary_t *channel = data;
+
+ int mono = 0;
+ led_control_binary_map_color(r, g, b, &mono);
+ led_channel_binary_set_value(channel + 0, mono);
+}
+
+static void
+led_control_binary_close_cb(void *data)
+{
+ led_channel_binary_t *channel = data;
+ led_channel_binary_close(channel + 0);
+}
+
+static bool
+led_control_binary_static_probe(led_channel_binary_t *channel)
+{
+ /** Sysfs control paths for binary leds */
+ static const led_paths_binary_t paths[][BINARY_CHANNELS] =
+ {
+ // binary
+ {
+ {
+ .brightness = "/sys/class/leds/button-backlight/brightness",
+ },
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( (ack = led_channel_binary_probe(channel+0, &paths[i][0])) )
+ break;
+ }
+
+ return ack;
+}
+
+static bool
+led_control_binary_dynamic_probe(led_channel_binary_t *channel)
+{
+ static const objconf_t binary_conf[] =
+ {
+ OBJCONF_FILE(led_paths_binary_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_binary_t, max_brightness, MaxBrightness),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[BINARY_CHANNELS] =
+ {
+ "Led",
+ };
+
+ bool ack = false;
+
+ led_paths_binary_t paths[BINARY_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < BINARY_CHANNELS; ++i )
+ objconf_init(binary_conf, &paths[i]);
+
+ for( size_t i = 0; i < BINARY_CHANNELS; ++i ) {
+ if( !objconf_parse(binary_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_binary_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < BINARY_CHANNELS; ++i )
+ objconf_quit(binary_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_binary_probe(led_control_t *self)
+{
+ static led_channel_binary_t channel[BINARY_CHANNELS];
+
+ bool res = false;
+
+ led_channel_binary_init(channel+0);
+
+ self->name = "binary";
+ self->data = channel;
+ self->enable = 0;
+ self->blink = 0;
+ self->value = led_control_binary_value_cb;
+ self->close = led_control_binary_close_cb;
+
+ /* We can use sw breathing logic to simulate hw blinking */
+ self->can_breathe = true;
+ self->breath_type = LED_RAMP_HARD_STEP;
+
+ if( self->use_config )
+ res = led_control_binary_dynamic_probe(channel);
+
+ if( !res )
+ res = led_control_binary_static_probe(channel);
+
+ if( !res )
+ led_control_close(self);
+
+ return res;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-binary.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-binary.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_BINARY_H_
+# define SYSFS_LED_BINARY_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_binary_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_BINARY_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-f5121.c
^
|
@@ -0,0 +1,382 @@
+/** @file sysfs-led-f5121.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ * @author Kimmo Lindholm <kimmo.lindholm@eke.fi>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * RGB led control: Sony Xperia X backend
+ *
+ * Three channels, all of which:
+ * - must have 'brightness' control file
+ * - must have 'max_brightness' control file
+ * - must have 'blink' control file
+ *
+ * Assumptions built into code:
+ * - writing to 'blink' affects 'brightness' control too and vice versa
+ * ========================================================================= */
+
+#include "sysfs-led-f5121.h"
+#include "sysfs-led-util.h"
+#include "sysfs-val.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *max_brightness;
+ const char *brightness;
+ const char *blink;
+} led_paths_f5121_t;
+
+typedef struct
+{
+ sysfsval_t *cached_max_brightness;
+ sysfsval_t *cached_brightness;
+ sysfsval_t *cached_blink;
+
+ int control_value;
+ bool control_blink;
+
+} led_channel_f5121_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_f5121_init (led_channel_f5121_t *self);
+static void led_channel_f5121_close (led_channel_f5121_t *self);
+static bool led_channel_f5121_probe (led_channel_f5121_t *self, const led_paths_f5121_t *path);
+static void led_channel_f5121_set_value (led_channel_f5121_t *self, int value);
+static void led_channel_f5121_set_blink (led_channel_f5121_t *self, int on_ms, int off_ms);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_f5121_blink_cb (void *data, int on_ms, int off_ms);
+static void led_control_f5121_value_cb (void *data, int r, int g, int b);
+static void led_control_f5121_close_cb (void *data);
+
+bool led_control_f5121_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_f5121_init(led_channel_f5121_t *self)
+{
+ self->cached_max_brightness = sysfsval_create();
+ self->cached_brightness = sysfsval_create();
+ self->cached_blink = sysfsval_create();
+
+ self->control_blink = false;
+ self->control_value = 0;
+}
+
+static void
+led_channel_f5121_close(led_channel_f5121_t *self)
+{
+ sysfsval_delete(self->cached_max_brightness),
+ self->cached_max_brightness = 0;
+
+ sysfsval_delete(self->cached_brightness),
+ self->cached_brightness = 0;
+
+ sysfsval_delete(self->cached_blink),
+ self->cached_blink = 0;
+}
+
+static bool
+led_channel_f5121_probe(led_channel_f5121_t *self,
+ const led_paths_f5121_t *path)
+{
+ bool ack = false;
+
+ /* Probe control files in reverse existance likelihood order.
+ * Practically all led control directories have 'brightness'
+ * file, most have 'max_brightness' while only some have 'blink'.
+ */
+ if( !sysfsval_open_rw(self->cached_blink, path->blink) )
+ goto cleanup;
+
+ if( !sysfsval_open_ro(self->cached_max_brightness, path->max_brightness) )
+ goto cleanup;
+
+ /* The 'max_brightness' seems to be dynamic. Make an attempt
+ * to set it to an artificially high value and assume that kernel
+ * side will cap the value to the true maximum... */
+#if 0 // TODO: make a QUIRK out of this
+ sysfsval_set(self->cached_max_brightness, 255);
+#endif
+ sysfsval_refresh(self->cached_max_brightness);
+
+ if( sysfsval_get(self->cached_max_brightness) <= 0 )
+ goto cleanup;
+
+ if( !sysfsval_open_rw(self->cached_brightness, path->brightness) )
+ goto cleanup;
+
+ ack = true;
+
+cleanup:
+
+ /* Always close the max_brightness file */
+ sysfsval_close(self->cached_max_brightness);
+
+ /* On failure close the other files too */
+ if( !ack ) {
+ sysfsval_close(self->cached_brightness);
+ sysfsval_close(self->cached_blink);
+ }
+
+ return ack;
+}
+
+static void
+led_channel_f5121_set_value(led_channel_f5121_t *self,
+ int value)
+{
+ value = led_util_scale_value(value,
+ sysfsval_get(self->cached_max_brightness));
+
+ /* Ignore blinking requests while brightness is zero. */
+ if( value <= 0 )
+ self->control_blink = false;
+
+ /* Logically it probably should be that:
+ * - writing blink=1 implies brightness=255
+ * - writing blink=0 implies brightness=0
+ * - writing brightness=n implies blink=0
+ *
+ * However it seems swithing between blinking and non-blinking
+ * modes can cause hiccups that vary from one device to another
+ * (stale sysfs values left behind, led stays off when it should
+ * be lit, ...)
+ *
+ * So the logic is arranged that before switching from static
+ * color to blinking, a brightness=0 is done before writing
+ * blink=0, and when swithing from blinking to static color, a
+ * blink=0 is done before writing brightness=0.
+ *
+ * Note that upper level state machine logic + caching of the
+ * assumed sysfs values means that these transitions are done in
+ * 3 steps (cancel previous mode, reset to black, switch to new
+ * mode) with pproximately SYSFS_LED_KERNEL_DELAY ms in between
+ * the steps.
+ */
+ if( self->control_blink ) {
+ sysfsval_set(self->cached_brightness, 0);
+ sysfsval_set(self->cached_blink, 1);
+ }
+ else {
+ sysfsval_set(self->cached_blink, 0);
+ sysfsval_set(self->cached_brightness, value);
+ }
+
+ return;
+}
+static void
+led_channel_f5121_set_blink(led_channel_f5121_t *self,
+ int on_ms, int off_ms)
+{
+ /* The state machine at upper level adjusts blink setting first
+ * followed by brighthess setting - in f5121 modifying one will
+ * affect the other too and must thus be handled at the same
+ * time -> just cache the requested state. */
+ self->control_blink = (on_ms && off_ms);
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define F5121_CHANNELS 3
+
+static void
+led_control_f5121_blink_cb(void *data, int on_ms, int off_ms)
+{
+ led_channel_f5121_t *channel = data;
+ led_channel_f5121_set_blink(channel + 0, on_ms, off_ms);
+ led_channel_f5121_set_blink(channel + 1, on_ms, off_ms);
+ led_channel_f5121_set_blink(channel + 2, on_ms, off_ms);
+}
+
+static void
+led_control_f5121_value_cb(void *data, int r, int g, int b)
+{
+ led_channel_f5121_t *channel = data;
+ led_channel_f5121_set_value(channel + 0, r);
+ led_channel_f5121_set_value(channel + 1, g);
+ led_channel_f5121_set_value(channel + 2, b);
+}
+
+static void
+led_control_f5121_close_cb(void *data)
+{
+ led_channel_f5121_t *channel = data;
+ led_channel_f5121_close(channel + 0);
+ led_channel_f5121_close(channel + 1);
+ led_channel_f5121_close(channel + 2);
+}
+
+static bool
+led_control_f5121_static_probe(led_channel_f5121_t *channel)
+{
+ /** Sysfs control paths for RGB leds */
+ static const led_paths_f5121_t f5121_paths[][F5121_CHANNELS] =
+ {
+ // f5121 (Sony Xperia X)
+ {
+ {
+ .max_brightness = "/sys/class/leds/led:rgb_red/max_brightness",
+ .brightness = "/sys/class/leds/led:rgb_red/brightness",
+ .blink = "/sys/class/leds/led:rgb_red/blink",
+ },
+ {
+ .max_brightness = "/sys/class/leds/led:rgb_green/max_brightness",
+ .brightness = "/sys/class/leds/led:rgb_green/brightness",
+ .blink = "/sys/class/leds/led:rgb_green/blink",
+ },
+ {
+ .max_brightness = "/sys/class/leds/led:rgb_blue/max_brightness",
+ .brightness = "/sys/class/leds/led:rgb_blue/brightness",
+ .blink = "/sys/class/leds/led:rgb_blue/blink",
+ },
+ },
+ {
+ {
+ .max_brightness = "/sys/class/leds/red/max_brightness",
+ .brightness = "/sys/class/leds/red/brightness",
+ .blink = "/sys/class/leds/red/blink",
+ },
+ {
+ .max_brightness = "/sys/class/leds/green/max_brightness",
+ .brightness = "/sys/class/leds/green/brightness",
+ .blink = "/sys/class/leds/green/blink",
+ },
+ {
+ .max_brightness = "/sys/class/leds/blue/max_brightness",
+ .brightness = "/sys/class/leds/blue/brightness",
+ .blink = "/sys/class/leds/blue/blink",
+ },
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(f5121_paths); ++i ) {
+ if( led_channel_f5121_probe(&channel[0], &f5121_paths[i][0]) &&
+ led_channel_f5121_probe(&channel[1], &f5121_paths[i][1]) &&
+ led_channel_f5121_probe(&channel[2], &f5121_paths[i][2]) ) {
+ ack = true;
+ break;
+ }
+ }
+
+ return ack;
+}
+
+static bool
+led_control_f5121_dynamic_probe(led_channel_f5121_t *channel)
+{
+ /* See inifiles/60-f5121.ini for example */
+ static const objconf_t f5121_conf[] =
+ {
+ OBJCONF_FILE(led_paths_f5121_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_f5121_t, max_brightness, MaxBrightness),
+ OBJCONF_FILE(led_paths_f5121_t, blink, Blink),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[F5121_CHANNELS] =
+ {
+ "Red", "Green", "Blue"
+ };
+
+ bool ack = false;
+
+ led_paths_f5121_t paths[F5121_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < F5121_CHANNELS; ++i )
+ objconf_init(f5121_conf, &paths[i]);
+
+ for( size_t i = 0; i < F5121_CHANNELS; ++i )
+ {
+ if( !objconf_parse(f5121_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_f5121_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < F5121_CHANNELS; ++i )
+ objconf_quit(f5121_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_f5121_probe(led_control_t *self)
+{
+ static led_channel_f5121_t channel[F5121_CHANNELS];
+
+ bool ack = false;
+
+ led_channel_f5121_init(channel+0);
+ led_channel_f5121_init(channel+1);
+ led_channel_f5121_init(channel+2);
+
+ self->name = "f5121";
+ self->data = channel;
+ self->enable = 0;
+ self->blink = led_control_f5121_blink_cb;
+ self->value = led_control_f5121_value_cb;
+ self->close = led_control_f5121_close_cb;
+
+ /* Prefer to use the built-in soft-blinking */
+ self->can_breathe = false;
+
+ if( self->use_config )
+ ack = led_control_f5121_dynamic_probe(channel);
+
+ if( !ack )
+ ack = led_control_f5121_static_probe(channel);
+
+ if( !ack )
+ led_control_close(self);
+
+ return ack;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-f5121.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-f5121.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_F5121_H_
+# define SYSFS_LED_F5121_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_f5121_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_F5121_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-hammerhead.c
^
|
@@ -0,0 +1,343 @@
+/** @file sysfs-led-hammerhead.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * RGB led control: Hammerhead backend
+ *
+ * Three channels, all of which:
+ * - must have 'brightness' control file
+ * - must have 'max_brightness' control file
+ * - must have 'on_off_ms' blink delay control file
+ * - must have 'rgb_start' enable/disable control file
+ *
+ * Assumptions built into code:
+ * - Blinking is always soft, handled by kernel driver / hw.
+ * - The sysfs writes will block until change is finished -> Intensity
+ * changes are slow. Breathing from userspace can't be used as it
+ * would constantly block mce mainloop.
+ * ========================================================================= */
+
+#include "sysfs-led-hammerhead.h"
+
+#include "sysfs-led-util.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *max_brightness;
+ const char *brightness;
+ const char *on_off_ms;
+ const char *rgb_start;
+} led_paths_hammerhead_t;
+
+typedef struct
+{
+ int cached_max_brightness;
+ int fd_brightness;
+ int fd_on_off_ms;
+ int fd_rgb_start;
+} led_channel_hammerhead_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_hammerhead_init (led_channel_hammerhead_t *self);
+static void led_channel_hammerhead_close (led_channel_hammerhead_t *self);
+static bool led_channel_hammerhead_probe (led_channel_hammerhead_t *self, const led_paths_hammerhead_t *path);
+static void led_channel_hammerhead_set_enabled(const led_channel_hammerhead_t *self, bool enable);
+static void led_channel_hammerhead_set_value (const led_channel_hammerhead_t *self, int value);
+static void led_channel_hammerhead_set_blink (const led_channel_hammerhead_t *self, int on_ms, int off_ms);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_hammerhead_enable_cb (void *data, bool enable);
+static void led_control_hammerhead_blink_cb (void *data, int on_ms, int off_ms);
+static void led_control_hammerhead_value_cb (void *data, int r, int g, int b);
+static void led_control_hammerhead_close_cb (void *data);
+
+bool led_control_hammerhead_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_hammerhead_init(led_channel_hammerhead_t *self)
+{
+ self->cached_max_brightness = -1;
+ self->fd_brightness = -1;
+ self->fd_on_off_ms = -1;
+ self->fd_rgb_start = -1;
+}
+
+static void
+led_channel_hammerhead_close(led_channel_hammerhead_t *self)
+{
+ led_util_close_file(&self->fd_brightness);
+ led_util_close_file(&self->fd_on_off_ms);
+ led_util_close_file(&self->fd_rgb_start);
+}
+
+static bool
+led_channel_hammerhead_probe(led_channel_hammerhead_t *self,
+ const led_paths_hammerhead_t *path)
+{
+ bool res = false;
+
+ led_channel_hammerhead_close(self);
+
+ if( (self->cached_max_brightness = led_util_read_number(path->max_brightness)) <= 0 )
+ {
+ goto cleanup;
+ }
+
+ if( !led_util_open_file(&self->fd_brightness, path->brightness) ||
+ !led_util_open_file(&self->fd_on_off_ms, path->on_off_ms) ||
+ !led_util_open_file(&self->fd_rgb_start, path->rgb_start) )
+ {
+ goto cleanup;
+ }
+
+ res = true;
+
+cleanup:
+
+ if( !res ) led_channel_hammerhead_close(self);
+
+ return res;
+}
+
+static void
+led_channel_hammerhead_set_enabled(const led_channel_hammerhead_t *self,
+ bool enable)
+{
+ if( self->fd_rgb_start != -1 )
+ {
+ dprintf(self->fd_rgb_start, "%d", enable);
+ }
+}
+
+static void
+led_channel_hammerhead_set_value(const led_channel_hammerhead_t *self,
+ int value)
+{
+ if( self->fd_brightness != -1 )
+ {
+ dprintf(self->fd_brightness, "%d", led_util_scale_value(value, self->cached_max_brightness));
+ }
+}
+
+static void
+led_channel_hammerhead_set_blink(const led_channel_hammerhead_t *self,
+ int on_ms, int off_ms)
+{
+ if( self->fd_on_off_ms != -1 )
+ {
+ char tmp[32];
+ int len = snprintf(tmp, sizeof tmp, "%d %d", on_ms, off_ms);
+ if( len > 0 && len <= (int)sizeof tmp )
+ {
+ if( write(self->fd_on_off_ms, tmp, len) < 0 ) {
+ // dontcare, keep compiler from complaining too
+ }
+ }
+ }
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define HAMMERHEAD_CHANNELS 3
+
+static void
+led_control_hammerhead_enable_cb(void *data, bool enable)
+{
+ const led_channel_hammerhead_t *channel = data;
+ led_channel_hammerhead_set_enabled(channel + 0, enable);
+ led_channel_hammerhead_set_enabled(channel + 1, enable);
+ led_channel_hammerhead_set_enabled(channel + 2, enable);
+}
+
+static void
+led_control_hammerhead_blink_cb(void *data, int on_ms, int off_ms)
+{
+ const led_channel_hammerhead_t *channel = data;
+ led_channel_hammerhead_set_blink(channel + 0, on_ms, off_ms);
+ led_channel_hammerhead_set_blink(channel + 1, on_ms, off_ms);
+ led_channel_hammerhead_set_blink(channel + 2, on_ms, off_ms);
+}
+
+static void
+led_control_hammerhead_value_cb(void *data, int r, int g, int b)
+{
+ const led_channel_hammerhead_t *channel = data;
+ led_channel_hammerhead_set_value(channel + 0, r);
+ led_channel_hammerhead_set_value(channel + 1, g);
+ led_channel_hammerhead_set_value(channel + 2, b);
+}
+
+static void
+led_control_hammerhead_close_cb(void *data)
+{
+ led_channel_hammerhead_t *channel = data;
+ led_channel_hammerhead_close(channel + 0);
+ led_channel_hammerhead_close(channel + 1);
+ led_channel_hammerhead_close(channel + 2);
+}
+
+static bool
+led_control_hammerhead_static_probe(led_channel_hammerhead_t *channel)
+{
+ /** Sysfs control paths for RGB leds */
+ static const led_paths_hammerhead_t paths[][HAMMERHEAD_CHANNELS] =
+ {
+ // hammerhead (Nexus 5)
+ {
+ {
+ .max_brightness = "/sys/class/leds/red/max_brightness",
+ .brightness = "/sys/class/leds/red/brightness",
+ .on_off_ms = "/sys/class/leds/red/on_off_ms",
+ .rgb_start = "/sys/class/leds/red/rgb_start",
+ },
+ {
+ .max_brightness = "/sys/class/leds/green/max_brightness",
+ .brightness = "/sys/class/leds/green/brightness",
+ .on_off_ms = "/sys/class/leds/green/on_off_ms",
+ .rgb_start = "/sys/class/leds/green/rgb_start",
+ },
+ {
+ .max_brightness = "/sys/class/leds/blue/max_brightness",
+ .brightness = "/sys/class/leds/blue/brightness",
+ .on_off_ms = "/sys/class/leds/blue/on_off_ms",
+ .rgb_start = "/sys/class/leds/blue/rgb_start",
+ }
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( led_channel_hammerhead_probe(&channel[0], &paths[i][0]) &&
+ led_channel_hammerhead_probe(&channel[1], &paths[i][1]) &&
+ led_channel_hammerhead_probe(&channel[2], &paths[i][2]) ) {
+ ack = true;
+ break;
+ }
+ }
+
+ return ack;
+}
+
+static bool
+led_control_hammerhead_dynamic_probe(led_channel_hammerhead_t *channel)
+{
+ /* See inifiles/60-hammerhead.ini for example */
+ static const objconf_t hammerhead_conf[] =
+ {
+ OBJCONF_FILE(led_paths_hammerhead_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_hammerhead_t, max_brightness, MaxBrightness),
+ OBJCONF_FILE(led_paths_hammerhead_t, on_off_ms, OnOffMs),
+ OBJCONF_FILE(led_paths_hammerhead_t, rgb_start, RgbStart),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[HAMMERHEAD_CHANNELS] =
+ {
+ "Red", "Green", "Blue"
+ };
+
+ bool ack = false;
+
+ led_paths_hammerhead_t paths[HAMMERHEAD_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < HAMMERHEAD_CHANNELS; ++i )
+ objconf_init(hammerhead_conf, &paths[i]);
+
+ for( size_t i = 0; i < HAMMERHEAD_CHANNELS; ++i )
+ {
+ if( !objconf_parse(hammerhead_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_hammerhead_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < HAMMERHEAD_CHANNELS; ++i )
+ objconf_quit(hammerhead_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_hammerhead_probe(led_control_t *self)
+{
+
+ static led_channel_hammerhead_t channel[HAMMERHEAD_CHANNELS];
+
+ bool ack = false;
+
+ led_channel_hammerhead_init(channel+0);
+ led_channel_hammerhead_init(channel+1);
+ led_channel_hammerhead_init(channel+2);
+
+ self->name = "hammerhead";
+ self->data = channel;
+ self->enable = led_control_hammerhead_enable_cb;
+ self->blink = led_control_hammerhead_blink_cb;
+ self->value = led_control_hammerhead_value_cb;
+ self->close = led_control_hammerhead_close_cb;
+
+ /* Changing led parameters is so slow and consumes so much
+ * cpu cycles that we just can't have breathing available */
+ self->can_breathe = false;
+
+ if( self->use_config )
+ ack = led_control_hammerhead_dynamic_probe(channel);
+
+ if( !ack )
+ ack = led_control_hammerhead_static_probe(channel);
+
+ if( !ack )
+ led_control_close(self);
+
+ return ack;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-hammerhead.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-hammerhead.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_HAMMERHEAD_H_
+# define SYSFS_LED_HAMMERHEAD_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_hammerhead_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_HAMMERHEAD_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-htcvision.c
^
|
@@ -0,0 +1,336 @@
+/** @file sysfs-led-htcvision.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * Amber/green led control: Htcvision backend
+ *
+ * Two channels (amber and green), both of which:
+ * - must have 'brightness' control file
+ * - must have 'max_brightness' control file
+ * - must have 'blink' enable/disable control file
+ *
+ * Assumptions built into code:
+ * - while there are two channels, kernel and/or hw only allows one of them
+ * to be active -> Map rgb form request from mce to amber/green and try
+ * to minimize color error.
+ * ========================================================================= */
+
+#include "sysfs-led-htcvision.h"
+
+#include "sysfs-led-util.h"
+#include "sysfs-val.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *max_brightness;
+ const char *brightness;
+ const char *blink;
+} led_paths_htcvision_t;
+
+typedef struct
+{
+ sysfsval_t * cached_max_brightness;
+ sysfsval_t * cached_brightness;
+ sysfsval_t * cached_blink;
+} led_channel_htcvision_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_htcvision_init (led_channel_htcvision_t *self);
+static void led_channel_htcvision_close (led_channel_htcvision_t *self);
+static bool led_channel_htcvision_probe (led_channel_htcvision_t *self, const led_paths_htcvision_t *path);
+static void led_channel_htcvision_set_value (const led_channel_htcvision_t *self, int value);
+static void led_channel_htcvision_set_blink (const led_channel_htcvision_t *self, int blink);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_htcvision_map_color (int r, int g, int b, int *amber, int *green);
+static void led_control_htcvision_blink_cb (void *data, int on_ms, int off_ms);
+static void led_control_htcvision_value_cb (void *data, int r, int g, int b);
+static void led_control_htcvision_close_cb (void *data);
+
+bool led_control_htcvision_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_htcvision_init(led_channel_htcvision_t *self)
+{
+ self->cached_max_brightness = sysfsval_create();
+ self->cached_brightness = sysfsval_create();
+ self->cached_blink = sysfsval_create();
+}
+
+static void
+led_channel_htcvision_close(led_channel_htcvision_t *self)
+{
+ sysfsval_delete(self->cached_max_brightness),
+ self->cached_max_brightness = 0;
+
+ sysfsval_delete(self->cached_brightness),
+ self->cached_brightness = 0;
+
+ sysfsval_delete(self->cached_blink),
+ self->cached_blink = 0;
+}
+
+static bool
+led_channel_htcvision_probe(led_channel_htcvision_t *self,
+ const led_paths_htcvision_t *path)
+{
+ bool res = false;
+
+ if( !sysfsval_open_rw(self->cached_blink, path->blink) )
+ goto cleanup;
+
+ if( !sysfsval_open_rw(self->cached_brightness, path->brightness) )
+ goto cleanup;
+
+ if( sysfsval_open_ro(self->cached_max_brightness, path->max_brightness) )
+ sysfsval_refresh(self->cached_max_brightness);
+
+ if( sysfsval_get(self->cached_max_brightness) <= 0 )
+ sysfsval_assume(self->cached_max_brightness, 1);
+
+ res = true;
+
+cleanup:
+
+ /* Always close the max_brightness file */
+ sysfsval_close(self->cached_max_brightness);
+
+ /* On failure close the other files too */
+ if( !res ) {
+ sysfsval_close(self->cached_brightness);
+ sysfsval_close(self->cached_blink);
+ }
+
+ return res;
+}
+
+static void
+led_channel_htcvision_set_value(const led_channel_htcvision_t *self,
+ int value)
+{
+ value = led_util_scale_value(value,
+ sysfsval_get(self->cached_max_brightness));
+ sysfsval_set(self->cached_brightness, value);
+}
+
+static void
+led_channel_htcvision_set_blink(const led_channel_htcvision_t *self, int blink)
+{
+ sysfsval_set(self->cached_blink, blink ? 0 : 1);
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define HTCVISION_CHANNELS 2
+
+static void
+led_control_htcvision_map_color(int r, int g, int b,
+ int *amber, int *green)
+{
+ /* Only "amber" or "green" color can be used.
+ *
+ * Assume amber = r:ff g:7f b:00
+ * green = r:00 g:ff b:00
+ *
+ * Try to choose the one with smaller delta to the
+ * requested rgb color by using the 'r':'g' ratio.
+ *
+ * The 'b' is used for intensity preservation only.
+ */
+
+ if( r * 3 < g * 4)
+ {
+ *amber = 0;
+ *green = (g > b) ? g : b;
+ }
+ else
+ {
+ *amber = (r > b) ? r : b;
+ *green = 0;
+ }
+}
+
+static void
+led_control_htcvision_blink_cb(void *data, int on_ms, int off_ms)
+{
+ const led_channel_htcvision_t *channel = data;
+
+ int blink = (on_ms && off_ms);
+
+ led_channel_htcvision_set_blink(channel + 0, blink);
+ led_channel_htcvision_set_blink(channel + 1, blink);
+}
+
+static void
+led_control_htcvision_value_cb(void *data, int r, int g, int b)
+{
+ const led_channel_htcvision_t *channel = data;
+
+ int amber = 0;
+ int green = 0;
+ led_control_htcvision_map_color(r, g, b, &amber, &green);
+
+ led_channel_htcvision_set_value(channel + 0, amber);
+ led_channel_htcvision_set_value(channel + 1, green);
+}
+
+static void
+led_control_htcvision_close_cb(void *data)
+{
+ led_channel_htcvision_t *channel = data;
+ led_channel_htcvision_close(channel + 0);
+ led_channel_htcvision_close(channel + 1);
+}
+
+static bool
+led_control_htcvision_static_probe(led_channel_htcvision_t *channel)
+{
+ /** Sysfs control paths for Amber/Green leds */
+ static const led_paths_htcvision_t paths[][3] =
+ {
+ // htc vision, htc ace
+ {
+ {
+ .max_brightness = "/sys/class/leds/amber/max_brightness",
+ .brightness = "/sys/class/leds/amber/brightness",
+ .blink = "/sys/class/leds/amber/blink",
+ },
+ {
+ .max_brightness = "/sys/class/leds/green/max_brightness",
+ .brightness = "/sys/class/leds/green/brightness",
+ .blink = "/sys/class/leds/green/blink",
+ },
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( led_channel_htcvision_probe(&channel[0], &paths[i][0]) &&
+ led_channel_htcvision_probe(&channel[1], &paths[i][1]) ) {
+ ack = true;
+ break;
+ }
+ }
+
+ return ack;
+}
+
+static bool
+led_control_htcvision_dynamic_probe(led_channel_htcvision_t *channel)
+{
+ /* See inifiles/60-htcvision.ini for example */
+ static const objconf_t htcvision_conf[] =
+ {
+ OBJCONF_FILE(led_paths_htcvision_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_htcvision_t, max_brightness, MaxBrightness),
+ OBJCONF_FILE(led_paths_htcvision_t, blink, Blink),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[HTCVISION_CHANNELS] =
+ {
+ "Amber", "Green"
+ };
+
+ bool ack = false;
+
+ led_paths_htcvision_t paths[HTCVISION_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < HTCVISION_CHANNELS; ++i )
+ objconf_init(htcvision_conf, &paths[i]);
+
+ for( size_t i = 0; i < HTCVISION_CHANNELS; ++i )
+ {
+ if( !objconf_parse(htcvision_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_htcvision_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < HTCVISION_CHANNELS; ++i )
+ objconf_quit(htcvision_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_htcvision_probe(led_control_t *self)
+{
+
+ static led_channel_htcvision_t channel[HTCVISION_CHANNELS];
+
+ bool ack = false;
+
+ led_channel_htcvision_init(channel+0);
+ led_channel_htcvision_init(channel+1);
+
+ self->name = "htcvision";
+ self->data = channel;
+ self->enable = 0;
+ self->blink = led_control_htcvision_blink_cb;
+ self->value = led_control_htcvision_value_cb;
+ self->close = led_control_htcvision_close_cb;
+
+ /* TODO: check if breathing can be left enabled */
+ self->can_breathe = true;
+
+ if( self->use_config )
+ ack = led_control_htcvision_dynamic_probe(channel);
+
+ if( !ack )
+ ack = led_control_htcvision_static_probe(channel);
+
+ if( !ack )
+ led_control_close(self);
+
+ return ack;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-htcvision.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-htcvision.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_HTCVISION_H_
+# define SYSFS_LED_HTCVISION_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_htcvision_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_HTCVISION_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-main.c
^
|
@@ -0,0 +1,941 @@
+/** @file sysfs-led-main.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "sysfs-led-main.h"
+
+#include "sysfs-led-util.h"
+#include "sysfs-led-vanilla.h"
+#include "sysfs-led-hammerhead.h"
+#include "sysfs-led-bacon.h"
+#include "sysfs-led-f5121.h"
+#include "sysfs-led-htcvision.h"
+#include "sysfs-led-binary.h"
+#include "sysfs-led-redgreen.h"
+#include "sysfs-led-white.h"
+
+#include "plugin-logging.h"
+#include "plugin-config.h"
+#include "plugin-quirks.h"
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * CONSTANTS
+ * ========================================================================= */
+
+/** Questimate of the duration of the kernel delayed work */
+#define SYSFS_LED_KERNEL_DELAY 10 // [ms]
+
+/** Minimum delay between breathing steps */
+#define SYSFS_LED_STEP_DELAY 50 // [ms]
+
+/** Maximum number of breathing steps; rise and fall time combined */
+#define SYSFS_LED_MAX_STEPS 256
+
+/** Minimum number of breathing steps on rise/fall time */
+#define SYSFS_LED_MIN_STEPS 5
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+/* ------------------------------------------------------------------------- *
+ * LED_CONTROL
+ *
+ * Frontend for controlling (assumed to be RGB) led via sysfs
+ * ------------------------------------------------------------------------- */
+
+static void led_control_enable (led_control_t *self, bool enable);
+static void led_control_blink (led_control_t *self, int on_ms, int off_ms);
+static void led_control_value (led_control_t *self, int r, int g, int b);
+static void led_control_init (led_control_t *self);
+
+static bool led_control_can_breathe (const led_control_t *self);
+static led_ramp_t led_control_breath_type (const led_control_t *self);
+
+static bool led_control_probe (led_control_t *self);
+void led_control_close (led_control_t *self);
+
+/* ------------------------------------------------------------------------- *
+ * LED_STATE
+ *
+ * Managing logical state of indicator led
+ * ------------------------------------------------------------------------- */
+
+/** Led state
+ */
+typedef struct
+{
+ int r,g,b; // color
+ int on,off; // blink timing
+ int level; // brightness [0 ... 255]
+ bool breathe; // breathe instead of blinking
+} led_state_t;
+
+/** Different styles of led patterns
+ */
+typedef enum
+{
+ STYLE_OFF, // led is off
+ STYLE_STATIC, // led has constant color
+ STYLE_BLINK, // led is blinking with on/off periods
+ STYLE_BREATH, // led is breathing with rise/fall times
+} led_style_t;
+
+static bool led_state_has_equal_timing (const led_state_t *self, const led_state_t *that);
+static bool led_state_is_equal (const led_state_t *self, const led_state_t *that);
+static bool led_state_has_color (const led_state_t *self);
+static void led_state_sanitize (led_state_t *self);
+static led_style_t led_state_get_style (const led_state_t *self);
+
+/* ------------------------------------------------------------------------- *
+ * SYSFS_LED
+ *
+ * Top level sysfs led functionality used by mce hybris plugin.
+ * ------------------------------------------------------------------------- */
+
+static void sysfs_led_close_files (void);
+static bool sysfs_led_probe_files (void);
+
+static void sysfs_led_set_rgb_blink (int on, int off);
+static void sysfs_led_set_rgb_value (int r, int g, int b);
+
+static void sysfs_led_generate_ramp_half_sin (int ms_on, int ms_off);
+static void sysfs_led_generate_ramp_hard_step (int ms_on, int ms_off);
+static void sysfs_led_generate_ramp_dummy (void);
+static void sysfs_led_generate_ramp (int ms_on, int ms_off);
+
+static gboolean sysfs_led_static_cb (gpointer aptr);
+static gboolean sysfs_led_step_cb (gpointer aptr);
+static gboolean sysfs_led_stop_cb (gpointer aptr);
+static void sysfs_led_start (const led_state_t *next);
+
+static void sysfs_led_wait_kernel (void);
+
+bool sysfs_led_init (void);
+void sysfs_led_quit (void);
+
+bool sysfs_led_set_pattern (int r, int g, int b, int ms_on, int ms_off);
+bool sysfs_led_can_breathe (void);
+void sysfs_led_set_breathing (bool enable);
+void sysfs_led_set_brightness (int level);
+
+/* ========================================================================= *
+ * LED_CONTROL
+ * ========================================================================= */
+
+/** Set RGB LED enabled/disable
+ *
+ * @param self control object
+ * @param enable true for enable, or false for disable
+ */
+static void
+led_control_enable(led_control_t *self, bool enable)
+{
+ if( self->enable )
+ {
+ self->enable(self->data, enable);
+ }
+}
+
+/** Set RGB LED blinking period
+ *
+ * If both on and off are greater than zero, then the PWM generator
+ * is used to full intensity blinking. Otherwise it is used for
+ * adjusting the LED brightness.
+ *
+ * @param self control object
+ * @param on milliseconds on
+ * @param off milliseconds off
+ */
+static void
+led_control_blink(led_control_t *self, int on_ms, int off_ms)
+{
+ if( self->blink )
+ {
+ led_control_enable(self, false);
+ self->blink(self->data, on_ms, off_ms);
+ }
+}
+
+/** Set RGB LED color
+ *
+ * @param self control object
+ * @param r red intensity (0 ... 255)
+ * @param g green intensity (0 ... 255)
+ * @param b blue intensity (0 ... 255)
+ */
+static void
+led_control_value(led_control_t *self, int r, int g, int b)
+{
+ if( self->value )
+ {
+ led_control_enable(self, false);
+ self->value(self->data, r, g, b);
+ led_control_enable(self, true);
+ }
+}
+
+/** Reset RGB led control object
+ *
+ * Initialize control object to closed but valid state.
+ *
+ * @param self uninitialized control object
+ */
+static void
+led_control_init(led_control_t *self)
+{
+ self->name = 0;
+ self->data = 0;
+ self->enable = 0;
+ self->blink = 0;
+ self->value = 0;
+ self->close = 0;
+
+ /* Assume paths from config are not to be used */
+ self->use_config = false;
+
+ /* Assume that it is exceptional if sw breathing can't be supported */
+ self->can_breathe = true;
+ /* And half sine curve should be used for breathing */
+ self->breath_type = LED_RAMP_HALF_SINE;
+
+}
+
+/** Query if backend can support sw breathing
+ *
+ * @return true if breathing can be enabled, false otherwise
+ */
+static bool
+led_control_can_breathe(const led_control_t *self)
+{
+ return self->can_breathe;
+}
+
+/** Query type of sw breathing backend supports
+ *
+ * @return LED_RAMP_DISABLED, LED_RAMP_HALF_SINE, or ...
+ */
+static led_ramp_t
+led_control_breath_type(const led_control_t *self)
+{
+ return self->can_breathe ? self->breath_type : LED_RAMP_DISABLED;
+}
+
+/** Probe sysfs for RGB LED controls
+ *
+ * @param self control object
+ *
+ * @return true if required control files were available, false otherwise
+ */
+static bool
+led_control_probe(led_control_t *self)
+{
+ typedef bool (*led_control_probe_fn)(led_control_t *);
+
+ /* The probing should be done in order that minimizes
+ * chances of false positives.
+ */
+ static const struct
+ {
+ const char *name;
+ led_control_probe_fn func;
+ } lut[] =
+ {
+ /* The hammerhead backend requires presense of
+ * unique 'on_off_ms' and 'rgb_start' files. */
+ { "hammerhead", led_control_hammerhead_probe },
+
+ /* The htc vision backend requires presense of
+ * unique 'amber' control directory. */
+ { "htcvision", led_control_htcvision_probe },
+
+ /* The bacon backend */
+ { "bacon", led_control_bacon_probe },
+
+ /* The f5121 requires 'brightness', 'max_brightness' and 'blink'
+ * control files to be present for red, green and blue channels. */
+ { "f5121", led_control_f5121_probe },
+
+ /* The vanilla backend requires only 'brightness'
+ * control file, but still needs three directories
+ * to be present for red, green and blue channels. */
+ { "vanilla", led_control_vanilla_probe },
+
+ /* The redgreen uses subset of "standard" rgb led
+ * control paths, so to avoid false positive matches
+ * it must be probed after rgb led controls. */
+ { "redgreen", led_control_redgreen_probe },
+
+ /* Single control channel with actually working
+ * brightness control and max_brightness. */
+ { "white", led_control_white_probe },
+
+ /* The binary backend needs just one directory
+ * that has 'brightness' control file. */
+ { "binary", led_control_binary_probe },
+ };
+
+ bool ack = false;
+ gchar *name = plugin_config_get_string(MCE_CONF_LED_CONFIG_HYBRIS_GROUP,
+ MCE_CONF_LED_CONFIG_HYBRIS_BACKEND,
+ 0);
+
+ for( size_t i = 0; i < G_N_ELEMENTS(lut); ++i )
+ {
+ self->use_config = false;
+
+ if( name ) {
+ if( strcmp(lut[i].name, name) ) {
+ continue;
+ }
+
+ self->use_config = true;
+ }
+
+ if( name && strcmp(lut[i].name, name) )
+ {
+ continue;
+ }
+
+ if( !lut[i].func(self) )
+ {
+ continue;
+ }
+
+ self->can_breathe = QUIRK(QUIRK_BREATHING, self->can_breathe);
+
+ ack = true;
+ break;
+ }
+
+ g_free(name);
+
+ return ack;
+}
+
+/** Set RGB LED enabled/disable
+ *
+ * @param self control object
+ * @param enable true for enable, or false for disable
+ */
+
+void
+led_control_close(led_control_t *self)
+{
+ if( self->close )
+ {
+ self->close(self->data);
+ }
+ led_control_init(self);
+}
+
+/* ========================================================================= *
+ * LED_STATE
+ * ========================================================================= */
+
+/** Test for led request blink/breathing timing equality
+ */
+static bool
+led_state_has_equal_timing(const led_state_t *self, const led_state_t *that)
+{
+ return (self->on == that->on &&
+ self->off == that->off);
+}
+
+/** Test for led request equality
+ */
+static bool
+led_state_is_equal(const led_state_t *self, const led_state_t *that)
+{
+ return (self->r == that->r &&
+ self->g == that->g &&
+ self->b == that->b &&
+ self->on == that->on &&
+ self->off == that->off &&
+ self->level == that->level &&
+ self->breathe == that->breathe);
+}
+
+/** Test for active led request
+ */
+static bool
+led_state_has_color(const led_state_t *self)
+{
+ return self->r > 0 || self->g > 0 || self->b > 0;
+}
+
+/** Normalize/sanity check requested values
+ */
+static void
+led_state_sanitize(led_state_t *self)
+{
+ int min_period = SYSFS_LED_STEP_DELAY * SYSFS_LED_MIN_STEPS;
+
+ if( !led_state_has_color(self) ) {
+ /* blinking/breathing black and black makes no sense */
+ self->on = 0;
+ self->off = 0;
+ self->breathe = false;
+ }
+ else if( self->on <= 0 || self->off <= 0) {
+ /* both on and off periods must be > 0 for blinking/breathing */
+ self->on = 0;
+ self->off = 0;
+ self->breathe = false;
+ }
+ else if( self->on < min_period || self->off < min_period ) {
+ /* Whether a pattern should breathe or not is decided at mce side.
+ * But, since there are limitations on how often the led intensity
+ * can be changed, we must check that the rise/fall times are long
+ * enough to allow a reasonable amount of adjustments to be made. */
+ self->breathe = false;
+ }
+}
+
+/** Evaluate request style
+ */
+static led_style_t
+led_state_get_style(const led_state_t *self)
+{
+ if( !led_state_has_color(self) ) {
+ return STYLE_OFF;
+ }
+
+ if( self->on <= 0 || self->off <= 0 ) {
+ return STYLE_STATIC;
+ }
+
+ if( self->breathe ) {
+ return STYLE_BREATH;
+ }
+
+ return STYLE_BLINK;
+}
+
+/* ========================================================================= *
+ * SYSFS_LED
+ * ========================================================================= */
+
+/** Currently used intensity curve for sw breathing */
+static struct {
+ size_t step;
+ size_t steps;
+ int delay;
+ uint8_t value[SYSFS_LED_MAX_STEPS];
+} sysfs_led_breathe =
+{
+ .step = 0,
+ .steps = 0,
+ .delay = 0,
+};
+
+/** Currently active RGB led state; initialize to invalid color */
+static led_state_t sysfs_led_curr =
+{
+ /* force 1st change to take effect by initializing to invalid color */
+ .r = -1,
+ .g = -1,
+ .b = -1,
+
+ /* not blinking or breathing */
+ .on = 0,
+ .off = 0,
+ .breathe = false,
+
+ /* full brightness */
+ .level = 255,
+};
+
+static led_control_t led_control;
+
+/** Close all LED sysfs files
+ */
+static void
+sysfs_led_close_files(void)
+{
+ led_control_close(&led_control);
+}
+
+/** Open sysfs control files for RGB leds
+ *
+ * @return true if required control files were available, false otherwise
+ */
+static bool
+sysfs_led_probe_files(void)
+{
+ led_control_init(&led_control);
+
+ bool probed = led_control_probe(&led_control);
+
+ /* Note: As there are devices that do not have indicator
+ * led, a ailures to find a suitable backend must
+ * be assumed to be ok and not logged in the default
+ * verbosity level.
+ */
+ mce_log(LL_NOTICE, "led sysfs backend: %s",
+ probed ? led_control.name : "N/A");
+
+ return probed;
+}
+
+/** Change blinking attributes of RGB led
+ */
+static void
+sysfs_led_set_rgb_blink(int on, int off)
+{
+ mce_log(LOG_DEBUG, "on_ms = %d, off_ms = %d", on, off);
+ led_control_blink(&led_control, on, off);
+}
+
+/** Change intensity attributes of RGB led
+ */
+static void
+sysfs_led_set_rgb_value(int r, int g, int b)
+{
+ mce_log(LOG_DEBUG, "rgb = %d %d %d", r, g, b);
+ led_control_value(&led_control, r, g, b);
+}
+
+/** Generate half sine intensity curve for use from breathing timer
+ */
+static void
+sysfs_led_generate_ramp_half_sin(int ms_on, int ms_off)
+{
+ int t = ms_on + ms_off;
+ int s = (t + SYSFS_LED_MAX_STEPS - 1) / SYSFS_LED_MAX_STEPS;
+
+ if( s < SYSFS_LED_STEP_DELAY ) {
+ s = SYSFS_LED_STEP_DELAY;
+ }
+ int n = (t + s - 1) / s;
+
+ int steps_on = (n * ms_on + t / 2) / t;
+ int steps_off = n - steps_on;
+
+ const float m_pi_2 = (float)M_PI_2;
+
+ int k = 0;
+
+ for( int i = 0; i < steps_on; ++i ) {
+ float a = i * m_pi_2 / steps_on;
+ sysfs_led_breathe.value[k++] = (uint8_t)(sinf(a) * 255.0f);
+ }
+ for( int i = 0; i < steps_off; ++i ) {
+ float a = m_pi_2 + i * m_pi_2 / steps_off;
+ sysfs_led_breathe.value[k++] = (uint8_t)(sinf(a) * 255.0f);
+ }
+
+ sysfs_led_breathe.delay = s;
+ sysfs_led_breathe.steps = k;
+
+ mce_log(LL_DEBUG, "delay=%d, steps_on=%d, steps_off=%d",
+ sysfs_led_breathe.delay, steps_on, steps_off);
+}
+
+/** Generate hard step intensity curve for use from breathing timer
+ */
+static void
+sysfs_led_generate_ramp_hard_step(int ms_on, int ms_off)
+{
+ /* Calculate ramp duration - round up given on/off lengths
+ * to avoid totally bizarre values that could cause excessive
+ * number of timer wakeups.
+ */
+ ms_on = led_util_roundup(ms_on, 100);
+ ms_off = led_util_roundup(ms_off, 100);
+
+ int ms_tot = ms_on + ms_off;
+
+ /* Ideally we would want to wake up only to flip the led
+ * on/off. But to keep using the existing ramp timer logic,
+ * we wake up in pace of the greatest common divisor for on
+ * and off periods.
+ */
+ int ms_step = led_util_gcd(ms_on, ms_off);
+
+ if( ms_step < SYSFS_LED_STEP_DELAY ) {
+ ms_step = SYSFS_LED_STEP_DELAY;
+ }
+
+ /* Calculate number of steps we need and make sure it does
+ * not exceed the defined maximum value.
+ */
+ int steps_tot = (ms_tot + ms_step - 1) / ms_step;
+
+ if( steps_tot > SYSFS_LED_MAX_STEPS ) {
+ steps_tot = SYSFS_LED_MAX_STEPS;
+ ms_step = (ms_tot + steps_tot - 1) / steps_tot;
+
+ if( ms_step < SYSFS_LED_STEP_DELAY ) {
+ ms_step = SYSFS_LED_STEP_DELAY;
+ }
+ }
+
+ int steps_on = (ms_on + ms_step - 1 ) / ms_step;
+ int steps_off = steps_tot - steps_on;
+
+ /* Set intensity value for each step on the ramp.
+ */
+ int i = 0;
+
+ while( i < steps_on ) sysfs_led_breathe.value[i++] = 255;
+ while( i < steps_tot ) sysfs_led_breathe.value[i++] = 0;
+
+ sysfs_led_breathe.delay = ms_step;
+ sysfs_led_breathe.steps = steps_tot;
+
+ mce_log(LL_DEBUG, "delay=%d, steps_on=%d, steps_off=%d",
+ sysfs_led_breathe.delay, steps_on, steps_off);
+}
+
+/** Invalidate sw breathing intensity curve
+ */
+static void
+sysfs_led_generate_ramp_dummy(void)
+{
+ sysfs_led_breathe.delay = 0;
+ sysfs_led_breathe.steps = 0;
+}
+
+/** Generate intensity curve for use from breathing timer
+ */
+static void
+sysfs_led_generate_ramp(int ms_on, int ms_off)
+{
+ switch( led_control_breath_type(&led_control) ) {
+ case LED_RAMP_HARD_STEP:
+ sysfs_led_generate_ramp_hard_step(ms_on, ms_off);
+ break;
+
+ case LED_RAMP_HALF_SINE:
+ sysfs_led_generate_ramp_half_sin(ms_on, ms_off);
+ break;
+
+ default:
+ sysfs_led_generate_ramp_dummy();
+ break;
+ }
+}
+
+/** Timer id for stopping led */
+static guint sysfs_led_stop_id = 0;
+
+/** Timer id for breathing/setting led */
+static guint sysfs_led_step_id = 0;
+
+/** Timer callback for setting led
+ */
+static gboolean
+sysfs_led_static_cb(gpointer aptr)
+{
+ (void) aptr;
+
+ if( !sysfs_led_step_id ) {
+ goto cleanup;
+ }
+
+ sysfs_led_step_id = 0;
+
+ // get configured color
+ int r = sysfs_led_curr.r;
+ int g = sysfs_led_curr.g;
+ int b = sysfs_led_curr.b;
+
+ // adjust by brightness level
+ int l = sysfs_led_curr.level;
+
+ r = led_util_scale_value(r, l);
+ g = led_util_scale_value(g, l);
+ b = led_util_scale_value(b, l);
+
+ // set led blinking and color
+ sysfs_led_set_rgb_blink(sysfs_led_curr.on, sysfs_led_curr.off);
+ sysfs_led_set_rgb_value(r, g, b);
+
+cleanup:
+
+ return FALSE;
+}
+
+/** Timer callback for taking a led breathing step
+ */
+static gboolean
+sysfs_led_step_cb(gpointer aptr)
+{
+ (void)aptr;
+
+ if( !sysfs_led_step_id ) {
+ goto cleanup;
+ }
+
+ if( sysfs_led_breathe.step >= sysfs_led_breathe.steps ) {
+ sysfs_led_breathe.step = 0;
+ }
+
+ // get configured color
+ int r = sysfs_led_curr.r;
+ int g = sysfs_led_curr.g;
+ int b = sysfs_led_curr.b;
+
+ // adjust by brightness level
+ int l = sysfs_led_curr.level;
+
+ r = led_util_scale_value(r, l);
+ g = led_util_scale_value(g, l);
+ b = led_util_scale_value(b, l);
+
+ // adjust by curve position
+ size_t i = sysfs_led_breathe.step++;
+ int v = sysfs_led_breathe.value[i];
+
+ r = led_util_scale_value(r, v);
+ g = led_util_scale_value(g, v);
+ b = led_util_scale_value(b, v);
+
+ // set led color
+ sysfs_led_set_rgb_value(r, g, b);
+
+cleanup:
+
+ return sysfs_led_step_id != 0;
+}
+
+static bool sysfs_led_reset_blinking = true;
+
+/** Timer callback from stopping/restarting led
+ */
+static gboolean
+sysfs_led_stop_cb(gpointer aptr)
+{
+ (void) aptr;
+
+ if( !sysfs_led_stop_id ) {
+ goto cleanup;
+ }
+ sysfs_led_stop_id = 0;
+
+ if( sysfs_led_reset_blinking ) {
+ // blinking off - must be followed by rgb set to have an effect
+ sysfs_led_set_rgb_blink(0, 0);
+ }
+
+ if( !led_state_has_color(&sysfs_led_curr) ) {
+ // set rgb to black before returning
+ sysfs_led_reset_blinking = true;
+ }
+ else {
+ if( sysfs_led_breathe.delay > 0 ) {
+ // start breathing timer
+ sysfs_led_step_id = g_timeout_add(sysfs_led_breathe.delay,
+ sysfs_led_step_cb, 0);
+ }
+ else {
+ // set rgb to target after timer delay
+ sysfs_led_step_id = g_timeout_add(SYSFS_LED_KERNEL_DELAY,
+ sysfs_led_static_cb, 0);
+ }
+ }
+
+ if( sysfs_led_reset_blinking ) {
+ // set rgb to black
+ sysfs_led_set_rgb_value(0, 0, 0);
+ sysfs_led_reset_blinking = false;
+ }
+
+cleanup:
+
+ return FALSE;
+}
+
+/** Start static/blinking/breathing led
+ */
+static void
+sysfs_led_start(const led_state_t *next)
+{
+ led_state_t work = *next;
+
+ led_state_sanitize(&work);
+
+ if( led_state_is_equal(&sysfs_led_curr, &work) ) {
+ goto cleanup;
+ }
+
+ /* Assumption: Before changing the led state, we need to wait a bit
+ * for kernel side to finish with last change we made and then possibly
+ * reset the blinking status and wait a bit more */
+ bool restart = true;
+
+ led_style_t old_style = led_state_get_style(&sysfs_led_curr);
+ led_style_t new_style = led_state_get_style(&work);
+
+ /* Exception: When we are already breathing and continue to
+ * breathe, the blinking is not in use and the breathing timer
+ * is keeping the updates far enough from each other */
+ if( old_style == STYLE_BREATH && new_style == STYLE_BREATH &&
+ led_state_has_equal_timing(&sysfs_led_curr, &work) ) {
+ restart = false;
+ }
+
+ /* If only the als-based brightness level changes, we need to
+ * adjust the breathing amplitude without affecting the phase.
+ * Otherwise assume that the pattern has been changed and the
+ * breathing step counter needs to be reset. */
+ sysfs_led_curr.level = work.level;
+ if( !led_state_is_equal(&sysfs_led_curr, &work) ) {
+ sysfs_led_breathe.step = 0;
+ }
+
+ sysfs_led_curr = work;
+
+ if( restart ) {
+ // stop existing breathing timer
+ if( sysfs_led_step_id ) {
+ g_source_remove(sysfs_led_step_id), sysfs_led_step_id = 0;
+ }
+
+ // re-evaluate breathing constants
+ sysfs_led_breathe.delay = 0;
+ if( new_style == STYLE_BREATH ) {
+ sysfs_led_generate_ramp(work.on, work.off);
+ }
+
+ if( old_style == STYLE_BLINK || new_style == STYLE_BLINK )
+ sysfs_led_reset_blinking = true;
+
+ /* Schedule led off after kernel settle timeout; once that
+ * is done, new led color/blink/breathing will be started */
+ if( !sysfs_led_stop_id ) {
+ sysfs_led_stop_id = g_timeout_add(SYSFS_LED_KERNEL_DELAY,
+ sysfs_led_stop_cb, 0);
+ }
+ }
+
+cleanup:
+
+ return;
+}
+
+/** Nanosleep helper
+ */
+static void
+sysfs_led_wait_kernel(void)
+{
+ struct timespec ts = { 0, SYSFS_LED_KERNEL_DELAY * 1000000l };
+ TEMP_FAILURE_RETRY(nanosleep(&ts, &ts));
+}
+
+bool
+sysfs_led_init(void)
+{
+ bool ack = false;
+
+ if( !sysfs_led_probe_files() ) {
+ goto cleanup;
+ }
+
+ /* adjust current state to: color=black */
+ led_state_t req = sysfs_led_curr;
+ req.r = 0;
+ req.g = 0;
+ req.b = 0;
+ sysfs_led_start(&req);
+
+ ack = true;
+
+cleanup:
+
+ return ack;
+}
+
+void
+sysfs_led_quit(void)
+{
+ // cancel timers
+ if( sysfs_led_step_id ) {
+ g_source_remove(sysfs_led_step_id), sysfs_led_step_id = 0;
+ }
+ if( sysfs_led_stop_id ) {
+ g_source_remove(sysfs_led_stop_id), sysfs_led_stop_id = 0;
+ }
+
+ // allow kernel side to settle down
+ sysfs_led_wait_kernel();
+
+ // blink off
+ sysfs_led_set_rgb_blink(0, 0);
+
+ // zero brightness
+ sysfs_led_set_rgb_value(0, 0, 0);
+
+ // close sysfs files
+ sysfs_led_close_files();
+}
+
+bool
+sysfs_led_set_pattern(int r, int g, int b,
+ int ms_on, int ms_off)
+{
+ /* adjust current state to: color & timing as requested */
+ led_state_t req = sysfs_led_curr;
+ req.r = r;
+ req.g = g;
+ req.b = b;
+ req.on = ms_on;
+ req.off = ms_off;
+ sysfs_led_start(&req);
+
+ return true;
+}
+
+bool
+sysfs_led_can_breathe(void)
+{
+ return led_control_can_breathe(&led_control);
+}
+
+void
+sysfs_led_set_breathing(bool enable)
+{
+ if( sysfs_led_can_breathe() ) {
+ /* adjust current state to: breathing as requested */
+ led_state_t work = sysfs_led_curr;
+ work.breathe = enable;
+ sysfs_led_start(&work);
+ }
+}
+
+void
+sysfs_led_set_brightness(int level)
+{
+ /* adjust current state to: brightness as requested */
+ led_state_t work = sysfs_led_curr;
+ work.level = level;
+ sysfs_led_start(&work);
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-main.h
^
|
@@ -0,0 +1,72 @@
+/** @file sysfs-led-main.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_MAIN_H_
+# define SYSFS_LED_MAIN_H_
+
+# include <stdbool.h>
+
+/* ------------------------------------------------------------------------- *
+ * LED_CONTROL - Common RGB LED control API
+ * ------------------------------------------------------------------------- */
+
+/** Brightness ramp type used for SW-breathing
+ */
+typedef enum {
+ /** Used when sw breathing is not used */
+ LED_RAMP_DISABLED = 0,
+
+ /** The default half sine curve */
+ LED_RAMP_HALF_SINE = 1,
+
+ /** Step function used for emulating blinking via sw breathing */
+ LED_RAMP_HARD_STEP = 2,
+} led_ramp_t;
+
+typedef struct led_control_t led_control_t;
+
+/** Led control backend
+ */
+struct led_control_t
+{
+ const char *name;
+ void *data;
+ bool can_breathe;
+ bool use_config;
+ led_ramp_t breath_type;
+ void (*enable)(void *data, bool enable);
+ void (*blink) (void *data, int on_ms, int off_ms);
+ void (*value) (void *data, int r, int g, int b);
+ void (*close) (void *data);
+};
+
+bool sysfs_led_init (void);
+void sysfs_led_quit (void);
+bool sysfs_led_set_pattern (int r, int g, int b, int ms_on, int ms_off);
+bool sysfs_led_can_breathe (void);
+void sysfs_led_set_breathing (bool enable);
+void sysfs_led_set_brightness (int level);
+
+void led_control_close (led_control_t *self);
+
+#endif /* SYSFS_LED_MAIN_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-redgreen.c
^
|
@@ -0,0 +1,292 @@
+/** @file sysfs-led-redgreen.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * Red + green led control
+ *
+ * Two channels (red and green), both of which:
+ * - must have 'brightness' control file
+ * - must have 'max_brightness' control file
+ *
+ * Notes:
+ * - despite having wide max_brightness range, the brightness control
+ * is binary: zero for off and any non-zero value for on.
+ * ========================================================================= */
+
+#include "sysfs-led-redgreen.h"
+
+#include "sysfs-led-util.h"
+#include "sysfs-val.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *max_brightness;
+ const char *brightness;
+} led_paths_redgreen_t;
+
+typedef struct
+{
+ sysfsval_t *cached_max_brightness;
+ sysfsval_t *cached_brightness;
+} led_channel_redgreen_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_redgreen_init (led_channel_redgreen_t *self);
+static void led_channel_redgreen_close (led_channel_redgreen_t *self);
+static bool led_channel_redgreen_probe (led_channel_redgreen_t *self, const led_paths_redgreen_t *path);
+static void led_channel_redgreen_set_value (const led_channel_redgreen_t *self, int value);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_redgreen_map_color (int r, int g, int b, int *red, int *green);
+static void led_control_redgreen_value_cb (void *data, int r, int g, int b);
+static void led_control_redgreen_close_cb (void *data);
+
+bool led_control_redgreen_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_redgreen_init(led_channel_redgreen_t *self)
+{
+ self->cached_max_brightness = sysfsval_create();
+ self->cached_brightness = sysfsval_create();
+}
+
+static void
+led_channel_redgreen_close(led_channel_redgreen_t *self)
+{
+ sysfsval_delete(self->cached_max_brightness),
+ self->cached_max_brightness = 0;
+
+ sysfsval_delete(self->cached_brightness),
+ self->cached_brightness = 0;
+}
+
+static bool
+led_channel_redgreen_probe(led_channel_redgreen_t *self,
+ const led_paths_redgreen_t *path)
+{
+ bool res = false;
+
+ if( !sysfsval_open_rw(self->cached_brightness, path->brightness) )
+ goto cleanup;
+
+ if( sysfsval_open_ro(self->cached_max_brightness, path->max_brightness) )
+ sysfsval_refresh(self->cached_max_brightness);
+
+ if( sysfsval_get(self->cached_max_brightness) <= 0 )
+ goto cleanup;
+
+ res = true;
+
+cleanup:
+
+ /* Always close the max_brightness file */
+ sysfsval_close(self->cached_max_brightness);
+
+ /* On failure close the other files too */
+ if( !res )
+ {
+ sysfsval_close(self->cached_brightness);
+ }
+
+ return res;
+}
+
+static void
+led_channel_redgreen_set_value(const led_channel_redgreen_t *self, int value)
+{
+ value = led_util_scale_value(value,
+ sysfsval_get(self->cached_max_brightness));
+ sysfsval_set(self->cached_brightness, value);
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define REDGREEN_CHANNELS 2
+
+static void
+led_control_redgreen_map_color(int r, int g, int b, int *red, int *green)
+{
+ /* If the pattern defines red and/or green intensities, those should
+ * be used. Otherwise make sure that requesting for blue only colour
+ * does not result in the led being turned off. */
+ if( r || g )
+ {
+ *red = r;
+ *green = g;
+ }
+ else
+ {
+ *red = b;
+ *green = b;
+ }
+}
+
+static void
+led_control_redgreen_value_cb(void *data, int r, int g, int b)
+{
+ const led_channel_redgreen_t *channel = data;
+
+ int red = 0;
+ int green = 0;
+ led_control_redgreen_map_color(r, g, b, &red, &green);
+
+ led_channel_redgreen_set_value(channel + 0, red);
+ led_channel_redgreen_set_value(channel + 1, green);
+}
+
+static void
+led_control_redgreen_close_cb(void *data)
+{
+ led_channel_redgreen_t *channel = data;
+ led_channel_redgreen_close(channel + 0);
+ led_channel_redgreen_close(channel + 1);
+}
+
+static bool
+led_control_redgreen_static_probe(led_channel_redgreen_t *channel)
+{
+ /** Sysfs control paths for Red + Green leds */
+ static const led_paths_redgreen_t paths[][REDGREEN_CHANNELS] =
+ {
+ // "standard" paths
+ {
+ {
+ .max_brightness = "/sys/class/leds/red/max_brightness",
+ .brightness = "/sys/class/leds/red/brightness",
+ },
+ {
+ .max_brightness = "/sys/class/leds/green/max_brightness",
+ .brightness = "/sys/class/leds/green/brightness",
+ },
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( led_channel_redgreen_probe(&channel[0], &paths[i][0]) &&
+ led_channel_redgreen_probe(&channel[1], &paths[i][1]) ) {
+ ack = true;
+ break;
+ }
+ }
+
+ return ack;
+}
+
+static bool
+led_control_redgreen_dynamic_probe(led_channel_redgreen_t *channel)
+{
+ /* See inifiles/60-redgreen.ini for example config file */
+ static const objconf_t redgreen_conf[] =
+ {
+ OBJCONF_FILE(led_paths_redgreen_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_redgreen_t, max_brightness, MaxBrightness),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[REDGREEN_CHANNELS] =
+ {
+ "Red", "Green",
+ };
+
+ bool ack = false;
+
+ led_paths_redgreen_t paths[REDGREEN_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < REDGREEN_CHANNELS; ++i )
+ objconf_init(redgreen_conf, &paths[i]);
+
+ for( size_t i = 0; i < REDGREEN_CHANNELS; ++i )
+ {
+ if( !objconf_parse(redgreen_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_redgreen_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < REDGREEN_CHANNELS; ++i )
+ objconf_quit(redgreen_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_redgreen_probe(led_control_t *self)
+{
+ static led_channel_redgreen_t channel[REDGREEN_CHANNELS];
+
+ bool res = false;
+
+ led_channel_redgreen_init(channel + 0);
+ led_channel_redgreen_init(channel + 1);
+
+ self->name = "redgreen";
+ self->data = channel;
+ self->enable = 0;
+ self->value = led_control_redgreen_value_cb;
+ self->close = led_control_redgreen_close_cb;
+
+ /* We can use sw breathing logic to simulate hw blinking */
+ self->can_breathe = true;
+ self->breath_type = LED_RAMP_HARD_STEP;
+
+ if( self->use_config )
+ res = led_control_redgreen_dynamic_probe(channel);
+
+ if( !res )
+ res = led_control_redgreen_static_probe(channel);
+
+ if( !res )
+ led_control_close(self);
+
+ return res;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-redgreen.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-redgreen.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_REDGREEN_H_
+# define SYSFS_LED_REDGREEN_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_redgreen_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_REDGREEN_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-util.c
^
|
@@ -0,0 +1,147 @@
+/** @file sysfs-led-util.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "sysfs-led-util.h"
+
+#include "plugin-logging.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+int led_util_read_number(const char *path);
+void led_util_close_file (int *fd_ptr);
+bool led_util_open_file (int *fd_ptr, const char *path);
+int led_util_scale_value(int in, int max);
+int led_util_gcd (int a, int b);
+int led_util_roundup (int val, int range);
+
+/* ========================================================================= *
+ * FUNCTIONS
+ * ========================================================================= */
+
+/** Read number from file
+ */
+int
+led_util_read_number(const char *path)
+{
+ int res = -1;
+ int fd = -1;
+ char tmp[64];
+
+ if( (fd = open(path, O_RDONLY)) == -1 ) {
+ goto cleanup;
+ }
+ int rc = read(fd, tmp, sizeof tmp - 1);
+ if( rc < 0 ) {
+ goto cleanup;
+ }
+ tmp[rc] = 0;
+ res = strtol(tmp, 0, 0);
+
+cleanup:
+
+ if( fd != -1 ) close(fd);
+
+ return res;
+}
+
+/** Close led sysfs control file
+ */
+void
+led_util_close_file(int *fd_ptr)
+{
+ if( fd_ptr && *fd_ptr != -1 )
+ {
+ close(*fd_ptr), *fd_ptr = -1;
+ }
+}
+
+/** Open led sysfs control file in append mode
+ */
+bool
+led_util_open_file(int *fd_ptr, const char *path)
+{
+ bool res = false;
+
+ led_util_close_file(fd_ptr);
+
+ if( fd_ptr && path )
+ {
+ if( (*fd_ptr = open(path, O_WRONLY|O_APPEND)) != -1 )
+ {
+ res = true;
+ }
+ else if( errno != ENOENT )
+ {
+ mce_log(LL_WARN, "%s: %s: %m", path, "open");
+ }
+ }
+
+ return res;
+}
+
+/** Scale value from 0...255 to 0...max range
+ */
+int
+led_util_scale_value(int in, int max)
+{
+ int out = (in * max + 128) / 255;
+
+ return (out < 0) ? 0 : (out < max) ? out : max;
+}
+
+/** Calculate the greatest common divisor of two integer numbers
+ */
+int
+led_util_gcd(int a, int b)
+{
+ int t;
+ /* Use abs values; will fail if a or b < -INT_MAX */
+ if( a < 0 ) a = -a;
+ if( b < 0 ) b = -b;
+
+ /* Make it so that: a >= b */
+ if( a < b ) t = a, a = b, b = t;
+
+ /* Iterate until a mod b reaches zero */
+ while( b ) t = a % b, a = b, b = t;
+
+ /* Do not return zero even on a == b == 0 */
+ return a ?: 1;
+}
+
+/** Round up number to the next multiple of given step size
+ */
+int
+led_util_roundup(int val, int range)
+{
+ int extra = val % range;
+ if( extra ) extra = range - extra;
+ return val + extra;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-util.h
^
|
@@ -0,0 +1,36 @@
+/** @file sysfs-led-util.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_UTIL_H_
+# define SYSFS_LED_UTIL_H_
+
+# include <stdbool.h>
+
+int led_util_read_number (const char *path);
+void led_util_close_file (int *fd_ptr);
+bool led_util_open_file (int *fd_ptr, const char *path);
+int led_util_scale_value (int in, int max);
+int led_util_gcd (int a, int b);
+int led_util_roundup (int val, int range);
+
+#endif /* SYSFS_LED_UTIL_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-vanilla.c
^
|
@@ -0,0 +1,426 @@
+/** @file sysfs-led-vanilla.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ * @author Kimmo Lindholm <kimmo.lindholm@eke.fi>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * RGB led control: Jolla 1 backend
+ *
+ * Three channels, all of which:
+ * - must have 'brightness' control file
+ * - must have 'max_brightness' control file or nonzero fixed maximum
+ * - can have either
+ * o blink on/off delay control files
+ * o blink enabled/disable control control file
+ *
+ * Assumptions built into code:
+ *
+ * - The write() calls to sysfs controls return immediately from kernel to
+ * userspace, but the kernel side can stay busy with the change for few
+ * milliseconds -> Frequent intensity changes do not block mce process,
+ * so sw breathing is feasible. Minimum delay between led state changes
+ * must be enforced.
+ *
+ * - Blink controls for the R, G and B channels are independent. To avoid
+ * "rainbow patterns" when more than one channel is used the blink enabling
+ * for all of the channels as simultaneously as possible.
+ * ========================================================================= */
+
+#include "sysfs-led-vanilla.h"
+#include "sysfs-led-util.h"
+#include "sysfs-val.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *max_brightness; // R
+ const char *brightness; // W
+ const char *blink_delay_on; // W
+ const char *blink_delay_off; // W
+ const char *blink; // W
+ int max_override;// value to use if max_brightness path is NULL
+} led_paths_vanilla_t;
+
+typedef struct
+{
+ sysfsval_t *cached_max_brightness;
+ sysfsval_t *cached_brightness;
+ sysfsval_t *cached_blink_delay_on;
+ sysfsval_t *cached_blink_delay_off;
+ sysfsval_t *cached_blink;
+} led_channel_vanilla_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_vanilla_init (led_channel_vanilla_t *self);
+static void led_channel_vanilla_close (led_channel_vanilla_t *self);
+static bool led_channel_vanilla_probe (led_channel_vanilla_t *self, const led_paths_vanilla_t *path);
+static void led_channel_vanilla_set_value (led_channel_vanilla_t *self, int value);
+static void led_channel_vanilla_set_blink (led_channel_vanilla_t *self, int on_ms, int off_ms);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_vanilla_blink_cb (void *data, int on_ms, int off_ms);
+static void led_control_vanilla_value_cb (void *data, int r, int g, int b);
+static void led_control_vanilla_close_cb (void *data);
+
+bool led_control_vanilla_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_vanilla_init(led_channel_vanilla_t *self)
+{
+ self->cached_max_brightness = sysfsval_create();
+ self->cached_brightness = sysfsval_create();
+ self->cached_blink_delay_on = sysfsval_create();
+ self->cached_blink_delay_off = sysfsval_create();
+ self->cached_blink = sysfsval_create();
+}
+
+static void
+led_channel_vanilla_close(led_channel_vanilla_t *self)
+{
+ sysfsval_delete(self->cached_max_brightness),
+ self->cached_max_brightness = 0;
+
+ sysfsval_delete(self->cached_brightness),
+ self->cached_brightness = 0;
+
+ sysfsval_delete(self->cached_blink_delay_on),
+ self->cached_blink_delay_on = 0;
+
+ sysfsval_delete(self->cached_blink_delay_off),
+ self->cached_blink_delay_off = 0;
+
+ sysfsval_delete(self->cached_blink),
+ self->cached_blink = 0;
+}
+
+static bool
+led_channel_vanilla_probe(led_channel_vanilla_t *self,
+ const led_paths_vanilla_t *path)
+{
+ bool res = false;
+
+ // maximum brightness can be read from file or given in config
+ if( sysfsval_open_ro(self->cached_max_brightness, path->max_brightness) )
+ sysfsval_refresh(self->cached_max_brightness);
+
+ if( path->max_override > 0 )
+ sysfsval_assume(self->cached_max_brightness, path->max_override);
+
+ if( sysfsval_get(self->cached_max_brightness) <= 0 )
+ goto cleanup;
+
+ // we always must have brightness control
+ if( !sysfsval_open_rw(self->cached_brightness, path->brightness) )
+ goto cleanup;
+
+ // on/off period controls are optional, but both
+ // are needed if one is present
+ if( sysfsval_open_rw(self->cached_blink_delay_on, path->blink_delay_on) ) {
+ if( !sysfsval_open_rw(self->cached_blink_delay_off, path->blink_delay_off) )
+ sysfsval_close(self->cached_blink_delay_on);
+ }
+
+ // having "blink" control file is optional
+ sysfsval_open_rw(self->cached_blink, path->blink);
+
+ res = true;
+
+cleanup:
+
+ /* Always close the max_brightness file */
+ sysfsval_close(self->cached_max_brightness);
+
+ /* On failure close the other files too */
+ if( !res ) {
+ sysfsval_close(self->cached_brightness);
+ sysfsval_close(self->cached_blink_delay_on);
+ sysfsval_close(self->cached_blink_delay_off);
+ sysfsval_close(self->cached_blink);
+ }
+
+ return res;
+}
+
+static void
+led_channel_vanilla_set_value(led_channel_vanilla_t *self, int value)
+{
+ value = led_util_scale_value(value,
+ sysfsval_get(self->cached_max_brightness));
+ sysfsval_set(self->cached_brightness, value);
+
+ value = (sysfsval_get(self->cached_blink_delay_on) &&
+ sysfsval_get(self->cached_blink_delay_off));
+ sysfsval_set(self->cached_blink, value);
+
+}
+static void
+led_channel_vanilla_set_blink(led_channel_vanilla_t *self,
+ int on_ms, int off_ms)
+{
+ /* Note: Blinking config is taken in use when brightness
+ * sysfs is written to -> we need to invalidate
+ * cached brightness value if blinking changes
+ * are made.
+ */
+ sysfsval_set(self->cached_blink_delay_on, on_ms);
+ sysfsval_set(self->cached_blink_delay_off, off_ms);
+ sysfsval_invalidate(self->cached_brightness);
+
+ /* Note: Blinking enabled/disabled needs to happen
+ * after the brightness has been set
+ */
+ sysfsval_invalidate(self->cached_blink);
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define VANILLA_CHANNELS 3
+
+static void
+led_control_vanilla_blink_cb(void *data, int on_ms, int off_ms)
+{
+ led_channel_vanilla_t *channel = data;
+ led_channel_vanilla_set_blink(channel + 0, on_ms, off_ms);
+ led_channel_vanilla_set_blink(channel + 1, on_ms, off_ms);
+ led_channel_vanilla_set_blink(channel + 2, on_ms, off_ms);
+}
+
+static void
+led_control_vanilla_value_cb(void *data, int r, int g, int b)
+{
+ led_channel_vanilla_t *channel = data;
+ led_channel_vanilla_set_value(channel + 0, r);
+ led_channel_vanilla_set_value(channel + 1, g);
+ led_channel_vanilla_set_value(channel + 2, b);
+}
+
+static void
+led_control_vanilla_close_cb(void *data)
+{
+ led_channel_vanilla_t *channel = data;
+ led_channel_vanilla_close(channel + 0);
+ led_channel_vanilla_close(channel + 1);
+ led_channel_vanilla_close(channel + 2);
+}
+
+static bool
+led_control_vanilla_static_probe(led_channel_vanilla_t *channel)
+{
+ /** Sysfs control paths for RGB leds */
+ static const led_paths_vanilla_t paths[][VANILLA_CHANNELS] =
+ {
+ // vanilla
+ {
+ {
+ .blink_delay_on = "/sys/class/leds/led:rgb_red/blink_delay_on",
+ .blink_delay_off = "/sys/class/leds/led:rgb_red/blink_delay_off",
+ .brightness = "/sys/class/leds/led:rgb_red/brightness",
+ .max_brightness = "/sys/class/leds/led:rgb_red/max_brightness",
+ },
+ {
+ .blink_delay_on = "/sys/class/leds/led:rgb_green/blink_delay_on",
+ .blink_delay_off = "/sys/class/leds/led:rgb_green/blink_delay_off",
+ .brightness = "/sys/class/leds/led:rgb_green/brightness",
+ .max_brightness = "/sys/class/leds/led:rgb_green/max_brightness",
+ },
+ {
+ .blink_delay_on = "/sys/class/leds/led:rgb_blue/blink_delay_on",
+ .blink_delay_off = "/sys/class/leds/led:rgb_blue/blink_delay_off",
+ .brightness = "/sys/class/leds/led:rgb_blue/brightness",
+ .max_brightness = "/sys/class/leds/led:rgb_blue/max_brightness",
+ }
+ },
+ // i9300 (galaxy s3 international)
+ {
+ {
+ .blink_delay_on = "/sys/class/leds/led_r/delay_on",
+ .blink_delay_off = "/sys/class/leds/led_r/delay_off",
+ .brightness = "/sys/class/leds/led_r/brightness",
+ .max_brightness = "/sys/class/leds/led_r/max_brightness",
+ .blink = "/sys/class/leds/led_r/blink",
+ },
+ {
+ .blink_delay_on = "/sys/class/leds/led_g/delay_on",
+ .blink_delay_off = "/sys/class/leds/led_g/delay_off",
+ .brightness = "/sys/class/leds/led_g/brightness",
+ .max_brightness = "/sys/class/leds/led_g/max_brightness",
+ .blink = "/sys/class/leds/led_g/blink",
+ },
+ {
+ .blink_delay_on = "/sys/class/leds/led_b/delay_on",
+ .blink_delay_off = "/sys/class/leds/led_b/delay_off",
+ .brightness = "/sys/class/leds/led_b/brightness",
+ .max_brightness = "/sys/class/leds/led_b/max_brightness",
+ .blink = "/sys/class/leds/led_b/blink",
+ }
+ },
+ // yuga (sony xperia z)
+ {
+ {
+ .brightness = "/sys/class/leds/lm3533-red/brightness",
+ .max_override = 255,
+ },
+ {
+ .brightness = "/sys/class/leds/lm3533-green/brightness",
+ .max_override = 255,
+ },
+ {
+ .brightness = "/sys/class/leds/lm3533-blue/brightness",
+ .max_override = 255,
+ },
+ },
+ // onyx (OnePlus X)
+ {
+ {
+ .brightness = "/sys/class/leds/red/brightness",
+ .max_brightness = "/sys/class/leds/red/max_brightness",
+ .blink_delay_on = "/sys/class/leds/red/pause_hi",
+ .blink_delay_off = "/sys/class/leds/red/pause_lo",
+ .blink = "/sys/class/leds/red/blink",
+ },
+ {
+ .brightness = "/sys/class/leds/green/brightness",
+ .max_brightness = "/sys/class/leds/green/max_brightness",
+ .blink_delay_on = "/sys/class/leds/green/pause_hi",
+ .blink_delay_off = "/sys/class/leds/green/pause_lo",
+ .blink = "/sys/class/leds/green/blink",
+ },
+ {
+ .brightness = "/sys/class/leds/blue/brightness",
+ .max_brightness = "/sys/class/leds/blue/max_brightness",
+ .blink_delay_on = "/sys/class/leds/blue/pause_hi",
+ .blink_delay_off = "/sys/class/leds/blue/pause_lo",
+ .blink = "/sys/class/leds/blue/blink",
+ },
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( led_channel_vanilla_probe(&channel[0], &paths[i][0]) &&
+ led_channel_vanilla_probe(&channel[1], &paths[i][1]) &&
+ led_channel_vanilla_probe(&channel[2], &paths[i][2]) ) {
+ ack = true;
+ break;
+ }
+ }
+
+ return ack;
+}
+
+static bool
+led_control_vanilla_dynamic_probe(led_channel_vanilla_t *channel)
+{
+ static const objconf_t vanilla_conf[] =
+ {
+ OBJCONF_FILE(led_paths_vanilla_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_vanilla_t, max_brightness, MaxBrightness),
+ OBJCONF_FILE(led_paths_vanilla_t, blink_delay_on, BlinkDelayOn),
+ OBJCONF_FILE(led_paths_vanilla_t, blink_delay_off, BlinkDelayOff),
+ OBJCONF_FILE(led_paths_vanilla_t, blink, Blink),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[VANILLA_CHANNELS] =
+ {
+ "Red", "Green", "Blue"
+ };
+
+ bool ack = false;
+
+ led_paths_vanilla_t paths[VANILLA_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < VANILLA_CHANNELS; ++i )
+ objconf_init(vanilla_conf, &paths[i]);
+
+ for( size_t i = 0; i < VANILLA_CHANNELS; ++i )
+ {
+ if( !objconf_parse(vanilla_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_vanilla_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < VANILLA_CHANNELS; ++i )
+ objconf_quit(vanilla_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_vanilla_probe(led_control_t *self)
+{
+
+ static led_channel_vanilla_t channel[VANILLA_CHANNELS];
+
+ bool res = false;
+
+ led_channel_vanilla_init(channel+0);
+ led_channel_vanilla_init(channel+1);
+ led_channel_vanilla_init(channel+2);
+
+ self->name = "vanilla";
+ self->data = channel;
+ self->enable = 0;
+ self->blink = led_control_vanilla_blink_cb;
+ self->value = led_control_vanilla_value_cb;
+ self->close = led_control_vanilla_close_cb;
+
+ if( self->use_config )
+ res = led_control_vanilla_dynamic_probe(channel);
+
+ if( !res )
+ res = led_control_vanilla_static_probe(channel);
+
+ if( !res )
+ led_control_close(self);
+
+ return res;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-vanilla.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-vanilla.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2013-2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_VANILLA_H_
+# define SYSFS_LED_VANILLA_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_vanilla_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_VANILLA_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-white.c
^
|
@@ -0,0 +1,267 @@
+/** @file sysfs-led-white.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* ========================================================================= *
+ * White / single color led control
+ *
+ * One channel, which:
+ * - must have 'brightness' control file
+ * - must have 'max_brightness' control file
+ * ========================================================================= */
+
+#include "sysfs-led-white.h"
+
+#include "sysfs-led-util.h"
+#include "sysfs-val.h"
+#include "plugin-config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+/* ========================================================================= *
+ * PROTOTYPES
+ * ========================================================================= */
+
+typedef struct
+{
+ const char *max_brightness; // R
+ const char *brightness; // W
+} led_paths_white_t;
+
+typedef struct
+{
+ sysfsval_t *cached_max_brightness;
+ sysfsval_t *cached_brightness;
+} led_channel_white_t;
+
+/* ------------------------------------------------------------------------- *
+ * ONE_CHANNEL
+ * ------------------------------------------------------------------------- */
+
+static void led_channel_white_init (led_channel_white_t *self);
+static void led_channel_white_close (led_channel_white_t *self);
+static bool led_channel_white_probe (led_channel_white_t *self, const led_paths_white_t *path);
+static void led_channel_white_set_value (const led_channel_white_t *self, int value);
+
+/* ------------------------------------------------------------------------- *
+ * ALL_CHANNELS
+ * ------------------------------------------------------------------------- */
+
+static void led_control_white_map_color (int r, int g, int b, int *white);
+static void led_control_white_value_cb (void *data, int r, int g, int b);
+static void led_control_white_close_cb (void *data);
+
+bool led_control_white_probe (led_control_t *self);
+
+/* ========================================================================= *
+ * ONE_CHANNEL
+ * ========================================================================= */
+
+static void
+led_channel_white_init(led_channel_white_t *self)
+{
+ self->cached_max_brightness = sysfsval_create();
+ self->cached_brightness = sysfsval_create();
+}
+
+static void
+led_channel_white_close(led_channel_white_t *self)
+{
+ sysfsval_delete(self->cached_max_brightness),
+ self->cached_max_brightness = 0;
+
+ sysfsval_delete(self->cached_brightness),
+ self->cached_brightness = 0;
+}
+
+static bool
+led_channel_white_probe(led_channel_white_t *self,
+ const led_paths_white_t *path)
+{
+ bool res = false;
+
+ if( !sysfsval_open_rw(self->cached_brightness, path->brightness) )
+ goto cleanup;
+
+ if( !sysfsval_open_ro(self->cached_max_brightness, path->max_brightness) )
+ goto cleanup;
+
+ sysfsval_refresh(self->cached_max_brightness);
+
+ if( sysfsval_get(self->cached_max_brightness) <= 0 )
+ goto cleanup;
+
+ res = true;
+
+cleanup:
+
+ /* Always close the max_brightness file */
+ sysfsval_close(self->cached_max_brightness);
+
+ /* On failure close the other files too */
+ if( !res )
+ {
+ sysfsval_close(self->cached_brightness);
+ }
+
+ return res;
+}
+
+static void
+led_channel_white_set_value(const led_channel_white_t *self, int value)
+{
+ value = led_util_scale_value(value,
+ sysfsval_get(self->cached_max_brightness));
+ sysfsval_set(self->cached_brightness, value);
+}
+
+/* ========================================================================= *
+ * ALL_CHANNELS
+ * ========================================================================= */
+
+#define WHITE_CHANNELS 1
+
+static void
+led_control_white_map_color(int r, int g, int b, int *white)
+{
+ /* Use maximum value from requested RGB value */
+ if( r < g ) r = g;
+ if( r < b ) r = b;
+ *white = r;
+}
+
+static void
+led_control_white_value_cb(void *data, int r, int g, int b)
+{
+ const led_channel_white_t *channel = data;
+
+ int white = 0;
+ led_control_white_map_color(r, g, b, &white);
+
+ led_channel_white_set_value(channel + 0, white);
+}
+
+static void
+led_control_white_close_cb(void *data)
+{
+ led_channel_white_t *channel = data;
+ led_channel_white_close(channel + 0);
+}
+static bool
+led_control_white_static_probe(led_channel_white_t *channel)
+{
+ /** Sysfs control paths for White leds */
+ static const led_paths_white_t paths[][WHITE_CHANNELS] =
+ {
+ // "Motorola Moto G (2nd gen)"
+ {
+ {
+ .max_brightness = "/sys/class/leds/white/max_brightness",
+ .brightness = "/sys/class/leds/white/brightness",
+ },
+ },
+ };
+
+ bool ack = false;
+
+ for( size_t i = 0; i < G_N_ELEMENTS(paths); ++i ) {
+ if( (ack = led_channel_white_probe(channel+0, &paths[i][0])) )
+ break;
+ }
+
+ return ack;
+}
+
+static bool
+led_control_white_dynamic_probe(led_channel_white_t *channel)
+{
+ static const objconf_t white_conf[] =
+ {
+ OBJCONF_FILE(led_paths_white_t, brightness, Brightness),
+ OBJCONF_FILE(led_paths_white_t, max_brightness, MaxBrightness),
+ OBJCONF_STOP
+ };
+
+ static const char * const pfix[WHITE_CHANNELS] =
+ {
+ "Led",
+ };
+
+ bool ack = false;
+
+ led_paths_white_t paths[WHITE_CHANNELS];
+
+ memset(paths, 0, sizeof paths);
+ for( size_t i = 0; i < WHITE_CHANNELS; ++i )
+ objconf_init(white_conf, &paths[i]);
+
+ for( size_t i = 0; i < WHITE_CHANNELS; ++i ) {
+ if( !objconf_parse(white_conf, &paths[i], pfix[i]) )
+ goto cleanup;
+
+ if( !led_channel_white_probe(channel+i, &paths[i]) )
+ goto cleanup;
+ }
+
+ ack = true;
+
+cleanup:
+
+ for( size_t i = 0; i < WHITE_CHANNELS; ++i )
+ objconf_quit(white_conf, &paths[i]);
+
+ return ack;
+}
+
+bool
+led_control_white_probe(led_control_t *self)
+{
+
+ static led_channel_white_t channel[WHITE_CHANNELS];
+
+ bool res = false;
+
+ led_channel_white_init(channel + 0);
+
+ self->name = "white";
+ self->data = channel;
+ self->enable = 0;
+ self->value = led_control_white_value_cb;
+ self->close = led_control_white_close_cb;
+
+ /* We can use sw breathing logic */
+ self->can_breathe = true;
+
+ if( self->use_config )
+ res = led_control_white_dynamic_probe(channel);
+
+ if( !res )
+ res = led_control_white_static_probe(channel);
+
+ if( !res )
+ led_control_close(self);
+
+ return res;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-led-white.h
^
|
@@ -0,0 +1,31 @@
+/** @file sysfs-led-white.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_LED_WHITE_H_
+# define SYSFS_LED_WHITE_H_
+
+# include "sysfs-led-main.h"
+
+bool led_control_white_probe(led_control_t *self);
+
+#endif /* SYSFS_LED_WHITE_H_ */
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-val.c
^
|
@@ -0,0 +1,374 @@
+/** @file sysfs-val.c
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "sysfs-val.h"
+
+#include "plugin-logging.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* ========================================================================= *
+ * TYPES
+ * ========================================================================= */
+
+struct sysfsval_t
+{
+ char *sv_path;
+ int sv_file;
+ int sv_curr;
+};
+
+/* ========================================================================= *
+ * PROTOS
+ * ========================================================================= */
+
+static void sysfsval_ctor (sysfsval_t *self);
+static void sysfsval_dtor (sysfsval_t *self);
+
+sysfsval_t *sysfsval_create (void);
+void sysfsval_delete (sysfsval_t *self);
+bool sysfsval_open_rw (sysfsval_t *self, const char *path);
+bool sysfsval_open_ro (sysfsval_t *self, const char *path);
+static bool sysfsval_open_ex (sysfsval_t *self, const char *path, mode_t mode);
+void sysfsval_close (sysfsval_t *self);
+const char *sysfsval_path (const sysfsval_t *self);
+int sysfsval_get (const sysfsval_t *self);
+bool sysfsval_set (sysfsval_t *self, int value);
+void sysfsval_invalidate(sysfsval_t *self);
+bool sysfsval_refresh (sysfsval_t *self);
+
+/* ========================================================================= *
+ * CODE
+ * ========================================================================= */
+
+/** Initialize sysfsval_t object to a sane state
+ *
+ * @param self sysfsval_t object pointer
+ */
+static void
+sysfsval_ctor(sysfsval_t *self)
+{
+ self->sv_path = 0;
+ self->sv_file = -1;
+ self->sv_curr = -1;
+}
+
+/** Release all dynamically allocated resources used by sysfsval_t object
+ *
+ * @param self sysfsval_t object pointer
+ */
+static void
+sysfsval_dtor(sysfsval_t *self)
+{
+ sysfsval_close(self);
+}
+
+/** Allocate and initialize an sysfsval_t object
+ *
+ * @return sysfsval_t object pointer
+ */
+sysfsval_t *
+sysfsval_create(void)
+{
+ sysfsval_t *self = calloc(1, sizeof *self);
+ sysfsval_ctor(self);
+ return self;
+}
+
+/** De-initialize and release sysfsval_t object
+ *
+ * @param self sysfsval_t object pointer, or NULL
+ */
+void
+sysfsval_delete(sysfsval_t *self)
+{
+ if( self ) {
+ sysfsval_dtor(self);
+ free(self);
+ }
+}
+
+/** Assign path to sysfsval_t object and open the file in read+write mode
+ *
+ * @param self sysfsval_t object pointer
+ *
+ * @return true if file was opened succesfully, false otherwise
+ */
+bool
+sysfsval_open_rw(sysfsval_t *self, const char *path)
+{
+ return sysfsval_open_ex(self, path, O_RDWR);
+}
+
+/** Assign path to sysfsval_t object and open the file in read-only mode
+ *
+ * @param self sysfsval_t object pointer
+ *
+ * @return true if file was opened succesfully, false otherwise
+ */
+bool
+sysfsval_open_ro(sysfsval_t *self, const char *path)
+{
+ return sysfsval_open_ex(self, path, O_RDONLY);
+}
+
+static bool
+sysfsval_open_ex(sysfsval_t *self, const char *path, mode_t mode)
+{
+ bool ack = false;
+
+ sysfsval_close(self);
+
+ if( !path )
+ goto EXIT;
+
+ if( (self->sv_path = strdup(path)) == 0 )
+ goto EXIT;
+
+ if( (self->sv_file = open(path, mode)) == -1 ) {
+ if( errno == ENOENT )
+ mce_log(LOG_DEBUG, "%s: open: %m", path);
+ else
+ mce_log(LOG_ERR, "%s: open: %m", path);
+ goto EXIT;
+ }
+
+ mce_log(LOG_DEBUG, "%s: opened", sysfsval_path(self));
+
+ /* Note: Current value is not fetched by default */
+
+ ack = true;
+
+EXIT:
+ if( !ack )
+ sysfsval_close(self);
+
+ return ack;
+}
+
+/** Close file associated with sysfsval_t object and forget file path
+ *
+ * @param self sysfsval_t object pointer
+ */
+void
+sysfsval_close(sysfsval_t *self)
+{
+ if( self->sv_file != -1 ) {
+ mce_log(LOG_DEBUG, "%s: closed", sysfsval_path(self));
+ close(self->sv_file), self->sv_file = -1;
+ }
+
+ free(self->sv_path), self->sv_path = 0;
+}
+
+/** Get file path associated with sysfsval_t object
+ *
+ * Note: This function is meant to be used only for diagnostic
+ * logging and it can be assumed to always return a valid c string.
+ *
+ * @param self sysfsval_t object pointer
+ *
+ * @return file path, or "unset"
+ */
+const char *
+sysfsval_path(const sysfsval_t *self)
+{
+ return self->sv_path ?: "unset";
+}
+
+/** Get integer value associated with sysfsval_t object
+ *
+ * @param self sysfsval_t object pointer
+ *
+ * @return cached content of sysfs file as integer, or -1
+ */
+int
+sysfsval_get(const sysfsval_t *self)
+{
+ return self->sv_curr;
+}
+
+/** Update sysfs content associated with sysfsval_t object
+ *
+ * @param self sysfsval_t object pointer
+ * @param value number to write to sysfs file
+ *
+ * @return false if updating sysfs content failed, true otherwise
+ */
+bool
+sysfsval_set(sysfsval_t *self, int value)
+{
+ bool ack = true;
+
+ int prev = self->sv_curr;
+ self->sv_curr = value;
+
+ if( prev == self->sv_curr )
+ goto EXIT;
+
+ /* If file is closed: assume it was optional and do not
+ * spam journal with transitions related to it */
+ if( self->sv_file == -1 )
+ goto EXIT;
+
+ mce_log(LOG_DEBUG, "%s: write: %d -> %d", sysfsval_path(self),
+ prev, self->sv_curr);
+
+ char data[256];
+
+ int todo = snprintf(data, sizeof data, "%d", value);
+ int done = write(self->sv_file, data, todo);
+
+ if( done == todo )
+ goto EXIT;
+
+ ack = false;
+
+ if( done == -1 )
+ mce_log(LOG_ERR, "%s: write: %m", sysfsval_path(self));
+ else
+ mce_log(LOG_ERR, "%s: write: partial", sysfsval_path(self));
+
+EXIT:
+ return ack;
+}
+
+/** Update cached value associated with sysfsval_t object
+ *
+ * Meant to be used in cases where it is known that writing to
+ * one sysfs file changes also the value of some other sysfs
+ * control file and we want to be able to avoid unnecessary
+ * write when the next sysfsval_set() call is made.
+ *
+ * @param self sysfsval_t object pointer
+ * @param value number to write to sysfs file
+ */
+void
+sysfsval_assume(sysfsval_t *self, int value)
+{
+ int prev = self->sv_curr;
+ self->sv_curr = value;
+
+ if( prev == self->sv_curr )
+ goto EXIT;
+
+ /* If file is closed: assume it was optional and do not
+ * spam journal with transitions related to it */
+ if( self->sv_file == -1 )
+ goto EXIT;
+
+ mce_log(LOG_DEBUG, "%s: assume: %d -> %d", sysfsval_path(self),
+ prev, self->sv_curr);
+
+EXIT:
+ return;
+}
+
+/** Invalidate cached value associated with sysfsval_t object
+ *
+ * Meant to be used in cases where it is known that the
+ * sysfs file needs to be written the next time sysfsval_set()
+ * gets called.
+ *
+ * @param self sysfsval_t object pointer
+ * @param value number to write to sysfs file
+ */
+void
+sysfsval_invalidate(sysfsval_t *self)
+{
+ int prev = self->sv_curr;
+ self->sv_curr = -1;
+
+ if( prev == self->sv_curr )
+ goto EXIT;
+
+ /* If file is closed: assume it was optional and do not
+ * spam journal with transitions related to it */
+ if( self->sv_file == -1 )
+ goto EXIT;
+
+ mce_log(LOG_DEBUG, "%s: invalidated", sysfsval_path(self));
+
+EXIT:
+ return;
+}
+
+/** Read value from sysfs file associated with sysfsval_t object
+ *
+ * Meant to be used for obtainining initial value / in cases
+ * it is known that the cached value is most likely not reflecting
+ * the actual data available via sysfs.
+ *
+ * @param self sysfsval_t object pointer
+ *
+ * @return true if reading succeeded, false otherwise
+ */
+bool
+sysfsval_refresh(sysfsval_t *self)
+{
+ bool ack = false;
+ int value = -1;
+
+ char data[256];
+
+ if( self->sv_file == -1 )
+ goto EXIT;
+
+ if( lseek(self->sv_file, 0, SEEK_SET) == -1 ) {
+ mce_log(LOG_ERR, "%s: seek: %m", sysfsval_path(self));
+ goto EXIT;
+ }
+
+ int done = read(self->sv_file, data, sizeof data - 1);
+
+ if( done == -1 ) {
+ mce_log(LOG_ERR, "%s: read: %m", sysfsval_path(self));
+ goto EXIT;
+ }
+
+ if( done == 0 ) {
+ mce_log(LOG_ERR, "%s: read: EOF", sysfsval_path(self));
+ goto EXIT;
+ }
+
+ data[done] = 0;
+ value = strtol(data, 0, 0);
+
+ mce_log(LOG_DEBUG, "%s: read: %d -> %d", sysfsval_path(self),
+ self->sv_curr, value);
+ self->sv_curr = value;
+
+ ack = true;
+
+EXIT:
+
+ if( !ack )
+ sysfsval_invalidate(self);
+
+ return ack;
+}
|
[-]
[+]
|
Added |
_service:tar_git:mce-plugin-libhybris-1.12.1.tar.bz2/sysfs-val.h
^
|
@@ -0,0 +1,51 @@
+/** @file sysfs-val.h
+ *
+ * mce-plugin-libhybris - Libhybris plugin for Mode Control Entity
+ * <p>
+ * Copyright (C) 2017 Jolla Ltd.
+ * <p>
+ * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
+ *
+ * mce-plugin-libhybris is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * mce-plugin-libhybris is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with mce-plugin-libhybris; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSFS_VAL_H_
+# define SYSFS_VAL_H_
+
+#include <stdbool.h>
+
+/* ========================================================================= *
+ * TYPES
+ * ========================================================================= */
+
+typedef struct sysfsval_t sysfsval_t;
+
+/* ========================================================================= *
+ * PROTOS
+ * ========================================================================= */
+
+sysfsval_t *sysfsval_create (void);
+void sysfsval_delete (sysfsval_t *self);
+bool sysfsval_open_rw (sysfsval_t *self, const char *path);
+bool sysfsval_open_ro (sysfsval_t *self, const char *path);
+void sysfsval_close (sysfsval_t *self);
+const char *sysfsval_path (const sysfsval_t *self);
+int sysfsval_get (const sysfsval_t *self);
+bool sysfsval_set (sysfsval_t *self, int value);
+void sysfsval_assume (sysfsval_t *self, int value);
+void sysfsval_invalidate(sysfsval_t *self);
+bool sysfsval_refresh (sysfsval_t *self);
+
+#endif /* SYSFS_VAL_H_ */
|
[-]
[+]
|
Deleted |
_service:tar_git:mce-plugin-libhybris-1.7.1.tar.bz2/hybris.c
^
|
@@ -1,2964 +0,0 @@
-/* ------------------------------------------------------------------------- *
- * Copyright (C) 2013 Jolla Ltd.
- * Contact: Simo Piiroinen <simo.piiroinen@jollamobile.com>
- * License: LGPLv2.1
- * ------------------------------------------------------------------------- */
-
-/* ========================================================================= *
- * This module implements "mce-libhybris-plugin" for use from
- * "mce-libhybris-module" within mce.
- *
- * The idea of "hybris-plugin" is shortly:
- * - it uses no mce functions or data types
- * - it can be compiled independently from mce
- * - it exposes no libhybris/android datatypes / functions
- *
- * And the idea of "hybris-module" is:
- * - it contains functions with the same names as "hybris-plugin"
- * - if called, the functions will load & call "hybris-plugin" code
- * - if "hybris-plugin" is not present "hybris-module" functions
- * still work, but return failures for everything
- *
- * Put together:
- * - mce code can assume that libhybris code is always available and
- * callable during hw probing activity
- * - if hybris plugin is not installed (or if some hw is not supported
- * by the underlying android code), failures will be reported and mce
- * can try other existing ways to proble hw controls
- * ========================================================================= */
-
-#define MCE_HYBRIS_INTERNAL 2
-#include "mce-hybris.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <syslog.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <math.h>
-#include <errno.h>
-
-#include <glib.h>
-
-#include <system/window.h>
-#include <hardware/lights.h>
-#include <hardware/fb.h>
-#include <hardware/sensors.h>
-
-static void mce_hybris_sensors_quit(void);
-
-static void mce_hybris_log(int lev, const char *file,
- const char *func, const char *fmt,
- ...) __attribute__ ((format (printf, 4, 5)));
-
-/* ========================================================================= *
- * LOGGING
- * ========================================================================= */
-
-/** Callback function for diagnostic output, or NULL for stderr output */
-static mce_hybris_log_fn log_cb = 0;
-
-/** Set diagnostic output forwarding callback
- *
- * @param cb The callback function to use, or NULL for stderr output
- */
-void mce_hybris_set_log_hook(mce_hybris_log_fn cb)
-{
- log_cb = cb;
-}
-
-/** Wrapper for diagnostic logging
- *
- * @param lev syslog priority (=mce_log level) i.e. LOG_ERR etc
- * @param file source code path
- * @param func name of function within file
- * @param fmt printf compatible format string
- * @param ... parameters required by the format string
- */
-static void mce_hybris_log(int lev, const char *file, const char *func,
- const char *fmt, ...)
-{
- char *msg = 0;
- va_list va;
-
- va_start(va, fmt);
- if( vasprintf(&msg, fmt, va) < 0 ) msg = 0;
- va_end(va);
-
- if( msg ) {
- if( log_cb ) log_cb(lev, file, func, msg);
- else fprintf(stderr, "%s: %s: %s\n", file, func, msg);
- free(msg);
- }
-}
-
-/** Logging from hybris plugin mimics mce-log.h API */
-#define mce_log(LEV,FMT,ARGS...) \
- mce_hybris_log(LEV, __FILE__, __FUNCTION__ ,FMT, ## ARGS)
-
-/* ========================================================================= *
- * THREAD helpers
- * ========================================================================= */
-
-/** Thread start details; used for inserting custom thread setup code */
-typedef struct
-{
- void *data;
- void (*func)(void *);
-} gate_t;
-
-/** Mutex used for synchronous worker thread startup */
-static pthread_mutex_t gate_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/** Condition used for signaling worker thread startup */
-static pthread_cond_t gate_cond = PTHREAD_COND_INITIALIZER;
-
-/** Wrapper for starting new worker thread
- *
- * For use from mce_hybris_start_thread().
- *
- * Before the actual thread start routine is called, the
- * new thread is put in to asynchronously cancellabe state
- * and the starter is woken up via condition.
- *
- * @param aptr wrapper data as void pointer
- *
- * @return 0 on thread exit - via pthread_join()
- */
-static void *gate_start(void *aptr)
-{
- gate_t *gate = aptr;
-
- void (*func)(void*);
- void *data;
-
- /* Allow quick and dirty cancellation */
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
-
- /* Tell thread gate we're up and running */
- pthread_mutex_lock(&gate_mutex);
- pthread_cond_broadcast(&gate_cond);
- pthread_mutex_unlock(&gate_mutex);
-
- /* Collect data we need, release rest */
- func = gate->func;
- data = gate->data;
- free(gate), gate = 0;
-
- /* Call the real thread start */
- func(data);
-
- return 0;
-}
-
-/** Helper for starting new worker thread
- *
- * @param start function to call from new thread
- * @param arg data to pass to start function
- *
- * @return thread id on success, or 0 on error
- */
-static pthread_t mce_hybris_start_thread(void (*start)(void *),
- void* arg)
-{
- pthread_t res = 0;
- gate_t *gate = 0;
-
- if( !(gate = calloc(1, sizeof gate)) ) {
- goto EXIT;
- }
-
- gate->data = arg;
- gate->func = start;
-
- pthread_mutex_lock(&gate_mutex);
-
- if( pthread_create(&res, 0, gate_start, gate) != 0 ) {
- mce_log(LOG_ERR, "could not start worker thread");
-
- /* content of res is undefined on failure, force to zero */
- res = 0;
- }
- else {
- /* wait until thread has had time to start and set
- * up the cancellation parameters */
- mce_log(LOG_DEBUG, "waiting worker to start ...");
- pthread_cond_wait(&gate_cond, &gate_mutex);
- mce_log(LOG_DEBUG, "worker started");
-
- /* the thread owns the gate now */
- gate = 0;
- }
-
- pthread_mutex_unlock(&gate_mutex);
-
-EXIT:
-
- free(gate);
-
- return res;
-}
-
-/* ========================================================================= *
- * FRAMEBUFFER module
- * ========================================================================= */
-
-/** Handle for libhybris framebuffer plugin */
-static const struct hw_module_t *mod_fb = 0;
-
-/** Pointer to libhybris frame buffer device object */
-static struct framebuffer_device_t *dev_fb = 0;
-
-/** Load libhybris framebuffer plugin
- *
- * @return true on success, false on failure
- */
-static bool mce_hybris_modfb_load(void)
-{
- static bool done = false;
-
- if( !done ) {
- done = true;
- hw_get_module(GRALLOC_HARDWARE_FB0, &mod_fb);
- if( !mod_fb ) {
- mce_log(LOG_WARNING, "failed to open frame buffer module");
- }
- else {
- mce_log(LOG_DEBUG, "mod_fb = %p", mod_fb);
- }
- }
-
- return mod_fb != 0;
-}
-
-/** Unload libhybris framebuffer plugin
- */
-static void mce_hybris_modfb_unload(void)
-{
-
- /* cleanup dependencies */
- mce_hybris_framebuffer_quit();
-
- /* actually unload the module */
- // FIXME: how to unload libhybris modules?
-}
-
-/* ------------------------------------------------------------------------- *
- * framebuffer device
- * ------------------------------------------------------------------------- */
-
-/** Convenience function for opening frame buffer device
- *
- * Similar to what we might or might not have available from hardware/fb.h
- */
-static int
-mce_framebuffer_open(const struct hw_module_t* module,
- struct framebuffer_device_t** device)
-{
- return module->methods->open(module, GRALLOC_HARDWARE_FB0,
- (struct hw_device_t**)device);
-}
-
-/** Convenience function for closing frame buffer device
- *
- * Similar to what we might or might not have available from hardware/fb.h
- */
-static int
-mce_framebuffer_close(struct framebuffer_device_t* device)
-{
- return device->common.close(&device->common);
-}
-
-/** Initialize libhybris frame buffer device object
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_framebuffer_init(void)
-{
- static bool done = false;
-
- if( !done ) {
- done = true;
-
- if( !mce_hybris_modfb_load() ) {
- goto cleanup;
- }
-
- mce_framebuffer_open(mod_fb, &dev_fb);
- if( !dev_fb ) {
- mce_log(LOG_ERR, "failed to open framebuffer device");
- }
- else {
- mce_log(LOG_DEBUG, "dev_fb = %p", dev_fb);
- }
- }
-
-cleanup:
- return dev_fb != 0;
-}
-
-/** Release libhybris frame buffer device object
- */
-void mce_hybris_framebuffer_quit(void)
-{
- if( dev_fb ) {
- mce_framebuffer_close(dev_fb), dev_fb = 0;
- }
-}
-
-/** Set frame buffer power state via libhybris
- *
- * @param state true to power on, false to power off
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_framebuffer_set_power(bool state)
-{
- bool ack = false;
-
- if( !mce_hybris_framebuffer_init() ) {
- goto cleanup;
- }
-
- if( dev_fb->enableScreen(dev_fb, state) < 0 ) {
- goto cleanup;
- }
-
- ack = true;
-
-cleanup:
- return ack;
-}
-
-/* ========================================================================= *
- * LIGHTS module
- * ========================================================================= */
-
-/** Handle for libhybris lights plugin */
-static const struct hw_module_t *mod_lights = 0;
-
-/** Pointer to libhybris frame display backlight device object */
-static struct light_device_t *dev_backlight = 0;
-
-/** Pointer to libhybris frame keypad backlight device object */
-static struct light_device_t *dev_keypad = 0;
-
-/** Pointer to libhybris frame indicator led device object */
-static struct light_device_t *dev_indicator = 0;
-
-/** Load libhybris lights plugin
- *
- * @return true on success, false on failure
- */
-static bool mce_hybris_modlights_load(void)
-{
- static bool done = false;
-
- if( !done ) {
- done = true;
- hw_get_module(LIGHTS_HARDWARE_MODULE_ID, &mod_lights);
- if( !mod_lights ) {
- mce_log(LOG_WARNING, "failed to open lights module");
- }
- else {
- mce_log(LOG_DEBUG, "mod_lights = %p", mod_lights);
- }
- }
-
- return mod_lights != 0;
-}
-
-/** Unload libhybris lights plugin
- */
-static void mce_hybris_modlights_unload(void)
-{
- /* cleanup dependencies */
- mce_hybris_backlight_quit();
- mce_hybris_keypad_quit();
- mce_hybris_indicator_quit();
-
- /* actually unload the module */
- // FIXME: how to unload libhybris modules?
-}
-
-/* ========================================================================= *
- * LIGHTS module: display backlight device
- * ========================================================================= */
-
-/** Convenience function for opening a light device
- *
- * Similar to what we might or might not have available from hardware/lights.h
- */
-static int
-mce_light_device_open(const struct hw_module_t* module, const char *id,
- struct light_device_t** device)
-{
- return module->methods->open(module, id, (struct hw_device_t**)device);
-}
-
-/** Convenience function for closing a light device
- *
- * Similar to what we might or might not have available from hardware/lights.h
- */
-static void
-mce_light_device_close(const struct light_device_t *device)
-{
- device->common.close((struct hw_device_t*) device);
-}
-
-/** Initialize libhybris display backlight device object
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_backlight_init(void)
-{
- static bool done = false;
-
- if( !done ) {
- done = true;
-
- if( !mce_hybris_modlights_load() ) {
- goto cleanup;
- }
-
- mce_light_device_open(mod_lights, LIGHT_ID_BACKLIGHT, &dev_backlight);
-
- if( !dev_backlight ) {
- mce_log(LOG_WARNING, "failed to open backlight device");
- }
- else {
- mce_log(LOG_DEBUG, "%s() -> %p", __FUNCTION__, dev_backlight);
- }
- }
-
-cleanup:
- return dev_backlight != 0;
-}
-
-/** Release libhybris display backlight device object
- */
-void mce_hybris_backlight_quit(void)
-{
- if( dev_backlight ) {
- mce_light_device_close(dev_backlight), dev_backlight = 0;
- }
-}
-
-/** Set display backlight brightness via libhybris
- *
- * @param level 0=off ... 255=maximum brightness
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_backlight_set_brightness(int level)
-{
- bool ack = false;
- unsigned lev = (level < 0) ? 0 : (level > 255) ? 255 : level;
-
- struct light_state_t lst;
-
- if( !mce_hybris_backlight_init() ) {
- goto cleanup;
- }
-
- memset(&lst, 0, sizeof lst);
- lst.color = (0xff << 24) | (lev << 16) | (lev << 8) | (lev << 0);
- lst.flashMode = LIGHT_FLASH_NONE;
- lst.flashOnMS = 0;
- lst.flashOffMS = 0;
- lst.brightnessMode = BRIGHTNESS_MODE_USER;
-
- if( dev_backlight->set_light(dev_backlight, &lst) < 0 ) {
- goto cleanup;
- }
-
- ack = true;
-
-cleanup:
-
- mce_log(LOG_DEBUG, "%s(%d) -> %s", __FUNCTION__, level, ack ? "success" : "failure");
-
- return ack;
-}
-
-/* ========================================================================= *
- * LIGHTS module: keypad backlight device
- * ========================================================================= */
-
-/** Initialize libhybris keypad backlight device object
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_keypad_init(void)
-{
- static bool done = false;
-
- if( !done ) {
- done = true;
-
- if( !mce_hybris_modlights_load() ) {
- goto cleanup;
- }
-
- mce_light_device_open(mod_lights, LIGHT_ID_KEYBOARD, &dev_keypad);
-
- if( !dev_keypad ) {
- mce_log(LOG_WARNING, "failed to open keypad backlight device");
- }
- else {
- mce_log(LOG_DEBUG, "%s() -> %p", __FUNCTION__, dev_keypad);
- }
- }
-
-cleanup:
- return dev_keypad != 0;
-}
-
-/** Release libhybris keypad backlight device object
- */
-void mce_hybris_keypad_quit(void)
-{
- if( dev_keypad ) {
- mce_light_device_close(dev_keypad), dev_keypad = 0;
- }
-}
-
-/** Set display keypad brightness via libhybris
- *
- * @param level 0=off ... 255=maximum brightness
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_keypad_set_brightness(int level)
-{
- bool ack = false;
- unsigned lev = (level < 0) ? 0 : (level > 255) ? 255 : level;
-
- struct light_state_t lst;
-
- if( !mce_hybris_keypad_init() ) {
- goto cleanup;
- }
-
- memset(&lst, 0, sizeof lst);
- lst.color = (0xff << 24) | (lev << 16) | (lev << 8) | (lev << 0);
- lst.flashMode = LIGHT_FLASH_NONE;
- lst.flashOnMS = 0;
- lst.flashOffMS = 0;
- lst.brightnessMode = BRIGHTNESS_MODE_USER;
-
- if( dev_keypad->set_light(dev_keypad, &lst) < 0 ) {
- goto cleanup;
- }
-
- ack = true;
-
-cleanup:
-
- mce_log(LOG_DEBUG, "%s(%d) -> %s", __FUNCTION__, level, ack ? "success" : "failure");
-
- return ack;
-}
-
-/* ========================================================================= *
- * LIGHTS module: indicator led device
- * ========================================================================= */
-
-/* ------------------------------------------------------------------------- *
- * generic led utils
- * ------------------------------------------------------------------------- */
-
-/** Read number from file */
-static int led_util_read_number(const char *path)
-{
- int res = -1;
- int fd = -1;
- char tmp[64];
-
- if( (fd = open(path, O_RDONLY)) == -1 ) {
- goto cleanup;
- }
- int rc = read(fd, tmp, sizeof tmp - 1);
- if( rc < 0 ) {
- goto cleanup;
- }
- tmp[rc] = 0;
- res = strtol(tmp, 0, 0);
-
-cleanup:
- if( fd != -1 ) close(fd);
-
- return res;
-}
-
-/** Close led sysfs control file
- */
-static void led_util_close_file(int *fd_ptr)
-{
- if( fd_ptr && *fd_ptr != -1 )
- {
- close(*fd_ptr), *fd_ptr = -1;
- }
-}
-
-/** Open led sysfs control file in append mode
- */
-static bool led_util_open_file(int *fd_ptr, const char *path)
-{
- bool res = false;
-
- led_util_close_file(fd_ptr);
-
- if( fd_ptr && path )
- {
- if( (*fd_ptr = open(path, O_WRONLY|O_APPEND)) != -1 )
- {
- res = true;
- }
- else if( errno != ENOENT )
- {
- mce_log(LOG_WARNING, "%s: %s: %m", path, "open");
- }
- }
-
- return res;
-}
-
-/** Scale value from 0...255 to 0...max range
- */
-static int led_util_scale_value(int in, int max)
-{
- int out = (in * max + 128) / 255;
-
- return (out < 0) ? 0 : (out < max) ? out : max;
-}
-
-/* ------------------------------------------------------------------------- *
- * vanilla sysfs controls for one channel in RGB led
- * ------------------------------------------------------------------------- */
-
-typedef struct
-{
- const char *max; // R
- const char *val; // W
- const char *on; // W
- const char *off; // W
- const char *blink; // W
- int maxval;// value to use if max path is NULL
-} led_paths_vanilla_t;
-
-typedef struct
-{
- int maxval;
- int fd_val;
- int fd_on;
- int fd_off;
- int fd_blink;
-
- int cur_val;
- int cur_on;
- int cur_off;
- int cur_blink;
-
-} led_state_vanilla_t;
-
-static void
-led_state_vanilla_init(led_state_vanilla_t *self)
-{
- self->fd_on = -1;
- self->fd_off = -1;
- self->fd_val = -1;
- self->fd_blink = -1;
- self->maxval = -1;
-
- self->cur_val = -1;
- self->cur_on = -1;
- self->cur_off = -1;
- self->cur_blink = -1;
-}
-
-static void
-led_state_vanilla_close(led_state_vanilla_t *self)
-{
- led_util_close_file(&self->fd_on);
- led_util_close_file(&self->fd_off);
- led_util_close_file(&self->fd_val);
- led_util_close_file(&self->fd_blink);
-}
-
-static bool
-led_state_vanilla_probe(led_state_vanilla_t *self,
- const led_paths_vanilla_t *path)
-{
- bool res = false;
-
- led_state_vanilla_close(self);
-
- // maximum brightness can be read from file or given in config
- if( path->max )
- {
- self->maxval = led_util_read_number(path->max);
- }
- else
- {
- self->maxval = path->maxval;
- }
-
- if( self->maxval <= 0 )
- {
- goto cleanup;
- }
-
- // we always must have brightness control
- if( !led_util_open_file(&self->fd_val, path->val) )
- {
- goto cleanup;
- }
-
- // on/off period controls are optional, but both
- // are needed if one is present
- if( led_util_open_file(&self->fd_on, path->on) )
- {
- if( !led_util_open_file(&self->fd_off, path->off) )
- {
- led_util_close_file(&self->fd_on);
- }
- }
-
- // having "blink" control file is optional
- led_util_open_file(&self->fd_blink, path->blink);
-
- res = true;
-
-cleanup:
-
- if( !res ) led_state_vanilla_close(self);
-
- return res;
-}
-
-static void
-led_state_vanilla_set_value(led_state_vanilla_t *self,
- int value)
-{
- if( self->fd_val != -1 )
- {
- value = led_util_scale_value(value, self->maxval);
- if( self->cur_val != value )
- {
- self->cur_val = value;
- self->cur_blink = -1;
- dprintf(self->fd_val, "%d", value);
- }
- }
-
- if( self->fd_blink != -1 )
- {
- int blink = (self->cur_on > 0 && self->cur_off > 0);
- if( self->cur_blink != blink )
- {
- self->cur_blink = blink;
- dprintf(self->fd_blink, "%d", blink);
- }
- }
-}
-static void
-led_state_vanilla_set_blink(led_state_vanilla_t *self,
- int on_ms, int off_ms)
-{
- /* Note: Blinking config is taken in use when brightness
- * sysfs is written to -> we need to invalidate
- * cached brightness value if blinking changes
- * are made.
- */
-
- if( self->fd_on != -1 && self->cur_on != on_ms )
- {
- self->cur_on = on_ms;
- self->cur_val = -1;
- self->cur_blink = -1;
- dprintf(self->fd_on, "%d", on_ms);
- }
-
- if( self->fd_off != -1 && self->cur_off != off_ms )
- {
- self->cur_off = off_ms;
- self->cur_val = -1;
- self->cur_blink = -1;
- dprintf(self->fd_off, "%d", off_ms);
- }
-}
-
-/* ------------------------------------------------------------------------- *
- * hammerhead sysfs controls for one channel in RGB led
- * ------------------------------------------------------------------------- */
-
-typedef struct
-{
- const char *max; // R
- const char *val; // W
- const char *on_off; // W
- const char *enable; // W
-} led_paths_hammerhead_t;
-
-typedef struct
-{
- int maxval;
- int fd_val;
- int fd_on_off;
- int fd_enable;
-} led_state_hammerhead_t;
-
-static void
-led_state_hammerhead_init(led_state_hammerhead_t *self)
-{
- self->maxval = -1;
- self->fd_val = -1;
- self->fd_on_off = -1;
- self->fd_enable = -1;
-}
-
-static void
-led_state_hammerhead_close(led_state_hammerhead_t *self)
-{
- led_util_close_file(&self->fd_val);
- led_util_close_file(&self->fd_on_off);
- led_util_close_file(&self->fd_enable);
-}
-
-static bool
-led_state_hammerhead_probe(led_state_hammerhead_t *self,
- const led_paths_hammerhead_t *path)
-{
- bool res = false;
-
- led_state_hammerhead_close(self);
-
- if( (self->maxval = led_util_read_number(path->max)) <= 0 )
- {
- goto cleanup;
- }
-
- if( !led_util_open_file(&self->fd_val, path->val) ||
- !led_util_open_file(&self->fd_on_off, path->on_off) ||
- !led_util_open_file(&self->fd_enable, path->enable) )
- {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
-
- if( !res ) led_state_hammerhead_close(self);
-
- return res;
-}
-
-static void
-led_state_hammerhead_set_enabled(const led_state_hammerhead_t *self,
- bool enable)
-{
- if( self->fd_enable != -1 )
- {
- dprintf(self->fd_enable, "%d", enable);
- }
-}
-
-static void
-led_state_hammerhead_set_value(const led_state_hammerhead_t *self,
- int value)
-{
- if( self->fd_val != -1 )
- {
- dprintf(self->fd_val, "%d", led_util_scale_value(value, self->maxval));
- }
-}
-
-static void
-led_state_hammerhead_set_blink(const led_state_hammerhead_t *self,
- int on_ms, int off_ms)
-{
- if( self->fd_on_off != -1 )
- {
- char tmp[32];
- int len = snprintf(tmp, sizeof tmp, "%d %d", on_ms, off_ms);
- if( len > 0 && len <= (int)sizeof tmp )
- {
- if( write(self->fd_on_off, tmp, len) < 0 ) {
- // dontcare, keep compiler from complaining too
- }
- }
- }
-}
-
-/* ------------------------------------------------------------------------- *
- * htcvision sysfs controls for one channel in amber/green led
- * ------------------------------------------------------------------------- */
-
-typedef struct
-{
- const char *max; // R
- const char *val; // W
- const char *blink; // W
-} led_paths_htcvision_t;
-
-typedef struct
-{
- int maxval;
- int fd_val;
- int fd_blink;
-} led_state_htcvision_t;
-
-static void
-led_state_htcvision_init(led_state_htcvision_t *self)
-{
- self->maxval = -1;
- self->fd_val = -1;
- self->fd_blink = -1;
-}
-
-static void
-led_state_htcvision_close(led_state_htcvision_t *self)
-{
- led_util_close_file(&self->fd_val);
- led_util_close_file(&self->fd_blink);
-}
-
-static bool
-led_state_htcvision_probe(led_state_htcvision_t *self,
- const led_paths_htcvision_t *path)
-{
- bool res = false;
-
- led_state_htcvision_close(self);
-
- if( (self->maxval = led_util_read_number(path->max)) <= 0 )
- {
- goto cleanup;
- }
-
- if( !led_util_open_file(&self->fd_val, path->val) ||
- !led_util_open_file(&self->fd_blink, path->blink) )
- {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
-
- if( !res ) led_state_htcvision_close(self);
-
- return res;
-}
-
-static void
-led_state_htcvision_set_value(const led_state_htcvision_t *self,
- int value)
-{
- if( self->fd_val != -1 )
- {
- dprintf(self->fd_val, "%d", led_util_scale_value(value, self->maxval));
- }
-}
-
-static void
-led_state_htcvision_set_blink(const led_state_htcvision_t *self, int blink)
-{
- if( self->fd_blink != -1 )
- {
- dprintf(self->fd_val, "%d", blink);
- }
-}
-
-/* ------------------------------------------------------------------------- *
- * sysfs controls for binary on/off led
- * ------------------------------------------------------------------------- */
-
-typedef struct
-{
- const char *val; // W
-} led_paths_binary_t;
-
-typedef struct
-{
- int maxval;
- int fd_val;
- int val_last;
-} led_state_binary_t;
-
-static void
-led_state_binary_init(led_state_binary_t *self)
-{
- self->maxval = -1;
- self->fd_val = -1;
- self->val_last = -1;
-}
-
-static void
-led_state_binary_close(led_state_binary_t *self)
-{
- led_util_close_file(&self->fd_val);
-}
-
-static bool
-led_state_binary_probe(led_state_binary_t *self,
- const led_paths_binary_t *path)
-{
- bool res = false;
-
- led_state_binary_close(self);
-
- self->maxval = 1;
-
- if( !led_util_open_file(&self->fd_val, path->val) )
- {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
-
- if( !res ) led_state_binary_close(self);
-
- return res;
-}
-
-static void
-led_state_binary_set_value(led_state_binary_t *self,
- int value)
-{
- if( self->fd_val != -1 )
- {
- int scaled = led_util_scale_value(value, self->maxval);
- if( self->val_last != scaled ) {
- self->val_last = scaled;
- dprintf(self->fd_val, "%d", scaled);
- }
- }
-}
-
-/* ------------------------------------------------------------------------- *
- * RGB led control: generic frontend
- * ------------------------------------------------------------------------- */
-
-typedef enum {
- /** Used when sw breathing is not used */
- LED_RAMP_DISABLED = 0,
-
- /** The default half sine curve */
- LED_RAMP_HALF_SINE = 1,
-
- /** Step function used for emulating blinking via sw breathing */
- LED_RAMP_HARD_STEP = 2,
-} led_ramp_t;
-
-typedef struct led_control_t led_control_t;
-
-struct led_control_t
-{
- const char *name;
- void *data;
- bool can_breathe;
- led_ramp_t breath_type;
- void (*enable)(void *data, bool enable);
- void (*blink)(void *data, int on_ms, int off_ms);
- void (*value)(void *data, int r, int g, int b);
- void (*close)(void *data);
-};
-
-static bool led_control_vanilla_probe(led_control_t *self);
-static bool led_control_hammerhead_probe(led_control_t *self);
-static bool led_control_htcvision_probe(led_control_t *self);
-static bool led_control_binary_probe(led_control_t *self);
-
-/** Set RGB LED enabled/disable
- *
- * @param self control object
- * @param enable true for enable, or false for disable
- */
-static void
-led_control_enable(led_control_t *self, bool enable)
-{
- if( self->enable )
- {
- self->enable(self->data, enable);
- }
-}
-
-/** Set RGB LED blinking period
- *
- * If both on and off are greater than zero, then the PWM generator
- * is used to full intensity blinking. Otherwise it is used for
- * adjusting the LED brightness.
- *
- * @param self control object
- * @param on milliseconds on
- * @param off milliseconds off
- */
-static void
-led_control_blink(led_control_t *self, int on_ms, int off_ms)
-{
- if( self->blink )
- {
- led_control_enable(self, false);
- self->blink(self->data, on_ms, off_ms);
- }
-}
-
-/** Set RGB LED color
- *
- * @param self control object
- * @param r red intensity (0 ... 255)
- * @param g green intensity (0 ... 255)
- * @param b blue intensity (0 ... 255)
- */
-static void
-led_control_value(led_control_t *self, int r, int g, int b)
-{
- if( self->value )
- {
- led_control_enable(self, false);
- self->value(self->data, r, g, b);
- led_control_enable(self, true);
- }
-}
-
-/** Reset RGB led control object
- *
- * Initialize control object to closed but valid state.
- *
- * @param self uninitialized control object
- */
-static void
-led_control_init(led_control_t *self)
-{
- self->name = 0;
- self->data = 0;
- self->enable = 0;
- self->blink = 0;
- self->value = 0;
- self->close = 0;
-
- /* Assume that it is exceptional if sw breathing can't be supported */
- self->can_breathe = true;
- /* And half sine curve should be used for breathing */
- self->breath_type = LED_RAMP_HALF_SINE;
-
-}
-
-/** Set RGB LED enabled/disable
- *
- * @param self control object
- * @param enable true for enable, or false for disable
- */
-
-static void
-led_control_close(led_control_t *self)
-{
- if( self->close )
- {
- self->close(self->data);
- }
- led_control_init(self);
-}
-
-/** Probe sysfs for RGB LED controls
- *
- * @param self control object
- *
- * @return true if required control files were available, false otherwise
- */
-static bool
-led_control_probe(led_control_t *self)
-{
- typedef bool (*led_control_probe_fn)(led_control_t *);
-
- /* The probing should be done in order that minimizes
- * chances of false positives.
- */
- static const led_control_probe_fn lut[] =
- {
- /* The hammerhead backend requires presense of
- * unique 'on_off_ms' and 'rgb_start' files. */
- led_control_hammerhead_probe,
-
- /* The htc vision backend requires presense of
- * unique 'amber' control directory. */
- led_control_htcvision_probe,
-
- /* The vanilla backend requires only 'brightness'
- * control file, but still needs three directories
- * to be present for red, green and blue channels. */
- led_control_vanilla_probe,
-
- /* The binary backend needs just one directory
- * that has 'brightness' control file. */
- led_control_binary_probe,
- };
-
- for( size_t i = 0; i < G_N_ELEMENTS(lut); ++i )
- {
- if( lut[i](self) ) return true;
- }
-
- return false;
-}
-
-/** Query if backend can support sw breathing
- *
- * @return true if breathing can be enabled, false otherwise
- */
-static bool
-led_control_can_breathe(const led_control_t *self)
-{
- return self->can_breathe;
-}
-
-/** Query type of sw breathing backend supports
- *
- * @return LED_RAMP_DISABLED, LED_RAMP_HALF_SINE, or ...
- */
-static led_ramp_t
-led_control_breath_type(const led_control_t *self)
-{
- return self->can_breathe ? self->breath_type : LED_RAMP_DISABLED;
-}
-
-/* ------------------------------------------------------------------------- *
- * RGB led control: default backend
- *
- * Three channels, all of which:
- * - must have 'brightness' control file
- * - must have 'max_brightness' control file or nonzero fixed maximum
- * - can have either
- * o blink on/off delay control files
- * o blink enabled/disable control control file
- *
- * Assumptions built into code:
- *
- * - The write() calls to sysfs controls return immediately from kernel to
- * userspace, but the kernel side can stay busy with the change for few
- * milliseconds -> Frequent intensity changes do not block mce process,
- * so sw breathing is feasible. Minimum delay between led state changes
- * must be enforced.
- *
- * - Blink controls for the R, G and B channels are independent. To avoid
- * "rainbow patterns" when more than one channel is used the blink enabling
- * for all of the channels as simultaneously as possible.
- * ------------------------------------------------------------------------- */
-
-static void
-led_control_vanilla_blink_cb(void *data, int on_ms, int off_ms)
-{
- led_state_vanilla_t *state = data;
- led_state_vanilla_set_blink(state + 0, on_ms, off_ms);
- led_state_vanilla_set_blink(state + 1, on_ms, off_ms);
- led_state_vanilla_set_blink(state + 2, on_ms, off_ms);
-}
-
-static void
-led_control_vanilla_value_cb(void *data, int r, int g, int b)
-{
- led_state_vanilla_t *state = data;
- led_state_vanilla_set_value(state + 0, r);
- led_state_vanilla_set_value(state + 1, g);
- led_state_vanilla_set_value(state + 2, b);
-}
-
-static void
-led_control_vanilla_close_cb(void *data)
-{
- led_state_vanilla_t *state = data;
- led_state_vanilla_close(state + 0);
- led_state_vanilla_close(state + 1);
- led_state_vanilla_close(state + 2);
-}
-
-static bool
-led_control_vanilla_probe(led_control_t *self)
-{
- /** Sysfs control paths for RGB leds */
- static const led_paths_vanilla_t paths[][3] =
- {
- // vanilla
- {
- {
- .on = "/sys/class/leds/led:rgb_red/blink_delay_on",
- .off = "/sys/class/leds/led:rgb_red/blink_delay_off",
- .val = "/sys/class/leds/led:rgb_red/brightness",
- .max = "/sys/class/leds/led:rgb_red/max_brightness",
- },
- {
- .on = "/sys/class/leds/led:rgb_green/blink_delay_on",
- .off = "/sys/class/leds/led:rgb_green/blink_delay_off",
- .val = "/sys/class/leds/led:rgb_green/brightness",
- .max = "/sys/class/leds/led:rgb_green/max_brightness",
- },
- {
- .on = "/sys/class/leds/led:rgb_blue/blink_delay_on",
- .off = "/sys/class/leds/led:rgb_blue/blink_delay_off",
- .val = "/sys/class/leds/led:rgb_blue/brightness",
- .max = "/sys/class/leds/led:rgb_blue/max_brightness",
- }
- },
- // i9300 (galaxy s3 international)
- {
- {
- .on = "/sys/class/leds/led_r/delay_on",
- .off = "/sys/class/leds/led_r/delay_off",
- .val = "/sys/class/leds/led_r/brightness",
- .max = "/sys/class/leds/led_r/max_brightness",
- .blink = "/sys/class/leds/led_r/blink",
- },
- {
- .on = "/sys/class/leds/led_g/delay_on",
- .off = "/sys/class/leds/led_g/delay_off",
- .val = "/sys/class/leds/led_g/brightness",
- .max = "/sys/class/leds/led_g/max_brightness",
- .blink = "/sys/class/leds/led_g/blink",
- },
- {
- .on = "/sys/class/leds/led_b/delay_on",
- .off = "/sys/class/leds/led_b/delay_off",
- .val = "/sys/class/leds/led_b/brightness",
- .max = "/sys/class/leds/led_b/max_brightness",
- .blink = "/sys/class/leds/led_b/blink",
- }
- },
- // yuga (sony xperia z)
- {
- {
- .val = "/sys/class/leds/lm3533-red/brightness",
- .maxval = 255,
- },
- {
- .val = "/sys/class/leds/lm3533-green/brightness",
- .maxval = 255,
- },
- {
- .val = "/sys/class/leds/lm3533-blue/brightness",
- .maxval = 255,
- },
- },
- // onyx (OnePlus X)
- {
- {
- .val = "/sys/class/leds/red/brightness",
- .max = "/sys/class/leds/red/max_brightness",
- .on = "/sys/class/leds/red/pause_hi",
- .off = "/sys/class/leds/red/pause_lo",
- .blink = "/sys/class/leds/red/blink",
- },
- {
- .val = "/sys/class/leds/green/brightness",
- .max = "/sys/class/leds/green/max_brightness",
- .on = "/sys/class/leds/green/pause_hi",
- .off = "/sys/class/leds/green/pause_lo",
- .blink = "/sys/class/leds/green/blink",
- },
- {
- .val = "/sys/class/leds/blue/brightness",
- .max = "/sys/class/leds/blue/max_brightness",
- .on = "/sys/class/leds/blue/pause_hi",
- .off = "/sys/class/leds/blue/pause_lo",
- .blink = "/sys/class/leds/blue/blink",
- },
- },
- };
-
- static led_state_vanilla_t state[3];
-
- bool res = false;
-
- led_state_vanilla_init(state+0);
- led_state_vanilla_init(state+1);
- led_state_vanilla_init(state+2);
-
- self->name = "vanilla";
- self->data = state;
- self->enable = 0;
- self->blink = led_control_vanilla_blink_cb;
- self->value = led_control_vanilla_value_cb;
- self->close = led_control_vanilla_close_cb;
-
- for( size_t i = 0; i < G_N_ELEMENTS(paths) ; ++i )
- {
- if( led_state_vanilla_probe(&state[0], &paths[i][0]) &&
- led_state_vanilla_probe(&state[1], &paths[i][1]) &&
- led_state_vanilla_probe(&state[2], &paths[i][2]) )
- {
- res = true;
- break;
- }
- }
-
- if( !res )
- {
- led_control_close(self);
- }
-
- return res;
-}
-
-/* ------------------------------------------------------------------------- *
- * RGB led control: hammerhead backend
- *
- * Three channels, all of which:
- * - must have 'brightness' control file
- * - must have 'max_brightness' control file
- * - must have 'on_off_ms' blink delay control file
- * - must have 'rgb_start' enable/disable control file
- *
- * Assumptions built into code:
- * - Blinking is always soft, handled by kernel driver / hw.
- * - The sysfs writes will block until change is finished -> Intensity
- * changes are slow. Breathing from userspace can't be used as it
- * would constantly block mce mainloop.
- * ------------------------------------------------------------------------- */
-
-static void
-led_control_hammerhead_enable_cb(void *data, bool enable)
-{
- const led_state_hammerhead_t *state = data;
- led_state_hammerhead_set_enabled(state + 0, enable);
- led_state_hammerhead_set_enabled(state + 1, enable);
- led_state_hammerhead_set_enabled(state + 2, enable);
-}
-
-static void
-led_control_hammerhead_blink_cb(void *data, int on_ms, int off_ms)
-{
- const led_state_hammerhead_t *state = data;
- led_state_hammerhead_set_blink(state + 0, on_ms, off_ms);
- led_state_hammerhead_set_blink(state + 1, on_ms, off_ms);
- led_state_hammerhead_set_blink(state + 2, on_ms, off_ms);
-}
-
-static void
-led_control_hammerhead_value_cb(void *data, int r, int g, int b)
-{
- const led_state_hammerhead_t *state = data;
- led_state_hammerhead_set_value(state + 0, r);
- led_state_hammerhead_set_value(state + 1, g);
- led_state_hammerhead_set_value(state + 2, b);
-}
-
-static void
-led_control_hammerhead_close_cb(void *data)
-{
- led_state_hammerhead_t *state = data;
- led_state_hammerhead_close(state + 0);
- led_state_hammerhead_close(state + 1);
- led_state_hammerhead_close(state + 2);
-}
-
-static bool
-led_control_hammerhead_probe(led_control_t *self)
-{
- /** Sysfs control paths for RGB leds */
- static const led_paths_hammerhead_t paths[][3] =
- {
- // hammerhead (Nexus 5)
- {
- {
- .max = "/sys/class/leds/red/max_brightness",
- .val = "/sys/class/leds/red/brightness",
- .on_off = "/sys/class/leds/red/on_off_ms",
- .enable = "/sys/class/leds/red/rgb_start",
- },
- {
- .max = "/sys/class/leds/green/max_brightness",
- .val = "/sys/class/leds/green/brightness",
- .on_off = "/sys/class/leds/green/on_off_ms",
- .enable = "/sys/class/leds/green/rgb_start",
- },
- {
- .max = "/sys/class/leds/blue/max_brightness",
- .val = "/sys/class/leds/blue/brightness",
- .on_off = "/sys/class/leds/blue/on_off_ms",
- .enable = "/sys/class/leds/blue/rgb_start",
- }
- },
- };
-
- static led_state_hammerhead_t state[3];
-
- bool res = false;
-
- led_state_hammerhead_init(state+0);
- led_state_hammerhead_init(state+1);
- led_state_hammerhead_init(state+2);
-
- self->name = "hammerhead";
- self->data = state;
- self->enable = led_control_hammerhead_enable_cb;
- self->blink = led_control_hammerhead_blink_cb;
- self->value = led_control_hammerhead_value_cb;
- self->close = led_control_hammerhead_close_cb;
-
- /* Changing led parameters is so slow and consumes so much
- * cpu cycles that we just can't have breathing available */
- self->can_breathe = false;
-
- for( size_t i = 0; i < G_N_ELEMENTS(paths) ; ++i )
- {
- if( led_state_hammerhead_probe(&state[0], &paths[i][0]) &&
- led_state_hammerhead_probe(&state[1], &paths[i][1]) &&
- led_state_hammerhead_probe(&state[2], &paths[i][2]) )
- {
- res = true;
- break;
- }
- }
-
- if( !res )
- {
- led_control_close(self);
- }
-
- return res;
-}
-
-/* ------------------------------------------------------------------------- *
- * RGB led control: htcvision backend
- *
- * Two channels (amber and green), both of which:
- * - must have 'brightness' control file
- * - must have 'max_brightness' control file
- * - must have 'blink' enable/disable control file
- *
- * Assumptions built into code:
- * - while there are two channels, kernel and/or hw only allows one of them
- * to be active -> Map rgb form request from mce to amber/green and try
- * to minimize color error.
- * ------------------------------------------------------------------------- */
-
-static void
-led_control_htcvision_map_color(int r, int g, int b,
- int *amber, int *green)
-{
- /* Only "amber" or "green" color can be used.
- *
- * Assume amber = r:ff g:7f b:00
- * green = r:00 g:ff b:00
- *
- * Try to choose the one with smaller delta to the
- * requested rgb color by using the 'r':'g' ratio.
- *
- * The 'b' is used for intensity preservation only.
- */
-
- if( r * 3 < g * 4)
- {
- *amber = 0;
- *green = (g > b) ? g : b;
- }
- else
- {
- *amber = (r > b) ? r : b;
- *green = 0;
- }
-}
-
-static void
-led_control_htcvision_blink_cb(void *data, int on_ms, int off_ms)
-{
- const led_state_htcvision_t *state = data;
-
- int blink = (on_ms && off_ms);
-
- led_state_htcvision_set_blink(state + 0, blink);
- led_state_htcvision_set_blink(state + 1, blink);
-}
-
-static void
-led_control_htcvision_value_cb(void *data, int r, int g, int b)
-{
- const led_state_htcvision_t *state = data;
-
- int amber = 0;
- int green = 0;
- led_control_htcvision_map_color(r, g, b, &amber, &green);
-
- led_state_htcvision_set_value(state + 0, amber);
- led_state_htcvision_set_value(state + 1, green);
-}
-
-static void
-led_control_htcvision_close_cb(void *data)
-{
- led_state_htcvision_t *state = data;
- led_state_htcvision_close(state + 0);
- led_state_htcvision_close(state + 1);
-}
-
-static bool
-led_control_htcvision_probe(led_control_t *self)
-{
- /** Sysfs control paths for Amber/Green leds */
- static const led_paths_htcvision_t paths[][3] =
- {
- // htc vision, htc ace
- {
- {
- .max = "/sys/class/leds/amber/max_brightness",
- .val = "/sys/class/leds/amber/brightness",
- .blink = "/sys/class/leds/amber/blink",
- },
- {
- .max = "/sys/class/leds/green/max_brightness",
- .val = "/sys/class/leds/green/brightness",
- .blink = "/sys/class/leds/green/blink",
- },
- },
- };
-
- static led_state_htcvision_t state[2];
-
- bool res = false;
-
- led_state_htcvision_init(state+0);
- led_state_htcvision_init(state+1);
-
- self->name = "htcvision";
- self->data = state;
- self->enable = 0;
- self->blink = led_control_htcvision_blink_cb;
- self->value = led_control_htcvision_value_cb;
- self->close = led_control_htcvision_close_cb;
-
- /* TODO: check if breathing can be left enabled */
- self->can_breathe = true;
-
- for( size_t i = 0; i < G_N_ELEMENTS(paths) ; ++i )
- {
- if( led_state_htcvision_probe(&state[0], &paths[i][0]) &&
- led_state_htcvision_probe(&state[1], &paths[i][1]) )
- {
- res = true;
- break;
- }
- }
-
- if( !res )
- {
- led_control_close(self);
- }
-
- return res;
-}
-
-/* ------------------------------------------------------------------------- *
- * RGB led control: binary backend
- *
- * One channels, which:
- * - must have 'brightness' control file
- *
- * Assumptions built into code:
- * - Using zero brightness disables led, any non-zero value enables it -> If
- * mce requests "black" rgb value, use brightness of zero - otherwise 255.
- * ------------------------------------------------------------------------- */
-
-static void
-led_control_binary_map_color(int r, int g, int b, int *mono)
-{
- /* Only binary on/off control is available, use
- * 255 as logical level if nonzero rgb value has
- * been requested.
- */
- *mono = (r || g || b) ? 255 : 0;
-}
-
-static void
-led_control_binary_value_cb(void *data, int r, int g, int b)
-{
- led_state_binary_t *state = data;
-
- int mono = 0;
- led_control_binary_map_color(r, g, b, &mono);
- led_state_binary_set_value(state + 0, mono);
-}
-
-static void
-led_control_binary_close_cb(void *data)
-{
- led_state_binary_t *state = data;
- led_state_binary_close(state + 0);
-}
-
-static bool
-led_control_binary_probe(led_control_t *self)
-{
- /** Sysfs control paths for binary leds */
- static const led_paths_binary_t paths[][1] =
- {
- // binary
- {
- {
- .val = "/sys/class/leds/button-backlight/brightness",
- },
- },
- };
-
- static led_state_binary_t state[1];
-
- bool res = false;
-
- led_state_binary_init(state+0);
-
- self->name = "binary";
- self->data = state;
- self->enable = 0;
- self->blink = 0;
- self->value = led_control_binary_value_cb;
- self->close = led_control_binary_close_cb;
-
- /* We can use sw breathing logic to simulate hw blinking */
- self->can_breathe = true;
- self->breath_type = LED_RAMP_HARD_STEP;
-
- for( size_t i = 0; i < G_N_ELEMENTS(paths) ; ++i )
- {
- if( led_state_binary_probe(&state[0], &paths[i][0]) )
- {
- res = true;
- break;
- }
- }
-
- if( !res )
- {
- led_control_close(self);
- }
-
- return res;
-}
-
-/* ------------------------------------------------------------------------- *
- * LED control flow and timing logic underneath hybris API
- * ------------------------------------------------------------------------- */
-
-/** Questimate of the duration of the kernel delayed work */
-#define LED_CTRL_KERNEL_DELAY 10 // [ms]
-
-/** Minimum delay between breathing steps */
-#define LED_CTRL_BREATHING_DELAY 50 // [ms]
-
-/** Maximum number of breathing steps; rise and fall time combined */
-#define LED_CTRL_MAX_STEPS 256
-
-/** Minimum number of breathing steps on rise/fall time */
-#define LED_CTRL_MIN_STEPS 5
-
-/** Led request parameters */
-typedef struct
-{
- int r,g,b; // color
- int on,off; // blink timing
- int level; // brightness [0 ... 255]
- bool breathe; // breathe instead of blinking
-} led_request_t;
-
-/** Test for led request blink/breathing timing equality
- */
-static bool led_request_has_equal_timing(const led_request_t *self,
- const led_request_t *that)
-{
- return (self->on == that->on &&
- self->off == that->off);
-}
-
-/** Test for led request equality
- */
-static bool led_request_is_equal(const led_request_t *self,
- const led_request_t *that)
-{
- return (self->r == that->r &&
- self->g == that->g &&
- self->b == that->b &&
- self->on == that->on &&
- self->off == that->off &&
- self->level == that->level &&
- self->breathe == that->breathe);
-}
-
-/** Test for active led request
- */
-static bool led_request_has_color(const led_request_t *self)
-{
- return self->r > 0 || self->g > 0 || self->b > 0;
-}
-
-/** Normalize/sanity check requested values
- */
-static void led_request_sanitize(led_request_t *self)
-{
- int min_period = LED_CTRL_BREATHING_DELAY * LED_CTRL_MIN_STEPS;
-
- if( !led_request_has_color(self) ) {
- /* blinking/breathing black and black makes no sense */
- self->on = 0;
- self->off = 0;
- self->breathe = false;
- }
- else if( self->on <= 0 || self->off <= 0) {
- /* both on and off periods must be > 0 for blinking/breathing */
- self->on = 0;
- self->off = 0;
- self->breathe = false;
- }
- else if( self->on < min_period || self->off < min_period ) {
- /* Whether a pattern should breathe or not is decided at mce side.
- * But, since there are limitations on how often the led intensity
- * can be changed, we must check that the rise/fall times are long
- * enough to allow a reasonable amount of adjustments to be made. */
- self->breathe = false;
- }
-}
-
-/** Different styles of led patterns */
-typedef enum {
- STYLE_OFF, // led is off
- STYLE_STATIC, // led has constant color
- STYLE_BLINK, // led is blinking with on/off periods
- STYLE_BREATH, // led is breathing with rise/fall times
-} led_style_t;
-
-/** Evaluate request style
- */
-static led_style_t led_request_get_style(const led_request_t *self)
-{
- if( !led_request_has_color(self) ) {
- return STYLE_OFF;
- }
-
- if( self->on <= 0 || self->off <= 0 ) {
- return STYLE_STATIC;
- }
-
- if( self->breathe ) {
- return STYLE_BREATH;
- }
-
- return STYLE_BLINK;
-}
-
-/** Intensity curve for sw breathing */
-static struct {
- size_t step;
- size_t steps;
- int delay;
- uint8_t value[LED_CTRL_MAX_STEPS];
-} led_ctrl_breathe =
-{
- .step = 0,
- .steps = 0,
- .delay = 0,
-};
-
-/** Flag for: controls for RGB leds exist in sysfs */
-static bool led_ctrl_uses_sysfs = false;
-
-/** Currently active RGB led state; initialize to invalid color */
-static led_request_t led_ctrl_curr =
-{
- /* force 1st change to take effect by initializing to invalid color */
- .r = -1,
- .g = -1,
- .b = -1,
-
- /* not blinking or breathing */
- .on = 0,
- .off = 0,
- .breathe = false,
-
- /* full brightness */
- .level = 255,
-};
-
-static led_control_t led_control;
-
-/** Close all LED sysfs files */
-static void led_ctrl_close_sysfs_files(void)
-{
- led_control_close(&led_control);
-}
-
-/** Open sysfs control files for RGB leds
- *
- * @return true if required control files were available, false otherwise
- */
-static bool led_ctrl_probe_sysfs_files(void)
-{
- led_control_init(&led_control);
-
- bool probed = led_control_probe(&led_control);
-
- /* Note: As there are devices that do not have indicator
- * led, a ailures to find a suitable backend must
- * be assumed to be ok and not logged in the default
- * verbosity level.
- */
- mce_log(LOG_NOTICE, "led sysfs backend: %s",
- probed ? led_control.name : "N/A");
-
- return probed;
-}
-
-/** Change blinking attributes of RGB led */
-static void led_ctrl_set_rgb_blink(int on, int off)
-{
- led_control_blink(&led_control, on, off);
-}
-
-/** Change intensity attributes of RGB led */
-static void led_ctrl_set_rgb_value(int r, int g, int b)
-{
- led_control_value(&led_control, r, g, b);
-}
-
-/** Generate half sine intensity curve for use from breathing timer
- */
-static void led_ctrl_generate_ramp_half_sin(int ms_on, int ms_off)
-{
- int t = ms_on + ms_off;
- int s = (t + LED_CTRL_MAX_STEPS - 1) / LED_CTRL_MAX_STEPS;
-
- if( s < LED_CTRL_BREATHING_DELAY ) {
- s = LED_CTRL_BREATHING_DELAY;
- }
- int n = (t + s - 1) / s;
-
- int steps_on = (n * ms_on + t / 2) / t;
- int steps_off = n - steps_on;
-
- const float m_pi_2 = (float)M_PI_2;
-
- int k = 0;
-
- for( int i = 0; i < steps_on; ++i ) {
- float a = i * m_pi_2 / steps_on;
- led_ctrl_breathe.value[k++] = (uint8_t)(sinf(a) * 255.0f);
- }
- for( int i = 0; i < steps_off; ++i ) {
- float a = m_pi_2 + i * m_pi_2 / steps_off;
- led_ctrl_breathe.value[k++] = (uint8_t)(sinf(a) * 255.0f);
- }
-
- led_ctrl_breathe.delay = s;
- led_ctrl_breathe.steps = k;
-
- mce_log(LOG_DEBUG, "delay=%d, steps_on=%d, steps_off=%d",
- led_ctrl_breathe.delay, steps_on, steps_off);
-}
-
-/** Calculate the greatest common divisor of two integer numbers
- */
-static int gcd(int a, int b)
-{
- int t;
- /* Use abs values; will fail if a or b < -INT_MAX */
- if( a < 0 ) a = -a;
- if( b < 0 ) b = -b;
-
- /* Make it so that: a >= b */
- if( a < b ) t = a, a = b, b = t;
-
- /* Iterate until a mod b reaches zero */
- while( b ) t = a % b, a = b, b = t;
-
- /* Do not return zero even on a == b == 0 */
- return a ?: 1;
-}
-
-/** Round up number to the next multiple of given step size
- */
-static int roundup(int val, int range)
-{
- int extra = val % range;
- if( extra ) extra = range - extra;
- return val + extra;
-}
-
-/** Generate hard step intensity curve for use from breathing timer
- */
-static void led_ctrl_generate_ramp_hard_step(int ms_on, int ms_off)
-{
- /* Calculate ramp duration - round up given on/off lengths
- * to avoid totally bizarre values that could cause excessive
- * number of timer wakeups.
- */
- ms_on = roundup(ms_on, 100);
- ms_off = roundup(ms_off, 100);
-
- int ms_tot = ms_on + ms_off;
-
- /* Ideally we would want to wake up only to flip the led
- * on/off. But to keep using the existing ramp timer logic,
- * we wake up in pace of the greatest common divisor for on
- * and off periods.
- */
- int ms_step = gcd(ms_on, ms_off);
-
- if( ms_step < LED_CTRL_BREATHING_DELAY ) {
- ms_step = LED_CTRL_BREATHING_DELAY;
- }
-
- /* Calculate number of steps we need and make sure it does
- * not exceed the defined maximum value.
- */
- int steps_tot = (ms_tot + ms_step - 1) / ms_step;
-
- if( steps_tot > LED_CTRL_MAX_STEPS ) {
- steps_tot = LED_CTRL_MAX_STEPS;
- ms_step = (ms_tot + steps_tot - 1) / steps_tot;
-
- if( ms_step < LED_CTRL_BREATHING_DELAY ) {
- ms_step = LED_CTRL_BREATHING_DELAY;
- }
- }
-
- int steps_on = (ms_on + ms_step - 1 ) / ms_step;
- int steps_off = steps_tot - steps_on;
-
- /* Set intensity value for each step on the ramp.
- */
- int i = 0;
-
- while( i < steps_on ) led_ctrl_breathe.value[i++] = 255;
- while( i < steps_tot ) led_ctrl_breathe.value[i++] = 0;
-
- led_ctrl_breathe.delay = ms_step;
- led_ctrl_breathe.steps = steps_tot;
-
- mce_log(LOG_DEBUG, "delay=%d, steps_on=%d, steps_off=%d",
- led_ctrl_breathe.delay, steps_on, steps_off);
-}
-
-/** Invalidate sw breathing intensity curve
- */
-static void led_ctrl_generate_ramp_dummy(void)
-{
- led_ctrl_breathe.delay = 0;
- led_ctrl_breathe.steps = 0;
-}
-
-/** Generate intensity curve for use from breathing timer
- */
-static void led_ctrl_generate_ramp(int ms_on, int ms_off)
-{
- switch( led_control_breath_type(&led_control) ) {
- case LED_RAMP_HARD_STEP:
- led_ctrl_generate_ramp_hard_step(ms_on, ms_off);
- break;
-
- case LED_RAMP_HALF_SINE:
- led_ctrl_generate_ramp_half_sin(ms_on, ms_off);
- break;
-
- default:
- led_ctrl_generate_ramp_dummy();
- break;
- }
-}
-
-/** Timer id for stopping led */
-static guint led_ctrl_stop_id = 0;
-
-/** Timer id for breathing/setting led */
-static guint led_ctrl_step_id = 0;
-
-/** Timer callback for setting led
- */
-static gboolean led_ctrl_static_cb(gpointer aptr)
-{
- (void) aptr;
-
- if( !led_ctrl_step_id ) {
- goto cleanup;
- }
-
- led_ctrl_step_id = 0;
-
- // get configured color
- int r = led_ctrl_curr.r;
- int g = led_ctrl_curr.g;
- int b = led_ctrl_curr.b;
-
- // adjust by brightness level
- int l = led_ctrl_curr.level;
-
- r = led_util_scale_value(r, l);
- g = led_util_scale_value(g, l);
- b = led_util_scale_value(b, l);
-
- // set led blinking and color
- led_ctrl_set_rgb_blink(led_ctrl_curr.on, led_ctrl_curr.off);
- led_ctrl_set_rgb_value(r, g, b);
-
-cleanup:
- return FALSE;
-}
-
-/** Timer callback for taking a led breathing step
- */
-static gboolean led_ctrl_step_cb(gpointer aptr)
-{
- (void)aptr;
-
- if( !led_ctrl_step_id ) {
- goto cleanup;
- }
-
- if( led_ctrl_breathe.step >= led_ctrl_breathe.steps ) {
- led_ctrl_breathe.step = 0;
- }
-
- // get configured color
- int r = led_ctrl_curr.r;
- int g = led_ctrl_curr.g;
- int b = led_ctrl_curr.b;
-
- // adjust by brightness level
- int l = led_ctrl_curr.level;
-
- r = led_util_scale_value(r, l);
- g = led_util_scale_value(g, l);
- b = led_util_scale_value(b, l);
-
- // adjust by curve position
- size_t i = led_ctrl_breathe.step++;
- int v = led_ctrl_breathe.value[i];
-
- r = led_util_scale_value(r, v);
- g = led_util_scale_value(g, v);
- b = led_util_scale_value(b, v);
-
- // set led color
- led_ctrl_set_rgb_value(r, g, b);
-
-cleanup:
- return led_ctrl_step_id != 0;
-}
-
-static bool reset_blinking = true;
-
-/** Timer callback from stopping/restarting led
- */
-static gboolean led_ctrl_stop_cb(gpointer aptr)
-{
- (void) aptr;
-
- if( !led_ctrl_stop_id ) {
- goto cleanup;
- }
- led_ctrl_stop_id = 0;
-
- if( reset_blinking ) {
- // blinking off - must be followed by rgb set to have an effect
- led_ctrl_set_rgb_blink(0, 0);
- }
-
- if( !led_request_has_color(&led_ctrl_curr) ) {
- // set rgb to black before returning
- reset_blinking = true;
- }
- else {
- if( led_ctrl_breathe.delay > 0 ) {
- // start breathing timer
- led_ctrl_step_id = g_timeout_add(led_ctrl_breathe.delay,
- led_ctrl_step_cb, 0);
- }
- else {
- // set rgb to target after timer delay
- led_ctrl_step_id = g_timeout_add(LED_CTRL_KERNEL_DELAY,
- led_ctrl_static_cb, 0);
- }
- }
-
- if( reset_blinking ) {
- // set rgb to black
- led_ctrl_set_rgb_value(0, 0, 0);
- reset_blinking = false;
- }
-
-cleanup:
-
- return FALSE;
-}
-
-/** Start static/blinking/breathing led
- */
-static void
-led_ctrl_start(const led_request_t *next)
-{
- led_request_t work = *next;
-
- led_request_sanitize(&work);
-
- if( led_request_is_equal(&led_ctrl_curr, &work) ) {
- goto cleanup;
- }
-
- /* Assumption: Before changing the led state, we need to wait a bit
- * for kernel side to finish with last change we made and then possibly
- * reset the blinking status and wait a bit more */
- bool restart = true;
-
- led_style_t old_style = led_request_get_style(&led_ctrl_curr);
- led_style_t new_style = led_request_get_style(&work);
-
- /* Exception: When we are already breathing and continue to
- * breathe, the blinking is not in use and the breathing timer
- * is keeping the updates far enough from each other */
- if( old_style == STYLE_BREATH && new_style == STYLE_BREATH &&
- led_request_has_equal_timing(&led_ctrl_curr, &work) ) {
- restart = false;
- }
-
- /* If only the als-based brightness level changes, we need to
- * adjust the breathing amplitude without affecting the phase.
- * Otherwise assume that the pattern has been changed and the
- * breathing step counter needs to be reset. */
- led_ctrl_curr.level = work.level;
- if( !led_request_is_equal(&led_ctrl_curr, &work) ) {
- led_ctrl_breathe.step = 0;
- }
-
- led_ctrl_curr = work;
-
- if( restart ) {
- // stop existing breathing timer
- if( led_ctrl_step_id ) {
- g_source_remove(led_ctrl_step_id), led_ctrl_step_id = 0;
- }
-
- // re-evaluate breathing constants
- led_ctrl_breathe.delay = 0;
- if( new_style == STYLE_BREATH ) {
- led_ctrl_generate_ramp(work.on, work.off);
- }
-
- /* Schedule led off after kernel settle timeout; once that
- * is done, new led color/blink/breathing will be started */
- if( !led_ctrl_stop_id ) {
- reset_blinking = (old_style == STYLE_BLINK ||
- new_style == STYLE_BLINK);
- led_ctrl_stop_id = g_timeout_add(LED_CTRL_KERNEL_DELAY,
- led_ctrl_stop_cb, 0);
- }
- }
-
-cleanup:
-
- return;
-}
-
-/** Nanosleep helper
- */
-static void led_ctrl_wait_kernel(void)
-{
- struct timespec ts = { 0, LED_CTRL_KERNEL_DELAY * 1000000l };
- TEMP_FAILURE_RETRY(nanosleep(&ts, &ts));
-}
-
-/* ------------------------------------------------------------------------- *
- * hybris led API
- * ------------------------------------------------------------------------- */
-
-/** Initialize libhybris indicator led device object
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_indicator_init(void)
-{
- static bool done = false;
- static bool ack = false;
-
- if( done ) {
- goto cleanup;
- }
-
- done = true;
-
- led_ctrl_uses_sysfs = led_ctrl_probe_sysfs_files();
-
- if( led_ctrl_uses_sysfs ) {
- /* Use raw sysfs controls */
-
- /* adjust current state to: color=black */
- led_request_t req = led_ctrl_curr;
- req.r = 0;
- req.g = 0;
- req.b = 0;
- led_ctrl_start(&req);
- }
- else {
- /* Fall back to libhybris */
-
- if( !mce_hybris_modlights_load() ) {
- goto cleanup;
- }
-
- mce_light_device_open(mod_lights, LIGHT_ID_NOTIFICATIONS, &dev_indicator);
-
- if( !dev_indicator ) {
- mce_log(LOG_WARNING, "failed to open indicator led device");
- goto cleanup;
- }
- }
-
- ack = true;
-
-cleanup:
-
- mce_log(LOG_DEBUG, "res = %s", ack ? "true" : "false");
-
- return ack;
-}
-
-/** Release libhybris indicator led device object
- */
-void mce_hybris_indicator_quit(void)
-{
- /* Release libhybris controls */
-
- if( dev_indicator ) {
- mce_light_device_close(dev_indicator), dev_indicator = 0;
- }
-
- /* Release sysfs controls */
-
- if( led_ctrl_uses_sysfs ) {
- // cancel timers
- if( led_ctrl_step_id ) {
- g_source_remove(led_ctrl_step_id), led_ctrl_step_id = 0;
- }
- if( led_ctrl_stop_id ) {
- g_source_remove(led_ctrl_stop_id), led_ctrl_stop_id = 0;
- }
-
- // allow kernel side to settle down
- led_ctrl_wait_kernel();
-
- // blink off
- led_ctrl_set_rgb_blink(0, 0);
-
- // zero brightness
- led_ctrl_set_rgb_value(0, 0, 0);
-
- // close sysfs files
- led_ctrl_close_sysfs_files();
- }
-}
-
-/** Clamp integer values to given range
- *
- * @param lo minimum value allowed
- * @param hi maximum value allowed
- * @param val value to clamp
- *
- * @return val clamped to [lo, hi]
- */
-static inline int clamp_to_range(int lo, int hi, int val)
-{
- return val <= lo ? lo : val <= hi ? val : hi;
-}
-
-/** Set indicator led pattern via libhybris
- *
- * @param r red intensity 0 ... 255
- * @param g green intensity 0 ... 255
- * @param b blue intensity 0 ... 255
- * @param ms_on milliseconds to keep the led on, or 0 for no flashing
- * @param ms_on milliseconds to keep the led off, or 0 for no flashing
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_indicator_set_pattern(int r, int g, int b,
- int ms_on, int ms_off)
-{
- bool ack = false;
-
- /* Sanitize input values */
-
- /* Clamp time periods to [0, 60] second range.
- *
- * While periods longer than few seconds might not count as "blinking",
- * we need to leave some slack to allow beacon style patterns with
- * relatively long off periods */
- ms_on = clamp_to_range(0, 60000, ms_on);
- ms_off = clamp_to_range(0, 60000, ms_off);
-
- /* Both on and off periods need to be non-zero for the blinking
- * to happen in the first place. And if the periods are too
- * short it starts to look like led failure more than indication
- * of something. */
- if( ms_on < 50 || ms_off < 50 ) {
- ms_on = ms_off = 0;
- }
-
- /* Clamp rgb values to [0, 255] range */
- r = clamp_to_range(0, 255, r);
- g = clamp_to_range(0, 255, g);
- b = clamp_to_range(0, 255, b);
-
- /* Use raw sysfs controls if possible */
-
- if( led_ctrl_uses_sysfs ) {
-
- /* adjust current state to: color & timing as requested */
- led_request_t req = led_ctrl_curr;
- req.r = r;
- req.g = g;
- req.b = b;
- req.on = ms_on;
- req.off = ms_off;
- led_ctrl_start(&req);
-
- ack = true;
- goto cleanup;
- }
-
- /* Fall back to libhybris API */
-
- struct light_state_t lst;
-
- if( !mce_hybris_indicator_init() ) {
- goto cleanup;
- }
-
- memset(&lst, 0, sizeof lst);
-
- lst.color = (0xff << 24) | (r << 16) | (g << 8) | (b << 0);
- lst.brightnessMode = BRIGHTNESS_MODE_USER;
-
- if( ms_on > 0 && ms_off > 0 ) {
- lst.flashMode = LIGHT_FLASH_HARDWARE;
- lst.flashOnMS = ms_on;
- lst.flashOffMS = ms_off;
- }
- else {
- lst.flashMode = LIGHT_FLASH_NONE;
- lst.flashOnMS = 0;
- lst.flashOffMS = 0;
- }
-
- if( dev_indicator->set_light(dev_indicator, &lst) < 0 ) {
- goto cleanup;
- }
-
- ack = true;
-
-cleanup:
-
- mce_log(LOG_DEBUG, "%s(%d,%d,%d,%d,%d) -> %s", __FUNCTION__,
- r,g,b, ms_on, ms_off , ack ? "success" : "failure");
-
- return ack;
-}
-
-/** Query if currently active led backend can support breathing
- *
- * @return true if breathing can be requested, false otherwise
- */
-bool
-mce_hybris_indicator_can_breathe(void)
-{
- bool ack = false;
-
- /* Note: We can't know how access via hybris behaves, so err
- * on the safe side and assume that breathing is not ok
- * unless we have direct sysfs controls.
- */
-
- if( led_ctrl_uses_sysfs )
- {
- ack = led_control_can_breathe(&led_control);
- }
-
- /* The result does not change during runtime of mce, so
- * log only once */
-
- static bool logged = false;
-
- if( !logged )
- {
- logged = true;
- mce_log(LOG_DEBUG, "res = %s", ack ? "true" : "false");
- }
-
- return ack;
-}
-
-/** Enable/disable sw breathing
- *
- * @param enable true to enable sw breathing, false to disable
- */
-void mce_hybris_indicator_enable_breathing(bool enable)
-{
- mce_log(LOG_DEBUG, "enable = %s", enable ? "true" : "false");
-
- if( !mce_hybris_indicator_can_breathe() ) {
- if( enable ) {
- static bool once = false;
- if( !once ) {
- once = true;
- mce_log(LOG_ERR, "sw breathing was requested even"
- " though it can't be supported");
- }
- }
- goto cleanup;
- }
-
- /* adjust current state to: breathing as requested */
- led_request_t work = led_ctrl_curr;
- work.breathe = enable;
- led_ctrl_start(&work);
-
-cleanup:
- return;
-}
-
-/** Set indicator led brightness
- *
- * @param level 1=minimum, 255=maximum
- *
- * @return true on success, or false on failure
- */
-bool mce_hybris_indicator_set_brightness(int level)
-{
- mce_log(LOG_DEBUG, "level = %d", level);
-
- if( !led_ctrl_uses_sysfs ) {
- // no breathing control via hybris api
- goto cleanup;
- }
-
- /* Clamp brightness values to [1, 255] range */
- level = clamp_to_range(1, 255, level);
-
- /* adjust current state to: brightness as requested */
- led_request_t work = led_ctrl_curr;
- work.level = level;
- led_ctrl_start(&work);
-
-cleanup:
- /* Note: failure means this function is not available - which is
- * handled at mce side stub. From this plugin we always return true */
- return true;
-}
-
-/* ========================================================================= *
- * SENSORS module
- * ========================================================================= */
-
-/** Convenience function for opening sensors device
- *
- * Similar to what we might or might not have available from hardware/sensors.h
- */
-static int
-mce_sensors_open(const struct hw_module_t* module,
- struct sensors_poll_device_t** device)
-{
- return module->methods->open(module, SENSORS_HARDWARE_POLL,
- (struct hw_device_t**)device);
-}
-
-/** Convenience function for closing sensors device
- *
- * Similar to what we might or might not have available from hardware/sensors.h
- */
-static int
-mce_sensors_close(struct sensors_poll_device_t* device)
-{
- return device->common.close(&device->common);
-}
-
-/** Handle for libhybris sensors plugin */
-static struct sensors_module_t *mod_sensors = 0;
-
-/** Pointer to libhybris sensor poll device object */
-static struct sensors_poll_device_t *dev_poll = 0;
-
-/** Array of sensors available via mod_sensors */
-static const struct sensor_t *sensor_lut = 0;
-
-/** Number of sensors available via mod_sensors */
-static int sensor_cnt = 0;
-
-/** Pointer to libhybris proximity sensor object */
-static const struct sensor_t *ps_sensor = 0;
-
-/** Callback for forwarding proximity sensor events */
-static mce_hybris_ps_fn ps_hook = 0;
-
-/** Pointer to libhybris ambient light sensor object */
-static const struct sensor_t *als_sensor = 0;
-
-/** Callback for forwarding ambient light sensor events */
-static mce_hybris_als_fn als_hook = 0;
-
-/** Helper for locating sensor objects by type
- *
- * @param type SENSOR_TYPE_LIGHT etc
- *
- * @return sensor pointer, or NULL if not available
- */
-static const struct sensor_t *mce_hybris_modsensors_get_sensor(int type)
-{
- const struct sensor_t *res = 0;
-
- for( int i = 0; i < sensor_cnt; ++i ) {
-
- if( sensor_lut[i].type == type ) {
- res = &sensor_lut[i];
- break;
- }
- }
-
- return res;
-}
-
-/** Load libhybris sensors plugin
- *
- * Also initializes look up table for supported sensors.
- *
- * @return true on success, false on failure
- */
-static bool mce_hybris_modsensors_load(void)
-{
- static bool done = false;
-
- if( done ) goto cleanup;
-
- done = true;
-
- {
- const struct hw_module_t *mod = 0;
- hw_get_module(SENSORS_HARDWARE_MODULE_ID, &mod);
- mod_sensors = (struct sensors_module_t *)mod;
- }
-
- if( !mod_sensors ) {
- mce_log(LOG_WARNING, "failed top open sensors module");
- }
- else {
- mce_log(LOG_DEBUG, "mod_sensors = %p", mod_sensors);
- }
-
- if( !mod_sensors ) {
- goto cleanup;
- }
-
- sensor_cnt = mod_sensors->get_sensors_list(mod_sensors, &sensor_lut);
-
- als_sensor = mce_hybris_modsensors_get_sensor(SENSOR_TYPE_LIGHT);
- ps_sensor = mce_hybris_modsensors_get_sensor(SENSOR_TYPE_PROXIMITY);
-
-cleanup:
-
- return mod_sensors != 0;
-}
-
-/** Unload libhybris sensors plugin
- */
-static void mce_hybris_modsensors_unload(void)
-{
- /* cleanup dependencies */
- mce_hybris_sensors_quit();
-
- /* actually unload the module */
- // FIXME: how to unload libhybris modules?
-}
-
-/* ------------------------------------------------------------------------- *
- * poll device
- * ------------------------------------------------------------------------- */
-
-/** Worker thread id */
-static pthread_t poll_tid = 0;
-
-/** Worker thread for reading sensor events via blocking libhybris interface
- *
- * Note: no mce_log() calls from this function - they are not thread safe
- *
- * @param aptr (thread parameter, not used)
- */
-static void mce_hybris_sensors_thread(void *aptr)
-{
- (void)aptr;
-
- sensors_event_t eve[32];
-
- while( dev_poll ) {
- /* This blocks until there are events available, or possibly sooner
- * if enabling/disabling sensors changes something. Since we can't
- * guarantee that we ever return from the call, the thread is cancelled
- * asynchronously on cleanup - and any resources possibly reserved by
- * the dev_poll->poll() are lost. */
- int n = dev_poll->poll(dev_poll, eve, G_N_ELEMENTS(eve));
-
- for( int i = 0; i < n; ++i ) {
- sensors_event_t *e = &eve[i];
-
- /* Forward data via per sensor callback routines. The callbacks must
- * handle the fact that they get called from the context of the worker
- * thread. */
- switch( e->type ) {
- case SENSOR_TYPE_LIGHT:
- if( als_hook ) {
- als_hook(e->timestamp, e->distance);
- }
- break;
- case SENSOR_TYPE_PROXIMITY:
- if( ps_hook ) {
- ps_hook(e->timestamp, e->light);
- }
- break;
-
- case SENSOR_TYPE_ACCELEROMETER:
- case SENSOR_TYPE_MAGNETIC_FIELD:
- case SENSOR_TYPE_ORIENTATION:
- case SENSOR_TYPE_GYROSCOPE:
- case SENSOR_TYPE_PRESSURE:
- case SENSOR_TYPE_TEMPERATURE:
- case SENSOR_TYPE_GRAVITY:
- case SENSOR_TYPE_LINEAR_ACCELERATION:
- case SENSOR_TYPE_ROTATION_VECTOR:
- case SENSOR_TYPE_RELATIVE_HUMIDITY:
- case SENSOR_TYPE_AMBIENT_TEMPERATURE:
- break;
- }
- }
- }
-}
-
-/** Initialize libhybris sensor poll device object
- *
- * Also:
- * - disables ALS and PS sensor inputs if possible
- * - starts worker thread to handle sensor input events
- *
- * @return true on success, false on failure
- */
-static bool mce_hybris_sensors_init(void)
-{
- static bool done = false;
-
- if( !done ) {
- done = true;
-
- if( !mce_hybris_modsensors_load() ) {
- goto cleanup;
- }
-
- mce_sensors_open(&mod_sensors->common, &dev_poll);
-
- if( !dev_poll ) {
- mce_log(LOG_WARNING, "failed to open sensor poll device");
- }
- else {
- mce_log(LOG_DEBUG, "dev_poll = %p", dev_poll);
-
- if( ps_sensor ) {
- dev_poll->activate(dev_poll, ps_sensor->handle, false);
- }
- if( als_sensor ) {
- dev_poll->activate(dev_poll, als_sensor->handle, false);
- }
-
- poll_tid = mce_hybris_start_thread(mce_hybris_sensors_thread, 0);
- }
- }
-
-cleanup:
- return dev_poll != 0;
-}
-
-/** Release libhybris display backlight device object
- *
- * Also:
- * - stops the sensor input worker thread
- * - disables ALS and PS sensor inputs if possible
- */
-static void mce_hybris_sensors_quit(void)
-{
-
- if( dev_poll ) {
- /* Looks like there is no nice way to get the thread to return from
- * dev_poll->poll(), so we need to just cancel the thread ... */
- if( poll_tid != 0 ) {
- mce_log(LOG_DEBUG, "stopping worker thread");
- if( pthread_cancel(poll_tid) != 0 ) {
- mce_log(LOG_ERR, "failed to stop worker thread");
- }
- else {
- void *status = 0;
- pthread_join(poll_tid, &status);
- mce_log(LOG_DEBUG, "worker stopped, status = %p", status);
- }
- poll_tid = 0;
- }
-
- if( ps_sensor ) {
- dev_poll->activate(dev_poll, ps_sensor->handle, false);
- }
- if( als_sensor ) {
- dev_poll->activate(dev_poll, als_sensor->handle, false);
- }
-
- mce_sensors_close(dev_poll), dev_poll = 0;
- }
-}
-
-/* ------------------------------------------------------------------------- *
- * proximity sensor
- * ------------------------------------------------------------------------- */
-
-/** Start using proximity sensor via libhybris
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_ps_init(void)
-{
- bool res = false;
-
- if( !mce_hybris_sensors_init() ) {
- goto cleanup;
- }
-
- if( !ps_sensor ) {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
- return res;
-}
-
-/** Stop using proximity sensor via libhybris
- *
- * @return true on success, false on failure
- */
-void mce_hybris_ps_quit(void)
-{
- ps_hook = 0;
-}
-
-/** Set proximity sensort input enabled state
- *
- * @param state true to enable input, or false to disable input
- */
-bool mce_hybris_ps_set_active(bool state)
-{
- bool res = false;
-
- if( !mce_hybris_ps_init() ) {
- goto cleanup;
- }
-
- if( dev_poll->activate(dev_poll, ps_sensor->handle, state) < 0 ) {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
- return res;
-}
-
-/** Set callback function for handling proximity sensor events
- *
- * Note: the callback function will be called from worker thread.
- */
-void mce_hybris_ps_set_hook(mce_hybris_ps_fn cb)
-{
- ps_hook = cb;
-}
-
-/* ------------------------------------------------------------------------- *
- * ambient light sensor
- * ------------------------------------------------------------------------- */
-
-/** Start using ambient light sensor via libhybris
- *
- * @return true on success, false on failure
- */
-bool mce_hybris_als_init(void)
-{
- bool res = false;
-
- if( !mce_hybris_sensors_init() ) {
- goto cleanup;
- }
-
- if( !als_sensor ) {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
- return res;
-}
-
-/** Stop using ambient light sensor via libhybris
- *
- * @return true on success, false on failure
- */
-void mce_hybris_als_quit(void)
-{
- als_hook = 0;
-}
-
-/** Set ambient light sensor input enabled state
- *
- * @param state true to enable input, or false to disable input
- */
-bool mce_hybris_als_set_active(bool state)
-{
- bool res = false;
-
- if( !mce_hybris_als_init() ) {
- goto cleanup;
- }
-
- if( dev_poll->activate(dev_poll, als_sensor->handle, state) < 0 ) {
- goto cleanup;
- }
-
- res = true;
-
-cleanup:
- return res;
-}
-
-/** Set callback function for handling ambient light sensor events
- *
- * Note: the callback function will be called from worker thread.
- */
-void mce_hybris_als_set_hook(mce_hybris_als_fn cb)
-{
- als_hook = cb;
-}
-
-/* ------------------------------------------------------------------------- *
- * common
- * ------------------------------------------------------------------------- */
-
-/** Release all resources allocated by this module */
-void mce_hybris_quit(void)
-{
- mce_hybris_modfb_unload();
- mce_hybris_modlights_unload();
- mce_hybris_modsensors_unload();
-}
|
[-]
[+]
|
Deleted |
_service:tar_git:mce-plugin-libhybris-1.7.1.tar.bz2/mce-hybris.h
^
|
@@ -1,110 +0,0 @@
-/* ------------------------------------------------------------------------- *
- * Copyright (C) 2013 Jolla Ltd.
- * Contact: Simo Piiroinen <simo.piiroinen@jollamobile.com>
- * License: LGPLv2.1
- * ------------------------------------------------------------------------- */
-
-/* FIXME: This header is included in sourcetrees of both mce and
- * mce-plugin-libhybris. For now it must be kept in sync
- * manually.
- */
-
-#ifndef MCE_HYBRIS_H_
-# define MCE_HYBRIS_H_
-
-# ifndef MCE_HYBRIS_INTERNAL
-# define MCE_HYBRIS_INTERNAL 0
-# endif
-
-# include <stdbool.h>
-# include <stdint.h>
-
-# ifdef __cplusplus
-extern "C" {
-# elif 0
-} /* fool JED indentation ... */
-# endif
-
-/* - - - - - - - - - - - - - - - - - - - *
- * frame buffer power state
- * - - - - - - - - - - - - - - - - - - - */
-
-bool mce_hybris_framebuffer_init(void);
-void mce_hybris_framebuffer_quit(void);
-bool mce_hybris_framebuffer_set_power(bool on);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * display backlight brightness
- * - - - - - - - - - - - - - - - - - - - */
-
-bool mce_hybris_backlight_init(void);
-void mce_hybris_backlight_quit(void);
-bool mce_hybris_backlight_set_brightness(int level);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * keypad backlight brightness
- * - - - - - - - - - - - - - - - - - - - */
-
-bool mce_hybris_keypad_set_brightness(int level);
-void mce_hybris_keypad_quit(void);
-bool mce_hybris_keypad_init(void);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * indicator led pattern
- * - - - - - - - - - - - - - - - - - - - */
-
-bool mce_hybris_indicator_init(void);
-void mce_hybris_indicator_quit(void);
-bool mce_hybris_indicator_set_pattern(int r, int g, int b, int ms_on, int ms_off);
-void mce_hybris_indicator_enable_breathing(bool enable);
-bool mce_hybris_indicator_set_brightness(int level);
-bool mce_hybris_indicator_can_breathe(void);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * proximity sensor
- * - - - - - - - - - - - - - - - - - - - */
-
-typedef void (*mce_hybris_ps_fn)(int64_t timestamp, float distance);
-
-bool mce_hybris_ps_init(void);
-void mce_hybris_ps_quit(void);
-bool mce_hybris_ps_set_active(bool active);
-bool mce_hybris_ps_set_callback(mce_hybris_ps_fn cb);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * ambient light sensor
- * - - - - - - - - - - - - - - - - - - - */
-
-typedef void (*mce_hybris_als_fn)(int64_t timestamp, float light);
-
-bool mce_hybris_als_init(void);
-void mce_hybris_als_quit(void);
-bool mce_hybris_als_set_active(bool active);
-bool mce_hybris_als_set_callback(mce_hybris_als_fn cb);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * generic
- * - - - - - - - - - - - - - - - - - - - */
-
-void mce_hybris_quit(void);
-
-/* - - - - - - - - - - - - - - - - - - - *
- * internal to module <--> plugin
- * - - - - - - - - - - - - - - - - - - - */
-
-# if MCE_HYBRIS_INTERNAL >= 1
-typedef void (*mce_hybris_log_fn)(int lev, const char *file, const char *func,
- const char *text);
-# endif
-
-# if MCE_HYBRIS_INTERNAL >= 2
-void mce_hybris_set_log_hook(mce_hybris_log_fn cb);
-void mce_hybris_ps_set_hook(mce_hybris_ps_fn cb);
-void mce_hybris_als_set_hook(mce_hybris_als_fn cb);
-# endif
-
-# ifdef __cplusplus
-};
-# endif
-
-#endif /* MCE_HYBRIS_H_ */
|