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

📄 modemutil.c

📁 VoiFax is a program that manage voice/data/fax modem in the same manner of vgetty and mgetty.VoiFax
💻 C
字号:
/*  voifax low level modem interface library *  Copyright (C) 2004  Simone Freddio & Andrea Emanuelli * *  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 */#include "modemutil.h"#include "common.h"#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <sys/select.h>#include <termios.h>#include <stdio.h>#include <stdlib.h>#include "util.h"#include "libconfig.h"/* Local prototypes *//* Chiama le callbacks associate per i dati contenuti in un buffer */int call_handlers(t_modem *modem, char *buf, int size);int search_free_handler(t_modem *modem);int from_num_to_bps(int num);/* Local functions */int call_handlers(t_modem *modem, char *buf, int size){	char module[] = "call_handlers";	int a = 0;	int c = 0;	char args[100];	/* Scorrimento buffer dati */	for (c = 0; c < size; c++)	{		/* Controllo per ogni handler installato */		for (a = 0; a < MODEM_MAX_HANDLERS; a++)		{			/* Controllo se l'handler attuale e' attivo */			if (modem->handlers[a].str[0] != 0 &&					modem->handlers[a].callback != NULL)			{				/* Check fine buffer */				if (c + modem->handlers[a].len < size)				{					/* Confronto chiave */					if(!memcmp(&buf[c],											modem->handlers[a].str, 											modem->handlers[a].len))					{						/* La chiave e' contenuta nel buffer di ricezione */						memset(args, 0, sizeof(args));						memmove(args, 										&buf[c + modem->handlers[a].len], 										modem->handlers[a].arg_chars);						/* Verifica il caso in cui è un falso <DLE> */						if (buf[c] == 0x10 && buf[c + 1] == 0x10)						{							/* Nel qual caso, salta il successivo carattere dall'analisi */							c++;						}						else						{							/* Altrimenti esegui la callback */							if (!modem->handlers[a].callback(args))							{								TRC(TRC_ERR, module, "Event handler failed!");								return false;							}						}					}				}/*				else					TRC("Last buffer characters = EVENT!!!");*/			}		}	}	return true;}int search_free_handler(t_modem *modem){	int a = 0;	for (a = 0; a < MODEM_MAX_HANDLERS; a++)	{		if (modem->handlers[a].str[0] == 0 &&				modem->handlers[a].callback == NULL)		{			return a;		}	}	return -1;}#define BPS_MATCH(num) case num: return B##num; break;int from_num_to_bps(int num){	switch (num)	{		BPS_MATCH(50);		BPS_MATCH(75);		BPS_MATCH(110);		BPS_MATCH(134);		BPS_MATCH(150);		BPS_MATCH(200);		BPS_MATCH(300);		BPS_MATCH(600);		BPS_MATCH(1200);		BPS_MATCH(1800);		BPS_MATCH(2400);		BPS_MATCH(4800);		BPS_MATCH(9600);		BPS_MATCH(19200);		BPS_MATCH(38400);		BPS_MATCH(57600);		BPS_MATCH(115200);		BPS_MATCH(230400);		BPS_MATCH(460800);		BPS_MATCH(500000);		BPS_MATCH(576000);		BPS_MATCH(921600);		BPS_MATCH(1000000);		BPS_MATCH(1152000);		BPS_MATCH(1500000);		BPS_MATCH(2000000);		BPS_MATCH(2500000);		BPS_MATCH(3000000);		BPS_MATCH(3500000);		BPS_MATCH(4000000);		default:			return -1;	}}#undef BPS_MATCH/* Exported functions */int modem_init(t_modem *modem, char *dev){	char module[] = "modem_init";	char whole_dev[100];	char trc[300];  struct termios new_term;  struct termios old_term;	int ret;	sprintf(whole_dev,					"%s/%s", 					libconfig_getvalue(dev, "device_path", "/dev"), 					dev);	/* Apertura device di lettura*/		modem->r_fd = open(whole_dev, O_RDONLY | O_NONBLOCK | O_NOCTTY, 0);	if (modem->r_fd == -1)	{		TRC(TRC_ERR, module, "Unable to open serial device (read)");		return false;	}	modem->w_fd = open(libconfig_getvalue(dev, "write_dev", whole_dev), 											O_WRONLY | O_NONBLOCK | O_NOCTTY, 0);	if (modem->w_fd == -1)	{		TRC(TRC_ERR, module, "Unable to open serial device (read)");		return false;	}		/* Impostazione dati di configurazione */	strcpy(modem->dev, dev);	strcpy(modem->full_dev, whole_dev);	modem->seek_end = atoi(libconfig_getvalue(dev, "seek_end", "0"));	modem->retries = atoi(libconfig_getvalue(dev, "retries", "10"));	modem->response_timeout.tv_sec = 											atoi(libconfig_getvalue(dev, "timeout_sec", "0"));	modem->response_timeout.tv_usec = 											atoi(libconfig_getvalue(dev, "timeout_usec", "100000"));	modem->response_initialsleep = 0;	modem->baudrate = atoi(libconfig_getvalue(dev, "baudrate", "115200"));	modem->baudrate_const = from_num_to_bps(modem->baudrate);				memset(modem->handlers, 0, sizeof(modem->handlers));	sprintf(trc, "Timeouts: sec %d, usec %d, retries %d", 					(int)modem->response_timeout.tv_sec,					(int)modem->response_timeout.tv_usec,					modem->retries);	TRC(TRC_INFO, module, trc);	if (strcmp(				libconfig_getvalue(dev, "skip_serial_init", "0"),				"1") == 0)	{		TRC(TRC_WARN, module, "Skipping serial init...");		return true;	}	/* TODO:	Controllare le seguenti impostazioni della seriale!		 				Quelle che ci sono adesso le ho copiate da un frammento di codice						di un programma che comunica via seriale e che funziona :)))	 */	/* Parte di inizializzazione porta seriale */	ret=tcgetattr(modem->r_fd, &old_term);	if( ret== -1 )	{		TRC(TRC_ERR, module, "Error on getattr");		return false;	}		memset((void *)&new_term, '\0', sizeof(new_term));	new_term.c_cflag = CS8 | CLOCAL | CREAD | CRTSCTS;	new_term.c_iflag = 0;	new_term.c_lflag = 0;	new_term.c_oflag = 0;	new_term.c_cc[VINTR] = 0;	new_term.c_cc[VMIN] = 1;	new_term.c_cc[VTIME] = 0;	sprintf(trc, "Port %s baudrate: %d", dev, modem->baudrate);	TRC(TRC_INFO, module, trc);		ret = cfsetospeed(&new_term, modem->baudrate_const);	if (ret == -1)	{		TRC(TRC_ERR, module, "Failed cfsetospeed");		return false;	}                                			ret = cfsetispeed(&new_term, modem->baudrate_const);	if (ret == -1)	{		TRC(TRC_ERR, module, "Failed cfsetispeed");		return false;	}                                		ret = tcsetattr(modem->r_fd, TCSANOW, &new_term);	if (ret == -1)	{		TRC(TRC_ERR, module, "Failed tcsetattr");		return false;	}	return true;}int modem_close(t_modem *modem){	char module[] = "modem_close";	int ret;		ret = close(modem->r_fd);	if (ret == -1)	{		TRC(TRC_ERR, module, "Unable to close device (read)");		return false;	}	ret = close(modem->w_fd);	if (ret == -1)	{		TRC(TRC_ERR, module, "Unable to close device (write)");		return false;	}	memset(modem, 0, sizeof(t_modem));	return true;}int modem_sendcmd(t_modem *modem, char *cmd){	char module[] = "modem_sendcmd";	int bytes, len;	char cmd_to_send[100];	/* Aggiunta \n alla stringa */	sprintf(cmd_to_send, "%s\r", cmd);	len = strlen(cmd_to_send);/*	if (modem->seek_end)		lseek(modem->fd, 0, SEEK_END);*/	bytes = write(modem->w_fd, cmd_to_send, len);	if (bytes == -1)	{		TRC(TRC_ERR, module, "Write error on fd");		return false;	}	if (bytes != len)	{		TRC(TRC_ERR, module, "Communication broken");		return false;	}	return true;}int modem_receiveresp(t_modem *modem, char *buf, int maxlen, int clean_resp){	char module[] = "modem_receiveresp";	struct timeval tv;	fd_set set;	int retsel = 1, bytes = 0, totread = 0;	/*TRC(TRC_INFO, module, "Start");*/	memset(buf, 0, maxlen);	while (retsel > 0 && totread < maxlen)	{		/* Delay iniziale per l'attesa dati */		usleep(modem->response_initialsleep);				FD_ZERO(&set);		FD_SET(modem->r_fd, &set);		memcpy(&tv, &modem->response_timeout, sizeof(tv));		/* Attesa dati in coda (esce con timeout */		retsel = select(modem->r_fd + 1, &set, NULL, NULL, &tv);		if (retsel > 0)		{			if (FD_ISSET(modem->r_fd, &set))			{				/* Dati ricevuti, lettura dalla porta */				bytes = read(modem->r_fd, &buf[totread], maxlen - totread);				/*TRC(TRC_INFO, module, buf);*/				if (bytes != 0)				{					/* Verifica e chiamata handlers */					if (!call_handlers(modem, &buf[totread], bytes))					{						TRC(TRC_ERR, module, "Failed handler!");						return -1;					}				}				else					retsel = 0;										totread += bytes;			}			else			{				TRC(TRC_ERR, module, "Fd mismatch?");				return -1;			}		}	}	/*TRC(TRC_INFO, module, "End");*/	if (retsel < 0)	{		TRC(TRC_ERR, module, "Error on select!");		return -1;	}	if (clean_resp)	{		remove_special_chars(buf);	}	return totread;}int modem_chat(t_modem *modem, char *cmd, char *resp){	char module[] = "modem_chat";	char curr_resp[200];	int readed;	char trc[300];	int found = false, timeout = modem->retries;		sprintf(trc, "Command to send: '%s'", cmd);	TRC(TRC_INFO, module, trc);	if (!modem_sendcmd(modem, cmd))	{		TRC(TRC_ERR, module, "Chat send failed");		return -1;	}	if (strlen(resp) != 0)	{		while (found == false && timeout != 0)		{			readed = modem_receiveresp(modem, curr_resp, sizeof(curr_resp), true);			if (readed == -1)			{				TRC(TRC_ERR, module, "Chat receiveresp failed");				return -1;			}			if (readed < (int)sizeof(curr_resp))				timeout--;			sprintf(trc, "Response received: '%s', %d", curr_resp, readed);			TRC(TRC_INFO, module, trc);			found = memory_search(curr_resp, readed, resp, strlen(resp)) == -1 							? false : true;			sprintf(trc, "Response compare: '%s', %d", 							found ? "true" : "false", timeout);			TRC(TRC_INFO, module, trc);		}	}	return found;}int modem_chat_timeout(t_modem *modem, char *cmd, char *resp, int sec, int usec){	int o_sec = modem->response_timeout.tv_sec;	int o_usec = modem->response_timeout.tv_usec;	int ret;		modem->response_timeout.tv_sec = sec;	modem->response_timeout.tv_usec = usec;		ret = modem_chat(modem, cmd, resp);		modem->response_timeout.tv_sec = o_sec;	modem->response_timeout.tv_usec = o_usec;	return ret;}int modem_add_handler(t_modem			*modem,											t_callback	*callback,											char				*str,											int					chars_to_get){	char module[] = "modem_add_handler";	int hndl = search_free_handler(modem);	if (hndl == -1)	{		TRC(TRC_ERR, module, "No free handlers!");		return false;	}	strcpy(modem->handlers[hndl].str, str);	modem->handlers[hndl].callback = callback;	modem->handlers[hndl].len = strlen(str);	modem->handlers[hndl].arg_chars = chars_to_get;	return true;}int modem_remove_handler(t_modem *modem, t_callback *callback){	int a = 0;	for (a = 0; a < MODEM_MAX_HANDLERS; a++)	{		if (modem->handlers[a].callback == callback)		{			memset(&modem->handlers[a], 0, sizeof(modem->handlers[a]));			return true;		}	}	return false;}

⌨️ 快捷键说明

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