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

📄 atcmd.c

📁 Linux下gsm/gprs modem的看守程序。支持短信发送与接受。
💻 C
📖 第 1 页 / 共 2 页
字号:
					memset(g->mlbuf, 0, MLPARSE_BUF_SIZE);				}				g->mlbuf_len = 0;			}			/* the current buf will be appended to mlbuf below */		}	} else {		if (!strcmp(buf, "RING") ||		    ((g->flags & GSMD_FLAG_V0) && buf[0] == '2')) {			/* this is the only non-extended unsolicited return			 * code, part of Case 'B' */			return unsolicited_parse(g, buf, len, NULL);		}		if (!strcmp(buf, "ERROR") ||		    ((g->flags & GSMD_FLAG_V0) && buf[0] == '4')) {			/* Part of Case 'C' */			DEBUGP("unspecified error\n");			if (cmd)				cmd->ret = 4;			goto final_cb;		}		if (!strncmp(buf, "OK", 2) ||		    ((g->flags & GSMD_FLAG_V0) && buf[0] == '0')) {			/* Part of Case 'C' */			if (cmd)				cmd->ret = 0;			goto final_cb;		}		/* FIXME: handling of those special commands in response to		 * ATD / ATA */		if (!strncmp(buf, "NO CARRIER", 10) ||		    ((g->flags & GSMD_FLAG_V0) && buf[0] == '3')) {			/* Part of Case 'D' */			goto final_cb;		}		if (!strncmp(buf, "BUSY", 4) ||		    ((g->flags & GSMD_FLAG_V0) && buf[0] == '7')) {			/* Part of Case 'D' */			goto final_cb;		}	}	/* we reach here, if we are at an information response that needs to be	 * passed on */	if (g->mlbuf_len)		g->mlbuf[g->mlbuf_len ++] = '\n';	DEBUGP("Appending buf to mlbuf\n");	if (len > MLPARSE_BUF_SIZE - g->mlbuf_len)		len = MLPARSE_BUF_SIZE - g->mlbuf_len;	memcpy(g->mlbuf + g->mlbuf_len, buf, len);	g->mlbuf_len += len;	if (g->mlunsolicited) {		rc = unsolicited_parse(g, (const char*) g->mlbuf, (int) g->mlbuf_len,				strchr((const char*)g->mlbuf, ':') + 1);		if (rc == -EAGAIN) {			/* The parser wants one more line of			 * input.  Wait for the next line, concatenate			 * and resumbit to unsolicited_parse().  */			DEBUGP("Multiline unsolicited code\n");			return 0;		}		g->mlunsolicited = 0;		g->mlbuf_len = 0;	}	return rc;final_cb:	/* if reach here, the final result code of a command has been reached */	if (!cmd)		return rc;	if (cmd && cme_error)		generate_event_from_cme(g, cmd->ret);		if (cmd && cms_error)		generate_event_from_cms(g, cmd->ret);	return atcmd_done(g, cmd, buf);}/* called when the modem asked for a new line of a multiline atcmd */static int atcmd_prompt(void *data){	struct gsmd *g = data;        atcmd_wake_pending_queue(g);	return 0;}/* callback to be called if [virtual] UART has some data for us */static int atcmd_select_cb(int fd, unsigned int what, void *data){	int len, rc;	static char rxbuf[1024];	struct gsmd *g = data;	char *cr;	if (what & GSMD_FD_READ) {		memset(rxbuf, 0, sizeof(rxbuf));		while ((len = read(fd, rxbuf, sizeof(rxbuf)))) {			if (len < 0) {				if (errno == EAGAIN)					return 0;				gsmd_log(GSMD_NOTICE, "ERROR reading from fd %u: %d (%s)\n", fd, len,					strerror(errno));					return len;			}			rc = llparse_string(&g->llp, rxbuf, len);			if (rc < 0) {				gsmd_log(GSMD_ERROR, "ERROR during llparse_string: %d\n", rc);				return rc;			}		}	}	/* write pending commands to UART */	if ((what & GSMD_FD_WRITE) && g->interpreter_ready) {		struct gsmd_atcmd *pos, *pos2;		llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {			cr = strchr(pos->cur, '\n');			if (cr)				len = cr - pos->cur;			else				len = pos->buflen - 1;  /* assuming zero-terminated strings */			rc = write(fd, pos->cur, len);			if (rc == 0) {				gsmd_log(GSMD_ERROR, "write returns 0, aborting\n");				break;			} else if (rc < 0) {				gsmd_log(GSMD_ERROR, "error during write to fd %d: %d\n",					fd, rc);				return rc;			}			if (!cr || rc == len)				rc ++;	/* Skip the \n or \0 */			pos->buflen -= rc;			pos->cur += rc;			write(fd, "\r", 1);			if (!pos->buflen) {				/* success: create atcommand timeout timer */				pos->timeout = pos->create_timer_func(g);  				/* success: remove from global list of				 * to-be-sent atcmds */				llist_del(&pos->list);				/* append to global list of executing atcmds */				llist_add_tail(&pos->list, &g->busy_atcmds);				/* we only send one cmd at the moment */				break;			} else {				/* The write was short or the atcmd has more				 * lines to send after a "> ".  */				if (rc < len)					return 0;				break;			}		}		/* Either pending_atcmds is empty or a command has to wait */                atcmd_wait_pending_queue(g);	}	return 0;}static void discard_timeout(struct gsmd_timer *tmr, void *data) {        struct gsmd *g=data;        struct gsmd_atcmd *cmd=NULL;        DEBUGP("discard time out!!\n");        if (!llist_empty(&g->busy_atcmds)) {                cmd = llist_entry(g->busy_atcmds.next,struct gsmd_atcmd, list);        }        if (!cmd) {                 DEBUGP("ERROR!! busy_atcmds is NULL\n");                return;        }        if (cmd->timeout != tmr) {                DEBUGP("ERROR!! cmd->timeout != tmr\n");                return;        }        gsmd_timer_free(cmd->timeout);        cmd->timeout = NULL;	if (cmd->cb) {		cmd->resp = "Timeout";                cmd->cb(cmd, cmd->ctx, cmd->resp);	}		// discard the timeout at command	llist_del(&cmd->list);	talloc_free(cmd);		// pass the next pending at command	if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) {		atcmd_wake_pending_queue(g);	}}static struct gsmd_timer * discard_timer(struct gsmd *g){        	struct timeval tv;	tv.tv_sec = GSMD_ATCMD_TIMEOUT;	tv.tv_usec = 0;         	DEBUGP("Create discard timer\n");		return gsmd_timer_create(&tv, &discard_timeout, g);}struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen,			      atcmd_cb_t cb, void *ctx, u_int16_t id,			      create_timer_t ct){	int buflen = strlen(cmd);	struct gsmd_atcmd *atcmd;	if (rlen > buflen)		buflen = rlen;	atcmd = talloc_size(__atcmd_ctx, sizeof(*atcmd)+ buflen);	if (!atcmd)		return NULL;	atcmd->ctx = ctx;	atcmd->id = id;	atcmd->flags = 0;	atcmd->ret = -255;	atcmd->buflen = buflen;	atcmd->buf[buflen-1] = '\0';	atcmd->cur = atcmd->buf;	atcmd->cb = cb;	atcmd->resp = NULL;	atcmd->timeout = NULL;	strncpy(atcmd->buf, cmd, buflen-1);	if (!ct)		atcmd->create_timer_func = discard_timer; 	else		atcmd->create_timer_func = ct;	return atcmd;}static int remove_timer(struct gsmd_atcmd * cmd){	if (cmd->timeout) {		DEBUGP("Get respond before timeout, remove timer!\n");		gsmd_timer_unregister(cmd->timeout);		gsmd_timer_free(cmd->timeout);		cmd->timeout = NULL;	} else {		DEBUGP("ERROR!! The %s response comes too late!!\n", cmd->buf);	}	return 0;}/* submit an atcmd in the global queue of pending atcmds */int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd){	if (g->machinepl->ex_submit) {		DEBUGP("extra-submiting command\n");		g->machinepl->ex_submit(g);	}	DEBUGP("submitting command `%s'\n", cmd->buf);	llist_add_tail(&cmd->list, &g->pending_atcmds);	if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds)) {		atcmd_wake_pending_queue(g);	}	return 0;}/* cancel a currently executing atcmd by issuing the command given as * parameter, usually AT ot ATH.  */int cancel_atcmd(struct gsmd *g, struct gsmd_atcmd *cmd){        struct gsmd_atcmd *cur;        if (llist_empty(&g->busy_atcmds)) {                return atcmd_submit(g, cmd);        }        cur = llist_entry(g->busy_atcmds.next, struct gsmd_atcmd, list);        DEBUGP("cancelling command `%s' with an `%s'\n", cur->buf, cmd->buf);                if (g->mlbuf_len) {                DEBUGP("Discarding mlbuf: %.*s\n", g->mlbuf_len, g->mlbuf);                g->mlbuf_len = 0;        }                llist_add(&cmd->list, &g->pending_atcmds);        return atcmd_done(g, cur, "ERROR");}void atcmd_drain(int fd){	int rc;	struct termios t;	rc = tcflush(fd, TCIOFLUSH);	rc = tcgetattr(fd, &t);	DEBUGP("c_iflag = 0x%08x, c_oflag = 0x%08x, c_cflag = 0x%08x, c_lflag = 0x%08x\n",		t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag);	t.c_iflag = t.c_oflag = 0;	cfmakeraw(&t);	rc = tcsetattr(fd, TCSANOW, &t);}/* init atcmd parser */int atcmd_init(struct gsmd *g, int sockfd){	__atcmd_ctx = talloc_named_const(gsmd_tallocs, 1, "atcmds");	g->gfd_uart.fd = sockfd;	g->gfd_uart.when = GSMD_FD_READ;	g->gfd_uart.data = g;	g->gfd_uart.cb = &atcmd_select_cb;	INIT_LLIST_HEAD(&g->pending_atcmds);	INIT_LLIST_HEAD(&g->busy_atcmds);	llparse_init (&g->llp);	g->mlbuf_len = 0;	g->mlunsolicited = 0;	g->alive_responded = 0;	g->llp.cur = g->llp.buf;	g->llp.len = sizeof(g->llp.buf);	g->llp.cb = &ml_parse;	g->llp.prompt_cb = &atcmd_prompt;	g->llp.ctx = g;	g->llp.flags = LGSM_ATCMD_F_EXTENDED;	return gsmd_register_fd(&g->gfd_uart);}/* remove from the queues any command whose .ctx matches given */int atcmd_terminate_matching(struct gsmd *g, void *ctx){	int num = 0;	struct gsmd_atcmd *cmd, *pos;	llist_for_each_entry_safe(cmd, pos, &g->busy_atcmds, list)		if (cmd->ctx == ctx) {			cmd->ret = -ESHUTDOWN;			cmd->cb(cmd, cmd->ctx, "ERROR");			cmd->cb = NULL;			cmd->ctx = NULL;			num ++;		}	llist_for_each_entry_safe(cmd, pos, &g->pending_atcmds, list)		if (cmd->ctx == ctx) {			llist_del(&cmd->list);			cmd->ret = -ESHUTDOWN;			cmd->cb(cmd, cmd->ctx, "ERROR");			talloc_free(cmd);			num ++;		}	return num;}

⌨️ 快捷键说明

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