zap_channel_command(zchan, ZAP_COMMAND_GET_INTERVAL, &interval);
zap_channel_command(zchan, ZAP_COMMAND_GET_CODEC, &codec);
-
switch(codec) {
case ZAP_CODEC_ULAW:
{
switch (tech_pvt->zchan->type) {
case ZAP_CHAN_TYPE_FXO:
+ {
+ if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) {
+ zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP);
+ }
+ }
+ break;
case ZAP_CHAN_TYPE_FXS:
{
if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) {
char dtmf[128] = "";
zap_status_t status;
int total_to = timeout;
- int chunk;
+ int chunk, do_break = 0;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
assert(tech_pvt->zchan != NULL);
chunk = tech_pvt->zchan->effective_interval * 2;
+
top:
- if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
+
+ if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
+ switch_clear_flag_locked(tech_pvt, TFLAG_BREAK);
+ do_break = 1;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_HOLD) || do_break) {
switch_yield(tech_pvt->zchan->effective_interval * 1000);
*frame = &tech_pvt->cng_frame;
tech_pvt->cng_frame.datalen = tech_pvt->zchan->packet_len;
return SWITCH_STATUS_BREAK;
}
}
+
goto top;
}
if (++tech_pvt->wr_error > 10) {
return SWITCH_STATUS_GENERR;
}
+ } else {
+ tech_pvt->wr_error = 0;
}
- tech_pvt->wr_error = 0;
-
return SWITCH_STATUS_SUCCESS;
}
-static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t channel_receive_message_fxo(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ switch_channel_t *channel;
+ private_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = (private_t *) switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_message_fxs(switch_core_session_t *session, switch_core_session_message_t *msg)
{
switch_channel_t *channel;
private_t *tech_pvt;
assert(tech_pvt != NULL);
switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
- zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
+ if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
+ }
break;
case SWITCH_MESSAGE_INDICATE_RINGING:
zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_RING);
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ private_t *tech_pvt;
+
+ tech_pvt = (private_t *) switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (tech_pvt->zchan->type) {
+ case ZAP_CHAN_TYPE_FXS:
+ return channel_receive_message_fxs(session, msg);
+ case ZAP_CHAN_TYPE_FXO:
+ return channel_receive_message_fxo(session, msg);
+ case ZAP_CHAN_TYPE_B:
+ return channel_receive_message_b(session, msg);
+ default:
+ return SWITCH_STATUS_FALSE;
+ }
+}
+
static const switch_state_handler_table_t channel_event_handlers = {
/*.on_init */ channel_on_init,
/*.on_ring */ channel_on_ring,
switch_core_session_t **new_session, switch_memory_pool_t **pool)
{
- char *dest;
- int span_id = 0;
+ char *p, *dest;
+ int span_id = 0, chan_id = 0;
zap_channel_t *zchan = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
char name[128];
+ zap_status_t status;
if (!outbound_profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
- if ((dest = strchr('/', outbound_profile->destination_number))) {
- dest++;
+ if ((p = strchr(outbound_profile->destination_number, '/'))) {
+ dest = p + 1;
span_id = atoi(outbound_profile->destination_number);
+ if ((p = strchr(dest, '/'))) {
+ chan_id = atoi(dest);
+ dest = p + 1;
+ }
}
if (!span_id) {
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
- if (zap_channel_open_any(span_id, ZAP_TOP_DOWN, &zchan) != ZAP_SUCCESS) {
+ if (chan_id) {
+ status = zap_channel_open(span_id, chan_id, &zchan);
+ } else {
+ status = zap_channel_open_any(span_id, ZAP_TOP_DOWN, &zchan);
+
+ }
+
+ if (status != ZAP_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels available\n");
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
goto fail;
}
- snprintf(name, sizeof(name), "OPENZAP/%s", outbound_profile->destination_number);
+ snprintf(name, sizeof(name), "OPENZAP/%s", dest);
switch_channel_set_name(channel, name);
-
+ zap_set_string(zchan->caller_data.ani, dest);
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
switch_channel_set_caller_profile(channel, caller_profile);
tech_pvt->caller_profile = caller_profile;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
+ if ((tech_pvt->token_id = zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session))) < 0) {
+ switch_core_session_destroy(new_session);
+ cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ goto fail;
+ }
+
+ zap_channel_outgoing_call(zchan);
return SWITCH_CAUSE_SUCCESS;
}
tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
"OpenZAP",
- SPAN_CONFIG[sigmsg->span->span_id].dialplan,
+ SPAN_CONFIG[sigmsg->channel->span_id].dialplan,
sigmsg->channel->chan_name,
sigmsg->channel->chan_number,
NULL,
NULL,
NULL,
(char *) modname,
- SPAN_CONFIG[sigmsg->span->span_id].context,
- sigmsg->dnis);
+ SPAN_CONFIG[sigmsg->channel->span_id].context,
+ sigmsg->channel->caller_data.dnis);
assert(tech_pvt->caller_profile != NULL);
snprintf(name, sizeof(name), "OpenZAP/%s", tech_pvt->caller_profile->destination_number);
static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
{
- zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
+ switch_core_session_t *session = NULL;
+ zap_status_t status;
+
+ zap_log(ZAP_LOG_DEBUG, "got fxo sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
+
+ switch(sigmsg->event_id) {
+ case ZAP_SIGEVENT_START:
+ {
+ status = zap_channel_from_event(sigmsg, &session);
+ if (status != ZAP_SUCCESS) {
+ zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_DOWN);
+ }
+ }
+ break;
+ }
+
return ZAP_SUCCESS;
}
zap_log(ZAP_LOG_DEBUG, "got fxs sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
switch(sigmsg->event_id) {
+ case ZAP_SIGEVENT_UP:
+ {
+ if ((session = zap_channel_get_session(sigmsg->channel, 0))) {
+ channel = switch_core_session_get_channel(session);
+ switch_channel_mark_answered(channel);
+ switch_core_session_rwunlock(session);
+ }
+ }
+ break;
case ZAP_SIGEVENT_START:
{
status = zap_channel_from_event(sigmsg, &session);
#define GOTO_STATUS(label,st) status = st; goto label ;
#define zap_copy_string(x,y,z) strncpy(x, y, z - 1)
+#define zap_set_string(x,y) strncpy(x, y, sizeof(x)-1)
#define zap_strlen_zero(s) (!s || *s == '\0')
#define ZAP_TOKEN_STRLEN 128
#define ZAP_MAX_TOKENS 10
+
+
+struct zap_caller_data {
+ char cid_name[80];
+ char ani[25];
+ char aniII[25];
+ char dnis[25];
+};
+
struct zap_channel {
uint32_t span_id;
uint32_t chan_id;
uint32_t token_count;
char chan_name[128];
char chan_number[32];
+ struct zap_caller_data caller_data;
struct zap_span *span;
struct zap_io_interface *zio;
};
uint32_t chan_id;
uint32_t span_id;
zap_channel_t *channel;
- zap_span_t *span;
- char cid_name[80];
- char ani[25];
- char aniII[25];
- char dnis[25];
void *raw_data;
uint32_t raw_data_len;
};
char last_error[256];
char tone_map[ZAP_TONEMAP_INVALID+1][ZAP_TONEMAP_LEN];
zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN];
+ zio_channel_outgoing_call_t outgoing_call;
void *app_data;
};
zio_span_next_event_t next_event;
};
+zap_status_t zap_channel_outgoing_call(zap_channel_t *zchan);
void zap_channel_rotate_tokens(zap_channel_t *zchan);
zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id);
zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token);
ZAP_STR2ENUM_P(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t)
typedef enum {
- ZAP_OOB_DTMF, ZAP_OOB_ONHOOK,
+ ZAP_OOB_DTMF,
+ ZAP_OOB_ONHOOK,
ZAP_OOB_OFFHOOK,
ZAP_OOB_WINK,
ZAP_OOB_FLASH,
ZAP_COMMAND_GET_DTMF_ON_PERIOD,
ZAP_COMMAND_SET_DTMF_OFF_PERIOD,
ZAP_COMMAND_GET_DTMF_OFF_PERIOD,
-
+ ZAP_COMMAND_GENERATE_RING_ON,
+ ZAP_COMMAND_GENERATE_RING_OFF,
+ ZAP_COMMAND_OFFHOOK,
+ ZAP_COMMAND_ONHOOK,
ZAP_COMMAND_COUNT
} zap_command_t;
ZAP_CHANNEL_STATE_BUSY,
ZAP_CHANNEL_STATE_ATTN,
ZAP_CHANNEL_STATE_IDLE,
+ ZAP_CHANNEL_STATE_GENRING,
ZAP_CHANNEL_STATE_INVALID
} zap_channel_state_t;
-#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID"
+#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "GENRING", "INVALID"
ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t)
typedef enum {
ZAP_CHANNEL_FLASH = (1 << 10),
ZAP_CHANNEL_STATE_CHANGE = (1 << 11),
ZAP_CHANNEL_HOLD = (1 << 12),
- ZAP_CHANNEL_INUSE = (1 << 13)
+ ZAP_CHANNEL_INUSE = (1 << 13),
+ ZAP_CHANNEL_OFFHOOK = (1 << 14),
+ ZAP_CHANNEL_RINGING = (1 << 15)
} zap_channel_flag_t;
typedef struct zap_sigmsg zap_sigmsg_t;
typedef struct zap_span zap_span_t;
+#define ZIO_CHANNEL_OUTGOING_CALL_ARGS (zap_channel_t *zchan)
#define ZIO_SPAN_POLL_EVENT_ARGS (zap_span_t *span, uint32_t ms)
#define ZIO_SPAN_NEXT_EVENT_ARGS (zap_span_t *span, zap_event_t **event)
#define ZIO_SIGNAL_CB_ARGS (zap_sigmsg_t *sigmsg)
#define ZIO_READ_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen)
#define ZIO_WRITE_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen)
+typedef zap_status_t (*zio_channel_outgoing_call_t) ZIO_CHANNEL_OUTGOING_CALL_ARGS ;
typedef zap_status_t (*zio_span_poll_event_t) ZIO_SPAN_POLL_EVENT_ARGS ;
typedef zap_status_t (*zio_span_next_event_t) ZIO_SPAN_NEXT_EVENT_ARGS ;
typedef zap_status_t (*zio_signal_cb_t) ZIO_SIGNAL_CB_ARGS ;
typedef zap_status_t (*zio_read_t) ZIO_READ_ARGS ;
typedef zap_status_t (*zio_write_t) ZIO_WRITE_ARGS ;
+#define ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) zap_status_t name ZIO_CHANNEL_OUTGOING_CALL_ARGS
#define ZIO_SPAN_POLL_EVENT_FUNCTION(name) zap_status_t name ZIO_SPAN_POLL_EVENT_ARGS
#define ZIO_SPAN_NEXT_EVENT_FUNCTION(name) zap_status_t name ZIO_SPAN_NEXT_EVENT_ARGS
#define ZIO_SIGNAL_CB_FUNCTION(name) zap_status_t name ZIO_SIGNAL_CB_ARGS
#define ZIO_READ_FUNCTION(name) zap_status_t name ZIO_READ_ARGS
#define ZIO_WRITE_FUNCTION(name) zap_status_t name ZIO_WRITE_ARGS
-#define ZIO_CONFIGURE_SPAN_MUZZLE assert(zio != NULL)
-#define ZIO_OPEN_MUZZLE assert(zchan != NULL)
-#define ZIO_CLOSE_MUZZLE assert(zchan != NULL)
-#define ZIO_COMMAND_MUZZLE assert(zchan != NULL); assert(command != 0); assert(obj != NULL)
-#define ZIO_WAIT_MUZZLE assert(zchan != NULL); assert(flags != 0); assert(to != 0)
-#define ZIO_READ_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL)
-#define ZIO_WRITE_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL)
-
#define ZAP_PRE __FILE__, __FUNCTION__, __LINE__
-
#define ZAP_LOG_LEVEL_DEBUG 7
#define ZAP_LOG_LEVEL_INFO 6
#define ZAP_LOG_LEVEL_NOTICE 5
{
zap_span_t *span;
int span_id;
-
+
if (argc < 2) {
printf("usage %s <spanno>\n", argv[0]);
exit(-1);
#include "openzap.h"
#include "zap_analog.h"
+static void *zap_analog_channel_run(zap_thread_t *me, void *obj);
+
+static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call)
+{
+ return ZAP_FAIL;
+}
+
+static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call)
+{
+
+ if (!zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) {
+ zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_GENRING);
+ zap_thread_create_detached(zap_analog_channel_run, zchan);
+ }
+
+ return ZAP_SUCCESS;
+}
+
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)
{
span->analog_data->max_dialstr = max_dialstr;
span->analog_data->sig_cb = sig_cb;
span->signal_type = ZAP_SIGTYPE_ANALOG;
+ span->outgoing_call = span->trunk_type == ZAP_TRUNK_FXS ? analog_fxs_outgoing_call : analog_fxo_outgoing_call;
zap_span_load_tones(span, tonemap);
return ZAP_SUCCESS;
sig.chan_id = chan->chan_id;
sig.span_id = chan->span_id;
sig.channel = chan;
- sig.span = chan->span;
+
while (zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) {
zap_wait_flag_t flags = ZAP_READ;
if (!zap_test_flag(chan, ZAP_CHANNEL_STATE_CHANGE)) {
switch(chan->state) {
+ case ZAP_CHANNEL_STATE_GENRING:
+ {
+ if (state_counter > 60000) {
+ zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN);
+ } else {
+ zap_sleep(interval);
+ continue;
+ }
+ }
+ break;
case ZAP_CHANNEL_STATE_DIALTONE:
{
if (state_counter > 10000) {
case ZAP_CHANNEL_STATE_UP:
{
zap_channel_use(chan);
+
+ if (chan->type == ZAP_CHAN_TYPE_FXO && !zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) {
+ zap_channel_command(chan, ZAP_COMMAND_OFFHOOK, NULL);
+ }
+
+ if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) {
+ zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
+ }
+
if (zap_test_flag(chan, ZAP_CHANNEL_HOLD)) {
zap_clear_flag(chan, ZAP_CHANNEL_HOLD);
sig.event_id = ZAP_SIGEVENT_FLASH;
{
zap_channel_use(chan);
sig.event_id = ZAP_SIGEVENT_START;
- zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis));
+ zap_copy_string(chan->caller_data.dnis, dtmf, sizeof(chan->caller_data.dnis));
data->sig_cb(&sig);
continue;
}
indicate = 1;
}
break;
+ case ZAP_CHANNEL_STATE_GENRING:
+ {
+ zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
+ }
+ break;
case ZAP_CHANNEL_STATE_RING:
{
zap_channel_done(chan);
}
}
- if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) {
- if (chan->state == ZAP_CHANNEL_STATE_DIALTONE || chan->state == ZAP_CHANNEL_STATE_COLLECT) {
- zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset);
- if (chan->state == ZAP_CHANNEL_STATE_DIALTONE) {
- zap_set_state_locked(chan, ZAP_CHANNEL_STATE_COLLECT);
- }
- dtmf_offset = strlen(dtmf);
- last_digit = elapsed;
- }
- }
+ if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) {
+ if (chan->state == ZAP_CHANNEL_STATE_DIALTONE || chan->state == ZAP_CHANNEL_STATE_COLLECT) {
+ zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset);
+ if (chan->state == ZAP_CHANNEL_STATE_DIALTONE) {
+ zap_set_state_locked(chan, ZAP_CHANNEL_STATE_COLLECT);
+ }
+ dtmf_offset = strlen(dtmf);
+ last_digit = elapsed;
+ }
+ }
+
+ if (last_digit && ((elapsed - last_digit > data->digit_timeout) || strlen(dtmf) > data->max_dialstr)) {
+ zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
+ zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE);
+ last_digit = 0;
+ }
+
+ if (zap_channel_wait(chan, &flags, interval * 2) != ZAP_SUCCESS) {
+ continue;
+ }
- if (last_digit && ((elapsed - last_digit > data->digit_timeout) || strlen(dtmf) > data->max_dialstr)) {
- zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
- zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE);
- last_digit = 0;
- }
+ if (!(flags & ZAP_READ)) {
+ continue;
+ }
- if (zap_channel_wait(chan, &flags, interval * 2) != ZAP_SUCCESS) {
- continue;
- }
-
- if (!(flags & ZAP_READ)) {
- continue;
- }
-
- if (zap_channel_read(chan, frame, &len) != ZAP_SUCCESS) {
- goto done;
- }
-
- if (!indicate) {
- continue;
- }
-
- if (chan->effective_codec != ZAP_CODEC_SLIN) {
- len *= 2;
- }
-
- rlen = zap_buffer_read_loop(dt_buffer, frame, len);
-
- if (chan->effective_codec != ZAP_CODEC_SLIN) {
- zio_codec_t codec_func = NULL;
-
- if (chan->native_codec == ZAP_CODEC_ULAW) {
- codec_func = zio_slin2ulaw;
- } else if (chan->native_codec == ZAP_CODEC_ALAW) {
- codec_func = zio_slin2alaw;
- }
-
- if (codec_func) {
- status = codec_func(frame, sizeof(frame), &rlen);
- } else {
- snprintf(chan->last_error, sizeof(chan->last_error), "codec error!");
- goto done;
- }
- }
-
- zap_channel_write(chan, frame, &rlen);
- }
-
- done:
-
- closed_chan = chan;
- zap_channel_close(&chan);
-
- zap_channel_command(closed_chan, ZAP_COMMAND_SET_NATIVE_CODEC, NULL);
-
- 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;
- }
-
- static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
- {
- zap_sigmsg_t sig;
- zap_analog_data_t *data = event->channel->span->analog_data;
-
- memset(&sig, 0, sizeof(sig));
- sig.chan_id = event->channel->chan_id;
- sig.span_id = event->channel->span_id;
- sig.channel = event->channel;
- sig.span = event->channel->span;
-
- 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_ONHOOK:
- {
- zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN);
- }
- break;
- case ZAP_OOB_FLASH:
- {
+ if (zap_channel_read(chan, frame, &len) != ZAP_SUCCESS) {
+ goto done;
+ }
- sig.event_id = ZAP_SIGEVENT_FLASH;
- zap_channel_rotate_tokens(event->channel);
+ if (!indicate) {
+ continue;
+ }
+
+ if (chan->type == ZAP_CHAN_TYPE_FXO && !zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) {
+ zap_channel_command(chan, ZAP_COMMAND_OFFHOOK, NULL);
+ }
+
+ if (chan->effective_codec != ZAP_CODEC_SLIN) {
+ len *= 2;
+ }
+
+ rlen = zap_buffer_read_loop(dt_buffer, frame, len);
+
+ if (chan->effective_codec != ZAP_CODEC_SLIN) {
+ zio_codec_t codec_func = NULL;
+
+ if (chan->native_codec == ZAP_CODEC_ULAW) {
+ codec_func = zio_slin2ulaw;
+ } else if (chan->native_codec == ZAP_CODEC_ALAW) {
+ codec_func = zio_slin2alaw;
+ }
+
+ if (codec_func) {
+ status = codec_func(frame, sizeof(frame), &rlen);
+ } else {
+ snprintf(chan->last_error, sizeof(chan->last_error), "codec error!");
+ goto done;
+ }
+ }
- if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) {
- zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
- } else {
- data->sig_cb(&sig);
- 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);
- }
- }
- }
+ zap_channel_write(chan, frame, &rlen);
+ }
+
+ done:
+
+ if (chan->type == ZAP_CHAN_TYPE_FXO && zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) {
+ zap_channel_command(chan, ZAP_COMMAND_ONHOOK, NULL);
+ }
+
+ if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) {
+ zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL);
+ }
+
+
+ closed_chan = chan;
+ zap_channel_close(&chan);
+
+ zap_channel_command(closed_chan, ZAP_COMMAND_SET_NATIVE_CODEC, NULL);
+
+ 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;
+}
+
+static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
+{
+ zap_sigmsg_t sig;
+ zap_analog_data_t *data = event->channel->span->analog_data;
+
+ 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)) {
+ sig.event_id = ZAP_SIGEVENT_START;
+ zap_set_string(event->channel->caller_data.dnis, event->channel->chan_number);
+ data->sig_cb(&sig);
+ zap_channel_command(event->channel, ZAP_COMMAND_OFFHOOK, NULL);
+ zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_RING);
+ zap_thread_create_detached(zap_analog_channel_run, event->channel);
+ }
+ }
+ break;
+ case ZAP_OOB_ONHOOK:
+ {
+ zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN);
+ }
+ break;
+ case ZAP_OOB_FLASH:
+ {
+
+ sig.event_id = ZAP_SIGEVENT_FLASH;
+ zap_channel_rotate_tokens(event->channel);
+
+ if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) {
+ zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP);
+ } else {
+ data->sig_cb(&sig);
+ 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);
+ }
+ }
+ }
break;
case ZAP_OOB_OFFHOOK:
{
- if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
+ if (zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
+ if (event->channel->type == ZAP_CHAN_TYPE_FXS && 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);
}
}
}
-
+
zap_mutex_unlock(event->channel->mutex);
return ZAP_SUCCESS;
}
if (span_id) {
span_max = span_id;
+ j = span_id;
} else {
span_max = globals.span_index;
- }
-
- if (direction == ZAP_TOP_DOWN) {
- j = 1;
- } else {
- j = span_max;
+ if (direction == ZAP_TOP_DOWN) {
+ j = 1;
+ } else {
+ j = span_max;
+ }
}
for(;;) {
span = &globals.spans[j];
-
if (!zap_test_flag(span, ZAP_SPAN_CONFIGURED)) {
goto next_loop;
}
if (status == ZAP_SUCCESS) {
zap_set_flag(check, ZAP_CHANNEL_INUSE);
+ zap_channel_open_chan(check);
*zchan = check;
return status;
}
zchan->event_callback = NULL;
zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
- zap_clear_flag(zchan, ZAP_CHANNEL_INUSE);
+ zap_channel_done(zchan);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_HOLD);
memset(zchan->tokens, 0, sizeof(zchan->tokens));
zchan->token_count = 0;
return status;
}
+zap_status_t zap_channel_outgoing_call(zap_channel_t *zchan)
+{
+ assert(zchan != NULL);
+ if (zchan->span->outgoing_call) {
+ return zchan->span->outgoing_call(zchan);
+ } else {
+ zap_log(ZAP_LOG_ERROR, "outgoing_call method not implemented!\n");
+ }
+
+ return ZAP_FAIL;
+}
+
zap_status_t zap_channel_done(zap_channel_t *zchan)
{
assert(zchan != NULL);
+ memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
zap_clear_flag_locked(zchan, ZAP_CHANNEL_INUSE);
return ZAP_SUCCESS;
assert(zchan != NULL);
assert(zchan->zio != NULL);
- if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
- snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
- return ZAP_FAIL;
- }
-
zap_mutex_lock(zchan->mutex);
switch(command) {
static ZIO_CLOSE_FUNCTION(wanpipe_close)
{
- ZIO_CLOSE_MUZZLE;
return ZAP_SUCCESS;
}
wanpipe_tdm_api_t tdm_api;
int err = 0;
- ZIO_COMMAND_MUZZLE;
-
memset(&tdm_api, 0, sizeof(tdm_api));
switch(command) {
for(x = start; x < end; x++) {
zap_channel_t *chan;
zap_socket_t sockfd = ZT_INVALID_SOCKET;
- int command;
int len;
snprintf(path, sizeof(path), "/dev/zap/%d", x);
sockfd = open(path, O_RDWR);
if (sockfd != ZT_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
- command = ZT_START;
-#if 0
-
- if (ioctl(sockfd, ZT_HOOK, &command)) {
- zap_log(ZAP_LOG_INFO, "failure configuring device %s as OpenZAP device %d:%d fd:%d err:%s\n",
- path, chan->span_id, chan->chan_id, sockfd, strerror(errno));
-
- continue;
- }
-#endif
-
-
len = zt_globals.codec_ms * 8;
if (ioctl(chan->sockfd, ZT_SET_BLOCKSIZE, &len)) {
zap_log(ZAP_LOG_INFO, "failure configuring device %s as OpenZAP device %d:%d fd:%d err:%s\n",
static ZIO_OPEN_FUNCTION(zt_open)
{
- ZIO_OPEN_MUZZLE;
return ZAP_SUCCESS;
}
static ZIO_CLOSE_FUNCTION(zt_close)
{
- ZIO_CLOSE_MUZZLE;
return ZAP_SUCCESS;
}
zt_params_t ztp = {0};
int err = 0;
- ZIO_COMMAND_MUZZLE;
-
switch(command) {
+ case ZAP_COMMAND_OFFHOOK:
+ {
+ int command = ZT_OFFHOOK;
+ if (ioctl(zchan->sockfd, ZT_HOOK, &command)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed");
+ return ZAP_FAIL;
+ }
+ zap_set_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
+ }
+ break;
+ case ZAP_COMMAND_ONHOOK:
+ {
+ int command = ZT_ONHOOK;
+ if (ioctl(zchan->sockfd, ZT_HOOK, &command)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed");
+ return ZAP_FAIL;
+ }
+ zap_clear_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
+ }
+ break;
+ case ZAP_COMMAND_GENERATE_RING_ON:
+ {
+ int command = ZT_RING;
+ if (ioctl(zchan->sockfd, ZT_HOOK, &command)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
+ return ZAP_FAIL;
+ }
+ zap_set_flag_locked(zchan, ZAP_CHANNEL_RINGING);
+ }
+ break;
+ case ZAP_COMMAND_GENERATE_RING_OFF:
+ {
+ int command = ZT_RINGOFF;
+ if (ioctl(zchan->sockfd, ZT_HOOK, &command)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off failed");
+ return ZAP_FAIL;
+ }
+ zap_clear_flag_locked(zchan, ZAP_CHANNEL_RINGING);
+ }
+ break;
case ZAP_COMMAND_GET_INTERVAL:
{
if (!(err = ioctl(zchan->sockfd, ZT_GET_BLOCKSIZE, &zchan->packet_len))) {
int i, j = 0, k = 0, r, e;
for(i = 1; i <= span->chan_count; i++) {
- e = ZT_IOMUX_SIGEVENT;
memset(&pfds[j], 0, sizeof(pfds[j]));
pfds[j].fd = span->channels[i].sockfd;
pfds[j].events = POLLPRI;
- ioctl(span->channels[i].sockfd ,ZT_IOMUX, &e);
j++;
}
}
switch(zt_event_id) {
+ case ZT_EVENT_RINGEROFF:
+ {
+ return ZAP_FAIL;
+ }
+ break;
+ case ZT_EVENT_RINGERON:
+ {
+ return ZAP_FAIL;
+ }
+ break;
+ case ZT_EVENT_RINGBEGIN:
+ {
+ event_id = ZAP_OOB_RING_START;
+ }
+ break;
case ZT_EVENT_ONHOOK:
{
event_id = ZAP_OOB_ONHOOK;
zt_interface.configure_span = zt_configure_span;
zt_interface.open = zt_open;
zt_interface.close = zt_close;
+ zt_interface.command = zt_command;
zt_interface.wait = zt_wait;
zt_interface.read = zt_read;
zt_interface.write = zt_write;