You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
537 lines
13 KiB
C
537 lines
13 KiB
C
/* Includes ------------------------------------------------------------------*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
/* 标准C库头文件. */
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <poll.h>
|
|
|
|
#include "cmd.h"
|
|
#include "mtimer.h"
|
|
#include "process.h"
|
|
#include "hwgpio.h"
|
|
#include "fifo.h"
|
|
#include "ca_dbg.h"
|
|
#include "ca_csg.h"
|
|
#include "ca_cau.h"
|
|
#include "ca_param.h"
|
|
#include "ca_network.h"
|
|
#include "debug.h"
|
|
#include "common.h"
|
|
extern int csg_reconn_times;
|
|
extern int mqtt_reconn_times;
|
|
|
|
/* Private define ------------------------------------------------------------*/
|
|
int _network_chat(int fd, const char *at, const char *expect, int timeout, char **response, bool IsPrintf)
|
|
{
|
|
int ret;
|
|
int read_len = 0;
|
|
static char buf[512];
|
|
int errNo = 0;
|
|
|
|
if (response)
|
|
{
|
|
*response = NULL;
|
|
}
|
|
|
|
tcflush(fd, TCIOFLUSH);
|
|
|
|
if (IsPrintf == 1)
|
|
{
|
|
LOG("chat --> %s", at);
|
|
}
|
|
|
|
do
|
|
{
|
|
ret = write(fd, at, strlen(at));
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
if (ret <= 0)
|
|
{
|
|
if (IsPrintf == 1)
|
|
{
|
|
errNo = errno;
|
|
LOG("chat write error on stdout: %s(%d) ", strerror(errNo), errNo);
|
|
}
|
|
return errno ? errno : EINVAL;
|
|
}
|
|
|
|
struct pollfd poll_fd = {fd, POLLIN, 0};
|
|
if (poll(&poll_fd, 1, timeout > 600 ? timeout : 600) <= 0)
|
|
{
|
|
if (errno != EINTR)
|
|
{
|
|
if (IsPrintf == 1)
|
|
{
|
|
errNo = errno;
|
|
LOG("chat poll error on stdin:[%d][%s] %s(%d) ", ret, at, strerror(errNo), errNo);
|
|
}
|
|
return errno ? errno : EINVAL;
|
|
}
|
|
}
|
|
if (poll_fd.revents && (poll_fd.revents & POLLIN))
|
|
{
|
|
memset(buf, 0, sizeof(buf));
|
|
usleep(100 * 1000);
|
|
if ((read_len = read(fd, buf, sizeof(buf) - 1)) <= 0)
|
|
{
|
|
if (IsPrintf == 1)
|
|
{
|
|
errNo = errno;
|
|
LOG("chat read error on stdin: %s(%d) ", strerror(errNo), errNo);
|
|
}
|
|
return errno ? errno : EINVAL;
|
|
}
|
|
|
|
if (IsPrintf == 1)
|
|
{
|
|
LOG("\nchat return ret=[%d] at=[%s]string.len = [%d] <----- [%s];expect:[%s]\n", ret, at, strlen(buf), buf, expect);
|
|
}
|
|
|
|
if (read_len >= 512)
|
|
{
|
|
LOG("chat read max len [read:%d--max:%d]\n", read_len, 512);
|
|
return -1;
|
|
}
|
|
|
|
if (strstr(buf, expect))
|
|
{
|
|
|
|
if (response)
|
|
{
|
|
*response = strstr(buf, expect);
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if (response)
|
|
{
|
|
*response = buf;
|
|
}
|
|
}
|
|
}
|
|
|
|
return errno ? errno : EINVAL;
|
|
}
|
|
|
|
int _network_AT_read_operation(const char *Devname, const char *cmd, \
|
|
const char *tag, char *response, int timeout)
|
|
{
|
|
int modem_fd = -1, fdflags;
|
|
struct termios ios;
|
|
int modembits = TIOCM_DTR;
|
|
char *TmpResponse;
|
|
int ret = 0;
|
|
|
|
if (Devname == NULL || response == NULL || tag == NULL)
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
pthread_mutex_lock(&network_ctrl.m_mutex);
|
|
|
|
modem_fd = open (Devname, O_RDWR | O_NONBLOCK);
|
|
if (modem_fd == -1)
|
|
{
|
|
LOG("open AT Dev[%s] error\n", Devname);
|
|
pthread_mutex_unlock(&network_ctrl.m_mutex);
|
|
return 1;
|
|
}
|
|
|
|
fdflags = fcntl(modem_fd, F_GETFL);
|
|
if (fdflags != -1)
|
|
{
|
|
fcntl(modem_fd, F_SETFL, fdflags | O_NONBLOCK);
|
|
}
|
|
tcgetattr( modem_fd, &ios );
|
|
cfmakeraw(&ios);
|
|
ios.c_lflag = 0;
|
|
cfsetispeed(&ios, B115200);
|
|
cfsetospeed(&ios, B115200);
|
|
tcsetattr( modem_fd, TCSANOW, &ios );
|
|
ioctl(modem_fd, (0 ? TIOCMBIS : TIOCMBIC), &modembits);
|
|
|
|
ret = _network_chat(modem_fd, cmd, tag, timeout, &TmpResponse, 1);
|
|
if (0 != ret)
|
|
{
|
|
LOG("AT Error!!ret=%s, AT:[%s]----->response:[%s].", strerror(ret), cmd, TmpResponse);
|
|
close(modem_fd);
|
|
pthread_mutex_unlock(&network_ctrl.m_mutex);
|
|
return 2;
|
|
}
|
|
//_MSG("TmpResponse :%s, len = %d\n", TmpResponse, strlen(TmpResponse));
|
|
memcpy(response, TmpResponse, sizeof(char) * 512);
|
|
|
|
pthread_mutex_unlock(&network_ctrl.m_mutex);
|
|
return 0;
|
|
}
|
|
|
|
int _network_change_apn(const char *apn)
|
|
{
|
|
int i=0,num;
|
|
char str[100][256]={{0}};
|
|
char linedata[256]={0};
|
|
FILE *fp=fopen("/etc/ppp/peers/quectel-chat-connect","r");
|
|
if(NULL == fp)
|
|
{
|
|
LOG("fopen failed [%d:%s]", errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
while (fgets(linedata,sizeof(linedata)-1,fp))
|
|
{
|
|
if (strstr(linedata,"AT+CGDCONT")!=NULL)
|
|
{
|
|
sprintf(str[i],"OK \\rAT+CGDCONT=1,\"IP\",\"%s\",,0,0\n",apn);
|
|
}
|
|
else
|
|
{
|
|
strcpy(str[i],linedata);
|
|
}
|
|
i++;
|
|
}
|
|
fclose(fp);
|
|
|
|
num=i;
|
|
FILE * fpw = fopen("/etc/ppp/peers/quectel-chat-connect","w");
|
|
for (i=0;i<num;i++)
|
|
{
|
|
fputs(str[i],fpw);
|
|
}
|
|
fflush(fpw);
|
|
fclose(fpw);
|
|
return 0;
|
|
}
|
|
|
|
void _network_usb_4g_power_on(void)
|
|
{
|
|
LOG("\n");
|
|
GPIO_USB_4G_PWR(ON);
|
|
GPIO_USB_4G_WAKEUP(ON);
|
|
sleep(5);
|
|
}
|
|
|
|
void _network_usb_4g_reset(void)
|
|
{
|
|
/* RST
|
|
____ ___ ____
|
|
| |
|
|
| |
|
|
|-------------------|
|
|
|<---150ms~460ms--->|
|
|
*
|
|
*/
|
|
|
|
LOG("\n");
|
|
GPIO_USB_4G_RST(1); // low
|
|
usleep(350*1000);
|
|
GPIO_USB_4G_RST(0); // high
|
|
sleep(30);
|
|
}
|
|
|
|
void _network_quectel_exec(void)
|
|
{
|
|
char cmd[250] = {0};
|
|
strcpy(cmd, "pppd call quectel-ppp &");
|
|
LOG("%s", cmd);
|
|
system(cmd);
|
|
sleep(20);
|
|
}
|
|
|
|
void _network_kill_ppp()
|
|
{
|
|
char cmd[250] = {0};
|
|
strcpy(cmd, "killall pppd");
|
|
LOG("%s", cmd);
|
|
system(cmd);
|
|
}
|
|
|
|
int _network_check_usb_exist(const char* iDevPath)
|
|
{
|
|
int iReturnCode = 0;
|
|
struct stat tmpstat;
|
|
if (NULL == iDevPath)
|
|
{
|
|
iReturnCode = 1;
|
|
}
|
|
else
|
|
{
|
|
if (stat(iDevPath, &tmpstat) != 0)
|
|
{
|
|
LOG("4G module USB not exist!\n");
|
|
iReturnCode = 1;
|
|
}
|
|
}
|
|
|
|
return iReturnCode;
|
|
}
|
|
|
|
int _network_ppp_check(void)
|
|
{
|
|
char cmd[100];
|
|
FILE *Read_fp;
|
|
int chars_read;
|
|
char buffer[1000];
|
|
static int ResetEC20Cnt = 0; //重启次数
|
|
memset(buffer,0,1000);
|
|
memset(cmd,0,100);
|
|
sprintf(cmd,"ifconfig | grep ppp0");
|
|
Read_fp = popen(cmd,"r");
|
|
if(Read_fp != NULL)
|
|
{
|
|
chars_read = fread(buffer,sizeof(char),1000-1,Read_fp);
|
|
pclose(Read_fp);
|
|
|
|
if(chars_read > 0)
|
|
{
|
|
ResetEC20Cnt = 0;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
ResetEC20Cnt++;
|
|
if(ResetEC20Cnt > 6)
|
|
{
|
|
ResetEC20Cnt = 0;
|
|
reboot_system(LOG_NETWORK, BOOT_PPP_NO_FOUND);
|
|
}
|
|
|
|
system("killall pppd");
|
|
_network_usb_4g_power_on();
|
|
_network_usb_4g_reset();
|
|
LOG("ppp0:No Found.EC20 掉线");
|
|
_network_quectel_exec();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int _network_ppp_check_test(void)
|
|
{
|
|
char cmd[100];
|
|
FILE *Read_fp;
|
|
int chars_read;
|
|
char buffer[1000];
|
|
memset(buffer,0,sizeof(buffer));
|
|
memset(cmd,0,sizeof(cmd));
|
|
sprintf(cmd,"ifconfig | grep ppp0");
|
|
Read_fp = popen(cmd,"r");
|
|
if(Read_fp != NULL)
|
|
{
|
|
chars_read = fread(buffer,sizeof(char),1000-1,Read_fp);
|
|
pclose(Read_fp);
|
|
|
|
if(chars_read > 0)
|
|
{
|
|
//LOG("ppp0 success");
|
|
return 1;
|
|
}
|
|
}
|
|
LOG("not found ppp0");
|
|
return 0;
|
|
}
|
|
|
|
|
|
void _network_connect_4g()
|
|
{
|
|
int iReturnCode = -1;
|
|
char response[512] = {0};
|
|
if (network_ctrl.net_dev_stat == PPP_ON)
|
|
{
|
|
//if (_network_get_module_type() == WCDMA_EC20)
|
|
//{
|
|
// ret_code = _network_AT_read_operation(DEV_NAME_4G_QUECTEL, "AT+CSQ\r\n", "+CSQ:", response);
|
|
//}
|
|
if (_network_check_usb_exist(DEV_NAME_4G_QUECTEL) != 0)
|
|
{
|
|
network_ctrl.net_dev_stat = PPP_OFF;
|
|
}
|
|
//iReturnCode = _network_AT_read_operation(DEV_NAME_4G_QUECTEL, "AT+CSQ\r\n", "+CSQ:", response, 0);
|
|
//LOG("at return=%d", iReturnCode);
|
|
//LOG("response=%s", response);
|
|
}
|
|
else
|
|
{
|
|
//_network_usb_4g_reset();
|
|
//sleep(20);
|
|
_network_quectel_exec();
|
|
network_ctrl.net_dev_stat = PPP_ON;
|
|
sleep(20);
|
|
}
|
|
}
|
|
|
|
void _network_recovery_dial_file()
|
|
{
|
|
int i, num;
|
|
char src[128] = {0};
|
|
char cmd[256] = {0};
|
|
char file_path[128] = {0};
|
|
char file_name[][128] =
|
|
{
|
|
"quectel-chat-connect",
|
|
"quectel-chat-disconnect",
|
|
"quectel-dial",
|
|
"quectel-ppp"
|
|
};
|
|
|
|
num = sizeof(file_name)/sizeof(file_name[0]);
|
|
//LOG("num=%d\n", num);
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
snprintf(file_path, 128, "%s/%s", DIAL_PPP_PATH, file_name[i]);
|
|
|
|
if (access(file_path, F_OK))
|
|
{
|
|
snprintf(src, 128, "%s/%s", DIAL_PPP_BAK_PATH, file_name[i]);
|
|
if (access(src, F_OK) == 0)
|
|
{
|
|
snprintf(cmd, 256, "cp -rf %s %s", src, DIAL_PPP_PATH);
|
|
system(cmd);
|
|
LOG("exec:%s\n", cmd);
|
|
usleep(100*1000);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void *_network_manage_thread(void *args)
|
|
{
|
|
//_network_connect_4g();
|
|
|
|
int reset_cnt = 0;
|
|
int ppp_not_found_cnt = 0;
|
|
int start_4g_flag = 0;
|
|
|
|
while (1)
|
|
{
|
|
if (pparam_config->gateway.radioType != 1)
|
|
{
|
|
DBG(DBG_M_CA_NETWORK, "radioType:%d", pparam_config->gateway.radioType);
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
if (start_4g_flag == 0)
|
|
{
|
|
start_4g_flag = 1;
|
|
_network_usb_4g_power_on();
|
|
LOG("4G module power on");
|
|
sleep(15);
|
|
_network_quectel_exec();
|
|
}
|
|
|
|
if (access(DEV_NAME_4G_QUECTEL, F_OK) == 0)
|
|
{
|
|
reset_cnt = 0;
|
|
if (_network_ppp_check_test() == 0)
|
|
{
|
|
// not found ppp0
|
|
if (++ppp_not_found_cnt >= 6)
|
|
{
|
|
LOG("ppp0 not found > %d times, should reboot.", ppp_not_found_cnt);
|
|
ppp_not_found_cnt = 0;
|
|
reboot_system(LOG_NETWORK, BOOT_PPP_NO_FOUND);
|
|
|
|
}
|
|
_network_kill_ppp();
|
|
_network_usb_4g_power_on();
|
|
_network_usb_4g_reset();
|
|
_network_quectel_exec();
|
|
}
|
|
else
|
|
{
|
|
// found ppp0
|
|
ppp_not_found_cnt = 0;
|
|
// The connection still fails in the presence of ppp0 and needs to be restarted
|
|
if (pparam_config->gateway.CommunicationMode == 2)
|
|
{
|
|
if (mqtt_reconn_times > 6)
|
|
{
|
|
reboot_system(LOG_NETWORK, BOOT_PPP_FOUND_MQTT_LINK_FAIL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (csg_reconn_times > 10)
|
|
{
|
|
reboot_system(LOG_NETWORK, BOOT_PPP_FOUND_CSG_LINK_FAIL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ppp_not_found_cnt = 0;
|
|
LOG("%s is not exist!!!! reset_cnt = %d\n", DEV_NAME_4G_QUECTEL, reset_cnt);
|
|
if (++reset_cnt >= 6)
|
|
{
|
|
reset_cnt = 0;
|
|
reboot_system(LOG_NETWORK, BOOT_TTYUSB_NO_FOUND);
|
|
}
|
|
|
|
_network_usb_4g_power_on();
|
|
_network_usb_4g_reset();
|
|
_network_quectel_exec();
|
|
}
|
|
_network_recovery_dial_file();
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
int _network_handle_init_common()
|
|
{
|
|
struct sched_param param;
|
|
pthread_attr_t attr;
|
|
pthread_t pid;
|
|
int32_t rv = 0;
|
|
|
|
/* 配置线程RR调度, 优先级72 */
|
|
pthread_attr_init(&attr);
|
|
param.sched_priority = 76;
|
|
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
|
pthread_attr_setschedparam(&attr, ¶m);
|
|
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
rv = pthread_create(&pid, &attr, _network_manage_thread, NULL);
|
|
if (rv != 0)
|
|
{
|
|
log_err(LOG_NETWORK, "PD can't create _network_manage_thread %d!", rv);
|
|
return E_ERROR;
|
|
}
|
|
else
|
|
{
|
|
thread_m_add("CA_NETWORK", pid);
|
|
}
|
|
pthread_attr_destroy(&attr);
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
|
|
/* Interface functions -------------------------------------------------------*/
|
|
/* 4G模块初始化. */
|
|
int network_handle_init(void)
|
|
{
|
|
//_network_usb_4g_power_on();
|
|
//LOG("4G module power on");
|
|
//sleep(15);
|
|
memset(&network_ctrl, 0, sizeof(network_ctrl));
|
|
network_ctrl.net_dev_stat = PPP_OFF;
|
|
pthread_mutex_init(&network_ctrl.m_mutex, NULL);
|
|
/* 初始化模块. */
|
|
LD_E_RETURN(DBG_M_CA_NETWORK_ERR, _network_handle_init_common());
|
|
|
|
return E_NONE;
|
|
}
|
|
|