- Fixed call-deflection and moved this feature from separate application
to capicommand().V0_6
parent
5ea11118df
commit
8f8b5bd30c
7
INSTALL
7
INSTALL
|
@ -4,17 +4,14 @@ INSTALL
|
|||
Modify the Makefile to fit your system, especially the path to the Asterisk
|
||||
include files.
|
||||
|
||||
Currently there are some buildtime configuration parameters:
|
||||
- You can switch to Ulaw.
|
||||
|
||||
To build the driver you will need an installed capi system, including header
|
||||
files.
|
||||
|
||||
To build the channel driver type:
|
||||
To build the channel driver:
|
||||
---------------------------------
|
||||
make
|
||||
|
||||
To install type:
|
||||
To install:
|
||||
----------------
|
||||
make install
|
||||
|
||||
|
|
2
Makefile
2
Makefile
|
@ -42,7 +42,7 @@ LIBS=-ldl -lpthread -lm
|
|||
CC=gcc
|
||||
INSTALL=install
|
||||
|
||||
SHAREDOS=chan_capi.so app_capiCD.so app_capiHOLD.so app_capiRETRIEVE.so \
|
||||
SHAREDOS=chan_capi.so app_capiHOLD.so app_capiRETRIEVE.so \
|
||||
app_capiECT.so app_capiMCID.so app_capiNoES.so app_capiFax.so
|
||||
|
||||
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
||||
|
|
19
README
19
README
|
@ -92,16 +92,21 @@ The Dial string
|
|||
capi.conf has been removed. The callerID is also taken from the calling channel.
|
||||
|
||||
|
||||
CAPI command application
|
||||
========================
|
||||
chan_capi provides an additional Asterisk application
|
||||
capicommand()
|
||||
With this application, special capi commands and features can be used.
|
||||
|
||||
Call Deflection:
|
||||
Forwards an unanswered call to another number.
|
||||
Example:
|
||||
exten => s,1,capicommand(deflect|12345678)
|
||||
|
||||
|
||||
Helper applications
|
||||
===================
|
||||
Kapejod says: "No No No, don't use those yet....!" (except maybe HOLD,ECT...)
|
||||
|
||||
app_capiCD.c
|
||||
Forwards an unanswered call to another phone (does not rely on sservice CD)
|
||||
Example:
|
||||
exten => s,1,Wait,1
|
||||
exten => s,2,capiCD,12345678
|
||||
|
||||
app_capiHOLD.c
|
||||
Puts an answered call on hold, this has nothing to do with asterisk's onhold
|
||||
thingie (music et al)
|
||||
|
|
186
app_capiCD.c
186
app_capiCD.c
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
* (CAPI*)
|
||||
*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Call Deflection, inspired by capircvd by Alexander Brickwedde
|
||||
*
|
||||
* Copyright (C) 2005 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* Reworked, but based on the work of
|
||||
* Copyright (C) 2002-2005 Junghanns.NET GmbH
|
||||
*
|
||||
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#ifndef CC_AST_HAVE_TECH_PVT
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#endif
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <capi20.h>
|
||||
#include "chan_capi_pvt.h"
|
||||
#include "chan_capi_app.h"
|
||||
|
||||
|
||||
static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
|
||||
static char *app = "capiCD";
|
||||
static char *synopsis = "call deflection";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int capiCD_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
|
||||
MESSAGE_EXCHANGE_ERROR Info;
|
||||
_cmsg CMSG;
|
||||
char bchaninfo[1];
|
||||
char fac[60];
|
||||
int res = 0;
|
||||
int ms = 3000;
|
||||
struct localuser *u;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Do our thing here */
|
||||
|
||||
if ((i->state == CAPI_STATE_CONNECTED) ||
|
||||
(i->state == CAPI_STATE_BCONNECTED)) {
|
||||
ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wait until the channel is alerting, so we dont drop the call and interfer with msgs */
|
||||
while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
|
||||
sleep(100);
|
||||
ms -= 100;
|
||||
}
|
||||
|
||||
/* make sure we hang up correctly */
|
||||
i->state = CAPI_STATE_CONNECTPENDING;
|
||||
|
||||
fac[0] = 0; /* len */
|
||||
fac[1] = 0; /* len */
|
||||
fac[2] = 0x01; /* Use D-Chan */
|
||||
fac[3] = 0; /* Keypad len */
|
||||
fac[4] = 31; /* user user data? len = 31 = 29 + 2 */
|
||||
fac[5] = 0x1c; /* magic? */
|
||||
fac[6] = 0x1d; /* strlen destination + 18 = 29 */
|
||||
fac[7] = 0x91; /* .. */
|
||||
fac[8] = 0xA1;
|
||||
fac[9] = 0x1A; /* strlen destination + 15 = 26 */
|
||||
fac[10] = 0x02;
|
||||
fac[11] = 0x01;
|
||||
fac[12] = 0x70;
|
||||
fac[13] = 0x02;
|
||||
fac[14] = 0x01;
|
||||
fac[15] = 0x0d;
|
||||
fac[16] = 0x30;
|
||||
fac[17] = 0x12; /* strlen destination + 7 = 18 */
|
||||
fac[18] = 0x30; /* ...hm 0x30 */
|
||||
fac[19] = 0x0d; /* strlen destination + 2 */
|
||||
fac[20] = 0x80; /* CLIP */
|
||||
fac[21] = 0x0b; /* strlen destination */
|
||||
fac[22] = 0x01; /* destination start */
|
||||
fac[23] = 0x01; /* */
|
||||
fac[24] = 0x01; /* */
|
||||
fac[25] = 0x01; /* */
|
||||
fac[26] = 0x01; /* */
|
||||
fac[27] = 0x01; /* */
|
||||
fac[28] = 0x01; /* */
|
||||
fac[29] = 0x01; /* */
|
||||
fac[30] = 0x01; /* */
|
||||
fac[31] = 0x01; /* */
|
||||
fac[32] = 0x01; /* */
|
||||
fac[33] = 0x01; /* 0x01 = sending complete */
|
||||
fac[34] = 0x01;
|
||||
fac[35] = 0x01;
|
||||
|
||||
memcpy((unsigned char *)fac + 22, data, strlen(data));
|
||||
|
||||
fac[22 + strlen(data)] = 0x01; /* fill with 0x01 if number is only 6 numbers (local call) */
|
||||
fac[23 + strlen(data)] = 0x01;
|
||||
fac[24 + strlen(data)] = 0x01;
|
||||
fac[25 + strlen(data)] = 0x01;
|
||||
fac[26 + strlen(data)] = 0x01;
|
||||
|
||||
fac[6] = 18 + strlen(data);
|
||||
fac[9] = 15 + strlen(data);
|
||||
fac[17] = 7 + strlen(data);
|
||||
fac[19] = 2 + strlen(data);
|
||||
fac[21] = strlen(data);
|
||||
|
||||
bchaninfo[0] = 0x1;
|
||||
|
||||
INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
|
||||
INFO_REQ_CONTROLLER(&CMSG) = i->controller;
|
||||
INFO_REQ_PLCI(&CMSG) = i->PLCI;
|
||||
INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; /* use D-Channel */
|
||||
INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
|
||||
INFO_REQ_USERUSERDATA(&CMSG) = 0;
|
||||
INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*)fac + 4;
|
||||
|
||||
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
|
||||
res = (int)Info;
|
||||
} else {
|
||||
if (capidebug) {
|
||||
ast_log(LOG_NOTICE, "sent INFO_REQ PLCI = %#x\n",
|
||||
i->PLCI);
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, capiCD_exec, synopsis, tdesc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
206
chan_capi.c
206
chan_capi.c
|
@ -534,107 +534,6 @@ static int capi_alert(struct ast_channel *c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* deflect a call
|
||||
*/
|
||||
static int capi_deflect(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(chan);
|
||||
MESSAGE_EXCHANGE_ERROR Info;
|
||||
_cmsg CMSG;
|
||||
char bchaninfo[1];
|
||||
char fac[60];
|
||||
int res = 0;
|
||||
int ms = 3000;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "%s: CD requires an argument (destination phone number)\n",
|
||||
i->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
|
||||
ast_log(LOG_ERROR, "%s: call deflection does not work with calls that are already connected!\n",
|
||||
i->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wait until the channel is alerting, so we dont drop the call and interfer with msgs */
|
||||
while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
|
||||
sleep(100);
|
||||
ms -= 100;
|
||||
}
|
||||
|
||||
/* make sure we hang up correctly */
|
||||
i->state = CAPI_STATE_CONNECTPENDING;
|
||||
|
||||
fac[0] = 0; /* len */
|
||||
fac[1] = 0; /* len */
|
||||
fac[2] = 0x01; /* Use D-Chan */
|
||||
fac[3] = 0; /* Keypad len */
|
||||
fac[4] = 31; /* user user data? len = 31 = 29 + 2 */
|
||||
fac[5] = 0x1c; /* magic? */
|
||||
fac[6] = 0x1d; /* strlen destination + 18 = 29 */
|
||||
fac[7] = 0x91; /* .. */
|
||||
fac[8] = 0xA1;
|
||||
fac[9] = 0x1A; /* strlen destination + 15 = 26 */
|
||||
fac[10] = 0x02;
|
||||
fac[11] = 0x01;
|
||||
fac[12] = 0x70;
|
||||
fac[13] = 0x02;
|
||||
fac[14] = 0x01;
|
||||
fac[15] = 0x0d;
|
||||
fac[16] = 0x30;
|
||||
fac[17] = 0x12; /* strlen destination + 7 = 18 */
|
||||
fac[18] = 0x30; /* ...hm 0x30 */
|
||||
fac[19] = 0x0d; /* strlen destination + 2 */
|
||||
fac[20] = 0x80; /* CLIP */
|
||||
fac[21] = 0x0b; /* strlen destination */
|
||||
fac[22] = 0x01; /* destination start */
|
||||
fac[23] = 0x01;
|
||||
fac[24] = 0x01;
|
||||
fac[25] = 0x01;
|
||||
fac[26] = 0x01;
|
||||
fac[27] = 0x01;
|
||||
fac[28] = 0x01;
|
||||
fac[29] = 0x01;
|
||||
fac[30] = 0x01;
|
||||
fac[31] = 0x01;
|
||||
fac[32] = 0x01;
|
||||
fac[33] = 0x01; /* 0x1 = sending complete */
|
||||
fac[34] = 0x01;
|
||||
fac[35] = 0x01;
|
||||
|
||||
memcpy((unsigned char *)fac + 22, data, strlen(data));
|
||||
fac[22 + strlen(data)] = 0x01; /* fill with 0x01 if number is only 6 numbers (local call) */
|
||||
fac[23 + strlen(data)] = 0x01;
|
||||
fac[24 + strlen(data)] = 0x01;
|
||||
fac[25 + strlen(data)] = 0x01;
|
||||
fac[26 + strlen(data)] = 0x01;
|
||||
|
||||
fac[6] = 18 + strlen(data);
|
||||
fac[9] = 15 + strlen(data);
|
||||
fac[17] = 7 + strlen(data);
|
||||
fac[19] = 2 + strlen(data);
|
||||
fac[21] = strlen(data);
|
||||
|
||||
bchaninfo[0] = 0x1;
|
||||
|
||||
INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
|
||||
INFO_REQ_CONTROLLER(&CMSG) = i->controller;
|
||||
INFO_REQ_PLCI(&CMSG) = i->PLCI;
|
||||
INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; /* use D-Channel */
|
||||
INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
|
||||
INFO_REQ_USERUSERDATA(&CMSG) = 0;
|
||||
INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
|
||||
|
||||
if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
|
||||
return Info;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup the interface
|
||||
*/
|
||||
|
@ -2470,6 +2369,101 @@ static void capi_handle_disconnect_indication(_cmsg *CMSG, unsigned int PLCI, un
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* deflect a call
|
||||
*/
|
||||
static int capi_call_deflect(struct ast_channel *c, char *param)
|
||||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
_cmsg CMSG;
|
||||
char bchaninfo[1];
|
||||
char fac[60];
|
||||
int res = 0;
|
||||
|
||||
if ((!param) || (!strlen(param))) {
|
||||
ast_log(LOG_WARNING, "capi deflection requires an argument (destination phone number)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((i->state != CAPI_STATE_INCALL) &&
|
||||
(i->state != CAPI_STATE_DID) &&
|
||||
(i->state != CAPI_STATE_ALERTING)) {
|
||||
ast_log(LOG_WARNING, "wrong state of call for call deflection\n");
|
||||
return -1;
|
||||
}
|
||||
if (i->state != CAPI_STATE_ALERTING) {
|
||||
capi_alert(c);
|
||||
}
|
||||
|
||||
fac[0] = 0; /* len */
|
||||
fac[1] = 0; /* len */
|
||||
fac[2] = 0x01; /* Use D-Chan */
|
||||
fac[3] = 0; /* Keypad len */
|
||||
fac[4] = 31; /* user user data? len = 31 = 29 + 2 */
|
||||
fac[5] = 0x1c; /* magic? */
|
||||
fac[6] = 0x1d; /* strlen destination + 18 = 29 */
|
||||
fac[7] = 0x91; /* .. */
|
||||
fac[8] = 0xA1;
|
||||
fac[9] = 0x1A; /* strlen destination + 15 = 26 */
|
||||
fac[10] = 0x02;
|
||||
fac[11] = 0x01;
|
||||
fac[12] = 0x70;
|
||||
fac[13] = 0x02;
|
||||
fac[14] = 0x01;
|
||||
fac[15] = 0x0d;
|
||||
fac[16] = 0x30;
|
||||
fac[17] = 0x12; /* strlen destination + 7 = 18 */
|
||||
fac[18] = 0x30; /* ...hm 0x30 */
|
||||
fac[19] = 0x0d; /* strlen destination + 2 */
|
||||
fac[20] = 0x80; /* CLIP */
|
||||
fac[21] = 0x0b; /* strlen destination */
|
||||
fac[22] = 0x01; /* destination start */
|
||||
fac[23] = 0x01; /* */
|
||||
fac[24] = 0x01; /* */
|
||||
fac[25] = 0x01; /* */
|
||||
fac[26] = 0x01; /* */
|
||||
fac[27] = 0x01; /* */
|
||||
fac[28] = 0x01; /* */
|
||||
fac[29] = 0x01; /* */
|
||||
fac[30] = 0x01; /* */
|
||||
fac[31] = 0x01; /* */
|
||||
fac[32] = 0x01; /* */
|
||||
fac[33] = 0x01; /* 0x01 = sending complete */
|
||||
fac[34] = 0x01;
|
||||
fac[35] = 0x01;
|
||||
|
||||
memcpy((unsigned char *)fac + 22, param, strlen(param));
|
||||
|
||||
fac[22 + strlen(param)] = 0x01; /* fill with 0x01 if number is only 6 numbers (local call) */
|
||||
fac[23 + strlen(param)] = 0x01;
|
||||
fac[24 + strlen(param)] = 0x01;
|
||||
fac[25 + strlen(param)] = 0x01;
|
||||
fac[26 + strlen(param)] = 0x01;
|
||||
|
||||
fac[6] = 18 + strlen(param);
|
||||
fac[9] = 15 + strlen(param);
|
||||
fac[17] = 7 + strlen(param);
|
||||
fac[19] = 2 + strlen(param);
|
||||
fac[21] = strlen(param);
|
||||
|
||||
bchaninfo[0] = 0x1;
|
||||
|
||||
INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
|
||||
INFO_REQ_CONTROLLER(&CMSG) = i->controller;
|
||||
INFO_REQ_PLCI(&CMSG) = i->PLCI;
|
||||
INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; /* use D-Channel */
|
||||
INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
|
||||
INFO_REQ_USERUSERDATA(&CMSG) = 0;
|
||||
INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*)fac + 4;
|
||||
|
||||
_capi_put_cmsg(&CMSG);
|
||||
|
||||
cc_ast_verbose(2, 1, VERBOSE_PREFIX_2 "%s: sent INFO_REQ for CD PLCI = %#x\n",
|
||||
i->name, i->PLCI);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* CAPI CONNECT_IND
|
||||
*/
|
||||
|
@ -2600,7 +2594,7 @@ static void capi_handle_connect_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
#endif
|
||||
if (deflect == 1) {
|
||||
if (i->deflect2) {
|
||||
capi_deflect(i->owner, i->deflect2);
|
||||
capi_call_deflect(i->owner, i->deflect2);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
@ -2919,14 +2913,16 @@ static int capicommand_exec(struct ast_channel *chan, void *data)
|
|||
}
|
||||
s = ast_strdupa(data);
|
||||
stringp = s;
|
||||
command = strsep(&stringp, ",");
|
||||
params = strsep(&stringp, ",");
|
||||
cc_ast_verbose(2, 1, VERBOSE_PREFIX_3 "capiCommand: '%s' '%s'\n",
|
||||
command = strsep(&stringp, "|");
|
||||
params = stringp;
|
||||
cc_ast_verbose(2, 1, VERBOSE_PREFIX_1 "capiCommand: '%s' '%s'\n",
|
||||
command, params);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!strcasecmp(command, "earlyb3")) {
|
||||
res = capi_set_earlyb3(chan, params);
|
||||
} else if (!strcasecmp(command, "deflect")) {
|
||||
res = capi_call_deflect(chan, params);
|
||||
} else {
|
||||
res = -1;
|
||||
ast_log(LOG_WARNING, "Unknown command '%s' for capiCommand\n",
|
||||
|
|
Loading…
Reference in New Issue