| /******************************************************************************* |
| * °æÈ¨ËùÓÐ (C)2023, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£ |
| * |
| * ÎļþÃû³Æ: nvserver_rpc.c |
| * Îļþ±êʶ: nvserver_rpc.c |
| * ÄÚÈÝÕªÒª: nvserverת½ÓcapµÄnvserver |
| * |
| * ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ |
| * ------------------------------------------------------------------------------ |
| * 2016/06/13 V1.0 Create ÁõÑÇÄÏ ´´½¨ |
| * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * Í·Îļþ * |
| *******************************************************************************/ |
| #include <unistd.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <dirent.h> |
| #include <string.h> |
| #include <sys/file.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/ipc.h> |
| #include <sys/msg.h> |
| |
| #include "nvserver.h" |
| #include "nv_typedef.h" |
| #include <message.h> |
| #include "sc_rpc.h" |
| #include "soft_timer.h" |
| #include "zxicbasic_api.h" |
| #include "pub_debug_info.h" |
| |
| #ifdef __cplusplus |
| extern "C" |
| { |
| #endif |
| |
| /******************************************************************************* |
| * ³£Á¿¶¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ºê¶¨Òå * |
| *******************************************************************************/ |
| #define RPC_RPMSG_DEV "/dev/rpmsg8" |
| #define NVSERVER_LOG_START_TIME (120) /* 2 minutes */ |
| #define MODULE_ID_AP_SERVER "ap_nvserver" |
| #define NVSERVER_LOG_TIMER_ID (0x1984) |
| |
| /******************************************************************************* |
| * Êý¾ÝÀàÐͶ¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ¾Ö²¿º¯ÊýÉùÃ÷ * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ¾Ö²¿¾²Ì¬±äÁ¿¶¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * È«¾Ö±äÁ¿¶¨Òå * |
| *******************************************************************************/ |
| static int g_rpc_fd = -1; |
| static unsigned int g_msgRcvCnt = 0; |
| static unsigned int g_msgRcvErrCnt = 0; |
| static unsigned int g_msgSndCnt = 0; |
| static unsigned int g_msgSndErrCnt = 0; |
| static int g_debug_info_flag = 0; /* not log debug info */ |
| |
| /******************************************************************************* |
| * ¾Ö²¿º¯ÊýʵÏÖ * |
| *******************************************************************************/ |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: analyMsg |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) msgrecv:½ÓÊÕÏûÏ¢ |
| * (´«³ö²ÎÊý) msgsnd:·¢ËÍÏûÏ¢ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static void analyMsg(T_NV_MSG_INFO *msgrecv, T_NV_MSG_RESULT *msgsnd, T_sc_rpc_msg *rpc_data, T_sc_rpc_msg *rpc_data2) |
| { |
| unsigned int timeout = 10; |
| int send_once_flag = 0; |
| int ret; |
| |
| rpc_data->header.msg_type = RPC_MSG_TYPE_REQUEST; |
| rpc_data->header.func_id = RPC_FUNC_ID_NV; |
| rpc_data->header.data_len = sizeof(T_NV_MSG_INFO) - NV_MAX_FILE_LEN - NV_MAX_KEY_LEN - NV_MAX_VAL_LEN; |
| rpc_data->header.file_len = strlen(msgrecv->file) + 1; |
| rpc_data->header.data_len += rpc_data->header.file_len; |
| memcpy(rpc_data->data, msgrecv, rpc_data->header.data_len); |
| rpc_data->header.key_len = strlen(msgrecv->key) + 1; |
| memcpy(rpc_data->data+rpc_data->header.data_len, msgrecv->key, rpc_data->header.key_len); |
| rpc_data->header.data_len += rpc_data->header.key_len; |
| rpc_data->header.value_len = strlen(msgrecv->value); |
| if (rpc_data->header.value_len > 0) |
| { |
| rpc_data->header.value_len += 1; |
| memcpy(rpc_data->data+rpc_data->header.data_len, msgrecv->value, rpc_data->header.value_len); |
| rpc_data->header.data_len += rpc_data->header.value_len; |
| } |
| |
| do |
| { |
| if (send_once_flag == 0) |
| { |
| ret = sc_rpc_send(g_rpc_fd, rpc_data, 0); |
| if (ret == 0) |
| { |
| send_once_flag = 1; // send success |
| } |
| else |
| { |
| assert(0); // send fail |
| } |
| } |
| |
| ret = sc_rpc_recv(g_rpc_fd, rpc_data2, timeout); |
| if (ret == 0) |
| { |
| break; // recv success and break |
| } |
| |
| } while (1); //µÈ´ýÍê³É |
| |
| if (rpc_data2->header.msg_type != RPC_MSG_TYPE_REPLY) |
| assert(0); |
| |
| memcpy(msgsnd, rpc_data2->data, rpc_data2->header.data_len); |
| } |
| |
| static int nv_rpc_wait_ready(int fd) |
| { |
| T_sc_rpc_header *rpc_data; |
| unsigned int timeout = 100; // ms |
| |
| rpc_data = malloc(sizeof(T_sc_rpc_header)); |
| if (rpc_data == NULL) |
| return -1; |
| |
| while(1) |
| { |
| rpc_data->msg_type = RPC_MSG_TYPE_READY; |
| if (write(fd, rpc_data, sizeof(T_sc_rpc_header)) == sizeof(T_sc_rpc_header)) |
| break; |
| else |
| usleep(timeout * 1000); |
| } |
| |
| free(rpc_data); |
| return 0; |
| } |
| |
| static void log_timer_callback(void *argc) |
| { |
| g_debug_info_flag = 1; |
| //logmsg("log_timer_callback\n"); |
| } |
| |
| // return -1 error; 1 active; 0 sleep |
| int cap_is_active(void) |
| { |
| char buf[4]; |
| int ret = -1; |
| |
| memset(buf, 0, sizeof(buf)); |
| ret = open_read_close("/sys/zte_pm/cap_state", buf, sizeof(buf)); |
| if (ret < 0) |
| return -1; |
| //logmsg("cap_is_active:%s\n", buf); |
| if (buf[0] == '1') |
| { |
| //logmsg("cap_is_active:active\n"); |
| return 1; |
| } |
| else |
| { |
| if (buf[0] == '0') |
| { |
| //logmsg("cap_is_active:sleeping\n"); |
| return 0; |
| } |
| else |
| { |
| //logmsg("cap_is_active:error\n"); |
| return -1; |
| } |
| } |
| } |
| |
| static void log_nv_info(T_NV_MSG_INFO *msg) |
| { |
| //logmsg("log_nv_info\n"); |
| switch(msg->nvType) |
| { |
| case MSG_GET: |
| //printf("[nvrpc] cfg_get key:%s\n", msg->key); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_get key:%s\n", msg->key); |
| break; |
| case MSG_SET: |
| //printf("[nvrpc] cfg_set key:%s value:%s\n", msg->key, msg->value); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_set key:%s value:%s\n", msg->key, msg->value); |
| break; |
| case MSG_UNSET: |
| //printf("[nvrpc] cfg_unset key:%s\n", msg->key); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_unset key:%s\n", msg->key); |
| break; |
| case MSG_CLEAR: |
| //printf("[nvrpc] cfg_clear\n"); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_clear\n"); |
| break; |
| case MSG_RESET: |
| //printf("[nvrpc] cfg_reset\n"); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_reset\n"); |
| break; |
| case MSG_SHOW: |
| //printf("[nvrpc] cfg_show\n"); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_show\n"); |
| break; |
| case MSG_COMMIT: |
| //printf("[nvrpc] cfg_save\n"); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "cfg_save\n"); |
| break; |
| default: |
| //printf("[nvrpc] cfg other action\n"); |
| sc_debug_info_record(MODULE_ID_AP_SERVER, "error cfg other action\n"); |
| break; |
| } |
| } |
| |
| /******************************************************************************* |
| * È«¾Öº¯ÊýʵÏÖ * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: main |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| int nvserver_main(int argc, char *argv[]) |
| { |
| int msgId = 0; |
| T_NV_MSG_INFO rcvBuf; |
| T_NV_MSG_RESULT sndBuf; |
| struct msqid_ds msgInfo; |
| T_sc_rpc_msg *rpc_data; |
| T_sc_rpc_msg *rpc_data2; |
| long pid_backup; /* app-libnvram pid backup */ |
| |
| prctl(PR_SET_NAME, "nvserver_rpc", 0, 0, 0); |
| |
| memset(&msgInfo, 0, sizeof(msgInfo)); |
| |
| if (0 != sc_timer_create(NVSERVER_LOG_TIMER_ID, TIMER_FLAG_ONCE, NVSERVER_LOG_START_TIME*1000, log_timer_callback, NULL)) |
| { |
| abort(); // create timer error |
| } |
| |
| g_rpc_fd = sc_rpc_open(RPC_RPMSG_DEV); |
| |
| msgId = msgget(MODULE_ID_NV, IPC_CREAT | 0600); |
| if (-1 == msgId) |
| { |
| printf("nvserver error: msgget msgId fail, errno = %d\n", errno); |
| return -1; |
| } |
| |
| if (-1 != msgctl(msgId, IPC_STAT, &msgInfo)) |
| { |
| msgInfo.msg_qbytes = 262144; // 256k |
| if (-1 == msgctl(msgId, IPC_SET, &msgInfo)) |
| { |
| printf("nvserver error: msgctl msgId fail, errno = %d\n", errno); |
| } |
| } |
| |
| rpc_data = malloc(sizeof(T_sc_rpc_msg)); |
| if (rpc_data == NULL) |
| { |
| perror("[error]nvrpc malloc error\n"); |
| return -2; |
| } |
| rpc_data2 = malloc(sizeof(T_sc_rpc_msg)); |
| if (rpc_data2 == NULL) |
| { |
| perror("[error]nvrpc malloc2 error\n"); |
| free(rpc_data); |
| return -3; |
| } |
| |
| if (nv_rpc_wait_ready(g_rpc_fd) < 0) |
| { |
| assert(0); |
| } |
| sc_rpc_clear(g_rpc_fd); |
| printf("apnv and nv-rpc-daemon are ready both."); |
| |
| // ÏûÏ¢½»»¥ |
| while (1) |
| { |
| memset(&rcvBuf, 0, sizeof(rcvBuf)); |
| memset(&sndBuf, 0, sizeof(sndBuf)); |
| if (g_msgRcvCnt != g_msgSndCnt) |
| { |
| printf("[nvserver_rpc]Rcv:%u Snd:%u RcvErr:%u SndErr:%u\n", g_msgRcvCnt, g_msgSndCnt, g_msgRcvErrCnt, g_msgSndErrCnt); |
| assert(0); |
| } |
| if (-1 == msgrcv(msgId, &rcvBuf, sizeof(T_NV_MSG_INFO) - sizeof(long), MSG_TYPE_NV, 0)) |
| { |
| g_msgRcvErrCnt++; |
| printf("nvserver error: nvserver msgrcv fail, errno = %d!\n", errno); |
| continue; |
| } |
| //printf("apnv nvserver_rpc msgrcv pid:%d\n", rcvBuf.pid); |
| pid_backup = rcvBuf.pid; |
| g_msgRcvCnt++; /* msgrcv success count */ |
| |
| if (g_debug_info_flag && (cap_is_active() == 0)) |
| { //start log and cap is sleeping |
| log_nv_info(&rcvBuf); |
| } |
| analyMsg(&rcvBuf, &sndBuf, rpc_data, rpc_data2); |
| |
| //printf("apnv nvserver_rpc msgsnd pid:%d, backup:%d\n", sndBuf.msgType, pid_backup); |
| if (-1 == msgsnd(msgId, &sndBuf, sizeof(T_NV_MSG_RESULT) - sizeof(long), 0)) |
| { |
| g_msgSndErrCnt++; |
| printf("nvserver error: nvserver msgsnd fail, errno = %d!\n", errno); |
| continue; |
| } |
| g_msgSndCnt++; /* msgsnd success count */ |
| if (sndBuf.msgType != pid_backup) |
| { |
| assert(0); |
| } |
| } |
| |
| free(rpc_data); |
| free(rpc_data2); |
| return (0); |
| } |
| |
| #ifdef __cplusplus |
| } |
| #endif |