blob: 6ae159ef812d1ef4b10f4fcccccd515c18644874 [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 mbtk_lock_name_s mbtk_lock_name[LOCK_MAX_SIZE]={0};
#define EPOLL_SIZE_HINT 128
int mEpollFd = -1;
mbtk_info_callback_func g_sleep_timer_cb;
int g_sleep_timer_fd = 0;
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(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 {
g_sleep_timer_cb(NULL, 0);
mbtk_autosuspend_enable(0);
g_sleep_timer_fd = 0;
LOGI("suspend_timer_success\n");
}
}
return 0;
}
static int suspend_timer_timer_init(void)
{
pthread_attr_t thread_attr;
pthread_t net_led_thread_id;
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(&net_led_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_info_callback_func cb)
{
if(0 < g_sleep_timer_fd)
{
LOGE("suspend timer has been init");
return -1;
}
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;
}
struct itimerspec timerSet;
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;
}
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN | EPOLLET;
eventItem.data.fd = g_sleep_timer_fd;
int result = epoll_ctl(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;
}