OSDN Git Service

add tablet-mode fake lid switch which read the actual tablet/laptop mode switch from...
authorStefan Seidel <android@stefanseidel.info>
Sat, 25 Feb 2012 22:06:18 +0000 (23:06 +0100)
committerStefan Seidel <android@stefanseidel.info>
Sat, 25 Feb 2012 22:06:18 +0000 (23:06 +0100)
excluded-input-devices.xml
init.thinkpad_x41t.rc
overlays/frameworks/base/core/res/res/values/config.xml
tablet-mode/Android.mk [new file with mode: 0644]
tablet-mode/MODULE_LICENSE_GPL [new file with mode: 0644]
tablet-mode/Makefile [new file with mode: 0644]
tablet-mode/tablet-mode.c [new file with mode: 0644]
x41t.mk

index b1180de..0f7cef9 100644 (file)
@@ -19,4 +19,5 @@
 <devices>
     <device name="Power Button" />
     <device name="Lid Switch" />
+    <device name="ThinkPad Extra Buttons" />
 </devices>
index c3b0991..97d2565 100755 (executable)
@@ -8,15 +8,16 @@ on boot
     setkeycode 0x68 127
     setkeycode 0x6c 172
     setkeycode 0x67 116
-    
+
     setprop system_init.startsurfaceflinger 0
 
 service wacom-input /system/bin/wacom-input
+    class late_start
     disabled
 
-#service amixer-master /system/bin/alsa_amixer set Master 100 on
-#    oneshot
-#    disabled
+service tablet-mode /system/bin/tablet-mode
+    class late_start
+    disabled
 
 service amixer-pcm /system/bin/alsa_amixer set PCM 100 on
     oneshot
@@ -24,7 +25,7 @@ service amixer-pcm /system/bin/alsa_amixer set PCM 100 on
 
 on property:dev.bootcomplete=1
     start wacom-input
-    start amixer-master
+    start tablet-mode
     start amixer-pcm
 
     chmod 660 /sys/class/rfkill/rfkill0/state
index a426f06..9a3bd96 100644 (file)
@@ -2,4 +2,15 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <bool name="config_reverseDefaultRotation">true</bool>
     <integer name="config_lidOpenRotation">0</integer>
-</resources>
\ No newline at end of file
+    <!-- Indicate whether the lid state impacts the accessibility of
+         the physical keyboard.  0 means it doesn't, 1 means it is accessible
+         when the lid is open, 2 means it is accessible when the lid is
+         closed.  The default is 1. -->
+    <integer name="config_lidKeyboardAccessibility">1</integer>
+
+    <!-- Indicate whether the lid state impacts the accessibility of
+         the physical keyboard.  0 means it doesn't, 1 means it is accessible
+         when the lid is open, 2 means it is accessible when the lid is
+         closed.  The default is 0. -->
+    <integer name="config_lidNavigationAccessibility">1</integer>
+</resources>
diff --git a/tablet-mode/Android.mk b/tablet-mode/Android.mk
new file mode 100644 (file)
index 0000000..e2dc636
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2012 The Android-x86 Open Source Project
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= tablet-mode.c
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_CFLAGS := -O2 -Wall
+
+ifeq ($(TARGET_ARCH),x86)
+LOCAL_CFLAGS += -Ulinux
+endif
+
+LOCAL_MODULE := tablet-mode
+LOCAL_MODULE_TAGS := optional
+#LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+
+include $(BUILD_EXECUTABLE)
diff --git a/tablet-mode/MODULE_LICENSE_GPL b/tablet-mode/MODULE_LICENSE_GPL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tablet-mode/Makefile b/tablet-mode/Makefile
new file mode 100644 (file)
index 0000000..f59362b
--- /dev/null
@@ -0,0 +1,16 @@
+CC=gcc
+CFLAGS=-c -Wall -O2
+SOURCES=tablet-mode.c
+OBJECTS=$(SOURCES:.c=.o)
+EXECUTABLE=tablet-mode
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+       $(CC) $(LDFLAGS) $(OBJECTS) -o $@
+
+.c.o:
+       $(CC) $(CFLAGS) $< -o $@
+
+clean:
+       rm $(OBJECTS) $(EXECUTABLE)
diff --git a/tablet-mode/tablet-mode.c b/tablet-mode/tablet-mode.c
new file mode 100644 (file)
index 0000000..592343f
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * Convert SW_TABLET_MODE events to SW_LID events for Android
+ *
+ * Copyright 2012 The Android-x86 Open Source Project
+ *
+ * Author: Stefan Seidel <android@stefanseidel.info>
+ *
+ * Licensed under GPLv2 or later
+ *
+ **/
+
+#define LOG_TAG "tablet-mode"
+
+#include <sys/stat.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <cutils/log.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+
+/* we must use this kernel-compatible implementation */
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x)  ((x)%BITS_PER_LONG)
+#define BIT(x)  (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
+
+int openfd(void)
+{
+       int fd;
+       const char *dirname = "/dev/input";
+       DIR *dir;
+       if ((dir = opendir(dirname))) {
+               struct dirent *de;
+               while ((de = readdir(dir))) {
+                       if (de->d_name[0] != 'e') // eventX
+                               continue;
+                       char name[PATH_MAX];
+                       snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
+                       fd = open(name, O_RDONLY);
+                       if (fd < 0) {
+                               LOGE("could not open %s, %s", name, strerror(errno));
+                               continue;
+                       }
+                       name[sizeof(name) - 1] = '\0';
+                       if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+                               LOGE("could not get device name for %s, %s\n", name, strerror(errno));
+                               name[0] = '\0';
+                       }
+                       if (!strcmp(name, "ThinkPad Extra Buttons")) {
+                               LOGI("open %s(%s) ok", de->d_name, name);
+                               return fd;
+                       }
+                       close(fd);
+               }
+               closedir(dir);
+       }
+       return -1;
+}
+
+void send_switch(int ufd, int state) {
+       struct input_event nev;
+       LOGI("Tablet Mode Switch to %d\n", state);
+       memset(&nev, 0, sizeof(struct input_event));
+       nev.type = EV_SW;
+       nev.code = SW_LID;
+       nev.value = state;
+       write(ufd, &nev, sizeof(struct input_event));
+       nev.type = EV_SYN;
+       nev.code = SYN_REPORT;
+       nev.value = 0;
+       write(ufd, &nev, sizeof(struct input_event));
+}
+
+int main(void)
+{
+       int ifd = openfd();
+       if (ifd < 0) {
+               LOGE("could not find ThinkPad Extra Buttons, exiting.");
+               return -1;
+       }
+
+       sleep(15); //wait some time or otherwise EventHub might not pick up our event!?
+
+       int ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);
+       if (ufd >= 0) {
+               struct uinput_user_dev ud;
+               memset(&ud, 0, sizeof(struct uinput_user_dev));
+               strcpy(ud.name, "Android Tablet Lid Switch");
+               write(ufd, &ud, sizeof(struct uinput_user_dev));
+               ioctl(ufd, UI_SET_EVBIT, EV_SW);
+               ioctl(ufd, UI_SET_SWBIT, SW_LID);
+               ioctl(ufd, UI_DEV_CREATE, 0);
+       } else {
+               LOGE("could not open uinput device: %s", strerror(errno));
+               return -1;
+       }
+
+       // send initial switch state
+       unsigned long sw_state[NBITS(SW_MAX+1)];
+       memset(sw_state, 0, sizeof(sw_state));
+       if (ioctl(ifd, EVIOCGSW(sizeof(sw_state)), sw_state) >= 0) {
+               send_switch(ufd, test_bit(SW_TABLET_MODE, sw_state) ? 0 : 1);
+       }
+
+       // read events and pass them on modified
+       while (1) {
+               struct input_event iev;
+               size_t res = read(ifd, &iev, sizeof(struct input_event));
+               if (res < sizeof(struct input_event)) {
+                       LOGW("insufficient input data(%d)? fd=%d", res, ifd);
+                       continue;
+               }
+//             LOGV("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, fd);
+               if (iev.type == EV_SW && iev.code == SW_TABLET_MODE) {
+                       send_switch(ufd, !iev.value);
+               }
+       }
+
+       return 0;
+}
diff --git a/x41t.mk b/x41t.mk
index a44172e..45738ac 100644 (file)
--- a/x41t.mk
+++ b/x41t.mk
@@ -2,6 +2,7 @@ PRODUCT_PACKAGES := $(THIRD_PARTY_APPS)
 PRODUCT_PACKAGES += lights.default
 PRODUCT_PACKAGES += sensors.$(TARGET_PRODUCT)
 PRODUCT_PACKAGES += wacom-input
+PRODUCT_PACKAGES += tablet-mode
 PRODUCT_PACKAGES += su Superuser FileManager libchromium_net alsa_amixer radiooptions rild libreference-ril
 
 $(call inherit-product,$(SRC_TARGET_DIR)/product/generic_x86.mk)