blob: 407b906734c95ef219e42745b279e134b2c8821f [file] [log] [blame]
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include "mbtk_sleep.h"
#include "mbtk_log.h"
#include "mbtk_utils.h"
static bool autosleep_enable = FALSE;
static mbtk_lock_name_s mbtk_lock_name[LOCK_MAX_SIZE]={0};
int g_mEpollFd = -1;
mbtk_sleep_callback_func g_sleep_timer_cb;
int g_sleep_timer_fd = 0;
pthread_t g_timer_thread_id;
int mbtk_powerrind_get()
{
char buffer[4];
int ret = 0;
int fd = open(MTBK_POWERIND, O_RDWR | O_SYNC, 0662);
if (fd != -1)
{
mbtk_read(fd, buffer, strlen(buffer)+1);
close(fd);
}
ret = atoi(buffer);
return ret;
}
int mbtk_autosuspend_enable(char enable)
{
if((enable == 1) || enable == '1')
{
if(!access("/sys/power/autosleep", W_OK))
{
mbtk_system("echo mem > /sys/power/autosleep");
autosleep_enable = TRUE;
return 0;
}
else
{
LOGE("/sys/power/autosleep can not write.");
return -1;
}
}
else if((enable == 0) || enable == '0')
{
if(!access("/sys/power/autosleep", W_OK))
{
mbtk_system("echo off > /sys/power/autosleep");
autosleep_enable = FALSE;
return 0;
}
else
{
LOGE("/sys/power/autosleep can not write.");
return -1;
}
}
else
{
LOGE("qser_autosuspend_enablecan enable err.");
return -1;
}
return 0;
}
int mbtk_wakelock_create(const char* name , size_t len)
{
int len_t;
len_t = strlen(name);
if((name != NULL) && (len < 33) && (len_t < 33))
{
int i;
for(i=1 ;i<LOCK_MAX_SIZE;i++)
{
if(strcmp(mbtk_lock_name[i].name, name) == 0)
{
LOGE("Repeated names.");
return -1;
}
}
for(i=1 ;i<LOCK_MAX_SIZE;i++)
{
if(mbtk_lock_name[i].fd == 0)
break;
}
if (i >= LOCK_MAX_SIZE)
{
LOGE("Fd is full.");
return -1;
}
memcpy(mbtk_lock_name[i].name, name, strlen(name)+1);
mbtk_lock_name[i].fd = i;
return mbtk_lock_name[i].fd -1;//Starting from scratch
}
else
return -1;
return -1;
}
int mbtk_wakelock_lock(int fd)
{
int i;
for(i=1;i<LOCK_MAX_SIZE;i++)
{
if(mbtk_lock_name[i].fd -1 == fd)
break;
}
if(i == LOCK_MAX_SIZE)
{
LOGE("LOCK_MAX_SIZE is full\n");
return -1;
}
if(!access("/sys/power/wake_lock", W_OK))
{
char cmd[128]={0};
sprintf(cmd, "echo %s > /sys/power/wake_lock", mbtk_lock_name[i].name);
mbtk_system(cmd);
return 0;
}
else
{
LOGE("/sys/power/wake_lock can not write.");
return -1;
}
return 0;
}
int mbtk_wakelock_unlock(int fd)
{
int i;
for(i=1;i<LOCK_MAX_SIZE;i++)
{
if(mbtk_lock_name[i].fd -1 == fd)
break;
}
if(i == LOCK_MAX_SIZE)
{
LOGE("LOCK_MAX_SIZE is full\n");
return -1;
}
if(!access("/sys/power/wake_unlock", W_OK))
{
char cmd[128]={0};
sprintf(cmd, "echo %s > /sys/power/wake_unlock", mbtk_lock_name[i].name);
mbtk_system(cmd);
return 0;
}
else
{
LOGE("/sys/power/wake_unlock can not write.");
return -1;
}
return 0;
}
int mbtk_wakelock_destroy(int fd)
{
int i;
for(i=1;i<LOCK_MAX_SIZE;i++)
{
if(mbtk_lock_name[i].fd -1 == fd)
break;
}
if(i == LOCK_MAX_SIZE)
{
LOGE("LOCK_MAX_SIZE is full\n");
return -1;
}
else
{
mbtk_lock_name[i].fd = 0;
memset(mbtk_lock_name[i].name, 0, 64);
return 0;
}
return 0;
}
static void* suspend_timer_thread_run(void* arg)
{
struct epoll_event eventItems[EPOLL_SIZE_HINT];
int eventCount = epoll_wait(g_mEpollFd, eventItems, EPOLL_SIZE_HINT, -1);
int timerFd = -1;
int eventIndex = 0;
uint64_t readCounter;
if (eventCount < 0) {
LOGE("Poll failed with an unexpected error: %s\n", strerror(errno));
return (void*)-1;
}
for (; eventIndex < eventCount; ++eventIndex)
{
timerFd = eventItems[eventIndex].data.fd;
int retRead = read(timerFd, &readCounter, sizeof(uint64_t));
if (retRead < 0)
{
LOGE("read %d failed...\n", timerFd);
continue;
}
else
{
mbtk_autosuspend_enable(0);
g_sleep_timer_cb(NULL, 0);
g_sleep_timer_fd = 0;
LOGI("suspend_timer_success, retRead:%d\n", retRead);
}
}
return 0;
}
static int suspend_timer_timer_init(void)
{
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
{
LOGE("[suspend] pthread_attr_setdetachstate() fail.");
return -1;
}
if(pthread_create(&g_timer_thread_id, &thread_attr, suspend_timer_thread_run, NULL))
{
LOGE("[suspend] pthread_create() fail.");
return -1;
}
pthread_attr_destroy(&thread_attr);
return 0;
}
int mbtk_suspend_timer_set(int time, mbtk_sleep_callback_func cb)
{
struct itimerspec timerSet;
struct epoll_event eventItem;
int result = 0;
if(0 < g_sleep_timer_fd)
{
LOGE("suspend timer has been init, restart");
if(timerfd_settime(g_sleep_timer_fd, TFD_TIMER_CANCEL_ON_SET, &timerSet, NULL) != 0)
{
LOGE("suspend timer cancel fail");
}
pthread_detach(g_timer_thread_id);
pthread_cancel(g_timer_thread_id);
result = epoll_ctl(g_mEpollFd, EPOLL_CTL_DEL, g_sleep_timer_fd, &eventItem);
if (result != 0)
{
LOGE("Could not del timer fd(%d) to epoll instance: %s\n", g_sleep_timer_fd, strerror(errno));
}
close(g_sleep_timer_fd);
}
g_mEpollFd = epoll_create(EPOLL_SIZE_HINT);
g_sleep_timer_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
if (g_sleep_timer_fd < 0) {
LOGE("Could not create timer fd: %s\n", strerror(errno));
return 0;
}
timerSet.it_interval.tv_sec = 0;
timerSet.it_interval.tv_nsec = 0;
timerSet.it_value.tv_sec = time;
timerSet.it_value.tv_nsec = 0;
if (timerfd_settime(g_sleep_timer_fd, 0, &timerSet, NULL) != 0) {
LOGE("timerfd_settime failed: %s\n", strerror(errno));
close(g_sleep_timer_fd);
return 0;
}
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN | EPOLLET;
eventItem.data.fd = g_sleep_timer_fd;
result = epoll_ctl(g_mEpollFd, EPOLL_CTL_ADD, g_sleep_timer_fd, &eventItem);
if (result != 0) {
LOGE("Could not add timer fd(%d) to epoll instance: %s\n", g_sleep_timer_fd, strerror(errno));
}
mbtk_autosuspend_enable(1);
g_sleep_timer_cb = cb;
suspend_timer_timer_init();
return 0;
}
int mbtk_suspend_timer_cancel(void)
{
int ret = -1;
struct itimerspec timerSet;
if(0 < g_sleep_timer_fd)
{
LOGD("[%s] suspend timer deinit", __func__);
memset(&timerSet, 0x0, sizeof(struct itimerspec));
if(timerfd_settime(g_sleep_timer_fd, TFD_TIMER_CANCEL_ON_SET, &timerSet, NULL) != 0)
{
LOGE("[%s] timerfd_settime fail", __func__);
return -1;
}
}
if(0 < g_mEpollFd)
{
ret = epoll_ctl(g_mEpollFd, EPOLL_CTL_DEL, g_sleep_timer_fd, NULL);
if (ret != 0)
{
LOGE("[%s] epoll_ctl[%d] del g_sleep_timer_fd[%d] fail. [%s]\n", g_mEpollFd, g_sleep_timer_fd, strerror(errno));
return -1;
}
}
pthread_detach(g_timer_thread_id);
pthread_cancel(g_timer_thread_id);
g_timer_thread_id = 0;
if(0 < g_sleep_timer_fd)
{
close(g_sleep_timer_fd);
g_sleep_timer_fd = -1;
}
if(0 < g_mEpollFd)
{
close(g_mEpollFd);
g_mEpollFd = -1;
}
return 0;
}