QSIG:
- moved more code from chan_capi.c to qsig_core - make Call Transfer on alerting state working (wrong number will be displayed on target number at the moment)
This commit is contained in:
parent
04d4580bc4
commit
9d4968ab3a
11
chan_capi.c
11
chan_capi.c
|
@ -2731,10 +2731,6 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
case 0x001c: /* Facility Q.932 */
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element FACILITY\n",
|
||||
i->vname);
|
||||
if (i->qsigfeat) { /* chances are high, that we got an QSIG Facility */
|
||||
unsigned int qsiginvoke;
|
||||
qsiginvoke = cc_qsig_handle_capi_facilityind( (unsigned char*) INFO_IND_INFOELEMENT(CMSG), i);
|
||||
}
|
||||
break;
|
||||
case 0x001e: /* Progress Indicator */
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element PI %02x %02x\n",
|
||||
|
@ -2842,9 +2838,6 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
if (i->owner)
|
||||
ast_setstate(i->owner, AST_STATE_RINGING);
|
||||
|
||||
if (i->qsigfeat) {
|
||||
/* TODO: some checks, if there's any work here */
|
||||
}
|
||||
break;
|
||||
case 0x8002: /* CALL PROCEEDING */
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element CALL PROCEEDING\n",
|
||||
|
@ -2936,6 +2929,10 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig
|
|||
i->vname, INFO_IND_INFONUMBER(CMSG), PLCI);
|
||||
break;
|
||||
}
|
||||
|
||||
/* QSIG worker - is only executed, if QSIG is enabled */
|
||||
pbx_capi_qsig_handle_info_indication(CMSG, PLCI, NCCI, i);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ struct cc_qsig_nfe {
|
|||
*/
|
||||
|
||||
extern int cc_qsig_build_facility_struct(unsigned char * buf, unsigned int *idx, int apdu_interpr, struct cc_qsig_nfe *nfe);
|
||||
extern int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke);
|
||||
extern int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
|
||||
extern unsigned int cc_qsig_asn1_get_string(unsigned char *buf, int buflen, unsigned char *data);
|
||||
extern unsigned int cc_qsig_asn1_get_integer(unsigned char *data, int *idx);
|
||||
|
@ -169,6 +169,7 @@ 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 void interface_cleanup_qsig(struct capi_pvt *i);
|
||||
extern void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
|
||||
|
||||
/*
|
||||
*** ECMA QSIG Functions
|
||||
|
|
|
@ -183,8 +183,9 @@ int cc_qsig_build_facility_struct(unsigned char * buf, unsigned int *idx, int ap
|
|||
/*
|
||||
* Add invoke to buf
|
||||
*/
|
||||
int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke)
|
||||
int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
|
||||
{
|
||||
unsigned char oid1[] = {0x2b,0x0c,0x09,0x00};
|
||||
int myidx = *idx;
|
||||
int invlenidx;
|
||||
int result;
|
||||
|
@ -199,6 +200,26 @@ int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_in
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (invoke->descr_type == -1) {
|
||||
switch (i->qsigfeat) {
|
||||
case QSIG_TYPE_ALCATEL_ECMA:
|
||||
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
|
||||
/* Set ECMA/ETSI OID */
|
||||
oid1[3] = (unsigned char)invoke->type;
|
||||
invoke->oid_len = sizeof(oid1);
|
||||
memcpy(invoke->oid_bin, oid1, sizeof(oid1));
|
||||
break;
|
||||
case QSIG_TYPE_HICOM_ECMAV2:
|
||||
invoke->descr_type = ASN1_INTEGER;
|
||||
/* Leave type as it is */
|
||||
break;
|
||||
default:
|
||||
/* INVOKE is not encoded */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (invoke->descr_type) {
|
||||
case ASN1_INTEGER:
|
||||
result = cc_qsig_asn1_add_integer(buf, &myidx, invoke->type);
|
||||
|
@ -769,7 +790,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
|
|||
/*mg:remember me switch (i->doqsig) {*/
|
||||
cc_qsig_build_facility_struct(data, &dataidx, APDUINTERPRETATION_IGNORE, &nfe);
|
||||
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0);
|
||||
cc_qsig_add_invoke(data, &dataidx, &invoke);
|
||||
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
|
||||
|
||||
if (add_externalinfo) {
|
||||
/* add PROGRESS INDICATOR for external calls*/
|
||||
|
@ -796,12 +817,12 @@ unsigned int cc_qsig_do_facility(unsigned char *fac, struct ast_channel *c, cha
|
|||
switch (factype) {
|
||||
case 12: /* ECMA-178 callTransfer */
|
||||
cc_qsig_encode_ecma_calltransfer(fac, &facidx, &invoke, i, param, info1);
|
||||
cc_qsig_add_invoke(fac, &facidx, &invoke);
|
||||
cc_qsig_add_invoke(fac, &facidx, &invoke, i);
|
||||
|
||||
break;
|
||||
case 99: /* ECMA-300 simpleCallTransfer */
|
||||
cc_qsig_encode_ecma_sscalltransfer(fac, &facidx, &invoke, i, param);
|
||||
cc_qsig_add_invoke(fac, &facidx, &invoke);
|
||||
cc_qsig_add_invoke(fac, &facidx, &invoke, i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -936,3 +957,124 @@ void interface_cleanup_qsig(struct capi_pvt *i)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* find the interface (pvt) the PLCI belongs to
|
||||
*/
|
||||
static struct capi_pvt *find_interface_by_plci(unsigned int plci)
|
||||
{
|
||||
struct capi_pvt *i;
|
||||
|
||||
if (plci == 0)
|
||||
return NULL;
|
||||
|
||||
for (i = iflist; i; i = i->next) {
|
||||
if (i->PLCI == plci)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CAPI INFO_IND (QSIG part)
|
||||
*/
|
||||
void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i)
|
||||
{
|
||||
if (!i->qsigfeat) /* Run only, if QSIG enabled */
|
||||
return;
|
||||
|
||||
switch(INFO_IND_INFONUMBER(CMSG)) {
|
||||
case 0x0008: /* Cause */
|
||||
break;
|
||||
case 0x0014: /* Call State */
|
||||
break;
|
||||
case 0x0018: /* Channel Identification */
|
||||
break;
|
||||
case 0x001c: /* Facility Q.932 */
|
||||
{
|
||||
unsigned int qsiginvoke;
|
||||
qsiginvoke = cc_qsig_handle_capi_facilityind( (unsigned char*) INFO_IND_INFOELEMENT(CMSG), i);
|
||||
}
|
||||
break;
|
||||
case 0x001e: /* Progress Indicator */
|
||||
break;
|
||||
case 0x0027: /* Notification Indicator */
|
||||
break;
|
||||
case 0x0028: /* DSP */
|
||||
break;
|
||||
case 0x0029: /* Date/Time */
|
||||
break;
|
||||
case 0x0070: /* Called Party Number */
|
||||
break;
|
||||
case 0x0074: /* Redirecting Number */
|
||||
break;
|
||||
case 0x0076: /* Redirection Number */
|
||||
break;
|
||||
case 0x00a1: /* Sending Complete */
|
||||
break;
|
||||
case 0x4000: /* CHARGE in UNITS */
|
||||
break;
|
||||
case 0x4001: /* CHARGE in CURRENCY */
|
||||
break;
|
||||
case 0x8001: /* ALERTING */
|
||||
/* TODO: some checks, if there's any work here */
|
||||
if (i->qsig_data.calltransfer_onring) {
|
||||
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
|
||||
struct capi_pvt *ii = find_interface_by_plci(i->qsig_data.partner_plci);
|
||||
|
||||
_cmsg CMSG3;
|
||||
|
||||
i->qsig_data.calltransfer_onring = 0;
|
||||
|
||||
if (ii) {
|
||||
cc_qsig_do_facility(fac, ii->owner, NULL, 12, 0);
|
||||
|
||||
INFO_REQ_HEADER(&CMSG3, capi_ApplID, get_capi_MessageNumber(),0);
|
||||
INFO_REQ_PLCI(&CMSG3) = ii->PLCI;
|
||||
INFO_REQ_FACILITYDATAARRAY(&CMSG3) = fac;
|
||||
_capi_put_cmsg(&CMSG3);
|
||||
|
||||
cc_qsig_do_facility(fac, i->owner, NULL, 12, 1);
|
||||
|
||||
INFO_REQ_HEADER(&CMSG3, capi_ApplID, get_capi_MessageNumber(),0);
|
||||
INFO_REQ_PLCI(&CMSG3) = i->PLCI;
|
||||
INFO_REQ_FACILITYDATAARRAY(&CMSG3) = fac;
|
||||
_capi_put_cmsg(&CMSG3);
|
||||
} else {
|
||||
cc_log(LOG_WARNING, "Call Transfer failed - second channel not found (PLCI %#x)!\n", i->qsig_data.partner_plci);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x8002: /* CALL PROCEEDING */
|
||||
break;
|
||||
case 0x8003: /* PROGRESS */
|
||||
break;
|
||||
case 0x8005: /* SETUP */
|
||||
break;
|
||||
case 0x8007: /* CONNECT */
|
||||
break;
|
||||
case 0x800d: /* SETUP ACK */
|
||||
break;
|
||||
case 0x800f: /* CONNECT ACK */
|
||||
break;
|
||||
case 0x8045: /* DISCONNECT */
|
||||
break;
|
||||
case 0x804d: /* RELEASE */
|
||||
break;
|
||||
case 0x805a: /* RELEASE COMPLETE */
|
||||
break;
|
||||
case 0x8062: /* FACILITY */
|
||||
break;
|
||||
case 0x806e: /* NOTIFY */
|
||||
break;
|
||||
case 0x807b: /* INFORMATION */
|
||||
break;
|
||||
case 0x807d: /* STATUS */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
|
@ -80,8 +80,6 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap
|
|||
*/
|
||||
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype)
|
||||
{
|
||||
const unsigned char oid[] = {0x2b,0x0c,0x09,0x00}; /* 1.3.12.9.0 */
|
||||
int oid_len = sizeof(oid);
|
||||
unsigned char namebuf[51];
|
||||
unsigned char data[255];
|
||||
int dataidx = 0;
|
||||
|
@ -106,13 +104,12 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
|
|||
}
|
||||
|
||||
invoke->id = 1;
|
||||
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
|
||||
invoke->oid_len = oid_len;
|
||||
memcpy(invoke->oid_bin, oid, oid_len);
|
||||
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*/
|
||||
|
||||
/* HACK: */
|
||||
if (nametype)
|
||||
invoke->oid_bin[3] = 2;
|
||||
invoke->type = 2;
|
||||
|
||||
if (namelen>0) {
|
||||
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
|
||||
|
@ -127,7 +124,6 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
|
|||
invoke->datalen = dataidx;
|
||||
memcpy(invoke->data, data, dataidx);
|
||||
|
||||
/* qsig_add_invoke(buf, idx, invoke); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -270,7 +266,6 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap
|
|||
*/
|
||||
void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param, int info)
|
||||
{
|
||||
const unsigned char oid[] = {0x2b,0x0c,0x09,0xc}; /* 1.3.12.9.12 */
|
||||
char *cid, *ccanswer;
|
||||
int icanswer = 0;
|
||||
int cidlen = 0;
|
||||
|
@ -278,6 +273,7 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
|
|||
char c[255];
|
||||
int ix = 0;
|
||||
|
||||
if (param) { /* got Call Transfer Parameters */
|
||||
if (info) {
|
||||
cid = strsep(¶m, "|");
|
||||
cidlen = strlen(cid);
|
||||
|
@ -295,6 +291,13 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
|
|||
if (ccanswer[0])
|
||||
icanswer = ccanswer[0] - 0x30;
|
||||
}
|
||||
} else {
|
||||
cid = strdup(i->owner->cid.cid_num);
|
||||
cidlen = strlen(cid);
|
||||
|
||||
if (!info)
|
||||
icanswer = i->qsig_data.calltransfer_onring % 1;
|
||||
}
|
||||
|
||||
seqlen += cidlen;
|
||||
|
||||
|
@ -324,16 +327,19 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
|
|||
/* there are optional data possible here */
|
||||
|
||||
invoke->id = 12;
|
||||
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
|
||||
invoke->oid_len = sizeof(oid);
|
||||
memcpy(invoke->oid_bin, oid, sizeof(oid));
|
||||
invoke->descr_type = -1;
|
||||
invoke->type = 12; /* Invoke Operation Code */
|
||||
|
||||
invoke->datalen = ix;
|
||||
memcpy(invoke->data, c, ix);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_CT: %i->%s\n", info, cid);
|
||||
|
||||
if (cid)
|
||||
free(cid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.99 ECMA/ISDN/SINGLESTEPCALLTRANSFER
|
||||
*
|
||||
|
@ -352,7 +358,6 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
|
|||
*/
|
||||
void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
|
||||
{
|
||||
const unsigned char oid[] = {0x2b,0x0c,0x09,0x63}; /* 1.3.12.9.99 */
|
||||
char *cidsrc, *ciddst;
|
||||
int srclen, dstlen;
|
||||
int seqlen = 12;
|
||||
|
@ -398,9 +403,8 @@ void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx,
|
|||
/* there are optional data possible here */
|
||||
|
||||
invoke->id = 99;
|
||||
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
|
||||
invoke->oid_len = sizeof(oid);
|
||||
memcpy(invoke->oid_bin, oid, sizeof(oid));
|
||||
invoke->descr_type = -1;
|
||||
invoke->type = 99;
|
||||
|
||||
invoke->datalen = ix;
|
||||
memcpy(invoke->data, c, ix);
|
||||
|
@ -498,7 +502,7 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca
|
|||
void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
|
||||
{
|
||||
/* TODO: write code */
|
||||
const unsigned char oid[] = {0x2b,0x0c,0x09,0x13}; /* 1.3.12.9.99 */
|
||||
// int invokeop = 19;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue