| #include <stdio.h> | |
| #include <string.h> | |
| #include <strings.h> | |
| #include <stdlib.h> | |
| #include <errno.h> | |
| #include <termios.h> | |
| #include <fcntl.h> | |
| #include <signal.h> | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
| #include <pthread.h> | |
| #include <time.h> | |
| #include <sys/ioctl.h> | |
| #include <dlfcn.h> | |
| #include <stdint.h> | |
| #include <sys/time.h> | |
| #include "gsw_pm_interface.h" | |
| #include "gsw_log_interface.h" | |
| #define GSW_PM "[HAL][GSW_PM]" | |
| #define GSW_WAKELOCK_NAME "gsw_app_wakelock" | |
| #define LOCK_MAX_SIZE 129 | |
| #define SDK_READY_CMD "uci get lynq_uci.sdk_ready" | |
| #define MBTK_REBOOT_REASON "uci get persist.mbtk.reboot_reason" | |
| #define CHECK_SYSTEM(cmd) do { \ | |
| int _ret = system(cmd); \ | |
| if (_ret == -1) perror("system error"); \ | |
| } while(0) | |
| typedef void (*GSW_PM_WAKEUPCALLBACK)(int32_t wakeup_in); | |
| typedef void (*mbtk_lpm_handler_t)(int32_t wakeup_in); | |
| //typedef void (*mbtk_log)(int level, const char *format,...); | |
| int (*mbtk_autosuspend_enable)(char); | |
| int (*mbtk_wakelock_create)(const char* name , size_t); | |
| int (*mbtk_wakelock_lock)(int); | |
| int (*mbtk_wakelock_unlock)(int); | |
| int (*mbtk_wakelock_destroy)(int); | |
| int (*mbtk_lpm_init)(mbtk_lpm_handler_t ); | |
| int lock_fd = -1; | |
| pthread_mutex_t pm_lock; | |
| typedef struct | |
| { | |
| int fd; | |
| char *name; | |
| } mbtk_lock_name_s; | |
| static mbtk_lock_name_s lock_name[LOCK_MAX_SIZE]={0}; | |
| //static mbtk_log fun_ptr_log = NULL; | |
| static void *dlHandle_sleep = NULL; | |
| char *lynqLib_sleep = "/lib/libmbtk_lib.so"; | |
| //0 success,1 timeout,the timeout is 60s | |
| static int wait_sdk_ready() | |
| { | |
| char buffer[8] = {0}; | |
| int sdk_value = -1; | |
| int timeout = 0; | |
| const char *s_kmsg = "echo \"check_sdk_ready ready\" > /dev/kmsg"; | |
| const char *f_kmsg = "echo \"check_sdk_ready timeout\" > /dev/kmsg"; | |
| while(timeout < 500) // ~= 60s | |
| { | |
| timeout++; | |
| FILE *fp = popen(SDK_READY_CMD, "r"); | |
| if(NULL == fp) | |
| { | |
| continue; | |
| } | |
| memset(buffer,0,sizeof(buffer)); | |
| if(fgets(buffer, sizeof(buffer), fp) == NULL) | |
| { | |
| pclose(fp); | |
| perror("fgets failed:"); | |
| continue; | |
| } | |
| pclose(fp); | |
| printf("gsw wait_sdk_ready:%s",buffer); | |
| sdk_value = atoi(buffer); | |
| if(sdk_value == 0) //sdk ready | |
| { | |
| CHECK_SYSTEM(s_kmsg); | |
| return 0; | |
| } | |
| usleep(1000*100);//100ms | |
| } | |
| CHECK_SYSTEM(f_kmsg); | |
| return 1; | |
| } | |
| /** | |
| * @brief Enable autosleep | |
| * @param void | |
| * @retval GSW_HAL_SUCCESS\GSW_HAL_NORMAL_FAIL | |
| */ | |
| static int handle() | |
| { | |
| if(dlHandle_sleep == NULL) | |
| { | |
| dlHandle_sleep = dlopen(lynqLib_sleep, RTLD_NOW); | |
| //fun_ptr_log = (mbtk_log)dlsym(dlHandle_sleep, "mbtk_log"); | |
| if(dlHandle_sleep == NULL) | |
| { | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| } | |
| return GSW_HAL_SUCCESS; | |
| } | |
| int32_t gsw_autosleep_enable(void) | |
| { | |
| int ret; | |
| if (handle()) | |
| return GSW_HAL_NORMAL_FAIL; | |
| mbtk_autosuspend_enable=(int(*)(char))dlsym(dlHandle_sleep, "mbtk_autosuspend_enable"); | |
| ret = mbtk_autosuspend_enable(1); | |
| if(ret < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_autosuspend_enable FAIL.\n"); | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| return GSW_HAL_SUCCESS; | |
| } | |
| /** | |
| * @brief Disable autosleep | |
| * @param void | |
| * @retval GSW_HAL_SUCCESS\GSW_HAL_NORMAL_FAIL | |
| */ | |
| int32_t gsw_autosleep_disenable(void) | |
| { | |
| int ret; | |
| if (handle()) | |
| return GSW_HAL_NORMAL_FAIL; | |
| mbtk_autosuspend_enable=(int(*)(char))dlsym(dlHandle_sleep, "mbtk_autosuspend_enable"); | |
| ret = mbtk_autosuspend_enable(0); | |
| if(ret < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_autosuspend_enable FAIL.\n"); | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| return GSW_HAL_SUCCESS; | |
| } | |
| /** | |
| * @brief Init power manager module | |
| * @param [in]GSW_PM_WAKEUPCALLBACKHandler wakeup_callback | |
| * @retval GSW_HAL_SUCCESS\GSW_HAL_NORMAL_FAIL | |
| */ | |
| int32_t gsw_pm_sdk_init(GSW_PM_WAKEUPCALLBACK wakeup_callback) | |
| { | |
| int ret = 0; | |
| ret = wait_sdk_ready(); //Continue to execute even if timed out | |
| printf("wait_sdk_ready ret:%d\n",ret); //due to the LOG* can not use | |
| if (handle()) | |
| return GSW_HAL_NORMAL_FAIL; | |
| if (pthread_mutex_init(&pm_lock, NULL) != 0) | |
| { | |
| LOGE(GSW_PM,"pthread_mutex_init pm_lock failed\n"); | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| mbtk_lpm_init=(int(*)(mbtk_lpm_handler_t))dlsym(dlHandle_sleep, "mbtk_lpm_init"); | |
| ret = mbtk_lpm_init((mbtk_lpm_handler_t)wakeup_callback); | |
| if(ret < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_lpm_init FAIL.\n"); | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| return GSW_HAL_SUCCESS; | |
| } | |
| /** | |
| * @brief Release wake lock, enter sleep | |
| * @param [in]int32_t wakeup_in | |
| * @retval int | |
| */ | |
| int32_t gsw_pm_enter_sleep(const char *gsw_wakelock_name) | |
| { | |
| int ret; | |
| int i; | |
| if (handle()) | |
| return GSW_HAL_NORMAL_FAIL; | |
| if (gsw_wakelock_name == NULL) | |
| return GSW_HAL_NORMAL_FAIL; | |
| pthread_mutex_lock(&pm_lock); | |
| for(i=0 ;i<LOCK_MAX_SIZE;i++) | |
| { | |
| if(lock_name[i].name != NULL && strcmp(lock_name[i].name, gsw_wakelock_name) == 0) | |
| { | |
| lock_fd = lock_name[i].fd; | |
| break; | |
| } | |
| } | |
| if (i >= LOCK_MAX_SIZE) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_lock not create.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto enter_sleep_end; | |
| } | |
| mbtk_wakelock_unlock=(int(*)(int))dlsym(dlHandle_sleep, "mbtk_wakelock_unlock"); | |
| ret = mbtk_wakelock_unlock(lock_fd); | |
| if(ret < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_unlock FAIL.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto enter_sleep_end; | |
| } | |
| mbtk_wakelock_destroy=(int(*)(int))dlsym(dlHandle_sleep, "mbtk_wakelock_destroy"); | |
| ret = mbtk_wakelock_destroy(lock_fd); | |
| if(ret < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_destroy FAIL.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto enter_sleep_end; | |
| } | |
| if (lock_name[i].name != NULL) | |
| { | |
| free(lock_name[i].name); | |
| lock_name[i].name = NULL; | |
| lock_name[i].fd = -1; | |
| } | |
| ret = GSW_HAL_SUCCESS; | |
| enter_sleep_end: | |
| pthread_mutex_unlock(&pm_lock); | |
| return ret; | |
| } | |
| /** | |
| * @brief Creat wakeup lock | |
| * @param [in]int32_t wakeup_in | |
| * @retval int | |
| */ | |
| int32_t gsw_pm_exit_sleep(const char *gsw_wakelock_name) | |
| { | |
| int ret; | |
| int i; | |
| if (handle()) | |
| return GSW_HAL_NORMAL_FAIL; | |
| if (gsw_wakelock_name == NULL) | |
| return GSW_HAL_NORMAL_FAIL; | |
| pthread_mutex_lock(&pm_lock); | |
| mbtk_wakelock_create=(int(*)(const char* name , size_t))dlsym(dlHandle_sleep, "mbtk_wakelock_create"); | |
| lock_fd = mbtk_wakelock_create(gsw_wakelock_name, strlen(gsw_wakelock_name)); | |
| if(lock_fd < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_create FAIL.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto exit_sleep_end; | |
| } | |
| mbtk_wakelock_lock=(int(*)(int))dlsym(dlHandle_sleep, "mbtk_wakelock_lock"); | |
| ret = mbtk_wakelock_lock(lock_fd); | |
| if(ret < 0) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_lock FAIL.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto exit_sleep_end; | |
| } | |
| for(i=0 ;i<LOCK_MAX_SIZE;i++) | |
| { | |
| if(lock_name[i].name == NULL) | |
| break; | |
| } | |
| if(i == LOCK_MAX_SIZE) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_lock not space FAIL.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto exit_sleep_end; | |
| } | |
| lock_name[i].name = malloc(strlen(gsw_wakelock_name)+1); | |
| if (lock_name[i].name == NULL) | |
| { | |
| LOGE(GSW_PM,"mbtk_wakelock_lock remeber FAIL.\n"); | |
| ret = GSW_HAL_NORMAL_FAIL; | |
| goto exit_sleep_end; | |
| } | |
| memcpy(lock_name[i].name, gsw_wakelock_name, strlen(gsw_wakelock_name)+1); | |
| lock_name[i].fd = lock_fd; | |
| ret = GSW_HAL_SUCCESS; | |
| exit_sleep_end: | |
| pthread_mutex_unlock(&pm_lock); | |
| return ret; | |
| } | |
| /** | |
| * @brief Module log disk drop, used when restarting or hibernating | |
| * @param [in]void | |
| * @retval void | |
| */ | |
| void gsw_modem_log_sync(void) | |
| { | |
| FILE *fp; | |
| char command[256]; | |
| char buffer[256]; | |
| int pid = -1; | |
| const char *process_name = "mbtk_logd"; | |
| snprintf(command, sizeof(command), "pgrep %s", process_name); | |
| fp = popen(command, "r"); | |
| if (fp == NULL) | |
| { | |
| perror("error comman"); | |
| return; | |
| } | |
| if (fgets(buffer, sizeof(buffer), fp) != NULL) | |
| { | |
| pid = atoi(buffer); | |
| } | |
| pclose(fp); | |
| if (pid != -1) | |
| { | |
| if (kill(pid, SIGTERM) == -1) | |
| { | |
| perror("send SIGTERM signal failed"); | |
| return; | |
| } | |
| } | |
| return; | |
| } | |
| /** | |
| * @brief get Modem reset reason | |
| * @param [in]int32_t * reset_reason | |
| * @retval void | |
| */ | |
| int32_t gsw_get_modem_reset_reason(int32_t *reset_reason) | |
| { | |
| char buf[8] = {0}; | |
| int value = -1; | |
| FILE *fp = popen(MBTK_REBOOT_REASON, "r"); | |
| if(NULL == fp) | |
| { | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| memset(buf,0,sizeof(buf)); | |
| if(fgets(buf, sizeof(buf), fp) == NULL) | |
| { | |
| pclose(fp); | |
| perror("fgets failed:"); | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| pclose(fp); | |
| value = atoi(buf); | |
| if (value >= 0 && value <= 6) | |
| { | |
| *reset_reason = (int32_t)value; | |
| return GSW_HAL_SUCCESS; | |
| } | |
| return GSW_HAL_NORMAL_FAIL; | |
| } | |
| /** | |
| * @brief enable autosleep | |
| * @return int : 0 is success , other failed | |
| */ | |
| int gswAutoSleepEnable(void) | |
| { | |
| return gsw_autosleep_enable(); | |
| } | |
| /** | |
| * @brief disenable autosleep | |
| * @return int : 0 is success , other failed | |
| */ | |
| int gswAutoSleepDisable(void) | |
| { | |
| return gsw_autosleep_disenable(); | |
| } | |
| /** | |
| * @brief modem relase wakeuplock | |
| * @return void | |
| */ | |
| void gswPMStartSleep(void) | |
| { | |
| gsw_pm_enter_sleep(GSW_WAKELOCK_NAME); | |
| } | |
| /** | |
| * @brief modem add wakeuplock | |
| * @return int : 0 is success , other failed | |
| */ | |
| int gswPMStopSleep(void) | |
| { | |
| return gsw_pm_exit_sleep(GSW_WAKELOCK_NAME); | |
| } | |
| int gswPmSDKInit(gsw_pm_wakeup_handler gswPmCallBack) | |
| { | |
| return gsw_pm_sdk_init(gswPmCallBack); | |
| } |