Added linkage id handling for CCBS/CCNR.
parent
cd18383e0e
commit
a9c2413461
10
README
10
README
|
@ -202,6 +202,11 @@ ECT:
|
|||
exten => s,1,capicommand(hold)
|
||||
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
|
||||
==========
|
||||
|
@ -362,7 +367,10 @@ CALLINGSUBADDRESS
|
|||
|
||||
CALLEDSUBADDRESS
|
||||
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
|
||||
Can be set before answering and if set, the content is used for
|
||||
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;
|
||||
}
|
||||
|
||||
i->peer = cc_get_peer_link_id(pbx_builtin_getvar_helper(c, "CAPIPEERLINKID"));
|
||||
|
||||
i->MessageNumber = get_capi_MessageNumber();
|
||||
CONNECT_REQ_HEADER(&CMSG, capi_ApplID, i->MessageNumber, 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
@ -4621,6 +4641,7 @@ static struct capicommands_s {
|
|||
int (*cmd)(struct ast_channel *, char *);
|
||||
int capionly;
|
||||
} capicommands[] = {
|
||||
{ "peerlink", pbx_capi_peer_link, 0 },
|
||||
{ "progress", pbx_capi_signal_progress, 1 },
|
||||
{ "deflect", pbx_capi_call_deflect, 1 },
|
||||
{ "receivefax", pbx_capi_receive_fax, 1 },
|
||||
|
@ -4634,7 +4655,7 @@ static struct capicommands_s {
|
|||
{ "ect", pbx_capi_ect, 1 },
|
||||
{ "3pty_begin", pbx_capi_3pty_begin, 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_getplci", pbx_capi_qsig_getplci, 1 },
|
||||
{ NULL, NULL, 0 }
|
||||
|
|
|
@ -291,6 +291,9 @@ struct capi_pvt {
|
|||
/*! Channel we belong to, possibly NULL */
|
||||
struct ast_channel *owner;
|
||||
|
||||
/*! Channel who called us, possibly NULL */
|
||||
struct ast_channel *peer;
|
||||
|
||||
/* capi message number */
|
||||
_cword MessageNumber;
|
||||
unsigned int NCCI;
|
||||
|
|
|
@ -20,6 +20,53 @@
|
|||
#include "chan_capi_supplementary.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
|
||||
|
@ -81,6 +128,7 @@ void handle_facility_indication_supplementary(
|
|||
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",
|
||||
PLCI & 0xff, PLCI, infoword);
|
||||
del_ccbsnr_id(PLCI, infoword);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -134,10 +182,12 @@ void handle_facility_indication_supplementary(
|
|||
case 0x8013: /* CCBS info retain */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCBS unique id=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
new_ccbsnr_id(CCBSNR_TYPE_CCBS, PLCI, infoword, i);
|
||||
break;
|
||||
case 0x8015: /* CCNR info retain */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCNR unique id=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
new_ccbsnr_id(CCBSNR_TYPE_CCNR, PLCI, infoword, i);
|
||||
break;
|
||||
case 0x800d: /* CCBS erase call linkage ID */
|
||||
/* handled above */
|
||||
|
|
|
@ -20,4 +20,22 @@
|
|||
extern void ListenOnSupplementary(unsigned controller);
|
||||
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
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
|
@ -26,6 +27,9 @@ AST_MUTEX_DEFINE_STATIC(capi_put_lock);
|
|||
|
||||
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
|
||||
*/
|
||||
|
@ -617,3 +621,41 @@ void parse_dialstring(char *buffer, char **interface, char **dest, char **param,
|
|||
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 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 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) \
|
||||
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
|
||||
|
|
Loading…
Reference in New Issue