- support for CALLEDNAME
 - support for CONNECTEDNAME
 - startet some code for sendtext, still disabled - i've to find an trick to implement this
This commit is contained in:
MelwareDE 2007-07-10 17:44:09 +00:00
parent 9ae64305da
commit 03cb7d3048
6 changed files with 218 additions and 13 deletions

View File

@ -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:

View File

@ -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,

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);