| /** |
| * @file rtc-service.c |
| * @brief Implementation of Sanechips |
| * |
| * Copyright (C) 2017 Sanechips Technology Co., Ltd. |
| * @author linxu Gebin |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| */ |
| |
| /******************************************************************************* |
| * Include header files * |
| ******************************************************************************/ |
| #include "rtc-service.h" |
| #include "hotplug.h" |
| #include <limits.h> |
| |
| /******************************************************************************* |
| * Global variable definitions * |
| ******************************************************************************/ |
| int g_rtc_fd = 0; |
| struct list_head rtc_timer_list; |
| struct list_head rtc_alarm_list; |
| #define RTC_ALARM_TIMEOUT_MSG "PMIC RTC ALARM IRQ COME" |
| #define RTC_TIMER_TIMEOUT_MSG "PMIC RTC TIMER IRQ COME" |
| |
| #ifdef PRODUCT_NOT_USE_RTC |
| time_t g_set_softtime; |
| #define RTC_USE_SOFTTIMER_ID 300 //µ±Ã»ÓÐrtcʱ£¬ÔÏÈʹÓÃrtc¶¨Ê±Æ÷µÄÓÐrtcͳһÊÊÅäµ½softtimerÉÏ£¬Õû¸ö¿ò¼Ü²»±ä |
| #endif |
| /******************************************************************************* |
| * Local variable definitions * |
| ******************************************************************************/ |
| static pthread_t rtc_looper_id = 0; |
| static int g_clean_flag = 0; |
| static int g_time_offset = 2; //ÔÊÐíÎó²î·¶Î§£¬ÊÊÅärtcºÍOSʱÖÓÆµÂʲ»Ò»ÖÂÎÊÌâ |
| /******************************************************************************* |
| * Local function implementations * |
| ******************************************************************************/ |
| static int open_rtc(void); |
| static void close_rtc(int fd); |
| static void* rtc_looper(); |
| static int start_rtc_thread(); |
| static int handle_get_time(MSG_BUF *pmsg_buf); |
| static int handle_set_time(MSG_BUF *pmsg_buf); |
| static int handle_alarm_add(MSG_BUF *pmsg_buf); |
| static int handle_alarm_del(MSG_BUF *pmsg_buf); |
| static int handle_alarm_timeout(MSG_BUF *pmsg_buf); |
| static int process_msg(MSG_BUF *pmsg_buf); |
| static void msg_looper(void); |
| static void update_timer_remain(int new_remian); |
| static void alarm_fix_value(struct list_head *rtc_list); |
| static void alarm_restart(struct list_head *rtc_list); |
| static void update_alarm(); |
| static void alarm_adjust_value(int time); |
| static long get_RtcTime(); |
| static void convert_time(time_t timeSec, struct tm * tmTime, TIME_CONVERT_TYPE type); |
| static void convert_time(time_t timeSec, struct tm * tmTime, TIME_CONVERT_TYPE type) |
| { |
| time_t tmpTime = 0; |
| if(tmTime == NULL) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: wrong input param, check it! \n"); |
| return ; |
| } |
| tmpTime = timeSec; |
| |
| if(type == CONVERT_TYPE_RTC) { |
| gmtime_r((time_t*)&tmpTime, tmTime); |
| } |
| else { |
| localtime_r((time_t*)&tmpTime, tmTime); |
| } |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "Time:%ld, tm_year:%d, tm_mon:%d, tm_hour:%d, tm_min:%d, tm_sec:%d, tm_yday:%d, tm_mday:%d, tm_wday:%d \n", |
| mktime(tmTime), tmTime->tm_year, tmTime->tm_mon, tmTime->tm_hour, tmTime->tm_min, tmTime->tm_sec, tmTime->tm_yday, tmTime->tm_mday, tmTime->tm_wday); |
| |
| } |
| |
| static long get_RtcTime() |
| { |
| long curRtcTime = 0; |
| struct rtc_time rtc_tm = {0}; |
| struct tm tmp = {0}; |
| if(g_rtc_fd <= 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: g_rtc_fd: %d , invalid fd. \n", g_rtc_fd); |
| return -1; |
| } |
| |
| if(ioctl(g_rtc_fd, RTC_RD_TIME, &rtc_tm) < 0) // cov M CHECKED_RETURN |
| { |
| slog(RTC_PRINT, SLOG_ERR, "ioctl fail.\n"); |
| } |
| tmp.tm_sec = rtc_tm.tm_sec; |
| tmp.tm_min= rtc_tm.tm_min; |
| tmp.tm_hour= rtc_tm.tm_hour; |
| tmp.tm_mon= rtc_tm.tm_mon; |
| tmp.tm_year= rtc_tm.tm_year; |
| tmp.tm_mday= rtc_tm.tm_mday; |
| tmp.tm_wday= rtc_tm.tm_wday; |
| tmp.tm_yday= rtc_tm.tm_yday; |
| tmp.tm_isdst= rtc_tm.tm_isdst; |
| |
| curRtcTime = mktime(&tmp); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: curRtcTime: %ld . \n", curRtcTime); |
| return curRtcTime; |
| } |
| static void write_lockfile(char *filepath, char *setbuf) |
| { |
| int f, len = 0; |
| |
| f = open(filepath, O_RDWR); |
| if (f == -1) { |
| return; |
| } |
| |
| len = strlen(setbuf); |
| if (write(f, setbuf, len) != len) { |
| } else { |
| } |
| close(f); |
| } |
| |
| |
| static void wake_rtc_lock() |
| { |
| write_lockfile("/sys/power/wake_lock", "rtc_lock"); |
| } |
| |
| static void wake_rtc_unlock() |
| { |
| write_lockfile("/sys/power/wake_unlock", "rtc_lock"); |
| } |
| |
| static void wake_rtc_io_lock() |
| { |
| write_lockfile("/sys/power/wake_lock", "rtc_io_lock"); |
| } |
| |
| static void wake_rtc_io_unlock() |
| { |
| write_lockfile("/sys/power/wake_unlock", "rtc_io_lock"); |
| } |
| |
| static void wake_timeout_lock(char *lockname, unsigned long interval) |
| { |
| char cmd[100] = {0}; |
| sprintf(cmd, "echo %s %lu > /sys/power/wake_lock", lockname, interval); |
| soft_system(cmd); |
| } |
| |
| static int init_rtc_alarm(void) |
| { |
| FILE* fp = NULL; |
| int gap_start = 0; |
| int gap_end = 0; |
| size_t size = 0; |
| long cur_rtc_time = 0; |
| ALARM_T* iter = NULL; |
| RTC_DATA_BUF buf = {0}; |
| int ret = -1; |
| |
| // cur_rtc_time = get_RtcTime(); |
| cur_rtc_time = time(0); |
| if ((fp = (FILE*)fopen(RTC_ALARM_DATA, "rb")) == NULL) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: failed to open %s \n", RTC_ALARM_DATA); |
| return -1; |
| } |
| |
| while(1) |
| { |
| size = fread(&gap_start, sizeof(int), 1, fp);//0xa5a5 |
| if(0 == size || gap_start != DATA_S ||feof(fp) != 0 ) |
| break; |
| |
| iter = (ALARM_T*)malloc(sizeof(ALARM_T)); |
| if(iter) |
| memset(iter,0,sizeof(ALARM_T)); |
| else |
| { |
| fclose(fp); |
| return -1; |
| } |
| |
| size = fread(iter, sizeof(ALARM_T), 1, fp);//struct |
| if(0 ==size||feof(fp) != 0)//check the end of the file |
| { |
| memset(iter, 0, sizeof(ALARM_T));//kw |
| free(iter); |
| break; |
| } |
| |
| size = fread(&gap_end, sizeof(int), 1, fp);//0x5a5a |
| if(0 == size || gap_end != DATA_E ||feof(fp) != 0) |
| { |
| memset(iter, 0, sizeof(ALARM_T));//kw |
| free(iter); |
| break; |
| } |
| |
| if(iter->interval < 0 || iter->interval > LONG_MAX-1) |
| { |
| iter->interval = 0 ; |
| } |
| |
| |
| if(iter->time_val < 0 || iter->time_val > LONG_MAX-1) |
| { |
| iter->time_val = 0 ; |
| } |
| |
| |
| if(cur_rtc_time > iter->interval + iter->time_val) |
| { |
| buf.module = iter->rtc_id; |
| buf.time_val = iter->time_val + iter->interval; |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_alarm_timeout: target:0x%x, rtc_id:0x%x, utc:%d, cur_rtc_time:%ld \n", iter->module_id, buf.module, iter->is_utc, cur_rtc_time); |
| ret = ipc_send_message2(MODULE_ID_RTC_SERVICE, iter->module_id, RTC_MSG_ALARM_ELAPSED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: ipc_send_message unexpected\n"); |
| } |
| } |
| list_add_tail(&iter->list, &rtc_alarm_list); |
| if(feof(fp) != 0)//check the end of the file |
| break; |
| } |
| fclose(fp); |
| |
| return 0; |
| } |
| |
| static int save_rtc_alarm(void) |
| { |
| FILE* fp = NULL; |
| int gap_start = DATA_S; |
| int gap_end = DATA_E; |
| ALARM_T *temp = NULL; |
| |
| if ((fp = (FILE*)fopen(RTC_ALARM_DATA, "wb")) == NULL) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: failed to open %s \n", RTC_ALARM_DATA); |
| return -1; |
| } |
| |
| if (!list_empty(&rtc_alarm_list)) { |
| list_for_each_entry(temp, &rtc_alarm_list, list) { |
| if(temp->wakeup) |
| { |
| fwrite(&gap_start, sizeof(int), 1, fp); |
| fwrite(temp, sizeof(ALARM_T), 1, fp); |
| fwrite(&gap_end, sizeof(int), 1, fp); |
| } |
| } |
| } |
| |
| fflush(fp); |
| if(fsync(fileno(fp)) < 0) |
| { |
| // todo: cov M |
| } |
| fclose(fp); |
| |
| return 0; |
| } |
| |
| /******************************************** |
| ¹¦ÄÜ:´ò¿ªrtc |
| *******************************************/ |
| static int open_rtc(void) |
| { |
| int fd = 0; |
| fd = open(RTC_DEV_NAME, O_RDWR); |
| |
| if (fd < 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: Open %s error!\n", RTC_DEV_NAME); |
| return fd; |
| } |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: Open %s OK!\n", RTC_DEV_NAME); |
| return fd; |
| } |
| |
| /******************************************** |
| ¹¦ÄÜ:¹Ø±Õrtc |
| *******************************************/ |
| static void close_rtc(int fd) |
| { |
| if (fd < 0) { |
| return; |
| } |
| |
| close(fd); |
| } |
| |
| |
| /******************************************** |
| * handle_get_time |
| * get RTC time. |
| *******************************************/ |
| static int handle_get_time(MSG_BUF *pmsg_buf) |
| { |
| struct rtc_time rtc_tm = {0}; |
| int ret = 0; |
| RTC_DATA_BUF * buf = pmsg_buf->aucDataBuf; |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_get_time NOOPS.\n"); |
| |
| if(buf->cpu == RTC_CPU_CAP) |
| { |
| int cmd = RTC_MSG_GET_TIME; |
| RTC_DATA_BUF sendbuf = {0}; |
| unsigned long cur_sec =0; |
| |
| ret = ioctl(g_rtc_fd, RTC_RD_TIME, &rtc_tm); |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_get_time tm_year:%d, tm_mon:%d, tm_hour:%d, tm_min:%d, tm_yday:%d, tm_mday:%d, tm_wday:%d.\n", |
| rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_yday, rtc_tm.tm_mday, rtc_tm.tm_wday); |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_get_time src_id:0x%x, buf->cpu:%d.\n",buf->srcModule,buf->cpu); |
| |
| cur_sec = mktime(&rtc_tm); |
| sendbuf.srcModule = buf->srcModule; |
| sendbuf.cpu = RTC_CPU_AP; |
| sendbuf.ulSec = cur_sec; |
| |
| slog(RTC_PRINT, SLOG_NORMAL, "[rtc] handle_get_time: send to cap cmd:0x%x, srcMod:0x%x, cur_sec:%lu \n", cmd, sendbuf.srcModule, sendbuf.ulSec); |
| ret = send_soc_msg(FAR_PS, MODULE_ID_RTC_SERVICE, cmd, sizeof(RTC_DATA_BUF), (void *)&sendbuf); |
| if (ret != 0) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: ipc_send_message unexpected,ret:%d\n",ret);; |
| } |
| } |
| |
| return 0; |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:ÉèÖÃrtcʱ¼ä |
| *******************************************/ |
| static int handle_set_time(MSG_BUF *pmsg_buf) |
| { |
| time_t os_time = 0; |
| struct tm tmTime = {0}; |
| struct rtc_time rtc_tm = {0}; |
| int ret = 0; |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_set_time enter.\n"); |
| memcpy(&os_time, pmsg_buf->aucDataBuf, sizeof(time_t)); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_set_time enter: set time: %ld \n", os_time); |
| convert_time(os_time, &tmTime, CONVERT_TYPE_RTC); |
| memcpy(&rtc_tm, &tmTime, sizeof(struct rtc_time)); |
| slog(RTC_PRINT, SLOG_ERR, "Time:%ld, tm_year:%d, tm_mon:%d, tm_hour:%d, tm_min:%d, tm_sec:%d, tm_yday:%d, tm_mday:%d, tm_wday:%d \n", |
| mktime(&tmTime), rtc_tm.tm_year, rtc_tm.tm_mon, rtc_tm.tm_hour, rtc_tm.tm_min, tmTime.tm_sec, rtc_tm.tm_yday, rtc_tm.tm_mday, rtc_tm.tm_wday); |
| |
| ret = ioctl(g_rtc_fd, RTC_SET_TIME, &rtc_tm); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: RTC_SET_TIME ioctl ret = %d exit.\n", ret); |
| { |
| char buf[32] = {0}; |
| snprintf(buf,32,"AT+ZMMI=2,%d,%d\r\n",1900 + rtc_tm.tm_year,1 + rtc_tm.tm_mon); |
| ret = get_modem_info(buf, NULL, NULL); |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: handle_set_time ret=%d %s\n",ret,buf); |
| } |
| return 0; |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:sntpͬ²½ÏµÍ³Ê±¼ä |
| *******************************************/ |
| static int handle_sntp_update(MSG_BUF *pmsg_buf) |
| { |
| time_t os_time = 0; |
| struct timeval time_tv = {0}; |
| int ret = 0; |
| |
| memcpy(&os_time, pmsg_buf->aucDataBuf, sizeof(time_t)); |
| |
| time_tv.tv_sec = os_time; |
| ret = settimeofday(&time_tv,NULL); |
| if(ret!=0) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "handle_sntp_update is fail,ret:%d \n",ret); |
| } |
| return 0; |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:Ôö¼Ó¶¨Ê±Æ÷ |
| *******************************************/ |
| static int handle_alarm_add(MSG_BUF *pmsg_buf) |
| { |
| //long cur_rtc_time = 0; |
| |
| struct rtc_time rtc_tm = {0}; |
| ALARM_T *pAlarm = 0; |
| |
| RTC_DATA_BUF *buf = pmsg_buf->aucDataBuf; |
| ALARM_T *temp = NULL; |
| int mark = 0; |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_add enter.\n"); |
| |
| if (buf->ulSec <= 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: handle_alarm_add invalid interval.\n"); |
| return -1; |
| } |
| |
| pAlarm = malloc(sizeof(ALARM_T)); |
| if (pAlarm == NULL) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: handle_alarm_add no memory.\n"); |
| return -1; |
| } |
| |
| //»ñÈ¡µ±Ç°Ê±¼ä second |
| if(ioctl(g_rtc_fd, RTC_RD_TIME, &rtc_tm) < 0) // cov M CHECKED_RETURN |
| { |
| slog(RTC_PRINT, SLOG_ERR, "ioctl fail.\n"); |
| } |
| memcpy(&pAlarm->rtc_tm, &rtc_tm, sizeof(rtc_tm)); |
| |
| pAlarm->rtc_id = buf->module; |
| pAlarm->module_id = buf->srcModule; |
| pAlarm->interval = buf->ulSec ; // count down time |
| pAlarm->remain_time = buf->ulSec; // remain count down time |
| pAlarm->wakeup = buf->wakeup; |
| pAlarm->is_utc = buf->is_utc; |
| pAlarm->cpu = buf->cpu; |
| pAlarm->time_val = buf->time_val;// cur_rtc_time is mktime(&local_tm) |
| //pAlarm->time_val = get_RtcTime();// cur_rtc_time is mktime(&local_tm) |
| |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_alarm_add pAlarm->interval is %ld ,pAlarm->time_val() is %ld, is_utc:%d.\n", |
| pAlarm->interval, pAlarm->time_val, pAlarm->is_utc); |
| /* |
| if (pAlarm->time_val + pAlarm->remain_time < cur_rtc_time) { |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service handle_alarm_add error, pAlarm->remain_time = %ld, pAlarm->time_val = %ld, current= %ld\n", pAlarm->remain_time, pAlarm->time_val, cur_rtc_time); |
| } |
| */ |
| |
| #ifdef PRODUCT_NOT_USE_RTC |
| pAlarm->is_utc = 0; //´Ëģʽ϶¼°´timerÉèÖö¨Ê±Æ÷£¬²»Ö§³Öutc |
| pAlarm->wakeup = 0; |
| #endif |
| |
| if (pAlarm->is_utc == 0) { |
| if (!list_empty(&rtc_timer_list)) { |
| //update_timer_remain(pAlarm->remain_time); |
| list_for_each_entry(temp, &rtc_timer_list, list) { |
| if (temp->remain_time > pAlarm->remain_time) { |
| mark = 1; |
| list_add(&pAlarm->list, temp->list.prev); |
| break; |
| } |
| } |
| } |
| if (mark == 0) { |
| list_add_tail(&pAlarm->list, &rtc_timer_list); |
| } |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: add rtc timer\n"); |
| alarm_restart(&rtc_timer_list); |
| } else { |
| if (!list_empty(&rtc_alarm_list)) { |
| list_for_each_entry(temp, &rtc_alarm_list, list) { |
| if (temp->interval + temp->time_val > pAlarm->interval + pAlarm->time_val) { |
| mark = 1; |
| list_add(&pAlarm->list, temp->list.prev); |
| break; |
| } |
| } |
| } |
| if (mark == 0) { |
| list_add_tail(&pAlarm->list, &rtc_alarm_list); |
| } |
| |
| if(pAlarm->wakeup) |
| save_rtc_alarm(); |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: add rtc alarm \n"); |
| alarm_restart(&rtc_alarm_list); |
| } |
| |
| return 0; |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:°´µ±Ç°¶¨Ê±Æ÷Ê£Óàʱ¼ä¸üж¨Ê±Æ÷ |
| *******************************************/ |
| static void update_timer_remain(int new_remian) |
| { |
| if (list_empty(&rtc_timer_list)) { |
| return; |
| } |
| int ret, remain_time; |
| ALARM_T *pTmp; |
| //list_entry(pTmp, &rtc_timer_list, list); |
| pTmp = list_entry(rtc_timer_list.next, ALARM_T, list); |
| |
| #ifdef PRODUCT_NOT_USE_RTC |
| time_t cur = time(NULL); |
| remain_time = g_set_softtime + pTmp->remain_time - cur; |
| if ((remain_time > pTmp->remain_time) || (remain_time <= 0)) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: cur:%u, set:%u, remain:%u, inveral:%u\n", cur, g_set_softtime, remain_time, pTmp->remain_time); |
| //ʱ¼ä·¢Éú¹ýÖØÖõȣ¬Ö±½ÓÉèÖö¨Ê±Æ÷µ½£¬¸÷Ä£¿éÓ¦ÔÚÊÕµ½RTC_MSG_TIME_CHANGEDÏûϢʱ¼°Ê±¸üж¨Ê±Æ÷ |
| remain_time = 0; |
| } |
| #else |
| ret = ioctl(g_rtc_fd, ZX234290_GET_TIMER_REMAIN, &remain_time); |
| #endif |
| if (ret < 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: handle_alarm_add no free alarm remain_time %d %s errno.\n", errno, strerror(errno)); |
| // return -1; |
| } |
| //if(remain_time > new_remian) |
| { |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: pTmp->remain_time: %d, rtc remain_time: %d \n", pTmp->remain_time, remain_time); |
| alarm_adjust_value(pTmp->remain_time - remain_time); |
| alarm_fix_value(&rtc_timer_list); |
| } |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:ɾ³ýÏûÏ¢Ô´Ä£¿éµÄËùÓж¨Ê±Æ÷ |
| *******************************************/ |
| static int handle_alarm_del(MSG_BUF *pmsg_buf) |
| { |
| RTC_DATA_BUF * buf = pmsg_buf->aucDataBuf; |
| ALARM_T *pTmp, *pTmp1; |
| int wakeup = 0; |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_del enter.\n"); |
| list_for_each_entry_safe(pTmp, pTmp1, &rtc_timer_list, list) { |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_del timer module:0x%x - 0x%x, src:0x%x - 0x%x.\n", |
| buf->module, pTmp->rtc_id, buf->srcModule, pTmp->module_id); |
| if ((buf->module == pTmp->rtc_id) && (buf->srcModule == pTmp->module_id)&& (buf->cpu == pTmp->cpu)) { |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_alarm_del timer module:0x%x , src:0x%x , cpu:%d \n", |
| buf->module, buf->srcModule, buf->cpu); |
| list_del(&pTmp->list); |
| free(pTmp); |
| break; |
| } |
| } |
| |
| list_for_each_entry_safe(pTmp, pTmp1, &rtc_alarm_list, list) { |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_del alarm module:0x%x - 0x%x, src:0x%x - 0x%x.\n", |
| buf->module, pTmp->rtc_id, buf->srcModule, pTmp->module_id); |
| if ((buf->module == pTmp->rtc_id) && (buf->srcModule == pTmp->module_id)&& (buf->cpu == pTmp->cpu)) { |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_alarm_del alarm module:0x%x , src:0x%x , cpu:%d \n", |
| buf->module, buf->srcModule, buf->cpu); |
| wakeup = pTmp->wakeup; |
| list_del(&pTmp->list); |
| free(pTmp); |
| break; |
| } |
| } |
| |
| if(wakeup) |
| save_rtc_alarm(); |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_del exit.\n"); |
| |
| return 0; |
| } |
| |
| void send_ok_del_rsp(MSG_BUF *pmsg_buf) |
| { |
| RTC_DATA_BUF * buf = pmsg_buf->aucDataBuf; |
| |
| if(buf->cpu == RTC_CPU_CAP) |
| { |
| int ret = 0; |
| RTC_DATA_BUF sendbuf = {0}; |
| sendbuf.cpu = RTC_CPU_AP; |
| sendbuf.module = buf->module; |
| sendbuf.srcModule = buf->srcModule; |
| ret = send_soc_msg(FAR_PS, MODULE_ID_RTC_SERVICE, RTC_MSG_DEL_ALARM, sizeof(RTC_DATA_BUF), (void *)&sendbuf); |
| if (ret != 0) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "send_ok_del_rsp: failed,ret:%d\n",ret); |
| } |
| } |
| } |
| /******************************************** |
| *¹¦ÄÜ:¶¨Ê±Æ÷³¬Ê±´¦Àí |
| *******************************************/ |
| static int handle_alarm_timeout(MSG_BUF *pmsg_buf) |
| { |
| long ret = -1; |
| ALARM_T *pAlarm; |
| RTC_DATA_BUF buf = {0}; |
| long rtc_report_time = 0; |
| long alarm_node_time = 0; |
| enum RTC_MSG_CMD cmd = pmsg_buf->usMsgCmd; |
| int wakeup = 0; |
| |
| if (cmd == RTC_MSG_TIMER_TIMEOUT && !list_empty(&rtc_timer_list)) { |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: rtc timer timeout\n"); |
| pAlarm = list_entry(rtc_timer_list.next, ALARM_T, list); |
| } else if (cmd == RTC_MSG_ALARM_TIMEOUT && !list_empty(&rtc_alarm_list)) { |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: rtc alarm timeout\n"); |
| pAlarm = list_entry(rtc_alarm_list.next, ALARM_T, list); |
| rtc_report_time = atol(pmsg_buf->aucDataBuf); |
| if (rtc_report_time < 0 || rtc_report_time > LONG_MAX-1) |
| { |
| rtc_report_time = 0; |
| } |
| alarm_node_time = pAlarm->interval + pAlarm->time_val; |
| if((rtc_report_time>alarm_node_time && (rtc_report_time-alarm_node_time)>g_time_offset) |
| ||(alarm_node_time>rtc_report_time && (alarm_node_time-rtc_report_time)>g_time_offset)) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: rtc node was deleted, timeout unexpected; node:%ld, rtc:%ld \n", alarm_node_time, rtc_report_time); |
| alarm_fix_value(&rtc_alarm_list); |
| |
| if(pAlarm->wakeup) |
| save_rtc_alarm(); |
| |
| alarm_restart(&rtc_alarm_list); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_timeout restart alarm.\n"); |
| return 0; |
| } |
| buf.time_val = alarm_node_time; |
| } else { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: timeout unexpected\n"); |
| return -1; |
| } |
| |
| wakeup = pAlarm->wakeup; |
| list_del(&pAlarm->list); |
| buf.module = pAlarm->rtc_id; |
| buf.srcModule = pAlarm->module_id; |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: handle_alarm_timeout: target:0x%x, rtc_id:0x%x, utc:%d \n", pAlarm->module_id, buf.module, pAlarm->is_utc); |
| if(pAlarm->cpu == RTC_CPU_AP) |
| { |
| ret = ipc_send_message2(MODULE_ID_RTC_SERVICE, pAlarm->module_id, RTC_MSG_ALARM_ELAPSED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: ipc_send_message unexpected,ret:%d\n",ret); |
| } |
| } |
| else |
| { |
| buf.module = pAlarm->rtc_id; |
| buf.srcModule = pAlarm->module_id; |
| buf.cpu = RTC_CPU_AP; |
| buf.is_utc = pAlarm->is_utc; |
| |
| slog(RTC_PRINT, SLOG_NORMAL, "[rtc] handle_alarm_timeout: send to cap cmd:0x%x, srcMod:0x%x, module:0x%x, utc:%d \n", cmd, buf.srcModule, buf.module, pAlarm->is_utc); |
| ret = send_soc_msg(FAR_PS, MODULE_ID_RTC_SERVICE, cmd, sizeof(RTC_DATA_BUF), (void *)&buf); |
| if (ret != 0) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: ipc_send_message unexpected,ret:%d\n",ret);; |
| } |
| } |
| if (pAlarm->is_utc == 0) { |
| alarm_adjust_value(pAlarm->remain_time); |
| alarm_fix_value(&rtc_timer_list); |
| alarm_restart(&rtc_timer_list); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_timeout restart imer.\n"); |
| } else { |
| alarm_fix_value(&rtc_alarm_list); |
| if(wakeup) |
| save_rtc_alarm(); |
| alarm_restart(&rtc_alarm_list); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_timeout restart alarm.\n"); |
| } |
| |
| free(pAlarm); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: handle_alarm_timeout exit.\n"); |
| return 0; |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:ɾ³ý¹Ø»ú²»±£´æµÄ¶¨Ê±Æ÷ |
| *******************************************/ |
| static void handle_del_all(MSG_BUF *pmsg_buf) |
| { |
| ALARM_T *pTmp, *pTmp1; |
| |
| update_timer_remain(0); |
| list_for_each_entry_safe(pTmp, pTmp1, &rtc_timer_list, list) { |
| if (pTmp->wakeup == 0) { |
| list_del(&pTmp->list); |
| free(pTmp); |
| } |
| } |
| alarm_restart(&rtc_timer_list); |
| |
| list_for_each_entry_safe(pTmp, pTmp1, &rtc_alarm_list, list) { |
| if (pTmp->wakeup == 0) { |
| list_del(&pTmp->list); |
| free(pTmp); |
| } |
| } |
| alarm_restart(&rtc_alarm_list); |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:sntpͬ²½³É¹¦ºó£¬¸üÐÂalarm_list |
| *******************************************/ |
| static void update_alarm() |
| { |
| ALARM_T *pTmp, *pTmp1; |
| //long sec = get_RtcTime(); |
| long sec = time(0); |
| RTC_DATA_BUF buf = {0}; |
| |
| #ifdef PRODUCT_NOT_USE_RTC |
| list_for_each_entry_safe(pTmp, pTmp1, &rtc_timer_list, list) { |
| buf.module = pTmp->rtc_id; |
| ipc_send_message2(MODULE_ID_RTC_SERVICE, pTmp->module_id, RTC_MSG_TIME_CHANGED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| if(pTmp->is_utc){ |
| if (pTmp->interval + pTmp->time_val < sec) { |
| list_del(&pTmp->list); |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: delete ELAPSED timer, alarm_id(%d), alarm_time(%ld).\n", pTmp->rtc_id, (pTmp->interval + pTmp->time_val)); |
| free(pTmp); |
| } else { |
| pTmp->remain_time = pTmp->interval + pTmp->time_val - sec; |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: timer adjust, alarm_id(%d), alarm_time(%ld), remain(%ld).\n", pTmp->rtc_id, (pTmp->interval + pTmp->time_val), pTmp->remain_time); |
| } |
| } |
| } |
| alarm_restart(&rtc_timer_list); |
| #else |
| list_for_each_entry_safe(pTmp, pTmp1, &rtc_alarm_list, list) { |
| buf.module = pTmp->rtc_id; |
| ipc_send_message2(MODULE_ID_RTC_SERVICE, pTmp->module_id, RTC_MSG_TIME_CHANGED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| if (pTmp->interval + pTmp->time_val < sec) { |
| list_del(&pTmp->list); |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: delete ELAPSED alarm, alarm_id(%d), alarm_time(%ld).\n", pTmp->rtc_id, (pTmp->interval + pTmp->time_val)); |
| free(pTmp); |
| } |
| } |
| alarm_restart(&rtc_alarm_list); |
| #endif |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: update_alarm exit cur_rtc_time: % ld.\n", sec); |
| } |
| |
| /******************************************** |
| * ¹¦ÄÜ:¸üж¨Ê±Æ÷Ê£Óàʱ¼ä |
| *******************************************/ |
| static void alarm_adjust_value(int time) |
| { |
| ALARM_T * temp; |
| list_for_each_entry(temp, &rtc_timer_list, list) { |
| temp->remain_time -= time; |
| } |
| } |
| |
| /******************************************** |
| *¹¦ÄÜ: ɾ³ýÎÞЧ¶¨Ê±Æ÷ |
| *******************************************/ |
| static void alarm_fix_value(struct list_head *rtc_list) |
| { |
| ALARM_T *pTmp, *pTmp1; |
| RTC_DATA_BUF buf = {0}; |
| int wakeup = 0; |
| int ret =0; |
| enum RTC_MSG_CMD cmd = 0; |
| |
| if (rtc_list == &rtc_timer_list) { |
| list_for_each_entry_safe(pTmp, pTmp1, rtc_list, list) { |
| if (pTmp->remain_time <= 0) { |
| buf.module = pTmp->rtc_id; |
| if(pTmp->cpu == RTC_CPU_CAP) |
| { |
| buf.srcModule = pTmp->module_id; |
| buf.cpu = RTC_CPU_AP; |
| buf.is_utc = pTmp->is_utc; |
| cmd = RTC_MSG_TIMER_TIMEOUT; |
| slog(RTC_PRINT, SLOG_NORMAL, "[rtc] handle_alarm_timeout: send to cap cmd:0x%x, srcMod:0x%x, module:0x%x, utc:%d \n", cmd, buf.srcModule, buf.module, buf.is_utc); |
| ret = send_soc_msg(FAR_PS, MODULE_ID_RTC_SERVICE, cmd, sizeof(RTC_DATA_BUF), (void *)&buf); |
| if (ret != 0) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: send_soc_msg unexpected,ret:%d\n",ret);; |
| } |
| } |
| else |
| { |
| ipc_send_message2(MODULE_ID_RTC_SERVICE, pTmp->module_id, RTC_MSG_ALARM_ELAPSED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| } |
| list_del(&pTmp->list); |
| free(pTmp); |
| } |
| } |
| } else if (rtc_list == &rtc_alarm_list) { |
| list_for_each_entry_safe(pTmp, pTmp1, rtc_list, list) { |
| if (pTmp->time_val + pTmp->interval <= (time(0) + g_time_offset)) { |
| if(pTmp->wakeup) |
| wakeup = pTmp->wakeup; |
| |
| buf.module = pTmp->rtc_id; |
| buf.time_val = pTmp->time_val + pTmp->interval; |
| if(pTmp->cpu == RTC_CPU_CAP) |
| { |
| buf.srcModule = pTmp->module_id; |
| buf.cpu = RTC_CPU_AP; |
| buf.is_utc = pTmp->is_utc; |
| cmd = RTC_MSG_ALARM_TIMEOUT; |
| slog(RTC_PRINT, SLOG_NORMAL, "[rtc] handle_alarm_timeout: send to cap cmd:0x%x, srcMod:0x%x, module:0x%x, utc:%d \n", cmd, buf.srcModule, buf.module, buf.is_utc); |
| ret = send_soc_msg(FAR_PS, MODULE_ID_RTC_SERVICE, cmd, sizeof(RTC_DATA_BUF), (void *)&buf); |
| if (ret != 0) |
| { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: send_soc_msg unexpected,ret:%d\n",ret);; |
| } |
| } |
| else |
| { |
| ipc_send_message2(MODULE_ID_RTC_SERVICE, pTmp->module_id, RTC_MSG_ALARM_ELAPSED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| } |
| list_del(&pTmp->list); |
| free(pTmp); |
| } |
| } |
| |
| if(wakeup) |
| save_rtc_alarm(); |
| } |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: alarm_fix_value exit.\n"); |
| } |
| |
| #ifdef PRODUCT_NOT_USE_RTC |
| /*¶ÔӦûÓÐrtcµÄ²úÆ·£¬rtc¶¨Ê±Æ÷ÊÊÅäµ½softtimerµÄ»Øµ÷º¯Êý*/ |
| static void rtc_set_softtimer_cb(void *param) |
| { |
| int ret = -1; |
| |
| slog(NET_PRINT, SLOG_ERR, "rtc-service: rtc_adapt_softtimer_cb \n"); |
| |
| ret = ipc_send_message(MODULE_ID_RTC_SERVICE, MODULE_ID_RTC_SERVICE, RTC_MSG_TIMER_TIMEOUT, 0, 0, 0);; |
| if (ret != 0) { |
| slog(MISC_PRINT, SLOG_ERR, "rtc-service: set rtc timer send msg failed \n"); |
| } |
| return 0; |
| } |
| #endif |
| |
| /******************************************** |
| * ¹¦ÄÜ:ÖØÆô¶¨Ê±Æ÷£¬Ã»ÓÐÔò¹Ø±Õ¶¨Ê±Æ÷ |
| *******************************************/ |
| static void alarm_restart(struct list_head *rtc_list) |
| { |
| int ret = 0; |
| //struct tm *p_tm = 0; |
| struct tm ret_tm = {0}; |
| struct rtc_wkalrm alarm = {0}; |
| long tVal = 0; |
| long remain = -1; |
| ALARM_T *ptmp = NULL; |
| long cur_rtc_time = time(0); |
| RTC_DATA_BUF buf = {0}; |
| NEXT: |
| if (!list_empty(rtc_list)) { |
| ptmp = list_entry(rtc_list->next, ALARM_T, list); |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: alarm_restart enter.\n"); |
| memset(&buf, 0, sizeof(RTC_DATA_BUF)); |
| if (ptmp->is_utc == 0) { |
| #ifdef PRODUCT_NOT_USE_RTC |
| g_set_softtime = time(NULL); |
| sc_timer_delete(RTC_USE_SOFTTIMER_ID); |
| ret = sc_timer_create(RTC_USE_SOFTTIMER_ID, TIMER_FLAG_ONCE, ptmp->remain_time*1000, rtc_set_softtimer_cb, NULL); |
| #else |
| ret = ioctl(g_rtc_fd, ZX234290_SET_TIMER, ptmp->remain_time); |
| #endif |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: alarm_restart timer: set failed, ret:%d \n", ret); |
| return; |
| } |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: alarm_restart: set timer ok, remain_time:%ld, cur_rtc_time:%ld, module:0x%x, rtc_id:0x%x\n", ptmp->remain_time, cur_rtc_time, ptmp->module_id, ptmp->rtc_id); |
| } else { |
| tVal = ptmp->interval + ptmp->time_val; |
| remain = tVal - cur_rtc_time; |
| if (remain <= g_time_offset) { |
| //¹ýʱ¶¨Ê±Æ÷¶ªÆú´¦Àí£¬Èç¹û¶àÄ£¿éÕýºÃÉèµÄ»ù±¾ÔÚͬһ¸öʱ¼äµã£¬ºóÕ߻ᱻ¶ªÆú£¬¿¼ÂÇÐ޸ijÉÖ±½Ó֪ͨģ¿éʱ¼äµ½ |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: remain time error, time_set:%ld, remain:%ld, alarmer:%ld, interval:%ld, current:%ld, module:0x%x, rtc_id:0x%x\n", ptmp->time_val, remain, tVal, ptmp->interval, cur_rtc_time, ptmp->module_id, ptmp->rtc_id); |
| buf.module = ptmp->rtc_id; |
| buf.time_val = ptmp->time_val + ptmp->interval; |
| ipc_send_message2(MODULE_ID_RTC_SERVICE, ptmp->module_id, RTC_MSG_ALARM_ELAPSED, sizeof(RTC_DATA_BUF), (unsigned char*)&buf, 0); |
| list_del(&ptmp->list); |
| free(ptmp); |
| ptmp = NULL; |
| goto NEXT; |
| } |
| |
| //localtime_r(&tVal, &ret_tm); |
| gmtime_r(&tVal, &ret_tm); |
| memcpy(&alarm.time, &ret_tm, sizeof(struct rtc_time)); |
| alarm.enabled = 1; |
| |
| /*Ê×ÏÈ´ò¿ªalarm ÖжÏ*/ |
| ret = ioctl(g_rtc_fd, RTC_AIE_ON); |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: open alarm failed, ret:%d\n", ret); |
| return; |
| } |
| |
| /*ÉèÖÃalarm ʱ¼ä*/ |
| ret = ioctl(g_rtc_fd, RTC_WKALM_SET, &alarm); |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: set alarm failed, ret:%d\n", ret); |
| return; |
| } |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: alarm_restart set alarm ok, remain_time:%ld, cur_rtc_time:%ld, module:0x%x, rtc_id:0x%x \n", remain, cur_rtc_time, ptmp->module_id, ptmp->rtc_id); |
| } |
| } else { |
| if (rtc_list == &rtc_timer_list) { |
| //¹Ø±Õrtc time, Éè¼ä¸ôʱ¼äΪ0 |
| ret = ioctl(g_rtc_fd, ZX234290_TIMER_ENABLED, 0); |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: disable timer failed, ret:%d\n", ret); |
| return; |
| } |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: alarm_restart disable timer ok \n"); |
| } else { |
| /*¹Ø±Õalarm ÖжÏ*/ |
| ret = ioctl(g_rtc_fd, RTC_AIE_OFF); |
| if (ret != 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: disable alarm failed, ret:%d\n", ret); |
| return; |
| } |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: alarm_restart disable alarm ok \n"); |
| } |
| } |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: alarm_restart exit.\n"); |
| } |
| |
| static void rtc_set_local_time(MSG_BUF *msg) |
| { |
| struct tm set_tm = {0}; |
| struct timeval time_tv; |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc_set_local_time, %d, %d \n", sizeof(struct tm), msg->usDataLen); |
| |
| memcpy(&set_tm, msg->aucDataBuf, msg->usDataLen); |
| |
| slog(RTC_PRINT, SLOG_ERR, "rtc_set_local_time, year:%d, month:%d, day:%d, hour:%d, min:%d, sec:%d, wday:%d \n", |
| set_tm.tm_year, set_tm.tm_mon, set_tm.tm_mday, set_tm.tm_hour, set_tm.tm_min, set_tm.tm_sec, set_tm.tm_wday); |
| |
| time_tv.tv_sec = mktime(&set_tm); |
| if(time_tv.tv_sec < 0) |
| { |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "mktime fail, set time_tv.tv_sec to 0 \n"); |
| time_tv.tv_sec = 0; |
| } |
| time_tv.tv_usec = 0; |
| |
| if (0 != settimeofday(&time_tv, NULL)) |
| slog(RTC_PRINT, SLOG_ERR, "rtc_set_local_time failed \n"); |
| } |
| |
| /******************************************** |
| * process_msg |
| * handle the specified MSG. |
| *******************************************/ |
| static int process_msg(MSG_BUF *pmsg_buf) |
| { |
| enum RTC_MSG_CMD cmd = pmsg_buf->usMsgCmd; |
| unsigned short req_cmd = 0; |
| |
| switch (cmd) { |
| case RTC_MSG_GET_TIME: |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: process_msg RTC_MSG_GET_TIME, src:0x%x.\n", pmsg_buf->src_id); |
| handle_get_time(pmsg_buf); |
| break; |
| case RTC_MSG_SET_TIME: |
| security_log(pmsg_buf->src_id,"set time"); |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: process_msg RTC_MSG_SET_TIME, src:0x%x.\n", pmsg_buf->src_id); |
| handle_set_time(pmsg_buf); |
| update_alarm(); |
| break; |
| case RTC_MSG_SNTP_UPDATE: |
| handle_sntp_update(pmsg_buf); |
| break; |
| case RTC_MSG_ADD_ALARM: |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: process_msg RTC_MSG_ADD_ALARM, src:0x%x, g_clean_flag = %d.\n", pmsg_buf->src_id, g_clean_flag); |
| //Ìí¼ÓrtcǰÏÈɾ³ý´Ërtc_idÒÑÌí¼Ó¼Ç¼£¬Ã¿¸örtc_idÖ»±£Áô1¸ö¶¨Ê±Æ÷ |
| if(0 == g_clean_flag){ |
| update_timer_remain(0); |
| handle_alarm_del(pmsg_buf); |
| handle_alarm_add(pmsg_buf); |
| } |
| else{ |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: g_clean_flag is nonzero:0x%x, dont add alarm.\n", g_clean_flag); |
| } |
| |
| //wifi´¦ÀíÍêǰ²»ÄÜÐÝÃߣ¬ÔÝʱʹÓÃÑÓÊ±Ëø£¬´ý·½°¸×鏸³ö·½°¸ºóÔÙµ÷Õû |
| //if (pmsg_buf->usSourceModuleID == MODULE_ID_WDT) |
| //write_lockfile("/sys/power/wake_unlock", "rtc_io_time_timeout_lock"); |
| |
| break; |
| case RTC_MSG_DEL_ALARM: |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: process_msg RTC_MSG_DEL_ALARM, src:0x%x.\n", pmsg_buf->src_id); |
| update_timer_remain(0); |
| handle_alarm_del(pmsg_buf); |
| send_ok_del_rsp(pmsg_buf); |
| alarm_restart(&rtc_timer_list); |
| alarm_restart(&rtc_alarm_list); |
| break; |
| case RTC_MSG_ALARM_TIMEOUT: |
| case RTC_MSG_TIMER_TIMEOUT: |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: process_msg RTC_TIMEOUT, src:0x%x, cmd:0x%x.\n", pmsg_buf->src_id, cmd); |
| handle_alarm_timeout(pmsg_buf); |
| break; |
| case RTC_MSG_DEL_ALL: |
| slog(RTC_PRINT, SLOG_NORMAL, "rtc-service: process_msg RTC_MSG_DEL_ALL, src:0x%x.\n", pmsg_buf->src_id); |
| memcpy(&req_cmd, pmsg_buf->aucDataBuf, sizeof(unsigned short)); |
| if(MSG_CMD_RESET_RSP == req_cmd || MSG_CMD_POWEROFF_RSP == req_cmd || MSG_CMD_RESTART_RSP == req_cmd){ |
| g_clean_flag = req_cmd; |
| } |
| handle_del_all(pmsg_buf); |
| save_rtc_alarm(); |
| //ÕâÀﻹÐèҪ֪ͨÖ÷¿Ø |
| ipc_send_message(MODULE_ID_RTC_SERVICE, pmsg_buf->src_id, req_cmd, 0, 0, 0); |
| break; |
| |
| default: |
| break; |
| } |
| return 0; |
| } |
| |
| static int rtc_service_sock_init() |
| { |
| int sockfd = 0; |
| int ret; |
| struct sockaddr_nl snl; |
| |
| bzero(&snl, sizeof(struct sockaddr_nl)); |
| snl.nl_family = AF_NETLINK; |
| snl.nl_pid = getpid(); |
| snl.nl_groups = 1; |
| |
| if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) |
| perror ("signal"); |
| |
| sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); |
| if (sockfd < 0) |
| { |
| slog(RTC_PRINT,SLOG_ERR, "create rtc service socket failed!\n"); |
| return -1; |
| } |
| // setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); |
| |
| ret = bind(sockfd, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl)); |
| if (ret < 0) |
| { |
| slog(RTC_PRINT,SLOG_ERR, "rtc service socket bind fail!\n"); |
| close(sockfd); |
| return -1; |
| } |
| |
| return sockfd; |
| } |
| //change@/devices/platform/zx29_i2c.0/i2c-0/0-0012/zx234290-rtc |
| static int rtc_time_msg_parse(const char *msg, int msglen) |
| { |
| int offlen = 0; |
| const char *keys = NULL; |
| char* timeStr = NULL; |
| char *pSec = NULL; |
| slog(RTC_PRINT,SLOG_ERR, "[%s][%d] zx234290-rtc \n", __func__, __LINE__); |
| |
| offlen += strlen((char *)msg) + 1; |
| while (offlen <= msglen) { |
| keys = (char *)(msg + offlen); |
| //slog(NET_PRINT,SLOG_ERR, "[%s][%d] zx234290-rtc%s, %d\n", __func__, __LINE__, keys, offlen); |
| if (strncmp(keys, RTC_ALARM_TIMEOUT_MSG, strlen(RTC_ALARM_TIMEOUT_MSG)) == 0) |
| { |
| #if 1 // cov M DEADCODE |
| pSec = strstr(keys, "sec:"); |
| if (pSec == NULL) { |
| slog(RTC_PRINT,SLOG_ERR, "zx234290-rtc event no sec \n"); |
| return -1; |
| } |
| timeStr = pSec + strlen("sec:"); |
| |
| #else |
| timeStr = strstr(keys, "sec:") + strlen("sec:"); |
| if (timeStr == NULL) { |
| slog(RTC_PRINT,SLOG_ERR, "zx234290-rtc event no sec \n"); |
| return -1; |
| } |
| #endif |
| ipc_send_message2(MODULE_ID_HOTPLUG, MODULE_ID_RTC_SERVICE, RTC_MSG_ALARM_TIMEOUT, strlen(timeStr), timeStr, 0); |
| slog(RTC_PRINT,SLOG_NORMAL, "zx234290-rtc alarm timeout \n"); |
| return 0; |
| } |
| else if (strncmp(keys, RTC_TIMER_TIMEOUT_MSG, strlen(keys)) == 0) |
| { |
| ipc_send_message2(MODULE_ID_HOTPLUG, MODULE_ID_RTC_SERVICE, RTC_MSG_TIMER_TIMEOUT, 0, NULL, 0); |
| slog(RTC_PRINT,SLOG_NORMAL, "zx234290-rtc timer timeout \n"); |
| return 0; |
| } |
| offlen += strlen((char *)keys) + 1; |
| } |
| slog(RTC_PRINT,SLOG_ERR, "zx234290-rtc event not supported \n"); |
| return -1; |
| } |
| |
| /******************************************** |
| * rtc_service_thread_process |
| * looper for processing zx234290-rtc msg. |
| *******************************************/ |
| void rtc_event_process(void) |
| { |
| int rtc_service_fd = 0; |
| fd_set readfds; |
| int maxfd = 0; |
| char buf[RTC_MSG_BUFFER_SIZE] = {0}; |
| int len = 0; |
| int ret = 0; |
| prctl(PR_SET_NAME, "rtceventhandle", 0, 0, 0); |
| rtc_service_fd = rtc_service_sock_init(); |
| if(rtc_service_fd < 0) |
| { |
| slog(RTC_PRINT,SLOG_ERR, "rtc service socket init fail!\n"); |
| return ; |
| } |
| |
| maxfd = rtc_service_fd; |
| while (1) |
| { |
| FD_ZERO(&readfds); |
| FD_SET(rtc_service_fd, &readfds); |
| |
| ret = select(maxfd + 1, &readfds, NULL, NULL, NULL); |
| if (ret == -1 && errno == EINTR) |
| continue; |
| |
| if(FD_ISSET(rtc_service_fd, &readfds)) |
| { |
| memset(buf, 0, sizeof(buf)); |
| len = recv(rtc_service_fd, &buf, sizeof(buf), 0); |
| if(len <= 0) |
| { |
| slog(RTC_PRINT,SLOG_ERR, "rtc service socket recv msg fail!\n"); |
| continue; |
| } |
| |
| /*½øÐÐueventÏûÏ¢½âÎö£¬·µ»Ø½âÎö½á¹û*/ |
| if (strstr(buf, "zx234290-rtc")){ |
| rtc_time_msg_parse(buf, len); |
| } |
| continue; |
| } |
| } |
| } |
| |
| /******************************************** |
| * msg_looper |
| * main looper for processing MSG. |
| *******************************************/ |
| static void msg_looper(void) |
| { |
| int ret = 0; |
| int msg_id = 0; |
| MSG_BUF msg_buf = {0}; |
| // key_t msgkey = get_msg_key(); |
| |
| msg_id = msgget(MODULE_ID_RTC_SERVICE, IPC_CREAT | 0600); |
| |
| memset(&msg_buf, 0, sizeof(msg_buf)); |
| |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: msg_looper enter(msgid=%d)&waiting...\n", msg_id); |
| while (1) { |
| ret = msgrcv(msg_id, &msg_buf, sizeof(MSG_BUF) - sizeof(long), 0, 0); |
| wake_rtc_lock(); |
| if (ret <= 0) { |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: msg_looper recv msg break(%d)\n", ret); |
| wake_rtc_unlock(); |
| continue; |
| } |
| slog(RTC_PRINT, SLOG_DEBUG, "rtc-service: msg_looper process_msg in, src:0x%x, target:0x%x.\n", msg_buf.src_id, msg_buf.dst_id); |
| |
| process_msg(&msg_buf); |
| |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: msg_looper process_msg out.\n"); |
| wake_rtc_unlock(); |
| } |
| } |
| |
| static void print_rtc_list_info(void) |
| { |
| ALARM_T *temp = NULL; |
| int remain_time; |
| |
| if(ioctl(g_rtc_fd, ZX234290_GET_TIMER_REMAIN, &remain_time) < 0) // cov M CHECKED_RETURN |
| { |
| slog(RTC_PRINT, SLOG_ERR, "ioctl fail.\n"); |
| } |
| |
| |
| slog(RTC_PRINT, SLOG_ERR, "rtc-service: rtc remain_time :%ld \n", remain_time); |
| |
| if (!list_empty(&rtc_timer_list)) { |
| list_for_each_entry(temp, &rtc_timer_list, list) { |
| slog(RTC_PRINT,SLOG_ERR, "rtc-service rtc_alarm_list node rtc_id:0x%x, module_id:0x%x, time_val:%ld, remain_time:%ld, cpu:%d\n", |
| temp->rtc_id, |
| temp->module_id, |
| temp->time_val, |
| temp->remain_time, |
| temp->cpu); |
| } |
| } |
| else { |
| slog(RTC_PRINT,SLOG_ERR, "rtc-service rtc_timer_list is empty!"); |
| } |
| |
| if (!list_empty(&rtc_alarm_list)) { |
| list_for_each_entry(temp, &rtc_alarm_list, list) { |
| slog(RTC_PRINT,SLOG_ERR, "rtc-service rtc_alarm_list node rtc_id:0x%x, module_id:0x%x, time_val:%ld, remain_time:%ld, cpu:%d, \ |
| rtc_tm.tm_year:%d, rtc_tm.tm_mon:%d, rtc_tm.tm_mday:%d, rtc_tm.tm_min:%d, rtc_tm.tm_sec:%d \n", |
| temp->rtc_id, |
| temp->module_id, |
| temp->time_val, |
| temp->remain_time, |
| temp->cpu, |
| temp->rtc_tm.tm_year, temp->rtc_tm.tm_mon, temp->rtc_tm.tm_mday, temp->rtc_tm.tm_min, temp->rtc_tm.tm_sec); |
| } |
| } |
| else { |
| slog(RTC_PRINT,SLOG_ERR, "rtc-service rtc_alarm_list is empty!"); |
| } |
| } |
| |
| /* ÐźŴ¦Àí*/ |
| static void sig_usr(int signo) |
| { |
| #if 0//(APP_OS_TYPE == APP_OS_LINUX) |
| if (signo == SIGUSR1) |
| { |
| slog(RTC_PRINT,SLOG_NORMAL, "rtc-service receive SIGUSR1! \n"); |
| print_rtc_list_info(); |
| } |
| else |
| { |
| slog(RTC_PRINT,SLOG_ERR, "rtc-service receive signo:%d", signo); |
| } |
| #endif |
| } |
| |
| /*RTCÏûÏ¢½âÎö*/ |
| int rtc_app_msg_parse(const char *msg, int msglen, struct hotplug_event *event) |
| { |
| if (strstr(msg, "zx234290-rtc")){ |
| rtc_time_msg_parse(msg, msglen); |
| } |
| return -1; |
| } |
| |
| /******************************************** |
| * main |
| * entry of RTC-Service! |
| *******************************************/ |
| int rtc_service_main(int argc, char **argv) |
| { |
| |
| slog(RTC_PRINT,SLOG_DEBUG, "rtc-service enter...\n"); |
| pthread_t rtcservice_thread_id; |
| pthread_attr_t attr; |
| int result = 0; |
| prctl(PR_SET_NAME, "rtc-service", 0, 0, 0); |
| |
| //¸ù¾ÝNV³õʼ»¯´òÓ¡¼¶±ð£¬²¢×¢²á¶¯Ì¬µ÷Õû´òÓ¡¼¶±ðÐźÅÁ¿ |
| loglevel_init(); |
| |
| if (signal(SIGUSR1, sig_usr) == SIG_ERR) |
| { |
| slog(RTC_PRINT,SLOG_ERR, "rtc-service not catch SIGUSR1 \n"); |
| } |
| |
| INIT_LIST_HEAD(&rtc_timer_list); |
| INIT_LIST_HEAD(&rtc_alarm_list); |
| |
| g_clean_flag = 0; |
| |
| //rtcÔÚAPʱ£¬½Úµã±ØÐë´ò¿ª³É¹¦£»ÔÚÆäËûºËʱÓÉÆäËûºËÅÐ¶Ï |
| if ((g_rtc_fd = open_rtc()) < 0) { |
| slog(RTC_PRINT, SLOG_ERR, "Cannt open rtc dev!\n"); |
| return -1; |
| } |
| init_rtc_alarm(); |
| /* |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| result = pthread_create(&rtcservice_thread_id, &attr, rtc_event_process, NULL); |
| pthread_attr_destroy(&attr); |
| if(result != 0) |
| { |
| slog(RTC_PRINT,SLOG_ERR, "[rtc-service] rtcservice_thread pthread_create faild!\n"); |
| return -1; |
| } |
| else |
| { |
| printf("[rtc-service] rtcservice_thread pthread_create SUCCESS!\n"); |
| } |
| */ |
| hotplug_parse_register(DEVICE_TYPE_APP_RTC, rtc_app_msg_parse); |
| msg_looper(); |
| //klocwork |
| //close_rtc(g_rtc_fd); |
| |
| //slog(RTC_PRINT, SLOG_ERR, "rtc-service exit...\n"); |
| |
| return 0; |
| } |