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

📄 gsm0710.c

📁 该源码是针对支持Mux技术的手机Modem的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** GSM 07.10 Implementation with User Space Serial Ports** Copyright (C) 2003  Tuukka Karvonen <tkarvone@iki.fi>** Version 1.0 October 2003** 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.** Modified November 2004 by David Jander <david@protonic.nl>*  - Hacked to use Pseudo-TTY's instead of the (obsolete?) USSP driver.*  - Fixed some bugs which prevented it from working with Sony-Ericsson modems*  - Seriously broke hardware handshaking.*  - Changed commandline interface to use getopts:** Modified January 2006 by Tuukka Karvonen <tkarvone@iki.fi> and * Antti Haapakoski <antti.haapakoski@iki.fi>*  - Applied patches received from Ivan S. Dubrov*  - Disabled possible CRLF -> LFLF conversions in serial port initialization*  - Added minicom like serial port option setting if baud rate is configured.*    This was needed to get the options right on some platforms and to *    wake up some modems.*  - Added possibility to pass PIN code for modem in initialization*   (Sometimes WebBox modems seem to hang if PIN is given on a virtual channel)*  - Removed old code that was commented out*  - Added support for Unix98 scheme pseudo terminals (/dev/ptmx)*    and creation of symlinks for slave devices*  - Corrected logging of slave port names*  - at_command looks for AT/ERROR responses with findInBuf function instead*    of strstr function so that incoming carbage won't confuse it** Modified March 2006 by Tuukka Karvonen <tkarvone@iki.fi>*  - Added -r option which makes the mux driver to restart itself in case*    the modem stops responding. This should make the driver more fault*    tolerant. *  - Some code restructuring that was required by the automatic restarting*  - buffer.c to use syslog instead of PDEBUG*  - fixed open_pty function to grant right for Unix98 scheme pseudo*    terminals even though symlinks are not in use** New Usage:* gsmMuxd [options] <pty1> <pty2> ...** To see the options, type:* ./gsmMuxd -h*/#ifdef HAVE_CONFIG_H#include <config.h>#endif#ifndef _GNU_SOURCE// To get ptsname grandpt and unlockpt definitions from stdlib.h#define _GNU_SOURCE#endif#include <features.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <stdio.h>#include <time.h>#include <errno.h>#include <fcntl.h>#include <signal.h>#include <termios.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <string.h>#include <paths.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>//syslog#include <syslog.h>#include "buffer.h"#include "gsm0710.h"#define DEFAULT_NUMBER_OF_PORTS 3#define WRITE_RETRIES 5/**********************************************************	modified by Huangsw 2008-02-29 : change from 32 to 4**********************************************************/#define MAX_CHANNELS   4//vitorio, only to use if necessary (don't ask in what i was thinking  when i wrote this)#define TRUE	1#define FALSE	0#define UNKNOW_MODEM	0#define MC35			1#define GENERIC			2// Defines how often the modem is polled when automatic restarting is enabled// The value is in seconds#define POLLING_INTERVAL 5#define MAX_PINGS 4static volatile int terminate = 0;static int terminateCount = 0;static char* devSymlinkPrefix = 0;static int *ussp_fd;static int serial_fd;static Channel_Status *cstatus;static int max_frame_size = 31; // The limit of Sony-Ericsson GM47static int wait_for_daemon_status = 0;static GSM0710_Buffer *in_buf;  // input bufferstatic int _debug = 0;static pid_t the_pid;int _priority;int _modem_type;static char *serportdev;static int pin_code = 0;static char *ptydev[MAX_CHANNELS];static int numOfPorts;static int maxfd;static int baudrate = 0;static int *remaining;static int faultTolerant = 0;static int restart = 0;/* The following arrays must have equal length and the values must  * correspond. */static int baudrates[] = {	0, 9600, 19200, 38400, 57600, 115200, 230400, 460800};static speed_t baud_bits[] = {    0, B9600, B19200, B38400, B57600, B115200, B230400, B460800 };#if 0/* Opens USSP port for use.** PARAMS:* port - port number* RETURNS* file descriptor or -1 on error*/int ussp_open(int port){	int fd;	char name[] = "ser0\0";	name[3] = (char) (0x30 + port);	PDEBUG("Open serial port %s ", name);	fd = open(name, O_RDWR | O_NONBLOCK);	PDEBUG("done.\n");	return fd;}#endif/** * Returns success, when an ussp is opened. */int ussp_connected(int port){#if 0	struct ussp_operation op;	op.op = USSP_OPEN_RESULT;	if (cstatus[port + 1].opened)		op.arg = 0;	else		op.arg = -1;	op.len = 0;	write(ussp_fd[port], &op, sizeof(op));	PDEBUG("USSP port %d opened.\n", port);	return 0;#else	return 0;#endif}/** Writes a frame to a logical channel. C/R bit is set to 1.* Doesn't support FCS counting for UI frames.** PARAMS:* channel - channel number (0 = control)* input   - the data to be written* count   - the length of the data* type    - the type of the frame (with possible P/F-bit)** RETURNS:* number of characters written*/int write_frame(int channel, const char *input, int count, unsigned char type){	// flag, EA=1 C channel, frame type, length 1-2	unsigned char prefix[5] = { F_FLAG, EA | CR, 0, 0, 0 };	unsigned char postfix[2] = { 0xFF, F_FLAG };	int prefix_length = 4, c;	if(_debug)		syslog(LOG_DEBUG,"send frame to ch: %d \n", channel);	// EA=1, Command, let's add address	prefix[1] = prefix[1] | ((63 & (unsigned char) channel) << 2);	// let's set control field	prefix[2] = type;	// let's not use too big frames	count = min(max_frame_size, count);	// length	if (count > 127)	{		prefix_length = 5;		prefix[3] = ((127 & count) << 1);		prefix[4] = (32640 & count) >> 7;	}	else	{		prefix[3] = 1 | (count << 1);	}	// CRC checksum	postfix[0] = make_fcs(prefix + 1, prefix_length - 1);	c = write(serial_fd, prefix, prefix_length);	if (c != prefix_length)	{		if(_debug)			syslog(LOG_DEBUG,"Couldn't write the whole prefix to the serial port for the virtual port %d. Wrote only %d  bytes.", channel, c);		return 0;	}	if (count > 0)	{		c = write(serial_fd, input, count);		if (count != c)		{			if(_debug)				syslog(LOG_DEBUG,"Couldn't write all data to the serial port from the virtual port %d. Wrote only %d bytes.\n", channel, c);			return 0;		}	}	c = write(serial_fd, postfix, 2);	if (c != 2)	{		if(_debug)			syslog(LOG_DEBUG,"Couldn't write the whole postfix to the serial port for the virtual port %d. Wrote only %d bytes.", channel, c);		return 0;	}	return count;}/* Handles received data from ussp device.** This function is derived from a similar function in RFCOMM Implementation* with USSPs made by Marcel Holtmann.** PARAMS:* buf   - buffer, which contains received data* len   - the length of the buffer* port  - the number of ussp device (logical channel), where data was*         received* RETURNS:* the number of remaining bytes in partial packet*/int ussp_recv_data(unsigned char *buf, int len, int port){#if 0	int n, written;	unsigned char pkt_buf[4096];	struct ussp_operation *op = (struct ussp_operation *) pkt_buf, *top;	struct termios *tiosp;	int i;                      // size	unsigned char msc[5] = { CR | C_MSC, 0x5, 0, 0, 1 };	PDEBUG( "(DEBUG) %s chamada\n", __FUNCTION__);	memcpy(pkt_buf, buf, len);	n = len;	op = (struct ussp_operation *) pkt_buf;	for (top = op;		/* check for partial packet - first, make sure top->len is actually in pkt_buf */		((char *) top + sizeof(struct ussp_operation) <= ((char *) op) + n)		&& ((char *) top + sizeof(struct ussp_operation) + top->len <= ((char *) op) + n);		top = (struct ussp_operation *) (((char *) top) + top->len + sizeof(struct ussp_operation)))	{		switch (top->op)		{			case USSP_OPEN:				ussp_connected(port);				break;			case USSP_CLOSE:				PDEBUG("Close ussp port %d\n", port);				break;			case USSP_WRITE:				written = 0;				i = 0;				// try to write 5 times				while ((written += write_frame(port + 1, top->data + written,											top->len - written, UIH)) != top->len && i < WRITE_RETRIES)				{					i++;				}				if (i == WRITE_RETRIES)				{					PDEBUG("Couldn't write data to channel %d. Wrote only %d bytes, when should have written %ld.\n",						(port + 1), written, top->len);				}				break;			case USSP_SET_TERMIOS:				tiosp = (struct termios *) (top + 1);				if ((tiosp->c_cflag & CBAUD) == B0 && (cstatus[(port + 1)].v24_signals & S_RTC) > 0)				{					// drop DTR					PDEBUG("Drop DTR.\n");					msc[2] = 3 | ((63 & (port + 1)) << 2);					msc[3] = cstatus[(port + 1)].v24_signals & ~S_RTC;					cstatus[(port + 1)].v24_signals = msc[3];					write_frame(0, msc, 4, UIH);				}				else if ((tiosp->c_cflag & CBAUD) != B0 && (cstatus[(port + 1)].v24_signals & S_RTC) == 0)				{					// DTR up					PDEBUG("DTR up.\n");					msc[2] |= ((63 & (port + 1)) << 2);					msc[3] = cstatus[(port + 1)].v24_signals | S_RTC;					cstatus[(port + 1)].v24_signals = msc[3];					write_frame(0, msc, 4, UIH);				}#ifdef DEBUG				PDEBUG("Set termios for ussp port %d\n", port);				PDEBUG("\tinput mode flags:   0x%04x\n", tiosp->c_iflag);				PDEBUG("\toutput mode flags:  0x%04x\n", tiosp->c_oflag);				PDEBUG("\tcontrol mode flags: 0x%04x\n", tiosp->c_cflag);				PDEBUG("\tlocal mode flags:   0x%04x\n", tiosp->c_lflag);				PDEBUG("\tline discipline:    0x%02x\n", tiosp->c_line);				PDEBUG("\tcontrol characters: ");				for (i = 0; i < NCCS; i++)					PDEBUG("0x%02x ", tiosp->c_cc[i]);				PDEBUG("\n");				PDEBUG("\tinput speed:        0x%02x (%i)\n", tiosp->c_ispeed, tiosp->c_ispeed);				PDEBUG("\toutput speed:       0x%02x (%i)\n", tiosp->c_ospeed, tiosp->c_ospeed);#endif				break;			case USSP_MSC:				PDEBUG("Modem signal change\n");				msc[2] = 3 | ((63 & (port + 1)) << 2);				msc[3] = S_DV;				if ((top->arg & USSP_DTR) == USSP_DTR)				{					msc[3] |= S_RTC;					PDEBUG("RTC\n");				}				if ((top->arg & USSP_RTS) == USSP_RTS)				{					msc[3] |= S_RTR;					PDEBUG("RTR\n");				}				else				{					msc[3] |= S_FC;					PDEBUG("FC\n");				}				cstatus[(port + 1)].v24_signals = msc[3];       // save the signals				write_frame(0, msc, 4, UIH);				break;			default:				PDEBUG("Unknown code: %d\n", top->op);				break;		}	}	/* remaining bytes in partial packet */	return ((char *) op + n) - (char *) top;#else	int written = 0;	int i = 0;    int last  = 0;	// try to write 5 times	while (written  != len && i < WRITE_RETRIES)	{        last = write_frame(port + 1, buf + written,								len - written, UIH);        written += last;        if (last == 0)         {		    i++;        }	}	if (i == WRITE_RETRIES)	{		if(_debug)			syslog(LOG_DEBUG,"Couldn't write data to channel %d. Wrote only %d bytes, when should have written %ld.\n",			(port + 1), written, (long)len);	}	return 0;#endif}int ussp_send_data(unsigned char *buf, int n, int port){#if 0	struct ussp_operation *op;	op = malloc(sizeof(struct ussp_operation) + n);	op->op = USSP_READ;	op->arg = 0;	op->len = n;	memcpy(op->data, buf, n);	write(ussp_fd[port], op, sizeof(struct ussp_operation) + n);	free(op);#else	if(_debug)		syslog(LOG_DEBUG,"send data to port virtual port %d\n", port);	write(ussp_fd[port], buf, n);#endif	return n;}// Returns 1 if found, 0 otherwise. needle must be null-terminated.// strstr might not work because WebBox sends garbage before the first OKint findInBuf(char* buf, int len, char* needle) {  int i;  int needleMatchedPos=0;    if (needle[0] == '\0') {    return 1;  }  for (i=0;i<len;i++) {    if (needle[needleMatchedPos] == buf[i]) {      needleMatchedPos++;      if (needle[needleMatchedPos] == '\0') {	// Entire needle was found	return 1;       }          } else {      needleMatchedPos=0;    }  }  return 0;}/* Sends an AT-command to a given serial port and waits* for reply.** PARAMS:* fd  - file descriptor* cmd - command* to  - how many microseconds to wait for response (this is done 100 times)* RETURNS:* 1 on success (OK-response), 0 otherwise*/int at_command(int fd, char *cmd, int to){	fd_set rfds;	struct timeval timeout;	unsigned char buf[1024];	int sel, len, i;	int returnCode = 0;	int wrote = 0;	if(_debug)		syslog(LOG_DEBUG, "is in %s\n", __FUNCTION__);	wrote = write(fd, cmd, strlen(cmd));	if(_debug)		syslog(LOG_DEBUG, " wrote  %d \n", wrote);	tcdrain(fd);	sleep(1);	//memset(buf, 0, sizeof(buf));	//len = read(fd, buf, sizeof(buf));	for (i = 0; i < 100; i++)	{		FD_ZERO(&rfds);		FD_SET(fd, &rfds);		timeout.tv_sec = 0;		timeout.tv_usec = to;		if ((sel = select(fd + 1, &rfds, NULL, NULL, &timeout)) > 0)		//if ((sel = select(fd + 1, &rfds, NULL, NULL, NULL)) > 0)		{			if (FD_ISSET(fd, &rfds))			{				memset(buf, 0, sizeof(buf));				len = read(fd, buf, sizeof(buf));				if(_debug)					syslog(LOG_DEBUG, " read %d bytes == %s\n", len, buf);				//if (strstr(buf, "\r\nOK\r\n") != NULL)				if (findInBuf(buf, len, "OK"))				{					returnCode = 1;					break;				}				if (findInBuf(buf, len, "ERROR"))

⌨️ 快捷键说明

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