📄 libvoice.c
字号:
/* 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 + -