2007-05-22 22:07:05 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2007, Anthony Minessale II
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* * Neither the name of the original author; nor the names of any contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
|
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "openzap.h"
|
2007-05-24 03:42:40 +00:00
|
|
|
#include "zap_analog.h"
|
|
|
|
|
2007-06-15 22:07:53 +00:00
|
|
|
#ifndef localtime_r
|
|
|
|
struct tm * localtime_r(const time_t *clock, struct tm *result);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
static void *zap_analog_channel_run(zap_thread_t *me, void *obj);
|
|
|
|
|
|
|
|
static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call)
|
|
|
|
{
|
2007-06-01 00:31:50 +00:00
|
|
|
if (!zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK) && !zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) {
|
2007-11-17 01:39:28 +00:00
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_TRACE_INPUT, "/tmp/inbound.ul");
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_TRACE_OUTPUT, "/tmp/outbound.ul");
|
2007-06-21 00:00:10 +00:00
|
|
|
zap_channel_clear_needed_tones(zchan);
|
|
|
|
zap_channel_clear_detected_tones(zchan);
|
|
|
|
|
2007-06-01 00:31:50 +00:00
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_OFFHOOK, NULL);
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_ENABLE_PROGRESS_DETECT, NULL);
|
2007-06-01 15:25:36 +00:00
|
|
|
zchan->needed_tones[ZAP_TONEMAP_DIAL] = 1;
|
2007-06-01 00:31:50 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DIALING);
|
|
|
|
zap_thread_create_detached(zap_analog_channel_run, zchan);
|
|
|
|
return ZAP_SUCCESS;
|
|
|
|
}
|
2007-06-11 18:15:09 +00:00
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
return ZAP_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call)
|
|
|
|
{
|
|
|
|
|
2007-06-11 18:15:09 +00:00
|
|
|
if (zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_CALLWAITING);
|
|
|
|
} else {
|
2007-05-31 20:15:16 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_GENRING);
|
|
|
|
zap_thread_create_detached(zap_analog_channel_run, zchan);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ZAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-05-24 21:57:03 +00:00
|
|
|
zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, zio_signal_cb_t sig_cb)
|
2007-05-24 03:42:40 +00:00
|
|
|
{
|
2007-06-25 05:26:37 +00:00
|
|
|
zap_analog_data_t *analog_data;
|
2007-05-24 21:57:03 +00:00
|
|
|
assert(sig_cb != NULL);
|
|
|
|
|
2007-05-24 03:42:40 +00:00
|
|
|
if (span->signal_type) {
|
|
|
|
snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
|
|
|
|
return ZAP_FAIL;
|
|
|
|
}
|
2007-05-24 16:42:38 +00:00
|
|
|
|
2007-05-24 21:57:03 +00:00
|
|
|
if (digit_timeout < 2000 || digit_timeout > 10000) {
|
|
|
|
digit_timeout = 2000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_dialstr < 2 || max_dialstr > 20) {
|
|
|
|
max_dialstr = 11;
|
|
|
|
}
|
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
analog_data = malloc(sizeof(*analog_data));
|
|
|
|
memset(analog_data, 0, sizeof(*analog_data));
|
|
|
|
assert(analog_data != NULL);
|
2007-05-24 21:57:03 +00:00
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
analog_data->digit_timeout = digit_timeout;
|
|
|
|
analog_data->max_dialstr = max_dialstr;
|
|
|
|
analog_data->sig_cb = sig_cb;
|
2007-05-24 03:42:40 +00:00
|
|
|
span->signal_type = ZAP_SIGTYPE_ANALOG;
|
2007-06-25 05:26:37 +00:00
|
|
|
span->signal_data = analog_data;
|
2007-05-31 20:15:16 +00:00
|
|
|
span->outgoing_call = span->trunk_type == ZAP_TRUNK_FXS ? analog_fxs_outgoing_call : analog_fxo_outgoing_call;
|
2007-05-24 16:42:38 +00:00
|
|
|
zap_span_load_tones(span, tonemap);
|
2007-05-24 21:57:03 +00:00
|
|
|
|
2007-05-24 03:42:40 +00:00
|
|
|
return ZAP_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
|
|
|
|
{
|
|
|
|
zap_buffer_t *dt_buffer = ts->user_data;
|
|
|
|
int wrote;
|
|
|
|
|
|
|
|
if (!dt_buffer) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
wrote = teletone_mux_tones(ts, map);
|
|
|
|
zap_buffer_write(dt_buffer, ts->buffer, wrote * 2);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
static void send_caller_id(zap_channel_t *zchan)
|
2007-06-11 18:15:09 +00:00
|
|
|
{
|
|
|
|
zap_fsk_data_state_t fsk_data;
|
|
|
|
uint8_t databuf[1024] = "";
|
|
|
|
char time_str[9];
|
|
|
|
struct tm tm;
|
|
|
|
time_t now;
|
|
|
|
zap_mdmf_type_t mt = MDMF_INVALID;
|
|
|
|
|
|
|
|
time(&now);
|
|
|
|
#ifdef WIN32
|
|
|
|
_tzset();
|
|
|
|
_localtime64_s(&tm, &now);
|
|
|
|
#else
|
|
|
|
localtime_r(&now, &tm);
|
|
|
|
#endif
|
|
|
|
strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm);
|
|
|
|
|
|
|
|
zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf));
|
|
|
|
zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8);
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_strlen_zero(zchan->caller_data.cid_num)) {
|
2007-06-11 18:15:09 +00:00
|
|
|
mt = MDMF_NO_NUM;
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_string(zchan->caller_data.cid_num, "O");
|
|
|
|
} else if (!strcasecmp(zchan->caller_data.cid_num, "P") || !strcasecmp(zchan->caller_data.cid_num, "O")) {
|
2007-06-11 18:15:09 +00:00
|
|
|
mt = MDMF_NO_NUM;
|
|
|
|
} else {
|
|
|
|
mt = MDMF_PHONE_NUM;
|
|
|
|
}
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) zchan->caller_data.cid_num, (uint8_t)strlen(zchan->caller_data.cid_num));
|
2007-06-11 18:15:09 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_strlen_zero(zchan->caller_data.cid_name)) {
|
2007-06-11 18:15:09 +00:00
|
|
|
mt = MDMF_NO_NAME;
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_string(zchan->caller_data.cid_name, "O");
|
|
|
|
} else if (!strcasecmp(zchan->caller_data.cid_name, "P") || !strcasecmp(zchan->caller_data.cid_name, "O")) {
|
2007-06-11 18:15:09 +00:00
|
|
|
mt = MDMF_NO_NAME;
|
|
|
|
} else {
|
|
|
|
mt = MDMF_PHONE_NAME;
|
|
|
|
}
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) zchan->caller_data.cid_name, (uint8_t)strlen(zchan->caller_data.cid_name));
|
2007-06-11 18:15:09 +00:00
|
|
|
|
|
|
|
zap_fsk_data_add_checksum(&fsk_data);
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_send_fsk_data(zchan, &fsk_data, -14);
|
2007-06-11 18:15:09 +00:00
|
|
|
}
|
|
|
|
|
2007-05-24 03:42:40 +00:00
|
|
|
static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_t *zchan = (zap_channel_t *) obj;
|
2007-05-24 03:42:40 +00:00
|
|
|
zap_buffer_t *dt_buffer = NULL;
|
|
|
|
teletone_generation_session_t ts;
|
|
|
|
uint8_t frame[1024];
|
|
|
|
zap_size_t len, rlen;
|
|
|
|
zap_tone_type_t tt = ZAP_TONE_DTMF;
|
2007-05-27 18:14:49 +00:00
|
|
|
char dtmf[128] = "";
|
2007-05-27 04:42:10 +00:00
|
|
|
zap_size_t dtmf_offset = 0;
|
2007-06-25 05:26:37 +00:00
|
|
|
zap_analog_data_t *analog_data = zchan->span->signal_data;
|
2007-05-24 21:57:03 +00:00
|
|
|
zap_channel_t *closed_chan;
|
2007-06-01 15:25:36 +00:00
|
|
|
uint32_t state_counter = 0, elapsed = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
|
2007-05-24 21:57:03 +00:00
|
|
|
zap_sigmsg_t sig;
|
2007-05-26 03:27:31 +00:00
|
|
|
zap_status_t status;
|
2007-06-01 00:31:50 +00:00
|
|
|
|
2007-05-24 03:42:40 +00:00
|
|
|
zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
|
|
|
|
|
2007-05-27 04:42:10 +00:00
|
|
|
ts.buffer = NULL;
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) {
|
2007-06-09 14:23:02 +00:00
|
|
|
zap_log(ZAP_LOG_ERROR, "OPEN ERROR\n");
|
2007-05-24 03:42:40 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zap_buffer_create(&dt_buffer, 1024, 3192, 0) != ZAP_SUCCESS) {
|
2007-06-21 02:13:41 +00:00
|
|
|
snprintf(zchan->last_error, sizeof(zchan->last_error), "memory error!");
|
2007-06-09 14:23:02 +00:00
|
|
|
zap_log(ZAP_LOG_ERROR, "MEM ERROR\n");
|
2007-05-24 03:42:40 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_channel_command(zchan, ZAP_COMMAND_ENABLE_DTMF_DETECT, &tt) != ZAP_SUCCESS) {
|
|
|
|
snprintf(zchan->last_error, sizeof(zchan->last_error), "error initilizing tone detector!");
|
2007-06-09 14:23:02 +00:00
|
|
|
zap_log(ZAP_LOG_ERROR, "TONE ERROR\n");
|
2007-05-24 03:42:40 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_flag_locked(zchan, ZAP_CHANNEL_INTHREAD);
|
2007-05-24 03:42:40 +00:00
|
|
|
teletone_init_session(&ts, 0, teletone_handler, dt_buffer);
|
2007-05-24 16:42:38 +00:00
|
|
|
ts.rate = 8000;
|
2007-06-07 05:30:09 +00:00
|
|
|
#if 0
|
|
|
|
ts.debug = 1;
|
|
|
|
ts.debug_stream = stdout;
|
|
|
|
#endif
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_GET_INTERVAL, &interval);
|
2007-05-24 21:57:03 +00:00
|
|
|
zap_buffer_set_loops(dt_buffer, -1);
|
2007-05-27 18:14:49 +00:00
|
|
|
|
|
|
|
memset(&sig, 0, sizeof(sig));
|
2007-06-21 02:13:41 +00:00
|
|
|
sig.chan_id = zchan->chan_id;
|
|
|
|
sig.span_id = zchan->span_id;
|
|
|
|
sig.channel = zchan;
|
2007-06-27 19:18:13 +00:00
|
|
|
|
|
|
|
assert(interval != 0);
|
2007-05-24 03:42:40 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
while (zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) {
|
2007-05-24 03:42:40 +00:00
|
|
|
zap_wait_flag_t flags = ZAP_READ;
|
|
|
|
zap_size_t dlen = 0;
|
2007-05-25 23:39:01 +00:00
|
|
|
|
2007-05-24 03:42:40 +00:00
|
|
|
len = sizeof(frame);
|
2007-05-24 21:57:03 +00:00
|
|
|
|
|
|
|
elapsed += interval;
|
|
|
|
state_counter += interval;
|
2007-05-25 23:39:01 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (!zap_test_flag(zchan, ZAP_CHANNEL_STATE_CHANGE)) {
|
|
|
|
switch(zchan->state) {
|
2007-06-05 16:57:32 +00:00
|
|
|
case ZAP_CHANNEL_STATE_GET_CALLERID:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
if (state_counter > 5000 || !zap_test_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT)) {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_IDLE);
|
2007-06-05 16:57:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-06-01 00:31:50 +00:00
|
|
|
case ZAP_CHANNEL_STATE_DIALING:
|
|
|
|
{
|
2007-06-01 15:25:36 +00:00
|
|
|
if (state_counter > dial_timeout) {
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->needed_tones[ZAP_TONEMAP_DIAL]) {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
|
2007-06-01 00:31:50 +00:00
|
|
|
} else {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
|
2007-06-01 00:31:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-05-31 20:15:16 +00:00
|
|
|
case ZAP_CHANNEL_STATE_GENRING:
|
|
|
|
{
|
|
|
|
if (state_counter > 60000) {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
|
|
|
|
} else if (!zchan->fsk_buffer || !zap_buffer_inuse(zchan->fsk_buffer)) {
|
2007-05-31 20:15:16 +00:00
|
|
|
zap_sleep(interval);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-05-24 21:57:03 +00:00
|
|
|
case ZAP_CHANNEL_STATE_DIALTONE:
|
|
|
|
{
|
|
|
|
if (state_counter > 10000) {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_BUSY:
|
|
|
|
{
|
|
|
|
if (state_counter > 20000) {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_ATTN);
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-06-05 16:57:32 +00:00
|
|
|
case ZAP_CHANNEL_STATE_ATTN:
|
|
|
|
{
|
|
|
|
if (state_counter > 20000) {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
|
2007-06-05 16:57:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-05-27 14:58:01 +00:00
|
|
|
case ZAP_CHANNEL_STATE_HANGUP:
|
|
|
|
{
|
2007-06-09 14:23:02 +00:00
|
|
|
if (state_counter > 500) {
|
2007-11-17 01:39:28 +00:00
|
|
|
if (zap_test_flag(zchan, ZAP_CHANNEL_RINGING)) {
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
|
|
|
}
|
|
|
|
|
2007-06-21 03:31:07 +00:00
|
|
|
if (zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK) && zchan->last_state >= ZAP_CHANNEL_STATE_IDLE) {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
|
2007-06-09 14:23:02 +00:00
|
|
|
} else {
|
2007-11-17 01:39:28 +00:00
|
|
|
zchan->caller_data.hangup_cause = ZAP_CAUSE_NORMAL_CLEARING;
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
|
2007-06-09 14:23:02 +00:00
|
|
|
}
|
2007-05-27 14:58:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-06-11 18:15:09 +00:00
|
|
|
case ZAP_CHANNEL_STATE_CALLWAITING:
|
|
|
|
{
|
|
|
|
int done = 0;
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) {
|
|
|
|
send_caller_id(zchan);
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
|
|
|
|
} else if (state_counter > 600 && !zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) {
|
|
|
|
send_caller_id(zchan);
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++;
|
|
|
|
} else if (state_counter > 1000 && !zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) {
|
2007-06-11 18:15:09 +00:00
|
|
|
done = 1;
|
|
|
|
} else if (state_counter > 10000) {
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->fsk_buffer) {
|
|
|
|
zap_buffer_zero(zchan->fsk_buffer);
|
2007-06-11 18:15:09 +00:00
|
|
|
} else {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0);
|
2007-06-11 18:15:09 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
ts.user_data = zchan->fsk_buffer;
|
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]);
|
2007-06-11 18:15:09 +00:00
|
|
|
ts.user_data = dt_buffer;
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (done) {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
|
|
|
|
zap_clear_flag_locked(zchan, ZAP_CHANNEL_STATE_CHANGE);
|
|
|
|
zap_clear_flag_locked(zchan->span, ZAP_SPAN_STATE_CHANGE);
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0;
|
2007-06-11 18:15:09 +00:00
|
|
|
}
|
|
|
|
}
|
2007-05-24 21:57:03 +00:00
|
|
|
case ZAP_CHANNEL_STATE_UP:
|
|
|
|
case ZAP_CHANNEL_STATE_IDLE:
|
|
|
|
{
|
2007-05-25 14:42:34 +00:00
|
|
|
zap_sleep(interval);
|
|
|
|
continue;
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
break;
|
2007-05-31 02:41:50 +00:00
|
|
|
case ZAP_CHANNEL_STATE_DOWN:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_done(zchan);
|
2007-05-31 02:41:50 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
break;
|
2007-05-24 21:57:03 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_clear_flag_locked(zchan, ZAP_CHANNEL_STATE_CHANGE);
|
|
|
|
zap_clear_flag_locked(zchan->span, ZAP_SPAN_STATE_CHANGE);
|
2007-05-26 03:27:31 +00:00
|
|
|
indicate = 0;
|
|
|
|
state_counter = 0;
|
2007-11-17 01:39:28 +00:00
|
|
|
zap_log(ZAP_LOG_DEBUG, "Executing state handler on %d:%d for %s\n",
|
|
|
|
zchan->span_id, zchan->chan_id,
|
|
|
|
zap_channel_state2str(zchan->state));
|
2007-06-21 02:13:41 +00:00
|
|
|
switch(zchan->state) {
|
2007-05-24 21:57:03 +00:00
|
|
|
case ZAP_CHANNEL_STATE_UP:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_use(zchan);
|
|
|
|
zap_channel_clear_needed_tones(zchan);
|
2007-05-31 20:15:16 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXO && !zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK)) {
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_OFFHOOK, NULL);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->fsk_buffer && zap_buffer_inuse(zchan->fsk_buffer)) {
|
2007-06-09 14:23:02 +00:00
|
|
|
zap_log(ZAP_LOG_DEBUG, "Cancel FSK transmit due to early answer.\n");
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_buffer_zero(zchan->fsk_buffer);
|
2007-06-09 14:23:02 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(zchan, ZAP_CHANNEL_RINGING)) {
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_test_flag(zchan, ZAP_CHANNEL_HOLD)) {
|
|
|
|
zap_clear_flag(zchan, ZAP_CHANNEL_HOLD);
|
2007-05-31 02:41:50 +00:00
|
|
|
sig.event_id = ZAP_SIGEVENT_FLASH;
|
2007-05-27 18:14:49 +00:00
|
|
|
} else {
|
|
|
|
sig.event_id = ZAP_SIGEVENT_UP;
|
|
|
|
}
|
2007-05-31 02:41:50 +00:00
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
analog_data->sig_cb(&sig);
|
2007-05-24 21:57:03 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2007-06-01 00:31:50 +00:00
|
|
|
case ZAP_CHANNEL_STATE_DIALING:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_use(zchan);
|
2007-06-01 00:31:50 +00:00
|
|
|
}
|
|
|
|
break;
|
2007-05-24 21:57:03 +00:00
|
|
|
case ZAP_CHANNEL_STATE_IDLE:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_use(zchan);
|
2007-05-24 21:57:03 +00:00
|
|
|
sig.event_id = ZAP_SIGEVENT_START;
|
2007-06-05 16:57:32 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXO) {
|
|
|
|
zap_set_string(zchan->caller_data.dnis, zchan->chan_number);
|
2007-06-05 16:57:32 +00:00
|
|
|
} else {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_string(zchan->caller_data.dnis, dtmf);
|
2007-06-05 16:57:32 +00:00
|
|
|
}
|
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
analog_data->sig_cb(&sig);
|
2007-05-25 23:39:01 +00:00
|
|
|
continue;
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_DOWN:
|
|
|
|
{
|
|
|
|
sig.event_id = ZAP_SIGEVENT_STOP;
|
2007-06-25 05:26:37 +00:00
|
|
|
analog_data->sig_cb(&sig);
|
2007-11-17 01:39:28 +00:00
|
|
|
zap_channel_done(zchan);
|
2007-05-24 21:57:03 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_DIALTONE:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_done(zchan);
|
2007-05-27 18:14:49 +00:00
|
|
|
*dtmf = '\0';
|
|
|
|
dtmf_offset = 0;
|
2007-05-24 21:57:03 +00:00
|
|
|
zap_buffer_zero(dt_buffer);
|
2007-06-21 02:13:41 +00:00
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_DIAL]);
|
2007-05-24 21:57:03 +00:00
|
|
|
indicate = 1;
|
|
|
|
}
|
|
|
|
break;
|
2007-06-11 18:15:09 +00:00
|
|
|
case ZAP_CHANNEL_STATE_CALLWAITING:
|
2007-05-31 20:15:16 +00:00
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0;
|
|
|
|
if (zchan->fsk_buffer) {
|
|
|
|
zap_buffer_zero(zchan->fsk_buffer);
|
2007-06-09 14:23:02 +00:00
|
|
|
} else {
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0);
|
2007-06-09 14:23:02 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
ts.user_data = zchan->fsk_buffer;
|
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]);
|
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]);
|
2007-06-11 18:15:09 +00:00
|
|
|
ts.user_data = dt_buffer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_GENRING:
|
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
send_caller_id(zchan);
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
break;
|
2007-06-05 16:57:32 +00:00
|
|
|
case ZAP_CHANNEL_STATE_GET_CALLERID:
|
2007-05-24 21:57:03 +00:00
|
|
|
{
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_done(zchan);
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_ENABLE_CALLERID_DETECT, NULL);
|
2007-06-15 08:16:38 +00:00
|
|
|
continue;
|
2007-06-05 16:57:32 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_RING:
|
|
|
|
{
|
2007-05-24 21:57:03 +00:00
|
|
|
zap_buffer_zero(dt_buffer);
|
2007-06-21 02:13:41 +00:00
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_RING]);
|
2007-05-24 21:57:03 +00:00
|
|
|
indicate = 1;
|
2007-06-05 16:57:32 +00:00
|
|
|
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_BUSY:
|
|
|
|
{
|
2007-11-17 01:39:28 +00:00
|
|
|
zchan->caller_data.hangup_cause = ZAP_CAUSE_NORMAL_CIRCUIT_CONGESTION;
|
|
|
|
if (zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK) && !zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) {
|
|
|
|
zap_channel_done(zchan);
|
|
|
|
zap_buffer_zero(dt_buffer);
|
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_BUSY]);
|
|
|
|
indicate = 1;
|
|
|
|
} else {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
|
|
|
|
}
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_CHANNEL_STATE_ATTN:
|
|
|
|
{
|
2007-11-17 01:39:28 +00:00
|
|
|
if (zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK) && !zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) {
|
|
|
|
zap_channel_done(zchan);
|
|
|
|
zap_buffer_zero(dt_buffer);
|
|
|
|
teletone_run(&ts, zchan->span->tone_map[ZAP_TONEMAP_ATTN]);
|
|
|
|
indicate = 1;
|
|
|
|
} else {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
|
|
|
|
}
|
2007-05-24 21:57:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-05-25 23:39:01 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if ((dlen = zap_channel_dequeue_dtmf(zchan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) {
|
|
|
|
if (zchan->state == ZAP_CHANNEL_STATE_DIALTONE || zchan->state == ZAP_CHANNEL_STATE_COLLECT) {
|
2007-05-31 20:15:16 +00:00
|
|
|
zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset);
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->state == ZAP_CHANNEL_STATE_DIALTONE) {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_COLLECT);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
dtmf_offset = strlen(dtmf);
|
|
|
|
last_digit = elapsed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
if (last_digit && ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr)) {
|
2007-05-31 20:15:16 +00:00
|
|
|
zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_IDLE);
|
2007-05-31 20:15:16 +00:00
|
|
|
last_digit = 0;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_channel_wait(zchan, &flags, interval * 2) != ZAP_SUCCESS) {
|
2007-05-31 20:15:16 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flags & ZAP_READ)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zap_channel_read(zchan, frame, &len) != ZAP_SUCCESS) {
|
2007-06-09 14:23:02 +00:00
|
|
|
zap_log(ZAP_LOG_ERROR, "READ ERROR\n");
|
2007-05-31 20:15:16 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXO && zchan->detected_tones[0]) {
|
2007-06-01 00:31:50 +00:00
|
|
|
zap_sigmsg_t sig;
|
2007-06-01 15:25:36 +00:00
|
|
|
int i;
|
2007-06-01 00:31:50 +00:00
|
|
|
memset(&sig, 0, sizeof(sig));
|
2007-06-21 02:13:41 +00:00
|
|
|
sig.chan_id = zchan->chan_id;
|
|
|
|
sig.span_id = zchan->span_id;
|
|
|
|
sig.channel = zchan;
|
2007-06-01 00:31:50 +00:00
|
|
|
sig.event_id = ZAP_SIGEVENT_TONE_DETECTED;
|
|
|
|
|
2007-06-01 15:25:36 +00:00
|
|
|
for (i = 1; i < ZAP_TONEMAP_INVALID; i++) {
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->detected_tones[i]) {
|
2007-11-17 01:39:28 +00:00
|
|
|
zap_log(ZAP_LOG_DEBUG, "Detected tone %s on %d:%d\n", zap_tonemap2str(i), zchan->span_id, zchan->chan_id);
|
2007-06-01 15:25:36 +00:00
|
|
|
sig.raw_data = &i;
|
2007-11-17 01:39:28 +00:00
|
|
|
if (analog_data->sig_cb) {
|
|
|
|
analog_data->sig_cb(&sig);
|
|
|
|
}
|
2007-06-01 00:31:50 +00:00
|
|
|
}
|
|
|
|
}
|
2007-06-01 15:25:36 +00:00
|
|
|
|
2007-11-17 01:39:28 +00:00
|
|
|
if (zchan->detected_tones[ZAP_TONEMAP_BUSY] ||
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_FAIL1] ||
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_FAIL2] ||
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_FAIL3] ||
|
|
|
|
zchan->detected_tones[ZAP_TONEMAP_ATTN]
|
|
|
|
) {
|
|
|
|
zap_log(ZAP_LOG_ERROR, "Failure indication detected!\n");
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
|
|
|
|
} else if (zchan->detected_tones[ZAP_TONEMAP_DIAL]) {
|
|
|
|
if (zap_strlen_zero(zchan->caller_data.ani)) {
|
|
|
|
zap_log(ZAP_LOG_ERROR, "No Digits to send!\n");
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
|
|
|
|
} else {
|
|
|
|
if (zap_channel_command(zchan, ZAP_COMMAND_SEND_DTMF, zchan->caller_data.ani) != ZAP_SUCCESS) {
|
|
|
|
zap_log(ZAP_LOG_ERROR, "Send Digits Failed [%s]\n", zchan->last_error);
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_BUSY);
|
|
|
|
} else {
|
|
|
|
state_counter = 0;
|
|
|
|
zchan->needed_tones[ZAP_TONEMAP_RING] = 1;
|
|
|
|
zchan->needed_tones[ZAP_TONEMAP_BUSY] = 1;
|
|
|
|
zchan->needed_tones[ZAP_TONEMAP_FAIL1] = 1;
|
|
|
|
zchan->needed_tones[ZAP_TONEMAP_FAIL2] = 1;
|
|
|
|
zchan->needed_tones[ZAP_TONEMAP_FAIL3] = 1;
|
|
|
|
dial_timeout = ((zchan->dtmf_on + zchan->dtmf_off) * strlen(zchan->caller_data.ani)) + 3000;
|
|
|
|
}
|
|
|
|
}
|
2007-06-21 02:13:41 +00:00
|
|
|
} else if (zchan->detected_tones[ZAP_TONEMAP_RING]) {
|
|
|
|
zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP);
|
2007-06-01 15:25:36 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_clear_detected_tones(zchan);
|
2007-06-01 00:31:50 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if ((zchan->dtmf_buffer && zap_buffer_inuse(zchan->dtmf_buffer)) || (zchan->fsk_buffer && zap_buffer_inuse(zchan->fsk_buffer))) {
|
2007-06-01 00:31:50 +00:00
|
|
|
rlen = len;
|
|
|
|
memset(frame, 0, len);
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_write(zchan, frame, sizeof(frame), &rlen);
|
2007-06-01 00:31:50 +00:00
|
|
|
continue;
|
|
|
|
}
|
2007-06-05 16:57:32 +00:00
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
if (!indicate) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXO && !zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK)) {
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_OFFHOOK, NULL);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->effective_codec != ZAP_CODEC_SLIN) {
|
2007-05-31 20:15:16 +00:00
|
|
|
len *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
rlen = zap_buffer_read_loop(dt_buffer, frame, len);
|
2007-06-01 00:31:50 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->effective_codec != ZAP_CODEC_SLIN) {
|
2007-05-31 20:15:16 +00:00
|
|
|
zio_codec_t codec_func = NULL;
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->native_codec == ZAP_CODEC_ULAW) {
|
2007-05-31 20:15:16 +00:00
|
|
|
codec_func = zio_slin2ulaw;
|
2007-06-21 02:13:41 +00:00
|
|
|
} else if (zchan->native_codec == ZAP_CODEC_ALAW) {
|
2007-05-31 20:15:16 +00:00
|
|
|
codec_func = zio_slin2alaw;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (codec_func) {
|
|
|
|
status = codec_func(frame, sizeof(frame), &rlen);
|
|
|
|
} else {
|
2007-06-21 02:13:41 +00:00
|
|
|
snprintf(zchan->last_error, sizeof(zchan->last_error), "codec error!");
|
2007-05-31 20:15:16 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_write(zchan, frame, sizeof(frame), &rlen);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
2007-11-17 01:39:28 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
zap_channel_done(zchan);
|
2007-06-27 19:18:13 +00:00
|
|
|
|
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXO && zap_test_flag(zchan, ZAP_CHANNEL_OFFHOOK)) {
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_ONHOOK, NULL);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
2007-05-25 23:39:01 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
if (zchan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(zchan, ZAP_CHANNEL_RINGING)) {
|
|
|
|
zap_channel_command(zchan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
2007-05-26 03:27:31 +00:00
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
|
2007-06-21 02:13:41 +00:00
|
|
|
closed_chan = zchan;
|
|
|
|
zap_channel_close(&zchan);
|
2007-05-26 03:27:31 +00:00
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
zap_channel_command(closed_chan, ZAP_COMMAND_SET_NATIVE_CODEC, NULL);
|
2007-05-26 03:27:31 +00:00
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
if (ts.buffer) {
|
|
|
|
teletone_destroy_session(&ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dt_buffer) {
|
|
|
|
zap_buffer_destroy(&dt_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
zap_clear_flag(closed_chan, ZAP_CHANNEL_INTHREAD);
|
|
|
|
|
|
|
|
zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread ended.\n");
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-06-23 18:51:10 +00:00
|
|
|
static __inline__ zap_status_t process_event(zap_span_t *span, zap_event_t *event)
|
2007-05-31 20:15:16 +00:00
|
|
|
{
|
|
|
|
zap_sigmsg_t sig;
|
2007-06-25 05:26:37 +00:00
|
|
|
zap_analog_data_t *analog_data = event->channel->span->signal_data;
|
2007-05-31 20:15:16 +00:00
|
|
|
|
|
|
|
memset(&sig, 0, sizeof(sig));
|
|
|
|
sig.chan_id = event->channel->chan_id;
|
|
|
|
sig.span_id = event->channel->span_id;
|
|
|
|
sig.channel = event->channel;
|
|
|
|
|
|
|
|
|
|
|
|
zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n",
|
|
|
|
zap_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, zap_channel_state2str(event->channel->state));
|
|
|
|
|
|
|
|
zap_mutex_lock(event->channel->mutex);
|
|
|
|
|
|
|
|
|
|
|
|
switch(event->enum_id) {
|
|
|
|
case ZAP_OOB_RING_START:
|
|
|
|
{
|
|
|
|
|
|
|
|
if (event->channel->state == ZAP_CHANNEL_STATE_DOWN && !zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
|
2007-06-05 16:57:32 +00:00
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_GET_CALLERID);
|
2007-06-15 08:16:38 +00:00
|
|
|
event->channel->ring_count = 1;
|
2007-05-31 20:15:16 +00:00
|
|
|
zap_thread_create_detached(zap_analog_channel_run, event->channel);
|
2007-06-15 08:16:38 +00:00
|
|
|
} else {
|
|
|
|
event->channel->ring_count++;
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_OOB_ONHOOK:
|
|
|
|
{
|
2007-06-27 19:18:13 +00:00
|
|
|
if (zap_test_flag(event->channel, ZAP_CHANNEL_RINGING)) {
|
|
|
|
zap_channel_command(event->channel, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
|
|
|
}
|
2007-11-17 01:39:28 +00:00
|
|
|
|
|
|
|
if (event->channel->state != ZAP_CHANNEL_STATE_DOWN) {
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN);
|
|
|
|
}
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_OOB_FLASH:
|
|
|
|
{
|
2007-06-11 18:15:09 +00:00
|
|
|
if (event->channel->state == ZAP_CHANNEL_STATE_CALLWAITING) {
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
|
|
|
|
zap_clear_flag_locked(event->channel, ZAP_CHANNEL_STATE_CHANGE);
|
2007-06-14 03:54:02 +00:00
|
|
|
zap_clear_flag_locked(event->channel->span, ZAP_SPAN_STATE_CHANGE);
|
2007-06-11 18:15:09 +00:00
|
|
|
event->channel->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0;
|
|
|
|
}
|
2007-05-31 20:15:16 +00:00
|
|
|
|
|
|
|
zap_channel_rotate_tokens(event->channel);
|
2007-06-11 18:15:09 +00:00
|
|
|
|
2007-05-31 20:15:16 +00:00
|
|
|
if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) {
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
|
|
|
|
} else {
|
2007-06-11 18:15:09 +00:00
|
|
|
sig.event_id = ZAP_SIGEVENT_FLASH;
|
2007-06-25 05:26:37 +00:00
|
|
|
analog_data->sig_cb(&sig);
|
2007-05-31 20:15:16 +00:00
|
|
|
if (event->channel->token_count == 1) {
|
|
|
|
zap_set_flag_locked(event->channel, ZAP_CHANNEL_HOLD);
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DIALTONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-27 18:14:49 +00:00
|
|
|
break;
|
2007-05-24 03:42:40 +00:00
|
|
|
case ZAP_OOB_OFFHOOK:
|
|
|
|
{
|
2007-06-20 02:54:29 +00:00
|
|
|
if (event->channel->type == ZAP_CHAN_TYPE_FXS) {
|
|
|
|
if (zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
|
|
|
|
if (zap_test_flag(event->channel, ZAP_CHANNEL_RINGING)) {
|
|
|
|
zap_channel_command(event->channel, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
|
|
|
|
}
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
|
|
|
|
} else {
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DIALTONE);
|
|
|
|
zap_thread_create_detached(zap_analog_channel_run, event->channel);
|
2007-05-31 20:15:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
2007-06-20 02:54:29 +00:00
|
|
|
if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
|
|
|
|
if (zap_test_flag(event->channel, ZAP_CHANNEL_OFFHOOK)) {
|
|
|
|
zap_channel_command(event->channel, ZAP_COMMAND_ONHOOK, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN);
|
2007-05-24 03:42:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-31 20:15:16 +00:00
|
|
|
|
2007-05-27 18:14:49 +00:00
|
|
|
zap_mutex_unlock(event->channel->mutex);
|
2007-05-24 03:42:40 +00:00
|
|
|
return ZAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *zap_analog_run(zap_thread_t *me, void *obj)
|
|
|
|
{
|
|
|
|
zap_span_t *span = (zap_span_t *) obj;
|
2007-06-25 05:26:37 +00:00
|
|
|
zap_analog_data_t *analog_data = span->signal_data;
|
2007-05-24 03:42:40 +00:00
|
|
|
|
|
|
|
zap_log(ZAP_LOG_DEBUG, "ANALOG thread starting.\n");
|
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
while(zap_test_flag(analog_data, ZAP_ANALOG_RUNNING)) {
|
2007-05-24 03:42:40 +00:00
|
|
|
int waitms = 10;
|
|
|
|
zap_status_t status;
|
|
|
|
|
|
|
|
status = zap_span_poll_event(span, waitms);
|
|
|
|
|
|
|
|
switch(status) {
|
|
|
|
case ZAP_SUCCESS:
|
|
|
|
{
|
|
|
|
zap_event_t *event;
|
|
|
|
while (zap_span_next_event(span, &event) == ZAP_SUCCESS) {
|
2007-06-23 18:51:10 +00:00
|
|
|
if (event->enum_id == ZAP_OOB_NOOP) {
|
2007-06-20 02:54:29 +00:00
|
|
|
continue;
|
|
|
|
}
|
2007-05-24 03:42:40 +00:00
|
|
|
if (process_event(span, event) != ZAP_SUCCESS) {
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZAP_FAIL:
|
|
|
|
{
|
|
|
|
zap_log(ZAP_LOG_DEBUG, "Failure!\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
2007-06-25 05:26:37 +00:00
|
|
|
zap_clear_flag(analog_data, ZAP_ANALOG_RUNNING);
|
2007-05-24 03:42:40 +00:00
|
|
|
|
|
|
|
zap_log(ZAP_LOG_DEBUG, "ANALOG thread ending.\n");
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zap_status_t zap_analog_start(zap_span_t *span)
|
|
|
|
{
|
2007-06-25 05:26:37 +00:00
|
|
|
zap_analog_data_t *analog_data = span->signal_data;
|
|
|
|
zap_set_flag(analog_data, ZAP_ANALOG_RUNNING);
|
2007-05-24 03:42:40 +00:00
|
|
|
return zap_thread_create_detached(zap_analog_run, span);
|
|
|
|
}
|
|
|
|
|
2007-06-04 14:53:12 +00:00
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
|
|
|
* indent-tabs-mode:t
|
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
|
|
*/
|