blob: f48280bb4e42a2706ca77e9ddd68a7e30429d9db [file] [log] [blame]
/*******************************************************************************
* °æÈ¨ËùÓÐ (C)2016, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
*
* ÎļþÃû³Æ: ramdump.c
* Îļþ±êʶ: ramdump.c
* ÄÚÈÝÕªÒª: ramdump linuxµ¼³ö¹¤¾ß
*
* ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
* ------------------------------------------------------------------------------
* 2016/3/10 V1.0 Create ´´½¨
*
*******************************************************************************/
/*******************************************************************************
* Í·Îļþ *
*******************************************************************************/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<getopt.h>
#include<stdarg.h>
#include<termios.h>
#include<stddef.h>
#include<dirent.h>
#include <unistd.h>
#include<time.h>
//#include<properties.h>
//#include<cutils/properties.h>
//#include<cutils/log.h>
/*******************************************************************************
* ³£Á¿¶¨Òå *
*******************************************************************************/
/*******************************************************************************
* ºê¶¨Òå *
*******************************************************************************/
#define MODEM_TRAP_PATH "/dev/ttyUSB0"
#define MODEM_TRAP_PATH2 "/dev/ttyUSB1"
// #define MODEM_RAMDUMP_PATH "/data/local/log/Ramdump"
#define RAMDUMP_DEFAULT_BAUD B115200
#define RAMDUMP_DEFAULT_DELAY 1000
#define USB_DIR_FILE_NAME_SIZE 1024
#define LOG_TAG "Modem_Ramdump"
#define USB_DIR_BASE "/sys/bus/usb/devices"
#define USB_PID 0x0197
#define SUCCESS 0
#define FAIL -1
//#define printf(...) ALOGE(__VA_ARGS__)
/*Ramdump Ö¸ÁÒå*/
#define DUMPFILE_LINK_REQ (UINT32)1 //ͬ²½ÇëÇó
#define DUMPFILE_LINK_RSP (UINT32)2 //ͬ²½ÇëÇóÓ¦´ð£¬¸½´øramdumpÎļþÊýÄ¿
#define DUMPFILE_FILE_REQ (UINT32)3 //ÇëÇóÖ¸¶¨±àºÅÎļþÐÅÏ¢
#define DUMPFILE_FILE_RSP (UINT32)4 //Îļþ±àºÅÎļþÐÅÏ¢Ó¦´ð£¬¸½´ø´«ÊäÎļþÃû¼°´óС
#define DUMPFILE_READ_REQ (UINT32)5 //ÇëÇó¶Áȡָ¶¨±àºÅÎļþÄÚÈÝ
#define DUMPFILE_READ_RSP (UINT32)6 //ÎļþÄÚÈݶÁȡӦ´ð£¬¸½´øÎļþÄÚÈÝ
#define DUMPFILE_END_REQ (UINT32)7 //´«Êä½áÊø
#define DUMPFILE_END_RSP (UINT32)8 //´«Êä½áÊøÓ¦´ð
#define DUMPFILE_CMD_FAIL (UINT32)9 //Ö¸Áî´íÈ¥
#define DUMPFILE_NO_FAIL (UINT32)10 //Îļþ±àºÅ´íÎó
#define DUMPFILE_LENGTH_FAIL (UINT32)11 //ÎļþλÖôóС´íÎó
#define CMD_BUFFER_LEN (UINT32)16 //Ö¸Áî²Á·À¶¾
#define FILENAME_LEN (UINT32)32 //ÎļþÃû³¤¶È
#define FILENAME_MAX_LEN (UINT32)256 //ÎļþÃû×î´ó³¤¶È
#define DATA_BLOCK_SIZE (0x40000) // Êý¾Ý»º³å´óС
//#define DATA_BLOCK_SIZE (0x00800) // Êý¾Ý»º³å´óС,2k
#define MIN(a, b) ((a)< (b) ? (a): (b))
#define DEFAULT_RAMDUMP_FOLD "/home/dujing/code/v3/ramdump/ramdump_file/" //"/mnt/sdcard/ramdump"
//#define ZTE_LOG_PATH "/home/dujing/code/v3/ramdump/zte_file"
#define CPLOG_PATH "persist.service.ztelog.path"
//#define CPLOG_TIMESTAMP_DIR "persist.service.ztelog.timedir"
#define __FUNCTION__ "ramdumpfuc"
/*******************************************************************************
* Êý¾ÝÀàÐͶ¨Òå *
*******************************************************************************/
typedef struct {
char file_name[32];
unsigned int file_size;
} file_info_t;
typedef unsigned int UINT32;
/*******************************************************************************
* º¯ÊýÉùÃ÷ *
*******************************************************************************/
extern int dev_get_usbsys_val(const char *sys_filename, int base);
extern int dev_strStartsWith(const char *line, const char *src);
extern int dev_get_ttyport_by_syspath(char *syspath);
extern int dev_get_device(void);
/*******************************************************************************
* ¾Ö²¿¾²Ì¬±äÁ¿¶¨Òå *
*******************************************************************************/
static int g_modem_fd = -1;
static int g_reboot_flag = 0;
static int g_moniter_time = 0;
/*******************************************************************************
* È«¾Ö±äÁ¿¶¨Òå *
*******************************************************************************/
int PROPERTY_VALUE_MAX = 256;
extern int g_usb_dev;
/*******************************************************************************
* ¾Ö²¿º¯ÊýʵÏÖ *
*******************************************************************************/
static void mdp_print_array(const char* prefix, const char *buf, int length)
{
#if 0
int i = 0;
int len = MIN(length,16 );
printf("%s ", prefix );
for (i = 0; i< len; i++) {
printf("%02X ", buf[i]);
}
if (length > len)
printf("...");
printf("\n");
#endif
}
static int tty_write(int fd, const char *buf, int size)
{
int ret = 0;
int repeat_count = 0;
WRITE:
ret = write(fd, buf, size);
if (0 == ret) {
printf("%s error: %s\n", __FUNCTION__, strerror(errno));
repeat_count += 1;
if (3 > repeat_count) {
sleep(1);
goto WRITE;
}
}
if (ret != size) {
printf("%s failed, size=%d, ret=%d\n", __FUNCTION__, size, ret);
return -1;
}
return 0;
}
static int tty_read(int fd, char *buf, int size, unsigned int delay_ms)
{
int ret = -1;
int read_count = 0;
fd_set fds;
int repeat_count = 0;
struct timeval tv;
if (buf == NULL)
return -1;
tv.tv_sec = delay_ms / 1000;
tv.tv_usec = (delay_ms % 1000) * 1000;
FD_ZERO(&fds);//Çå¿Õfd_set¼¯ºÏ
FD_SET(fd, &fds);//½«¸ø¶¨µÄÃèÊö·ûfd¼ÓÈ뼯ºÏµ±ÖÐ
READ:
ret = select(fd + 1, &fds, NULL, NULL, &tv);
if (ret > 0) {
read_count = read(fd, buf, size);
if (read_count <= 0) {
printf("%s read failed for ret=%d\n", __FUNCTION__, read_count);
return -1;
}
return read_count;
} else if (ret == 0) {
printf("%s select time out %dms\n", __FUNCTION__, delay_ms);
printf("%s timeout error: %s\n", __FUNCTION__, strerror(errno));
if (3 > repeat_count) {
repeat_count += 1;
sleep(1);
goto READ;
}
} else {
printf("%s select failed %s\n", __FUNCTION__, strerror(errno));
}
return -1;
}
static int mdp_send(const char *buf, int size)
{
mdp_print_array(__FUNCTION__, buf, size);
return tty_write(g_modem_fd, buf, size);
}
static int mdp_receive(char *buf, int size)
{
int count = 0;
int ret = 0;
int length = size;
char *pbuffer = buf;
while (length > 0) {
count = tty_read(g_modem_fd, pbuffer, size, RAMDUMP_DEFAULT_DELAY);
if (count < 0) {
return -1;
}
pbuffer += count;
length -= count;
}
mdp_print_array(__FUNCTION__, buf, size);
return size;
}
static int mdp_send_command(unsigned int cmd, unsigned int argc, ...)
{
char buffer[CMD_BUFFER_LEN] = {0};
unsigned int i = 0;
unsigned int arg = 0;
UINT32 *pbuffer = (UINT32*)buffer;
*pbuffer = cmd;
va_list ap;
va_start(ap, argc);
for (i=0; i<argc; i++) {
arg = va_arg(ap, unsigned int);
*(++pbuffer) = arg;
}
va_end(ap);
return mdp_send(buffer, CMD_BUFFER_LEN);
}
static int mdp_receive_ack(unsigned int ack)
{
int ret = 0;
unsigned int resp;
char buffer[64] = {0};
ret = mdp_receive((char *)&resp, sizeof(unsigned int));
// ret = mdp_receive(buffer, 64);
if (ret > 0) {
// resp = *(unsigned int*)buffer;
if (ack == resp)
return 0;
}
return -1;
}
static int init_devices(char* dev_path, speed_t speed)
{
int fd = -1;
struct termios tios;
printf("%s\n", __FUNCTION__);
fd = open(dev_path, O_RDWR);
if (fd < 0) {
printf("Can't open %s(%s)\n", dev_path, strerror(errno));
return -1;
}
if (tcgetattr(fd, &tios) < 0) {
printf(" tcgetattr failed(%s)\n", strerror(errno));
return -1;
}
tios.c_cflag = CS8 | CREAD | CRTSCTS | CLOCAL;
tios.c_iflag = IGNPAR;
tios.c_oflag = 0;
tios.c_lflag = 0;
tios.c_cc[VTIME] = 0;
tios.c_cc[VMIN] = 1;
cfsetispeed(&tios, RAMDUMP_DEFAULT_BAUD);
cfsetospeed(&tios, RAMDUMP_DEFAULT_BAUD);
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd,TCSANOW, &tios) < 0) {
printf(" tcgetattr failed(%s)\n", strerror(errno));
return -1;
}
return fd;
}
static int create_fold(char *fold)
{
char buffer[256]= {0};
snprintf(buffer, 256, "mkdir -p %s\n", fold);
int ret = system(buffer);
if (ret < 0)
return -1;
return 0;
}
static int create_file(char* fold, char * path)
{
int fd = -1;
DIR *pdir = NULL;
char file_name[FILENAME_MAX_LEN] = {0};
int ret = 0;
if ((fold==NULL) || (*fold=='\0'))
fold = DEFAULT_RAMDUMP_FOLD;
if ( (path==NULL) || (*path=='\0')) {
printf("%s path=NULL\n", __FUNCTION__);
return -1;
}
if ((pdir = opendir(fold)) == NULL) {
ret = create_fold(fold);
if (ret < 0) {
printf("%s create fold %s failed (%s)", __FUNCTION__, fold, strerror(errno));
return -1;
}
}
if (pdir != NULL)
closedir(pdir);
snprintf(file_name, FILENAME_MAX_LEN, "%s/%s", fold, path);
unlink(file_name);
printf("%s %s\n", __FUNCTION__, file_name);
fd = open(file_name, O_CREAT| O_RDWR, 0777);
if (fd < 0) {
printf("failed to create %s (%s)\n", path, strerror(errno));
}
return fd;
}
static int write_to_file(int fd, char*buffer, int size)
{
int ret = 0;
if ((fd < 0) || (buffer==NULL) || (size<=0))
return -1;
ret = write(fd, buffer, size);
if (ret < size) {
printf("write to file failed, ret=%d, size=%d\n", ret, size);
return -1;
}
return 0;
}
static int dump_file(int index, char *fold)
{
int ret = 0;
char path[256] = {0};
char cmd_buffer[CMD_BUFFER_LEN] = {0};
file_info_t file_info = {{0}, 0};
char data_buffer[DATA_BLOCK_SIZE] = {0};
int fd = 0;
int file_size, read_count, file_offset;
if ((ret = mdp_send_command(DUMPFILE_FILE_REQ, 1, index)) < 0) {
printf("%s failed to send command DUMPFILE_FILE_REQ\n", __FUNCTION__);
return -1;
}
if ((ret = mdp_receive_ack(DUMPFILE_FILE_RSP)) < 0) {
printf("%s failed to receive DUMPFILE_FILE_RSP\n", __FUNCTION__);
return -1;
}
if ((ret = mdp_receive((char*)&file_info, sizeof(file_info))) < 0) {
printf("%s failed to get fileinfo\n", __FUNCTION__);
return -1;
}
if ((fd = create_file(fold, file_info.file_name)) < 0) {
printf("failed to create file %s\n", file_info.file_name);
return -1;
}
printf("filename=%s\t size=%d\n", file_info.file_name, file_info.file_size);
file_size = file_info.file_size;
file_offset = read_count = 0;
while (file_size > 0) {
read_count = MIN(file_size, DATA_BLOCK_SIZE);
if (mdp_send_command(DUMPFILE_READ_REQ, 3, index, file_offset, read_count) < 0) {
printf("%s failed to send DUMPFILE_READ_REQ\n", __FUNCTION__);
ret = -1;
goto exit;
}
if (mdp_receive_ack(DUMPFILE_READ_RSP) < 0) {
printf("%s failed to receive ack DUMPFILE_READ_RSP\n", __FUNCTION__);
ret = -1;
goto exit;
}
if (mdp_receive(data_buffer, read_count) < 0) {
printf("failed to read file data\n");
ret = -1;
goto exit;
}
if (write_to_file(fd, data_buffer, read_count)< 0) {
printf("failed to write file data\n");
ret = -1;
goto exit;
}
file_offset += read_count;
file_size -= read_count;
}
ret = 0;
exit:
close(fd);
return ret;;
}
static int do_modem_ramdump( char* tty, char*path)
{
int ret = -1;
int file_number = 0;
int i = 0;
g_modem_fd = init_devices(tty, RAMDUMP_DEFAULT_BAUD);
if (g_modem_fd < 0) {
printf("failed to open %s\n", tty);
return -1;
}
if ((ret = mdp_send_command(DUMPFILE_LINK_REQ, 0)) < 0) {
printf("Send DUMPFILE_LINK_REQ failed\n");
ret = -1;
goto exit;
}
if ((ret = mdp_receive_ack(DUMPFILE_LINK_RSP)) < 0) {
printf("failed to receive DUMPFILE_LINK_RSP\n");
ret = -1;
goto exit;
}
ret = mdp_receive((char*)&file_number, sizeof(unsigned int));
if (ret < 0) {
printf("failed to get filenumber\n");
ret = -1;
goto exit;
}
printf("file_number = %d\n", file_number);
for (i = 0; i < file_number; i++) {
printf("dump file index=%d \n", i);
ret = dump_file(i, path);
if (ret < 0) {
printf("dump file index=%d failed\n", i);
ret = -1;
goto exit;
}
printf("dump file index=%d success\n", i);
}
if (g_reboot_flag == 1){
printf("ramdump except reboot enabled\n");
if ((ret = mdp_send_command(DUMPFILE_END_REQ, 0)) < 0) {
printf("failed to send DUMPFILE_END_REQ\n");
ret = -1;
goto exit;
}
mdp_receive_ack(DUMPFILE_END_RSP);
}
ret = 0;
exit:
if (g_modem_fd > 0)
close(g_modem_fd);
return ret;
}
void broadcast_ramdump_result(int success)
{
char command[256];
snprintf(command, 256, "am broadcast -a zte.com.cn.intent_modemramdump_finished --ez extra_success %s", (success == 0 ? "true" : "false"));//Android·¢Ë͹㲥ָÁî
printf("%s %s\n", __FUNCTION__, command);
system(command);
}
static void compress_and_rm_fold(char *pfold, char *time_str)
{
char buffer[512] = {0};
int ret = 0;
//sunjy add
//delete duplicate file which preffix is g_current_file_index;
snprintf(buffer, 512, "cd %s; busybox rm -rvf %s\n", pfold, "*.tgz");
printf("%s %s\n", __FUNCTION__, buffer);
system(buffer);
char preffix[256] = {0};
char str[256] = {0};
strcat(preffix, time_str);
strcpy(time_str, preffix);
printf("%s %s %s\n", __FUNCTION__, pfold, time_str);
snprintf(buffer, 512, "cd %s; busybox tar -zcf %s.tgz %s/*\n", pfold, time_str, time_str);
printf("%s %s\n", __FUNCTION__, buffer);
ret = system(buffer);
if(ret != 0){
printf("compress failed, delete the unfinished compressed file\n");
snprintf(buffer, 512, "cd %s; busybox rm -rf %s.tgz \n", pfold, time_str);
}else {
printf("compress finished, delete the source fold\n");
snprintf(buffer, 512, "cd %s; busybox rm -rf %s\n", pfold, time_str);
// property_set("persist.service.ramdump.index", str); (ºóÐø´ò¿ª£©
// property_get("persist.service.ramdump.index", str, "6"); OPEN LATER
//printf("%s %s %s\n", __FUNCTION__, "persist.service.ramdump.index=", str);
}
printf("%s %s\n", __FUNCTION__, buffer);
system(buffer);
}
static int get_time_str(char *buf, size_t size)
{
struct tm cur_tm;
time_t now = time(NULL);
if (NULL==buf || size<=0)
return -1;
localtime_r(&now, &cur_tm);
strftime(buf, size, "%Y_%m%d_%H%M%S", &cur_tm);
printf("%s %s\n", __FUNCTION__, buf);
return 0;
}
static int get_ramdump_fold_name(char *ramdump_path, size_t size, char *prefix, char *time_buffer)
{
if (ramdump_path == NULL || size <= 0 || time_buffer == NULL)
return -1;
//sunjy add
//modify path,like "sdcard0/GoTaLog/Ramdump/index.yyyymmdd_hhmmss"
//char logTime[30] = {0};
//property_get(CPLOG_PATH, ramdump_path, ZTE_LOG_PATH);
strcat(ramdump_path, prefix);
strcat(ramdump_path, "/");
strcat(ramdump_path, time_buffer);
//snprintf(ramdump_path, size, "%s/%s", prefix, time_buffer);
printf("%s %s\n", __FUNCTION__, ramdump_path);
return 0;
}
static int ramdump_export(char *dump_path)
{
int ret = -1;
int i;
char dev_tty[256] = {0};
for (i = 0; i <= 255; i++) {
snprintf(dev_tty, 256, "/dev/ttyUSB%d", i);
if (access(dev_tty, F_OK) < 0){
continue;
}
printf("try to get the ramdump data from %s\n", dev_tty);
ret = do_modem_ramdump(dev_tty, dump_path);
if (ret >= 0) {
printf("get the ramdump data from %s success\n", dev_tty);
//compress_and_rm_fold(DEFAULT_RAMDUMP_FOLD, time_str);
break;
} else if (ret == -1) {
printf("try to repeat do_modem_ramdump begin\n");
ret = do_modem_ramdump(dev_tty, dump_path);
if (ret >= 0) {
printf("get the ramdump data from %s success\n", dev_tty);
//compress_and_rm_fold(DEFAULT_RAMDUMP_FOLD, time_str);
break;
}else{
printf("get the ramdump data from %s failed\n", dev_tty);
}
}
}
return ret;
}
static int ramdump_mainloop(int moniter_time, char *dump_path)
{
int ret = -1;
char dev_tty[256] = {0};
while(1)
{
if ((ret == -1) && (moniter_time >= 0))
sleep(moniter_time);
else
break;
ret = dev_get_device();
}
if (g_usb_dev < 0)
return -1;
snprintf(dev_tty, 256, "/dev/ttyUSB%d", g_usb_dev);
ret = do_modem_ramdump(dev_tty, dump_path);
if (ret >= 0) {
printf("get the ramdump data from %s success\n", dev_tty);
} else if (ret == -1) {
printf("try to repeat do_modem_ramdump begin\n");
ret = do_modem_ramdump(dev_tty, dump_path);
if (ret >= 0) {
printf("get the ramdump data from %s success\n", dev_tty);
}else{
printf("get the ramdump data from %s failed\n", dev_tty);
}
}
return ret;
}
/*******************************************************************************
* È«¾Öº¯ÊýʵÏÖ *
*******************************************************************************/
int main(int argc, char* argv[])
{
int ret = -1;
int opt = 0;
int dump_path_flag = 0;
char dump_path[256] = {0};
char time_str[64] = {0};
// property_set("ctl.stop", "ztemodemlog");
//sleep(1);
if(get_time_str(time_str, 64) < 0){
printf("Can't get the time str\n");
return -1;
}
if (argc == 1){
get_ramdump_fold_name(dump_path, 256, DEFAULT_RAMDUMP_FOLD, time_str);
dump_path_flag = 1;
ret = ramdump_export(dump_path);
return ret;
}
ret = -1;
while((opt = getopt(argc, argv, ":p:rt:m")) != -1){
switch(opt){
case 'p':
{
ret = get_ramdump_fold_name(dump_path, 256, optarg, time_str);
dump_path_flag = 1;
if (ret < 0) {
printf("Can't get the ramdump fold path\n");
return -1;
}
break;
}
case 'r':
{
g_reboot_flag = 1;
break;
}
case 't':
{
g_moniter_time = atoi(optarg);
}
case 'm':
{
printf("begin to monitor ramdump!\n");
if (dump_path_flag == 0){
get_ramdump_fold_name(dump_path, 256, DEFAULT_RAMDUMP_FOLD, time_str);
dump_path_flag = 1;
}
ret = ramdump_mainloop(g_moniter_time, dump_path);
return ret;
}
case '?':
printf("invailed arguments!\n");
return -1;
}
}
if (dump_path_flag == 0){
get_ramdump_fold_name(dump_path, 256, DEFAULT_RAMDUMP_FOLD, time_str);
dump_path_flag = 1;
}
ret = ramdump_export(dump_path);
return ret;
}