blob: d76371c72c37a68d6480add6575d88055e23943d [file] [log] [blame]
/**
* @file softap_api.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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <syslog.h>
#include <sys/klog.h>
#include <sys/msg.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <sys/un.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <limits.h>
#include "softap_api.h"
/* ƽ̨»ù´¡Ó¦Ó㬼´: ËùÓÐÐͺŻú¶¼ÐèÒªÆô¶¯µÄÓ¦Óà */
static int basic_apps[] = {
MODULE_ID_AT_CTL, // AT
MODULE_ID_MAIN_CTRL, // Ö÷¿Ø
MODULE_ID_RTC_SERVICE, // rtc
MODULE_ID_CODEC // audio ctrl
};
static int is_basic_app(int module_id)
{
int i = 0;
for (i = 0; i < sizeof(basic_apps) / sizeof(basic_apps[0]); i++) {
if (module_id == basic_apps[i]) {
return 1;
}
}
return 0;
}
//»ñÈ¡¶àºË»ù׼ʱ¼ä
long long int get_time_us()
{
int fd;
char buf[128] = {0};
fd = open("/proc/persistent_time", O_RDWR);
if (fd < 0) {
printf("fail to open\n");
return -1;
}
#if 1
int len = read(fd, buf, sizeof(buf)-1);
long long time = 0;
if(len < 0 ){
close(fd);
return -1;
}else{
close(fd);
time = atoll(buf);
if(time < 0 || time > LLONG_MAX-1)
{
time = 0;
}
return time;
}
#else
if (read(fd, buf, 127) > 0) {
close(fd);
return atoll(buf);
} else {
close(fd);
return -1;
}
#endif
}
/**************************************************************************
* º¯ÊýÃû³Æ£º soc_send_condition_check
* ¹¦ÄÜÃèÊö£º ¼ì²âÊÇ·ñÂú×ãSOCÏûÏ¢·¢ËÍÌõ¼þ£¬Èç¹ûÊÇ´ÓAP·¢Ë͵½CP£¬Ôòsrc_id±ØÐëΪAP²àµÄmoduleid£¬dst_id±ØÐëΪ
* moduleid; Èç¹ûÊÇ´ÓCP·¢Ë͵½AP£¬Ôòsrc_id±ØÐëΪCP²àµÄmoduleid£¬dst_id±ØÐëΪAP²àµÄmoduleid.
* ²ÎÊý˵Ã÷£ºsrc_id:ÏûÏ¢·¢ËÍÄ£¿éID dest_id:ÏûÏ¢½ÓÊÕÄ£¿éID
* ·µ »Ø Öµ£º 1:·ûºÏÌõ¼þ0:²»·ûºÏÌõ¼þ
* ÆäËü˵Ã÷£º
**************************************************************************/
static int soc_send_condition_check(int src_id, int dst_id)
{
#if (APP_OS_TYPE == APP_OS_TOS)
if ((src_id <= MODULE_ID_CPBASE) || (src_id >= MODULE_ID_MAX)) { //¼ì²âsrc_idÊÇ·ñΪCPºËÄ£¿éºÅ
return 0;
} else if ((dst_id <= MODULE_ID_APBASE) || (dst_id >= MODULE_ID_CPBASE)) { //¼ì²âdst_idÊÇ·ñΪAPºËÄ£¿éºÅ
return 0;
}
return 1;
#endif
#if (APP_OS_TYPE == APP_OS_LINUX)
if ((src_id <= MODULE_ID_APBASE) || (src_id >= MODULE_ID_CPBASE)) { //¼ì²âsrc_idÊÇ·ñΪAPºËÄ£¿éºÅ
return 0;
} else if ((dst_id <= MODULE_ID_CPBASE) || (dst_id >= MODULE_ID_MAX)) { //¼ì²âdst_idÊÇ·ñΪCPºËÄ£¿éºÅ
return 0;
}
return 1;
#endif
}
/************************ Ó¦Óü乫¹²º¯ÊýʵÏÖ ************************/
/*·µ»ØÖµ 0 ³É¹¦ ·Ç0ʧ°Ü£¬
Èç¹û·µ»ØÖµµÈÓÚENOENT£¬±íʾ½ÓÊÕ¶ÓÁв»´æÔÚ£¬Ó¦ÓÃ×ÔÐÐÅжϽÓÊÕÄ£¿éÊÇ·ñÒ»¶¨Æô¶¯£¬Èç¹ûÊÇ£¬µ÷ÓÃipc_send_message2·¢ËÍ*/
int ipc_send_message(int src_id, int dst_id, unsigned short Msg_cmd, unsigned short us_DataLen, unsigned char *pData, int msgflag)
{
MSG_BUF stMsg;
int lRet = 0;
int lTgtMsgID = 0;
LONG msgSize = offsetof(MSG_BUF, aucDataBuf) - sizeof(LONG) + us_DataLen;
int errNo = 0;
memset(&stMsg, 0, sizeof(MSG_BUF));
lTgtMsgID = msgget(dst_id, 0);
if (-1 == lTgtMsgID) {
errNo = errno;
slog(NET_PRINT, SLOG_ERR, "send_message failed:can not get target msg id, src:0x%x, target:0x%x, cmd:0x%x, errNo:%d! \n", src_id, dst_id, Msg_cmd, errNo); /*lint !e26*/
/* »ù´¡Ó¦ÓñØÐë·¢Ëͳɹ¦£¬Èç¹ûÓ¦Óû¹Ã»Æð¾ÍÖ±½ÓÏÈ´´½¨ÏûÏ¢½ÓÊÕ¶ÓÁУ¬Æô¶¯ºóÔÙ´¦Àí */
if (is_basic_app(dst_id)) {
slog(NET_PRINT, SLOG_ERR, "send_message failed, basic app \n");
return ipc_send_message2(src_id, dst_id, Msg_cmd, us_DataLen, pData, msgflag);
}
return errNo;
}
if (us_DataLen >= MSG_DATA_MAX_LEN) {
slog(NET_PRINT, SLOG_ERR, "send_message failed:us_DataLen %d is too big, src:0x%x, target:0x%x, cmd:0x%x! \n", us_DataLen, src_id, dst_id, Msg_cmd); /*lint !e26*/
softap_assert("send_message failed:us_DataLen %d is too big!", us_DataLen);
return EINVAL;
}
if ((us_DataLen > 0) && (NULL == pData)) {
slog(NET_PRINT, SLOG_ERR, "send_message failed:us_DataLen is %d, but pData is NULL! \n", us_DataLen); /*lint !e26*/
softap_assert("send_message failed:us_DataLen is %d, but pData is NULL!", us_DataLen);
return EINVAL;
}
stMsg.ulMagic = MSG_MAGIC_WORD;
stMsg.lMsgType = MSG_TYPE_DEFAULT;
stMsg.src_id = src_id;
stMsg.dst_id = dst_id;
stMsg.usMsgCmd = Msg_cmd;
stMsg.usDataLen = us_DataLen;
if (us_DataLen > 0) {
memcpy(stMsg.aucDataBuf, pData, us_DataLen);
}
AGAIN:
lRet = msgsnd(lTgtMsgID, &stMsg, msgSize, msgflag);
if (lRet < 0) {
if (errno == EINTR) {
goto AGAIN;
}
errNo = errno;
slog(NET_PRINT, SLOG_ERR, "send_message failed: msgsnd error code %d!, errNo:%d \n", lRet, errNo); /*lint !e26*/
if (msgflag != IPC_NOWAIT) {
softap_assert("send_message failed: msgsnd error code errNo:%d! \n", errNo);
}
return errNo;
}
return 0;
}
int ipc_send_message2(int src_id, int dst_id, unsigned short Msg_cmd, unsigned short us_DataLen, unsigned char *pData, int msgflag)
{
MSG_BUF stMsg;
int lRet = 0;
int lTgtMsgID = 0;
LONG msgSize = offsetof(MSG_BUF, aucDataBuf) - sizeof(LONG) + us_DataLen;
int errNo = 0;
memset(&stMsg, 0, sizeof(MSG_BUF));
lTgtMsgID = msgget(dst_id, IPC_CREAT | 0600);
if (-1 == lTgtMsgID) {
errNo = errno;
slog(NET_PRINT, SLOG_ERR, "send_message2 failed:can not get target id, src:0x%x, target:0x%x, cmd:0x%x, errNo:%d!", src_id, dst_id, Msg_cmd, errNo); /*lint !e26*/
softap_assert("send_message2 failed:can not get target msg id 0x%04x!", dst_id);
return errNo;
}
if (us_DataLen >= MSG_DATA_MAX_LEN) {
slog(NET_PRINT, SLOG_ERR, "send_message2 failed:us_DataLen %d is too big, src:0x%x, target:0x%x, cmd:0x%x!", us_DataLen, src_id, dst_id, Msg_cmd); /*lint !e26*/
softap_assert("send_message2 failed:us_DataLen %d is too big!", us_DataLen);
return EINVAL;
}
if ((us_DataLen > 0) && (NULL == pData)) {
slog(NET_PRINT, SLOG_ERR, "send_message2 failed:us_DataLen is %d, but pData is NULL!", us_DataLen); /*lint !e26*/
softap_assert("send_message2 failed:us_DataLen is %d, but pData is NULL!", us_DataLen);
return EINVAL;
}
stMsg.ulMagic = MSG_MAGIC_WORD;
stMsg.lMsgType = MSG_TYPE_DEFAULT;
stMsg.src_id = src_id;
stMsg.dst_id = dst_id;
stMsg.usMsgCmd = Msg_cmd;
stMsg.usDataLen = us_DataLen;
if (us_DataLen > 0) {
memcpy(stMsg.aucDataBuf, pData, us_DataLen);
}
AGAIN:
lRet = msgsnd(lTgtMsgID, &stMsg, msgSize, msgflag);
if (lRet < 0) {
errNo = errno;
if (errNo == EINTR) {
goto AGAIN;
}
if (errNo == EAGAIN) {
slog(NET_PRINT, SLOG_ERR, "send_message2 EAGAIN! src=0x%x dst=0x%x msg=0x%x\n",src_id,dst_id,Msg_cmd);
goto AGAIN;
}
slog(NET_PRINT, SLOG_ERR, "send_message failed: msgsnd error code %d, errNo:%d!", lRet, errNo); /*lint !e26*/
if (msgflag != IPC_NOWAIT) {
softap_assert("send_message failed: msgsnd error code errNo:%d!", errNo);
}
return errNo;
}
return 0;
}
int send_soc_msg(unsigned short position, int dst_id, unsigned short msg_cmd, unsigned short len, void *msg)
{
T_Soc_Msg socMsgInfo = {0};
int Msgsize = offsetof(T_Soc_Msg, msg) + len;
int ret = -1;
if ((len > 0) && (NULL == msg)) {
assert(0);
return EINVAL;
}
if (len >= SOC_MSG_MAX_LEN) {
assert(0);
return EINVAL;
}
//¿çºË·¢Ë͵½at_ctlµÄÏûÏ¢£¬ÄÚ²¿½øÐÐÈÝ´í
switch (dst_id) {
case MODULE_ID_AT_CTL:
dst_id = MODULE_ID_EXTERNAL_AT_CTL;
break;
case MODULE_ID_RTC_SERVICE:
dst_id = MODULE_ID_EXTERNAL_RTC_SERVICE;
break;
default:
break;
}
socMsgInfo.position = position;
socMsgInfo.targetId = dst_id;
socMsgInfo.msg_cmd = msg_cmd;
socMsgInfo.len = len;
if (len > 0) {
memcpy(socMsgInfo.msg, msg, len);
}
//´Ë´¦½«Ô´Ä£¿éÉèÖÃΪMODULE_ID_AT_CTL£¬socÊÇAT·â×°´¦Àí½Ó¿Ú
ret = ipc_send_message(MODULE_ID_AT_CTL, MODULE_ID_AT_CTL, MSG_CMD_SOC_MSG_REQ, Msgsize, &socMsgInfo, 0);
if (ret != 0)
assert(0);
return ret;
}
/*ƽ̨¼¶ÏûÏ¢·¢Ëͽӿڣ¬ÄÚ²¿Ò»Í³ipc_send_messageºÍsend_soc_msg½Ó¿Ú¡£µ±Ä¿±êÄ£¿éºÍÔ´Ä£¿é²»ÔÚÒ»¸öºËʱ£¬½øÐк˼äÏûÏ¢·¢ËÍ*/
int platform_send_msg(int src_id, int dst_id, unsigned short msg_cmd, unsigned short datalen, unsigned char *pData)
{
int position;
if (datalen >= SOC_MSG_MAX_LEN) {
softap_assert("platform_send_msg failed:datalen %d is too big!", datalen);
return EINVAL;
}
if ((datalen > 0) && (NULL == pData)) {
softap_assert("platform_send_msg failed:datalen is %d, but pData is NULL!", datalen);
return EINVAL;
}
//䶨ÒåÔ´Ä£¿éID£¬Ôò·Ö±ð¸³¶ÔÓ¦ºËµÄĬÈÏÖµ
if (src_id == 0) {
#if (APP_OS_TYPE == APP_OS_LINUX)
src_id = MODULE_ID_APBASE;
#else
src_id = MODULE_ID_CPBASE;
#endif
}
if (dst_id == 0)
softap_assert("platform_send_msg failed:src_id = %d, dst_id = %d!", src_id, dst_id);
//Ô´Ä£¿éIDÓëÄ¿±êÄ£¿éID²»ÔÚÒ»¸öºËÄÚ£¬Ôò×é×°²¢·¢Ëͺ˼äÏûÏ¢
if (((src_id & MODULE_ID_APBASE) != (dst_id & MODULE_ID_APBASE)) && ((src_id & MODULE_ID_CPBASE) != (dst_id & MODULE_ID_CPBASE))) {
int msglen = offsetof(T_Soc_Msg, msg) + datalen;
int ret = -1;
T_Soc_Msg socMsgInfo = {0};
//¼ì²âsrc_id,dst_idÊÇ·ñÂú×ãºË¼äͨѶµÄÌõ¼þ
if (0 == soc_send_condition_check(src_id, dst_id))
softap_assert("platform_send_msg failed: confition check failed, src_id = %d, dst_id = %d!", src_id, dst_id);
position = (dst_id & MODULE_ID_APBASE) ? FAR_PS : NEAR_PS;
socMsgInfo.position = position;
socMsgInfo.srcId = src_id;
socMsgInfo.targetId = dst_id;
socMsgInfo.msg_cmd = msg_cmd;
socMsgInfo.len = datalen;
if (datalen > 0) {
memcpy(socMsgInfo.msg, pData, datalen);
}
ret = ipc_send_message(src_id, MODULE_ID_AT_CTL, MSG_CMD_SOC_MSG_REQ, msglen, &socMsgInfo, 0);
if (ret != 0) //·¢Ë͵½at_ctlµÄÏûÏ¢²»ÔÊÐí·¢ËÍʧ°Ü
softap_assert("platform_send_msg failed: ipc_send_message MSG_CMD_SOC_MSG_REQ errNo:%d!", errno);
return ret;
} else {
//ºËÄÚÏûÏ¢´æÔÚÒòÄ¿±êÏûÏ¢¶ÓÁл¹Î´´´½¨µ¼Ö·¢ËÍʧ°ÜµÄÇé¿ö£¬¹Ê¸Ã´¦²»¶ÏÑÔ
return ipc_send_message(src_id, dst_id, msg_cmd, datalen, pData, 0);
}
}
int poweroff_request(int src_id)
{
return platform_send_msg(src_id, MODULE_ID_MAIN_CTRL, MSG_CMD_POWEROFF_REQUEST, 0, NULL);
}
int restart_request(int src_id)
{
return platform_send_msg(src_id, MODULE_ID_MAIN_CTRL, MSG_CMD_RESTART_REQUEST, 0, NULL);
}
int reset_request(int src_id)
{
return platform_send_msg(src_id, MODULE_ID_MAIN_CTRL, MSG_CMD_RESET_REQUEST, 0, NULL);
}
typedef struct system_cmd_proc
{
const char * str;
int (* proc)(const char * cmd, const char * str);
}
system_cmd_proc_t;
//awkÌ«¸´ÔÓ£¬¾ßÌåÎÊÌâ¾ßÌå·ÖÎö
//·Ö¸ô·û|ºóÃæ¿ÉÒÔ´æÔÚµÄÃüÁ´ýÍêÉÆ
const static const char * separator_whitelist[]={
"grep ","sort ","head "
};
//·µ»Ø×Ö·û´®¼°ÒÔǰµÄ³¤¶È£¬Ã»ÓÐÕÒµ½·µ»Ø0
static int system_cmd_used_curr(const char * cmd, const char * str)
{
char *tmp_str = NULL;
tmp_str = strstr(cmd, str);
if(tmp_str)
{
int len = tmp_str - cmd + strlen(str);
tmp_str = tmp_str + strlen(str);
while((*tmp_str)!='\0' && (*tmp_str)==' ')
{
tmp_str++;
}
if((*tmp_str) == '\0' || (*(tmp_str+1)) == '\0')
{//¹æ±Ü2>&1
return 0;
}
return len;
}
else
return 0;
}
//·µ»Ø³ý×Ö·û´®ÒÔǰµÄ³¤¶È£¬Ã»ÓÐÕÒµ½·µ»Ø0
static int system_cmd_used_before(const char * cmd, const char * str)
{
char *tmp_str = NULL;
tmp_str = strstr(cmd, str);
if(tmp_str)
return tmp_str -cmd;
else
return 0;
}
//¶Ô·Ö¸ô·û|µÄÌØÊâ´¦Àí£¬Ã»ÓÐÕÒµ½»òÔÊÐíÖ´Ðзµ»Ø0
static int system_cmd_separator_proc(const char * cmd, const char * str)
{
char *tmp_str = NULL;
tmp_str = strstr(cmd, str);
if(tmp_str)
{
int i = 0;
int len = tmp_str -cmd;
tmp_str = tmp_str + strlen(str);
while((*tmp_str)!='\0' && (*tmp_str)==' ')
{
tmp_str++;
}
for(i = 0; i < sizeof(separator_whitelist) / sizeof(const char *); i++)
{
if(strncmp(tmp_str, separator_whitelist[i], strlen(separator_whitelist[i])) == 0)
{
return 0;
}
}
return len;
}
else
return 0;
}
const static system_cmd_proc_t system_chack[]={
{"&",system_cmd_used_curr},
{"|",system_cmd_separator_proc},
{";",system_cmd_used_before},
{"\r",system_cmd_used_before},
{"\n",system_cmd_used_before}
};
int soft_system(const char *command)
{
int i = 0;
int flag = 0;
int len = strlen(command);
for(i = 0; i < sizeof(system_chack) / sizeof(system_cmd_proc_t); i++)
{
int offset = system_chack[i].proc(command,system_chack[i].str);
if(offset != 0 && offset < len)
{
len = offset;
flag = 1;
}
}
if(flag && len > 0 && len < strlen(command))
{
char *cmd = (char *)malloc(len+1);
int ret = 0;
if(cmd == NULL)
{
slog(NET_PRINT, SLOG_ERR, "@system@ malloc fail!\n");
return -1;
}
memset(cmd, 0, len+1);
strncpy(cmd, command, len);
slog(NET_PRINT, SLOG_ERR, "@system@ %s is inject!\n",command);
ret = system(cmd);
slog(NET_PRINT, SLOG_ERR, "@system@ %s is now,ret=%d!\n",cmd,ret);
free(cmd);
return ret;
}
else
return system(command);
}
long get_sys_uptime()
{
struct sysinfo info;
if(sysinfo(&info))
{
printf("Failed to get sysinfo failed\n");
return -1;
}
return info.uptime;
}