Added linkage id handling for CCBS/CCNR.
This commit is contained in:
parent
cd18383e0e
commit
a9c2413461
10
README
10
README
|
@ -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.
|
||||||
|
|
23
chan_capi.c
23
chan_capi.c
|
@ -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 }
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue