blob: c5e21007800aa1eee9adf26ccd5dbc8d3a094fe3 [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2008 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <ctype.h>
#include <libgen.h>
#include <cutils/properties.h>
#include <errno.h>
#include "utilities.h"
#include "utlTrace.h"
#include "paths_defs.h"
#define PROC_CMDLINE "/proc/cmdline"
#define CMDLINE_LEN 1024
#define BSPFLG_NAME "PROD="
#define ATMOD_FLAG "atcmdmode="
#define REGDUMP_FILE "/sys/power/regdump"
#define REG_LINE_LEN 1024
#define CHIPID_ADDRESS "0xfe282c00"
#define REG_ADD_CON_SPLIT ':'
#define EMMC_BOOT_FLAG "emmc_boot"
#define NEVO_TD_FLAG "nevo_td"
#define HARDWARE_VERSION_FILE "/proc/cpuinfo"
#define HDVER_LINE_LEN 1024
#define HDVER_KEY "Rev"
#define HDVER_KEY_VALUE_SPLIT ':'
/*
* Defined here since strcasestr is not C99 standard.
* Find the first occurrence of find in s, ignore case.
*/
char *strcasestr(const char *s, const char *find)
{
char c, sc;
size_t len;
if ((c = *find++) != 0) {
c = tolower((unsigned char)c);
len = strlen(find);
do {
do {
if ((sc = *s++) == 0)
return (NULL);
} while ((char)tolower((unsigned char)sc) != c);
} while (strncasecmp(s, find, len) != 0);
s--;
}
return ((char *)s);
}
/* Defined here since (v)asprintf is not C99 standard */
int vasprintf(char **ret, const char *format, va_list args)
{
int count;
va_list copy;
va_copy(copy, args);
*ret = NULL;
count = vsnprintf(NULL, 0, format, args);
if (count >= 0)
{
char* buffer = (char*) malloc(count + 1);
if (buffer != NULL)
{
count = vsnprintf(buffer, count + 1, format, copy);
if (count < 0)
free(buffer);
else
*ret = buffer;
}
else
count = -1;
}
va_end(copy);
return count;
}
int asprintf(char **ret, const char *format, ...)
{
int count;
va_list args;
va_start(args, format);
count = vasprintf(ret, format, args);
va_end(args);
return count;
}
int StringToInt(const char *pString, int *pVal, int strLen, int strMinLen, int strMaxLen, int valMin, int valMax)
{
int count;
int val;
/* Check string length */
if ((strLen < strMinLen) || (strLen > strMaxLen))
return (-1);
/* Check string characters, first character may be plus/minus sign */
if ((!isdigit(pString[0])) && (pString[0] != '+') && (pString[0] != '-'))
return (-2);
for (count=1 ; count<strLen ; count++) {
if (!isdigit(pString[count]))
return (-2);
}
/* Convert to integer */
val = atoi(pString);
/* Check integer value range */
if ((val < valMin) || (val > valMax))
return (-3);
*pVal = val;
return 0;
}
int HexStringToInt(const char *pString, void *pVal, int strLen, int strMinLen, int strMaxLen, int sizeBytes)
{
int count;
unsigned long val;
/* Check string length */
if ((strLen < strMinLen) || (strLen > strMaxLen))
return (-1);
/* Check string characters */
for (count=0 ; count<strLen ; count++) {
if (!isxdigit(pString[count]))
return (-2);
}
/* Convert to integer */
if (sizeBytes == 1) {
unsigned char *pChar = (unsigned char *)pVal;
for (count=0 ; count<((strLen+1)>>1) ; count++)
if (sscanf(&pString[count<<1], "%2lx", (unsigned long *)&val) == 1)
pChar[count] = (unsigned char)val;
else
return (-3);
} else if (sizeBytes == 2) {
unsigned short *pShort = (unsigned short *)pVal;
for (count=0 ; count<((strLen+3)>>2) ; count++)
if (sscanf(&pString[count<<2], "%4lx", (unsigned long *)&val) == 1)
pShort[count] = (unsigned short)val;
else
return (-3);
} else if (sizeBytes == 4) {
unsigned long *pLong = (unsigned long *)pVal;
for (count=0 ; count<((strLen+7)>>3) ; count++)
if (sscanf(&pString[count<<3], "%8lx", (unsigned long *)&val) == 1)
pLong[count] = (unsigned long)val;
else
return (-3);
} else {
return (-4);
}
return 0;
}
/* MRD still need to read /proc/cmdline after we drop root permission,
* so cache it in this function */
int get_kernel_cmdline(char *buf, int len)
{
static char cmdline[CMDLINE_LEN];
static int is_init = 0;
int ret = -1;
int fd;
if(!buf || len <= 0) return -1;
if(is_init)
goto INITED;
fd = open(PROC_CMDLINE, O_RDONLY);
if (fd < 0)
goto ERR_RET;
ret = read(fd, cmdline, CMDLINE_LEN);
close(fd);
if(ret <= 0 || ret > CMDLINE_LEN)
goto ERR_RET;
cmdline[ret - 1] = '\0';
INITED:
ret = strlen(cmdline) + 1;
if(ret > len)
ret = len;
strncpy(buf, cmdline, ret);
buf[ret - 1] = '\0';
is_init = 1;
return ret;
ERR_RET:
return -1;
}
int get_bspflag_from_kernel_cmdline(void)
{
char cmdline[CMDLINE_LEN];
char *pstr;
int ret;
static int is_init = 0;
static int flag = 0;
if(is_init) return flag;
ret = get_kernel_cmdline(cmdline, CMDLINE_LEN);
if (ret < 0)
{
/* read error, goto err_ret */
goto ERR_RET;
}
ret = 0;
/* find the string "PROD=" in cmdline*/
pstr = strstr(cmdline, BSPFLG_NAME);
if(pstr)
{
pstr += strlen(BSPFLG_NAME);
ret = atoi(pstr);
}
else // not found PROD, need to check atcmdmode flag
{
if (strstr(cmdline, ATMOD_FLAG))
{
ret = DIAG_ATCMD_BSPFLAG;
}
}
flag = ret;
is_init = 1;
ERR_RET:
return ret;
}
int InUARTProduction_Mode()
{
int bspflag;
bspflag = get_bspflag_from_kernel_cmdline();
if(bspflag == DIAG_UART_BSPFLAG || bspflag == DIAG_ATCMD_BSPFLAG)
return 1;
else
return 0;
}
int InProduction_Mode(void)
{
int bspflag;
int ProdFlag = 0;
int is_prod = 0;
ProdFlag = !access(PROD_FLAG_FILE, F_OK);
if (ProdFlag)
{
is_prod = 2; //production mode
}
else
{
bspflag = get_bspflag_from_kernel_cmdline();
if((bspflag == DIAG_USB_BSPFLAG) || (bspflag == DIAG_UART_BSPFLAG))
{
is_prod = 2; //production mode
}
else if(bspflag == DIAG_ATCMD_BSPFLAG)
{
is_prod = 1; //at cmd mode
}
}
return is_prod;
}
/* function: get_chipid()
* get chipid from regdump file.
* return value: <0 error; 1 success
*/
int get_chipid(unsigned long *chipid)
{
int ret = -1, len;
FILE *fp_reg = NULL;
char *pstr;
char regline[REG_LINE_LEN];
fp_reg = fopen(REGDUMP_FILE, "rb");
if (NULL == fp_reg)
{
ret = -2;
goto CH_ERR_RET;
}
len = strlen(CHIPID_ADDRESS);
while(NULL != fgets(regline, REG_LINE_LEN, fp_reg))
{
if (!strncmp(regline, CHIPID_ADDRESS, len))
{
pstr = strchr(regline, REG_ADD_CON_SPLIT);
// pstr+1: skip ':'
*chipid = strtoul(pstr+1, 0, 16);
ret = 1;
break;
}
}
fclose(fp_reg);
CH_ERR_RET:
return ret;
}
/* function: get_hardwareVersion()
* get hardware version from /proc/cpuinfo.
* return value: <0 error; 1 success
*/
int get_hardwareVersion(char *hardwareVerBuf, int maxHdVerBufSize)
{
int ret = -1, hdVerKeyLen, hdVerValueLen;
FILE *fp = NULL;
char *pstr;
char line[HDVER_LINE_LEN];
fp = fopen("/proc/cpuinfo", "rb");
if (NULL == fp)
{
ret = -2;
goto ERR_RET;
}
hdVerKeyLen = strlen(HDVER_KEY);
while(NULL != fgets(line, HDVER_LINE_LEN, fp))
{
if (!strncmp(line, HDVER_KEY, hdVerKeyLen))
{
pstr = strchr(line, HDVER_KEY_VALUE_SPLIT);
if(pstr == NULL)
{
ret = -3;
break;
}
// ++pstr: skip ':'
hdVerValueLen = strlen(++pstr);
while(isspace(pstr[hdVerValueLen - 1]))
{
hdVerValueLen--;
}
pstr[hdVerValueLen] = '\0';
// 1 is for the space between hdVerKey and hdVerValue
while(isspace(*pstr) || ((hdVerKeyLen + hdVerValueLen + 1 >= maxHdVerBufSize) && (*pstr == '0')))
{
hdVerValueLen--;
pstr++;
}
if(hdVerKeyLen + hdVerValueLen + 1 >= maxHdVerBufSize || hdVerValueLen <= 0)
{
ret = -4;
break;
}
snprintf(hardwareVerBuf, maxHdVerBufSize, "%s %s", HDVER_KEY, pstr);
ret = 1;
break;
}
}
fclose(fp);
ERR_RET:
return ret;
}
/* function: Is_TD_mode()
* judge whether the baseband is TD or UMTS
* return value: 1 TD; 0 UMTS
*/
BOOL Is_TD_mode()
{
#ifdef BIONIC
char baseband[PROPERTY_VALUE_MAX];
property_get(SYS_BASEBAND_PROPERTY, baseband, "");
if(strcmp(baseband, BASEBAND_TD) == 0)
return TRUE;
else if(strcmp(baseband, BASEBAND_UMTS) == 0)
return FALSE;
else
{
return FALSE;
}
#else
return FALSE;
#endif
}
int saveProcessName(const char *execPath, char *dest, unsigned int size)
{
int len;
char *pPath, *pBase;
if(execPath == NULL || dest == NULL)
return -1;
len = strlen(execPath);
pPath = (char *)malloc(len + 1);
if(pPath == NULL)
return -1;
strcpy(pPath, execPath);
pBase = basename(pPath);
if((len = strlen(pBase) >= size))
{
free(pPath);
return -1;
}
strcpy(dest, pBase);
free(pPath);
return 0;
}
BOOL isDualSimSolution()
{
#ifdef OPT_DSDS
return TRUE;
#else
#ifdef BIONIC
char value[PROPERTY_VALUE_MAX];
property_get("persist.radio.multisim.config", value, "");
return !(strncmp(value, DS_KEY, strlen(DS_KEY)));
#else
return FALSE;
#endif
#endif
}
BOOL isSim2Master()
{
BOOL bDualSim = isDualSimSolution();
if(bDualSim)
{
#ifdef OPT_DSDS
int ret;
char value[PROPERTY_VALUE_MAX];
property_get("persist.sys.sim2.master.enable", value, "0");
ret = atoi(value);
return ret != 0;
#else
return FALSE;
#endif
}
return FALSE;
}
void setSim2Master(BOOL option)
{
#ifdef OPT_DSDS
if(option)
{
property_set("persist.sys.sim2.master.enable", "1");
}
else
{
property_set("persist.sys.sim2.master.enable", "0");
}
#else
(void) option;
#endif
return;
}
int setDualSimType(int type)
{
int ret = 0;
BOOL bDualSim = isDualSimSolution();
char value[PROPERTY_VALUE_MAX];
if(bDualSim)
{
snprintf(value, sizeof(value), "%d", type);
ret = property_set("persist.radio.multisim.type", value);
}
return ret;
}
/* 0: DUAL_SIM_DUAL_STANDBY
* 1: DUAL_SIM_SINGLE_STANDBY
* 2: DUAL_SIM_SGIT
* 3: DUAL_SIM_DUAL_STANDBY_FP
*/
int getDualSimType(void)
{
int type = -1;
BOOL bDualSim = isDualSimSolution();
char value[PROPERTY_VALUE_MAX];
if(bDualSim)
{
property_get("persist.radio.multisim.type", value, "3");
type = atoi(value);
}
return type;
}
void initDualSimType(int type)
{
BOOL bDualSim = isDualSimSolution();
char value[PROPERTY_VALUE_MAX];
int ivalue = -1;
if(bDualSim)
{
property_get("persist.radio.multisim.type", value, "-1");
ivalue = atoi(value);
if (ivalue == -1)
setDualSimType(type);
}
}
int openTtyDevice(const char* deviceName)
{
struct termios tio;
int serialfd1 = open(deviceName, O_RDWR);
if (serialfd1 < 0) {
fprintf(stderr, "Error opening device %s: %s\n", deviceName, strerror(errno));
goto exit;
}
(void)fcntl(serialfd1, F_SETFL, 0);
memset(&tio, 0x0, sizeof(tio));
tio.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
tio.c_iflag = IGNPAR;
tio.c_cc[VERASE] = 0x8; /* del */
tio.c_cc[VEOF] = 4; /* Ctrl-d */
tio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
tio.c_cc[VEOL] = 0xD; /* '\0' */
tcflush(serialfd1, TCIFLUSH);
tcsetattr(serialfd1, TCSANOW, &tio);
exit:
return serialfd1;
}
int connectUnixSocket(const char* socketName)
{
struct sockaddr_un addr;
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
return -1;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketName, sizeof(addr.sun_path)-1);
if (/*TEMP_FAILURE_RETRY*/(connect(sock,(const struct sockaddr*) &addr, sizeof(addr))) /*!=*/ < 0) {
fprintf(stderr, "Error connect to socket %s: %s\n", socketName, strerror(errno));
close(sock);
return -1;
}
return sock;
}
BOOL eeh_sd_card_available(int rw)
{
#ifdef BIONIC
#define CHECK_SD_DIR "/lost+found" /*always exists */
#else
#define CHECK_SD_DIR "/" /* unavaliable if not mounted */
#endif
int ret, mode;
mode = F_OK;
//if (rw)
mode |= R_OK | W_OK;
ret = access(SDCARD_MOUNT CHECK_SD_DIR, mode);
return (ret == 0);
}
BOOL check_if_old_eeh_process(char *ind, BOOL is_cp_eeh_old_ver)
{
BOOL is_sd_dump = eeh_sd_card_available(0);
if (is_sd_dump)
return TRUE;
if (!is_cp_eeh_old_ver) {
return FALSE;
} else {
if (ind == NULL)
return FALSE;
if (!strcmp(ind, "old_ap_eeh"))
return TRUE;
if (!strcmp(ind, "new_ap_eeh"))
return FALSE;
#ifdef CONFIG_ASR1901_EEH
if (!strcmp(ind, "com_DTCM.bin") ||
!strcmp(ind, "com_ITCM.bin") ||
!strcmp(ind, "com_GBDump.bin") ||
!strcmp(ind, "com_IPCDump.bin") ||
!strcmp(ind, "com_L2_bx2.bin") ||
!strcmp(ind, "com_L1_bx2c.bin") ||
!strcmp(ind, "com_BSRAM.bin") ||
!strcmp(ind, "com_RAMLOG.bin") ||
!strcmp(ind, "com_bx2du0.bin") ||
!strcmp(ind, "com_bx2du1.bin"))
return TRUE;
else
return FALSE;
#elif CONFIG_ASR1903_EEH
if (!strcmp(ind, "com_DTCM.bin") ||
!strcmp(ind, "com_ITCM.bin") ||
!strcmp(ind, "com_L1_bx2c.bin") ||
!strcmp(ind, "com_L2_bx2.bin") ||
!strcmp(ind, "com_squ.bin") ||
!strcmp(ind, "com_RAMLOG.bin"))
return TRUE;
else
return FALSE;
#else
if(!strcmp(ind, "com_DTCM.bin") ||
!strcmp(ind, "com_ITCM.bin") ||
!strcmp(ind, "com_GBDump.bin") ||
!strcmp(ind, "com_IPCDump.bin"))
return TRUE;
else
return FALSE;
#endif
}
}
ssize_t readFile(const char* path, void* buf, size_t len)
{
int fd = open(path, O_RDONLY);
if (fd < 0)
return TEL_FILE_OPEN_FAILED;
ssize_t size = read(fd, buf, len);
close(fd);
if (size < 0)
return TEL_FILE_READ_FAILED;
return size;
}
#ifdef __GLIBC__
size_t strlcat(char *dst, const char *src, size_t size)
{
size_t srclen; /* Length of source string */
size_t dstlen; /* Length of destination string */
dstlen = strlen(dst);
size -= dstlen + 1;
if (!size)
return (dstlen); /* No room, return immediately... */
srclen = strlen(src);
if (srclen > size)
srclen = size;
memcpy(dst + dstlen, src, srclen);
dst[dstlen + srclen] = '\0';
return (dstlen + srclen);
}
#endif