QSIG:
- support for CALLEDNAME - support for CONNECTEDNAME - startet some code for sendtext, still disabled - i've to find an trick to implement thisV1_1
parent
9ae64305da
commit
03cb7d3048
|
@ -84,6 +84,13 @@ The QSIG support includes:
|
|||
- decoding of incoming Call Transfer feature
|
||||
Enables inbound Path Replacement. If received, an automatic Path Replacement with asterisk internal bridging will be fired.
|
||||
|
||||
- Support for sending CalledName
|
||||
If in dialplan a variable CALLEDNAME was set, it will be sent out to the switch, while the asterisk extension is ringing.
|
||||
|
||||
- Support for sending ConnectedName
|
||||
If in dialplan a variable CONNECTEDNAME was set, it will be sent out to the switch AFTER connection is answered by asterisk
|
||||
|
||||
|
||||
Future Targets:
|
||||
===============
|
||||
- check code for buffer overflows
|
||||
|
@ -91,7 +98,7 @@ Future Targets:
|
|||
- Call Rerouting feature [ECMA-174]
|
||||
- CCBS
|
||||
- AOC
|
||||
- Sent out LEG_INFO3 - maybe this would allow an sendtext (display instructions on the connected set)
|
||||
- sendtext implementation (e.g. display instructions on the connected set)
|
||||
- ...
|
||||
|
||||
How to use:
|
||||
|
|
17
chan_capi.c
17
chan_capi.c
|
@ -779,6 +779,7 @@ static int pbx_capi_send_digit(struct ast_channel *c, char digit)
|
|||
static int pbx_capi_alert(struct ast_channel *c)
|
||||
{
|
||||
struct capi_pvt *i = CC_CHANNEL_PVT(c);
|
||||
unsigned char *facilityarray = NULL;
|
||||
|
||||
if ((i->state != CAPI_STATE_INCALL) &&
|
||||
(i->state != CAPI_STATE_DID)) {
|
||||
|
@ -787,8 +788,11 @@ static int pbx_capi_alert(struct ast_channel *c)
|
|||
return -1;
|
||||
}
|
||||
|
||||
facilityarray = alloca(CAPI_MAX_FACILITYDATAARRAY_SIZE);
|
||||
cc_qsig_add_call_alert_data(facilityarray, i, c);
|
||||
|
||||
if (capi_sendf(NULL, 0, CAPI_ALERT_REQ, i->PLCI, get_capi_MessageNumber(),
|
||||
"()") != 0) {
|
||||
"(()()()s())", facilityarray) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1311,6 +1315,7 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf)
|
|||
char buf[CAPI_MAX_STRING];
|
||||
const char *dnid;
|
||||
const char *connectednumber;
|
||||
unsigned char *facilityarray = NULL;
|
||||
|
||||
if ((i->isdnmode == CAPI_ISDNMODE_DID) &&
|
||||
((strlen(i->incomingmsn) < strlen(i->dnid)) &&
|
||||
|
@ -1338,8 +1343,11 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf)
|
|||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: Answering for %s\n",
|
||||
i->vname, dnid);
|
||||
|
||||
facilityarray = alloca(CAPI_MAX_FACILITYDATAARRAY_SIZE);
|
||||
cc_qsig_add_call_answer_data(facilityarray, i, c);
|
||||
|
||||
if (capi_sendf(NULL, 0, CAPI_CONNECT_RESP, i->PLCI, i->MessageNumber,
|
||||
"w(wwwssss)s()()()",
|
||||
"w(wwwssss)s()()(()()()s())",
|
||||
0, /* accept call */
|
||||
/* B protocol */
|
||||
b_protocol_table[i->bproto].b1protocol,
|
||||
|
@ -1349,10 +1357,11 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf)
|
|||
b_protocol_table[i->bproto].b2configuration,
|
||||
b3conf,
|
||||
capi_set_global_configuration(i),
|
||||
buf /* connected number */
|
||||
buf, /* connected number */
|
||||
/* connected subaddress */
|
||||
/* LLC */
|
||||
/* Additional info */
|
||||
facilityarray
|
||||
) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -5189,7 +5198,7 @@ const struct ast_channel_tech capi_tech = {
|
|||
#else
|
||||
.send_digit = pbx_capi_send_digit,
|
||||
#endif
|
||||
.send_text = NULL,
|
||||
.send_text = pbx_capi_qsig_sendtext,
|
||||
.call = pbx_capi_call,
|
||||
.hangup = pbx_capi_hangup,
|
||||
.answer = pbx_capi_answer,
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
#define CCQSIG__ECMA__PRPROPOSE 1004 /* Path Replacement Propose */
|
||||
#define CCQSIG__ECMA__CTCOMPLETE 1012 /* Call Transfer Complete */
|
||||
#define CCQSIG__ECMA__LEGINFO2 1021 /* LEG INFORMATION2 */
|
||||
#define CCQSIG__ECMA__LEGINFO3 1022 /* LEG INFORMATION3 */
|
||||
|
||||
|
||||
#define CCQSIG_TIMER_WAIT_PRPROPOSE 1 /* Wait x seconds */
|
||||
|
@ -167,6 +168,8 @@ extern signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struc
|
|||
extern unsigned int cc_qsig_handle_capiind(unsigned char *data, struct capi_pvt *i);
|
||||
extern unsigned int cc_qsig_handle_capi_facilityind(unsigned char *data, struct capi_pvt *i);
|
||||
extern unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
|
||||
extern unsigned int cc_qsig_add_call_answer_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
|
||||
extern unsigned int cc_qsig_add_call_alert_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
|
||||
extern unsigned int cc_qsig_add_call_facility_data(unsigned char *data, struct capi_pvt *i, int facility);
|
||||
|
||||
extern signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protocol);
|
||||
|
@ -179,6 +182,7 @@ extern int pbx_capi_qsig_ssct(struct ast_channel *c, char *param);
|
|||
extern int pbx_capi_qsig_ct(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_qsig_callmark(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_qsig_bridge(struct capi_pvt *i0, struct capi_pvt *i1);
|
||||
extern int pbx_capi_qsig_sendtext(struct ast_channel *c, const char *text);
|
||||
|
||||
|
||||
extern void cc_qsig_interface_init(struct cc_capi_conf *conf, struct capi_pvt *tmp);
|
||||
|
|
|
@ -936,7 +936,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
|
|||
}
|
||||
|
||||
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
|
||||
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0);
|
||||
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0, i->owner->cid.cid_name);
|
||||
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
|
||||
|
||||
if (add_externalinfo) {
|
||||
|
@ -950,6 +950,81 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles outgoing Facilies on Call Answer
|
||||
*/
|
||||
unsigned int cc_qsig_add_call_answer_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c)
|
||||
{
|
||||
struct cc_qsig_invokedata invoke;
|
||||
struct cc_qsig_nfe nfe;
|
||||
unsigned int dataidx = 0;
|
||||
int protocolvar = 0;
|
||||
const char *connectedname;
|
||||
|
||||
if (!i->qsigfeat)
|
||||
return 0;
|
||||
|
||||
connectedname = pbx_builtin_getvar_helper(c, "CONNECTEDNAME");
|
||||
if (!strlen(connectedname))
|
||||
return 0;
|
||||
|
||||
switch (i->qsigfeat) {
|
||||
case QSIG_TYPE_ALCATEL_ECMA:
|
||||
protocolvar = Q932_PROTOCOL_ROSE;
|
||||
break;
|
||||
case QSIG_TYPE_HICOM_ECMAV2:
|
||||
protocolvar = Q932_PROTOCOL_EXTENSIONS;
|
||||
break;
|
||||
default:
|
||||
cc_log(LOG_WARNING, " Unknown QSIG variant configured.\n");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
|
||||
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 2, (char *)connectedname);
|
||||
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles outgoing Facilies on Call Answer
|
||||
*/
|
||||
unsigned int cc_qsig_add_call_alert_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c)
|
||||
{
|
||||
struct cc_qsig_invokedata invoke;
|
||||
struct cc_qsig_nfe nfe;
|
||||
unsigned int dataidx = 0;
|
||||
int protocolvar = 0;
|
||||
const char *connectedname;
|
||||
|
||||
if (!i->qsigfeat)
|
||||
return 0;
|
||||
|
||||
connectedname = pbx_builtin_getvar_helper(c, "CALLEDNAME");
|
||||
if (!strlen(connectedname))
|
||||
return 0;
|
||||
|
||||
switch (i->qsigfeat) {
|
||||
case QSIG_TYPE_ALCATEL_ECMA:
|
||||
protocolvar = Q932_PROTOCOL_ROSE;
|
||||
break;
|
||||
case QSIG_TYPE_HICOM_ECMAV2:
|
||||
protocolvar = Q932_PROTOCOL_EXTENSIONS;
|
||||
break;
|
||||
default:
|
||||
cc_log(LOG_WARNING, " Unknown QSIG variant configured.\n");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
|
||||
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 1, (char *)connectedname);
|
||||
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles outgoing Facilies on capicommand
|
||||
|
@ -1301,6 +1376,44 @@ int pbx_capi_qsig_bridge(struct capi_pvt *i0,struct capi_pvt *i1)
|
|||
|
||||
}
|
||||
|
||||
int pbx_capi_qsig_sendtext(struct ast_channel *c, const char *text)
|
||||
{
|
||||
struct capi_pvt *i = CC_CHANNEL_PVT(c);
|
||||
|
||||
#if 0
|
||||
/* suppress compiler warnings */
|
||||
unsigned char *data = alloca(CAPI_MAX_FACILITYDATAARRAY_SIZE);
|
||||
unsigned int dataidx = 0;
|
||||
struct cc_qsig_invokedata invoke;
|
||||
struct cc_qsig_nfe nfe;
|
||||
#endif
|
||||
|
||||
int protocolvar = 0;
|
||||
|
||||
if (!i->qsigfeat)
|
||||
return 0;
|
||||
|
||||
|
||||
if (!strlen(text))
|
||||
return 0;
|
||||
|
||||
switch (i->qsigfeat) {
|
||||
case QSIG_TYPE_ALCATEL_ECMA:
|
||||
protocolvar = Q932_PROTOCOL_ROSE;
|
||||
break;
|
||||
case QSIG_TYPE_HICOM_ECMAV2:
|
||||
protocolvar = Q932_PROTOCOL_EXTENSIONS;
|
||||
break;
|
||||
default:
|
||||
cc_log(LOG_WARNING, " Unknown QSIG variant configured.\n");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: implement something - QSIG_LEG_INFO3 doesn't work here */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CAPI INFO_IND (QSIG part)
|
||||
|
|
|
@ -116,15 +116,15 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap
|
|||
* returns
|
||||
* always 0
|
||||
*/
|
||||
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype)
|
||||
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, char * name)
|
||||
{
|
||||
unsigned char namebuf[51];
|
||||
unsigned char data[255];
|
||||
int dataidx = 0;
|
||||
int namelen = 0;
|
||||
|
||||
if (i->owner->cid.cid_name)
|
||||
namelen = strlen(i->owner->cid.cid_name);
|
||||
if (name)
|
||||
namelen = strlen(name);
|
||||
|
||||
if (namelen < 1) { /* There's no name available, try to take Interface-Name */
|
||||
if (i->name) {
|
||||
|
@ -138,15 +138,15 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
|
|||
} else {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
memcpy(namebuf, i->owner->cid.cid_name, namelen);
|
||||
memcpy(namebuf, name, namelen);
|
||||
}
|
||||
|
||||
invoke->id = 1;
|
||||
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
|
||||
invoke->type = 0; /* Invoke Operation Number, if OID it's the last byte*/
|
||||
invoke->type = (nametype % 4); /* Invoke Operation Number, if OID it's the last byte*/
|
||||
|
||||
if (namelen>0) {
|
||||
data[dataidx++] = 0x80 | (nametype % 4); /* We send only simple Name, Namepresentation allowed */
|
||||
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
|
||||
data[dataidx++] = namelen;
|
||||
memcpy(&data[dataidx], namebuf, namelen);
|
||||
dataidx += namelen;
|
||||
|
@ -163,6 +163,76 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.22 ECMA/ISDN/LEG_INFO3
|
||||
*
|
||||
* This function encodes the namepresentation facility
|
||||
* The name will be copied from the cid.cid_name field of the asterisk channel struct.
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data for facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* always 0
|
||||
*/
|
||||
int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name)
|
||||
{
|
||||
unsigned char namebuf[51];
|
||||
unsigned char data[255];
|
||||
|
||||
int dataidx = 0;
|
||||
int namelen = 0;
|
||||
|
||||
if (name)
|
||||
namelen = strlen(name);
|
||||
|
||||
if (namelen < 1) { /* There's no name available, try to take Interface-Name */
|
||||
if (i->name) {
|
||||
if (strlen(i->name) >= 1) {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
namelen = strlen(i->name);
|
||||
memcpy(namebuf, i->name, namelen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
memcpy(namebuf, name, namelen);
|
||||
}
|
||||
|
||||
invoke->id = 1;
|
||||
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
|
||||
invoke->type = 22; /* Invoke Operation Number, if OID it's the last byte*/
|
||||
|
||||
data[dataidx++] = ASN1_TF_CONSTRUCTED | ASN1_SEQUENCE;
|
||||
data[dataidx++] = 5 + namelen;
|
||||
|
||||
data[dataidx++] = ASN1_BOOLEAN; /* PresentationAllowedIndicator */
|
||||
data[dataidx++] = 1;
|
||||
data[dataidx++] = 1;
|
||||
|
||||
if (namelen>0) {
|
||||
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
|
||||
data[dataidx++] = namelen;
|
||||
memcpy(&data[dataidx], namebuf, namelen);
|
||||
dataidx += namelen;
|
||||
} else {
|
||||
data[dataidx++] = 0x84; /* Name not available */
|
||||
data[dataidx++] = 0;
|
||||
}
|
||||
|
||||
invoke->datalen = dataidx;
|
||||
memcpy(invoke->data, data, dataidx);
|
||||
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_LEG_INFO3 \"%s\": (%i byte(s))\n", namebuf, namelen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle Operation: 1.3.12.9.21 ECMA/ISDN/LEG_INFORMATION2
|
||||
|
|
|
@ -41,7 +41,9 @@ struct cc_qsig_ctcomplete {
|
|||
*/
|
||||
|
||||
extern void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype);
|
||||
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, char *name);
|
||||
|
||||
extern int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name);
|
||||
|
||||
extern void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
|
||||
|
|
Loading…
Reference in New Issue