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

📄 libvoice.c

📁 VoiFax is a program that manage voice/data/fax modem in the same manner of vgetty and mgetty.VoiFax
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  voifax general voice functions 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 <stdio.h>
#include <time.h>
#include <asm/ioctls.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "util.h"
#include "common.h"
#include "libvoice.h"
#include "libevent.h"
#include "modemutil.h"
#include "libconfig.h"

#define MAXCMDSIZE 256
#define MAXCMDNUMBER 500
#define CHUNKSIZE  1024

#define ST_VOICE			8
#define ST_DATA				0
#define ST_FAX1				1
#define ST_FAX2				2
#define ST_VOICE_PLAYING	ST_VOICE + 1
#define ST_VOICE_RECORDING	ST_VOICE + 2

int libvoice_status;
int libvoice_rings;
time_t libvoice_lastring;

char libvoice_device[100];

t_modem modem;

typedef struct {
	int used;
	char cmdname[MAXCMDSIZE];
	char cmd[MAXCMDSIZE];
	char rsp[MAXCMDSIZE];
} t_cmd;

t_cmd voicecmd[MAXCMDNUMBER];

/* Prototipi locali */
int libvoice_getconfig(char *device);
/*int libvoice_sendcmdwithargs(char *cmdname, int argc, char **argv);*/
void libvoice_insertcmd(char *cmdname, char *cmdstring, char *rspstring);
void libvoice_extractstring(char *instring, char *outstring);
void libvoice_replacespecialchar(char *instring, char *outstring);
int libvoice_hextoint(char *instring);
int libvoice_shielded_handler(char *param);
int libvoice_vcon_handler(char *param);
int libvoice_connect_handler(char *param);
int libvoice_ring_handler(char *param);
void virtual_ring_handler(int sig);

int libvoice_sendcmdwithargs(char *cmdname, int argc, char **argv)
{
	int argcounter, cmdindex;
	char cmdtosend[MAXCMDSIZE];
	char *cmdcopy;
	int ret;
	char *argpos;
	
	/* Il formato dei parametri DEVE essere del tipo AT+VTS=[$$,0,$$].
		I parametri all'interno del vettore argv verranno sostituiti
		all'interno del comando in modo sequenziale */
	
	argcounter = 0; ret = true;

	for (cmdindex = 0; cmdindex < MAXCMDNUMBER; cmdindex++)
	{
		if (strcmp(voicecmd[cmdindex].cmdname, cmdname) == 0)
		{
			argpos = 0;
			memset(cmdtosend, 0, MAXCMDSIZE - 1);
			cmdcopy = &voicecmd[cmdindex].cmd[0];
			while ((argpos = strstr(cmdcopy, "$$")) != NULL)
			{
				strncat(cmdtosend, cmdcopy, argpos - cmdcopy);
				strcat(cmdtosend, argv[argcounter]);
				argcounter++;
				cmdcopy = argpos + 2;
			}
			strcat(cmdtosend, cmdcopy);
			if (cmdtosend[0] == '$')
				ret &= libvoice_sendcmd(&cmdtosend[1]);
			else
				ret &= modem_chat(&modem, cmdtosend, voicecmd[cmdindex].rsp);
		}
	}

	if (argcounter - 1 > argc)
	{
		TRC(TRC_WARN, "libvoice_sendcmdwithargs", "not enough argv in vector!!!");
		return false;
	}

	return ret;
	
}

int libvoice_hextoint(char *instring)
{
int value;
	if (strlen(instring)!=2)
	{
		TRC(TRC_WARN, "hextoint", "impossibile convertire stringa di lunghezza diversa da 2!!!");
		return 0;
	}
	value = 0;
	if ((instring[0] > '0') && (instring[0] < '9'))
	{
		value += ((int)(instring[0]) - (int)('0')) * 16;
	}
	if ((instring[0] > 'A') && (instring[0] < 'F'))
	{
		value += ((int)(instring[0]) - (int)('A') + 10) * 16;
	}
	if ((instring[0] > 'a') && (instring[0] < 'f'))
	{
		value += ((int)(instring[0]) - (int)('a') + 10) * 16;
	}
	if ((instring[1] > '0') && (instring[1] < '9'))
	{
		value += ((int)(instring[1]) - (int)('0'));
	}
	if ((instring[1] > 'A') && (instring[1] < 'F'))
	{
		value += ((int)(instring[1]) - (int)('A') + 10);
	}
	if ((instring[1] > 'a') && (instring[1] < 'f'))
	{
		value += ((int)(instring[1]) - (int)('a') + 10);
	}
	return value;
}

void libvoice_replacespecialchar(char *instring, char *outstring)
{
	char *tmp, *tmpref, *tok;
	char value[2];
	
	tmp = (char *)malloc(strlen(instring) + 1);
	tmpref = tmp;
	strcpy(tmp, instring);
	outstring[0] = '\0';

	while (tmp!=NULL)
	{
		tok = strsep(&tmp, "<>");
		if ((strcasecmp(tok, "cr")!=0) && (strcasecmp(tok, "lf")!=0))
		{
			if (tok[0]=='h')
			{
				value[0] = (char)libvoice_hextoint(&tok[1]);
				value[1] = 0;
				strcat(outstring, value);	
			}
			else
			strcat(outstring, tok);
		}
	}

	free(tmpref);
}

void libvoice_extractstring(char *instring, char *outstring)
{
char *tmp, *tmp1, *tmpref;
	tmp = (char *)malloc(1024);
	tmp1 = (char *)malloc(1024);
	tmpref = tmp;
	
	strcpy(tmp, instring);
	strsep(&tmp, "\"");
	strcpy(tmp1, strsep(&tmp, "\""));
	
	libvoice_replacespecialchar(tmp1, outstring);
	
	free(tmpref);
	free(tmp1);
}



int libvoice_sendcmd(char *cmdname)
{
int res,i;

	res = true;
	i = 0;

	TRC(TRC_INFO, "libvoice_sendcmd", cmdname);
	
	for (i = 0; i < MAXCMDNUMBER; i++)
	{
		if (voicecmd[i].used == 1 && strcmp(cmdname, voicecmd[i].cmdname)==0)
		{
			if (voicecmd[i].cmd[0] == '$')	
				res &= libvoice_sendcmd(&voicecmd[i].cmd[1]);
			else
				res &= modem_chat(&modem, voicecmd[i].cmd, voicecmd[i].rsp);
		}
	}
	return res;
}

void libvoice_insertcmd(char *cmdname, char *cmdstring, char *rspstring)
{
int	i;
char dummy[1024];

	i = 0;
	while (voicecmd[i].used != 0) i++;
	if (i<MAXCMDNUMBER)
	{
		strcpy(voicecmd[i].cmdname, cmdname);
		libvoice_replacespecialchar(cmdstring, voicecmd[i].cmd);
		libvoice_replacespecialchar(rspstring, voicecmd[i].rsp);
		sprintf(dummy, "Inserting command: %s cmd:%s rsp:%s", cmdname,voicecmd[i].cmd,voicecmd[i].rsp);
		TRC(TRC_INFO, "libvoice_insert_cmd", dummy);
		voicecmd[i].used = 1;
	}
	else TRC(TRC_WARN, "libvoice_insertcmd", "Impossibile inserire il comando nell'elenco, e' stato raggiunto il massimo!");
}

int libvoice_getconfig(char *device)
{
char module[] = "libvoice_getconfig";
char *buffer;
char *modeminf;
FILE *voicefd;
char args[3][MAXCMDSIZE]; 
int argc;
	
	modeminf = libconfig_getvalue(device, "driver", "generic.inf");

	TRC(TRC_INFO, module, "apertura del file di configurazione");
	
	voicefd = fopen(modeminf, "r");
	if (voicefd!=NULL)
	{
		buffer = (char *)malloc(1024);
		while (!feof(voicefd))
		{
			fgets(buffer, 1024, voicefd);
			if (buffer[0]!=';' && buffer[0]!='#' && strlen(buffer)>1)
			{
				memset(args, 0, sizeof(args));
				argc = sscanf(buffer, "%s %s %s", args[0], args[1], args[2]);
				
				TRC(TRC_INFO, module, "Command Detected");	
				libvoice_insertcmd(args[0], args[1], args[2]);

				if (argc<2 || argc>3)
				{
					TRC(TRC_WARN, module, "malformed line in");
					TRC(TRC_WARN, module, modeminf);
				}
				
			}
		}
		fclose(voicefd);
		free(buffer);	
	}
	else
	{
		TRC(TRC_ERR, module, "Impossibile trovare il file indicato per la porta specificata");
		return false;
	}

	return true;
}

int libvoice_init(char *device)
{
char module[] = "libvoice_init";
int res;
char resp[100];

	/*Lettura file di configurazione*/
	TRC(TRC_INFO, module, "Lettura del file di configurazione");
	if (libvoice_getconfig(device)==false)
		return false;

	/*Inizializzazione della libreria del modem*/
	TRC(TRC_INFO, module, "Inizializzazione libreria modem");
	if (modem_init(&modem, device)!=true)
	{
		TRC(TRC_ERR, module, "Impossibile inizializzare la libreria modem!");
		return false;
	}

	/*Effettua una prima verifica per determinare se il modem
	supporta le funzionalita' voice.*/
	TRC(TRC_INFO, module, "Verifica presenza modem");
	modem_sendcmd(&modem, "AT&F");
	modem_receiveresp(&modem, resp, sizeof(resp), false);
			
	if (modem_chat(&modem, "ATE0","ATE0OK")!=true)
	{
		TRC(TRC_ERR, module, "AT --> ERROR");
		TRC(TRC_ERR, module, "Impossibile inizializzare il modem");
		return false;
	}

	TRC(TRC_INFO, module, "Verifica funzionalita' voce");

	res = libvoice_sendcmd("VoiceMode");
	
	if (res==false)
	{
		TRC(TRC_ERR, module, "Il modem non supporta le funzionalita' voce!!!");
		return false;
	}

	libvoice_status = ST_VOICE;
	libvoice_rings = atoi(libconfig_getvalue(device, "rings", "1"));
	
	TRC(TRC_INFO, module, "Funzionalita' voce supportate");

	TRC(TRC_INFO, module, "Registering shielded events to modemutil");
	modem_add_handler(&modem, libvoice_shielded_handler, "\x10", 1);

/*	TRC(TRC_INFO, module, "Registering VCON events to modemutil");
	modem_add_handler(&modem, libvoice_vcon_handler, "VCON", 0);*/

/*	TRC(TRC_INFO, module, "Registering CONNECT events to modemutil");
	modem_add_handler(&modem, libvoice_connect_handler, "CONNECT", 1);*/

	TRC(TRC_INFO, module, "Registering RING events to modemutil");
	modem_add_handler(&modem, libvoice_ring_handler, "RING", 1);

	TRC(TRC_INFO, module, "Registering SIGUSR1 event and Mapping to Virtual Ring");
	if (signal(SIGUSR1, virtual_ring_handler)==SIG_ERR)
	{
		TRC(TRC_WARN, module, "Registering SIGUSR1 failed, virtual ring disabled");
	}
	
	strcpy(libvoice_device, device);

	libvoice_sendcmd("Init");
	
	return true;
}

void virtual_ring_handler(int sig)
{
	sig = sig;
	TRC(TRC_INFO, "virtual_ring_handler", "Virtual ring detected");
	libevent_process_event("LV_RINGING");
}

int libvoice_shielded_handler(char *param)
{
	char message[100];
	/* solo per sicurezza controlla che il primo parametro sia DLE */
	switch (param[0])
	{
		case '\x3':									/* end of stream */
			libevent_process_event("LV_READY");
			if (libvoice_status==ST_VOICE_PLAYING ||
					libvoice_status==ST_VOICE_RECORDING)
				libvoice_status = ST_VOICE;
			break;
		case '*':
			libevent_process_event("LV_DTMF *");
			break;
		case '#':

⌨️ 快捷键说明

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