.PHONY: all clean install
+bindir=/usr/bin
pluginlibdir=`pkg-config hildon-control-panel --variable pluginlibdir`
plugindesktopentrydir=`pkg-config hildon-control-panel --variable plugindesktopentrydir`
HILDON_CFLAGS = `pkg-config --cflags hildon-1`
OSSO_CFLAGS = `pkg-config --cflags libosso`
+GLIB_CFLAGS = `pkg-config --cflags glib-2.0 gobject-2.0`
HILDON_LIBS = `pkg-config --libs hildon-1`
OSSO_LIBS = `pkg-config --libs libosso`
+GLIB_LIBS = `pkg-config --libs glib-2.0 gobject-2.0`
pluginlib_LTLIBRARY = \
libled-pattern-editor.so
plugindesktopentry_DATA = \
data/led-pattern-editor.desktop
-all: ${pluginlib_LTLIBRARY}
+bin_PROGRAM = \
+ led-pattern-helper
+
+all: ${pluginlib_LTLIBRARY} ${bin_PROGRAM}
led_pattern_editor_SOURCES = $(patsubst %.vala,%.c,${led_pattern_editor_VALASOURCES})
src/led-pattern-editor.c: ${led_pattern_editor_VALASOURCES}
valac -C ${led_pattern_editor_VALAFLAGS} -o $@ $^
+led_pattern_helper_SOURCES = \
+ src/led-pattern-helper.c
+
+led_pattern_helper_VALASOURCES = \
+ src/led-pattern-helper.vala
+
+${bin_PROGRAM}: ${led_pattern_helper_SOURCES}
+ gcc ${GLIB_CFLAGS} -o $@ $^ ${GLIB_LIBS}
+
+src/led-pattern-helper.c: ${led_pattern_helper_VALASOURCES}
+ valac -C -o $@ $^
+
clean:
- rm ${pluginlib_LTLIBRARY} src/*.c
+ rm ${pluginlib_LTLIBRARY} ${bin_PROGRAM} src/*.c
install:
install -d ${DESTDIR}${pluginlibdir}
install libled-pattern-editor.so ${DESTDIR}${pluginlibdir}/libled-pattern-editor.so
install -d ${DESTDIR}${plugindesktopentrydir}
install ${plugindesktopentry_DATA} ${DESTDIR}${plugindesktopentrydir}/`basename ${plugindesktopentry_DATA}`
+ install -d ${DESTDIR}${bindir}
+ install led-pattern-helper ${DESTDIR}${bindir}/led-pattern-helper
--- /dev/null
+/* This file is part of LED Pattern Editor.
+ *
+ * Copyright (C) 2010 Philipp Zabel
+ *
+ * LED Pattern Editor is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LED Pattern Editor is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LED Pattern Editor. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+public bool test_pattern (string pattern, bool apply) {
+ string[] key_value = pattern.split ("=");
+
+ if (key_value.length != 2) {
+ stderr.printf ("pattern does not contain '=': %s\n", pattern);
+ return false;
+ }
+
+ string[] p = key_value[1].split (";");
+ if (p.length != 6) {
+ stderr.printf ("pattern does not contain 6 components: %d\n", p.length);
+ return false;
+ }
+
+ if (p[0].has_prefix ("Pattern")) {
+ stderr.printf ("pattern name doesn't start with 'Pattern': '%s'\n", p[0]);
+ return false;
+ }
+
+ // priority = p[0].to_int ();
+ // screen_on = p[1].to_int ();
+ // timeout = p[2].to_int ();
+
+ int[] led_currents = { 2, 2, 2 };
+ string led_map1 = "000";
+ switch (p[3]) {
+ case "r":
+ led_map1 = "001";
+ led_currents = { 8, 0, 2 };
+ break;
+ case "g":
+ led_map1 = "010";
+ led_currents = { 2, 2, 2 };
+ break;
+ case "b":
+ led_map1 = "100";
+ led_currents = { 2, 2, 2 };
+ break;
+ case "rg":
+ led_map1 = "011";
+ led_currents = { 20, 2, 0 };
+ break;
+ case "rb":
+ led_map1 = "101";
+ // TODO: led_currents?
+ break;
+ case "gb":
+ led_map1 = "110";
+ // TODO: led_currents?
+ break;
+ case "rgb":
+ led_map1 = "111";
+ led_currents = { 8, 2, 2 };
+ break;
+ default:
+ stderr.printf ("only single-engine patterns supported for now\n");
+ return false;
+ }
+
+ if (p[4].length > 16*4 || p[5].length > 16*4) {
+ stderr.printf ("pattern too long!\n");
+ return false;
+ }
+
+ if (!(p[4].has_prefix ("9d80"))) {
+ stderr.printf ("engine1 pattern doesn't start with reset mux command\n");
+ return false;
+ }
+
+ if (!(p[4].has_suffix ("0000")) && !(p[4].has_suffix ("c000"))) {
+ stderr.printf ("engine1 pattern doesn't end with repeat or stop command\n");
+ return false;
+ }
+
+ if (p[5] != "9d800000") {
+ // FIXME
+ stderr.printf ("only single-engine patterns supported for now\n");
+ return false;
+ }
+
+ if (apply == false)
+ return true;
+
+ string i2c_dev = "/sys/bus/i2c/devices/2-0032";
+
+ var f = FileStream.open ("/sys/class/leds/lp5523:r/led_current", "w");
+ if (f == null) {
+ stderr.printf ("failed to set red led current\n");
+ return false;
+ }
+ f.printf ("%d\n", led_currents[0]);
+
+ f = FileStream.open ("/sys/class/leds/lp5523:g/led_current", "w");
+ if (f == null) {
+ stderr.printf ("failed to set green led current\n");
+ return false;
+ }
+ f.printf ("%d\n", led_currents[1]);
+
+ f = FileStream.open ("/sys/class/leds/lp5523:b/led_current", "w");
+ if (f == null) {
+ stderr.printf ("failed to set blue led current\n");
+ return false;
+ }
+ f.printf ("%d\n", led_currents[2]);
+
+ f = FileStream.open (Path.build_filename (i2c_dev, "engine1_mode"), "w");
+ if (f == null) {
+ stderr.printf ("failed to set engine1 to load mode\n");
+ return false;
+ }
+ f.printf ("load\n");
+
+ int retries = 100;
+ for (int i = 0; i < retries; i++) {
+ f = FileStream.open (Path.build_filename (i2c_dev, "engine1_leds"), "w");
+ if (f != null)
+ break;
+ }
+ if (f == null) {
+ stderr.printf ("failed to set engine1 mux\n");
+ return false;
+ }
+ f.printf ("0000%s00\n", led_map1);
+
+ f = FileStream.open (Path.build_filename (i2c_dev, "engine1_load"), "w");
+ if (f == null) {
+ stderr.printf ("failed to load engine1 pattern\n");
+ return false;
+ }
+ f.printf ("%s\n", p[4]);
+
+ f = FileStream.open (Path.build_filename (i2c_dev, "engine1_mode"), "w");
+ if (f == null) {
+ stderr.printf ("failed to set engine1 to run mode\n");
+ return false;
+ }
+ f.printf ("run\n");
+
+ return true;
+}
+
+bool mce_ini_check (string new_mce_ini) {
+ var f = FileStream.open ("/etc/mce/mce.ini", "r");
+ var g = FileStream.open (new_mce_ini, "r");
+
+ if (f == null || g == null) {
+ stderr.printf ("failed to open /etc/mce/mce.ini and %s\n", new_mce_ini);
+ return false;
+ }
+
+ var line1 = f.read_line ();
+ var line2 = g.read_line ();
+ while (line1 != null && line2 != null) {
+ if (line1 == line2) {
+ line1 = f.read_line ();
+ line2 = g.read_line ();
+ continue;
+ }
+
+ string[] key_value1 = line1.split ("=");
+ string[] key_value2 = line2.split ("=");
+
+ if (key_value1.length != 2 || key_value2.length != 2 || !line1.has_prefix ("Pattern")) {
+ stderr.printf ("not allowed to change anything but led patterns:\n-%s\n+%s\n",
+ line1, line2);
+ return false;
+ }
+
+ if (key_value1[0] != key_value2[0]) {
+ stderr.printf ("not allowed to change pattern names\n-%s\n+%s\n",
+ line1, line2);
+ return false;
+ }
+
+ if (!test_pattern (line2, false))
+ return false;
+
+ line1 = f.read_line ();
+ line2 = g.read_line ();
+ }
+
+ if (line1 != line2) {
+ stderr.printf ("different number of lines\n");
+ return false;
+ }
+
+ return true;
+}
+
+int mce_copy (string source, string destination) {
+ var f = FileStream.open (source, "r");
+ var g = FileStream.open (destination, "w");
+
+ if (f == null || g == null) {
+ return 1;
+ }
+
+ var line = f.read_line ();
+ while (line != null) {
+ g.printf ("%s\n", line);
+ line = f.read_line ();
+ }
+
+ return 0;
+}
+
+public static int main (string[] args) {
+ string usage = "usage: led-pattern-helper test <Pattern>\n";
+
+ if (args.length != 3) {
+ stderr.printf (usage);
+ return -1;
+ }
+
+ if (args[1] == "test") {
+ if (!test_pattern (args[2], true))
+ return -1;
+
+ return 0;
+ }
+
+ if (args[1] == "save") {
+ if (!FileUtils.test (args[2], FileTest.IS_REGULAR)) {
+ stderr.printf ("not a regular file: %s\n", args[2]);
+ return -1;
+ }
+
+ if (!mce_ini_check (args[2]))
+ return -1;
+
+ // Ok, we're good to go
+ int result = mce_copy ("/etc/mce/mce.ini", "/etc/mce/mce.ini.led-pattern-old");
+ if (result != 0) {
+ stderr.printf ("failed to copy old mce.ini to mce.ini.led-pattern-old\n");
+ return -1;
+ }
+ result = mce_copy (args[2], "/etc/mce/mce.ini.led-pattern-new");
+ if (result != 0) {
+ stderr.printf ("failed to copy new mce.ini to mce.ini.led-pattern-new\n");
+ return -1;
+ }
+ result = FileUtils.rename ("/etc/mce/mce.ini.led-pattern-new", "/etc/mce/mce.ini");
+ if (result != 0) {
+ stderr.printf ("failed to replace MCE configuration: %d\n", result);
+ return -1;
+ }
+
+ // Moment of truth, restart MCE
+ try {
+ int exit_status;
+ string error;
+ var command = "initctl stop mce";
+ Process.spawn_command_line_sync (command, null, out error, out exit_status);
+ if (exit_status != 0) {
+ stderr.printf ("stopping mce failed: %d\n%s", exit_status, error);
+ return -1;
+ }
+ command = "sleep 1";
+ Process.spawn_command_line_sync (command, null, out error, out exit_status);
+ command = "initctl start mce";
+ Process.spawn_command_line_sync (command, null, out error, out exit_status);
+ if (exit_status != 0) {
+ stderr.printf ("starting mce failed: %d\n%s", exit_status, error);
+ return -1;
+ }
+ } catch (SpawnError e) {
+ stderr.printf ("restarting mce failed: %s", e.message);
+ return -1;
+ }
+
+ return 0;
+ }
+
+ stderr.printf (usage);
+ return -1;
+}