ECT should work now (not yet really tested).
parent
ab3ff868aa
commit
aef27548d5
21
README
21
README
|
@ -137,17 +137,16 @@ Retrieve:
|
|||
or
|
||||
exten => s,1,capicommand(retrieve|${MYHOLDVAR})
|
||||
|
||||
|
||||
Helper applications
|
||||
===================
|
||||
|
||||
app_capiECT.c
|
||||
Explicit call transfer of the call on hold (must put call on hold first!)
|
||||
Example:
|
||||
exten => s,1,Answer
|
||||
exten => s,2,capicommand(hold)
|
||||
exten => s,3,capiECT,55:50
|
||||
Will ECT the call to 50 using 55 as the callerid/outgoing MSN
|
||||
ECT:
|
||||
Explicit call transfer of the call on hold (must put call on hold first!)
|
||||
Example:
|
||||
exten => s,1,capicommand(ect|${MYHOLDVAR})
|
||||
or
|
||||
[macro-capiect]
|
||||
exten => s,1,capicommand(ect)
|
||||
[default]
|
||||
exten => s,1,capicommand(hold)
|
||||
exten => s,2,Dial(CAPI/1234,60,M(capiect))
|
||||
|
||||
|
||||
Using CLIR
|
||||
|
|
|
@ -26,7 +26,7 @@ softdtmf=on ;enable/disable software dtmf detection, recommended for AVM ca
|
|||
relaxdtmf=on ;in addition to softdtmf, you can use relaxed dtmf detection
|
||||
accountcode= ;Asterisk accountcode to use in CDRs
|
||||
context=capi-in ;context for incoming calls
|
||||
hold=yes ;on hold, ISDN HOLD shall be used
|
||||
hold=yes ;when Asterisk put on hold, ISDN HOLD shall be used
|
||||
;immediate=yes ;immediate start of pbx with extension 's' if no digits were
|
||||
;received on incoming call (no destination number yet)
|
||||
;echosquelch=1 ;_VERY_PRIMITIVE_ echo suppression
|
||||
|
|
106
chan_capi.c
106
chan_capi.c
|
@ -596,6 +596,13 @@ static void capi_activehangup(struct ast_channel *c)
|
|||
i->cause = atoi(cause);
|
||||
}
|
||||
|
||||
if (i->isdnstate & CAPI_ISDN_STATE_ECT) {
|
||||
cc_ast_verbose(3, 1, VERBOSE_PREFIX_3 "%s: activehangup ECT call\n",
|
||||
i->name);
|
||||
/* we do nothing, just wait for DISCONNECT_IND */
|
||||
return;
|
||||
}
|
||||
|
||||
cc_ast_verbose(2, 1, VERBOSE_PREFIX_3 "%s: activehangingup (cause=%d)\n",
|
||||
i->name, i->cause);
|
||||
|
||||
|
@ -1809,6 +1816,13 @@ static void handle_info_disconnect(_cmsg *CMSG, unsigned int PLCI, unsigned int
|
|||
{
|
||||
_cmsg CMSG2;
|
||||
|
||||
if (i->isdnstate & CAPI_ISDN_STATE_ECT) {
|
||||
cc_ast_verbose(4, 1, VERBOSE_PREFIX_3 "%s: Disconnect ECT call\n",
|
||||
i->name);
|
||||
/* we do nothing, just wait for DISCONNECT_IND */
|
||||
return;
|
||||
}
|
||||
|
||||
if (PLCI == i->onholdPLCI) {
|
||||
cc_ast_verbose(4, 1, VERBOSE_PREFIX_3 "%s: Disconnect onhold call\n",
|
||||
i->name);
|
||||
|
@ -2037,6 +2051,10 @@ static void capi_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsigned
|
|||
cc_ast_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element RELEASE COMPLETE\n",
|
||||
i->name);
|
||||
break;
|
||||
case 0x8062: /* FACILITY */
|
||||
cc_ast_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element FACILITY\n",
|
||||
i->name);
|
||||
break;
|
||||
case 0x806e: /* NOTIFY */
|
||||
cc_ast_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element NOTIFY\n",
|
||||
i->name);
|
||||
|
@ -2110,14 +2128,23 @@ static void capi_handle_facility_indication(_cmsg *CMSG, unsigned int PLCI, unsi
|
|||
ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
|
||||
ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5]);
|
||||
#endif
|
||||
/* ECT */
|
||||
if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x6) &&
|
||||
(FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2) ) {
|
||||
cc_ast_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x ECT Reason=0x%02x%02x\n",
|
||||
i->name, PLCI,
|
||||
FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],
|
||||
FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
|
||||
}
|
||||
|
||||
/* RETRIEVE */
|
||||
if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x3) &&
|
||||
(FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2) ) {
|
||||
if ((FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5] != 0) ||
|
||||
(FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4] != 0)) {
|
||||
ast_log(LOG_WARNING, "%s: unable to retrieve PLCI=%#x, REASON = 0x%02x%02x\n",
|
||||
i->name,
|
||||
PLCI, FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],
|
||||
i->name, PLCI,
|
||||
FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],
|
||||
FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
|
||||
} else {
|
||||
/* reason != 0x0000 == problem */
|
||||
|
@ -2144,9 +2171,9 @@ static void capi_handle_facility_indication(_cmsg *CMSG, unsigned int PLCI, unsi
|
|||
/* reason != 0x0000 == problem */
|
||||
i->onholdPLCI = 0;
|
||||
i->state = CAPI_STATE_BCONNECTED;
|
||||
ast_log(LOG_WARNING, "%s: unable to put PLCI=%#x onhold, REASON = %#x%#x, maybe you need to subscribe for this...\n",
|
||||
i->name,
|
||||
PLCI, FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],
|
||||
ast_log(LOG_WARNING, "%s: unable to put PLCI=%#x onhold, REASON = 0x%02x%02x, maybe you need to subscribe for this...\n",
|
||||
i->name, PLCI,
|
||||
FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],
|
||||
FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
|
||||
} else {
|
||||
/* reason = 0x0000 == call on hold */
|
||||
|
@ -3006,7 +3033,7 @@ static int capi_retrieve(struct ast_channel *c, char *param)
|
|||
if ((!plci) || (i->state != CAPI_STATE_ONHOLD)) {
|
||||
ast_log(LOG_WARNING, "%s: 0x%x is not valid or not on hold to retrieve!\n",
|
||||
i->name, plci);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
cc_ast_verbose(2, 1, VERBOSE_PREFIX_4 "%s: using PLCI=%#x for retrieve\n",
|
||||
i->name, plci);
|
||||
|
@ -3032,6 +3059,8 @@ static int capi_retrieve(struct ast_channel *c, char *param)
|
|||
i->name, plci);
|
||||
|
||||
i->isdnstate &= ~CAPI_ISDN_STATE_HOLD;
|
||||
pbx_builtin_setvar_helper(i->owner, "_CALLERHOLDID", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3042,24 +3071,32 @@ static int capi_ect(struct ast_channel *c, char *param)
|
|||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
struct ast_capi_pvt *ii = NULL;
|
||||
_cmsg CMSG;
|
||||
char fac[8];
|
||||
unsigned int plci;
|
||||
_cmsg CMSG;
|
||||
char fac[8];
|
||||
char *id;
|
||||
unsigned int plci = 0;
|
||||
int waitcount = 200;
|
||||
|
||||
return -1;
|
||||
if ((id = pbx_builtin_getvar_helper(c, "CALLERHOLDID"))) {
|
||||
plci = (unsigned int)strtoul(id, NULL, 0);
|
||||
}
|
||||
|
||||
if (param) {
|
||||
plci = (unsigned int)strtoul(param, NULL, 0);
|
||||
}
|
||||
|
||||
if ((!param) || (!strlen(param))) {
|
||||
ast_log(LOG_WARNING, "capi ECT requires an argument (held call ID)\n");
|
||||
if (!plci) {
|
||||
ast_log(LOG_WARNING, "%s: No id for ECT !\n", i->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
plci = (unsigned int)strtoul(param, NULL, 0);
|
||||
ast_mutex_lock(&iflock);
|
||||
for (ii = iflist; ii; ii = ii->next) {
|
||||
if (ii->onholdPLCI == plci)
|
||||
break;
|
||||
}
|
||||
ast_mutex_unlock(&iflock);
|
||||
|
||||
if (!ii) {
|
||||
ast_log(LOG_WARNING, "%s: 0x%x is not on hold !\n",
|
||||
i->name, plci);
|
||||
|
@ -3070,11 +3107,33 @@ static int capi_ect(struct ast_channel *c, char *param)
|
|||
i->name, plci);
|
||||
|
||||
if (!(capi_controllers[i->controller]->ECT)) {
|
||||
ast_log(LOG_NOTICE,"%s: ECT for %s not supported by controller.\n",
|
||||
ast_log(LOG_WARNING, "%s: ECT for %s not supported by controller.\n",
|
||||
i->name, c->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(ii->isdnstate & CAPI_ISDN_STATE_HOLD)) {
|
||||
ast_log(LOG_WARNING, "%s: PLCI %#x (%s) is not on hold for ECT\n",
|
||||
i->name, plci, ii->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i->state == CAPI_STATE_BCONNECTED) {
|
||||
DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, get_ast_capi_MessageNumber(), 0);
|
||||
DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
|
||||
_capi_put_cmsg(&CMSG);
|
||||
}
|
||||
|
||||
while ((i->state != CAPI_STATE_CONNECTED) && (waitcount > 0)) {
|
||||
waitcount--;
|
||||
usleep(10000);
|
||||
}
|
||||
if (i->state != CAPI_STATE_CONNECTED) {
|
||||
ast_log(LOG_WARNING, "%s: destination not connected for ECT\n",
|
||||
i->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fac[0] = 7; /* len */
|
||||
fac[1] = 0x06; /* ECT (function) */
|
||||
fac[2] = 0x00;
|
||||
|
@ -3088,6 +3147,11 @@ static int capi_ect(struct ast_channel *c, char *param)
|
|||
FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (char *)&fac;
|
||||
|
||||
_capi_put_cmsg(&CMSG);
|
||||
|
||||
ii->isdnstate &= ~CAPI_ISDN_STATE_HOLD;
|
||||
ii->isdnstate |= CAPI_ISDN_STATE_ECT;
|
||||
i->isdnstate |= CAPI_ISDN_STATE_ECT;
|
||||
|
||||
cc_ast_verbose(2, 1, VERBOSE_PREFIX_4 "%s: sent ECT for PLCI=%#x to PLCI=%#x\n",
|
||||
i->name, plci, i->PLCI);
|
||||
|
||||
|
@ -3101,8 +3165,15 @@ static int capi_hold(struct ast_channel *c, char *param)
|
|||
{
|
||||
struct ast_capi_pvt *i = CC_AST_CHANNEL_PVT(c);
|
||||
_cmsg CMSG;
|
||||
char buffer[16];
|
||||
char fac[4];
|
||||
|
||||
if (i->isdnstate & CAPI_ISDN_STATE_HOLD) {
|
||||
ast_log(LOG_NOTICE,"%s: %s already on hold.\n",
|
||||
i->name, c->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i->state != CAPI_STATE_BCONNECTED) {
|
||||
ast_log(LOG_NOTICE,"%s: Cannot put on hold %s while not connected.\n",
|
||||
i->name, c->name);
|
||||
|
@ -3131,11 +3202,11 @@ static int capi_hold(struct ast_channel *c, char *param)
|
|||
i->onholdPLCI= i->PLCI;
|
||||
i->isdnstate |= CAPI_ISDN_STATE_HOLD;
|
||||
|
||||
snprintf(buffer, sizeof(buffer) - 1, "%d", i->PLCI);
|
||||
if (param) {
|
||||
char buffer[16];
|
||||
snprintf(buffer, sizeof(buffer) - 1, "%d", i->PLCI);
|
||||
pbx_builtin_setvar_helper(i->owner, param, buffer);
|
||||
}
|
||||
pbx_builtin_setvar_helper(i->owner, "_CALLERHOLDID", buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3150,7 +3221,7 @@ static int capi_malicious(struct ast_channel *c, char *param)
|
|||
char fac[4];
|
||||
|
||||
if (!(capi_controllers[i->controller]->MCID)) {
|
||||
ast_log(LOG_NOTICE,"%s: MCID for %s not supported by controller.\n",
|
||||
ast_log(LOG_NOTICE, "%s: MCID for %s not supported by controller.\n",
|
||||
i->name, c->name);
|
||||
return -1;
|
||||
}
|
||||
|
@ -3313,6 +3384,7 @@ static int capi_indicate(struct ast_channel *c, int condition)
|
|||
case AST_CONTROL_RINGING:
|
||||
cc_ast_verbose(3, 1, VERBOSE_PREFIX_2 "%s: Requested RINGING-Indication for %s\n",
|
||||
i->name, c->name);
|
||||
#warning TODO somehow enable unhold on ringing, but when wanted only
|
||||
/* if (i->isdnstate & CAPI_ISDN_STATE_HOLD) */
|
||||
/* capi_retrieve(c, NULL); */
|
||||
ret = capi_alert(c);
|
||||
|
|
|
@ -164,6 +164,7 @@ struct ast_capi_gains {
|
|||
|
||||
#define CAPI_ISDN_STATE_SETUP_ACK 0x01
|
||||
#define CAPI_ISDN_STATE_HOLD 0x02
|
||||
#define CAPI_ISDN_STATE_ECT 0x04
|
||||
|
||||
/* ! Private data for a capi device */
|
||||
struct ast_capi_pvt {
|
||||
|
|
Loading…
Reference in New Issue