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);
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);
}
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);
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);
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.
pri_event *e;
struct pollfd fds[SIG_PRI_NUM_DCHANS];
int res;
- int chanpos = 0;
int x;
int law;
struct ast_channel *c;
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);
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 */
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
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)) {
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:
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);
}