| /* |
| * modem_controller.c -- modem controller module |
| * |
| * (C) Copyright [2006-2008] Marvell International Ltd. |
| * All Rights Reserved |
| * |
| */ |
| |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <cutils/properties.h> |
| #include <termios.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/ioctl.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <pthread.h> |
| #include <semaphore.h> |
| #include <sys/prctl.h> |
| #if 0// ndef BIONIC |
| #include <linux/prctl.h> |
| #endif |
| #include "pxa_dbg.h" |
| #include "ppprd_linux.h" |
| #include "modem_platform.h" |
| #include "modem_controller.h" |
| #include <linux/tty.h> |
| #include "utilities.h" |
| #include "ml_utils.h" |
| #include "cmux.h" |
| #include "utlTimer.h" |
| |
| |
| #ifdef PPP_WITHOUT_ATSRV |
| static int b_unlink_sent = 0; |
| #endif |
| |
| int ppp_at_fd; |
| int ppp_modem_fd = 0; |
| int ppprd_fd; |
| int pipefd[2]; |
| int ppp_cm_fd; |
| |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| int ppp_at_fd1; |
| int ppp_modem_fd1 = 0; |
| static struct at_channel_struct ppp_modem1; |
| static struct at_channel_struct ppp_at1; |
| #endif |
| |
| #ifdef UART2_AT |
| int ppp_at_fd2; |
| int ppp_uart2_fd; |
| static struct at_channel_struct ppp_uart2; |
| static struct at_channel_struct ppp_at2; |
| #endif |
| |
| #ifdef PPP_PSEUDO_DEVICE |
| int ppp_at_fd_pseudo = 0; |
| int ppp_modem_fd_pseudo = 0; |
| static struct at_channel_struct ppp_modem_pseudo; |
| static struct at_channel_struct ppp_at_pseudo; |
| #endif |
| |
| int ppp_gsm_fd[MAX_MUX]; |
| |
| static struct at_channel_struct ppp_modem; |
| static struct at_channel_struct ppp_at; |
| static struct at_channel_struct ppp_gsm[MAX_MUX]; |
| struct ml_fifo ppp_fifo; |
| |
| unsigned int old_connected_ppp_cid = INVALID_CID; |
| |
| modem_control_interface modem_if; |
| |
| static bool ath_data; |
| static bool ato_data; |
| |
| static speed_t baud_bits[] = { |
| 0, B9600, B19200, B38400, B57600, B115200, B230400, B460800 |
| }; |
| |
| static Serial serial; |
| |
| pthread_mutex_t channelid_lock; |
| |
| #define MODEM_AT_STATISTICS |
| #ifdef MODEM_AT_STATISTICS |
| struct modem_at_statistics { |
| int cmd_count; |
| int cmd_byte; |
| int rsp_count; |
| int rsp_byte; |
| }; |
| struct modem_at_statistics at_statistics; |
| #endif |
| |
| extern void setup_callback_funcs(ppp_cb_funcs *); |
| extern int get_modem_state(void); |
| |
| char *get_ppp_apn() |
| { |
| return modem_if.pdp_params.apn; |
| } |
| |
| char get_ppp_iptype() |
| { |
| return modem_if.pdp_params.ip_type; |
| } |
| |
| int get_modem_data_mode_fd(void) |
| { |
| int i = 0; |
| |
| for ( i = 0; i < MAX_MODEM_CHANNLE; i++) |
| { |
| if (modem_if.modem_state[i] == ACM_DATA_MODE) |
| break; |
| } |
| |
| if (i < MAX_MODEM_CHANNLE) |
| return modem_if.modem_fd[i]; |
| else |
| return ppp_modem_fd; |
| |
| } |
| |
| int get_modem_data_mode_at_fd(void) |
| { |
| int modem_fd = get_modem_data_mode_fd(); |
| int at_fd = 0; |
| |
| if (modem_fd == ppp_modem_fd) |
| at_fd = ppp_at_fd; |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| else if (modem_fd == ppp_modem_fd1) |
| at_fd = ppp_at_fd1; |
| #endif |
| #ifdef UART2_AT |
| else if (modem_fd == ppp_uart2_fd) |
| at_fd = ppp_at_fd2; |
| #endif |
| #ifdef PPP_PSEUDO_DEVICE |
| else if (modem_fd == ppp_modem_fd_pseudo) |
| at_fd = ppp_at_fd_pseudo; |
| #endif |
| else { |
| int i = 0; |
| |
| for ( i = 0; i <MAX_MUX -1; i++) { |
| if ( modem_fd == ppp_gsm_fd[i]) { |
| at_fd = ppp_gsm_fd[MAX_MUX - 1]; |
| break; |
| } |
| } |
| } |
| |
| if (at_fd == 0) |
| at_fd = ppp_at_fd; |
| |
| return at_fd; |
| } |
| |
| void set_modem_if_state(int fd, unsigned int state) |
| { |
| int i = 0; |
| |
| INFOMSG("%s: fd %d, modem_state %d", __func__, fd, state); |
| if (fd == 0) |
| { |
| for ( i = 0; i < MAX_MODEM_CHANNLE; i++) |
| modem_if.modem_state[i] = state; |
| |
| return; |
| } |
| |
| for ( i = 0; i < MAX_MODEM_CHANNLE; i++) |
| { |
| if (modem_if.modem_fd[i] == fd) |
| break; |
| } |
| |
| if (i < MAX_MODEM_CHANNLE) |
| { |
| modem_if.modem_state[i] = state; |
| INFOMSG("%s: update fd %d with modem_state %d", __func__, fd, state); |
| } |
| else |
| { |
| for ( i = 0; i < MAX_MODEM_CHANNLE; i++) |
| { |
| if (modem_if.modem_fd[i] == 0) |
| { |
| modem_if.modem_fd[i] = fd; |
| modem_if.modem_state[i] = state; |
| INFOMSG("%s: set fd %d with modem_state %d", __func__, fd, state); |
| break; |
| } |
| } |
| } |
| } |
| |
| unsigned int get_modem_if_state(int fd) |
| { |
| int i = 0; |
| |
| if (fd == 0) |
| { |
| for ( i = 0; i < MAX_MODEM_CHANNLE; i++) |
| { |
| if (modem_if.modem_state[i] == ACM_DATA_MODE) |
| break; |
| } |
| |
| goto end; |
| } |
| |
| for ( i = 0; i < MAX_MODEM_CHANNLE; i++) |
| { |
| if (modem_if.modem_fd[i] == fd) |
| break; |
| } |
| |
| end: |
| if (i < MAX_MODEM_CHANNLE) |
| return modem_if.modem_state[i]; |
| else |
| return ACM_CONTROL_MODE; |
| } |
| |
| int modem_cmux_is_data_mode(void) |
| { |
| int i = 0; |
| for (i = 0; i < MAX_MUX - 1; i ++) |
| { |
| if (get_modem_if_state(ppp_gsm_fd[i]) == ACM_DATA_MODE) |
| break; |
| } |
| |
| if (i < MAX_MUX - 1) |
| return TRUE; |
| else |
| return FALSE; |
| } |
| |
| /** |
| * Reads data from the AT channel, save in chan->at_buffer. |
| * Assumes it has exclusive read access to the FD |
| */ |
| static int read_channel(struct at_channel_struct *chan) |
| { |
| ssize_t count = 0; |
| size_t len = chan->at_buffer_tail - chan->at_buffer_head; |
| |
| if (len == 0) |
| { |
| /* empty buffer or full buffer */ |
| chan->at_buffer_head = chan->at_buffer; |
| chan->at_buffer_tail = chan->at_buffer; |
| memset(chan->at_buffer, 0, AT_CMD_BUF_SIZE); |
| } |
| else if (len > 0 && len < AT_CMD_BUF_SIZE) |
| { |
| /* there's data in the buffer from the last get_line*/ |
| memmove(chan->at_buffer, chan->at_buffer_head, len); |
| chan->at_buffer_head = chan->at_buffer; |
| chan->at_buffer_tail = chan->at_buffer_head + len; |
| memset(chan->at_buffer_tail, 0, AT_CMD_BUF_SIZE - len); |
| } |
| else |
| { |
| /* there's an at buffer pointer error */ |
| DBGMSG("at channel pointer ERROR, reset at channel!\n"); |
| chan->at_buffer_head = chan->at_buffer; |
| chan->at_buffer_tail = chan->at_buffer; |
| memset(chan->at_buffer, 0, AT_CMD_BUF_SIZE); |
| len = 0; |
| } |
| |
| do |
| { |
| DBGMSG("begin read fd=%d, bufsize=%d\n", chan->tty_fd, AT_CMD_BUF_SIZE - len); |
| count = read(chan->tty_fd, chan->at_buffer_tail , AT_CMD_BUF_SIZE - len); |
| DBGMSG("after read fd=%d, count=%d\n", chan->tty_fd, count); |
| } while (count < 0 && errno == EINTR); |
| |
| if (count > 0) { |
| INFOMSG("read_channel: receive[%d]:%s\n", count, chan->at_buffer_head); |
| } |
| |
| if (count > 0) |
| { |
| #ifdef PPP_WITHOUT_ATSRV |
| b_unlink_sent = 0; |
| /* echo the received data from modem */ |
| if (modem_if.echo_mode == MODEM_ECHO_MODE && chan == &ppp_modem) |
| writen(ppp_modem_fd, chan->at_buffer_tail, count); |
| #endif |
| chan->at_buffer_tail += count; /* relocate at_buffer_tail */ |
| } |
| else |
| { |
| #ifdef PPP_WITHOUT_ATSRV |
| if(ioctl(ppp_at_fd, IOCTL_MODEM_STATUS, NULL) != STATE_ONLINE) |
| { |
| if (get_modem_if_state(chan->tty_fd) == ACM_DATA_MODE && !b_unlink_sent) |
| { |
| INFOMSG("%s: modem crash, send linkdown\n", __func__); |
| modem_parse_atcmd((U_CHAR *)("\r\n+CSQ:99,99\r\n"), strlen("\r\n+CSQ:99,99\r\n"), FALSE); |
| b_unlink_sent = 1; |
| } |
| sleep(1); |
| } |
| #endif |
| /* read error encountered or EOF reached */ |
| if (count == 0) |
| { |
| DBGMSG("fd=%d: EOF reached", chan->tty_fd); |
| } |
| else |
| { |
| INFOMSG("fd=%d: read error %s", chan->tty_fd, strerror(errno)); |
| } |
| } |
| |
| return count; |
| } |
| |
| /** |
| * returns NULL if there is no complete line |
| */ |
| static U_CHAR *find_next_eol(U_CHAR *cur, U_CHAR *end, int smsControlCharConsider) |
| { |
| if(!smsControlCharConsider) |
| { |
| while (cur < end && *cur != '\r' && *cur != '\n') cur++; |
| } |
| else |
| { |
| /*SMS control character: control-z(0x1a), escape(0x1b)*/ |
| while (cur < end && *cur != '\r' && *cur != '\n' && *cur != 0x1a && *cur != 0x1b) cur++; |
| } |
| |
| return cur == end ? NULL : cur; |
| } |
| |
| /* get line from chan->at_buffer |
| * if not complete line in at_buffer, return NULL. |
| */ |
| static U_CHAR *get_line(struct at_channel_struct *chan, int smsControlCharConsider) |
| { |
| ssize_t count; |
| U_CHAR *p_sol = NULL; |
| U_CHAR *p_eol = NULL; |
| U_CHAR *ret = NULL; |
| |
| if (chan->at_buffer_head == chan->at_buffer_tail) return NULL; |
| |
| p_sol = chan->at_buffer_head; |
| |
| /* skip over leading newlines if it is exist */ |
| while(*p_sol == '\r' || *p_sol == '\n') |
| { |
| p_sol++; |
| } |
| |
| /* meaningless, discard */ |
| if (p_sol >= chan->at_buffer_tail) |
| { |
| chan->at_buffer_head = chan->at_buffer_tail; |
| return NULL; |
| } |
| |
| p_eol = find_next_eol(p_sol, chan->at_buffer_tail, smsControlCharConsider); |
| |
| if (p_eol) |
| { |
| /* a full line in the buffer. */ |
| ret = chan->at_buffer_head; |
| if (*(p_eol + 1) == '\n' && (p_eol + 2 <= chan->at_buffer_tail)) |
| chan->at_buffer_head = p_eol + 2; |
| else |
| chan->at_buffer_head = p_eol + 1; |
| |
| /* remove unexpected '\0'*/ |
| while (*ret == '\0' && ret < chan->at_buffer_head) |
| ret++; |
| |
| chan->cur_line_len = chan->at_buffer_head - ret; |
| } |
| return ret; |
| } |
| |
| struct ppp_cm_msg { |
| char enable; |
| char cid; |
| }; |
| |
| struct cm_ppp_msg { |
| char status; |
| }; |
| |
| static void send_msg_to_cm() |
| { |
| struct ppp_cm_msg msg; |
| msg.enable = 1; |
| msg.cid = modem_if.modem_current_cid; |
| |
| writen(ppp_cm_fd, &msg, sizeof(struct ppp_cm_msg)); |
| } |
| |
| static int handle_msg_from_cm() |
| { |
| struct cm_ppp_msg msg; |
| int len; |
| |
| len = read(ppp_cm_fd, &msg, sizeof(struct cm_ppp_msg)); |
| if (len != sizeof(struct cm_ppp_msg)) { |
| return -1; |
| } |
| return 0; |
| |
| } |
| |
| static void handle_dial(int modem_fd) |
| { |
| char value[PROPERTY_VALUE_MAX] = { '\0' }; |
| int simid = 0; |
| |
| /* get the value of ppp used cid property */ |
| property_get(PROP_PPP_CID, value, NULL); |
| if (atoi(value) > 0) /* means the last ppp have not disconnect data connection successfully */ |
| old_connected_ppp_cid = atoi(value) - 1; /* when new ppp connected, the old one should be disconnected */ |
| else |
| old_connected_ppp_cid = INVALID_CID; /* when new ppp connected, no old one should be disconnected */ |
| memset(value, 0x00, PROPERTY_VALUE_MAX); |
| /* set a property to let up layer know the ppp cid */ |
| sprintf(value, "%d", modem_if.modem_current_cid + 1); |
| property_set(PROP_PPP_CID, value); |
| |
| /*send msg to CM to tear down the ccinet first if needed*/ |
| //send_msg_cm(); |
| |
| /* reply "CONNECT" to PC, enter ACM_DATA_MODE */ |
| writen(modem_fd, "\r\nCONNECT\r\n", strlen("\r\nCONNECT\r\n")); |
| set_modem_if_state(modem_fd, ACM_DATA_MODE); |
| |
| INFOMSG(" enter ACM_DATA_MODE, cid is %u\n", modem_if.modem_current_cid); |
| modem_if.ppp_cbs.reset(); |
| modem_if.ppp_cbs.set_cid(modem_if.modem_current_cid); |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| if (modem_fd == ppp_modem_fd1) |
| simid = 1; |
| #endif |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPSIMID, simid); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPON, modem_if.modem_current_cid); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPSETCB); |
| } |
| |
| static void store_configure_params(U_CHAR *line, int len) |
| { |
| char lineBuf[AT_CMD_BUF_SIZE] = {0}; |
| int cid = 0, err = 0; |
| char *p, *apn, *ipType; |
| |
| if (len >= AT_CMD_BUF_SIZE) |
| goto end; |
| |
| memcpy(lineBuf, line, len); |
| p = lineBuf; |
| |
| err = at_start_with_tok(&p, '='); |
| if (err < 0) goto end; |
| err = at_tok_nextint(&p, &cid); |
| if (err < 0) goto end; |
| err = at_tok_nextstr(&p, &ipType); |
| if (err < 0) goto end; |
| err = at_tok_nextstr(&p, &apn); |
| if (err < 0) goto end; |
| |
| //(void)sscanf((const char *)line, "%*[^0-9]%d,\"%[^\"],\"%[^\"]", &cid, iptypePart, apnPart); |
| |
| ERRMSG("%s:cid %d, iptype %s, apn %s", __func__, cid, ipType, apn); |
| modem_if.modem_current_cid = cid -1; |
| if (strlen(apn) > 0) |
| strncpy(modem_if.pdp_params.apn, apn, sizeof(modem_if.pdp_params.apn) -1); |
| |
| if (strcasecmp(ipType,"IPV4V6") == 0) |
| modem_if.pdp_params.ip_type = 3; |
| else if (strcasecmp(ipType,"IPV6") == 0) |
| modem_if.pdp_params.ip_type = 2; |
| else if (strcasecmp(ipType,"IP") == 0) |
| modem_if.pdp_params.ip_type = 1; |
| |
| end: |
| return; |
| } |
| |
| static void store_auth_params(U_CHAR *line, int len UNUSED) |
| { |
| char usrPart[AT_CMD_BUF_SIZE] = {0}; |
| char pswdPart[AT_CMD_BUF_SIZE] = {0}; |
| int cid, type = 0; |
| (void)sscanf((const char *)line, "%*[^0-9]%d,%d%*[^\n]", &cid, &type); |
| if (type > 0) |
| (void)sscanf((const char *)line, "%*[^0-9]%d,%d,%[^,],%[^\n]", &cid, &type, usrPart, pswdPart); |
| |
| /*delete '\r' if needed*/ |
| if (pswdPart[strlen(pswdPart) - 1] == '\r') |
| pswdPart[strlen(pswdPart) - 1] =='\0'; |
| |
| ERRMSG("%s:cid %d, authType %d",__func__, cid, type); |
| if (type > 0) |
| ERRMSG("%s:username %s, password %s",__func__, usrPart, pswdPart); |
| |
| |
| if (modem_if.modem_current_cid != cid -1) |
| { |
| ERRMSG("%s: auth cid[%d] NOT for current cid[%d]",__func__, cid -1, modem_if.modem_current_cid); |
| return; |
| } |
| |
| modem_if.pdp_params.auth_type = type; |
| strncpy(modem_if.pdp_params.username, usrPart, 63); |
| if (type > 0) |
| { |
| strncpy(modem_if.pdp_params.username, usrPart, 63); |
| strncpy(modem_if.pdp_params.password, pswdPart, 63); |
| } |
| else |
| { |
| memset(modem_if.pdp_params.username, 0, 64); |
| memset(modem_if.pdp_params.password, 0, 64); |
| } |
| } |
| |
| static void store_configure_cid(U_CHAR *line, int len UNUSED) |
| { |
| char forepart[AT_CMD_BUF_SIZE] = {0}; |
| char rearpart[AT_CMD_BUF_SIZE] = {0}; |
| int cid = 0; |
| (void)sscanf((const char *)line, "%[^0-9]%d%[^\n]", forepart, &cid, rearpart); |
| modem_if.modem_current_cid = cid - 1; |
| } |
| |
| int open_serial_device(Serial* serial, int baud) |
| { |
| unsigned int i; |
| struct termios newtio; |
| |
| /* open the serial port */ |
| if(0 > serial->fd){ |
| open_port(&serial->fd, serial->devicename, O_RDWR | O_NOCTTY | O_NDELAY, 1); |
| } |
| |
| tcgetattr(serial->fd, &newtio); |
| speed_t speed = baud_bits[baud]; |
| cfsetispeed(&newtio, speed); |
| cfsetospeed(&newtio, speed); |
| tcflush(serial->fd, TCIFLUSH); |
| tcsetattr(serial->fd, TCSANOW, &newtio); |
| |
| usleep(1000*100); |
| return 0; |
| } |
| |
| int start_muxer(Serial* serial) |
| { |
| struct gsm_config c; |
| int ldisc = N_GSM0710; |
| |
| /* use n_gsm line discipline */ |
| ioctl(serial->fd, TIOCSETD, &ldisc); |
| |
| /* get n_gsm configuration */ |
| ioctl(serial->fd, GSMIOC_GETCONF, &c); |
| /* we are initiator and need encoding 0 (basic) */ |
| c.initiator = 1; |
| c.encapsulation = serial->cmux_mode; |
| /* our modem defaults to a maximum size of 127 bytes */ |
| c.mru = 127; |
| c.mtu = 127; |
| /* set the new configuration */ |
| ioctl(serial->fd, GSMIOC_SETCONF, &c); |
| |
| usleep(1000*1000); |
| return 0; |
| } |
| |
| static int cmux_process(Serial * serial) |
| { |
| const char dev[128] = {0}; |
| int i; |
| |
| if (open_serial_device(serial, serial->baud) != 0) { //first use default settings to open serial |
| return 1; |
| } |
| |
| if (start_muxer(serial) < 0) { |
| return 1; |
| } |
| |
| for(i=1; i<MAX_MUX; i++){ |
| sprintf(dev, "/dev/gsmtty%d", i); |
| open_port(&ppp_gsm_fd[i-1], dev, O_RDWR | O_NOCTTY | O_NDELAY, 1); |
| } |
| |
| #ifdef PPP_WITHOUT_ATSRV |
| open_port(&ppp_gsm_fd[i-1], CMUX_GSM4_DEVICE, O_RDWR, 1); |
| #else |
| ppp_gsm_fd[i-1] = open_socket(CMUX_GSM4_SOCKET); |
| #endif |
| |
| /* init channel */ |
| for(i=0; i<MAX_MUX; i++){ |
| init_channel_struct(&ppp_gsm[i], ppp_gsm_fd[i], i); |
| } |
| |
| pxa_dbg("Starting multiplexing\r\n"); |
| return 0; |
| } |
| |
| static int cmux_set(int fd, int mode, int baud) |
| { |
| serial.cmux_mode = mode; |
| serial.baud = baud; |
| serial.fd = fd; |
| serial.devicename = MODEM_TERM_DEVICE; |
| |
| cmux_process(&serial); |
| return 0; |
| } |
| |
| static int cmux_off(void) |
| { |
| const char dev[128] = {0}; |
| int i; |
| int ldisc = N_TTY; |
| |
| pxa_dbg("Ending multiplexing\r\n"); |
| |
| /* collect resources */ |
| for(i=0; i<MAX_MUX; i++){ |
| tcflush(ppp_gsm_fd[i], TCIOFLUSH); |
| close(ppp_gsm_fd[i]); |
| memset(&ppp_gsm[i], 0x00, sizeof(struct at_channel_struct)); |
| } |
| |
| /* use n_tty line discipline */ |
| ioctl(serial.fd, TIOCSETD, &ldisc); |
| serial.fd = -1; |
| |
| return 0; |
| } |
| |
| void configure_ppp_cid(int cid) |
| { |
| modem_if.modem_current_cid = (unsigned char)cid; |
| } |
| |
| int ppp_parse_profile_id(char *dial_string) |
| { |
| int id = 0; |
| char *start = NULL, *end = NULL; |
| |
| start = strstr(dial_string, "***"); |
| if (start) { |
| end = strchr(start, '#'); |
| if (end) { |
| end--; |
| if (*end >= '0' && *end <= '9') |
| id = *end - 0x30; |
| } |
| } |
| |
| return id; |
| } |
| |
| bool is_ppp_dial_string(char *line) |
| { |
| if((strncasecmp((char const *)line, "ATDT*99***", strlen("ATDT*99***")) == 0) || |
| (strncasecmp((char const *)line, "ATDT*98***", strlen("ATDT*98***")) == 0) || |
| (strncasecmp((char const *)line, "ATD*99***", strlen("ATD*99***")) == 0) || |
| (strncasecmp((char const *)line, "ATD#777", strlen("ATD#777")) == 0) || |
| (strncasecmp((char const *)line, "ATD*99#", strlen("ATD*99#")) == 0) || |
| (strncasecmp((char const *)line, "ATDT*99#", strlen("ATDT*99#")) == 0)) |
| return true; |
| else |
| return false; |
| } |
| |
| void ppp_send_at_rsp_2host(char *at_rsp) |
| { |
| char rsp[128] = { 0 }; |
| int size = 0; |
| |
| size = snprintf(rsp, 127, "\r\n%s\r\n", at_rsp); |
| writen(ppp_modem_fd, rsp, size); |
| } |
| |
| void ppp_ioctl_set_ipv6_addr(int type) |
| { |
| ip6_addr_t ppp_v6_addr; |
| |
| if (type == 0) |
| memcpy(&ppp_v6_addr, ppp_get_ipv6_addr(), sizeof(ip6_addr_t)); |
| else |
| memcpy(&ppp_v6_addr, ppp_get_ipv6_global_unicast(), sizeof(ip6_addr_t)); |
| |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPSETV6ADDR, &ppp_v6_addr); |
| |
| ip6_addr_debug_print("ppp_ioctl_set_ipv6_addr: ppp ipv6", &ppp_v6_addr); |
| } |
| |
| void ppp_ipcpv6_done(void) |
| { |
| ppp_ioctl_set_ipv6_addr(0); |
| |
| /*send RS to network*/ |
| ppp_ndisc_send_rs(); |
| ERRMSG("%s: done", __func__); |
| } |
| |
| void ppp_ipv6_receive_ra_done(void) |
| { |
| ppp_ioctl_set_ipv6_addr(1); |
| ERRMSG("%s: done", __func__); |
| } |
| |
| #ifdef MODEM_AT_STATISTICS |
| void write_at_stat_2file(char *file_path, struct modem_at_statistics *statistics) |
| { |
| FILE *fp = NULL; |
| fp = fopen(file_path, "w"); |
| if (!fp) |
| return; |
| |
| fprintf(fp, "IN:%d,%d OUT:%d,%d\n", statistics->cmd_count, statistics->cmd_byte, statistics->rsp_count, statistics->rsp_byte); |
| fclose(fp); |
| } |
| #endif |
| |
| bool wait_for_crlf = FALSE; |
| int wait_for_crlf_ticks = 100; |
| |
| static utlTimerId_T wait_crlf_timer = 0; |
| static utlRelativeTime_T wait_crlf_timeout = { 0, 100000 }; |
| int last_received_ticks, current_ticks; |
| |
| static unsigned long get_system_clock_msec(void) |
| { |
| struct timespec ts; |
| |
| clock_gettime(CLOCK_MONOTONIC, &ts); |
| |
| return (ts.tv_sec * 1000 + ts.tv_nsec/1000000); |
| } |
| |
| static utlReturnCode_T wait_for_crlf_timer_cb(const utlTimerId_T id, |
| const unsigned long timeout_count, |
| void *arg_p, |
| const utlAbsoluteTime_P2c curr_time_p) |
| { |
| UNUSEDPARAM(id) |
| UNUSEDPARAM(timeout_count) |
| UNUSEDPARAM(curr_time_p) |
| |
| int modem_fd = *(int *)arg_p; |
| if (wait_for_crlf == true) |
| { |
| wait_for_crlf = false; |
| INFOMSG("%s: +++CR received, fallback to ACM_CONTROL_MODE\n", __func__); |
| |
| set_modem_if_state(modem_fd, ACM_CONTROL_MODE); |
| //modem_if.modem_current_cid = INVALID_CID; |
| modem_if.ppp_cbs.reset(); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| ath_data = true; |
| } |
| |
| INFOMSG("%s: done\n", __func__); |
| return(utlSUCCESS); |
| } |
| |
| static int ppp_check_control_mode_streams(int modem_fd, char *packet_buffer, int received) |
| { |
| static char switch_buffer[4] = { 0 }; |
| |
| if (received == 1) |
| { |
| if (wait_for_crlf) |
| { |
| INFOMSG("%s: data %x received after +++ in ticks(%d)\n", __func__, packet_buffer[0], wait_for_crlf_ticks); |
| if(wait_crlf_timer != 0) |
| { |
| utlStopTimer(wait_crlf_timer); |
| wait_crlf_timer = 0; |
| } |
| wait_for_crlf = FALSE; |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| last_received_ticks = get_system_clock_msec(); |
| } |
| |
| if (packet_buffer[0] == '+') |
| { |
| if (strlen(switch_buffer) == 0) |
| current_ticks = get_system_clock_msec(); |
| |
| if (strlen(switch_buffer) >=1) |
| { |
| /* after first '+' longer than 1s */ |
| if (get_system_clock_msec() - current_ticks > 1000) |
| { |
| INFOMSG("%s: the + after first + longer than 1s\n", __func__); |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| last_received_ticks = current_ticks; |
| current_ticks = get_system_clock_msec(); |
| } |
| } |
| |
| if (strlen(switch_buffer) >= 2) |
| { |
| INFOMSG("%s: +++ received, current ticks %d last_received_ticks %d\n", __func__, current_ticks, last_received_ticks); |
| if (current_ticks - last_received_ticks > wait_for_crlf_ticks) |
| { |
| wait_for_crlf = true; |
| if (wait_crlf_timer == 0) |
| wait_crlf_timer = utlStartTimer(&wait_crlf_timeout, 1, &wait_for_crlf_timer_cb, (void *)&modem_fd); |
| } |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| last_received_ticks = get_system_clock_msec(); |
| } |
| else |
| switch_buffer[strlen(switch_buffer)] = '+'; |
| } |
| else |
| { |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| last_received_ticks = get_system_clock_msec(); |
| } |
| } |
| else |
| { |
| if (received == 2 && packet_buffer[0] == '+' && packet_buffer[1] == '+' ) |
| { |
| if (strlen(switch_buffer) == 1) |
| { |
| /*+, ++ received*/ |
| INFOMSG("%s: +,++ received, current ticks %d last_received_ticks %d\n", __func__, current_ticks, last_received_ticks); |
| /* after first '+' longer than 1s */ |
| if (get_system_clock_msec() - current_ticks > 1000) |
| { |
| INFOMSG("%s: the + after first + longer than 1s\n", __func__); |
| memset(switch_buffer, '+', 2); |
| last_received_ticks = current_ticks; |
| current_ticks = get_system_clock_msec(); |
| } |
| else |
| { |
| if (current_ticks - last_received_ticks > wait_for_crlf_ticks) |
| { |
| wait_for_crlf = true; |
| if (wait_crlf_timer == 0) |
| wait_crlf_timer = utlStartTimer(&wait_crlf_timeout, 1, &wait_for_crlf_timer_cb, (void *)&modem_fd); |
| } |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| } |
| } |
| else if (strlen(switch_buffer) == 0) |
| { |
| /*++ received*/ |
| memset(switch_buffer, '+', 2); |
| current_ticks = get_system_clock_msec(); |
| } |
| else |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| } |
| else |
| memset(switch_buffer, 0, sizeof(switch_buffer)); |
| } |
| |
| /*check if the packet is ''+++"*/ |
| if ((strlen(packet_buffer) == 3) && (strncasecmp(packet_buffer, "+++", strlen("+++")) == 0)) |
| { |
| current_ticks = get_system_clock_msec(); |
| if (current_ticks - last_received_ticks > wait_for_crlf_ticks) |
| { |
| INFOMSG("%s: only +++ received\n", __func__); |
| return true; |
| } |
| } |
| |
| if (received > 1 && strlen(switch_buffer) != 2) |
| last_received_ticks = get_system_clock_msec(); |
| |
| return false; |
| } |
| |
| void ppp_modem_receive_error(int mode, int received) |
| { |
| int modem_state = 0; |
| int count = 0; |
| |
| modem_state = get_modem_state(); |
| INFOMSG("mode [%d], ppp_modem_fd[%d], received[%d], modemState[%d],read error[%d] %s", mode, ppp_modem_fd, received, modem_state, errno, strerror(errno)); |
| if (modem_state == 0) { |
| if (ppp_modem_fd > 0) { |
| if (close(ppp_modem_fd) < 0) |
| INFOMSG("ppp_modem_fd close failed\r\n"); |
| |
| ppp_modem_fd = 0; |
| } |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| if (ppp_modem_fd1 > 0) |
| { |
| if (close(ppp_modem_fd1) < 0 ) |
| INFOMSG("ppp_modem_fd1 close failed\r\n"); |
| |
| ppp_modem_fd1 = 0; |
| } |
| #endif |
| INFOMSG("ppp_modem_fd recv error! may be closed!\r\n"); |
| } |
| else { |
| if (ENOENT == errno || EIO == errno) { |
| if (ppp_modem_fd > 0) { |
| if (close(ppp_modem_fd) < 0) |
| INFOMSG("ppp_modem_fd close failed\r\n"); |
| |
| ppp_modem_fd = 0; |
| } |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| if (ppp_modem_fd1 > 0) { |
| if (close(ppp_modem_fd1) < 0 ) |
| INFOMSG("ppp_modem_fd1 close failed\r\n"); |
| |
| ppp_modem_fd1 = 0; |
| } |
| #endif |
| INFOMSG("error happend with usb connected, will re-open port\r\n"); |
| while (count < 5) { |
| sleep(1); |
| open_port(&ppp_modem_fd, MODEM_TERM_DEVICE, O_RDWR, 1); |
| if (ppp_modem_fd) |
| break; |
| } |
| if (count == 5) |
| { |
| INFOMSG(" re-open port failed\r\n"); |
| } |
| } |
| } |
| } |
| |
| int modem_cmux_router(void) |
| { |
| int received; |
| U_CHAR *line = NULL; |
| U_CHAR packet_buffer[PPP_FRAME_SIZE] = { '\0' }; |
| int fdcount; |
| int nfds; |
| fd_set fds; |
| int i, cid; |
| |
| for(i=0; i<MAX_MUX; i++){ |
| FD_SET(ppp_gsm_fd[i], &fds); |
| if(ppp_gsm_fd[i] > nfds) |
| nfds = ppp_gsm_fd[i]; |
| } |
| |
| fdcount = select(nfds + 1, &fds, NULL, NULL, NULL); |
| if(fdcount < 0) /* error */ |
| { |
| INFOMSG("select returned %d, errno %d, continue\r\n", fdcount, errno); |
| return 1;; |
| } |
| |
| for(i=0; i<MAX_MUX-1; i++){ |
| if(FD_ISSET(ppp_gsm_fd[i], &fds)) |
| { /* handler packet message from terminal */ |
| FD_CLR(ppp_gsm_fd[i], &fds); |
| if (get_modem_if_state(ppp_gsm_fd[i]) == ACM_CONTROL_MODE) /* relay atcmd to ATCMDSRV: ppp_at_fd */ |
| { |
| received = read_channel(&ppp_gsm[i]); |
| if(received > 0) |
| { |
| while (1) |
| { |
| line = get_line(&ppp_gsm[i], 1); |
| if (line == NULL) break; |
| |
| dbg_dump_string("AT COMMAND (string), ppp_gsm modem_router\r\n", (char *)line, ppp_gsm[i].cur_line_len); |
| dbg_dump_buffer("AT COMMAND (buffer), ppp_gsm modem_router\r\n", (char *)line, ppp_gsm[i].cur_line_len); |
| |
| if(is_ppp_dial_string(line)) { |
| cid = ppp_parse_profile_id(line); |
| if (cid) |
| configure_ppp_cid(cid -1); |
| |
| handle_dial(ppp_gsm_fd[i]); |
| return 1; |
| } |
| |
| if (strncasecmp((const char *)line, "ATH", sizeof("ATH") - 1) == 0 && ath_data) { |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_gsm_fd[i], RESP_OK, sizeof(RESP_OK) - 1); |
| ath_data = false; |
| return 1; |
| } |
| |
| if(strncasecmp((char const *)line, "ATE0", strlen("ATE0")) == 0) |
| modem_if.echo_mode = MODEM_NORMAL_MODE; |
| |
| if(strncasecmp((char const *)line, "ATE1", strlen("ATE1")) == 0) |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| |
| if(strncasecmp((char const *)line, "AT+CGDCONT=", strlen("AT+CGDCONT=")) == 0) { |
| store_configure_params(line, ppp_gsm[i].cur_line_len); |
| } |
| |
| if(strncasecmp((char const *)line, "ATO", strlen("ATO")) == 0 && ato_data) { |
| writen(ppp_gsm_fd[i], "\r\nOK\r\n", strlen("\r\nOK\r\n")); |
| set_modem_if_state(ppp_gsm_fd[i], ACM_DATA_MODE); |
| ato_data = false; |
| } |
| |
| if(strncasecmp((char const *)line, "AT@POFF", strlen("AT@POFF")) == 0) { |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_gsm_fd[i], RESP_OK, sizeof(RESP_OK) - 1); |
| cmux_off(); |
| return 0; |
| }else{ |
| /* relay atcmd to ATCMDSRV */ |
| pthread_mutex_lock(&channelid_lock); |
| ppp_gsm[3].id = i; |
| writen(ppp_gsm_fd[3], line, ppp_gsm[i].cur_line_len); |
| pthread_mutex_unlock(&channelid_lock); |
| } |
| } |
| } |
| } |
| else if (get_modem_if_state(ppp_gsm_fd[i]) == ACM_DATA_MODE) |
| { |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppp_gsm_fd[i], packet_buffer, PPP_FRAME_SIZE); |
| if(received > 0) |
| { |
| /* check if the packet is "+++", which is the signal to enter ACM_CONTROL_MODE */ |
| if( ppp_check_control_mode_streams(ppp_gsm_fd[i], packet_buffer, received) && |
| strncasecmp((char const *)packet_buffer, "+++", strlen("+++")) == 0) |
| { |
| set_modem_if_state(ppp_gsm_fd[i], ACM_CONTROL_MODE); |
| //modem_if.modem_current_cid = INVALID_CID; |
| modem_if.ppp_cbs.reset(); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| ath_data = true; |
| ato_data = true; |
| } |
| else |
| modem_if.ppp_cbs.rx_modem(packet_buffer, received); |
| } |
| } |
| } |
| } |
| if(FD_ISSET(ppp_gsm_fd[MAX_MUX-1], &fds)) |
| { /* received AT response */ |
| FD_CLR(ppp_gsm_fd[MAX_MUX-1], &fds); |
| received = read_channel(&ppp_gsm[MAX_MUX-1]); |
| if(received > 0) |
| { |
| U_CHAR *p_sol = NULL; |
| int cur_count = 0; |
| p_sol = ppp_gsm[MAX_MUX-1].at_buffer_head; |
| while (1) |
| { |
| line = get_line(&ppp_gsm[MAX_MUX-1], 0); |
| if (line == NULL) break; |
| dbg_dump_string("AT RESPONSE (string), modem_router\r\n", (char *)line, ppp_gsm[MAX_MUX-1].cur_line_len); |
| dbg_dump_buffer("AT RESPONSE (buffer), modem_router\r\n", (char *)line, ppp_gsm[MAX_MUX-1].cur_line_len); |
| cur_count += ppp_gsm[MAX_MUX-1].cur_line_len; |
| |
| if (modem_cmux_is_data_mode()) |
| modem_parse_atcmd(line, ppp_gsm[MAX_MUX-1].cur_line_len, FALSE); |
| } |
| |
| if (!modem_cmux_is_data_mode() && cur_count > 0) { |
| pthread_mutex_lock(&channelid_lock); |
| writen(ppp_gsm_fd[ppp_gsm[MAX_MUX-1].id], p_sol, cur_count); |
| pthread_mutex_unlock(&channelid_lock); |
| dbg_dump_string("AT RESPONSE (string) Write to UART, modem_router\r\n", (char *)p_sol, cur_count); |
| } |
| } |
| } |
| |
| return 1; |
| } |
| |
| /* router thread */ |
| void modem_router(void) |
| { |
| int received; |
| U_CHAR *line = NULL; |
| U_CHAR packet_buffer[PPP_FRAME_SIZE] = { '\0' }; |
| |
| int fdcount; |
| fd_set fds; |
| int nfds, cid; |
| int cmux_flag = 0; |
| int modem_state = 0; |
| |
| pthread_detach(pthread_self()); |
| //TODO: need to allow pthread_setname_np for openwrt |
| //pthread_setname_np(pthread_self(), "PPP_ROUTER"); |
| prctl(PR_SET_NAME, "PPP_ROUTER"); |
| |
| while(1) |
| { |
| nfds = 0; |
| FD_ZERO(&fds); |
| |
| FD_SET(pipefd[0], &fds); |
| if(pipefd[0] > nfds) |
| nfds = pipefd[0]; |
| |
| FD_SET(ppp_at_fd, &fds); |
| if(ppp_at_fd > nfds) |
| nfds = ppp_at_fd; |
| |
| if(ppp_modem_fd > 0){ |
| FD_SET(ppp_modem_fd, &fds); |
| if(ppp_modem_fd > nfds) |
| nfds = ppp_modem_fd; |
| } |
| |
| |
| FD_SET(ppprd_fd, &fds); |
| if(ppprd_fd > nfds) |
| nfds = ppprd_fd; |
| |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| FD_SET(ppp_at_fd1, &fds); |
| if(ppp_at_fd1 > nfds) |
| nfds = ppp_at_fd1; |
| |
| if (ppp_modem_fd1 > 0) { |
| FD_SET(ppp_modem_fd1, &fds); |
| if(ppp_modem_fd1 > nfds) |
| nfds = ppp_modem_fd1; |
| } |
| #endif |
| #ifdef UART2_AT |
| FD_SET(ppp_at_fd2, &fds); |
| if(ppp_at_fd2 > nfds) |
| nfds = ppp_at_fd2; |
| |
| FD_SET(ppp_uart2_fd, &fds); |
| if(ppp_uart2_fd > nfds) |
| nfds = ppp_uart2_fd; |
| #endif |
| #ifdef PPP_PSEUDO_DEVICE |
| FD_SET(ppp_at_fd_pseudo, &fds); |
| if(ppp_at_fd_pseudo > nfds) |
| nfds = ppp_at_fd_pseudo; |
| |
| FD_SET(ppp_modem_fd_pseudo, &fds); |
| if(ppp_modem_fd_pseudo > nfds) |
| nfds = ppp_modem_fd_pseudo; |
| #endif |
| if(cmux_flag) |
| { |
| cmux_flag = modem_cmux_router(); |
| }else{ |
| fdcount = select(nfds + 1, &fds, NULL, NULL, NULL); |
| if(fdcount < 0) /* error */ |
| { |
| INFOMSG("select returned %d, errno %d, continue\r\n", fdcount, errno); |
| sleep(1); |
| continue; |
| } |
| |
| if(FD_ISSET(ppp_at_fd, &fds)) |
| { /* received AT response */ |
| FD_CLR(ppp_at_fd, &fds); |
| received = read_channel(&ppp_at); |
| if(received > 0) |
| { |
| U_CHAR *p_sol = NULL; |
| int cur_count = 0; |
| p_sol = ppp_at.at_buffer_head; |
| while (1) |
| { |
| line = get_line(&ppp_at, 0); |
| if (line == NULL) break; |
| dbg_dump_string("AT RESPONSE (string), modem_router\r\n", (char *)line, ppp_at.cur_line_len); |
| dbg_dump_buffer("AT RESPONSE (buffer), modem_router\r\n", (char *)line, ppp_at.cur_line_len); |
| cur_count += ppp_at.cur_line_len; |
| |
| if (get_modem_if_state(ppp_modem_fd) == ACM_DATA_MODE) |
| modem_parse_atcmd(line, ppp_at.cur_line_len, FALSE); |
| } |
| |
| if(get_modem_if_state(ppp_modem_fd) == ACM_CONTROL_MODE && cur_count > 0) { |
| if(ppp_modem_fd>0){ |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.rsp_count++; |
| at_statistics.rsp_byte += cur_count; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| |
| writen(ppp_modem_fd, p_sol, cur_count); |
| dbg_dump_string("AT RESPONSE (string) Write to UART, modem_router\r\n", (char *)p_sol, cur_count); |
| } |
| } |
| } |
| } |
| if(FD_ISSET(ppp_modem_fd, &fds)) |
| { /* handler packet message from terminal */ |
| FD_CLR(ppp_modem_fd, &fds); |
| if (get_modem_if_state(ppp_modem_fd) == ACM_CONTROL_MODE) |
| { |
| received = read_channel(&ppp_modem); |
| if(received > 0) |
| { |
| while (1) |
| { |
| line = get_line(&ppp_modem, 1); |
| if (line == NULL) break; |
| |
| dbg_dump_string("AT COMMAND (string), modem_router\r\n", (char *)line, ppp_modem.cur_line_len); |
| dbg_dump_buffer("AT COMMAND (buffer), modem_router\r\n", (char *)line, ppp_modem.cur_line_len); |
| |
| if(is_ppp_dial_string(line)) { |
| cid = ppp_parse_profile_id(line); |
| if (cid) |
| configure_ppp_cid(cid -1); |
| |
| handle_dial(ppp_modem_fd); |
| continue; |
| } |
| |
| if (strncasecmp((const char *)line, "ATH", sizeof("ATH") - 1) == 0 && ath_data) { |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_modem_fd, RESP_OK, sizeof(RESP_OK) - 1); |
| ath_data = false; |
| continue; |
| } |
| |
| if(strncasecmp((char const *)line, "ATE0", strlen("ATE0")) == 0) |
| modem_if.echo_mode = MODEM_NORMAL_MODE; |
| |
| if(strncasecmp((char const *)line, "ATE1", strlen("ATE1")) == 0) |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| |
| if(strncasecmp((char const *)line, "AT+CGDCONT=", strlen("AT+CGDCONT=")) == 0) { |
| store_configure_params(line, ppp_modem.cur_line_len); |
| } |
| |
| if(strncasecmp((char const *)line, "ATO", strlen("ATO")) == 0 && ato_data) { |
| writen(ppp_modem_fd, "\r\nOK\r\n", strlen("\r\nOK\r\n")); |
| set_modem_if_state(ppp_modem_fd, ACM_DATA_MODE); |
| ato_data = false; |
| } |
| #if 0 |
| if(strncasecmp((char const *)line, "AT+CGDCONT?", strlen("AT+CGDCONT?")) == 0) |
| modem_if.get_ip = TRUE; |
| |
| if(strncasecmp((char const *)line, "AT+CGCONTRDP", strlen("AT+CGCONTRDP")) == 0) |
| modem_if.get_ip = TRUE; |
| #endif |
| if(strncasecmp((char const *)line, "AT+CMUX=", strlen("AT+CMUX=")) == 0) { |
| int mode; |
| int baud; |
| (void)sscanf((const char *)line, "%*[^0-9]%d,%d", &mode, &baud); |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_modem_fd, RESP_OK, sizeof(RESP_OK) - 1); |
| cmux_set(ppp_modem_fd, mode, baud); |
| cmux_flag = 1; |
| } else { |
| /* relay atcmd to ATCMDSRV */ |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.cmd_count++; |
| at_statistics.cmd_byte += ppp_modem.cur_line_len; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_at_fd, line, ppp_modem.cur_line_len); |
| } |
| } |
| } |
| else |
| ppp_modem_receive_error(ACM_CONTROL_MODE, received); |
| } |
| else if (get_modem_if_state(ppp_modem_fd) == ACM_DATA_MODE) |
| { |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppp_modem_fd, packet_buffer, PPP_FRAME_SIZE); |
| if(received > 0) |
| { |
| /* check if the packet is "+++", which is the signal to enter ACM_CONTROL_MODE */ |
| if( ppp_check_control_mode_streams(ppp_modem_fd, packet_buffer, received) && |
| strncasecmp((char const *)packet_buffer, "+++", strlen("+++")) == 0) |
| { |
| set_modem_if_state(ppp_modem_fd, ACM_CONTROL_MODE); |
| //modem_if.modem_current_cid = INVALID_CID; |
| INFOMSG(" Fallback to ACM_CONTROL_MODE, modem_current_cid is 0xFF\n"); |
| modem_if.ppp_cbs.reset(); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| ath_data = true; |
| ato_data = true; |
| } |
| else |
| modem_if.ppp_cbs.rx_modem(packet_buffer, received); |
| } |
| else |
| ppp_modem_receive_error(ACM_DATA_MODE, received); |
| } |
| } |
| if(FD_ISSET(ppprd_fd, &fds)) |
| { /* received IP packet from CP through ppp router driver */ |
| FD_CLR(ppprd_fd, &fds); |
| if (get_modem_if_state(0) == ACM_DATA_MODE) |
| { |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppprd_fd, packet_buffer, PPP_FRAME_SIZE); |
| ERRMSG("[<<<] ppprd port %d received: %d bytes data\n", ppprd_fd, received); |
| |
| modem_if.ppp_cbs.rx_comm(packet_buffer, received); |
| }else{ |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppprd_fd, packet_buffer, PPP_FRAME_SIZE); |
| ERRMSG(" ppprd port %d received: %d bytes data\n", ppprd_fd, received); |
| ERRMSG(" ppprd_fd modem_state not ACM_DATA_MODE,clean the data\n"); |
| } |
| } |
| if(FD_ISSET(pipefd[0], &fds)) |
| { /* received terminate message */ |
| FD_CLR(pipefd[0], &fds); |
| |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(pipefd[0], packet_buffer, PPP_FRAME_SIZE); |
| ERRMSG(" received pipefd[%d] message[%s]\n",received,packet_buffer); |
| |
| if(!strcmp(packet_buffer, "term")){ |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ERRMSG(" reset PPPRD_IOCTL_TIOPPPRESETCB, loop again\n"); |
| }else if(!strcmp(packet_buffer, "start")){ |
| ERRMSG("[start]loop again to set ppp_modem_fd %d\n", ppp_modem_fd); |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| ERRMSG("[start]ppp_modem_fd1 %d\n", ppp_modem_fd1); |
| #endif |
| } |
| #ifdef TERMINATE_ALL_RESOURCES |
| break; |
| #else |
| continue; |
| #endif |
| } |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| if(FD_ISSET(ppp_at_fd1, &fds)) |
| { /* received AT response */ |
| FD_CLR(ppp_at_fd1, &fds); |
| received = read_channel(&ppp_at1); |
| if(received > 0) |
| { |
| U_CHAR *p_sol = NULL; |
| int cur_count = 0; |
| p_sol = ppp_at1.at_buffer_head; |
| while (1) |
| { |
| line = get_line(&ppp_at1, 0); |
| if (line == NULL) break; |
| |
| dbg_dump_string("AT RESPONSE1 (string), modem_router\r\n", (char *)line, ppp_at1.cur_line_len); |
| dbg_dump_buffer("AT RESPONSE1 (buffer), modem_router\r\n", (char *)line, ppp_at1.cur_line_len); |
| cur_count += ppp_at1.cur_line_len; |
| |
| if (get_modem_if_state(ppp_modem_fd1) == ACM_DATA_MODE) |
| modem_parse_atcmd(line, ppp_at1.cur_line_len, FALSE); |
| } |
| |
| if (get_modem_if_state(ppp_modem_fd1) == ACM_CONTROL_MODE && cur_count > 0) { |
| if(ppp_modem_fd1>0){ |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.rsp_count++; |
| at_statistics.rsp_byte += cur_count; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_modem_fd1, p_sol, cur_count); |
| dbg_dump_string("AT RESPONSE1 (string) Write to UART, modem_router\r\n", (char *)p_sol, cur_count); |
| |
| } |
| } |
| } |
| } |
| if(FD_ISSET(ppp_modem_fd1, &fds)) |
| { /* handler packet message from terminal */ |
| FD_CLR(ppp_modem_fd1, &fds); |
| if (get_modem_if_state(ppp_modem_fd1) == ACM_CONTROL_MODE) |
| { |
| received = read_channel(&ppp_modem1); |
| if(received > 0) |
| { |
| while (1) |
| { |
| line = get_line(&ppp_modem1, 1); |
| if (line == NULL) break; |
| |
| dbg_dump_string("AT COMMAND1 (string), modem_router\r\n", (char *)line, ppp_modem1.cur_line_len); |
| dbg_dump_buffer("AT COMMAND1 (buffer), modem_router\r\n", (char *)line, ppp_modem1.cur_line_len); |
| |
| if(is_ppp_dial_string(line)) { |
| cid = ppp_parse_profile_id(line); |
| if (cid) |
| configure_ppp_cid(cid -1); |
| |
| handle_dial(ppp_modem_fd1); |
| continue; |
| } |
| |
| if (strncasecmp((const char *)line, "ATH", sizeof("ATH") - 1) == 0 && ath_data) { |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_modem_fd1, RESP_OK, sizeof(RESP_OK) - 1); |
| ath_data = false; |
| continue; |
| } |
| |
| if(strncasecmp((char const *)line, "ATE0", strlen("ATE0")) == 0) |
| modem_if.echo_mode = MODEM_NORMAL_MODE; |
| |
| if(strncasecmp((char const *)line, "ATE1", strlen("ATE1")) == 0) |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| |
| if(strncasecmp((char const *)line, "AT+CGDCONT=", strlen("AT+CGDCONT=")) == 0) { |
| store_configure_params(line, ppp_modem1.cur_line_len); |
| } |
| |
| if(strncasecmp((char const *)line, "ATO", strlen("ATO")) == 0 && ato_data) { |
| writen(ppp_modem_fd, "\r\nOK\r\n", strlen("\r\nOK\r\n")); |
| set_modem_if_state(ppp_modem_fd, ACM_DATA_MODE); |
| ato_data = false; |
| } |
| if(strncasecmp((char const *)line, "AT+CMUX=", strlen("AT+CMUX=")) == 0) { |
| int mode; |
| int baud; |
| (void)sscanf((const char *)line, "%*[^0-9]%d,%d", &mode, &baud); |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_modem_fd1, RESP_OK, sizeof(RESP_OK) - 1); |
| cmux_set(ppp_modem_fd1, mode, baud); |
| cmux_flag = 1; |
| } else { |
| /* relay atcmd to ATCMDSRV */ |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.cmd_count++; |
| at_statistics.cmd_byte += ppp_modem1.cur_line_len; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_at_fd1, line, ppp_modem1.cur_line_len); |
| } |
| } |
| } |
| else |
| ppp_modem_receive_error(ACM_CONTROL_MODE, received); |
| } |
| else if(get_modem_if_state(ppp_modem_fd1) == ACM_DATA_MODE) /* relay packet to PPP server: message_queue */ |
| { |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppp_modem_fd1, packet_buffer, PPP_FRAME_SIZE); |
| if(received > 0) |
| { |
| /* check if the packet is "+++", which is the signal to enter ACM_CONTROL_MODE */ |
| if( ppp_check_control_mode_streams(ppp_modem_fd1, packet_buffer, received) && |
| strncasecmp((char const *)packet_buffer, "+++", strlen("+++")) == 0) |
| { |
| set_modem_if_state(ppp_modem_fd1, ACM_CONTROL_MODE); |
| //modem_if.modem_current_cid = INVALID_CID; |
| INFOMSG(" Fallback to ACM_CONTROL_MODE, modem_current_cid is 0xFF\n"); |
| modem_if.ppp_cbs.reset(); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| ath_data = true; |
| ato_data = true; |
| } |
| else |
| modem_if.ppp_cbs.rx_modem(packet_buffer, received); |
| } |
| else |
| ppp_modem_receive_error(ACM_DATA_MODE, received); |
| } |
| } |
| #endif |
| #ifdef UART2_AT |
| if(FD_ISSET(ppp_at_fd2, &fds)) |
| { /* received AT response */ |
| FD_CLR(ppp_at_fd2, &fds); |
| received = read_channel(&ppp_at2); |
| if(received > 0) |
| { |
| U_CHAR *p_sol = NULL; |
| int cur_count = 0; |
| p_sol = ppp_at2.at_buffer_head; |
| while (1) |
| { |
| line = get_line(&ppp_at2, 0); |
| if (line == NULL) break; |
| dbg_dump_string("AT RESPONSE UART (string), modem_router\r\n", (char *)line, ppp_at2.cur_line_len); |
| dbg_dump_buffer("AT RESPONSE UART (buffer), modem_router\r\n", (char *)line, ppp_at2.cur_line_len); |
| cur_count += ppp_at2.cur_line_len; |
| |
| if (get_modem_if_state(ppp_uart2_fd) == ACM_DATA_MODE) |
| modem_parse_atcmd(line, ppp_at2.cur_line_len, FALSE); |
| } |
| |
| if (get_modem_if_state(ppp_uart2_fd) == ACM_CONTROL_MODE && cur_count > 0) { |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.rsp_count++; |
| at_statistics.rsp_byte += cur_count; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_uart2_fd, p_sol, cur_count); |
| dbg_dump_string("AT RESPONSE UART (string) Write to UART, modem_router\r\n", (char *)p_sol, cur_count); } |
| } |
| } |
| if(FD_ISSET(ppp_uart2_fd, &fds)) |
| { /* handler packet message from terminal */ |
| FD_CLR(ppp_uart2_fd, &fds); |
| if (get_modem_if_state(ppp_uart2_fd) == ACM_CONTROL_MODE) |
| { |
| received = read_channel(&ppp_uart2); |
| if(received > 0) |
| { |
| while (1) |
| { |
| line = get_line(&ppp_uart2, 1); |
| if (line == NULL) break; |
| dbg_dump_string("AT COMMAND UART (string), modem_router\r\n", (char *)line, ppp_uart2.cur_line_len); |
| dbg_dump_buffer("AT COMMAND UART (buffer), modem_router\r\n", (char *)line, ppp_uart2.cur_line_len); |
| |
| if(is_ppp_dial_string(line)) { |
| cid = ppp_parse_profile_id(line); |
| if (cid) |
| configure_ppp_cid(cid -1); |
| |
| handle_dial(ppp_uart2_fd); |
| continue; |
| } |
| |
| if (strncasecmp((const char *)line, "ATH", sizeof("ATH") - 1) == 0 && ath_data) { |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_uart2_fd, RESP_OK, sizeof(RESP_OK) - 1); |
| ath_data = false; |
| continue; |
| } |
| |
| if(strncasecmp((char const *)line, "ATE0", strlen("ATE0")) == 0) |
| modem_if.echo_mode = MODEM_NORMAL_MODE; |
| |
| if(strncasecmp((char const *)line, "ATE1", strlen("ATE1")) == 0) |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| |
| if(strncasecmp((char const *)line, "AT+CGDCONT=", strlen("AT+CGDCONT=")) == 0) { |
| store_configure_params(line, ppp_uart2.cur_line_len); |
| } |
| |
| if(strncasecmp((char const *)line, "ATO", strlen("ATO")) == 0 && ato_data) { |
| writen(ppp_uart2_fd, "\r\nOK\r\n", strlen("\r\nOK\r\n")); |
| set_modem_if_state(ppp_uart2_fd, ACM_DATA_MODE); |
| ato_data = false; |
| } |
| if(strncasecmp((char const *)line, "AT+CMUX=", strlen("AT+CMUX=")) == 0) { |
| int mode; |
| int baud; |
| (void)sscanf((const char *)line, "%*[^0-9]%d,%d", &mode, &baud); |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_uart2_fd, RESP_OK, sizeof(RESP_OK) - 1); |
| cmux_set(ppp_uart2_fd, mode, baud); |
| cmux_flag = 1; |
| } else { |
| /* relay atcmd to ATCMDSRV */ |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.cmd_count++; |
| at_statistics.cmd_byte += ppp_uart2.cur_line_len; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_at_fd2, line, ppp_uart2.cur_line_len); |
| } |
| } |
| } |
| } |
| else if (get_modem_if_state(ppp_uart2_fd) == ACM_DATA_MODE) /* relay packet to PPP server: message_queue */ |
| { |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppp_uart2_fd, packet_buffer, PPP_FRAME_SIZE); |
| if(received > 0) |
| { |
| /* check if the packet is "+++", which is the signal to enter ACM_CONTROL_MODE */ |
| if( ppp_check_control_mode_streams(ppp_uart2_fd, packet_buffer, received) && |
| strncasecmp((char const *)packet_buffer, "+++", strlen("+++")) == 0) |
| { |
| set_modem_if_state(ppp_uart2_fd, ACM_CONTROL_MODE); |
| //modem_if.modem_current_cid = INVALID_CID; |
| INFOMSG(" Fallback to ACM_CONTROL_MODE, modem_current_cid is 0xFF\n"); |
| modem_if.ppp_cbs.reset(); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| ath_data = true; |
| ato_data = true; |
| } |
| else |
| modem_if.ppp_cbs.rx_modem(packet_buffer, received); |
| } |
| } |
| } |
| #endif |
| |
| #ifdef PPP_PSEUDO_DEVICE |
| if(FD_ISSET(ppp_at_fd_pseudo, &fds)) |
| { /* received AT response */ |
| FD_CLR(ppp_at_fd_pseudo, &fds); |
| received = read_channel(&ppp_at_pseudo); |
| if(received > 0) |
| { |
| U_CHAR *p_sol = NULL; |
| int cur_count = 0; |
| p_sol = ppp_at_pseudo.at_buffer_head; |
| while (1) |
| { |
| line = get_line(&ppp_at_pseudo, 0); |
| if (line == NULL) break; |
| dbg_dump_string("AT RESPONSE PSEUDO (string), modem_router\r\n", (char *)line, ppp_at_pseudo.cur_line_len); |
| dbg_dump_buffer("AT RESPONSE PSEUDO (buffer), modem_router\r\n", (char *)line, ppp_at_pseudo.cur_line_len); |
| cur_count += ppp_at_pseudo.cur_line_len; |
| |
| if (get_modem_if_state(ppp_modem_fd_pseudo) == ACM_DATA_MODE) |
| modem_parse_atcmd(line, ppp_at_pseudo.cur_line_len, FALSE); |
| } |
| |
| if (get_modem_if_state(ppp_modem_fd_pseudo) == ACM_CONTROL_MODE && cur_count > 0) { |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.rsp_count++; |
| at_statistics.rsp_byte += cur_count; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_modem_fd_pseudo, p_sol, cur_count); |
| dbg_dump_string("AT RESPONSE PSEUDO (string) Write to PSEUDO device, modem_router\r\n", (char *)p_sol, cur_count); } |
| } |
| } |
| if(FD_ISSET(ppp_modem_fd_pseudo, &fds)) |
| { /* handler packet message from terminal */ |
| FD_CLR(ppp_modem_fd_pseudo, &fds); |
| if (get_modem_if_state(ppp_modem_fd_pseudo) == ACM_CONTROL_MODE) |
| { |
| received = read_channel(&ppp_modem_pseudo); |
| if(received > 0) |
| { |
| while (1) |
| { |
| line = get_line(&ppp_modem_pseudo, 1); |
| if (line == NULL) break; |
| dbg_dump_string("AT COMMAND PSEUDO (string), modem_router\r\n", (char *)line, ppp_modem_pseudo.cur_line_len); |
| dbg_dump_buffer("AT COMMAND PSEUDO (buffer), modem_router\r\n", (char *)line, ppp_modem_pseudo.cur_line_len); |
| |
| if(is_ppp_dial_string(line)) { |
| cid = ppp_parse_profile_id(line); |
| if (cid) |
| configure_ppp_cid(cid -1); |
| |
| handle_dial(ppp_modem_fd_pseudo); |
| continue; |
| } |
| |
| if (strncasecmp((const char *)line, "ATH", sizeof("ATH") - 1) == 0 && ath_data) { |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_modem_fd_pseudo, RESP_OK, sizeof(RESP_OK) - 1); |
| ath_data = false; |
| continue; |
| } |
| |
| if(strncasecmp((char const *)line, "ATE0", strlen("ATE0")) == 0) |
| modem_if.echo_mode = MODEM_NORMAL_MODE; |
| |
| if(strncasecmp((char const *)line, "ATE1", strlen("ATE1")) == 0) |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| |
| if(strncasecmp((char const *)line, "AT+CGDCONT=", strlen("AT+CGDCONT=")) == 0) { |
| store_configure_params(line, ppp_modem_pseudo.cur_line_len); |
| } |
| |
| if(strncasecmp((char const *)line, "ATO", strlen("ATO")) == 0 && ato_data) { |
| writen(ppp_modem_fd_pseudo, "\r\nOK\r\n", strlen("\r\nOK\r\n")); |
| set_modem_if_state(ppp_modem_fd_pseudo, ACM_DATA_MODE); |
| ato_data = false; |
| } |
| if(strncasecmp((char const *)line, "AT+CMUX=", strlen("AT+CMUX=")) == 0) { |
| int mode; |
| int baud; |
| (void)sscanf((const char *)line, "%*[^0-9]%d,%d", &mode, &baud); |
| static const char RESP_OK[] = "\r\nOK\r\n"; |
| writen(ppp_modem_fd_pseudo, RESP_OK, sizeof(RESP_OK) - 1); |
| cmux_set(ppp_modem_fd_pseudo, mode, baud); |
| cmux_flag = 1; |
| } else { |
| /* relay atcmd to ATCMDSRV */ |
| #ifdef MODEM_AT_STATISTICS |
| at_statistics.cmd_count++; |
| at_statistics.cmd_byte += ppp_modem_pseudo.cur_line_len; |
| write_at_stat_2file("/tmp/modem_at_stat", &at_statistics); |
| #endif |
| writen(ppp_at_fd_pseudo, line, ppp_modem_pseudo.cur_line_len); |
| } |
| } |
| } |
| } |
| else if (get_modem_if_state(ppp_modem_fd_pseudo) == ACM_DATA_MODE) /* relay packet to PPP server: message_queue */ |
| { |
| memset(packet_buffer, 0x00, PPP_FRAME_SIZE); |
| received = read(ppp_modem_fd_pseudo, packet_buffer, PPP_FRAME_SIZE); |
| if(received > 0) |
| { |
| /* check if the packet is "+++", which is the signal to enter ACM_CONTROL_MODE */ |
| if( ppp_check_control_mode_streams(ppp_modem_fd_pseudo, packet_buffer, received) && |
| strncasecmp((char const *)packet_buffer, "+++", strlen("+++")) == 0) |
| { |
| set_modem_if_state(ppp_modem_fd_pseudo, ACM_CONTROL_MODE); |
| //modem_if.modem_current_cid = INVALID_CID; |
| INFOMSG(" Fallback to ACM_CONTROL_MODE, modem_current_cid is 0xFF\n"); |
| modem_if.ppp_cbs.reset(); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| ath_data = true; |
| ato_data = true; |
| } |
| else |
| modem_if.ppp_cbs.rx_modem(packet_buffer, received); |
| } |
| } |
| } |
| #endif |
| } |
| } |
| exit: |
| sem_post(&modem_if.router_exit); |
| } |
| |
| void modem_reset_ppprd(void) |
| { |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPRESETCB); |
| ioctl(ppprd_fd, PPPRD_IOCTL_TIOPPPOFF, modem_if.modem_current_cid); |
| INFOMSG("%s OK\n", __func__); |
| return; |
| } |
| |
| static void init_channel_struct(struct at_channel_struct *chan, int fd, int id) |
| { |
| chan->tty_fd = fd; |
| memset(chan->at_buffer, 0, sizeof(chan->at_buffer)); |
| chan->at_buffer_head = chan->at_buffer; |
| chan->at_buffer_tail = chan->at_buffer; |
| chan->id = id; |
| } |
| |
| static void open_port(int *fd_ptr, const char *file_path, int flag, int tty) |
| { |
| int fd; |
| |
| while((fd = open(file_path, flag)) < 0) |
| { |
| DBGMSG("%s: open %s failed\n", __func__, file_path); |
| sleep(1); |
| } |
| |
| if (tty) { |
| /* set newtio */ |
| struct termios newtio; |
| memset(&newtio, 0, sizeof(newtio)); |
| (void)fcntl(fd, F_SETFL, 0); |
| #ifdef UART2_AT |
| /* no flow control for uart by default */ |
| newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD; |
| #else |
| newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD; |
| #endif |
| newtio.c_iflag = IGNPAR; |
| //newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); |
| newtio.c_oflag = 0; |
| newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */ |
| |
| newtio.c_cc[VERASE] = 0x8; /* del */ |
| newtio.c_cc[VEOF] = 4; /* Ctrl-d */ |
| newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */ |
| newtio.c_cc[VEOL] = 0xD; /* '\0' */ |
| |
| tcflush(fd, TCIFLUSH); |
| tcsetattr(fd, TCSANOW, &newtio); |
| } |
| |
| *fd_ptr = fd; |
| } |
| |
| static int open_socket(const char* socketName) |
| { |
| int fd; |
| |
| while((fd = connectUnixSocket(socketName)) < 0) { |
| DBGMSG("%s: open %s failed\n", __func__, socketName); |
| sleep(1); |
| } |
| return fd; |
| } |
| |
| void modem_if_init() |
| { |
| set_modem_if_state(0, ACM_CONTROL_MODE); |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| modem_if.modem_nocarrier_query_cgcontrdp = INVALID_CID; |
| |
| modem_clear_ip_update_flag(); |
| ppp_set_nd_state(ND_STATE_INIT); |
| } |
| |
| static int modem_init_status=0; |
| int get_modem_init_status(void) |
| { |
| #ifdef TERMINATE_ALL_RESOURCES |
| return 0; |
| #else |
| return modem_init_status; |
| #endif |
| } |
| |
| int set_modem_init_status(int status) |
| { |
| modem_init_status = status; |
| return 0; |
| } |
| |
| |
| void modem_init(void) |
| { |
| static const char WELCOME_MSG[] = "\r\nMarvell AT server ready\r\n"; |
| char cmd[32]; |
| int init_done=get_modem_init_status(); |
| int count = 0; |
| |
| INFOMSG("%s: init done %d, usb state %d\n", __func__, init_done, get_modem_state()); |
| if(!init_done){ |
| /* call init ppp stack function*/ |
| setup_callback_funcs(&modem_if.ppp_cbs); |
| } |
| |
| if (modem_if.ppp_cbs.init) |
| modem_if.ppp_cbs.init(); |
| |
| if(!init_done){ |
| /* init pipefd */ |
| if (pipe(pipefd) == -1) |
| errExit("init pipe"); |
| |
| /* init router exit semaphore */ |
| sem_init(&modem_if.router_exit, 0, 0); |
| } |
| |
| /* init modem_if struct */ |
| set_modem_if_state(0, ACM_CONTROL_MODE); |
| modem_if.modem_current_cid = INVALID_CID; |
| modem_if.modem_nocarrier_query_cgcontrdp = INVALID_CID; |
| |
| if(!init_done){ |
| sem_init(&modem_if.atcmd_if.atcmd_response, 0, 0); |
| modem_if.atcmd_if.atcmd_send = FALSE; |
| /* init at channel */ |
| #ifdef PPP_WITHOUT_ATSRV |
| open_port(&ppp_at_fd, MODEM_ATCMD_DEVICE, O_RDWR, 1); |
| #else |
| ppp_at_fd = open_socket(MODEM_ATCMD_SOCKET); |
| #endif |
| init_channel_struct(&ppp_at, ppp_at_fd, 0); |
| } |
| /* init modem channel */ |
| if(ppp_modem_fd==0 && get_modem_state()) { |
| INFOMSG("%s found ppp_modem_fd is 0\n", __func__); |
| open_port(&ppp_modem_fd, MODEM_TERM_DEVICE, O_RDWR, 1); |
| while (ppp_modem_fd == 0 && count < 5) |
| { |
| close(ppp_modem_fd); |
| sleep(1); |
| open_port(&ppp_modem_fd, MODEM_TERM_DEVICE, O_RDWR, 1); |
| count++; |
| } |
| init_channel_struct(&ppp_modem, ppp_modem_fd, 0); |
| set_modem_if_state(ppp_modem_fd, ACM_CONTROL_MODE); |
| INFOMSG("%s: ppp_modem_fd %d, ppp_at_fd %d", __func__, ppp_modem_fd, ppp_at_fd); |
| if(init_done) |
| writen(pipefd[1], "start", strlen("start")); |
| } |
| |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| if(!init_done) { |
| ppp_at_fd1 = open_socket(MODEM_ATCMD_SOCKET1); |
| init_channel_struct(&ppp_at1, ppp_at_fd1, 0); |
| } |
| |
| if(ppp_modem_fd1==0 && get_modem_state()) { |
| INFOMSG("%s found ppp_modem_fd1 is 0\n", __func__); |
| open_port(&ppp_modem_fd1, MODEM_TERM_DEVICE1, O_RDWR, 1); |
| while (ppp_modem_fd == 0 && count < 5) |
| { |
| close(ppp_modem_fd); |
| sleep(1); |
| open_port(&ppp_modem_fd, MODEM_TERM_DEVICE, O_RDWR, 1); |
| count++; |
| } |
| init_channel_struct(&ppp_modem1, ppp_modem_fd1, 0); |
| set_modem_if_state(ppp_modem_fd1, ACM_CONTROL_MODE); |
| INFOMSG("%s: ppp_modem_fd1 %d, ppp_at_fd1 %d", __func__, ppp_modem_fd1, ppp_at_fd1); |
| |
| if(init_done) |
| writen(pipefd[1], "start", strlen("start")); |
| } |
| #endif |
| #ifdef UART2_AT |
| if(!init_done){ |
| ppp_at_fd2 = open_socket(MODEM_ATCMD_SOCKET2); |
| init_channel_struct(&ppp_at2, ppp_at_fd2, 0); |
| open_port(&ppp_uart2_fd, UART2_TERM_DEVICE, O_RDWR, 1); |
| init_channel_struct(&ppp_uart2, ppp_uart2_fd, 0); |
| set_modem_if_state(ppp_uart2_fd, ACM_CONTROL_MODE); |
| INFOMSG("%s: ppp_uart2_fd %d, ppp_at_fd2 %d", __func__, ppp_uart2_fd, ppp_at_fd2); |
| } |
| #endif |
| #ifdef PPP_PSEUDO_DEVICE |
| INFOMSG("%s int_done %d\n", __func__, init_done); |
| if(!init_done){ |
| char *pts_name = NULL; |
| int pts_fd = 0; |
| ppp_at_fd_pseudo = open_socket(MODEM_PSEUDO_ATCMD_SOCKET); |
| init_channel_struct(&ppp_at_pseudo, ppp_at_fd_pseudo, 0); |
| |
| INFOMSG("%s ppp_at_fd_pseudo %d, ppp_modem_fd_pseudo %d\n", __func__, ppp_at_fd_pseudo, ppp_modem_fd_pseudo); |
| if(ppp_modem_fd_pseudo == 0){ |
| INFOMSG("%s found ppp_modem_fd_pseudo is 0\n", __func__); |
| //ppp_modem_fd_pseudo = open(MODEM_PSEUDO_TERM_DEVICE, O_RDWR | O_NOCTTY); |
| open_port(&ppp_modem_fd_pseudo, MODEM_PSEUDO_TERM_DEVICE, O_RDWR |O_NOCTTY, 1); |
| init_channel_struct(&ppp_modem_pseudo, ppp_modem_fd_pseudo, 6); |
| set_modem_if_state(ppp_modem_fd_pseudo, ACM_CONTROL_MODE); |
| INFOMSG("%s: ppp_modem_fd_pseudo %d", __func__, ppp_modem_fd_pseudo); |
| |
| grantpt(ppp_modem_fd_pseudo); |
| unlockpt(ppp_modem_fd_pseudo); |
| pts_name = ptsname(ppp_modem_fd_pseudo); |
| pts_fd = open(pts_name, O_RDWR | O_NOCTTY); |
| INFOMSG("%s: pts_name %s, pts_fd %d", __func__, pts_name, pts_fd); |
| if(init_done) |
| writen(pipefd[1], "start", strlen("start")); |
| } |
| } |
| #endif |
| if(!init_done){ |
| /* init ppprd */ |
| open_port(&ppprd_fd, MODEM_COMM_DEVICE, O_RDWR, 0); |
| |
| //ppp_cm_fd = open_socket(MODEM_CONN_CM_SOCKET); |
| } |
| /* by default configure echo to be on */ |
| #ifdef AT_CONFIG_P701 |
| modem_if.echo_mode = MODEM_NORMAL_MODE; |
| #else |
| modem_if.echo_mode = MODEM_ECHO_MODE; |
| #endif |
| |
| writen(ppp_modem_fd, WELCOME_MSG, sizeof(WELCOME_MSG)-1); |
| |
| //not in production mode |
| if (!InProduction_Mode()) |
| { |
| memset(cmd,0,32); |
| snprintf(cmd, sizeof(cmd), "ATE%d\r", modem_if.echo_mode); |
| writen(ppp_at_fd, cmd, strlen(cmd)); |
| |
| //FixMe: Disable the unsolicited indication for Modem port in order to support GCF test ---201251225 Yhuang |
| /*shoule enable the unsolicited ind for modem port in ZTE project*/ |
| memset(cmd,0,32); |
| #ifdef AT_CONFIG_P701 |
| snprintf(cmd, sizeof(cmd), "AT*APPOWERIND=1;+CMEE=2\r"); |
| #else |
| snprintf(cmd, sizeof(cmd), "AT*APPOWERIND=1\r"); |
| #endif |
| writen(ppp_at_fd, cmd, strlen(cmd)); |
| } |
| |
| if(!init_done){ |
| /* create modem router thread */ |
| if(pthread_create(&modem_if.modem_router_ref, NULL, (void *)modem_router, NULL) != 0 ) |
| errExit("pthread_create"); |
| } |
| |
| INFOMSG("%s OK\n", __func__); |
| } |
| |
| void modem_deinit(void) |
| { |
| struct timespec ts; |
| |
| if (modem_if.ppp_cbs.deinit) |
| modem_if.ppp_cbs.deinit(); |
| |
| /* hot plug usb line without a disconnect msg*/ |
| if (get_modem_if_state(0) == ACM_DATA_MODE) |
| modem_ppp_terminate(modem_if.modem_current_cid); |
| |
| writen(pipefd[1], "term", strlen("term")); |
| |
| #ifdef TERMINATE_ALL_RESOURCES |
| INFOMSG("%s stop router thread\n", __func__); |
| /* stop router thread */ |
| |
| ts.tv_sec = time(NULL) + 10; |
| ts.tv_nsec = 0; |
| |
| if (sem_timedwait(&modem_if.router_exit, &ts) == -1) |
| { |
| DBGMSG("%s: sem wait for router exit fail\n", __func__); |
| } |
| INFOMSG("%s stop router thread done\n", __func__); |
| |
| /* collect resources */ |
| tcflush(ppp_modem_fd, TCIOFLUSH); |
| close(ppp_modem_fd); |
| close(ppprd_fd); |
| tcflush(ppp_at_fd, TCIOFLUSH); |
| close(ppp_at_fd); |
| #ifdef ADDITIONAL_MODEM_DEVICE |
| tcflush(ppp_modem_fd1, TCIOFLUSH); |
| close(ppp_modem_fd1); |
| tcflush(ppp_at_fd1, TCIOFLUSH); |
| close(ppp_at_fd1); |
| #endif |
| #ifdef UART2_AT |
| tcflush(ppp_uart2_fd, TCIOFLUSH); |
| close(ppp_uart2_fd); |
| tcflush(ppp_at_fd2, TCIOFLUSH); |
| close(ppp_at_fd2); |
| #endif |
| |
| #ifdef PPP_PSEUDO_DEVICE |
| close(ppp_modem_fd_pseudo); |
| close(ppp_at_fd_pseudo); |
| #endif |
| close(pipefd[0]); |
| close(pipefd[1]); |
| memset(&modem_if, 0x00, sizeof(modem_control_interface)); |
| #endif |
| |
| INFOMSG("%s OK\n", __func__); |
| } |