diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 149a773e15..03c799e0f1 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -2663,6 +2663,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ pthread_t threadid; struct ast_channel *chan; struct ast_frame *f; + struct ast_control_pvt_cause_code *cause_code; + int data_size = sizeof(*cause_code); + char *subclass = NULL; ast_debug(1, "%s %d\n", __FUNCTION__, p->channel); @@ -2693,7 +2696,29 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", analog_event2str(res), res, p->channel, idx); + /* add length of "ANALOG " */ + data_size += 7; + if (res & (ANALOG_EVENT_PULSEDIGIT | ANALOG_EVENT_DTMFUP)) { + /* add length of "ANALOG_EVENT_" */ + data_size += 13; + if (res & ANALOG_EVENT_PULSEDIGIT) { + /* add length of "PULSEDIGIT" */ + data_size += 10; + } else { + /* add length of "DTMFUP" */ + data_size += 6; + } + + /* add length of " (c)" */ + data_size += 4; + + cause_code = alloca(data_size); + ast_copy_string(cause_code->chan_name, ast_channel_name(ast), AST_CHANNEL_NAME); + snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "ANALOG ANALOG_EVENT_%s (%c)", + (res & ANALOG_EVENT_DTMFUP) ? "DTMFUP" : "PULSEDIGIT", res & 0xff); + ast_queue_control_data(ast, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size); + analog_set_pulsedial(p, (res & ANALOG_EVENT_PULSEDIGIT) ? 1 : 0); ast_debug(1, "Detected %sdigit '%c'\n", (res & ANALOG_EVENT_PULSEDIGIT) ? "pulse ": "", res & 0xff); analog_confmute(p, 0); @@ -2704,6 +2729,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ } if (res & ANALOG_EVENT_DTMFDOWN) { + /* add length of "ANALOG_EVENT_DTMFDOWN (c)" */ + data_size += 25; + + cause_code = alloca(data_size); + ast_copy_string(cause_code->chan_name, ast_channel_name(ast), AST_CHANNEL_NAME); + snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "ANALOG ANALOG_EVENT_DTMFDOWN (%c)", res & 0xff); + ast_queue_control_data(ast, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size); + ast_debug(1, "DTMF Down '%c'\n", res & 0xff); /* Mute conference */ analog_confmute(p, 1); @@ -2713,6 +2746,13 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ return f; } + subclass = analog_event2str(res); + data_size += strlen(subclass); + cause_code = alloca(data_size); + ast_copy_string(cause_code->chan_name, ast_channel_name(ast), AST_CHANNEL_NAME); + snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "ANALOG %s", subclass); + ast_queue_control_data(ast, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size); + switch (res) { case ANALOG_EVENT_EC_DISABLED: ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); diff --git a/channels/sig_pri.c b/channels/sig_pri.c index 93b9b4b8b9..ead02f5872 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -1259,6 +1259,37 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas pri_queue_frame(pri, chanpos, &f); } +/*! + * \internal + * \brief Queue a PVT_CAUSE_CODE frame onto the owner channel. + * \since 11 + * + * \param pri PRI span control structure. + * \param chanpos Channel position in the span. + * \param cause String describing the cause to be placed into the frame. + * + * \note Assumes the pri->lock is already obtained. + * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained. + * + * \return Nothing + */ +static void pri_queue_pvt_cause_data(struct sig_pri_span *pri, int chanpos, const char *cause) +{ + struct ast_channel *chan; + struct ast_control_pvt_cause_code *cause_code; + + sig_pri_lock_owner(pri, chanpos); + chan = pri->pvts[chanpos]->owner; + if (chan) { + int datalen = sizeof(*cause_code) + strlen(cause); + cause_code = alloca(datalen); + ast_copy_string(cause_code->chan_name, ast_channel_name(chan), AST_CHANNEL_NAME); + ast_copy_string(cause_code->code, cause, datalen + 1 - sizeof(*cause_code)); + ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen); + ast_channel_unlock(chan); + } +} + /*! * \internal * \brief Find the channel associated with the libpri call. @@ -5440,7 +5471,6 @@ static void *pri_dchannel(void *vpri) pri_event *e; struct pollfd fds[SIG_PRI_NUM_DCHANS]; int res; - int chanpos = 0; int x; int law; struct ast_channel *c; @@ -5648,6 +5678,9 @@ static void *pri_dchannel(void *vpri) ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); if (e) { + int chanpos = -1; + char cause_str[35]; + if (pri->debug) { ast_verbose("Span %d: Processing event %s(%d)\n", pri->span, pri_event2str(e->e), e->e); @@ -6448,6 +6481,11 @@ static void *pri_dchannel(void *vpri) e->proceeding.call); if (e->proceeding.cause > -1) { + if (pri->pvts[chanpos]->owner) { + snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_PROGRESS (%d)", e->proceeding.cause); + pri_queue_pvt_cause_data(pri, chanpos, cause_str); + } + ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); /* Work around broken, out of spec USER_BUSY cause in a progress message */ @@ -6459,6 +6497,8 @@ static void *pri_dchannel(void *vpri) pri_queue_control(pri, chanpos, AST_CONTROL_BUSY); } } + } else if (pri->pvts[chanpos]->owner) { + pri_queue_pvt_cause_data(pri, chanpos, "PRI PRI_EVENT_PROGRESS"); } if (!pri->pvts[chanpos]->progress @@ -6736,6 +6776,9 @@ static void *pri_dchannel(void *vpri) if (pri->pvts[chanpos]->owner) { int do_hangup = 0; + snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP (%d)", e->hangup.cause); + pri_queue_pvt_cause_data(pri, chanpos, cause_str); + /* Queue a BUSY instead of a hangup if our cause is appropriate */ ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause); switch (ast_channel_state(pri->pvts[chanpos]->owner)) { @@ -6885,6 +6928,9 @@ static void *pri_dchannel(void *vpri) if (pri->pvts[chanpos]->owner) { int do_hangup = 0; + snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP_REQ (%d)", e->hangup.cause); + pri_queue_pvt_cause_data(pri, chanpos, cause_str); + ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause); switch (ast_channel_state(pri->pvts[chanpos]->owner)) { case AST_STATE_BUSY: @@ -7218,6 +7264,27 @@ static void *pri_dchannel(void *vpri) pri->span, pri_event2str(e->e), e->e); break; } + + /* send tech-specific information for HANGUPCAUSE hash */ + if (chanpos > -1 && pri->pvts[chanpos]) { + switch (e->e) { + /* already handled above */ + case PRI_EVENT_PROGRESS: + case PRI_EVENT_HANGUP: + case PRI_EVENT_HANGUP_REQ: + break; + default: + sig_pri_lock_private(pri->pvts[chanpos]); + if (pri->pvts[chanpos]->owner) { + char *event_str = pri_event2str(e->e); + + snprintf(cause_str, sizeof(cause_str), "PRI %s", event_str); + pri_queue_pvt_cause_data(pri, chanpos, cause_str); + } + sig_pri_unlock_private(pri->pvts[chanpos]); + break; + } + } } ast_mutex_unlock(&pri->lock); }