Added linkage id handling for CCBS/CCNR.

This commit is contained in:
MelwareDE 2007-04-17 21:04:42 +00:00
parent cd18383e0e
commit a9c2413461
7 changed files with 146 additions and 2 deletions

10
README
View File

@ -202,6 +202,11 @@ ECT:
exten => s,1,capicommand(hold) exten => s,1,capicommand(hold)
exten => s,2,Dial(CAPI/contr1/1234,,M(capi3pty)) exten => s,2,Dial(CAPI/contr1/1234,,M(capi3pty))
Peer link creation:
Create a reference for chan-capi to know who is the calling channel on Dial().
This is needed if you want to use CCBS/CCNR afterwards.
Example:
exten => s,1,capicommand(peerlink)
Using CLIR Using CLIR
========== ==========
@ -362,7 +367,10 @@ CALLINGSUBADDRESS
CALLEDSUBADDRESS CALLEDSUBADDRESS
If set on dial(), the called subaddress will be set to the content. If set on dial(), the called subaddress will be set to the content.
CCLINKAGEID
If a Call-Linkage-Id is received for CCBS/CCNR, this variable contains this Id.
CONNECTEDNUMBER CONNECTEDNUMBER
Can be set before answering and if set, the content is used for Can be set before answering and if set, the content is used for
IE 'Connected Number' on answering. IE 'Connected Number' on answering.

View File

@ -1210,6 +1210,8 @@ static int pbx_capi_call(struct ast_channel *c, char *idest, int timeout)
dsa = calledsubaddress; dsa = calledsubaddress;
} }
i->peer = cc_get_peer_link_id(pbx_builtin_getvar_helper(c, "CAPIPEERLINKID"));
i->MessageNumber = get_capi_MessageNumber(); i->MessageNumber = get_capi_MessageNumber();
CONNECT_REQ_HEADER(&CMSG, capi_ApplID, i->MessageNumber, i->controller); CONNECT_REQ_HEADER(&CMSG, capi_ApplID, i->MessageNumber, i->controller);
CONNECT_REQ_CONTROLLER(&CMSG) = i->controller; CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
@ -4050,6 +4052,24 @@ static int pbx_capi_call_deflect(struct ast_channel *c, char *param)
return(res); return(res);
} }
/*
* store the peer for future actions
*/
static int pbx_capi_peer_link(struct ast_channel *c, char *param)
{
char buffer[32];
int id;
id = cc_add_peer_link_id(c);
if (id >= 0) {
snprintf(buffer, sizeof(buffer) - 1, "%d", id);
pbx_builtin_setvar_helper(c, "_CAPIPEERLINKID", buffer);
}
return 0;
}
/* /*
* retrieve a hold on call * retrieve a hold on call
*/ */
@ -4621,6 +4641,7 @@ static struct capicommands_s {
int (*cmd)(struct ast_channel *, char *); int (*cmd)(struct ast_channel *, char *);
int capionly; int capionly;
} capicommands[] = { } capicommands[] = {
{ "peerlink", pbx_capi_peer_link, 0 },
{ "progress", pbx_capi_signal_progress, 1 }, { "progress", pbx_capi_signal_progress, 1 },
{ "deflect", pbx_capi_call_deflect, 1 }, { "deflect", pbx_capi_call_deflect, 1 },
{ "receivefax", pbx_capi_receive_fax, 1 }, { "receivefax", pbx_capi_receive_fax, 1 },
@ -4634,7 +4655,7 @@ static struct capicommands_s {
{ "ect", pbx_capi_ect, 1 }, { "ect", pbx_capi_ect, 1 },
{ "3pty_begin", pbx_capi_3pty_begin, 1 }, { "3pty_begin", pbx_capi_3pty_begin, 1 },
{ "qsig_ssct", pbx_capi_qsig_ssct, 1 }, { "qsig_ssct", pbx_capi_qsig_ssct, 1 },
{ "qsig_ct", pbx_capi_qsig_ct, 1 }, { "qsig_ct", pbx_capi_qsig_ct, 1 },
{ "qsig_callmark",pbx_capi_qsig_callmark, 1 }, { "qsig_callmark",pbx_capi_qsig_callmark, 1 },
{ "qsig_getplci", pbx_capi_qsig_getplci, 1 }, { "qsig_getplci", pbx_capi_qsig_getplci, 1 },
{ NULL, NULL, 0 } { NULL, NULL, 0 }

View File

@ -291,6 +291,9 @@ struct capi_pvt {
/*! Channel we belong to, possibly NULL */ /*! Channel we belong to, possibly NULL */
struct ast_channel *owner; struct ast_channel *owner;
/*! Channel who called us, possibly NULL */
struct ast_channel *peer;
/* capi message number */ /* capi message number */
_cword MessageNumber; _cword MessageNumber;
unsigned int NCCI; unsigned int NCCI;

View File

@ -20,6 +20,53 @@
#include "chan_capi_supplementary.h" #include "chan_capi_supplementary.h"
#include "chan_capi_utils.h" #include "chan_capi_utils.h"
#define CCBSNR_MAX_LIST_ENTRIES 32
static struct ccbsnr_s ccbsnr_list[CCBSNR_MAX_LIST_ENTRIES];
/*
* a new CCBS/CCNR id was received
*/
static void new_ccbsnr_id(ccbsnrtype_t type, unsigned int plci,
_cword id, struct capi_pvt *i)
{
int a;
char buffer[CAPI_MAX_STRING];
for (a = 0; a < CCBSNR_MAX_LIST_ENTRIES; a++) {
if (ccbsnr_list[a].type == CCBSNR_TYPE_NULL) {
ccbsnr_list[a].type = type;
ccbsnr_list[a].id = id;
ccbsnr_list[a].plci = plci;
ccbsnr_list[a].state = CCBSNR_AVAILABLE;
if (i->peer) {
snprintf(buffer, CAPI_MAX_STRING-1, "%d", (id | ((plci & 0xff) << 16)));
pbx_builtin_setvar_helper(i->peer, "CCLINKAGEID", buffer);
}
break;
}
}
if (a == CCBSNR_MAX_LIST_ENTRIES) {
cc_log(LOG_ERROR, "No free entry for new CCBS/CCNR ID\n");
}
}
/*
* a CCBS/CCNR id was removed
*/
static void del_ccbsnr_id(unsigned int plci, _cword id)
{
int a;
for (a = 0; a < CCBSNR_MAX_LIST_ENTRIES; a++) {
if (((ccbsnr_list[a].plci & 0xff) == (plci & 0xff)) &&
(ccbsnr_list[a].id == id)) {
ccbsnr_list[a].type = CCBSNR_TYPE_NULL;
ccbsnr_list[a].state = 0;
break;
}
}
}
/* /*
* send Listen for supplementary to specified controller * send Listen for supplementary to specified controller
@ -81,6 +128,7 @@ void handle_facility_indication_supplementary(
case 0x800d: /* CCBS erase call linkage ID */ case 0x800d: /* CCBS erase call linkage ID */
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS/CCNR erase id=0x%04x\n", cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS/CCNR erase id=0x%04x\n",
PLCI & 0xff, PLCI, infoword); PLCI & 0xff, PLCI, infoword);
del_ccbsnr_id(PLCI, infoword);
break; break;
} }
@ -134,10 +182,12 @@ void handle_facility_indication_supplementary(
case 0x8013: /* CCBS info retain */ case 0x8013: /* CCBS info retain */
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCBS unique id=0x%04x\n", cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCBS unique id=0x%04x\n",
i->vname, PLCI, infoword); i->vname, PLCI, infoword);
new_ccbsnr_id(CCBSNR_TYPE_CCBS, PLCI, infoword, i);
break; break;
case 0x8015: /* CCNR info retain */ case 0x8015: /* CCNR info retain */
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCNR unique id=0x%04x\n", cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCNR unique id=0x%04x\n",
i->vname, PLCI, infoword); i->vname, PLCI, infoword);
new_ccbsnr_id(CCBSNR_TYPE_CCNR, PLCI, infoword, i);
break; break;
case 0x800d: /* CCBS erase call linkage ID */ case 0x800d: /* CCBS erase call linkage ID */
/* handled above */ /* handled above */

View File

@ -20,4 +20,22 @@
extern void ListenOnSupplementary(unsigned controller); extern void ListenOnSupplementary(unsigned controller);
extern void handle_facility_indication_supplementary(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i); extern void handle_facility_indication_supplementary(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
typedef enum {
CCBSNR_TYPE_NULL = 0,
CCBSNR_TYPE_CCBS,
CCBSNR_TYPE_CCNR
} ccbsnrtype_t;
#define CCBSNR_AVAILABLE 1
struct ccbsnr_s {
ccbsnrtype_t type;
_cword id;
unsigned int plci;
unsigned int state;
char context[AST_MAX_CONTEXT];
char exten[AST_MAX_EXTENSION];
int priority;
};
#endif #endif

View File

@ -12,6 +12,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include "chan_capi20.h" #include "chan_capi20.h"
#include "chan_capi.h" #include "chan_capi.h"
#include "chan_capi_utils.h" #include "chan_capi_utils.h"
@ -26,6 +27,9 @@ AST_MUTEX_DEFINE_STATIC(capi_put_lock);
static _cword capi_MessageNumber; static _cword capi_MessageNumber;
#define CAPI_MAX_PEERLINKCHANNELS 32
static struct ast_channel *peerlinkchannel[CAPI_MAX_PEERLINKCHANNELS];
/* /*
* helper for <pbx>_verbose with different verbose settings * helper for <pbx>_verbose with different verbose settings
*/ */
@ -617,3 +621,41 @@ void parse_dialstring(char *buffer, char **interface, char **dest, char **param,
return; return;
} }
/*
* Add a new peer link id
*/
int cc_add_peer_link_id(struct ast_channel *c)
{
int a;
for (a = 0; a < CAPI_MAX_PEERLINKCHANNELS; a++) {
if (peerlinkchannel[a] == NULL) {
peerlinkchannel[a] = c;
break;
}
}
if (a == CAPI_MAX_PEERLINKCHANNELS) {
return -1;
}
return a;
}
/*
* Get and remove peer link id
*/
struct ast_channel *cc_get_peer_link_id(const char *p)
{
int id = -1;
struct ast_channel *chan = NULL;
if (p) {
id = (int)strtoul(p, NULL, 0);
}
if ((id >= 0) && (id < CAPI_MAX_PEERLINKCHANNELS)) {
chan = peerlinkchannel[id];
peerlinkchannel[id] = NULL;
}
return chan;
}

View File

@ -29,6 +29,8 @@ extern void show_capi_info(struct capi_pvt *i, _cword info);
extern unsigned ListenOnController(unsigned long CIPmask, unsigned controller); extern unsigned ListenOnController(unsigned long CIPmask, unsigned controller);
extern void parse_dialstring(char *buffer, char **interface, char **dest, char **param, char **ocid); extern void parse_dialstring(char *buffer, char **interface, char **dest, char **param, char **ocid);
extern char *capi_number_func(unsigned char *data, unsigned int strip, char *buf); extern char *capi_number_func(unsigned char *data, unsigned int strip, char *buf);
extern int cc_add_peer_link_id(struct ast_channel *c);
extern struct ast_channel *cc_get_peer_link_id(const char *p);
#define capi_number(data, strip) \ #define capi_number(data, strip) \
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION)) capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))