/* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* 标准C库头文件. */ #include #include #include #include #include #include #include #include #include #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; /* 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; } void _network_set_connect_type(e_connetType type) { network_ctrl.connetType = type; } 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| * */ 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); } void _network_check_change() { if (network_ctrl.connetType == network_ctrl.last_connect_type) { return ; } else { if (network_ctrl.connetType == CONNET4G) { network_ctrl.net_dev_stat = PPP_OFF; } network_ctrl.last_connect_type = network_ctrl.connetType; } } 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 (csg_reconn_times > 10) { reboot_system(LOG_NETWORK, BOOT_PPP_FOUND_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_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; }