⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gprs.c

📁 嵌入式linux下的gprs代码
💻 C
字号:
/* * $Id$ * EAX-400 linux实验指导书配套实验代码 * 实验3.3 GPRS通信 * Copyright (c) 2006 Beijing EFLAG Technology Co.,LTD * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  */#ifndef _POSIX_SOURCE  #define _POSIX_SOURCE#endif #include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pthread.h>#include <fcntl.h>#include <errno.h>#include <signal.h>#include <sys/ioctl.h>#include <linux/limits.h>#include <termios.h>	#include "gprs.h"#include "eax400lab_error.h"#define DEF_BBAUD		B9600	/* SIM100-S默认的波特率 */#define DEF_GPRS_DEV		"/dev/ttyS4"#define GPRS_SEND_BUF_SZ	4096#define GPRS_RECV_BUF_SZ	4096#define QBUF_READ_SZ		1024#define QBUF_WRITE_SZ		1024#define DEF_TIMEOUT_SEC		100#define DEF_CMD			NULL	static struct gprs_stat gprs = {	name:	"SIM100-S GPRS Module",	fds:	-1,};static unsigned int msg_over;	/* 短消息发送结束标志 *//* 显示帮助信息 */static void usage(char *prog){	fprintf(stdout, "usage:\n\t%s: -d <dev> [-b <baud>]\n", prog);	}static int to_Bbaud(unsigned int baud) {	int Bbaud;		switch (baud) {		case 0:	/* default */		Bbaud = DEF_BBAUD;		break;				case 300:		Bbaud = B300;				break;	case 1200:		Bbaud = B1200;		break;	case 2400:		Bbaud = B2400;		break;		case 4800:		Bbaud = B4800;			break;	case 9600:		Bbaud = B9600;		break;	case 19200:		Bbaud = B19200;		break;	case 38400:		Bbaud = B38400;		break;	case 57600:		Bbaud = B57600;		break;					case 115200:		Bbaud = B115200;		break;							default:		pr_error("Invalid baud setting %d.\n", baud);		return -1;		}		return Bbaud;}	/* * 初始化串口 */static int init_serial(char *dev, unsigned int baud, 		struct termios *oldsterm){	int fds;	long vdisable;	struct termios sterm;	speed_t Bbaud;		if (!oldsterm) {		pr_error("Invalid termios.");		return -1;		}			/* 将输入的波特率转换为BXXX宏,同时进行参数检查 */	Bbaud = to_Bbaud(baud);	if (Bbaud < 0)		return -1;		fds = open(dev, O_RDWR | O_NOCTTY);	if (fds < 0) {		pr_error("open serial device %s error occured", dev);		return -1;	}			if ((vdisable = fpathconf(fds, _PC_VDISABLE)) < 0) {		close(fds);		pr_error("fpathconf() for serial device %s error", dev);		return -1;	}		if (!isatty(fds)) {		close(fds);		pr_error("device %s is not a tty device", dev);		return -1;	}		if (!isatty(STDIN_FILENO)) {		close(fds);		pr_error("stdin is not a tty device");		return -1;	}		if (!isatty(STDOUT_FILENO)) {		close(fds);		pr_error("stdout is not a tty device");		return -1;	}		/* 获得终端属性 */	if  (tcgetattr(fds, oldsterm)) {		close(fds);		pr_error("Can't get serial device %s tc attribute", dev);		return -1;			}	#if 1	bzero(&sterm, sizeof(sterm));	sterm.c_cc[VERASE]	= vdisable;	sterm.c_cc[VKILL]	= vdisable;	sterm.c_cc[VEOF]	= vdisable;	sterm.c_cc[VEOL]	= vdisable;	sterm.c_cc[VEOL2]	= vdisable;	sterm.c_cc[VREPRINT]	= vdisable;     	sterm.c_cc[VWERASE]	= vdisable;	sterm.c_cc[VLNEXT]	= vdisable;		sterm.c_cc[VSUSP]	= vdisable;	/* 为发送短信而保留^z */	sterm.c_cflag 		= (Bbaud | CS8 | CLOCAL | CREAD);	sterm.c_iflag		= (IGNPAR | IGNBRK);	sterm.c_oflag 		= (OPOST | ONLCR);	/* 向GPRS发出的AT命令应该以\r\n结尾(0xd 0xa) */	sterm.c_lflag 		= (ICANON);		/* 应用新的终端设置 */	if (tcsetattr(fds, TCSAFLUSH, &sterm)) {		tcsetattr(fds, TCSANOW, oldsterm);		close(fds);		pr_error("Can't set serial device %s tc attribute", dev);		return -1;	}#endif				//tcflush(fds, TCIOFLUSH);		gprs.fds = fds;			return fds;}/* 恢复串口的默认设置 */static int reset_serial(void){	int fds;			fds = gprs.fds;	gprs.fds = -1;	tcsetattr(fds, TCSANOW, &gprs.oldsterm);	close(fds);}/* * 这个函数对串口也进行了初始化。 */int init_gprs(char *dev, unsigned int baud){	int fds;	fds = init_serial(dev, baud, &gprs.oldsterm);	if (fds < 0)		return -1;		gprs.sbuf = malloc(GPRS_SEND_BUF_SZ);	if (!gprs.sbuf) {		reset_serial();		pr_error("allocate send buffer failed");		return -1;		}		gprs.rbuf = malloc(GPRS_RECV_BUF_SZ);	if (!gprs.rbuf) {		reset_serial();		free(gprs.sbuf);		pr_error("allocate receive buffer failed");				return -1;		}				gprs.serialdev = dev;	gprs.baudspeed = baud;	gprs.timeout = DEF_TIMEOUT_SEC;	//gprs.cmd = DEF_CMD;		//sc_syncmode(fds, "0");	//sc_autostart(fds, CT_SETPARM, "0");	//sc_testgprs(fds);	//sc_stop(fds);	//sc_start(fds);		return 0;}void kill_gprs(void){		}	int main(int argc, char *argv[]){	int optch;	char *dev = DEF_GPRS_DEV;	const char optstring[] = "d:b:";	unsigned int baud = 0;	pthread_t tidrr, tidrs;		/* 参数检查 */	while ((optch = getopt(argc, argv, optstring)) != -1)		switch (optch) {		case 'd':						dev = optarg;			break;		case 'b':			baud = atoi(optarg);			break;		default:			printf("unknown option -%c.\n", optch);			usage(argv[0]);			return -1;		}		if (init_gprs(dev, baud) < 0)		return -1;			fprintf(stdout, "%s initilizing ...\n", gprs.name);	if (pthread_create(&tidrs, NULL, (void *(*)(void *))write_to_serial, &gprs) < 0) {		reset_serial();		free(gprs.rbuf);		free(gprs.sbuf);		pr_error("Can't create send thread.");					return -1;	}		if (pthread_create(&tidrr, NULL, (void *(*)(void *))read_from_serial, &gprs) < 0) {		// TODO: kill send thread		reset_serial();		free(gprs.rbuf);		free(gprs.sbuf);		pr_error("Can't create send thread.");					return -1;	}		pthread_join(tidrr, NULL);	fprintf(stdout, "%s exiting ...\n", gprs.name);			return 0;}/* * * 从串口读数据到gprs->bufs中. * 注意:该函数会调用parse_msg()和parse_cmd()来解析数据。目前仅对???$GPGGA, $GPGSA, $GPGSV, $GPRMC 这4种消息 * 进行解析。 * * 返回值: *	大于0:成功从串口读取的字节数 *	-1:   出错 * */int read_from_serial(struct gprs_stat *gprs){	ssize_t nr;	int fds = gprs->fds;	char *rbuf = gprs->rbuf;//	unsigned int k;	static unsigned int read_serial_seq = 0;	while (1) { 		if ((nr = read(fds, rbuf, GPRS_RECV_BUF_SZ)) > 0) {			read_serial_seq++;			if (nr == GPRS_RECV_BUF_SZ)				rbuf[nr - 1] = '\0';			else				rbuf[nr] = '\0';			fprintf(stdout, "%s\n", rbuf);					//pr_debug("[%d gprs ack %d bytes]\n%s\n", read_serial_seq, 			//	nr, rbuf);			//pr_debug("[%d dump gprs ack]\n", read_serial_seq);			//for (k = 0; k < nr; k++)			//	 pr_debug("%02x ", rbuf[k]);			//pr_debug("\n");	     		}    		if (nr < 0) {    			pr_error("read from serial error occuren");			break;		}		if (!nr)			pr_error("read serial EOF!");	};	//gprs->nread = nr;	return nr;}static void gprs_menu(void){	fprintf(stdout, "[0] give a call\n");	fprintf(stdout, "[1] respond a call\n");	fprintf(stdout, "[2] hold a call\n");	fprintf(stdout, "[3] send a msg\n");	fprintf(stdout, "[4] recv a msg\n");			}static void gprs_shell(void){	fprintf(stdout, "gprs control shell > ");	fflush(stdout);	}static void gprs_at_shell(void){	fprintf(stdout, "gprs AT shell > ");	fflush(stdout);	}#define GPRS_CMD_SZ		128static inline ssize_t get_line(char *cmd){	return read(STDIN_FILENO, cmd, GPRS_CMD_SZ);}		static void gprs_call(char *number, int num){	number[num - 1] = '\0';	sprintf(gprs.sbuf, "atd%s;\n", number);	write(gprs.fds, gprs.sbuf, strlen(gprs.sbuf));}static void gprs_hold_call(void){	sprintf(gprs.sbuf, "ath\n");	write(gprs.fds, gprs.sbuf, strlen(gprs.sbuf));	}static void gprs_accept_call(void){	sprintf(gprs.sbuf, "ata\n");	write(gprs.fds, gprs.sbuf, strlen(gprs.sbuf));	}static void sigtstp_handler(int signum){	fprintf(stdout, "write message over...\n");	msg_over = 1;		}static void gprs_send_message(void){	char buf[GPRS_CMD_SZ];	ssize_t num;		if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) {		if (signal(SIGTSTP, sigtstp_handler) == SIG_ERR) {			perror("signal(SIGTSTP)");			return;		}				}			sprintf(gprs.sbuf, "at+cmgf=1\n");	write(gprs.fds, gprs.sbuf, strlen(gprs.sbuf));			fprintf(stdout, "Please input number: ");	fflush(stdout);	get_line(buf);	num = strlen(buf);	buf[num - 1] = '\0';	sprintf(gprs.sbuf, "at+cmgs=%s\n", buf);	write(gprs.fds, gprs.sbuf, strlen(gprs.sbuf));	//msg_over = 0;	while ((num = read(STDIN_FILENO, buf, GPRS_CMD_SZ)) > 0) {		write(gprs.fds, gprs.sbuf, num);		if (msg_over) {			char stp = 0x1a;	/* ^z */				write(gprs.fds, &stp, 1);			msg_over = 0;			break;		}		}		signal(SIGTSTP, SIG_DFL);		}		/* * * 向串口写数据。 *  * 返回值: *	大于0:成功写入串口的字节数 *	-1:   出错 *  */int write_to_serial(struct gprs_stat *gprs){	int fds = gprs->fds;	char *sbuf = gprs->sbuf;		//unsigned int k;	static unsigned int input_seq = 0;	char cmd[GPRS_CMD_SZ];	//tcflush(STDIN_FILENO, TCIOFLUSH);		while (1) {		gprs_menu();		gprs_shell();		get_line(cmd);		if (!strncmp("0", cmd, 1)) {			fprintf(stdout, "\nplease input number: ");			fflush(stdout);			get_line(cmd);			gprs_call(cmd, strlen(cmd));			fprintf(stdout, "calling... wait for a moment\n");			fflush(stdout);				sleep(3);				} else if (!strncmp("1", cmd, 1)) {			fprintf(stdout, "accept the call...\n");			gprs_accept_call();		} else if (!strncmp("2", cmd, 1)) {			fprintf(stdout, "hold the call...\n");			fflush(stdout);			gprs_hold_call();					} else if (!strncmp("3", cmd, 1)) {			fprintf(stdout, "send a message...\n");			fflush(stdout);									gprs_send_message();		} else if (!strncmp("4", cmd, 1)) {			fprintf(stdout, "recv a message...\n");			fflush(stdout);		} else {	/* 原始AT命令模式 */			ssize_t nr;			gprs_at_shell();						if ((nr = read(STDIN_FILENO, sbuf, GPRS_SEND_BUF_SZ)) > 0) {				input_seq++;				//pr_debug("[%d input %dbytes]\n\"%s\"\n", input_seq, nr, sbuf);				//pr_debug("[%d dump input]\n", input_seq);				//for (k = 0; k < nr; k++)				//	 pr_debug("%02x ", sbuf[k]);				//pr_debug("\n");	 							write(fds, sbuf, nr);			}	    		if (nr == -1) {	    			perror("read() from stdin error");				break;						}			if (!nr)				perror("stdin tty dev is EOF\n");		}			}		return -1;}/* * * 当程序运行结束时应该调用这个函数,恢复串口的原始设置 * * 返回值: *		0:	成功 *		-1:	出错 *  */int recover_serial(struct gprs_stat *gprs) // 线程交互时需要这个函数{	if (tcsetattr(gprs->fds, TCSAFLUSH, &gprs->oldsterm) == -1) {                pr_error("set old serial tc attribute error");                return -1;        }    		return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -