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

📄 gsm0710muxd.c

📁 Linux GPRS 模块多路复用实现多个虚拟串口
💻 C
📖 第 1 页 / 共 4 页
字号:
				}				else//channel already opened					LOG(LOG_WARNING, "Received SABM even though channel %d for %s was already closed",						frame->channel, channellist[frame->channel].origin);				channellist[frame->channel].opened = 1;				write_frame(frame->channel, NULL, 0, GSM0710_TYPE_UA | GSM0710_PF);				break;			}		}		destroy_frame(frame);	}	LOG(LOG_DEBUG, "Leave");	return frames_extracted;}/** * Function responsible by all signal handlers treatment * any new signal must be added here */void signal_treatment(	int param){	switch (param)	{	case SIGPIPE:		exit(0);	break;	case SIGHUP://reread the configuration files	break;	case SIGINT:	case SIGTERM:	case SIGUSR1:		//exit(0);//sig_term(param);		g_main_loop_quit(main_loop);	break;	case SIGKILL:	default:		exit(0);	break;	}}static int modem_hw_(const char* pm_base_dir, const char* entry, int on){	LOG(LOG_DEBUG, "Enter");	if (pm_base_dir != NULL)	{		char fn[256];		SYSCHECK(snprintf(fn, sizeof(fn), "%s/%s", pm_base_dir, entry));		LOG(LOG_DEBUG, "echo %c > %s", on?'1':'0', fn);		int fd;		SYSCHECK(fd = open(fn, O_RDWR | O_NONBLOCK));		SYSCHECK(write(fd, on?"1\n":"0\n", 2));		SYSCHECK(close(fd));	}	else		LOG(LOG_DEBUG, "no pm_base_dir");	LOG(LOG_DEBUG, "Leave");	return 0;}static int modem_hw_off(const char* pm_base_dir){	LOG(LOG_DEBUG, "Enter");	SYSCHECK(modem_hw_(pm_base_dir, "power_on", 0));	SYSCHECK(modem_hw_(pm_base_dir, "reset", 0));	LOG(LOG_DEBUG, "Leave");	return 0;}static int modem_hw_on(const char* pm_base_dir){	LOG(LOG_DEBUG, "Enter");	SYSCHECK(modem_hw_off(pm_base_dir));	sleep(1);	SYSCHECK(modem_hw_(pm_base_dir, "power_on", 1));	sleep(1);	SYSCHECK(modem_hw_(pm_base_dir, "reset", 1));	sleep(1);	SYSCHECK(modem_hw_(pm_base_dir, "reset", 0));	sleep(4);	LOG(LOG_DEBUG, "Leave");	return 0;}gboolean serial_device_read(GIOChannel *source, GIOCondition condition, gpointer data){	Serial* serial = (Serial*)data;	LOG(LOG_DEBUG, "Enter");	if (condition == G_IO_IN)	{		switch (serial->state)		{		case MUX_STATE_MUXING:		{			unsigned char buf[4096];			int len;			//input from serial port			LOG(LOG_DEBUG, "Serial Data");			int length;			if ((length = gsm0710_buffer_free(serial->in_buf)) > 0			&& (len = read(serial->fd, buf, min(length, sizeof(buf)))) > 0)			{				syslogdump("<s ", buf, len);				gsm0710_buffer_write(serial->in_buf, buf, len);				//extract and handle ready frames				if (extract_frames(serial->in_buf) > 0)				{					time(&serial->frame_receive_time); //get the current time					serial->ping_number = 0;				}			}			LOG(LOG_DEBUG, "Leave keep watching");			return TRUE;		}		break;		default:			LOG(LOG_WARNING, "Don't know how to handle reading in state %d", serial->state);		break;		}	}	else if (condition == G_IO_HUP)	{		LOG(LOG_WARNING, "hup on serial file, closing");		serial->state = MUX_STATE_CLOSING;					}	LOG(LOG_DEBUG, "Leave stop watching");	return FALSE;}int open_serial_device(	Serial* serial	){	LOG(LOG_DEBUG, "Enter");	SYSCHECK(modem_hw_on(serial->pm_base_dir));	int i;	for (i=0;i<GSM0710_MAX_CHANNELS;i++)		SYSCHECK(logical_channel_init(channellist+i, i));//open the serial port	SYSCHECK(serial->fd = open(serial->devicename, O_RDWR | O_NOCTTY | O_NONBLOCK));	LOG(LOG_INFO, "Opened serial port");	int fdflags;	SYSCHECK(fdflags = fcntl(serial->fd, F_GETFL));	SYSCHECK(fcntl(serial->fd, F_SETFL, fdflags & ~O_NONBLOCK));	struct termios t;	tcgetattr(serial->fd, &t);	t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);	t.c_cflag |= CREAD | CLOCAL | CS8 | CRTSCTS;	t.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG);	t.c_iflag &= ~(INPCK | IGNPAR | PARMRK | ISTRIP | IXANY | ICRNL);	t.c_iflag &= ~(IXON | IXOFF);	t.c_oflag &= ~(OPOST | OCRNL);	t.c_cc[VMIN] = 0;	t.c_cc[VINTR] = _POSIX_VDISABLE;	t.c_cc[VQUIT] = _POSIX_VDISABLE;	t.c_cc[VSTART] = _POSIX_VDISABLE;	t.c_cc[VSTOP] = _POSIX_VDISABLE;	t.c_cc[VSUSP] = _POSIX_VDISABLE;	speed_t speed = baud_bits[cmux_port_speed];	cfsetispeed(&t, speed);	cfsetospeed(&t, speed);	SYSCHECK(tcsetattr(serial->fd, TCSANOW, &t));	int status = TIOCM_DTR | TIOCM_RTS;	ioctl(serial->fd, TIOCMBIS, &status);	LOG(LOG_INFO, "Configured serial device");	serial->ping_number = 0;	time(&serial->frame_receive_time); //get the current time	serial->state = MUX_STATE_INITILIZING;	return 0;}int start_muxer(	Serial* serial	){	LOG(LOG_INFO, "Configuring modem");	char gsm_command[100];	if (chat(serial->fd, "\r\n\r\n\r\nAT\r\n", 1) < 0)	{		LOG(LOG_WARNING, "Modem does not respond to AT commands, trying close mux mode");		//if (cmux_mode) we do not know now so write both			write_frame(0, NULL, 0, GSM0710_CONTROL_CLD | GSM0710_CR);		//else			write_frame(0, close_channel_cmd, 2, GSM0710_TYPE_UIH);		SYSCHECK(chat(serial->fd, "AT\r\n", 1));	}	SYSCHECK(chat(serial->fd, "ATZ\r\n", 3));	SYSCHECK(chat(serial->fd, "ATE0\r\n", 1));	if (0)// additional siemens c35 init	{		SYSCHECK(snprintf(gsm_command, sizeof(gsm_command), "AT+IPR=%d\r\n", baud_rates[cmux_port_speed]));		SYSCHECK(chat(serial->fd, gsm_command, 1));		SYSCHECK(chat(serial->fd, "AT\r\n", 1));		SYSCHECK(chat(serial->fd, "AT&S0\r\n", 1));		SYSCHECK(chat(serial->fd, "AT\\Q3\r\n", 1));	}	//SYSCHECK(chat(serial->fd, "AT+CMUX=?\r\n", 1));	if (pin_code >= 0)	{		LOG(LOG_DEBUG, "send pin %04d", pin_code);//Some modems, such as webbox, will sometimes hang if SIM code//is given in virtual channel		SYSCHECK(snprintf(gsm_command, sizeof(gsm_command), "AT+CPIN=%04d\r\n", pin_code));		SYSCHECK(chat(serial->fd, gsm_command, 10));	}	SYSCHECK(chat(serial->fd, "AT+CFUN=0\r\n", 10));	SYSCHECK(snprintf(gsm_command, sizeof(gsm_command), "AT+CMUX=%d,%d,%d,%d"		//",%d,%d,%d,%d,%d"		"\r\n"		, cmux_mode		, cmux_subset		, cmux_port_speed		, cmux_N1		//, cmux_T1		//, cmux_N2		//, cmux_T2		//, cmux_T3		//, cmux_k		));	LOG(LOG_INFO, "Starting mux mode");	SYSCHECK(chat(serial->fd, gsm_command, 3));	serial->state = MUX_STATE_MUXING;	LOG(LOG_INFO, "Waiting for mux-mode");	sleep(1);	LOG(LOG_INFO, "Init control channel");	write_frame(0, NULL, 0, GSM0710_TYPE_SABM | GSM0710_PF);	GIOChannel* channel = g_io_channel_unix_new(serial->fd);	serial->g_source = g_io_add_watch(channel, G_IO_IN | G_IO_HUP, serial_device_read, serial);	return 0;}static int close_devices(){	LOG(LOG_DEBUG, "Enter");	g_source_remove(serial.g_source);	serial.g_source = -1;	int i;	for (i=1;i<GSM0710_MAX_CHANNELS;i++)	{//terminate command given. Close channels one by one and finaly close//the mux mode		if (channellist[i].fd >= 0)		{			SYSCHECK(dbus_signal_send_deactivate(channellist[i].ptsname));			if (channellist[i].opened)			{				LOG(LOG_INFO, "Closing down the logical channel %d", i);				if (cmux_mode)					write_frame(i, NULL, 0, GSM0710_CONTROL_CLD | GSM0710_CR);//multiplexer close down command doesn't work with benqM22a module, use: write_frame(0, NULL, 0, GSM0710_TYPE_DISC | GSM0710_PF);				else					write_frame(i, close_channel_cmd, 2, GSM0710_TYPE_UIH);				SYSCHECK(logical_channel_close(channellist+i));			}			LOG(LOG_INFO, "Logical channel %d closed", channellist[i].id);		}	}	if (serial.fd >= 0)	{		if (cmux_mode)			write_frame(0, NULL, 0, GSM0710_CONTROL_CLD | GSM0710_CR);		else			write_frame(0, close_channel_cmd, 2, GSM0710_TYPE_UIH);		static const char* poff = "AT@POFF\r\n";		syslogdump(">s ", (unsigned char *)poff, strlen(poff));		write(serial.fd, poff, strlen(poff));		SYSCHECK(close(serial.fd));		serial.fd = -1;	}	SYSCHECK(modem_hw_off(serial.pm_base_dir));	serial.state = MUX_STATE_OFF;	return 0;}static gboolean watchdog(gpointer data){	LOG(LOG_DEBUG, "Enter");	Serial* serial = (Serial*)data;	LOG(LOG_DEBUG, "Serial state is %d", serial->state);	switch (serial->state)	{	case MUX_STATE_OPENING:		if (open_serial_device(serial) < 0)			LOG(LOG_WARNING, "Could not open all devices and start muxer");		serial->g_source_watchdog = g_timeout_add_seconds(5, watchdog, data); // let the dog watch every 5 sec		LOG(LOG_INFO, "Watchdog started");	case MUX_STATE_INITILIZING:		if (start_muxer(serial) < 0)			LOG(LOG_WARNING, "Could not open all devices and start muxer errno=%d", errno);	break;	case MUX_STATE_MUXING:		if (use_ping)		{			if (serial->ping_number > use_ping)			{				LOG(LOG_DEBUG, "no ping reply for %d times, resetting modem", serial->ping_number);				serial->state = MUX_STATE_CLOSING;			}			else			{				LOG(LOG_DEBUG, "Sending PING to the modem");				//write_frame(0, psc_channel_cmd, sizeof(psc_channel_cmd), GSM0710_TYPE_UI);				write_frame(0, test_channel_cmd, sizeof(test_channel_cmd), GSM0710_TYPE_UI);				serial->ping_number++;			}		}		if (use_timeout)		{			time_t current_time;			time(&current_time); //get the current time			if (current_time - serial->frame_receive_time > use_timeout)			{				LOG(LOG_DEBUG, "timeout, resetting modem");				serial->state = MUX_STATE_CLOSING;			}		}	break;	case MUX_STATE_CLOSING:		close_devices();		serial->state = MUX_STATE_OPENING;	break;	default:		LOG(LOG_WARNING, "Don't know how to handle state %d", serial->state);	break;	}	return 1;}/** * shows how to use this program */static int usage(	char *_name){	fprintf(stderr, "\tUsage: %s [options]\n", _name);	fprintf(stderr, "Options:\n");	// process control	fprintf(stderr, "\t-d: Fork, get a daemon [%s]\n", no_daemon?"no":"yes");	fprintf(stderr, "\t-v: verbose logging\n");	// modem control	fprintf(stderr, "\t-s <serial port name>: Serial port device to connect to [%s]\n", serial.devicename);	fprintf(stderr, "\t-t <timeout>: reset modem after this number of seconds of silence [%d]\n", use_timeout);	fprintf(stderr, "\t-P <pin-code>: PIN code to unlock SIM [%d]\n", pin_code);	fprintf(stderr, "\t-p <number>: use ping and reset modem after this number of unanswered pings [%d]\n", use_ping);	fprintf(stderr, "\t-x <dir>: power managment base dir [%s]\n", serial.pm_base_dir?serial.pm_base_dir:"<not set>");	// legacy - will be removed	fprintf(stderr, "\t-b <baudrate>: mode baudrate [%d]\n", baud_rates[cmux_port_speed]);	fprintf(stderr, "\t-m <modem>: Mode (basic, advanced) [%s]\n", cmux_mode?"advanced":"basic");	fprintf(stderr, "\t-f <framsize>: Frame size [%d]\n", cmux_N1);	//	fprintf(stderr, "\t-h: Show this help message and show current settings.\n");	return -1;}/** * The main program */int main(	int argc,	char *argv[],	char *env[]){	LOG(LOG_DEBUG, "Enter");	int opt;	pid_t parent_pid;//for fault tolerance	serial.devicename = "/dev/ttySAC0";	while ((opt = getopt(argc, argv, "dvs:t:p:f:h?m:b:P:x:")) > 0)	{		switch (opt)		{		case 'v':			syslog_level++;			break;		case 'd':			no_daemon = !no_daemon;			break;		case 'x':			serial.pm_base_dir = optarg;			break;		case 's':			serial.devicename = optarg;			break;		case 't':			use_timeout = atoi(optarg);			break;		case 'p':			use_ping = atoi(optarg);			break;		case 'P':			pin_code = atoi(optarg);			break;		// will be removed if +CMUX? works		case 'f':			cmux_N1 = atoi(optarg);			break;		case 'm':			if (!strcmp(optarg, "basic"))				cmux_mode = 0;			else if (!strcmp(optarg, "advanced"))				cmux_mode = 1;			else				cmux_mode = 0;			break;		case 'b':			cmux_port_speed = baud_rate_index(atoi(optarg));			break;		default:		case '?':		case 'h':			usage(argv[0]);			exit(0);			break;		}	}	if (serial.pm_base_dir == NULL)	{		// auto detect - i hate windows-like-behavior but mickey want's it ;)		struct stat sb;		int i;		static char* fn[] = {			"/sys/bus/platform/devices/neo1973-pm-gsm.0",			"/sys/bus/platform/devices/gta01-pm-gsm.0",			NULL			};		for (i=0;fn[i];i++)			if (stat(fn[i], &sb) >= 0)			{				serial.pm_base_dir = fn[i];				LOG(LOG_INFO, "using '%s' as basedir for pm", fn[i]);				break;			}	}//daemonize show time	parent_pid = getpid();	if (!no_daemon && daemon(0, 0))	{		fprintf(stderr, "Failed to daemonize: %s (%d)", strerror(errno), errno);		exit(1);	}	umask(0);//signals treatment	signal(SIGHUP, signal_treatment);	signal(SIGPIPE, signal_treatment);	signal(SIGKILL, signal_treatment);	signal(SIGINT, signal_treatment);	signal(SIGUSR1, signal_treatment);	signal(SIGTERM, signal_treatment);	if (no_daemon)		openlog(argv[0], LOG_NDELAY | LOG_PID | LOG_PERROR, LOG_LOCAL0);	else		openlog(argv[0], LOG_NDELAY | LOG_PID, LOG_LOCAL0);	SYSCHECK(dbus_init());//allocate memory for data structures	if ((serial.in_buf = gsm0710_buffer_init()) == NULL	 || (serial.adv_frame_buf = (unsigned char*)malloc((cmux_N1 + 3) * 2 + 2)) == NULL)	{		LOG(LOG_ALERT, "Out of memory");		exit(-1);	}	LOG(LOG_DEBUG, "%s %s starting", *argv, revision);//Initialize modem and virtual ports	serial.state = MUX_STATE_OPENING;	watchdog(&serial);//start waiting for input and forwarding it back and forth --	main_loop = g_main_loop_new(NULL, FALSE);	g_main_loop_run(main_loop); // will/may be terminated in signal_treatment	g_main_loop_unref(main_loop);//finalize everything	SYSCHECK(close_devices());	free(serial.adv_frame_buf);	gsm0710_buffer_destroy(serial.in_buf);	LOG(LOG_INFO, "Received %ld frames and dropped %ld received frames during the mux-mode",		serial.in_buf->received_count, serial.in_buf->dropped_count);	SYSCHECK(dbus_deinit());	LOG(LOG_DEBUG, "%s finished", argv[0]);	closelog();// close syslog	return 0;}// vim:path=/usr/include,/usr/include/glib-2.0,/usr/include/dbus-1.0,src:

⌨️ 快捷键说明

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