From ca8393c352368485bcb8b277004fdb0c6cb572c6 Mon Sep 17 00:00:00 2001
From: tzh <tanzhtanzh@gmail.com>
Date: Fri, 23 Aug 2024 05:40:03 +0000
Subject: [PATCH] feat(ir): add allwinner ir func and hal

---
 android/device/softwinner/ceres-common/BoardConfigCommon.mk                            |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4cb3.kl         |   53 
 android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.cpp        |  164 +++
 android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/service.te                   |    1 
 android/frameworks/base/api/current.txt                                                |    1 
 android/vendor/aw/homlet/HomletBoardConfig.mk                                          |    9 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01_petrel.kl  |   33 
 android/vendor/aw/homlet/hardware/input/multi_ir/IRConfig.mk                           |    6 
 longan/device/config/chips/a133/configs/c3/board.dts                                   |   23 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_dd22.kl         |   47 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.cpp                      |  752 +++++++++++++
 android/vendor/aw/homlet/hardware/input/multi_ir/jni/Android.mk                        |   34 
 android/device/softwinner/ceres-common/ceres-common.mk                                 |    2 
 android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/private/service_contexts     |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_2992.kl         |   36 
 android/vendor/aw/homlet/hardware/input/multi_ir/jni/com_softwinner_multiir.cpp        |  173 +++
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_rc5_ir_04.kl       |    7 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/multi_ir.rc                      |    6 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_9f00.kl         |   48 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir.kl                 |  244 ++++
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01.kl         |   33 
 android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/file_contexts                |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/multiir.mk                            |   51 
 android/vendor/aw/homlet/hardware/input/multi_ir/Android.mk                            |   18 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4040.kl         |   25 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fc00.kl         |   12 
 android/frameworks/base/core/java/android/view/KeyEvent.java                           |    4 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.cpp                |  460 ++++++++
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-recovery.kl        |   19 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-uinput.kl          |  244 ++++
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ff00.kl         |   35 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/Vendor_000d_Product_3838.kl |   11 
 android/frameworks/base/core/res/res/values/attrs.xml                                  |    1 
 android/frameworks/native/include/android/keycodes.h                                   |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.h                        |   54 +
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fb04.kl         |   48 
 android/vendor/aw/homlet/homlet.mk                                                     |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/system_server.te             |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_bc00.kl         |   34 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/uevent_utils.cpp                 |  155 ++
 android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.h                  |   52 
 android/frameworks/base/api/test-current.txt                                           |    2 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ba04.kl         |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/Android.bp                 |   25 
 android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/multi_ir.te                  |   24 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_7f80.kl         |   37 
 android/frameworks/native/include/input/InputEventLabels.h                             |    1 
 android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.h          |   33 
 android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/virtual-remote.kl           |   26 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/Android.bp                       |   46 
 android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.cpp               |   69 +
 android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.h                 |   31 
 52 files changed, 3,189 insertions(+), 7 deletions(-)

diff --git a/android/device/softwinner/ceres-common/BoardConfigCommon.mk b/android/device/softwinner/ceres-common/BoardConfigCommon.mk
old mode 100644
new mode 100755
index f4da071..ee08155
--- a/android/device/softwinner/ceres-common/BoardConfigCommon.mk
+++ b/android/device/softwinner/ceres-common/BoardConfigCommon.mk
@@ -1,4 +1,5 @@
 include device/softwinner/common/BoardConfigCommon.mk
+include vendor/aw/homlet/HomletBoardConfig.mk
 
 TARGET_PLATFORM := tablet
 TARGET_BOARD_PLATFORM := ceres
diff --git a/android/device/softwinner/ceres-common/ceres-common.mk b/android/device/softwinner/ceres-common/ceres-common.mk
old mode 100644
new mode 100755
index 81082ab..9cb206d
--- a/android/device/softwinner/ceres-common/ceres-common.mk
+++ b/android/device/softwinner/ceres-common/ceres-common.mk
@@ -1,6 +1,8 @@
 # inherit common.mk
 $(call inherit-product-if-exists, device/softwinner/common/common.mk)
 
+$(call inherit-product-if-exists, vendor/aw/homlet/homlet.mk)
+
 PRODUCT_CPU_TYPE ?= A100
 
 DEVICE_PACKAGE_OVERLAYS := \
diff --git a/android/frameworks/base/api/current.txt b/android/frameworks/base/api/current.txt
index 9ce0a5c..b6856db 100644
--- a/android/frameworks/base/api/current.txt
+++ b/android/frameworks/base/api/current.txt
@@ -49070,6 +49070,7 @@
     field public static final int KEYCODE_ALT_RIGHT = 58; // 0x3a
     field public static final int KEYCODE_APOSTROPHE = 75; // 0x4b
     field public static final int KEYCODE_APP_SWITCH = 187; // 0xbb
+    field public static final int KEYCODE_APP_VIDEO = 289; // 0x121
     field public static final int KEYCODE_ASSIST = 219; // 0xdb
     field public static final int KEYCODE_AT = 77; // 0x4d
     field public static final int KEYCODE_AVR_INPUT = 182; // 0xb6
diff --git a/android/frameworks/base/api/test-current.txt b/android/frameworks/base/api/test-current.txt
old mode 100644
new mode 100755
index 6f0b6a8..ff5dd89
--- a/android/frameworks/base/api/test-current.txt
+++ b/android/frameworks/base/api/test-current.txt
@@ -3231,7 +3231,7 @@
   public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public static String actionToString(int);
     method public final void setDisplayId(int);
-    field public static final int LAST_KEYCODE = 288; // 0x120
+    field public static final int LAST_KEYCODE = 289; // 0x121
   }
 
   public final class KeyboardShortcutGroup implements android.os.Parcelable {
diff --git a/android/frameworks/base/core/java/android/view/KeyEvent.java b/android/frameworks/base/core/java/android/view/KeyEvent.java
old mode 100644
new mode 100755
index 8f53150..b1eaa53
--- a/android/frameworks/base/core/java/android/view/KeyEvent.java
+++ b/android/frameworks/base/core/java/android/view/KeyEvent.java
@@ -825,6 +825,8 @@
      */
     public static final int KEYCODE_PROFILE_SWITCH = 288;
 
+    public static final int KEYCODE_APP_VIDEO = 289;
+
     /* add for other platform,  Reserved for them */
     /**
      * @hide
@@ -897,7 +899,7 @@
      * @hide
      */
     @TestApi
-    public static final int LAST_KEYCODE = KEYCODE_PROFILE_SWITCH;
+    public static final int LAST_KEYCODE = KEYCODE_APP_VIDEO;
 
     private static boolean isHomlet;
 
diff --git a/android/frameworks/base/core/res/res/values/attrs.xml b/android/frameworks/base/core/res/res/values/attrs.xml
old mode 100644
new mode 100755
index 5dc430b..84ccdb4
--- a/android/frameworks/base/core/res/res/values/attrs.xml
+++ b/android/frameworks/base/core/res/res/values/attrs.xml
@@ -1924,6 +1924,7 @@
         <enum name="KEYCODE_THUMBS_UP" value="286" />
         <enum name="KEYCODE_THUMBS_DOWN" value="287" />
         <enum name="KEYCODE_PROFILE_SWITCH" value="288" />
+        <enum name="KEYCODE_APP_VIDEO" value="289" />
         <enum name="KEYCODE_TV_SYSTEM" value="10000" />
         <enum name="KEYCODE_GOTO" value="10001" />
         <enum name="KEYCODE_SUBTITLE" value="10002" />
diff --git a/android/frameworks/native/include/android/keycodes.h b/android/frameworks/native/include/android/keycodes.h
old mode 100644
new mode 100755
index 2233af1..0223229
--- a/android/frameworks/native/include/android/keycodes.h
+++ b/android/frameworks/native/include/android/keycodes.h
@@ -777,6 +777,7 @@
     /** Used to switch current account that is consuming content.
      * May be consumed by system to switch current viewer profile. */
     AKEYCODE_PROFILE_SWITCH = 288,
+    AKEYCODE_APP_VIDEO = 289,
     /* add some new keys for TVD */
     AKEYCODE_TV_SYSTEM       = 10000,
     AKEYCODE_GOTO            = 10001,
diff --git a/android/frameworks/native/include/input/InputEventLabels.h b/android/frameworks/native/include/input/InputEventLabels.h
old mode 100644
new mode 100755
index f0a9e61..fb3c75e
--- a/android/frameworks/native/include/input/InputEventLabels.h
+++ b/android/frameworks/native/include/input/InputEventLabels.h
@@ -328,6 +328,7 @@
     DEFINE_KEYCODE(THUMBS_UP),
     DEFINE_KEYCODE(THUMBS_DOWN),
     DEFINE_KEYCODE(PROFILE_SWITCH),
+    DEFINE_KEYCODE(APP_VIDEO),
     DEFINE_KEYCODE(TV_SYSTEM),
     DEFINE_KEYCODE(GOTO),
     DEFINE_KEYCODE(SUBTITLE),
diff --git a/android/vendor/aw/homlet/HomletBoardConfig.mk b/android/vendor/aw/homlet/HomletBoardConfig.mk
new file mode 100755
index 0000000..8e4b44c
--- /dev/null
+++ b/android/vendor/aw/homlet/HomletBoardConfig.mk
@@ -0,0 +1,9 @@
+include vendor/aw/homlet/hardware/input/multi_ir/IRConfig.mk
+
+# homlet common sepolicy
+#BOARD_SEPOLICY_DIRS += \
+#    vendor/aw/homlet/sepolicy
+
+# homlet private sepolicy
+#BOARD_PLAT_PRIVATE_SEPOLICY_DIR += \
+#    vendor/aw/homlet/sepolicy/private
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/Android.mk b/android/vendor/aw/homlet/hardware/input/multi_ir/Android.mk
new file mode 100755
index 0000000..75df1ec
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/Android.mk
@@ -0,0 +1,18 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/IRConfig.mk b/android/vendor/aw/homlet/hardware/input/multi_ir/IRConfig.mk
new file mode 100755
index 0000000..0189f20
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/IRConfig.mk
@@ -0,0 +1,6 @@
+
+BOARD_SEPOLICY_DIRS += \
+	vendor/aw/homlet/hardware/input/multi_ir/sepolicy
+
+BOARD_PLAT_PRIVATE_SEPOLICY_DIR += \
+	vendor/aw/homlet/hardware/input/multi_ir/sepolicy/private
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/Android.bp b/android/vendor/aw/homlet/hardware/input/multi_ir/core/Android.bp
new file mode 100755
index 0000000..f233661
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/Android.bp
@@ -0,0 +1,46 @@
+cc_binary {
+    name: "multi_ir",
+    recovery_available: true,
+    srcs: [
+        "multiir.cpp",
+        "virtual_input.cpp",
+        "uevent_utils.cpp",
+        "MultiirService.cpp",
+    ],
+
+    init_rc: ["multi_ir.rc"],
+
+    shared_libs: [
+        "libcutils",
+ //       "libc",
+        "liblog",
+        "libutils",
+        "libbinder",
+        "libandroid_runtime",
+        "libmultiirservice",
+    ],
+
+    include_dirs: [
+        "system/core/libutils/include",
+    ],
+
+    cflags: [
+        "-DLOG_TAG=\"multiir\"",
+        "-DCEC_ONE_TOUCH_PLAY",
+        "-llog",
+    ],
+
+    target: {
+        recovery: {
+            exclude_shared_libs: [
+                "libbinder",
+                "libandroid_runtime",
+                "libmultiirservice",
+            ],
+
+            exclude_srcs: ["MultiirService.cpp"],
+            cflags: ["-DBUILD_TARGET_RECOVERY"],
+        },
+
+    }
+}
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.cpp b/android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.cpp
new file mode 100755
index 0000000..ee17c32
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.cpp
@@ -0,0 +1,69 @@
+#ifndef BUILD_TARGET_RECOVERY
+#undef NDEBUG
+
+#include "MultiirService.h"
+#include "virtual_input.h"
+#include "multiir.h"
+#include <binder/IServiceManager.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+
+#define DEBUG true
+
+namespace android {
+
+void MultiirService::instantiate() {
+    defaultServiceManager()->addService(
+        String16("softwinner.multi_ir"), new MultiirService());
+}
+
+MultiirService::MultiirService() {
+    ALOGD("MultiirService create");
+}
+
+MultiirService::~MultiirService() {
+    ALOGD("MultiirService destoryed");
+}
+
+int MultiirService::enterMouseMode(void) {
+    if (DEBUG) ALOGD("MultiirService enterMouseMode");
+    int ret = create_virtual_mouse_dev("VirtualMouse");
+    return ret;
+}
+
+int MultiirService::exitMouseMode(void) {
+    if (DEBUG) ALOGD("MultiirService exitMouseMode");
+    int ret = destory_virtual_mouse_dev();
+    return ret;
+}
+
+int MultiirService::getDefaultPointerSpeed(void) {
+    return get_default_pointerspeed();
+}
+
+int MultiirService::getDefaultStepDistance(void) {
+    return get_default_stepdistance();
+}
+
+int MultiirService::setPointerSpeed(int mx) {
+    set_pointerspeed(mx);
+    return 1;
+}
+
+int MultiirService::setStepDistance(int px) {
+    set_stepdistance(px);
+    return 1;
+}
+
+int MultiirService::reset(void) {
+    reset();
+    return 1;
+}
+
+int MultiirService::reportMouseKeyEvent(int scan_code, int key_state) {
+	return report_mouse_keyevent(scan_code, key_state);
+}
+}
+
+#endif
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.h b/android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.h
new file mode 100755
index 0000000..8a04a86
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/MultiirService.h
@@ -0,0 +1,31 @@
+#ifndef ANDROID_MULTIIRSERVICE_H
+#define ANDROID_MULTIIRSERVICE_H
+#ifndef BUILD_TARGET_RECOVERY
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include "IMultiirService.h"
+
+namespace android {
+
+class MultiirService : public BnMultiirService {
+public:
+    static void instantiate();
+    virtual int enterMouseMode(void);
+    virtual int exitMouseMode(void);
+    virtual int getDefaultPointerSpeed(void);
+    virtual int getDefaultStepDistance(void);
+    virtual int setPointerSpeed(int ms);
+    virtual int setStepDistance(int px);
+    virtual int reset(void);
+    virtual int reportMouseKeyEvent(int scan_code, int key_state);
+
+private:
+    MultiirService();
+    virtual ~MultiirService();
+};
+
+};
+#endif
+
+#endif
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/multi_ir.rc b/android/vendor/aw/homlet/hardware/input/multi_ir/core/multi_ir.rc
new file mode 100755
index 0000000..09904cb
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/multi_ir.rc
@@ -0,0 +1,6 @@
+service multi_ir /system/bin/multi_ir
+        class main
+        user root
+        group system input uhid
+        seclabel u:r:multi_ir:s0
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.cpp b/android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.cpp
new file mode 100755
index 0000000..da50f02
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.cpp
@@ -0,0 +1,752 @@
+/*
+ * multi ir daemon for android -
+ * Copyright (C) 2015-2018 AllwinnerTech
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/inotify.h>
+#include <sys/types.h>
+#include <utils/Log.h>
+#include <sys/poll.h>
+#include <linux/input.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <pthread.h>
+#include <thread>
+
+#include "cutils/properties.h"
+#ifndef BUILD_TARGET_RECOVERY
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include "MultiirService.h"
+#endif
+#include "virtual_input.h"
+#include "multiir.h"
+
+
+#ifdef HDMI_CEC_STANDBY_SUPPORT
+extern int uevent_init(int *ufds);
+extern int uevent_process_event(void);
+#endif
+
+#define multi_debug(fmt, arg...)                \
+do {                                            \
+    if (mult_flags & PRINT_DEBUG)               \
+        fprintf(stdout, "[D] " fmt"\n", ##arg); \
+} while(0)
+
+enum {
+    PRINT_ERROR  = 1U << 0,
+    PRINT_WARN   = 1U << 1,
+    PRINT_DEBUG  = 1U << 2,
+};
+
+static int mult_flags = 0x0;
+
+extern int g_mousefd;
+int event_mode = 0;
+
+pthread_mutex_t mutex;
+struct itimerval timer_value;
+//#define DEBUG
+
+extern int nfds;
+#define MOUSE_CODE  (0xE8)
+#define DPAD_UP     19
+#define DPAD_DOWN   20
+#define DPAD_LEFT   21
+#define DPAD_RIGHT  22
+#define DPAD_CENTER 23
+
+#define KEY_LAYOUT_PATH         "/system/usr/keylayout"
+#define DEFAULT_KEYLAYOUT_FILE  "sunxi-ir.kl"
+#define IR_KEYPRESS_TIMEOUT      (500000)
+#define IR_REPEAT_PERIOD         (80)
+#define DEFAULT_POINTER_SPEED    IR_REPEAT_PERIOD
+#define POINTER_SPEED_MAX        (100)
+#define POINTER_SPEED_MIN        (10)
+#define DEFAULT_STEP_DISTANCE    20
+
+static int pointer_speed = DEFAULT_POINTER_SPEED;
+static int mDistance = DEFAULT_STEP_DISTANCE;
+
+int get_default_pointerspeed(void)
+{
+    return POINTER_SPEED_MAX - DEFAULT_POINTER_SPEED;
+}
+
+int get_default_stepdistance(void)
+{
+    return DEFAULT_STEP_DISTANCE;
+}
+
+void set_pointerspeed(int ms)
+{
+    // real speed = POINTER_SPEED_MAX - ms
+    // userspace set speed, value more smaller speed more faster
+    if (ms < POINTER_SPEED_MIN)
+        pointer_speed = POINTER_SPEED_MAX;
+    else if (ms > POINTER_SPEED_MAX)
+        pointer_speed = POINTER_SPEED_MIN;
+    else
+        pointer_speed = POINTER_SPEED_MAX - ms + POINTER_SPEED_MIN;
+}
+
+void set_stepdistance(int px)
+{
+    if (px < 5)
+        mDistance = 5;
+    else if (px > 50)
+        mDistance = 50;
+    else
+        mDistance = px;
+}
+
+void reset(void)
+{
+    set_pointerspeed(DEFAULT_POINTER_SPEED);
+    set_stepdistance(DEFAULT_STEP_DISTANCE);
+}
+
+/*
+ * A valid customer ir key layout file *MUST* namd by 'customer_ir_xxxx.kl',
+ * which 'xxxx' is the identity(ir address code, in hex),
+ * eg. customer_ir_9f00.kl
+*/
+#define FILENAME_PREFIX         "customer_ir_"
+#define FILENAME_PREFIX_RC5     "customer_rc5_ir_"
+#define FILENAME_EXTENSION      ".kl"
+
+#define IR_PROTOCOL_USED        "/proc/sunxi_ir_protocol"
+#define NEC (0)
+#define RC5 (1)
+static unsigned int  ir_protocol_used ;
+
+
+struct keymap_t {
+    int keycode;
+    char name[MAX_NAME_LEN];
+};
+
+struct key_dev_t {
+    int uinputfd;
+    struct input_event *event;
+    int last_code;
+    int last_value;
+    int keypressed;
+};
+
+struct keymap_t default_keys[KEYCODE_CNT];
+struct keymap_t customer_keys[KEYCODE_CNT];
+struct mapping_table_t mapping_table[KEY_MAPING_MAX];
+struct key_dev_t sunxi_ir_dev;
+
+int mapping_table_cnt = 0;
+
+void keymap_init(struct keymap_t *map)
+{
+    int i;
+    for (i=0; i<KEYCODE_CNT; i++, map++) {
+        map->keycode = RESERVE_CODE;
+        strcpy(map->name, RESERVE_NAME);
+    }
+}
+
+#ifdef DEBUG
+void dump_keymap(struct keymap_t *map)
+{
+    int i;
+
+    for (i=0; i<KEYCODE_CNT; i++, map++) {
+        if (!strlen(map->name)) continue;
+        printf("key\t%d\t%s\n", map->keycode, map->name);
+    }
+}
+
+void dump_mapping_table(struct mapping_table_t *table, struct keymap_t *def)
+{
+    int i;
+
+    printf("+ identity: 0x%04x\n", table->identity);
+    for (i=0; i<KEYCODE_CNT; i++) {
+        printf("\t[%3d] --> { %3d, %-20s }\n", i, table->value[i],
+                    (def + table->value[i])->name);
+    }
+}
+#endif
+
+static int isDPADKey(int scan) {
+    int DPADKeyCode[4] = {DPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT};
+    int i;
+    for (i = 0; i < 4; i++) {
+        if (DPADKeyCode[i] == scan) return 1;
+    }
+    return 0;
+}
+
+/**
+ * @brief: create a keymap form keylayout file(*.kl)
+ * @param: path - path to the target file
+ * @param: map - store the result
+ * @return:
+ */
+int create_keymap_from_file(const char *path, struct keymap_t *map)
+{
+    int ret = 0;
+    FILE *kl_fd = NULL;
+    char buf[1024], lable[32], name[MAX_NAME_LEN];
+    int keycode;
+    char *p;
+    struct keymap_t *des;
+
+    kl_fd = fopen(path, "r");
+    if (!kl_fd) {
+        ALOGE("open '%s' fail, %s\n", path, strerror(errno));
+        return -1;
+    }
+
+    while (fgets(buf, 1024, kl_fd)) {
+        p = buf;
+        while (*p==' ') p++;
+        if (*p=='#') continue;
+
+        if (sscanf(buf, "%31s %d %31s", lable, &keycode, name)!=3) continue;
+        if (strcmp(lable, "key")!=0 || keycode < KEYCODE_MIN || keycode > KEYCODE_MAX) continue;
+
+        des = (struct keymap_t *)(map + keycode);
+        des->keycode = keycode;
+        strcpy(des->name, name);
+    }
+
+    if (!feof(kl_fd)) {
+        ALOGE("reading '%s' error, %s\n", path, strerror(errno));
+        ret = -1;
+    }
+
+    fclose(kl_fd);
+    return ret;
+}
+
+/**
+ * @brief: make a mapping from src to des, the result is store at @table,
+ *         the mapping will set to ir driver through ioctl syscall.
+ * @param: src
+ * @param: des
+ * @param: table
+ */
+void generate_mapping_table(struct keymap_t* src, struct keymap_t *des, struct mapping_table_t *table)
+{
+    int i, j;
+    struct keymap_t *p;
+
+    memset(table, 0, sizeof(struct mapping_table_t));
+    for (i=0; i<KEYCODE_CNT; i++, src++) {
+        if (src->keycode==RESERVE_CODE) continue;
+
+        p = des;
+        for (j=0; j<KEYCODE_CNT; j++, p++) {
+            if (p->keycode!=-1 && strcmp(src->name, p->name)==0) {
+                table->value[p->keycode] = src->keycode;
+
+                if (table->powerkey==0 && strcmp(src->name, "POWER")==0) {
+                    table->powerkey = p->keycode;
+                }
+
+                p->keycode = -1;
+            }
+        }
+    }
+}
+
+/**
+ * @brief: filter out the valid kaylaout file.
+ * @param: name
+ * @return: -1 means something error, else the identity.
+ */
+int kl_filename_verify(const char *name)
+{
+    char *p;
+    int i, identity;
+    /* filename prefix filter */
+    if(ir_protocol_used == RC5){
+        if (strncmp(name, FILENAME_PREFIX_RC5, strlen(FILENAME_PREFIX_RC5)))
+            return -1;
+    }
+    else if(ir_protocol_used == NEC){
+        if (strncmp(name, FILENAME_PREFIX, strlen(FILENAME_PREFIX)))
+            return -1;
+    }
+    /* filename extensiion filter */
+    if(ir_protocol_used == RC5){
+        p = (char *)name + strlen(FILENAME_PREFIX_RC5) + 2;
+        if (strcmp(p, FILENAME_EXTENSION))
+            return -1;
+    }
+    else if(ir_protocol_used == NEC){
+        p = (char *)name + strlen(FILENAME_PREFIX) + 4;
+        if (strcmp(p, FILENAME_EXTENSION))
+            return -1;
+    }
+
+    /* identity filter, 4 hexadecimal number */
+    if(ir_protocol_used == RC5){
+        p = (char *)name + strlen(FILENAME_PREFIX_RC5);
+        for (i=0; i<2; i++) {
+            if (isxdigit(*(p+i))==0)
+                return -1;
+        }
+    }
+    else if(ir_protocol_used == NEC){
+        p = (char *)name + strlen(FILENAME_PREFIX);
+        for (i=0; i<4; i++) {
+            if (isxdigit(*(p+i))==0)
+                return -1;
+        }
+    }
+    identity =  strtol(p, &p, 16);
+
+    return identity;
+}
+
+int init_sunxi_ir_map(void)
+{
+    int mapping_table_cnt = 0;
+    char kl_path[512] = {0};
+    DIR *dir;
+    struct dirent *dirent;
+    int identity;
+
+    /* create default key map */
+    keymap_init(default_keys);
+    sprintf(kl_path, "%s/%s", KEY_LAYOUT_PATH, DEFAULT_KEYLAYOUT_FILE);
+    create_keymap_from_file(kl_path, default_keys);
+
+#ifdef DEBUG
+    dump_keymap(default_keys);
+#endif
+
+    dir = opendir(KEY_LAYOUT_PATH);
+    if (!dir) {
+        ALOGE("Open directory '%s' error, %s\n",
+            KEY_LAYOUT_PATH, strerror(errno));
+        exit(-1);
+    }
+
+    while ((dirent = readdir(dir))!= NULL) {
+        identity = kl_filename_verify(dirent->d_name);
+        if ((identity != -1) && (mapping_table_cnt < KEY_MAPING_MAX)) {
+#ifdef DEBUG
+            ALOGI("config filename %s\n", dirent->d_name);
+#endif
+            sprintf(kl_path, "%s/%s", KEY_LAYOUT_PATH, dirent->d_name);
+            memset(customer_keys, 0, sizeof(struct keymap_t)*(KEYCODE_CNT));
+            create_keymap_from_file(kl_path, customer_keys);
+            generate_mapping_table(default_keys, customer_keys, &(mapping_table[mapping_table_cnt]));
+            mapping_table[mapping_table_cnt].identity = identity;
+            #ifdef DEBUG
+                dump_mapping_table(&(mapping_table[mapping_table_cnt]), default_keys);
+            #endif
+            mapping_table_cnt++;
+        }
+    }
+    closedir(dir);
+    return mapping_table_cnt;
+}
+
+int detect_key_event(struct input_event *event, int ir_map_cnt)
+{
+    int i;
+    int scan_code = 0;
+    int scan_addr = 0;
+
+    if(ir_protocol_used == RC5){
+        scan_code = event->value & 0x7f;
+        scan_addr = (event->value >> 8) & 0x1f;
+    }
+    else if(ir_protocol_used == NEC){
+        scan_code = event->value & 0xff;
+        scan_addr = (event->value >> 8) & 0xffff;
+    }
+    for(i = 0; i < ir_map_cnt; i++)
+    {
+        if(mapping_table[i].identity == scan_addr)
+        {
+            return mapping_table[i].value[scan_code];
+        }
+    }
+    return -1;
+}
+
+int convertCenterEvent(int scancode, int sync)
+{
+    struct input_event temp_event;
+    if (scancode != DPAD_CENTER)
+        return 0;
+    temp_event.code = BTN_LEFT;
+    temp_event.type = EV_KEY;
+    temp_event.value = 0;
+    report_key_event(g_mousefd, &temp_event, sync);
+    return 0;
+}
+
+int ir_key_up(struct key_dev_t *ir_dev, int code, int sync)
+{
+    struct input_event temp_event;
+
+    if(!(ir_dev->keypressed))
+    {
+        return 0;
+    }
+    temp_event.type = EV_KEY;
+    if (event_mode && (code == DPAD_CENTER))
+        return convertCenterEvent(code, sync);
+    temp_event.code = code;
+    temp_event.value = 0;
+    report_key_event(ir_dev->uinputfd, &temp_event, sync);
+    multi_debug("up %04x %04x %08x\n", temp_event.type, temp_event.code, temp_event.value);
+    ir_dev->keypressed = 0;
+    return 0;
+}
+
+int convertEvent(struct key_dev_t *ir_dev, int scancode)
+{
+    struct input_event temp_event;
+    temp_event.type = EV_REL;
+    switch (scancode) {
+        case DPAD_UP:
+            temp_event.code = REL_Y;
+            temp_event.value = -mDistance;
+            break;
+        case DPAD_DOWN:
+            temp_event.code = REL_Y;
+            temp_event.value = mDistance;
+            break;
+        case DPAD_LEFT:
+            temp_event.code = REL_X;
+            temp_event.value = -mDistance;
+            break;
+        case DPAD_RIGHT:
+            temp_event.code = REL_X;
+            temp_event.value = mDistance;
+            break;
+        case DPAD_CENTER:
+            temp_event.type = EV_KEY;
+            temp_event.code = BTN_LEFT;
+            temp_event.value = 1;
+            break;
+        default:
+            return 0;
+    }
+    ir_dev->keypressed = 1;
+    ir_dev->last_code = temp_event.code;
+    ir_dev->last_value = temp_event.value;
+    report_key_event(g_mousefd, &temp_event, 1);
+    return 0;
+}
+
+int ir_key_down(struct key_dev_t *ir_dev, int scancode)
+{
+    struct input_event temp_event;
+
+    if (ir_dev->keypressed)
+        ir_key_up(ir_dev, scancode, 1);
+
+    if (event_mode && (isDPADKey(scancode) || scancode == DPAD_CENTER)) {
+        return convertEvent(ir_dev, scancode);
+    }
+
+    temp_event.type = EV_KEY;
+    temp_event.code = scancode;
+    temp_event.value = 1;
+    ir_dev->keypressed = 1;
+    ir_dev->last_code = scancode;
+    report_key_event(ir_dev->uinputfd, &temp_event, 1);
+    multi_debug("down %04x %04x %08x\n", temp_event.type, temp_event.code, temp_event.value);
+    return 0;
+}
+
+int sunxi_timer_init(struct itimerval *value, int repeat_num)
+{
+    if(repeat_num == 0)
+    {
+        value->it_value.tv_sec = 0;
+        value->it_value.tv_usec = IR_KEYPRESS_TIMEOUT; //200ms��ʱ
+        value->it_interval.tv_sec = 0;
+        value->it_interval.tv_usec = IR_KEYPRESS_TIMEOUT; //200ms��ʱ
+    }else if(repeat_num > 0) {  // Support to decrease the period of repeating time
+        value->it_value.tv_sec = 0;
+        value->it_value.tv_usec = pointer_speed * 1000;
+        value->it_interval.tv_sec = 0;
+        value->it_interval.tv_usec = pointer_speed * 1000;
+    }
+    setitimer(ITIMER_REAL, value, NULL);
+    return 0;
+}
+
+void ir_key_repeat(int signum)
+{
+    struct input_event temp_event;
+
+    if (signum!=SIGALRM)
+        return;
+
+    pthread_mutex_lock(&mutex);
+    if(sunxi_ir_dev.keypressed)
+    {
+        temp_event.type = EV_REL;
+        temp_event.code = sunxi_ir_dev.last_code;
+        temp_event.value = sunxi_ir_dev.last_value;
+        report_key_event(g_mousefd, &temp_event, 1);
+        sunxi_timer_init(&timer_value, 1);
+    }
+    pthread_mutex_unlock(&mutex);
+    return;
+}
+
+int sunxi_mod_timer(struct itimerval *value)
+{
+    setitimer(ITIMER_REAL, value, NULL);
+    return 0;
+}
+
+int sunxi_del_timer(struct itimerval *value)
+{
+    value->it_value.tv_sec = 0;
+    value->it_value.tv_usec = 0;
+    value->it_interval.tv_sec = 0;
+    value->it_interval.tv_usec = 0;
+    setitimer(ITIMER_REAL, value, NULL);
+    return 0;
+}
+
+#ifdef CEC_ONE_TOUCH_PLAY
+#define ONE_TOUCH_PLAY_CODE (0xDF)
+void trigger_one_touch_play(void)
+{
+    property_set("hdmi_cts.one_touch_play", "1");
+}
+#endif
+
+
+
+void setMouseMode(int mode) {
+    event_mode = mode;
+}
+
+int detect_key_input(struct key_dev_t *ir_dev)
+{
+    int scan_code;
+    int key_state;
+
+    scan_code = detect_key_event(ir_dev->event, mapping_table_cnt);
+
+    if(scan_code <= 0)
+    {
+        return 0;
+    }
+
+    key_state = (ir_dev->event->value >> 24) & 0x1;
+
+#ifdef CEC_ONE_TOUCH_PLAY
+    if (key_state && scan_code == ONE_TOUCH_PLAY_CODE) {
+        trigger_one_touch_play();
+        ALOGD("trigger one touch play.");
+    }
+#endif
+
+    if(key_state)
+    {
+        ir_key_down(ir_dev, scan_code);
+        if(event_mode && isDPADKey(scan_code))
+        {
+            sunxi_timer_init(&timer_value, 0);
+        }
+    }
+    else
+    {
+        if(event_mode)
+        {
+            sunxi_del_timer(&timer_value);
+        }
+        ir_key_up(ir_dev, scan_code, 1);
+    }
+    return 0;
+}
+
+static int _report_mouse_keyevent(struct key_dev_t *ir_dev, int scan_code, int key_state)
+{
+    if (scan_code <= 0) {
+        return 0;
+    }
+
+    if (key_state) {
+        ir_key_down(ir_dev, scan_code);
+        if (event_mode && isDPADKey(scan_code)) {
+            sunxi_timer_init(&timer_value, 0);
+        }
+    } else {
+        if (event_mode) {
+            sunxi_del_timer(&timer_value);
+        }
+        ir_key_up(ir_dev, scan_code, 1);
+    }
+    return 0;
+}
+
+int report_mouse_keyevent(int scan_code, int key_state)
+{
+    return _report_mouse_keyevent(&sunxi_ir_dev, scan_code, key_state);
+}
+
+static int  ir_protocol(unsigned int *ir_protocol_used )
+{
+    int res = 0,fd = 0;
+    fd = open(IR_PROTOCOL_USED,O_RDONLY|O_NONBLOCK);
+    res = read(fd,ir_protocol_used,sizeof(unsigned int));
+    printf("IR_PROTOCOL_USED = %d\n",*ir_protocol_used);
+    if(res < 0)
+    {
+        ALOGE("can not read IR_PROTOCOL_USED\n");
+        return  1;
+    }
+    if((*ir_protocol_used!= NEC)&&(*ir_protocol_used!= RC5))
+    {
+        ALOGE("WRONG : sunxi only support rc5 or nec protocol now\n\n");
+        return 1;
+    }
+    close(fd);
+    return 0;
+}
+#ifndef BUILD_TARGET_RECOVERY
+std::thread mServiceThread;
+void startService(void)
+{
+    android::sp<android::ProcessState> proc(android::ProcessState::self());
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::MultiirService::instantiate();
+    android::ProcessState::self()->startThreadPool();
+    android::IPCThreadState::self()->joinThreadPool();
+}
+#endif
+
+int main(void)
+{
+    int err;
+    //int scan_code = 0;
+    //const char *devname = NULL;
+    const char *inotify_path = "/dev/input";
+    char uinput_devname[32] = "sunxi-ir-uinput";
+    char devpath[PATH_MAX];
+    struct pollfd ufds[POLL_FD_NUM];
+    char device_name[16] = {0};
+    struct inputdev_info * sourcedev = NULL;
+    struct input_event ir_event;
+    int uinputfd = -1;
+    //To determine which protocol of IR will be used
+    if(ir_protocol(&ir_protocol_used))
+    {
+        ALOGE("WRONG:faied to get ir_protocol_used \
+            default to use NEC protocol\n");
+        ir_protocol_used = NEC;
+    }
+    //�����豸����
+    uinputfd = setup_virtual_input_dev(uinput_devname);
+    ALOGD("uinputfd=%d\n", uinputfd);
+    if(uinputfd <= 0)
+    {
+        return 0;
+    }
+
+    sunxi_ir_dev.uinputfd = uinputfd;
+    sunxi_ir_dev.event = &ir_event;
+
+    mapping_table_cnt = init_sunxi_ir_map();
+    if(mapping_table_cnt <= 0)
+    {
+        ALOGE("cant find any ir map");
+        return 0;
+    }
+
+    pthread_mutex_init(&mutex, NULL);
+    signal(SIGALRM, ir_key_repeat);
+
+    memset(ufds, 0, sizeof(ufds));
+    memset(&sourcedev, 0, sizeof(sourcedev));
+
+    /* inotify when '/dev/inpu't dir change */
+    nfds = 1;
+    ufds[0].fd = inotify_init();
+    ufds[0].events = POLLIN;
+    err = inotify_add_watch(ufds[0].fd, inotify_path, IN_DELETE | IN_CREATE);
+    if (err < 0) {
+        ALOGE("could not add watch for '%s', %s",
+            inotify_path, strerror(errno));
+        return -1;
+    }
+
+#ifdef HDMI_CEC_STANDBY_SUPPORT
+    if (uevent_init(&ufds[CEC_FD_INDEX].fd)==0) {
+        nfds++;
+        ufds[CEC_FD_INDEX].events = POLLIN;
+        ALOGD("uevent listen start");
+    }
+#endif
+
+    strcpy(device_name, "sunxi-ir");
+
+    /* try to find the target input device */
+    err = try_to_find_device(device_name, devpath);
+    if (err==0 && strlen(devpath)) {
+        ALOGD("find target device, path=%s", devpath);
+        sourcedev = open_device(devpath, ufds);
+    }
+
+#ifndef BUILD_TARGET_RECOVERY
+    mServiceThread = std::thread(startService);
+#endif
+
+    while(1) {
+        poll(ufds, nfds, -1);
+        if (ufds[0].revents & POLLIN) {
+            notify_process(sourcedev, uinput_devname, inotify_path, ufds[0].fd, ufds);
+        }
+        if (ufds[INPUT_FD_INDEX].revents & POLLIN) {
+
+            if(!input_event_process(ufds[INPUT_FD_INDEX].fd, &ir_event))
+            {
+                detect_key_input(&sunxi_ir_dev);
+            }
+        }
+        #ifdef HDMI_CEC_STANDBY_SUPPORT
+        if (ufds[CEC_FD_INDEX].revents & POLLIN) {
+            uevent_process_event();
+        }
+        #endif
+    }
+    return 0;
+}
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.h b/android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.h
new file mode 100755
index 0000000..9dadf06
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/multiir.h
@@ -0,0 +1,54 @@
+
+#ifndef __MULTI_IR_H__
+#define __MULTI_IR_H__
+
+#include <linux/ioctl.h>
+
+/* ioctl cmd define */
+#define MULTI_IR_IOC_MAGIC	'M'
+/* return the max mapping table count support, if error, return -1 */
+#define MULTI_IR_IOC_REQ_MAP	_IOR(MULTI_IR_IOC_MAGIC, 1, int *)
+#define MULTI_IR_IOC_SET_MAP	_IOW(MULTI_IR_IOC_MAGIC, 2, void *)
+#define MULTI_IR_IOC_CLR_MAP	_IOW(MULTI_IR_IOC_MAGIC, 3, int)
+
+#define MAX_NAME_LEN		(32)
+#define KEYCODE_MIN			(0)
+#define KEYCODE_MAX			(300)
+#define KEYCODE_CNT			(KEYCODE_MAX-KEYCODE_MIN+1)
+#define KEY_MAPING_MAX		(18)
+
+#define RESERVE_CODE	0
+#define RESERVE_NAME	"!RESERVE"
+
+
+/*
+ A mapping table is mapping from customer ir key layout file(*.kl)
+ to default layout file.
+
+ For example:
+	in coustomer kl file  -->  key 28  POWER
+	in default kl file    -->  key 57  POWER
+
+	then, the mapping will be like that: mapping_table.value[57] = 28
+*/
+struct mapping_table_t {
+	int identity;				/* means ir address */
+	int powerkey;				/* powerky to wakeup system */
+	int value[KEYCODE_CNT];		/* convert from coustomer keycode to
+                               default keycode */
+};
+
+void setMouseMode(int mode);
+int report_mouse_keyevent(int scan_code, int key_state);
+#define HDMI_CEC_STANDBY_SUPPORT
+
+#ifdef HDMI_CEC_STANDBY_SUPPORT
+#define POLL_FD_NUM		(3)
+#define CEC_FD_INDEX	(1)
+#define INPUT_FD_INDEX	(2)
+#else
+#define POLL_FD_NUM		(2)
+#define INPUT_FD_INDEX	(1)
+#endif
+
+#endif /* __MULTI_IR_H__ */
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/uevent_utils.cpp b/android/vendor/aw/homlet/hardware/input/multi_ir/core/uevent_utils.cpp
new file mode 100755
index 0000000..2bed3e2
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/uevent_utils.cpp
@@ -0,0 +1,155 @@
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/queue.h>
+#include <linux/netlink.h>
+#include <utils/Log.h>
+
+static const char * device_match_array[] = {
+	"change@/devices/platform/soc/hdmi",
+	"change@/devices/soc.0/1ee0000.hdmi",
+};
+
+static int fd = -1;
+
+/* Returns !0 on failure, 0 on success */
+int uevent_init(int *ufds)
+{
+    struct sockaddr_nl addr;
+    int sz = 64*1024;
+    int s;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.nl_family = AF_NETLINK;
+    addr.nl_pid = getpid();
+    addr.nl_groups = 0xffffffff;
+
+    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+    if(s < 0)
+        return 0;
+
+    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
+
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        close(s);
+        return 0;
+    }
+
+    fd = s;
+	*ufds = fd;
+    return (fd > 0) ? 0 : -1;
+}
+
+int uevent_next_event(char* buffer, int buffer_length)
+{
+    while (1) {
+        struct pollfd fds;
+        int nr;
+
+        fds.fd = fd;
+        fds.events = POLLIN;
+        fds.revents = 0;
+        nr = poll(&fds, 1, -1);
+
+        if(nr > 0 && (fds.revents & POLLIN)) {
+            int count = recv(fd, buffer, buffer_length, 0);
+            if (count > 0) {
+                return count;
+            }
+        }
+    }
+    return 0;
+}
+
+/* return interval in sec */
+long get_interval(void)
+{
+	static struct timeval previous;
+	struct timeval current, interval;
+
+	gettimeofday(&current, NULL);
+	timersub(&current, &previous, &interval);
+	previous = current;
+
+	return interval.tv_sec;
+}
+
+extern void report_standby_request(void);
+char msg[1024] = {0};
+int uevent_process_event(void)
+{
+	int i;
+	int count = 0;
+	char *substr = NULL;
+	int cec_opcode = 0;
+
+	count = recv(fd, msg, 1024, 0);
+	if (count<=0) return 0;
+
+	msg[count] = 0;
+	for (substr=msg; substr<msg+count; substr+=(strlen(substr)+1)) {
+		if (!strcmp(substr, device_match_array[0])
+				|| !strcmp(substr, device_match_array[1])) {
+			i = 0;
+			while (i++<4 && substr<(msg+count))
+				substr += (strlen(substr)+1);
+
+			sscanf(substr, "CEC_MSG=%x", &cec_opcode);
+			ALOGV("recv: %s, opcode [%02x]\n", substr, cec_opcode);
+
+			if (cec_opcode == 0x36) {
+				long interval = get_interval();
+				if (interval > 5 || interval < 0) {
+					report_standby_request();
+					ALOGD("standby request from HDMI-CEC\n");
+				}
+				ALOGD("receive CEC standy request, interval = %ld sec", interval);
+			}
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+	char msg[1024] = {0};
+	char *substr = NULL;
+	int count, i;
+	int cec_opcode = 0;
+
+	if (uevent_init()!=0) {
+		fprintf(stderr, "uevent init error\n");
+		return -1;
+	}
+
+	while (1) {
+		count = uevent_next_event(msg, sizeof(msg));
+		if (count > 0) {
+			msg[count] = 0;
+			for (substr=msg; substr<msg+count; substr+=(strlen(substr)+1)) {
+				if (strcmp(substr, DEVICE_MATCH_STR)==0) {
+					i = 0;
+					while (i++<4 && substr<(msg+count))
+						substr += (strlen(substr)+1);
+
+					sscanf(substr, "CEC_MSG=%x", &cec_opcode);
+					fprintf(stdout, "recv: %s, opcode [%02x]\n", substr, cec_opcode);
+					break;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+#endif
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.cpp b/android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.cpp
new file mode 100755
index 0000000..efd9feb
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.cpp
@@ -0,0 +1,460 @@
+/*
+ * multi ir daemon for android -
+ * Copyright (C) 2015-2018 AllwinnerTech
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/inotify.h>
+#include <sys/poll.h>
+#include <utils/Log.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include "multiir.h"
+#include "virtual_input.h"
+
+#define	uinput_debug(fmt, arg...) 				\
+do { 											\
+	if (print_flags & PRINT_DEBUG)				\
+		fprintf(stdout, "[D] " fmt"\n", ##arg);	\
+} while(0)
+
+#define	uinput_warning(fmt, arg...) 			\
+do { 											\
+	if (print_flags & PRINT_WARN)				\
+		fprintf(stdout, "[W] " fmt"\n", ##arg);	\
+} while(0)
+
+#define	uinput_error(fmt, arg...) 				\
+do { 											\
+	if (print_flags & PRINT_ERROR)				\
+		fprintf(stderr, "[E] " fmt"\n", ##arg);	\
+} while(0)
+
+enum {
+    PRINT_ERROR	 = 1U << 0,
+    PRINT_WARN	 = 1U << 1,
+    PRINT_DEBUG	 = 1U << 2,
+};
+
+#define UINPUT_NAME		"/dev/uinput"
+static int g_uinputfd = -1;
+int g_mousefd = -1;
+static int print_flags = 0;
+
+static struct uinput_user_dev virtual_inputdev;
+static struct uinput_user_dev virtual_mousedev;
+
+
+int nfds = 0;
+
+static int is_devname_match(const char *devpath, const char *tname)
+{
+	int fd;
+	char name[80];
+
+	if (!devpath || !tname)
+		return 0;
+
+	fd = open(devpath, O_RDWR);
+	if (fd<0) {
+		uinput_error("could not open '%s', %s",
+			devpath, strerror(errno));
+		return 0;
+	}
+	name[sizeof(name)-1] = '\0';
+	if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+		uinput_error("could not get device name for '%s', %s",
+			devpath, strerror(errno));
+		name[0] = '\0';
+		goto notmatch;
+	}
+	if (!strcmp(name, tname)) {
+		uinput_debug("find match device '%s'", devpath);
+		close(fd);
+		return 1;
+	}
+
+notmatch:
+	close(fd);
+	uinput_debug("device not match or ioctl error, %s(%s)", devpath, name);
+	return 0;
+}
+
+int try_to_find_device(const char *devname, char *path)
+{
+	const char *dirname = "/dev/input";
+    char devpath[PATH_MAX];
+    char *p;
+    DIR *dir;
+    struct dirent *de;
+
+	if (!devname || !path)
+		return -1;
+
+	path[0] = '\0';
+    dir = opendir(dirname);
+    if(dir == NULL)
+        return -1;
+    strcpy(devpath, dirname);
+    p = devpath + strlen(devpath);
+    *p++ = '/';
+    while((de = readdir(dir))) {
+        if(de->d_name[0] == '.' &&
+           (de->d_name[1] == '\0' ||
+            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+            continue;
+
+		strcpy(p, de->d_name);
+		if (is_devname_match(devpath, devname)) {
+			strcpy(path, devpath);
+			break;
+		}
+    }
+    closedir(dir);
+    return 0;
+}
+
+struct inputdev_info *open_device(const char *devpath, struct pollfd *ufds)
+{
+	struct inputdev_info *info;
+
+	if (!devpath)
+		goto errout;
+
+	info = (inputdev_info *)calloc(sizeof(*info), sizeof(char));
+	if (!info) {
+		uinput_error("could not malloc, %s", strerror(errno));
+		goto errout;
+	}
+
+	info->fd = open(devpath, O_RDWR);
+	if (info->fd < 0) {
+		uinput_error("could not open device '%s', %s",
+			devpath, strerror(errno));
+		free(info);
+		goto errout;
+	}
+
+	strcpy(info->devpath, devpath);
+	if (ioctl(info->fd, EVIOCGVERSION, &info->version)) {
+		uinput_warning("could not get driver version for '%s', %s",
+			devpath, strerror(errno));
+	}
+	if (ioctl(info->fd, EVIOCGID, &info->id)) {
+		uinput_warning("could not get driver id for '%s', %s",
+			devpath, strerror(errno));
+    }
+
+	if (ioctl(info->fd, EVIOCGNAME(sizeof(info->name)-1), info->name) < 1) {
+		uinput_warning("could not get device name for %s, %s",
+			devpath, strerror(errno));
+	}
+	if (ioctl(info->fd, EVIOCGPHYS(sizeof(info->location)-1), info->location) < 1) {
+		uinput_warning("could not get location for %s, %s",
+			devpath, strerror(errno));
+	}
+	if (ioctl(info->fd, EVIOCGUNIQ(sizeof(info->idstr) - 1), info->idstr) < 1) {
+		uinput_warning("could not get idstring for %s, %s",
+			devpath, strerror(errno));
+    }
+
+	if (print_flags & PRINT_DEBUG) {
+		fprintf(stdout, "    devpath:  %s\n", info->devpath);
+		fprintf(stdout, "    bus:      %04x\n"
+					 	"    vendor    %04x\n"
+						"    product   %04x\n"
+						"    version   %04x\n",
+						info->id.bustype, info->id.vendor,
+						info->id.product, info->id.version);
+		fprintf(stdout, "    name:     \"%s\"\n", info->name);
+		fprintf(stdout, "    location: \"%s\"\n"
+						"    id:       \"%s\"\n", info->location, info->idstr);
+		fprintf(stdout, "    version:  %d.%d.%d\n",
+						info->version >> 16,
+						(info->version >> 8) & 0xff,
+						info->version & 0xff);
+	}
+
+	ufds[INPUT_FD_INDEX].fd = info->fd;
+	ufds[INPUT_FD_INDEX].events = POLLIN;
+	nfds++;
+	uinput_debug("add device '%s' to poll", devpath);
+	return info;
+errout:
+	uinput_error("could open device '%s'!", devpath);
+	return NULL;
+}
+
+static void close_device(struct inputdev_info * sourcedev, const char *devpath, struct pollfd *ufds)
+{
+	if (!sourcedev)
+		return;
+
+	if (!strcmp(sourcedev->devpath, devpath)) {
+		close(sourcedev->fd);
+		free(sourcedev);
+		sourcedev = NULL;
+
+		nfds--;
+		ufds[nfds].fd = -1;
+		ufds[nfds].events = 0;
+		uinput_debug("close device '%s'", devpath);
+	} else {
+		uinput_debug("device '%s' not open, ignore", devpath);
+	}
+}
+
+int notify_process(struct inputdev_info * sourcedev, char *device_name, const char *dirname, int nfd, struct pollfd *ufds)
+{
+	int res;
+	char devpath[PATH_MAX];
+	char *p;
+	char event_buf[512];
+	int event_size;
+	int event_pos = 0;
+	struct inotify_event *event;
+
+	res = read(nfd, event_buf, sizeof(event_buf));
+	if (res < (int)sizeof(*event)) {
+		if (errno == EINTR)
+			return 0;
+		uinput_error("could not get event, %s", strerror(errno));
+		return 1;
+	}
+	uinput_debug("got %d bytes of event information", res);
+
+	strcpy(devpath, dirname);
+	p = devpath + strlen(devpath);
+	*p++ = '/';
+
+	while(res >= (int)sizeof(*event)) {
+		event = (struct inotify_event *)(event_buf + event_pos);
+		uinput_debug("%d: %08x \"%s\"",
+			event->wd, event->mask, event->len ? event->name : "");
+
+		if (event->len) {
+			strcpy(p, event->name);
+			if (event->mask & IN_CREATE) {
+				if (!sourcedev && is_devname_match(devpath, device_name)) {
+					uinput_debug("find target device, path=%s", devpath);
+					sourcedev = open_device(devpath, ufds);
+				}
+			} else {
+				close_device(sourcedev, devpath, ufds);
+			}
+		}
+
+		event_size = sizeof(*event) + event->len;
+		res -= event_size;
+		event_pos += event_size;
+	}
+
+	return 0;
+}
+
+int input_event_process(int nfd, struct input_event *event)
+{
+	int res;
+
+	res = read(nfd, event, sizeof(struct input_event));
+	if (res < (int)sizeof(struct input_event)) {
+		uinput_error("could not get event");
+		return -1;
+	}
+
+//	ALOGD("%04x %04x %08x", event->type, event->code, event->value);
+	return 0;
+}
+
+int create_virtual_mouse_dev(char *mouse_dev) {
+    int uinputfd = -1;
+
+    if (g_mousefd >= 0) {
+        ALOGD("multiir had enter mouse mode");
+        return 0;
+    }
+
+    ALOGD("multi_ir open uinput dev");
+
+    uinputfd = open(UINPUT_NAME, O_WRONLY | O_NDELAY);
+    if (uinputfd <= 0) {
+        ALOGE("could not open '%s', %s\n", UINPUT_NAME, strerror(errno));
+        return uinputfd;
+    }
+
+    memset(&virtual_mousedev, 0, sizeof(virtual_mousedev));
+    strncpy(virtual_mousedev.name, mouse_dev, UINPUT_MAX_NAME_SIZE);
+    virtual_mousedev.id.version = 0x0111;
+    virtual_mousedev.id.bustype = BUS_USB;
+    virtual_mousedev.id.vendor = 0x093a;
+    virtual_mousedev.id.product = 0x2521;
+
+    /* setup mouse coordinate event */
+    if (ioctl(uinputfd, UI_SET_EVBIT,  EV_REL) < 0) ALOGE("set evbit rel fail : %s", strerror(errno));
+    if (ioctl(uinputfd, UI_SET_EVBIT,  EV_KEY) < 0) ALOGE("set evbit key fail : %s", strerror(errno));
+    if (ioctl(uinputfd, UI_SET_RELBIT, REL_X) < 0) ALOGE("set relbit x fail : %s", strerror(errno));
+    if (ioctl(uinputfd, UI_SET_RELBIT, REL_Y) < 0) ALOGE("set relbit y fail : %s", strerror(errno));
+
+    /* setup mouse button event */
+    if (ioctl(uinputfd, UI_SET_KEYBIT, BTN_MOUSE) < 0) ALOGE("set keybit mouse fail : %s", strerror(errno));
+
+    /* create input device into input subsystem */
+    write(uinputfd, &virtual_mousedev, sizeof(virtual_mousedev));
+    if (ioctl(uinputfd, UI_DEV_CREATE)) {
+        ALOGE("could not create uinput device, %s\n", strerror(errno));
+        close(uinputfd);
+        uinputfd = -1;
+        return uinputfd;
+    }
+
+    g_mousefd = uinputfd;
+    setMouseMode(1);
+    return 0;
+}
+
+int destory_virtual_mouse_dev(void) {
+    if (g_mousefd == -1) {
+        ALOGD("multiir had exit mouse mode");
+        return 0;
+    }
+
+    if (ioctl(g_mousefd, UI_DEV_DESTROY)) {
+        ALOGD("could not destory virtual mouse: %s", strerror(errno));
+        close(g_mousefd);
+        g_mousefd = -1;
+        return -1;
+    }
+    close(g_mousefd);
+    g_mousefd = -1;
+    setMouseMode(0);
+    return 0;
+}
+
+int setup_virtual_input_dev(char *inputdev_name)
+{
+    int i;
+    int uinputfd = -1;
+
+    ALOGD("multi_ir open uinput dev");
+
+    uinputfd = open(UINPUT_NAME, O_WRONLY | O_NDELAY);
+    if (uinputfd <= 0) {
+        ALOGE("could not open '%s', %s\n", UINPUT_NAME, strerror(errno));
+        return uinputfd;
+    }
+
+    memset(&virtual_inputdev, 0, sizeof(virtual_inputdev));
+    strncpy(virtual_inputdev.name, inputdev_name, UINPUT_MAX_NAME_SIZE);
+    virtual_inputdev.id.version = 4;
+    virtual_inputdev.id.bustype = BUS_HOST;
+    ioctl(uinputfd, UI_SET_EVBIT, EV_KEY);
+   	ioctl(uinputfd, UI_SET_EVBIT, EV_MSC);
+   	ioctl(uinputfd, UI_SET_EVBIT, EV_REP);
+
+    /* register a cursor device */
+    ioctl(uinputfd, UI_SET_KEYBIT, BTN_MOUSE);
+    ioctl(uinputfd, UI_SET_RELBIT, REL_X);
+    ioctl(uinputfd, UI_SET_RELBIT, REL_Y);
+    ioctl(uinputfd, UI_SET_EVBIT,  EV_REL);
+#if 0
+	/* setup mouse coordinate event */
+    ioctl(uinputfd, UI_SET_EVBIT,  EV_REL);
+    ioctl(uinputfd, UI_SET_RELBIT, REL_X);
+    ioctl(uinputfd, UI_SET_RELBIT, REL_Y);
+
+    /* setup mouse button event */
+    ioctl(uinputfd, UI_SET_KEYBIT, BTN_MOUSE);
+    ioctl(uinputfd, UI_SET_KEYBIT, BTN_TOUCH);
+    ioctl(uinputfd, UI_SET_KEYBIT, BTN_LEFT);
+    ioctl(uinputfd, UI_SET_KEYBIT, BTN_RIGHT);
+    ioctl(uinputfd, UI_SET_KEYBIT, BTN_MIDDLE);
+#endif
+
+    for (i = KEYCODE_MIN; i < KEYCODE_CNT; i++)
+        ioctl(uinputfd, UI_SET_KEYBIT, i);
+
+    /* create input device into input subsystem */
+    write(uinputfd, &virtual_inputdev, sizeof(virtual_inputdev));
+    if (ioctl(uinputfd, UI_DEV_CREATE)) {
+        ALOGE("could not create uinput device, %s\n", strerror(errno));
+        close(uinputfd);
+        uinputfd = -1;
+        return uinputfd;
+    }
+
+    g_uinputfd = uinputfd;
+    return uinputfd;
+}
+
+void report_key_event(int uinputfd, struct input_event *event, int sync)
+{
+    struct input_event temp_event;
+
+    write(uinputfd, event, sizeof(struct input_event));
+
+    if (sync) {
+        memset(&temp_event, 0, sizeof(struct input_event));
+        temp_event.type = EV_SYN;
+        temp_event.code = SYN_REPORT;
+        temp_event.value = 0;
+        write(uinputfd, &temp_event, sizeof(struct input_event));
+    }
+}
+
+#define POWER_KEY	(0x74)
+void report_standby_request(void)
+{
+	int uinputfd = g_uinputfd;
+	struct input_event event;
+
+	if (uinputfd<0)
+		return;
+
+	memset(&event, 0, sizeof(event));
+	gettimeofday(&event.time, NULL);
+	event.type = EV_KEY;
+	event.code = POWER_KEY;
+	event.value = 1;
+	write(uinputfd, &event, sizeof(event));
+
+	event.type = EV_SYN;
+	event.code = SYN_REPORT;
+	event.value = 0;
+	write(uinputfd, &event, sizeof(event));
+
+	memset(&event, 0, sizeof(event));
+	gettimeofday(&event.time, NULL);
+	event.type = EV_KEY;
+	event.code = POWER_KEY;
+	event.value = 0;
+	write(uinputfd, &event, sizeof(event));
+
+	event.type = EV_SYN;
+	event.code = SYN_REPORT;
+	event.value = 0;
+	write(uinputfd, &event, sizeof(event));
+}
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.h b/android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.h
new file mode 100755
index 0000000..f28925a
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/core/virtual_input.h
@@ -0,0 +1,52 @@
+/*
+ * multi ir daemon for android -
+ * Copyright (C) 2015-2018 AllwinnerTech
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef  __virtual_input_h
+#define  __virtual_input_h
+
+#include <linux/input.h>
+
+struct inputdev_info {
+	char devpath[PATH_MAX];
+	char name[80];
+	char location[80];
+	char idstr[80];
+
+	struct input_id id;
+	int version;
+
+	int fd;
+	int idx;
+};
+
+int setup_virtual_input_dev(char *inputdev_name);
+int destory_virtual_mouse_dev(void);
+int create_virtual_mouse_dev(char *mouse_dev);
+int try_to_find_device(const char *devname, char *path);
+struct inputdev_info *open_device(const char *devpath, struct pollfd *ufds);
+int notify_process(struct inputdev_info * sourcedev, char *device_name, const char *dirname, int nfd, struct pollfd *ufds);
+int input_event_process(int nfd, struct input_event *event);
+void report_key_event(int uinputfd, struct input_event *event, int sync);
+int get_default_pointerspeed(void);
+int get_default_stepdistance(void);
+void set_pointerspeed(int ms);
+void set_stepdistance(int px);
+void reset(void);
+#endif
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/jni/Android.mk b/android/vendor/aw/homlet/hardware/input/multi_ir/jni/Android.mk
new file mode 100755
index 0000000..2fc80c9
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/jni/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    com_softwinner_multiir.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libandroid_runtime \
+    libnativehelper \
+    libutils \
+    libbinder \
+    libui \
+    libcutils \
+    libmultiirservice
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_C_INCLUDES += \
+    frameworks/base/core/jni \
+    $(LOCAL_PATH)/../libmultiir \
+	libnativehelper/include/nativehelper
+
+LOCAL_CFLAGS += -Wno-unused-parameter
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_LDLIBS := -llog
+
+LOCAL_MODULE:= libmultiir_jni
+
+LOCAL_PRELINK_MODULE:= false
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/jni/com_softwinner_multiir.cpp b/android/vendor/aw/homlet/hardware/input/multi_ir/jni/com_softwinner_multiir.cpp
new file mode 100755
index 0000000..e9183b7
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/jni/com_softwinner_multiir.cpp
@@ -0,0 +1,173 @@
+/*
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "JNIMultiir"
+#define LOG_NDEBUG 0
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "utils/Errors.h"
+#include "utils/String8.h"
+#include "android_util_Binder.h"
+#include <stdio.h>
+#include <assert.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include "IMultiirService.h"
+
+using namespace android;
+
+static sp<IMultiirService> multiirService;
+
+static int init_native(JNIEnv *env) {
+    int time = 100;
+    ALOGD("init");
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder;
+    do {
+        binder = sm->getService(String16("softwinner.multi_ir"));
+        if(binder != 0){
+            multiirService = interface_cast<IMultiirService>(binder);
+            return 0;
+        }
+        ALOGW("softwinner multiir service not published, waiting...");
+        usleep(500000);
+    } while(time--);
+
+    return -1;
+}
+
+static void throw_NullPointerException(JNIEnv *env, const char* msg) {
+    jclass clazz;
+    clazz = env->FindClass("java/lang/NullPointerException");
+    env->ThrowNew(clazz, msg);
+}
+
+static int enterMouseMode(JNIEnv *env, jobject clazz) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->enterMouseMode();
+    return ret;
+}
+
+static int exitMouseMode(JNIEnv *env, jobject clazz) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->exitMouseMode();
+    return ret;
+}
+
+static int getDefaultPointerSpeed(JNIEnv *env, jobject clazz) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->getDefaultPointerSpeed();
+    return ret;
+}
+
+static int getDefaultStepDistance(JNIEnv *env, jobject clazz) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->getDefaultStepDistance();
+    return ret;
+}
+
+static int reset(JNIEnv *env, jobject clazz) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->reset();
+    return ret;
+}
+
+static int setPointerSpeed(JNIEnv *env, jobject clazz, jint ms) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->setPointerSpeed(ms);
+    return ret;
+}
+
+static int setStepDistance(JNIEnv *env, jobject clazz, jint px) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->setStepDistance(px);
+    return ret;
+}
+
+static int reportMouseKeyEvent(JNIEnv *env, jobject clazz, jint scanCode, jint keyState) {
+    if(multiirService == NULL){
+        ALOGW("softwinner multiir service is not fount");
+        return -1;
+    }
+    int ret = multiirService->reportMouseKeyEvent(scanCode, keyState);
+    return ret;
+}
+
+static JNINativeMethod method_table[] = {
+    { "_nativeInit", "()I", (void*)init_native},
+    { "_enterMouseMode", "()I", (void*)enterMouseMode },
+    { "_exitMouseMode", "()I", (void*)exitMouseMode },
+    { "_getDefaultPointerSpeed", "()I", (void*)getDefaultPointerSpeed },
+    { "_getDefaultStepDistance", "()I", (void*)getDefaultStepDistance },
+    { "_reset", "()I", (void*)reset },
+    { "_setPointerSpeed", "(I)I", (void*)setPointerSpeed },
+    { "_setStepDistance", "(I)I", (void*)setStepDistance },
+    { "_reportMouseKeyEvent", "(II)I", (void*)reportMouseKeyEvent },
+};
+
+static int register_android_os_Multiir(JNIEnv *env){
+    return AndroidRuntime::registerNativeMethods(
+        env, "com/softwinner/Multiir",method_table, NELEM(method_table));
+}
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved){
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    ALOGD("Multiir JNI_OnLoad()");
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        ALOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    if (register_android_os_Multiir(env) < 0) {
+        ALOGE("ERROR: Multiir native registration failed\n");
+        goto bail;
+    }
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/Vendor_000d_Product_3838.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/Vendor_000d_Product_3838.kl
new file mode 100755
index 0000000..7ea6771
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/Vendor_000d_Product_3838.kl
@@ -0,0 +1,11 @@
+key   1   BACK
+key 127   MENU
+key 353   DPAD_CENTER
+key 108   DPAD_DOWN
+key 103   DPAD_UP
+key 240   HOME
+key 105   DPAD_LEFT
+key 106   DPAD_RIGHT
+key 233   VOLUME_UP
+key 234   VOLUME_DOWN
+key 116   POWER
\ No newline at end of file
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_2992.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_2992.kl
new file mode 100755
index 0000000..5bd10f2
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_2992.kl
@@ -0,0 +1,36 @@
+key 39   BACK
+key 27   MENU
+key 54   SEARCH
+key 55   DPAD_CENTER
+key 40   DPAD_DOWN
+key 42   DPAD_UP
+key 43   HOME
+key 26   DPAD_LEFT
+key 41   DPAD_RIGHT
+key 24   VOLUME_UP
+key 23   VOLUME_DOWN
+key 242  POWER
+key 49   0
+key 22   1
+key 52   2
+key 36   3
+key 21   4
+key 51   5
+key 35   6
+key 20   7
+key 50   8
+key 34   9
+key 45   MEDIA_PLAY_PAUSE
+key 57   MEDIA_STOP
+key 28   MEDIA_PREVIOUS
+key 44   MEDIA_NEXT
+key 56   MEDIA_REWIND
+key 61   MEDIA_FAST_FORWARD
+key 63   VOLUME_MUTE
+key 59   TV_SYSTEM
+key 47   SETTINGS
+key 16   PROG_RED
+key 30   PROG_BLUE
+key 46   PROG_GREEN
+key 58   PROG_YELLOW
+key 32   MOUSE
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4040.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4040.kl
new file mode 100755
index 0000000..ec2c9fb
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4040.kl
@@ -0,0 +1,25 @@
+key 66   BACK
+key 69   MENU
+key 13   DPAD_CENTER
+key 14   DPAD_DOWN
+key 11   DPAD_UP
+key 26   HOME
+key 16   DPAD_LEFT
+key 17   DPAD_RIGHT
+key 24   VOLUME_UP
+key 23   VOLUME_DOWN
+key 77   POWER
+key 0    0
+key 1    1
+key 2    2
+key 3    3
+key 4    4
+key 5    5
+key 6    6
+key 7    7
+key 8    8
+key 9    9
+key 67   VOLUME_MUTE
+key 71   MOUSE
+key 12   DEL
+key 83   APP_VIDEO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4cb3.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4cb3.kl
new file mode 100755
index 0000000..499b1c7
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_4cb3.kl
@@ -0,0 +1,53 @@
+key 197   BACK
+#key 93   MENU
+#key 13   SEARCH
+key 206   DPAD_CENTER
+key 210   DPAD_DOWN
+key 202   DPAD_UP
+key 136   HOME
+key 153   DPAD_LEFT
+key 193   DPAD_RIGHT
+key 128   VOLUME_UP
+key 129   VOLUME_DOWN
+key 220   POWER
+key 135   0
+key 146   1
+key 147   2
+key 204   3
+key 142   4
+key 143   5
+key 200   6
+key 138   7
+key 139   8
+key 196   9
+
+key 149   MEDIA_PLAY_PAUSE
+#key 19   MEDIA_STOP
+key 221   MEDIA_PREVIOUS
+key 140   MEDIA_NEXT
+key 157   MEDIA_REWIND
+key 158   MEDIA_FAST_FORWARD
+key 156   VOLUME_MUTE
+#key 4    TV_SYSTEM
+#key 70   SUBTITLE
+key 152   AUDIO
+key 141   SETTINGS
+key 205   PROG_RED
+key 195   PROG_BLUE
+key 145   PROG_GREEN
+key 131   PROG_YELLOW
+#key 5    HELP
+key 155   FAVOURITE
+key 214   LOOP
+key 130   EXPAND
+#key 12   ZOOM_IN
+#key 88   ZOOM_OUT
+#key 27   MOUSE
+#key 84   MOVIE
+#key 91   APPS
+#key 23   BROWSER
+#key 16   INFO
+key 133   CHANNEL_UP
+key 134   CHANNEL_DOWN
+key 208   POUND
+key 218   STAR
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_7f80.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_7f80.kl
new file mode 100755
index 0000000..eb059d7
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_7f80.kl
@@ -0,0 +1,37 @@
+key 27  BACK WAKE_DROPPED
+key 73  MENU WAKE_DROPPED
+key 13  DPAD_CENTER WAKE_DROPPED
+key 40  DPAD_DOWN WAKE_DROPPED
+key 38  DPAD_UP WAKE_DROPPED
+key 83  HOME WAKE
+key 37  DPAD_LEFT WAKE_DROPPED
+key 39  DPAD_RIGHT WAKE_DROPPED
+key 78  VOLUME_UP WAKE
+key 86  VOLUME_DOWN WAKE
+key 81  POWER WAKE
+key 48  0 WAKE
+key 49  1 WAKE
+key 50  2 WAKE
+key 51  3 WAKE
+key 52  4 WAKE
+key 53  5 WAKE
+key 54  6 WAKE
+key 55  7 WAKE
+key 56  8 WAKE
+key 57  9 WAKE
+key 77  VOLUME_MUTE WAKE
+key 09  PROG_RED WAKE
+key 17  PROG_GREEN WAKE
+key 84  PROG_YELLOW WAKE
+key 79  PROG_BLUE WAKE
+key 187  MEDIA_NEXT WAKE
+key 189  MEDIA_PREVIOUS WAKE
+#key 83  MEDIA_PLAY_PAUSE
+key 68  DEL WAKE
+key 82  MOUSE WAKE
+key 88  PERIOD WAKE
+key 28  ENTER WAKE
+#key 205 TV WAKE
+#key 145 MOVIE WAKE
+#key 131 APPS WAKE
+#key 195 FAVOURITE WAKE
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_9f00.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_9f00.kl
new file mode 100755
index 0000000..220e312
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_9f00.kl
@@ -0,0 +1,48 @@
+key 79   BACK
+key 22   MENU
+key 13   SEARCH
+key 2    DPAD_CENTER
+key 10   DPAD_DOWN
+key 67   DPAD_UP
+key 71   HOME
+key 6    DPAD_LEFT
+key 14   DPAD_RIGHT
+key 0    VOLUME_UP
+key 93   VOLUME_DOWN
+key 87   POWER
+key 90   0
+key 26   1
+key 1    2
+key 69   3
+key 89   4
+key 77   5
+key 64   6
+key 82   7
+key 83   8
+key 65   9
+key 80   MEDIA_PLAY_PAUSE
+key 19   MEDIA_STOP
+key 15   MEDIA_PREVIOUS
+key 11   MEDIA_NEXT
+key 7    MEDIA_REWIND
+key 3    MEDIA_FAST_FORWARD
+key 92   VOLUME_MUTE
+key 4    TV_SYSTEM
+key 70   SUBTITLE
+key 68   AUDIO
+key 9    SETTINGS
+key 85   PROG_RED
+key 72   PROG_BLUE
+key 78   PROG_GREEN
+key 73   PROG_YELLOW
+key 5    HELP
+key 21   FAVOURITE
+key 8    LOOP
+key 20   EXPAND
+key 12   ZOOM_IN
+key 88   ZOOM_OUT
+key 17   MOUSE
+key 84   MOVIE
+key 91   APPS
+key 23   BROWSER
+key 16   INFO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ba04.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ba04.kl
new file mode 100755
index 0000000..0c0d47d
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ba04.kl
@@ -0,0 +1 @@
+key  06  F10  WAKE_DROPPED
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_bc00.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_bc00.kl
new file mode 100755
index 0000000..4e93864
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_bc00.kl
@@ -0,0 +1,34 @@
+key 72   BACK
+key 20   MENU
+key 21   DPAD_CENTER
+key 23   DPAD_DOWN
+key 22   DPAD_UP
+key 148  HOME
+key 25   DPAD_LEFT
+key 24   DPAD_RIGHT
+key 68   VOLUME_UP
+key 67   VOLUME_DOWN
+key 13   POWER
+key 0    0
+key 1    1
+key 2    2
+key 3    3
+key 4    4
+key 5    5
+key 6    6
+key 7    7
+key 8    8
+key 9    9
+key 78   MEDIA_PLAY_PAUSE
+key 90   MEDIA_STOP
+key 14   VOLUME_MUTE
+key 27   TV_SYSTEM
+key 152  SETTINGS
+key 98   PROG_RED
+key 101  PROG_BLUE
+key 99   PROG_GREEN
+key 100  PROG_YELLOW
+key 15   MENU
+key 77   HISENSE_FAC_NEC_DMP
+
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_dd22.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_dd22.kl
new file mode 100755
index 0000000..afdc9e9
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_dd22.kl
@@ -0,0 +1,47 @@
+key  130  HOME
+key  149  BACK
+key  135  0
+key  146  1
+key  147  2
+key  204  3
+key  142  4
+key  143  5
+key  200  6
+key  138  7
+key  139  8
+key  196  9
+key  202  DPAD_UP
+key  210  DPAD_DOWN
+key  153  DPAD_LEFT
+key  193  DPAD_RIGHT
+key  206  DPAD_CENTER
+key  128  VOLUME_UP
+key  129  VOLUME_DOWN
+key  220  POWER
+key  197  MENU
+key  217  MEDIA_PLAY_PAUSE
+key  132  MEDIA_FAST_FORWARD
+key  137  MEDIA_REWIND
+#key  89  MEDIA_REWIND
+key  156  MUTE
+key  221  PAGE_UP
+key  140  PAGE_DOWN
+key  150  MEDIA_STOP
+key  125  FORWARD
+key  164  VOLUME_MUTE
+key  133  CHANNEL_UP
+key  134  CHANNEL_DOWN
+key  141  SETTINGS
+#set181 =app_firstpage
+key  136  AVR_POWER
+#set182 =Fast switching
+key  214  AVR_INPUT
+key  205  PROG_RED
+key  145  PROG_GREEN
+key  131  PROG_YELLOW
+key  195  PROG_BLUE
+#set209 =Switch the channel
+key  152  MUSIC
+key  218  POUND
+key  208  STAR
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fb04.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fb04.kl
new file mode 100755
index 0000000..d0129e8
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fb04.kl
@@ -0,0 +1,48 @@
+key 10    BACK
+key 93    MENU
+#key 13   SEARCH
+key 92    DPAD_CENTER
+key 29    DPAD_DOWN
+key 68    DPAD_UP
+key 31    HOME
+key 28    DPAD_LEFT
+key 72    DPAD_RIGHT
+key 69    VOLUME_UP
+key 25    VOLUME_DOWN
+key 26    POWER
+key 71    0
+key 19    1
+key 16    2
+key 17    3
+key 15    4
+key 12    5
+key 13    6
+key 11    7
+key 8     8
+key 9     9
+key 80    MEDIA_PLAY_PAUSE
+#key 19   MEDIA_STOP
+#key 11   MEDIA_PREVIOUS
+#key 15   MEDIA_NEXT
+key 7     MEDIA_REWIND
+key 3     MEDIA_FAST_FORWARD
+key 35    VOLUME_MUTE
+key 4     TV_SYSTEM
+key 70    SUBTITLE
+#key 68   AUDIO
+key 83    SETTINGS
+key 85    PROG_RED
+#key 72   PROG_BLUE
+key 78    PROG_GREEN
+key 73    PROG_YELLOW
+key 5     HELP
+key 21    FAVOURITE
+#key 8    LOOP
+key 20    EXPAND
+#key 12   ZOOM_IN
+key 88    ZOOM_OUT
+key 27    MOUSE
+key 84    MOVIE
+key 91    APPS
+key 23    BROWSER
+#key 16   INFO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fc00.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fc00.kl
new file mode 100755
index 0000000..089f31e
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fc00.kl
@@ -0,0 +1,12 @@
+key 93   F1
+key 66   F2
+key 86   F3
+key 72   F4
+key 83   F5
+key 29   BACK
+key 79   F7
+key 71   HISENSE_FAC_NEC_OK
+key 10   HISENSE_FAC_NEC_MAC
+key 78   HISENSE_FAC_NEC_IP
+key 0    HISENSE_FAC_NEC_M
+key 21   HISENSE_FAC_NEC_AGING
\ No newline at end of file
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01.kl
new file mode 100755
index 0000000..dd92176
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01.kl
@@ -0,0 +1,33 @@
+key 25   BACK
+key 76   MENU
+key 19   DPAD_CENTER
+key 26   DPAD_DOWN
+key 22   DPAD_UP
+key 17   HOME
+key 81   DPAD_LEFT
+key 80   DPAD_RIGHT
+key 24   VOLUME_UP
+key 16   VOLUME_DOWN
+key 15   APPS
+key 67   SETTINGS
+key 64   POWER
+key 1    0
+key 78   1
+key 13   2
+key 12   3
+key 74   4
+key 9    5
+key 8    6
+key 70   7
+key 5    8
+key 4    9
+key 65   VOLUME_MUTE
+key 0    MOUSE
+key 213  CALCULATOR
+key 75   MEDIA_PREVIOUS
+key 79   MEDIA_NEXT
+key 66   DEL
+key 02   CALENDAR
+key 33   ZOOM_IN
+key 34   ZOOM_OUT
+key 35   INFO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01_petrel.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01_petrel.kl
new file mode 100755
index 0000000..d965127
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_fe01_petrel.kl
@@ -0,0 +1,33 @@
+key 25   BACK
+key 0    MENU
+key 19   DPAD_CENTER
+key 26   DPAD_DOWN
+key 22   DPAD_UP
+key 17   HOME
+key 81   DPAD_LEFT
+key 80   DPAD_RIGHT
+key 24   VOLUME_UP
+key 16   VOLUME_DOWN
+key 15   APPS
+key 67   CONTACTS
+key 64   POWER
+key 1    0
+key 78   1
+key 13   2
+key 12   3
+key 74   4
+key 9    5
+key 8    6
+key 70   7
+key 5    8
+key 4    9
+key 65   VOLUME_MUTE
+key 76   MOUSE
+key 213  CALCULATOR
+key 75   MEDIA_PREVIOUS
+key 79   MEDIA_NEXT
+key 66   DEL
+key 02   CALENDAR
+key 33   ZOOM_IN
+key 34   ZOOM_OUT
+key 35   INFO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ff00.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ff00.kl
new file mode 100755
index 0000000..6ebb150
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_ir_ff00.kl
@@ -0,0 +1,35 @@
+key 64   BACK
+key 4    MENU
+key 85   DPAD_CENTER
+key 22   DPAD_DOWN
+key 70   DPAD_UP
+key 78   HOME
+key 71   DPAD_LEFT
+key 21   DPAD_RIGHT
+key 20   VOLUME_UP
+key 16   VOLUME_DOWN
+key 24   POWER
+key 29   0
+key 15   1
+key 17   2
+key 18   3
+key 76   4
+key 88   5
+key 27   6
+key 23   7
+key 77   8
+key 10   9
+key 91   VOLUME_MUTE
+key 90   PROG_RED
+key 2    PROG_BLUE
+key 13   PROG_GREEN
+key 6    PROG_YELLOW
+key 80   MEDIA_NEXT
+key 82   MEDIA_PREVIOUS
+key 79   SETTINGS
+key 30   DEL
+key 28   ENTER
+key 205  TV
+key 145  MOVIE
+key 131  APPS
+key 195  FAVOURITE
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_rc5_ir_04.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_rc5_ir_04.kl
new file mode 100755
index 0000000..65d93ec
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/customer_rc5_ir_04.kl
@@ -0,0 +1,7 @@
+key 20   DPAD_DOWN
+key 14   DPAD_UP
+key 16   DPAD_LEFT
+key 18   DPAD_RIGHT
+key 1    POWER
+key 17   STAR
+key 14   BACK
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-recovery.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-recovery.kl
new file mode 100755
index 0000000..857aefa
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-recovery.kl
@@ -0,0 +1,19 @@
+key  102  HOME
+key  158  BACK
+key  11  0
+key  2  1
+key  3  2
+key  4  3
+key  5  4
+key  6  5
+key  7  6
+key  8  7
+key  9  8
+key  10  9
+key  103  DPAD_UP
+key  108  DPAD_DOWN
+key  105  DPAD_LEFT
+key  106  DPAD_RIGHT
+key  28  DPAD_CENTER
+key  114  VOLUME_DOWN
+key  115  VOLUME_UP
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-uinput.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-uinput.kl
new file mode 100755
index 0000000..38a16a3
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir-uinput.kl
@@ -0,0 +1,244 @@
+key  1  SOFT_LEFT
+key  2  SOFT_RIGHT
+key  3  HOME
+key  4  BACK
+key  5  CALL
+key  6  ENDCALL
+key  7  0
+key  8  1
+key  9  2
+key  10  3
+key  11  4
+key  12  5
+key  13  6
+key  14  7
+key  15  8
+key  16  9
+key  17  STAR
+key  18  POUND
+key  19  DPAD_UP
+key  20  DPAD_DOWN
+key  21  DPAD_LEFT
+key  22  DPAD_RIGHT
+key  23  DPAD_CENTER
+key  24  VOLUME_UP
+key  25  VOLUME_DOWN
+key  26  SCROLL_LOCK
+key  27  CAMERA
+key  28  CLEAR
+key  29  A
+key  30  B
+key  31  C
+key  32  D
+key  33  E
+key  34  F
+key  35  G
+key  36  H
+key  37  I
+key  38  J
+key  39  K
+key  40  L
+key  41  M
+key  42  N
+key  43  O
+key  44  P
+key  45  Q
+key  46  R
+key  47  S
+key  48  T
+key  49  U
+key  50  V
+key  51  W
+key  52  X
+key  53  Y
+key  54  Z
+key  55  COMMA
+key  56  PERIOD
+key  57  ALT_LEFT
+key  58  ALT_RIGHT
+key  59  SHIFT_LEFT
+key  60  SHIFT_RIGHT
+key  61  TAB
+key  62  SPACE
+key  63  SYM
+key  64  EXPLORER
+key  65  ENVELOPE
+key  66  ENTER
+key  67  DEL
+key  68  GRAVE
+key  69  MINUS
+key  70  EQUALS
+key  71  LEFT_BRACKET
+key  72  RIGHT_BRACKET
+key  73  BACKSLASH
+key  74  SEMICOLON
+key  75  APOSTROPHE
+key  76  SLASH
+key  77  AT
+key  78  NUM
+key  79  HEADSETHOOK
+key  80  FOCUS
+key  81  PLUS
+key  82  MENU
+key  83  NOTIFICATION
+key  84  SEARCH
+key  85  MEDIA_PLAY_PAUSE
+key  86  MEDIA_STOP
+key  87  MEDIA_NEXT
+key  88  MEDIA_PREVIOUS
+key  89  MEDIA_REWIND
+key  90  MEDIA_FAST_FORWARD
+key  91  MUTE
+key  92  PAGE_UP
+key  93  PAGE_DOWN
+key  94  PICTSYMBOLS
+key  95  SWITCH_CHARSET
+# ir keyboard dont need gamepad key, fix kodi can not use ir keyboard
+#key  96  BUTTON_A
+#key  97  BUTTON_B
+#key  98  BUTTON_C
+#key  99  BUTTON_X
+#key  100  BUTTON_Y
+#key  101  BUTTON_Z
+#key  102  BUTTON_L1
+#key  103  BUTTON_R1
+#key  104  BUTTON_L2
+#key  105  BUTTON_R2
+#key  106  BUTTON_THUMBL
+#key  107  BUTTON_THUMBR
+#key  108  BUTTON_START
+#key  109  BUTTON_SELECT
+#key  110  BUTTON_MODE
+key  111  ESCAPE
+key  112  FORWARD_DEL
+key  113  CTRL_LEFT
+key  114  CTRL_RIGHT
+key  115  CAPS_LOCK
+key  116  POWER
+key  117  META_LEFT
+key  118  META_RIGHT
+key  119  FUNCTION
+key  120  SYSRQ
+key  121  BREAK
+key  122  MOVE_HOME
+key  123  MOVE_END
+key  124  INSERT
+key  125  FORWARD
+key  126  MEDIA_PLAY
+key  127  MEDIA_PAUSE
+key  128  MEDIA_CLOSE
+key  129  MEDIA_EJECT
+key  130  MEDIA_RECORD
+key  131  F1
+key  132  F2
+key  133  F3
+key  134  F4
+key  135  F5
+key  136  F6
+key  137  F7
+key  138  F8
+key  139  F9
+key  140  F10
+key  141  F11
+key  142  F12
+key  143  NUM_LOCK
+key  144  NUMPAD_0
+key  145  NUMPAD_1
+key  146  NUMPAD_2
+key  147  NUMPAD_3
+key  148  NUMPAD_4
+key  149  NUMPAD_5
+key  150  NUMPAD_6
+key  151  NUMPAD_7
+key  152  NUMPAD_8
+key  153  NUMPAD_9
+key  154  NUMPAD_DIVIDE
+key  155  NUMPAD_MULTIPLY
+key  156  NUMPAD_SUBTRACT
+key  157  NUMPAD_ADD
+key  158  NUMPAD_DOT
+key  159  NUMPAD_COMMA
+key  160  NUMPAD_ENTER
+key  161  NUMPAD_EQUALS
+key  162  NUMPAD_LEFT_PAREN
+key  163  NUMPAD_RIGHT_PAREN
+key  164  VOLUME_MUTE
+key  165  INFO
+key  166  CHANNEL_UP
+key  167  CHANNEL_DOWN
+key  168  ZOOM_IN
+key  169  ZOOM_OUT
+key  170  TV
+key  171  WINDOW
+key  172  GUIDE
+key  173  DVR
+key  174  BOOKMARK
+key  175  CAPTIONS
+key  176  SETTINGS
+key  177  TV_POWER
+key  178  TV_INPUT
+key  179  STB_INPUT
+key  180  STB_POWER
+key  181  AVR_POWER
+key  182  AVR_INPUT
+key  183  PROG_RED
+key  184  PROG_GREEN
+key  185  PROG_YELLOW
+key  186  PROG_BLUE
+key  187  APP_SWITCH
+key  188  BUTTON_1
+key  189  BUTTON_2
+key  190  BUTTON_3
+key  191  BUTTON_4
+key  192  BUTTON_5
+key  193  BUTTON_6
+key  194  BUTTON_7
+key  195  BUTTON_8
+key  196  BUTTON_9
+key  197  BUTTON_10
+key  198  BUTTON_11
+key  199  BUTTON_12
+key  200  BUTTON_13
+key  201  BUTTON_14
+key  202  BUTTON_15
+key  203  BUTTON_16
+key  204  LANGUAGE_SWITCH
+key  205  MANNER_MODE
+key  206  3D_MODE
+key  207  CONTACTS
+key  208  CALENDAR
+key  209  MUSIC
+key  210  CALCULATOR
+key  211  ZENKAKU_HANKAKU
+key  212  EISU
+key  213  MUHENKAN
+key  214  HENKAN
+key  215  KATAKANA_HIRAGANA
+key  216  YEN
+key  217  RO
+key  218  KANA
+key  219  ASSIST
+key  220  BRIGHTNESS_DOWN
+key  221  BRIGHTNESS_UP
+key  222  MEDIA_AUDIO_TRACK
+key  223  TV_SYSTEM
+key  224  GOTO
+key  225  SUBTITLE
+key  226  AUDIO
+key  227  ZOOM
+key  228  HELP
+key  229  FAVOURITE
+key  230  LOOP
+key  231  EXPAND
+key  232  MOUSE
+key  233  MOVIE
+key  234  APPS
+key  235  BROWSER
+key  236  SCREENSHOT
+#key	 237  HISENSE_FAC_NEC_DMP
+#key	 238  HISENSE_FAC_NEC_OK
+#key	 239  HISENSE_FAC_NEC_MAC
+#key	 240  HISENSE_FAC_NEC_IP
+#key	 241  HISENSE_FAC_NEC_M
+#key	 242  HISENSE_FAC_NEC_AGING
+key  289  APP_VIDEO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir.kl
new file mode 100755
index 0000000..38a16a3
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/sunxi-ir.kl
@@ -0,0 +1,244 @@
+key  1  SOFT_LEFT
+key  2  SOFT_RIGHT
+key  3  HOME
+key  4  BACK
+key  5  CALL
+key  6  ENDCALL
+key  7  0
+key  8  1
+key  9  2
+key  10  3
+key  11  4
+key  12  5
+key  13  6
+key  14  7
+key  15  8
+key  16  9
+key  17  STAR
+key  18  POUND
+key  19  DPAD_UP
+key  20  DPAD_DOWN
+key  21  DPAD_LEFT
+key  22  DPAD_RIGHT
+key  23  DPAD_CENTER
+key  24  VOLUME_UP
+key  25  VOLUME_DOWN
+key  26  SCROLL_LOCK
+key  27  CAMERA
+key  28  CLEAR
+key  29  A
+key  30  B
+key  31  C
+key  32  D
+key  33  E
+key  34  F
+key  35  G
+key  36  H
+key  37  I
+key  38  J
+key  39  K
+key  40  L
+key  41  M
+key  42  N
+key  43  O
+key  44  P
+key  45  Q
+key  46  R
+key  47  S
+key  48  T
+key  49  U
+key  50  V
+key  51  W
+key  52  X
+key  53  Y
+key  54  Z
+key  55  COMMA
+key  56  PERIOD
+key  57  ALT_LEFT
+key  58  ALT_RIGHT
+key  59  SHIFT_LEFT
+key  60  SHIFT_RIGHT
+key  61  TAB
+key  62  SPACE
+key  63  SYM
+key  64  EXPLORER
+key  65  ENVELOPE
+key  66  ENTER
+key  67  DEL
+key  68  GRAVE
+key  69  MINUS
+key  70  EQUALS
+key  71  LEFT_BRACKET
+key  72  RIGHT_BRACKET
+key  73  BACKSLASH
+key  74  SEMICOLON
+key  75  APOSTROPHE
+key  76  SLASH
+key  77  AT
+key  78  NUM
+key  79  HEADSETHOOK
+key  80  FOCUS
+key  81  PLUS
+key  82  MENU
+key  83  NOTIFICATION
+key  84  SEARCH
+key  85  MEDIA_PLAY_PAUSE
+key  86  MEDIA_STOP
+key  87  MEDIA_NEXT
+key  88  MEDIA_PREVIOUS
+key  89  MEDIA_REWIND
+key  90  MEDIA_FAST_FORWARD
+key  91  MUTE
+key  92  PAGE_UP
+key  93  PAGE_DOWN
+key  94  PICTSYMBOLS
+key  95  SWITCH_CHARSET
+# ir keyboard dont need gamepad key, fix kodi can not use ir keyboard
+#key  96  BUTTON_A
+#key  97  BUTTON_B
+#key  98  BUTTON_C
+#key  99  BUTTON_X
+#key  100  BUTTON_Y
+#key  101  BUTTON_Z
+#key  102  BUTTON_L1
+#key  103  BUTTON_R1
+#key  104  BUTTON_L2
+#key  105  BUTTON_R2
+#key  106  BUTTON_THUMBL
+#key  107  BUTTON_THUMBR
+#key  108  BUTTON_START
+#key  109  BUTTON_SELECT
+#key  110  BUTTON_MODE
+key  111  ESCAPE
+key  112  FORWARD_DEL
+key  113  CTRL_LEFT
+key  114  CTRL_RIGHT
+key  115  CAPS_LOCK
+key  116  POWER
+key  117  META_LEFT
+key  118  META_RIGHT
+key  119  FUNCTION
+key  120  SYSRQ
+key  121  BREAK
+key  122  MOVE_HOME
+key  123  MOVE_END
+key  124  INSERT
+key  125  FORWARD
+key  126  MEDIA_PLAY
+key  127  MEDIA_PAUSE
+key  128  MEDIA_CLOSE
+key  129  MEDIA_EJECT
+key  130  MEDIA_RECORD
+key  131  F1
+key  132  F2
+key  133  F3
+key  134  F4
+key  135  F5
+key  136  F6
+key  137  F7
+key  138  F8
+key  139  F9
+key  140  F10
+key  141  F11
+key  142  F12
+key  143  NUM_LOCK
+key  144  NUMPAD_0
+key  145  NUMPAD_1
+key  146  NUMPAD_2
+key  147  NUMPAD_3
+key  148  NUMPAD_4
+key  149  NUMPAD_5
+key  150  NUMPAD_6
+key  151  NUMPAD_7
+key  152  NUMPAD_8
+key  153  NUMPAD_9
+key  154  NUMPAD_DIVIDE
+key  155  NUMPAD_MULTIPLY
+key  156  NUMPAD_SUBTRACT
+key  157  NUMPAD_ADD
+key  158  NUMPAD_DOT
+key  159  NUMPAD_COMMA
+key  160  NUMPAD_ENTER
+key  161  NUMPAD_EQUALS
+key  162  NUMPAD_LEFT_PAREN
+key  163  NUMPAD_RIGHT_PAREN
+key  164  VOLUME_MUTE
+key  165  INFO
+key  166  CHANNEL_UP
+key  167  CHANNEL_DOWN
+key  168  ZOOM_IN
+key  169  ZOOM_OUT
+key  170  TV
+key  171  WINDOW
+key  172  GUIDE
+key  173  DVR
+key  174  BOOKMARK
+key  175  CAPTIONS
+key  176  SETTINGS
+key  177  TV_POWER
+key  178  TV_INPUT
+key  179  STB_INPUT
+key  180  STB_POWER
+key  181  AVR_POWER
+key  182  AVR_INPUT
+key  183  PROG_RED
+key  184  PROG_GREEN
+key  185  PROG_YELLOW
+key  186  PROG_BLUE
+key  187  APP_SWITCH
+key  188  BUTTON_1
+key  189  BUTTON_2
+key  190  BUTTON_3
+key  191  BUTTON_4
+key  192  BUTTON_5
+key  193  BUTTON_6
+key  194  BUTTON_7
+key  195  BUTTON_8
+key  196  BUTTON_9
+key  197  BUTTON_10
+key  198  BUTTON_11
+key  199  BUTTON_12
+key  200  BUTTON_13
+key  201  BUTTON_14
+key  202  BUTTON_15
+key  203  BUTTON_16
+key  204  LANGUAGE_SWITCH
+key  205  MANNER_MODE
+key  206  3D_MODE
+key  207  CONTACTS
+key  208  CALENDAR
+key  209  MUSIC
+key  210  CALCULATOR
+key  211  ZENKAKU_HANKAKU
+key  212  EISU
+key  213  MUHENKAN
+key  214  HENKAN
+key  215  KATAKANA_HIRAGANA
+key  216  YEN
+key  217  RO
+key  218  KANA
+key  219  ASSIST
+key  220  BRIGHTNESS_DOWN
+key  221  BRIGHTNESS_UP
+key  222  MEDIA_AUDIO_TRACK
+key  223  TV_SYSTEM
+key  224  GOTO
+key  225  SUBTITLE
+key  226  AUDIO
+key  227  ZOOM
+key  228  HELP
+key  229  FAVOURITE
+key  230  LOOP
+key  231  EXPAND
+key  232  MOUSE
+key  233  MOVIE
+key  234  APPS
+key  235  BROWSER
+key  236  SCREENSHOT
+#key	 237  HISENSE_FAC_NEC_DMP
+#key	 238  HISENSE_FAC_NEC_OK
+#key	 239  HISENSE_FAC_NEC_MAC
+#key	 240  HISENSE_FAC_NEC_IP
+#key	 241  HISENSE_FAC_NEC_M
+#key	 242  HISENSE_FAC_NEC_AGING
+key  289  APP_VIDEO
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/virtual-remote.kl b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/virtual-remote.kl
new file mode 100755
index 0000000..9e02ec2
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/keylayout/virtual-remote.kl
@@ -0,0 +1,26 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+key 217   SEARCH
+
+key 158   BACK
+key 172   HOME
+key 164   MEDIA_PLAY_PAUSE
+
+key 103   DPAD_UP
+key 108   DPAD_DOWN
+key 105   DPAD_LEFT
+key 106   DPAD_RIGHT
+key 353   DPAD_CENTER
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/Android.bp b/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/Android.bp
new file mode 100755
index 0000000..70d5f20
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/Android.bp
@@ -0,0 +1,25 @@
+cc_library_shared {
+    name: "libmultiirservice",
+
+    srcs: ["IMultiirService.cpp"],
+
+    shared_libs: [
+        "libcutils",
+        "libutils",
+        "libbinder",
+        "liblog",
+        "libandroid_runtime",
+    ],
+
+    export_include_dirs: [
+        ".",
+    ],
+
+    host_ldlibs: ["-llog"],
+
+}
+
+cc_library_headers {
+    name: "libmultiirservice_headers",
+    export_include_dirs: ["."],
+}
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.cpp b/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.cpp
new file mode 100755
index 0000000..d69bc04
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.cpp
@@ -0,0 +1,164 @@
+#undef NDEBUG
+#define LOG_TAG "MultiirService"
+
+#include <utils/Log.h>
+#include <memory.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include "IMultiirService.h"
+
+#define DEBUG true
+
+namespace android {
+
+enum {
+    ENTERMOUSEMODE = IBinder::FIRST_CALL_TRANSACTION,
+    EXITMOUSEMODE = ENTERMOUSEMODE + 1,
+    GETDEFAULTPOINTERSPEED = EXITMOUSEMODE + 1,
+    GETDEFAULTSTEPDISTANCE = GETDEFAULTPOINTERSPEED + 1,
+    SETPOINTERSPEED = GETDEFAULTSTEPDISTANCE + 1,
+    SETSTEPDISTANCE = SETPOINTERSPEED + 1,
+    RESET = SETSTEPDISTANCE + 1,
+    REPORTMOUSEKEYEVENT = RESET + 1,
+};
+
+class BpMultiirService : public BpInterface<IMultiirService> {
+
+public:
+    BpMultiirService(const sp<IBinder>& impl)
+        : BpInterface<IMultiirService>(impl){
+    }
+
+    int enterMouseMode(void) {
+        if (DEBUG) {
+            ALOGD("IMultiirService enter virtual mouse mode");
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        remote()->transact(ENTERMOUSEMODE, data, &reply);
+        return reply.readInt32();
+    }
+
+    int exitMouseMode(void) {
+        if (DEBUG) {
+            ALOGD("IMultiirService exit virtual mouse mode");
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        remote()->transact(EXITMOUSEMODE, data, &reply);
+        return reply.readInt32();
+    }
+
+    int getDefaultPointerSpeed(void) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        remote()->transact(GETDEFAULTPOINTERSPEED, data, &reply);
+        return reply.readInt32();
+    }
+
+    int getDefaultStepDistance(void) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        remote()->transact(GETDEFAULTSTEPDISTANCE, data, &reply);
+        return reply.readInt32();
+    }
+
+    int reset(void) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        remote()->transact(RESET, data, &reply);
+        return reply.readInt32();
+    }
+
+    int setPointerSpeed(int ms) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        data.writeInt32(ms);
+        remote()->transact(SETPOINTERSPEED, data, &reply);
+        return reply.readInt32();
+    }
+
+    int setStepDistance(int px) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        data.writeInt32(px);
+        remote()->transact(SETSTEPDISTANCE, data, &reply);
+        return reply.readInt32();
+    }
+    int reportMouseKeyEvent(int scan_code, int key_state) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMultiirService::getInterfaceDescriptor());
+        data.writeInt32(scan_code);
+        data.writeInt32(key_state);
+        remote()->transact(REPORTMOUSEKEYEVENT, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MultiirService, "com.softwinner.IMultiirService");
+
+status_t BnMultiirService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch (code) {
+        case ENTERMOUSEMODE :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            reply->writeInt32(enterMouseMode());
+            return NO_ERROR;
+        }
+		case EXITMOUSEMODE :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            reply->writeInt32(exitMouseMode());
+            return NO_ERROR;
+        }
+        case GETDEFAULTPOINTERSPEED :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            reply->writeInt32(getDefaultPointerSpeed());
+            return NO_ERROR;
+        }
+        case GETDEFAULTSTEPDISTANCE :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            reply->writeInt32(getDefaultStepDistance());
+            return NO_ERROR;
+        }
+        case SETPOINTERSPEED :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            int speed = data.readInt32();
+            reply->writeInt32(setPointerSpeed(speed));
+            return NO_ERROR;
+        }
+        case SETSTEPDISTANCE :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            int distance = data.readInt32();
+            reply->writeInt32(setStepDistance(distance));
+            return NO_ERROR;
+        }
+        case RESET :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            reply->writeInt32(reset());
+            return NO_ERROR;
+        }
+        case REPORTMOUSEKEYEVENT :
+        {
+            CHECK_INTERFACE(IMultiitService, data, reply);
+            int scan_code = data.readInt32();
+            int key_state = data.readInt32();
+            reply->writeInt32(reportMouseKeyEvent(scan_code, key_state));
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+};
+
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.h b/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.h
new file mode 100755
index 0000000..85cceff
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/libmultiir/IMultiirService.h
@@ -0,0 +1,33 @@
+#ifndef ANDROID_IMULTIIRSERVICE_H
+#define ANDROID_IMULTIIRSERVICE_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+class IMultiirService : public IInterface {
+
+public:
+    DECLARE_META_INTERFACE(MultiirService);
+    virtual int enterMouseMode(void) = 0;
+    virtual int exitMouseMode(void) = 0;
+    virtual int getDefaultPointerSpeed(void) = 0;
+    virtual int getDefaultStepDistance(void) = 0;
+    virtual int setPointerSpeed(int ms) = 0;
+    virtual int setStepDistance(int px) = 0;
+    virtual int reset(void) = 0;
+    virtual int reportMouseKeyEvent(int scan_code, int key_state) = 0;
+};
+
+class BnMultiirService : public BnInterface<IMultiirService> {
+
+public:
+    virtual status_t  onTransact(uint32_t code, const Parcel& data,
+                                 Parcel* reply, uint32_t flags = 0);
+};
+};
+
+#endif
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/multiir.mk b/android/vendor/aw/homlet/hardware/input/multi_ir/multiir.mk
new file mode 100755
index 0000000..1fc4cbe
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/multiir.mk
@@ -0,0 +1,51 @@
+# utils, add multi_ir to recovery
+PRODUCT_PACKAGES += \
+	multi_ir \
+	multi_ir.recovery \
+	libmultiir_jni \
+	libmultiirservice \
+
+BASE_KL_COPY_LIST := virtual-remote.kl \
+	sunxi-ir-uinput.kl \
+	customer_rc5_ir_04.kl \
+
+BASE_KL_COPY_LIST += customer_ir_9f00.kl \
+	customer_ir_dd22.kl \
+	customer_ir_fb04.kl \
+	customer_ir_ff00.kl \
+	customer_ir_4cb3.kl \
+	customer_ir_bc00.kl \
+	customer_ir_fc00.kl \
+	customer_ir_2992.kl \
+	customer_ir_4040.kl \
+	customer_ir_ba04.kl \
+	customer_ir_7f80.kl
+
+SYSTEM_KL_COPY_LIST := $(BASE_KL_COPY_LIST) \
+	Vendor_000d_Product_3838.kl \
+	sunxi-ir.kl \
+
+RECOVERY_KL_COPY_LIST := $(BASE_KL_COPY_LIST) \
+	customer_ir_fe01.kl
+
+SUNXI_VENDOR_KL_DIR := vendor/aw/homlet/hardware/input/multi_ir/keylayout
+SYSTEM_KL_DIR := system/usr/keylayout
+RECOVERY_KL_DIR := /root/system/usr/keylayout
+
+PRODUCT_COPY_FILES += $(foreach f,$(SYSTEM_KL_COPY_LIST),$(SUNXI_VENDOR_KL_DIR)/$(f):$(SYSTEM_KL_DIR)/$(f))
+
+# H6 use different ir keyboard
+ifeq ($(TARGET_BOARD_PLATFORM),petrel)
+PRODUCT_COPY_FILES += \
+	$(SUNXI_VENDOR_KL_DIR)/customer_ir_fe01_petrel.kl:$(SYSTEM_KL_DIR)/customer_ir_fe01.kl
+
+else
+PRODUCT_COPY_FILES += \
+	$(SUNXI_VENDOR_KL_DIR)/customer_ir_fe01.kl:$(SYSTEM_KL_DIR)/customer_ir_fe01.kl
+
+endif
+
+# recovery support multi_ir
+PRODUCT_COPY_FILES += $(foreach f,$(RECOVERY_KL_COPY_LIST),$(SUNXI_VENDOR_KL_DIR)/$(f):$(RECOVERY_KL_DIR)/$(f))
+PRODUCT_COPY_FILES += \
+	$(SUNXI_VENDOR_KL_DIR)/sunxi-ir-recovery.kl:$(RECOVERY_KL_DIR)/sunxi-ir.kl
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/file_contexts b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/file_contexts
new file mode 100755
index 0000000..1065fad
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/file_contexts
@@ -0,0 +1 @@
+/system/bin/multi_ir      u:object_r:multi_ir_exec:s0
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/multi_ir.te b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/multi_ir.te
new file mode 100755
index 0000000..0c3cd99
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/multi_ir.te
@@ -0,0 +1,24 @@
+type multi_ir, domain;
+type multi_ir_exec, exec_type, file_type, system_file_type;
+init_daemon_domain(multi_ir)
+typeattribute multi_ir coredomain;
+type proc_ir, fs_type, proc_type;
+
+binder_use(multi_ir)
+binder_service(multi_ir)
+allow multi_ir servicemanager:binder { call transfer };
+allow multi_ir softwinner_service:service_manager { add find };
+allow multi_ir proc_ir:file rw_file_perms;
+#allow multi_ir sysfs:file write;
+allow multi_ir sysfs_devices_system_cpu:file write;
+allow multi_ir rootfs:dir {open read};
+allow multi_ir rootfs:file {open read execute getattr };
+allow multi_ir rootfs:file {entrypoint};
+#allow multi_ir self:capability {dac_override net_admin};
+allow multi_ir self:netlink_kobject_uevent_socket {create setopt bind read};
+allow multi_ir uhid_device:chr_file {write open read ioctl};
+allow multi_ir input_device:dir {write open read search getattr};
+allow multi_ir input_device:chr_file {write open read ioctl};
+allow multi_ir property_socket:sock_file {write};
+allow multi_ir init:unix_stream_socket connectto;
+allow multi_ir self:capability { net_admin };
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/private/service_contexts b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/private/service_contexts
new file mode 100755
index 0000000..9fb1c4c
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/private/service_contexts
@@ -0,0 +1 @@
+softwinner\.multiir                       u:object_r:multiir_service:s0
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/service.te b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/service.te
new file mode 100755
index 0000000..50d7646
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/service.te
@@ -0,0 +1 @@
+type multiir_service, system_api_service, system_server_service, service_manager_type;
diff --git a/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/system_server.te b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/system_server.te
new file mode 100755
index 0000000..c0e53e4
--- /dev/null
+++ b/android/vendor/aw/homlet/hardware/input/multi_ir/sepolicy/system_server.te
@@ -0,0 +1 @@
+allow system_server multiir_service:service_manager { add find };
diff --git a/android/vendor/aw/homlet/homlet.mk b/android/vendor/aw/homlet/homlet.mk
new file mode 100755
index 0000000..bdcc156
--- /dev/null
+++ b/android/vendor/aw/homlet/homlet.mk
@@ -0,0 +1 @@
+$(call inherit-product-if-exists, vendor/aw/homlet/hardware/input/multi_ir/multiir.mk)
diff --git a/longan/device/config/chips/a133/configs/c3/board.dts b/longan/device/config/chips/a133/configs/c3/board.dts
index 55a6d3f..f9a0eac 100755
--- a/longan/device/config/chips/a133/configs/c3/board.dts
+++ b/longan/device/config/chips/a133/configs/c3/board.dts
@@ -370,10 +370,10 @@
 			pinctrl-1 = <&twi3_pins_b>;
 			status = "okay";
 			// RTC
-                        pcf8563@51 {
-                                compatible = "haoyu,hym8563";
-                                reg = <0x51>;
-                                status = "okay";
+			pcf8563@51 {
+					compatible = "haoyu,hym8563";
+					reg = <0x51>;
+					status = "okay";
 			};
 		};
 
@@ -1339,7 +1339,7 @@
 
                	sysled {
                        	label = "sysled";
-                       	gpios = <&r_pio PL 11 1 0 1 1>;
+                       	gpios = <&r_pio PL 10 1 0 1 1>;
 			linux,default_trigger = "heartbeat";
                	};
 
@@ -1355,6 +1355,19 @@
 	cpu-supply = <&reg_dcdc2>;
 };
 
+&s_cir0 {
+	status = "okay";
+
+	s_cir0_used = <1>;
+	ir_power_key_code0 = <0x4d>;
+	ir_addr_code0 = <0x4040>;
+	ir_power_key_code1 = <0x51>;
+	ir_addr_code1 = <0x7f80>;
+	ir_power_key_code2 = <0x1c>;
+	ir_addr_code2 = <0xdf00>;
+	wakeup-source;
+};
+
 //#include "lcd-lvds-21-1920-1080.dtsi"
 #include "lcd-lvds-7-1024-600.dtsi"
 //#include "lcd-mipi-10-800-1280.dtsi"

--
Gitblit v1.6.2