[Feature] add power management codes for autosuspend.service autosuspend_lib
Change-Id: I367a67e940dcbbfffeeadd25d23b47db23edbf83
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/libautosuspend/libautosuspend.bb b/meta/meta-mediatek-mt2735/recipes-lynq/libautosuspend/libautosuspend.bb
new file mode 100644
index 0000000..71b3711
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/libautosuspend/libautosuspend.bb
@@ -0,0 +1,48 @@
+inherit externalsrc package
+
+DESCRIPTION = "libautosuspend"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS += "platform-libs liblynq-log "
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/lynq/lib/libautosuspend"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -Wl,--hash-style=gnu"
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'RAT_CONFIG_C2K_SUPPORT = ${RAT_CONFIG_C2K_SUPPORT}'\
+ 'MTK_MULTI_SIM_SUPPORT = ${MTK_MULTI_SIM_SUPPORT}'\
+ 'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+FILES_${PN} = "${base_libdir}/*.so \
+ ${base_bindir}\
+ ${base_sbindir} \
+ /etc/dbus-1/system.d/"
+FILES_${PN}-dev = "/test \
+ ${includedir}"
+FILES_${PN}-doc = "/doc"
+FILES_${PN}-dbg ="${base_bindir}/.debug \
+ ${base_libdir}/.debug \
+ ${base_sbindir}/.debug"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+ if [ "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mfpu=neon-vfpv4 -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ elif [ "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mfpu=neon-vfpv4 -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ elif [ "${PACKAGE_ARCH}" = "cortexa53hf-neon-fp-armv8" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mfpu=neon-vfpv4 -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE -mhard-float -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53 -mtune=cortex-a53"
+ else
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ fi
+}
+
+do_install() {
+ oe_runmake install ROOT=${D}
+ if [ -d "${WORKONSRC}" ] ; then
+ install -d ${D}${includedir}
+ fi
+}
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb b/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb
index 1dfc739..ffdb8cf 100755
--- a/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb
@@ -4,6 +4,8 @@
inherit packagegroup
RDEPENDS_packagegroup-lync-mt2735 = "\
+ libautosuspend \
+ lynq-autosuspend \
lynq-system-service \
liblynq-log \
liblynq-uci \
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/LICENSE b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/LICENSE
new file mode 100644
index 0000000..1b15bd2
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/LICENSE
@@ -0,0 +1,31 @@
+opyright Statement:
+
+This software/firmware and related documentation ("MobileTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MobileTek Inc. and/or its licensors. Without
+the prior written permission of MobileTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MobileTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MobileTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MobileTek SOFTWARE")
+RECEIVED FROM MobileTek AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MobileTek EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MobileTek PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MobileTek SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MobileTek
+SOFTWARE. MobileTek SHALL ALSO NOT BE RESPONSIBLE FOR ANY MobileTek SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MobileTek'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MobileTek SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MobileTek'S OPTION, TO REVISE OR REPLACE THE
+MobileTek SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MobileTek FOR SUCH MobileTek SOFTWARE AT ISSUE.
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.c b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.c
new file mode 100644
index 0000000..ff653f6
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 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 "AUTOSUSPEND"
+
+#include <stdbool.h>
+
+#include <log/log.h>
+#include <liblog/lynq_deflog.h>
+
+#include "autosuspend.h"
+
+#include "autosuspend_ops.h"
+
+static struct autosuspend_ops *autosuspend_ops;
+static bool autosuspend_enabled;
+static bool autosuspend_inited;
+
+static int autosuspend_init(void)
+{
+ if (autosuspend_inited) {
+ return 0;
+ }
+
+ autosuspend_ops = autosuspend_wakeup_count_init();
+ if (autosuspend_ops) {
+ goto out;
+ }
+
+ if (!autosuspend_ops) {
+ ALOGI("failed to initialize autosuspend\n");
+ return -1;
+ }
+
+out:
+ autosuspend_inited = true;
+
+ ALOGI("autosuspend initialized\n");
+ return 0;
+}
+
+int autosuspend_enable(void)
+{
+ int ret;
+
+ ret = autosuspend_init();
+ if (ret) {
+ return ret;
+ }
+
+ ALOGI("autosuspend_enable\n");
+
+ if (autosuspend_enabled) {
+ return 0;
+ }
+
+ ret = autosuspend_ops->enable();
+ if (ret) {
+ return ret;
+ }
+
+ autosuspend_enabled = true;
+ return 0;
+}
+
+int autosuspend_disable(void)
+{
+ int ret;
+
+ ret = autosuspend_init();
+ if (ret) {
+ return ret;
+ }
+
+ ALOGI("autosuspend_disable\n");
+
+ if (!autosuspend_enabled) {
+ return 0;
+ }
+
+ ret = autosuspend_ops->disable();
+ if (ret) {
+ return ret;
+ }
+
+ autosuspend_enabled = false;
+ return 0;
+}
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.h b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.h
new file mode 100644
index 0000000..59188a8
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBSUSPEND_AUTOSUSPEND_H_
+#define _LIBSUSPEND_AUTOSUSPEND_H_
+
+#include <sys/cdefs.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+/*
+ * autosuspend_enable
+ *
+ * Turn on autosuspend in the kernel, allowing it to enter suspend if no
+ * wakelocks/wakeup_sources are held.
+ *
+ *
+ *
+ * Returns 0 on success, -1 if autosuspend was not enabled.
+ */
+int autosuspend_enable(void);
+
+/*
+ * autosuspend_disable
+ *
+ * Turn off autosuspend in the kernel, preventing suspend and synchronizing
+ * with any in-progress resume.
+ *
+ * Returns 0 on success, -1 if autosuspend was not disabled.
+ */
+int autosuspend_disable(void);
+
+/*
+ * set_wakeup_callback
+ *
+ * Set a function to be called each time the device returns from suspend.
+ * success is true if the suspend was sucessful and false if the suspend
+ * aborted due to some reason.
+ */
+void set_wakeup_callback(void (*func)(bool success));
+
+__END_DECLS
+
+#endif
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.service b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.service
new file mode 100644
index 0000000..3cbb46c
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=lynq-autosuspend-service
+
+[Service]
+ExecStart=/usr/bin/autosuspend
+Type=simple
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_ops.h b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_ops.h
new file mode 100644
index 0000000..698e25b
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_ops.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBSUSPEND_AUTOSUSPEND_OPS_H_
+#define _LIBSUSPEND_AUTOSUSPEND_OPS_H_
+
+struct autosuspend_ops {
+ int (*enable)(void);
+ int (*disable)(void);
+};
+
+struct autosuspend_ops *autosuspend_autosleep_init(void);
+struct autosuspend_ops *autosuspend_earlysuspend_init(void);
+struct autosuspend_ops *autosuspend_wakeup_count_init(void);
+
+#endif
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c
new file mode 100644
index 0000000..1f8284e
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2012 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 "AUTOSUSPEND"
+//#define LOG_NDEBUG 0
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <dlfcn.h>
+//#include <cutils/properties.h>
+#define LOG_TAG "AUTOSUSPEND"
+#define USER_LOG_TAG "PMS"
+#include <liblog/lynq_deflog.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include "autosuspend_ops.h"
+
+#define SYS_POWER_STATE "/sys/power/state"
+// #define SYS_POWER_STATE "/sys/power/autosleep"
+#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
+#define SYS_POWER_SPM_SUSPEND_CRTL "/sys/power/spm/suspend_ctrl"
+
+#define BASE_SLEEP_TIME 100000
+#define POSSIBLE_MAX_SLEEP_TIME 60000000
+
+static int state_fd;
+static int wakeup_count_fd;
+static int suspend_ctrl_fd;
+static pthread_t suspend_thread;
+static sem_t suspend_lockout;
+static const char *sleep_state = "mem";
+static const char *reg_netsys[5] = {"reg_netsys_srcclkena_mask_b 0",
+ "reg_netsys_infra_req_mask_b 0",
+ "reg_netsys_apsrc_req_mask_b 0",
+ "reg_netsys_vrf18_req_mask_b 0",
+ "reg_netsys_ddr_en_mask_b 0" };
+static void (*wakeup_func)(bool success) = NULL;
+static int sleep_time = BASE_SLEEP_TIME;
+static int possible_max_sleep_time = POSSIBLE_MAX_SLEEP_TIME;
+
+static void* dlHandle_sim;
+extern int adb_debug_mode;
+
+int (*lynq_screen)(int num);
+int (*lynq_sim_init)(int utoken);
+
+
+
+# define TEMP_FAILURE_RETRY(expression) \
+ (__extension__ \
+ ({ long int __result; \
+ do __result = (long int) (expression); \
+ while (__result == -1L && errno == EINTR); \
+ __result; }))
+
+
+
+
+void *dlHandle_wakelock;
+void *dlHandle_log;
+void *dlHandle_network;
+
+int (*acquire_wake_lock)(int lock, const char* id);
+int (*release_wake_lock)(const char* id);
+int (*lynq_query_registration_state)(const char *type,int* regState,int* imsRegState,char * LAC,char * CID,int *netType,int *radioTechFam);
+int (*lynq_network_init)(int utoken);
+
+pid_t pid = 0;
+
+enum {
+ PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off
+ FULL_WAKE_LOCK = 2 // the screen is also on
+};
+
+// while you have a lock held, the device will stay on at least at the
+// level you request.
+
+
+
+void init_wakelock_func(void)
+{
+ const char *lynqLibPath_WakeLock = "/usr/lib64/libpower.so";
+ const char *lynqLibPath_Log = "/lib64/liblynq-log.so";
+
+ dlHandle_wakelock = dlopen(lynqLibPath_WakeLock, RTLD_NOW);
+ if (dlHandle_wakelock == NULL)
+ {
+ ALOGI("dlopen lynqLibPath_WakeLock failed: %s", dlerror());
+ exit(EXIT_FAILURE);
+ }
+ dlHandle_log = dlopen(lynqLibPath_Log, RTLD_NOW);
+ if (dlHandle_log == NULL)
+ {
+ ALOGI("dlopen dlHandle_log failed: %s", dlerror());
+ exit(EXIT_FAILURE);
+ }
+ acquire_wake_lock = (int(*)(int,const char*))dlsym(dlHandle_wakelock, "acquire_wake_lock");
+ if (acquire_wake_lock == NULL) {
+ ALOGI("acquire_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+ exit(EXIT_FAILURE);
+ }
+ release_wake_lock = (int(*)( const char*))dlsym(dlHandle_wakelock, "release_wake_lock");
+ if (release_wake_lock == NULL) {
+ ALOGI("release_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+ exit(EXIT_FAILURE);
+ }
+ dlerror(); // Clear any previous dlerror
+
+ return;
+}
+
+
+
+ void init_sim_func()
+{
+ int res;
+ const char *lynqLibPath_Sim = "/lib64/liblynq-sim.so";
+
+ pid = getpid();
+ dlHandle_sim = dlopen(lynqLibPath_Sim, RTLD_NOW);
+ if (dlHandle_sim == NULL)
+ {
+ ALOGI("dlopen lynqLibPath_Sim failed: %s", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ lynq_screen = (int(*)(int))dlsym(dlHandle_sim, "lynq_screen");
+ if (lynq_screen == NULL) {
+ ALOGI("lynq_screen not defined or exported in %s", lynqLibPath_Sim);
+ exit(EXIT_FAILURE);
+ }
+
+ lynq_sim_init = (int(*)(int utoken))dlsym(dlHandle_sim,"lynq_sim_init");
+ if (lynq_sim_init == NULL) {
+ ALOGI("lynq_sim_init not defined or exported in %s", lynqLibPath_Sim);
+ exit(EXIT_FAILURE);
+ }
+ dlerror(); // Clear any previous dlerror
+
+ res = lynq_sim_init((int)pid);
+ if(res == 0)
+ {
+ ALOGI("Run lynq_sim_init\n");
+ }else{
+ ALOGI("lynq sim init error\n");
+ }
+
+ return;
+}
+
+
+void init_network_func()
+{
+ int res;
+ const char *lynqLibPath_Network = "/lib64/liblynq-network.so";
+ dlHandle_network = dlopen(lynqLibPath_Network, RTLD_NOW);
+ if (dlHandle_network == NULL)
+ {
+ ALOGI("dlopen lynqLibPath_Network failed: %s", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ lynq_query_registration_state = (int(*)(const char,int*,int*,char *,char *,int *,int *))dlsym(dlHandle_network, "lynq_query_registration_state");
+ if (lynq_query_registration_state == NULL) {
+ ALOGI("lynq_query_registration_state not defined or exported in %s", lynqLibPath_Network);
+ exit(EXIT_FAILURE);
+ }
+
+ lynq_network_init = (int(*)(int))dlsym(dlHandle_network, "lynq_network_init");
+ if (lynq_network_init == NULL) {
+ ALOGI("lynq_network_init not defined or exported in %s", lynqLibPath_Network);
+ exit(EXIT_FAILURE);
+ }
+
+ ALOGI("start lynq_network_init\n");
+ printf("start lynq_network_init\n");
+ res = lynq_network_init(2);
+ sleep(10);
+
+ if(res == 0)
+ {
+ ALOGI("Run lynq_network_init\n");
+ printf("Run lynq_network_init\n");
+ }else{
+ ALOGI("lynq_network_init error\n");
+ printf("lynq_network_init error\n");
+ }
+
+ dlerror(); // Clear any previous dlerror
+ return;
+}
+
+static int suspend_ctrl()
+{
+
+
+
+ char buf[80];
+
+ system("echo \"Sys standby mode\" >/dev/console");
+ // sleep(1);
+ system("echo 7 | emdlogger_ctrl");
+ // sleep(1);
+
+ if (lynq_screen(0) < 0) //notify ril for screen off
+ {
+ ALOGI("lynq_screen off fail\n");
+ return -1;
+ }
+
+ sleep(2); //delay 1s for ril handling screen off
+
+ for(int i = 0;i < 5;i++) //notify spm (other core) to handle pre-sleep configuration
+ {
+ if(TEMP_FAILURE_RETRY(write(suspend_ctrl_fd,reg_netsys[i],strlen(reg_netsys[i]))) < 0)
+ {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error writing to %s: %s\n", SYS_POWER_SPM_SUSPEND_CRTL, buf);
+ return -1;
+ }
+ }
+ if(TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state))) < 0) //enter suspend procedures in kernel
+ {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error writing to %s: %s\n", SYS_POWER_STATE, buf);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static void update_sleep_time(bool success) {
+ if (success) {
+ sleep_time = BASE_SLEEP_TIME;
+ return;
+ }
+ // double sleep time after each failure up to one minute
+ sleep_time = MIN(sleep_time * 2, possible_max_sleep_time);
+}
+
+static void *suspend_thread_func(void *arg __attribute__((unused)))
+{
+ char buf[80];
+ char wakeup_count[20];
+ int wakeup_count_len;
+ int ret;
+ bool success = true;
+
+
+
+
+ while (1) {
+ update_sleep_time(success);
+ usleep(sleep_time);
+ success = false;
+
+ ALOGI("%s: wait\n", __func__);
+ ret = sem_wait(&suspend_lockout);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error waiting on semaphore: %s\n", buf);
+ continue;
+ }
+
+ ALOGI("%s: [1613]start suspend_ctrl\n", __func__);
+ ret = suspend_ctrl();
+
+ if (ret >= 0) {
+ ALOGI("suspend_ctrl success.\n");
+ success = true;
+ }
+
+ void (*func)(bool success) = wakeup_func;
+ if (func != NULL) {
+ (*func)(success); //handling resume event for other libs /apps
+ }
+
+ ALOGI("%s: release sem\n", __func__);
+ ret = sem_post(&suspend_lockout);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error releasing semaphore: %s\n", buf);
+ }
+
+ ALOGI("%s: START SLEEP\n", __func__);
+ if (lynq_screen(1) < 0) // notify ril for screen on
+ {
+ ALOGI("lynq_screen on fail\n");
+
+ }
+
+ system("mdlogctl start");
+
+ // sleep(1);
+
+ system("echo 8 | emdlogger_ctrl");
+
+ sleep(2); //delay 2s for ril handling screen on
+ if(adb_debug_mode == 1) // it's neccessary to wait for autosuspend_disable function calling in debug mode when finish resume procedure.
+ {
+
+
+ sleep(40);
+ }
+ else
+ {
+ ALOGI("%s: adb_debug unsupported\n", __func__);
+ }
+ // LYDBGLOG("%s: [936]START wake_lock\n", __func__);
+ // if (acquire_wake_lock(PARTIAL_WAKE_LOCK,"aaa") < 0)
+ // {
+ // LYDBGLOG("acquire_wake_lock : aaa fail.\n");
+ // }
+ // else
+ // {
+ // LYDBGLOG("acquire_wake_lock : aaa success.\n");
+ // }
+
+ ALOGI("%s: END SLEEP\n", __func__);
+ }
+ return NULL;
+}
+
+static int autosuspend_wakeup_count_enable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGI("autosuspend_wakeup_count_enable\n");
+
+ ret = sem_post(&suspend_lockout);
+
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error changing semaphore: %s\n", buf);
+ }
+
+ ALOGI("autosuspend_wakeup_count_enable done\n");
+
+ return ret;
+}
+
+static int autosuspend_wakeup_count_disable(void)
+{
+ char buf[80];
+ int ret;
+
+ ALOGI("autosuspend_wakeup_count_disable\n");
+
+ ret = sem_wait(&suspend_lockout);
+
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error changing semaphore: %s\n", buf);
+ }
+
+ ALOGI("autosuspend_wakeup_count_disable done\n");
+
+ return ret;
+}
+
+void set_wakeup_callback(void (*func)(bool success))
+{
+ if (wakeup_func != NULL) {
+ ALOGI("Duplicate wakeup callback applied, keeping original");
+ return;
+ }
+ wakeup_func = func;
+}
+
+struct autosuspend_ops autosuspend_wakeup_count_ops = {
+ .enable = autosuspend_wakeup_count_enable,
+ .disable = autosuspend_wakeup_count_disable,
+};
+
+struct autosuspend_ops *autosuspend_wakeup_count_init(void)
+{
+ int ret;
+ char buf[80];
+ char timeout_str[100]="100000";
+
+ //if (property_get("sys.autosuspend.timeout", timeout_str, NULL))
+ {
+ possible_max_sleep_time = atoi(timeout_str);
+ ALOGI("autosuspend timeout is %d\n", possible_max_sleep_time);
+ }
+
+ state_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_STATE, O_RDWR));
+ if (state_fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error opening %s: %s\n", SYS_POWER_STATE, buf);
+ goto err_open_state;
+ }
+
+ wakeup_count_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_WAKEUP_COUNT, O_RDWR));
+ if (wakeup_count_fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error opening %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+ goto err_open_wakeup_count;
+ }
+
+ suspend_ctrl_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_SPM_SUSPEND_CRTL, O_RDWR));
+ if (suspend_ctrl_fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error opening %s: %s\n", SYS_POWER_SPM_SUSPEND_CRTL, buf);
+ goto err_open_suspend_ctrl;
+ }
+
+ ret = sem_init(&suspend_lockout, 0, 0);
+ if (ret < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGI("Error creating semaphore: %s\n", buf);
+ goto err_sem_init;
+ }
+ ret = pthread_create(&suspend_thread, NULL, suspend_thread_func, NULL);
+ if (ret) {
+ strerror_r(ret, buf, sizeof(buf));
+ ALOGI("Error creating thread: %s\n", buf);
+ goto err_pthread_create;
+ }
+
+ ALOGI("Selected wakeup count\n");
+ return &autosuspend_wakeup_count_ops;
+
+err_pthread_create:
+ sem_destroy(&suspend_lockout);
+err_sem_init:
+ close(wakeup_count_fd);
+err_open_wakeup_count:
+ close(state_fd);
+err_open_suspend_ctrl:
+ close(suspend_ctrl_fd);
+err_open_state:
+ return NULL;
+}
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c
new file mode 100755
index 0000000..0565bd2
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c
@@ -0,0 +1,508 @@
+/* //device/system/rild/rild.c
+**
+** 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.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <liblog/lynq_deflog.h>
+#include <include/lynq_uci.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define LOG_UCI_MODULE "lynq_autosuspend"
+#define LOG_UCI_FILE "lynq_uci"
+
+#define LOG_TAG "AUTOSUSPEND"
+
+#define USER_LOG_TAG "PMS"
+
+#define SOCK_PATH "/tmp/autosuspend.server" //不能在当前这个目录创建socket文件,否则报错找不到文件(可能是因为这是在共享文件夹下,不支持创建socket文件)
+
+// #define LYINFLOG(X...) lynq_log_global_output(LOG_INFO,X)
+
+#define TIME_OUT_TIME 30
+
+
+#include <log/log.h>
+
+
+#define MAX_LIB_ARGS 16
+
+int adb_debug_mode = 0;
+
+extern int autosuspend_enable(void);
+extern int autosuspend_disable(void);
+extern void init_wakelock_func(void);
+extern void init_sim_func();
+extern void init_network_func();
+
+
+static void usage(const char *argv0) {
+ fprintf(stderr, "Usage: %s -l <possible_max_sleep_time> [-- <args for Autosuspend Service>]\n", argv0);
+ exit(EXIT_FAILURE);
+}
+
+
+
+static int make_argv(char * args, char ** argv) {
+ // Note: reserve argv[0]
+ int count = 1;
+ char * tok;
+ char * s = args;
+
+ while ((tok = strtok(s, " \0"))) {
+ argv[count] = tok;
+ s = NULL;
+ count++;
+ }
+ return count;
+}
+
+static int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
+{
+ int n;
+
+ while((n = accept(fd, sa, salenptr)) < 0)
+ {
+ if((errno == ECONNABORTED) || (errno == EINTR))
+ continue;
+ else
+ {
+ ALOGI("accept error\n");
+ return -1;
+ }
+ }
+ return n;
+}
+
+static int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
+{
+ if(bind(fd, sa, salen) < 0)
+ {
+ // ALOGI("bind error\n");
+ perror("bind error");
+ return -1;
+ }
+ return 0;
+}
+
+static int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
+{
+ if(connect(fd, sa, salen) < 0)
+ {
+ ALOGI("connect error\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int Socket(int family, int type, int protocol)
+{
+ int n;
+
+ if ( (n = socket(family, type, protocol)) < 0)
+ {
+ ALOGI("socket error\n");
+ return -1;
+ }
+ return n;
+}
+
+static int Listen(int fd, int backlog)
+{
+ if(listen(fd, backlog) < 0)
+ {
+ ALOGI("listen error\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int connect_with_timeout(int sockfd, struct sockaddr *servaddr)
+{
+ int error = -1, len;
+ len = sizeof(int);
+ struct timeval tm;
+ fd_set set;
+ int flags;
+ flags = fcntl(sockfd, F_GETFL, 0);
+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+ int ret = -1;
+ if(connect(sockfd, servaddr, sizeof(struct sockaddr)) == -1)
+ {
+ tm.tv_sec = TIME_OUT_TIME;
+ tm.tv_usec = 0;
+ FD_ZERO(&set);
+ FD_SET(sockfd, &set);
+ if(select(sockfd + 1, NULL, &set, NULL, &tm) > 0)
+ {
+ //���ص�ǰsockfd����״̬����SO_ERROR
+ getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
+ if(error == 0)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ALOGI("connect error\n");
+ ret = -1;
+ }
+ }
+ else
+ {
+ ALOGI("connect time out\n");
+ ret = -1;
+ }
+ }
+ else
+ ret = 0;
+ fcntl(sockfd,F_SETFL,flags & ~O_NONBLOCK);
+ return ret;
+}
+
+
+static int listen_port(struct sockaddr_un *addr, char *sockpath)
+{
+ int listenfd;
+ listenfd = Socket(AF_UNIX,SOCK_STREAM,0);
+ if(listenfd == -1)
+ return -1;
+ memset(addr, 0, sizeof(struct sockaddr_un));
+ addr->sun_family = AF_UNIX;
+ strcpy(addr->sun_path,sockpath);
+ // int opt = 1;
+ // if(setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR, (const void *)&opt, sizeof(opt)) == -1)
+ // {
+ // perror("setsockopt error");
+ // return -1;
+ // }
+
+// 以上方法对非网络的本地socket无效,应该用unlink函数避免Address already in use的错误
+
+
+ unlink(sockpath);
+ if(Bind(listenfd,(struct sockaddr *)addr,sizeof(*addr)) == -1)
+ return -1;
+
+ if(Listen(listenfd,20) == -1)
+ return -1;
+
+ return listenfd;
+}
+
+static ssize_t Read(int fd, void *ptr, size_t nbytes)
+{
+ ssize_t n;
+
+ while((n = read(fd, ptr, nbytes)) == -1)
+ {
+ //printf("READ,%d\n",fd);
+ if (errno == EINTR)
+ {
+ ALOGI("read error eintr\n");
+ continue;
+ }
+ else if(errno == EAGAIN)
+ {
+ //PRINTF("read time out\n");
+ return -1;
+ }
+ else
+ {
+ ALOGI("read error\n");
+ return -1;
+ }
+ }
+ //sleep(2);
+ //printf("READ1,%d\n", fd);
+ return n;
+}
+
+static ssize_t Write(int fd, const void *ptr, size_t nbytes)
+{
+ ssize_t n;
+
+ while((n = write(fd, ptr, nbytes)) == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ else if(errno == EPIPE)
+ {
+ ALOGI("write error epipe\n");
+ return -1;
+ }
+ else
+ return -1;
+ }
+ return n;
+}
+
+static int Close(int fd)
+{
+ if (close(fd) == -1)
+ {
+ ALOGI("close error");
+ return -1;
+ }
+ return 0;
+}
+
+void *deal_autosuspend(void *sockfd)
+{
+ int commfd = *((int *)sockfd);
+ char buf[256];
+
+ while(1)
+ {
+ memset(buf,0,sizeof(buf));
+ ALOGI("deal_autosuspend start to read.\n");
+ // 错误点:read函数在对端关闭后,也会直接返回0,不会阻塞,因此要判断是否返回0,返回0表示对端已经关闭,此时要跳出while循环不再监听
+ // 为什么对端会关闭?因为在客户端没有用nohup方式打开的情况下,系统睡眠后客户端进行会直接被杀死,对端会关闭,所以会导致read不阻塞,且总是返回0的现象
+ if(Read(commfd,buf,sizeof(buf)) == 0)
+ {
+ break;
+ }
+ if(strcmp(buf,"enable") == 0)
+ {
+ if(autosuspend_enable() < 0)
+ {
+ ALOGI("autosuspend_enable fail.\n");
+ }
+ else
+ {
+ ALOGI("autosuspend_enable success.\n");
+ }
+ }
+ else if(strcmp(buf,"disable") == 0)
+ {
+ if(autosuspend_disable() < 0)
+ {
+ ALOGI("autosuspend_disable fail.\n");
+ }
+ else
+ {
+ ALOGI("autosuspend_disable success.\n");
+ }
+ }
+ else
+ {
+ ALOGI("Unknown cmd.\n");
+ }
+ }
+
+
+
+}
+
+
+
+int main(int argc, char **argv) {
+
+
+ // int i = 0;
+ // RLOGD("**Autosuspend Service Daemon Started**");
+ // RLOGD("**Autosuspend Service param count=%d**", argc);
+ char tmp[20];
+ int server_sock, commfd, len;
+ struct sockaddr_un server_sockaddr;
+ struct sockaddr_un client_sockaddr;
+ len = sizeof(server_sockaddr);
+
+ pthread_t tid;
+
+ int auto_enable = 0;
+ LYLOGEINIT(USER_LOG_TAG);
+ LYLOGSET(LOG_DEBUG);
+ // LYLOGSET(LOG_ERROR);
+
+
+ lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "debug", tmp);
+ ALOGI("[1832]Autosuspend Service Daemon. debug %s\n",tmp);
+ adb_debug_mode=atoi(tmp);
+ lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "auto_enable", tmp);
+ auto_enable=atoi(tmp);
+ ALOGI("Autosuspend Service Daemon. auto_enable %s\n",tmp);
+ init_wakelock_func();
+ init_sim_func();
+ // init_network_func();
+ if(auto_enable==0)
+ {
+ if(autosuspend_disable() < 0)
+ {
+ ALOGI("autosuspend_disable fail.\n");
+ }
+ else
+ {
+ ALOGI("autosuspend_disable success.\n");
+ }
+ }
+ if(auto_enable==1)
+ {
+ if(autosuspend_enable() < 0)
+ {
+ ALOGI("autosuspend_enable fail.\n");
+ }
+ else
+ {
+ ALOGI("autosuspend_enable success.\n");
+ }
+ }
+
+
+ server_sock = listen_port(&server_sockaddr,SOCK_PATH);
+ if(server_sock == -1)
+ return -1;
+
+ while (1)
+ {
+ ALOGI("service socket listening...\n");
+ commfd = Accept(server_sock,(struct sockaddr *)&client_sockaddr,&len);
+ if(commfd == -1)
+ {
+ return -1;
+ }
+ if(getpeername(commfd, (struct sockaddr *)&client_sockaddr, &len) == -1)
+ {
+ ALOGI("GETPEERNAME ERROR.\n");
+ close(server_sock);
+ close(commfd);
+ continue;
+ }
+ else
+ {
+ ALOGI("Client socket filepath: %s\n", client_sockaddr.sun_path);
+ }
+ pthread_create(&tid,NULL,deal_autosuspend,(void*)&commfd);//这里很容易错,最后一个参数要取地址,这是一个指针
+ pthread_detach(tid);
+
+ }
+
+ /* for (i = 1; i < argc ;) {
+ if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
+ rilLibPath = argv[i + 1];
+ i += 2;
+ } else if (0 == strcmp(argv[i], "--")) {
+ i++;
+ hasLibArgs = 1;
+ break;
+ } else if (0 == strcmp(argv[i], "-c") && (argc - i > 1)) {
+ clientId = argv[i+1];
+ i += 2;
+ } else {
+ usage(argv[0]);
+ }
+ }
+
+ if (clientId == NULL) {
+ clientId = "0";
+ } else if (atoi(clientId) >= MAX_RILDS) {
+ RLOGE("Max Number of rild's supported is: %d", MAX_RILDS);
+ exit(0);
+ }
+ if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) {
+ strncpy(ril_service_name, ril_service_name_base, MAX_SERVICE_NAME_LENGTH);
+ strncat(ril_service_name, clientId, MAX_SERVICE_NAME_LENGTH);
+ }
+
+ if (rilLibPath == NULL) {
+ if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
+ // No lib sepcified on the command line, and nothing set in props.
+ // Assume "no-ril" case.
+ goto done;
+ } else {
+ rilLibPath = libPath;
+ }
+ }
+
+ dlHandle = dlopen(rilLibPath, RTLD_NOW);
+
+ if (dlHandle == NULL) {
+ RLOGE("dlopen failed: %s", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ RIL_startEventLoop();
+
+ rilInit =
+ (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
+ dlsym(dlHandle, "RIL_Init");
+
+ if (rilInit == NULL) {
+ RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);
+ exit(EXIT_FAILURE);
+ }
+
+ dlerror(); // Clear any previous dlerror
+ rilUimInit =
+ (RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
+ dlsym(dlHandle, "RIL_SAP_Init");
+ err_str = dlerror();
+ if (err_str) {
+ RLOGW("RIL_SAP_Init not defined or exported in %s: %s\n", rilLibPath, err_str);
+ } else if (!rilUimInit) {
+ RLOGW("RIL_SAP_Init defined as null in %s. SAP Not usable\n", rilLibPath);
+ }
+
+ if (hasLibArgs) {
+ rilArgv = argv + i - 1;
+ argc = argc -i + 1;
+ } else {
+ static char * newArgv[MAX_LIB_ARGS];
+ static char args[PROPERTY_VALUE_MAX];
+ rilArgv = newArgv;
+ property_get(LIB_ARGS_PROPERTY, args, "");
+ argc = make_argv(args, rilArgv);
+ }
+
+ rilArgv[argc++] = "-c";
+ rilArgv[argc++] = (char*)clientId;
+ RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]);
+
+ // Make sure there's a reasonable argv[0]
+ rilArgv[0] = argv[0];
+
+ funcs = rilInit(&s_rilEnv, argc, rilArgv);
+ RLOGD("RIL_Init rilInit completed");
+
+ RIL_register(funcs);
+
+ RLOGD("RIL_Init RIL_register completed");
+
+ if (rilUimInit) {
+ RLOGD("RIL_register_socket started");
+ RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv);
+ }
+
+ RLOGD("RIL_register_socket completed");
+
+done:
+
+ rilc_thread_pool();
+
+ RLOGD("RIL_Init starting sleep loop");*/
+ while (1) {
+ // ALOGI("start autosuspend_enable:%d\n",(i++));
+ sleep(5);
+
+ }
+}
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/makefile b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/makefile
new file mode 100644
index 0000000..75e1102
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/makefile
@@ -0,0 +1,48 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+ -g -Os \
+ -flto \
+ -DRIL_SHLIB \
+ -DATCI_PARSE \
+ -DKEEP_ALIVE \
+ -D__LINUX_OS__ \
+ -DECALL_SUPPORT
+
+
+
+
+LOCAL_PATH = .
+
+LOCAL_C_INCLUDES = \
+ -I. -I$(ROOT)$(includedir)/liblog -I$(ROOT)$(includedir) \
+
+
+
+
+LOCAL_LIBS := \
+ -L. \
+ -ldl \
+ -lpthread \
+ -llynq-log \
+ -llynq-uci \
+ -llog \
+
+
+SOURCES = $(wildcard *.c )
+
+EXECUTABLE = autosuspend
+
+OBJECTS=$(SOURCES:.c=.o)
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.c
+ $(CC) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+.PHONY: clean
+clean:
+ $(RM) $(OBJECTS) $(EXECUTABLE)
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/lynq-autosuspend.bb b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/lynq-autosuspend.bb
new file mode 100644
index 0000000..97046eb
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/lynq-autosuspend.bb
@@ -0,0 +1,62 @@
+inherit externalsrc package systemd
+
+DESCRIPTION = "autosuspend.service"
+
+LICENSE = "MobileTekProprietary"
+LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=44d8d2b6296ca24bcd4894bb7155bf27"
+SRC_URI = "file://autosuspend.c file://LICENSE \
+ file://autosuspend.h \
+ file://autosuspend_ops.h \
+ file://autosuspend_wakeup_count.c \
+ file://main.c \
+ file://autosuspend.service \
+ file://makefile \
+"
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+LOCAL_C_INCLUDES = "-I. "
+
+DEPENDS = "liblynq-log liblynq-uci"
+
+LOCAL_LIBS = "-L. -ldl -lstdc++ -lpthread -llog"
+SOURCES = "$(wildcard *.c )"
+
+OBJECTS = "$(SOURCES:.c=.o)"
+
+EXECUTABLE = "autosuspend"
+S = "${WORKDIR}"
+TARGET_CC_ARCH += "${LDFLAGS}"
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "autosuspend.service"
+FILES_${PN} += "${systemd_unitdir}/system/autosuspend.service"
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+
+ #${CXX} -Wall ${LOCAL_C_INCLUDES} autosuspend.c autosuspend_wakeup_count.c main.c ${LOCAL_LIBS} -o ${EXECUTABLE}
+ if test "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" || test "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4"; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
+ else
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
+ fi
+}
+
+do_install() {
+ install -d ${D}${bindir}/
+ echo "Installing image PN ${PN}"
+ echo "Installing image systemd_unitdir ${systemd_unitdir}"
+ echo "Installing image D ${D}"
+ echo "Installing image B ${B}"
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/autosuspend.service ${D}${systemd_unitdir}/system
+ fi
+
+ install -m 0755 ${S}/autosuspend ${D}${bindir}/
+ install -d ${D}${includedir}
+}
+
+
+
+
+
+
diff --git a/src/bsp/lk/oe-logs b/src/bsp/lk/oe-logs
deleted file mode 120000
index 08508b3..0000000
--- a/src/bsp/lk/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-pokymllib32-linux-gnueabi/lib32-lk/2.0.0-r0/temp
\ No newline at end of file
diff --git a/src/bsp/lk/oe-workdir b/src/bsp/lk/oe-workdir
deleted file mode 120000
index 8641a45..0000000
--- a/src/bsp/lk/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-pokymllib32-linux-gnueabi/lib32-lk/2.0.0-r0
\ No newline at end of file
diff --git a/src/bsp/scatter/oe-logs b/src/bsp/scatter/oe-logs
deleted file mode 120000
index 3658b32..0000000
--- a/src/bsp/scatter/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/scatter/1.0-r0/temp
\ No newline at end of file
diff --git a/src/bsp/scatter/oe-workdir b/src/bsp/scatter/oe-workdir
deleted file mode 120000
index 117eb45..0000000
--- a/src/bsp/scatter/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/scatter/1.0-r0
\ No newline at end of file
diff --git a/src/bsp/trustzone/atf/oe-logs b/src/bsp/trustzone/atf/oe-logs
deleted file mode 120000
index 7d49aef..0000000
--- a/src/bsp/trustzone/atf/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-poky-linux/atf/1.6-r0/temp
\ No newline at end of file
diff --git a/src/bsp/trustzone/atf/oe-workdir b/src/bsp/trustzone/atf/oe-workdir
deleted file mode 120000
index 970d6ec..0000000
--- a/src/bsp/trustzone/atf/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-poky-linux/atf/1.6-r0
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/optee_client/mt2xxx/3.2.0/oe-logs b/src/bsp/trustzone/optee/optee_client/mt2xxx/3.2.0/oe-logs
deleted file mode 120000
index cf770d5..0000000
--- a/src/bsp/trustzone/optee/optee_client/mt2xxx/3.2.0/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/optee-client/3.2.0-r0/temp
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/optee_client/mt2xxx/3.2.0/oe-workdir b/src/bsp/trustzone/optee/optee_client/mt2xxx/3.2.0/oe-workdir
deleted file mode 120000
index e68bb3c..0000000
--- a/src/bsp/trustzone/optee/optee_client/mt2xxx/3.2.0/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/optee-client/3.2.0-r0
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/optee_os/mt2xxx/3.2.0/oe-logs b/src/bsp/trustzone/optee/optee_os/mt2xxx/3.2.0/oe-logs
deleted file mode 120000
index ce50370..0000000
--- a/src/bsp/trustzone/optee/optee_os/mt2xxx/3.2.0/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/optee-os/3.2.0-r0/temp
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/optee_os/mt2xxx/3.2.0/oe-workdir b/src/bsp/trustzone/optee/optee_os/mt2xxx/3.2.0/oe-workdir
deleted file mode 120000
index efd486d..0000000
--- a/src/bsp/trustzone/optee/optee_os/mt2xxx/3.2.0/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/optee-os/3.2.0-r0
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/optee_test/mt2xxx/oe-logs b/src/bsp/trustzone/optee/optee_test/mt2xxx/oe-logs
deleted file mode 120000
index bf01525..0000000
--- a/src/bsp/trustzone/optee/optee_test/mt2xxx/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-poky-linux/optee-test/3.2.0-r0/temp
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/optee_test/mt2xxx/oe-workdir b/src/bsp/trustzone/optee/optee_test/mt2xxx/oe-workdir
deleted file mode 120000
index 91ee4c4..0000000
--- a/src/bsp/trustzone/optee/optee_test/mt2xxx/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-poky-linux/optee-test/3.2.0-r0
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/oe-logs b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/oe-logs
deleted file mode 120000
index 2be1576..0000000
--- a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/optee-example/3.2.0-r0/temp
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/oe-workdir b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/oe-workdir
deleted file mode 120000
index 3a07f53..0000000
--- a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/optee-example/3.2.0-r0
\ No newline at end of file
diff --git a/src/devtools/datool/oe-logs b/src/devtools/datool/oe-logs
deleted file mode 120000
index 624438e..0000000
--- a/src/devtools/datool/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/fbtool/1.0-r0/temp
\ No newline at end of file
diff --git a/src/devtools/datool/oe-workdir b/src/devtools/datool/oe-workdir
deleted file mode 120000
index 9b5db70..0000000
--- a/src/devtools/datool/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/aarch64-poky-linux/fbtool/1.0-r0
\ No newline at end of file
diff --git a/src/kernel/linux/v4.19/oe-logs b/src/kernel/linux/v4.19/oe-logs
deleted file mode 120000
index 5d9c5b5..0000000
--- a/src/kernel/linux/v4.19/oe-logs
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-poky-linux/linux-mtk-extension/4.19-r0/temp
\ No newline at end of file
diff --git a/src/kernel/linux/v4.19/oe-workdir b/src/kernel/linux/v4.19/oe-workdir
deleted file mode 120000
index 703774c..0000000
--- a/src/kernel/linux/v4.19/oe-workdir
+++ /dev/null
@@ -1 +0,0 @@
-/home/ww/Share/MT2735_MP1_MR1/build/tmp/work/auto2735evb_ivt_main-poky-linux/linux-mtk-extension/4.19-r0
\ No newline at end of file
diff --git a/src/lynq/lib/libautosuspend/LICENSE b/src/lynq/lib/libautosuspend/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/lynq/lib/libautosuspend/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/lynq/lib/libautosuspend/libautosuspend.c b/src/lynq/lib/libautosuspend/libautosuspend.c
new file mode 100644
index 0000000..a933e9c
--- /dev/null
+++ b/src/lynq/lib/libautosuspend/libautosuspend.c
@@ -0,0 +1,125 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <dlfcn.h>
+
+#define LOG_TAG "libautosuspend"
+
+// #include <liblog/lynq_deflog.h>
+#include <log/log.h>
+
+#define SERVER_PATH "/tmp/autosuspend.server"
+// #define CLIENT_PATH "/tmp/autosuspend.client"
+
+
+static int send_cmd(char * value,int len)
+{
+ int client_sock, rc;
+ struct sockaddr_un server_sockaddr;
+ struct sockaddr_un client_sockaddr;
+
+
+
+ if(value == NULL)
+ {
+ return -1;
+ }
+
+ /**************************************/
+ /* Create a UNIX domain stream socket */
+ /**************************************/
+ client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (client_sock == -1) {
+ ALOGI("SOCKET ERROR ");
+ return -5;
+ }
+
+ /***************************************/
+ /* Set up the UNIX sockaddr structure */
+ /* by using AF_UNIX for the family and */
+ /* giving it a filepath to bind to. */
+ /* */
+ /* Unlink the file so the bind will */
+ /* succeed, then bind to that file. */
+ /***************************************/
+ client_sockaddr.sun_family = AF_UNIX;
+ // strcpy(client_sockaddr.sun_path, CLIENT_PATH);
+ sprintf(client_sockaddr.sun_path,"/tmp/suspend.%d.client",(int)getpid());
+ len = sizeof(client_sockaddr);
+
+ unlink(client_sockaddr.sun_path);
+ rc = bind(client_sock, (struct sockaddr *) &client_sockaddr, len);
+ if (rc == -1){
+ ALOGI("BIND ERROR ");
+ close(client_sock);
+ return -4;
+ }
+
+ /***************************************/
+ /* Set up the UNIX sockaddr structure */
+ /* for the server socket and connect */
+ /* to it. */
+ /***************************************/
+ server_sockaddr.sun_family = AF_UNIX;
+ strcpy(server_sockaddr.sun_path, SERVER_PATH);
+ rc = connect(client_sock, (struct sockaddr *) &server_sockaddr, len);
+ if(rc == -1){
+ ALOGI("CONNECT ERROR ");
+ close(client_sock);
+ return -3;
+ }
+
+ /************************************/
+ /* Copy the data to the buffer and */
+ /* send it to the server socket. */
+ /************************************/
+ // strcpy(buf, DATA);
+ printf("Sending data...\n");
+ rc = send(client_sock, value, len, 0);
+ if (rc == -1) {
+ ALOGI("SEND ERROR ");
+ close(client_sock);
+ return -2;
+ }
+ else {
+ ALOGI("Data sent: %s\n",value);
+ }
+
+ close(client_sock);
+
+ return rc;
+
+}
+
+int lynq_autosleep_enable(void)
+{
+ char value[15]="enable";
+ int rc = send_cmd(value,strlen(value));
+ if(rc < 0)
+ {
+ ALOGI("libautosleep_enable ret %d\n",rc);
+ }
+ return rc;
+}
+
+int lynq_autosleep_disable(void)
+{
+ char value[15]="disable";
+ int rc = send_cmd(value,strlen(value));
+ if(rc < 0)
+ {
+ ALOGI("libautosleep_disable ret %d\n",rc);
+ }
+ return rc;
+
+}
+
+
+
+
diff --git a/src/lynq/lib/libautosuspend/makefile b/src/lynq/lib/libautosuspend/makefile
new file mode 100644
index 0000000..7c9508d
--- /dev/null
+++ b/src/lynq/lib/libautosuspend/makefile
@@ -0,0 +1,69 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+ -std=gnu++14 \
+ -g -Os \
+ -flto \
+ -DRIL_SHLIB \
+ -DATCI_PARSE \
+ -fPIC \
+ -DKEEP_ALIVE \
+ -DECALL_SUPPORT \
+
+
+
+
+$(warning ################# libautosuspend ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH = .
+
+LOCAL_C_INCLUDES = \
+ -I. \
+ -I$(ROOT)$(includedir)/logger \
+ -I$(ROOT)$(includedir)/liblog \
+
+
+LOCAL_LIBS := \
+ -L. \
+ -ldl \
+ -lstdc++ \
+ -llog \
+ -lcutils \
+ -lutils \
+ -lbinder \
+ -lpthread \
+ -llynq-log \
+
+
+SOURCES = $(wildcard *.c)
+
+EXECUTABLE = libautosuspend.so
+
+OBJECTS=$(SOURCES:.c=.o)
+
+
+.PHONY: build clean install pack_rootfs
+all: build
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+ $(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build: $(EXECUTABLE)
+ $(warning ########## build $(EXECUTABLE) ##########)
+install:
+ mkdir -p $(ROOT)$(base_libdir)/
+ install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+ mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+pack_rootfs:
+ mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+ cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+ $(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+ mkdir -p $(PACK_TO)$(base_libdir)/
+ cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+ $(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+ $(RM) $(OBJECTS) $(EXECUTABLE)
+ -find . -name "*.o" -delete
diff --git a/src/lynq/lib/liblynq-uci/lynq_uci.config b/src/lynq/lib/liblynq-uci/lynq_uci.config
index 870e2f7..eb68dbe 100644
--- a/src/lynq/lib/liblynq-uci/lynq_uci.config
+++ b/src/lynq/lib/liblynq-uci/lynq_uci.config
@@ -6,4 +6,8 @@
option function_test_level '0'
config lynq_wifi_rw 'lynq_wifi'
- option gateway '192.168.11.1'
\ No newline at end of file
+ option gateway '192.168.11.1'
+
+config lynq_autosuspend 'lynq_autosuspend'
+ option auto_enable '0'
+ option debug '1'