# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-OBJS=hashtable.o hashtable_itr.o openzap.o zap_config.o libteletone_detect.o libteletone_generate.o zap_buffer.o
+OBJS=hashtable.o hashtable_itr.o openzap.o zap_config.o g711.o libteletone_detect.o libteletone_generate.o zap_buffer.o
CFLAGS=$(ZAP_CFLAGS) -Iinclude
MYLIB=libopenzap.a
TMP=-I../../libpri-1.2.4 -Iinclude -I. -w
$(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
clean:
- rm -f *.o $(MYLIB) *~ \#*
+ rm -f *.o $(MYLIB) *~ \#* testapp priserver
typedef size_t zap_size_t;
struct zap_software_interface;
+#define ZAP_COMMAND_OBJ_INT *((int *)obj)
+
#define zap_true(expr)\
(expr && ( !strcasecmp(expr, "yes") ||\
!strcasecmp(expr, "on") ||\
#define zap_copy_string(x,y,z) strncpy(x, y, z - 1)
+
+#define zap_channel_test_feature(obj, flag) ((obj)->features & flag)
+#define zap_channel_set_feature(obj, flag) (obj)->features |= (flag)
+#define zap_channel_clear_feature(obj, flag) (obj)->features &= ~(flag)
+
/*!
\brief Test for the existance of a flag on an arbitary object
\command obj the object to test
} zap_wait_flag_t;
typedef enum {
- ZAP_CODEC_NONE = (1 << 31),
ZAP_CODEC_ULAW = 0,
ZAP_CODEC_ALAW = 8,
- ZAP_CODEC_SLIN = 10
+ ZAP_CODEC_SLIN = 10,
+ ZAP_CODEC_NONE = (1 << 31)
} zap_codec_t;
+typedef enum {
+ ZAP_TONE_DTMF = (1 << 0)
+} zap_tone_type_t;
+
typedef enum {
ZAP_COMMAND_NOOP,
ZAP_COMMAND_SET_INTERVAL,
ZAP_COMMAND_GET_INTERVAL,
ZAP_COMMAND_SET_CODEC,
- ZAP_COMMAND_GET_CODEC
+ ZAP_COMMAND_GET_CODEC,
+ ZAP_COMMAND_ENABLE_TONE_DETECT,
+ ZAP_COMMAND_DISABLE_TONE_DETECT
} zap_command_t;
typedef enum {
ZAP_CHAN_TYPE_FXO
} zap_chan_type_t;
+typedef enum {
+ ZAP_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0)
+} zap_channel_feature_t;
+
typedef enum {
ZAP_CHANNEL_CONFIGURED = (1 << 0),
ZAP_CHANNEL_READY = (1 << 1),
- ZAP_CHANNEL_OPEN = (1 << 2)
+ ZAP_CHANNEL_OPEN = (1 << 2),
+ ZAP_CHANNEL_DTMF_DETECT = (1 << 3),
+ ZAP_CHANNEL_SUPRESS_DTMF = (1 << 4)
} zap_channel_flag_t;
-struct zap_channel {
- unsigned span_id;
- unsigned chan_id;
- zap_chan_type_t type;
- zap_socket_t sockfd;
- zap_channel_flag_t flags;
- char last_error[256];
- void *mod_data;
- struct zap_software_interface *zint;
-};
typedef struct zap_channel zap_channel_t;
+typedef struct zap_event zap_event_t;
-struct zap_span {
- unsigned span_id;
- unsigned chan_count;
- zap_span_flag_t flags;
- struct zap_software_interface *zint;
- zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN];
-};
-typedef struct zap_span zap_span_t;
-
+#define ZINT_EVENT_CB_ARGS (zap_channel_t *zchan, zap_event_t *event)
+#define ZINT_CODEC_ARGS (void *data, zap_size_t max, zap_size_t *datalen)
#define ZINT_CONFIGURE_ARGS (struct zap_software_interface *zint)
#define ZINT_OPEN_ARGS (zap_channel_t *zchan)
#define ZINT_CLOSE_ARGS (zap_channel_t *zchan)
#define ZINT_READ_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen)
#define ZINT_WRITE_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen)
+typedef zap_status_t (*zint_event_cb_t) ZINT_EVENT_CB_ARGS ;
+typedef zap_status_t (*zint_codec_t) ZINT_CODEC_ARGS ;
typedef zap_status_t (*zint_configure_t) ZINT_CONFIGURE_ARGS ;
typedef zap_status_t (*zint_open_t) ZINT_OPEN_ARGS ;
typedef zap_status_t (*zint_close_t) ZINT_CLOSE_ARGS ;
typedef zap_status_t (*zint_read_t) ZINT_READ_ARGS ;
typedef zap_status_t (*zint_write_t) ZINT_WRITE_ARGS ;
+#define ZINT_EVENT_CB_FUNCTION(name) zap_status_t name ZINT_EVENT_CB_ARGS
+#define ZINT_CODEC_FUNCTION(name) zap_status_t name ZINT_CODEC_ARGS
#define ZINT_CONFIGURE_FUNCTION(name) zap_status_t name ZINT_CONFIGURE_ARGS
#define ZINT_OPEN_FUNCTION(name) zap_status_t name ZINT_OPEN_ARGS
#define ZINT_CLOSE_FUNCTION(name) zap_status_t name ZINT_CLOSE_ARGS
#define ZAP_LOG_ALERT ZAP_PRE, ZAP_LOG_LEVEL_ALERT
#define ZAP_LOG_EMERG ZAP_PRE, ZAP_LOG_LEVEL_EMERG
+typedef enum {
+ ZAP_EVENT_NONE,
+ ZAP_EVENT_DTMF
+} zap_event_type_t;
+
+struct zap_event {
+ zap_event_type_t e_type;
+ void *data;
+};
+
+struct zap_channel {
+ unsigned span_id;
+ unsigned chan_id;
+ zap_chan_type_t type;
+ zap_socket_t sockfd;
+ zap_channel_flag_t flags;
+ zap_channel_feature_t features;
+ zap_codec_t effective_codec;
+ zap_codec_t native_codec;
+ teletone_dtmf_detect_state_t dtmf_detect;
+ zap_event_t event_header;
+ char last_error[256];
+ zint_event_cb_t event_callback;
+ void *mod_data;
+ unsigned skip_read_frames;
+ struct zap_span *span;
+ struct zap_software_interface *zint;
+};
+
+
+struct zap_span {
+ unsigned span_id;
+ unsigned chan_count;
+ zap_span_flag_t flags;
+ struct zap_software_interface *zint;
+ zint_event_cb_t event_callback;
+ zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN];
+};
+typedef struct zap_span zap_span_t;
+
+
typedef void (*zap_logger_t)(char *file, const char *func, int line, int level, char *fmt, ...);
extern zap_logger_t zap_log;
typedef struct zap_software_interface zap_software_interface_t;
+zap_status_t zap_span_find(const char *name, unsigned id, zap_span_t **span);
zap_status_t zap_span_create(zap_software_interface_t *zint, zap_span_t **span);
zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan);
-
+zap_status_t zap_span_set_event_callback(zap_span_t *span, zint_event_cb_t event_callback);
+zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zint_event_cb_t event_callback);
zap_status_t zap_channel_open(const char *name, unsigned span_id, unsigned chan_id, zap_channel_t **zchan);
zap_status_t zap_channel_open_any(const char *name, unsigned span_id, zap_direction_t direction, zap_channel_t **zchan);
zap_status_t zap_channel_close(zap_channel_t **zchan);
new_chan->zint = span->zint;
new_chan->span_id = span->span_id;
new_chan->chan_id = span->chan_count;
+ new_chan->span = span;
zap_set_flag(new_chan, ZAP_CHANNEL_CONFIGURED | ZAP_CHANNEL_READY);
*chan = new_chan;
return ZAP_SUCCESS;
return ZAP_FAIL;
}
+zap_status_t zap_span_find(const char *name, unsigned id, zap_span_t **span)
+{
+ zap_software_interface_t *zint = (zap_software_interface_t *) hashtable_search(globals.interface_hash, (char *)name);
+ zap_span_t *fspan;
+
+ if (!zint) {
+ return ZAP_FAIL;
+ }
+
+ if (id > ZAP_MAX_SPANS_INTERFACE) {
+ return ZAP_FAIL;
+ }
+
+ fspan = &zint->spans[id];
+
+ if (!zap_test_flag(fspan, ZAP_SPAN_CONFIGURED)) {
+ return ZAP_FAIL;
+ }
+
+ *span = fspan;
+
+ return ZAP_SUCCESS;
+
+}
+
+zap_status_t zap_span_set_event_callback(zap_span_t *span, zint_event_cb_t event_callback)
+{
+ span->event_callback = event_callback;
+ return ZAP_SUCCESS;
+}
+
+zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zint_event_cb_t event_callback)
+{
+ zchan->event_callback = event_callback;
+ return ZAP_SUCCESS;
+}
zap_status_t zap_channel_open_any(const char *name, unsigned span_id, zap_direction_t direction, zap_channel_t **zchan)
{
status = check->zint->close(check);
if (status == ZAP_SUCCESS) {
zap_clear_flag(check, ZAP_CHANNEL_OPEN);
+ check->event_callback = NULL;
+ zap_clear_flag(check, ZAP_CHANNEL_DTMF_DETECT);
+ zap_clear_flag(check, ZAP_CHANNEL_SUPRESS_DTMF);
*zchan = NULL;
}
}
assert(zchan->zint != NULL);
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
return ZAP_FAIL;
}
+ switch(command) {
+ case ZAP_COMMAND_ENABLE_TONE_DETECT:
+ {
+ /* if they don't have thier own, use ours */
+ if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF_DETECT)) {
+ zap_tone_type_t tt = ZAP_COMMAND_OBJ_INT;
+ if (tt == ZAP_TONE_DTMF) {
+ teletone_dtmf_detect_init (&zchan->dtmf_detect, 8000);
+ zap_set_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
+ zap_set_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
+ return ZAP_SUCCESS;
+ } else {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid command");
+ return ZAP_FAIL;
+ }
+ }
+ }
+ break;
+ case ZAP_COMMAND_DISABLE_TONE_DETECT:
+ {
+ if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF_DETECT)) {
+ zap_tone_type_t tt = ZAP_COMMAND_OBJ_INT;
+ if (tt == ZAP_TONE_DTMF) {
+ teletone_dtmf_detect_init (&zchan->dtmf_detect, 8000);
+ zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT);
+ zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF);
+ return ZAP_SUCCESS;
+ } else {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "invalid command");
+ return ZAP_FAIL;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
if (!zchan->zint->command) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "method not implemented");
return ZAP_FAIL;
}
assert(zchan->zint != NULL);
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
return ZAP_FAIL;
}
if (!zchan->zint->wait) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "method not implemented");
return ZAP_FAIL;
}
}
+/*******************************/
+ZINT_CODEC_FUNCTION(zint_slin2ulaw)
+{
+ int16_t sln_buf[512] = {0}, *sln = sln_buf;
+ uint8_t *lp = data;
+ unsigned i;
+ zap_size_t len = *datalen;
+
+ if (max > len) {
+ max = len;
+ }
+
+ memcpy(sln, data, max);
+
+ for(i = 0; i < max; i++) {
+ *lp++ = linear_to_ulaw(*sln++);
+ }
+
+ *datalen = max / 2;
+
+ return ZAP_SUCCESS;
+
+}
+
+
+ZINT_CODEC_FUNCTION(zint_ulaw2slin)
+{
+ int16_t *sln = data;
+ uint8_t law[1024] = {0}, *lp = law;
+ unsigned i;
+ zap_size_t len = *datalen;
+
+ if (max > len) {
+ max = len;
+ }
+
+ memcpy(law, data, max);
+
+ for(i = 0; i < max; i++) {
+ *sln++ = ulaw_to_linear(*lp++);
+ }
+
+ *datalen = max * 2;
+
+ return ZAP_SUCCESS;
+}
+
+ZINT_CODEC_FUNCTION(zint_slin2alaw)
+{
+ int16_t sln_buf[512] = {0}, *sln = sln_buf;
+ uint8_t *lp = data;
+ unsigned i;
+ zap_size_t len = *datalen;
+
+ if (max > len) {
+ max = len;
+ }
+
+ memcpy(sln, data, max);
+
+ for(i = 0; i < max; i++) {
+ *lp++ = linear_to_alaw(*sln++);
+ }
+
+ *datalen = max / 2;
+
+ return ZAP_SUCCESS;
+
+}
+
+
+ZINT_CODEC_FUNCTION(zint_alaw2slin)
+{
+ int16_t *sln = data;
+ uint8_t law[1024] = {0}, *lp = law;
+ unsigned i;
+ zap_size_t len = *datalen;
+
+ if (max > len) {
+ max = len;
+ }
+
+ memcpy(law, data, max);
+
+ for(i = 0; i < max; i++) {
+ *sln++ = alaw_to_linear(*lp++);
+ }
+
+ *datalen = max * 2;
+
+ return ZAP_SUCCESS;
+}
+
+ZINT_CODEC_FUNCTION(zint_ulaw2alaw)
+{
+ zap_size_t len = *datalen;
+ unsigned i;
+ uint8_t *lp = data;
+
+ if (max > len) {
+ max = len;
+ }
+
+ for(i = 0; i < max; i++) {
+ *lp = ulaw_to_alaw(*lp);
+ lp++;
+ }
+
+ return ZAP_SUCCESS;
+}
+
+ZINT_CODEC_FUNCTION(zint_alaw2ulaw)
+{
+ zap_size_t len = *datalen;
+ unsigned i;
+ uint8_t *lp = data;
+
+ if (max > len) {
+ max = len;
+ }
+
+ for(i = 0; i < max; i++) {
+ *lp = alaw_to_ulaw(*lp);
+ lp++;
+ }
+
+ return ZAP_SUCCESS;
+}
+
+/******************************/
zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *datalen)
{
+ zap_status_t status = ZAP_FAIL;
+ zint_codec_t codec_func;
+ zap_size_t max = *datalen;
+
assert(zchan != NULL);
assert(zchan->zint != NULL);
assert(zchan->zint != NULL);
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
return ZAP_FAIL;
}
if (!zchan->zint->read) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "method not implemented");
return ZAP_FAIL;
}
- return zchan->zint->read(zchan, data, datalen);
-
+ status = zchan->zint->read(zchan, data, datalen);
+
+ if (status == ZAP_SUCCESS && zchan->effective_codec != zchan->native_codec) {
+ if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_SLIN) {
+ codec_func = zint_ulaw2slin;
+ } else if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_ALAW) {
+ codec_func = zint_ulaw2alaw;
+ } else if (zchan->native_codec == ZAP_CODEC_ALAW && zchan->effective_codec == ZAP_CODEC_SLIN) {
+ codec_func = zint_alaw2slin;
+ } else if (zchan->native_codec == ZAP_CODEC_ALAW && zchan->effective_codec == ZAP_CODEC_ULAW) {
+ codec_func = zint_alaw2ulaw;
+ }
+
+ if (codec_func) {
+ status = codec_func(data, max, datalen);
+ } else {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "codec error!");
+ status = ZAP_FAIL;
+ }
+ }
+
+ if (zap_test_flag(zchan, ZAP_CHANNEL_DTMF_DETECT)) {
+ int16_t sln_buf[1024], *sln = sln_buf;
+ zap_size_t slen;
+ char digit_str[80] = "";
+
+ if (zchan->effective_codec == ZAP_CODEC_SLIN) {
+ sln = data;
+ slen = *datalen / 2;
+ } else {
+ zap_size_t len = *datalen;
+ unsigned i;
+ uint8_t *lp = data;
+ slen = max;
+
+ if (slen > len) {
+ slen = len;
+ }
+
+ if (zchan->effective_codec == ZAP_CODEC_ULAW) {
+ for(i = 0; i < max; i++) {
+ *sln++ = ulaw_to_linear(*lp++);
+ }
+ } else if (zchan->effective_codec == ZAP_CODEC_ALAW) {
+ for(i = 0; i < max; i++) {
+ *sln++ = alaw_to_linear(*lp++);
+ }
+ }
+
+ sln = sln_buf;
+ }
+
+ teletone_dtmf_detect (&zchan->dtmf_detect, sln, slen);
+ teletone_dtmf_get(&zchan->dtmf_detect, digit_str, sizeof(digit_str));
+ if(digit_str[0]) {
+ zint_event_cb_t event_callback = NULL;
+ if (zchan->span->event_callback) {
+ event_callback = zchan->span->event_callback;
+ } else if (zchan->event_callback) {
+ event_callback = zchan->event_callback;
+ }
+
+ if (event_callback) {
+ zchan->event_header.e_type = ZAP_EVENT_DTMF;
+ zchan->event_header.data = digit_str;
+ event_callback(zchan, &zchan->event_header);
+ zchan->event_header.e_type = ZAP_EVENT_NONE;
+ zchan->event_header.data = NULL;
+ }
+ if (zap_test_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF)) {
+ zchan->skip_read_frames = 20;
+ }
+ if (zchan->skip_read_frames > 0) {
+ memset(data, 0, *datalen);
+ zchan->skip_read_frames--;
+ }
+ }
+ }
+
+ return status;
}
zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t *datalen)
{
+ zap_status_t status = ZAP_FAIL;
+ zint_codec_t codec_func;
+ zap_size_t max = *datalen;
+
assert(zchan != NULL);
assert(zchan->zint != NULL);
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
return ZAP_FAIL;
}
if (!zchan->zint->write) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "method not implemented");
return ZAP_FAIL;
}
-
- return zchan->zint->write(zchan, data, datalen);
+
+ if (zchan->effective_codec != zchan->native_codec) {
+ if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_SLIN) {
+ codec_func = zint_slin2ulaw;
+ } else if (zchan->native_codec == ZAP_CODEC_ULAW && zchan->effective_codec == ZAP_CODEC_ALAW) {
+ codec_func = zint_alaw2ulaw;
+ } else if (zchan->native_codec == ZAP_CODEC_ALAW && zchan->effective_codec == ZAP_CODEC_SLIN) {
+ codec_func = zint_slin2alaw;
+ } else if (zchan->native_codec == ZAP_CODEC_ALAW && zchan->effective_codec == ZAP_CODEC_ULAW) {
+ codec_func = zint_ulaw2alaw;
+ }
+
+ if (codec_func) {
+ status = codec_func(data, max, datalen);
+ } else {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "codec error!");
+ status = ZAP_FAIL;
+ }
+ }
+
+ status = zchan->zint->write(zchan, data, datalen);
+
+ return status;
}
zap_status_t zap_global_init(void)
zap_channel_t *chan;
unsigned ms = 20;
zap_codec_t codec = ZAP_CODEC_SLIN;
-
+ unsigned runs = 4;
+
if (zap_global_init() != ZAP_SUCCESS) {
fprintf(stderr, "Error loading OpenZAP\n");
exit(-1);
printf("OpenZAP loaded\n");
-
+ top:
if (zap_channel_open_any("wanpipe", 0, ZAP_TOP_DOWN, &chan) == ZAP_SUCCESS) {
int x = 0;
printf("opened channel %d:%d\n", chan->span_id, chan->chan_id);
+#if 1
if (zap_channel_command(chan, ZAP_COMMAND_SET_INTERVAL, &ms) == ZAP_SUCCESS) {
ms = 0;
zap_channel_command(chan, ZAP_COMMAND_GET_INTERVAL, &ms);
} else {
printf("set interval failed [%s]\n", chan->last_error);
}
-
+#endif
if (zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec) == ZAP_SUCCESS) {
codec = 1;
zap_channel_command(chan, ZAP_COMMAND_GET_CODEC, &codec);
printf("wait fail [%s]\n", chan->last_error);
}
}
+ zap_channel_close(&chan);
} else {
printf("open fail [%s]\n", chan->last_error);
}
+ if(--runs) {
+ goto top;
+ }
zap_global_destroy();
}
OBJS += zap_wanpipe.o
WANPIPE_INCLUDE=/usr/include/wanpipe
-WP_CFLAGS =-I$(WANPIPE_INCLUDE) -I/usr/local/include -I/usr/src/linux/include -I. -I/usr/include
+WP_CFLAGS =-Wall -Werror -I$(WANPIPE_INCLUDE) -I/usr/local/include -I/usr/src/linux/include -I. -I/usr/include
WP_CFLAGS +=-D__LINUX__ -D_REENTRANT -D_GNU_SOURCE -DAFT_A104 -DWANPIPE_TDM_API -D_GNUC_ -DWANPIPE_TDM_API
#define WP_INVALID_SOCKET INVALID_HANDLE_VALUE
#else
#define WP_INVALID_SOCKET -1
+#include <stropts.h>
#endif
#include <wanpipe_defines.h>
#include <zap_wanpipe_windows.h>
#endif
+static struct {
+ unsigned codec_ms;
+} wp_globals;
static zap_software_interface_t wanpipe_interface;
+static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm_api)
+{
+ int err;
+
+#if defined(WIN32)
+ err = tdmv_api_ioctl(zchan->sockfd, &tdm_api->wp_tdm_cmd);
+#else
+ err = ioctl(zchan->sockfd, SIOC_WANPIPE_TDM_API, &tdm_api->wp_tdm_cmd);
+#endif
+
+ if (err) {
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
+ return ZAP_FAIL;
+ }
+
+ return ZAP_SUCCESS;
+}
+
static zap_socket_t wp_open_device(int span, int chan)
{
char fname[256];
if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d\n", spanno, x, chan->span_id, chan->chan_id, sockfd);
configured++;
+
} else {
zap_log(ZAP_LOG_ERROR, "failure configuring device s%dc%d\n", spanno, x);
}
return configured;
}
-static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm_api)
-{
- int err;
-
-#if defined(WIN32)
- err = tdmv_api_ioctl(zchan->sockfd, &tdm_api->wp_tdm_cmd);
-#else
- err = ioctl(zchan->sockfd, SIOC_WANPIPE_TDM_API, &tdm_api->wp_tdm_cmd);
-#endif
-
- if (err) {
- snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
- return ZAP_FAIL;
- }
-
- return ZAP_SUCCESS;
-}
-
static ZINT_CONFIGURE_FUNCTION(wanpipe_configure)
{
zap_config_t cfg;
}
while (zap_config_next_pair(&cfg, &var, &val)) {
- if (!strcasecmp(cfg.category, "span")) {
+ if (!strcasecmp(cfg.category, "defaults")) {
+ if (!strcasecmp(var, "codec_ms")) {
+ unsigned codec_ms = atoi(val);
+ if (codec_ms < 10 || codec_ms > 60) {
+ zap_log(ZAP_LOG_WARNING, "invalid codec ms at line %d\n", cfg.lineno);
+ } else {
+ wp_globals.codec_ms = codec_ms;
+ }
+ }
+ } else if (!strcasecmp(cfg.category, "span")) {
if (cfg.catno != catno) {
zap_log(ZAP_LOG_DEBUG, "found config for span\n");
catno = cfg.catno;
static ZINT_OPEN_FUNCTION(wanpipe_open)
{
- ZINT_OPEN_MUZZLE;
+
+ wanpipe_tdm_api_t tdm_api;
+
+ if (zchan->type == ZAP_CHAN_TYPE_DQ921 || zchan->type == ZAP_CHAN_TYPE_DQ931) {
+ zchan->native_codec = zchan->effective_codec = ZAP_CODEC_NONE;
+ } else {
+ tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_CODEC;
+ tdm_api.wp_tdm_cmd.tdm_codec = WP_NONE;
+ wp_tdm_cmd_exec(zchan, &tdm_api);
+
+ tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD;
+ tdm_api.wp_tdm_cmd.usr_period = wp_globals.codec_ms;
+ wp_tdm_cmd_exec(zchan, &tdm_api);
+
+ tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING;
+ if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
+ zchan->native_codec = zchan->effective_codec = ZAP_CODEC_ULAW;
+ } else {
+ zchan->native_codec = zchan->effective_codec = ZAP_CODEC_ALAW;
+ }
+ }
+
return ZAP_SUCCESS;
}
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_USR_PERIOD;
if (!(err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
- *((int *)obj) = tdm_api.wp_tdm_cmd.usr_period;
+ ZAP_COMMAND_OBJ_INT = tdm_api.wp_tdm_cmd.usr_period;
}
}
case ZAP_COMMAND_SET_INTERVAL:
{
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD;
- tdm_api.wp_tdm_cmd.usr_period = *((int *)obj);
+ tdm_api.wp_tdm_cmd.usr_period = ZAP_COMMAND_OBJ_INT;
err = wp_tdm_cmd_exec(zchan, &tdm_api);
}
break;
-
+
case ZAP_COMMAND_SET_CODEC:
{
- zap_codec_t codec = *((int *)obj);
- unsigned wp_codec = 0;
-
- switch(codec) {
- case ZAP_CODEC_SLIN:
- wp_codec = WP_SLINEAR;
- break;
- default:
- break;
- };
-
- if (wp_codec) {
- tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_CODEC;
- tdm_api.wp_tdm_cmd.tdm_codec = wp_codec;
- err = wp_tdm_cmd_exec(zchan, &tdm_api);
- } else {
- snprintf(zchan->last_error, sizeof(zchan->last_error), "Invalid Codec");
- return ZAP_FAIL;
- }
+ zchan->effective_codec = ZAP_COMMAND_OBJ_INT;
+ err = 0;
}
break;
+
case ZAP_COMMAND_GET_CODEC:
{
- tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_CODEC;
-
- if (!(err = wp_tdm_cmd_exec(zchan, &tdm_api))) {
- unsigned wp_codec = tdm_api.wp_tdm_cmd.tdm_codec;
- zap_codec_t codec = ZAP_CODEC_NONE;
- switch(wp_codec) {
- case WP_SLINEAR:
- codec = ZAP_CODEC_SLIN;
- break;
- default:
- break;
- };
-
- *((int *)obj) = codec;
- }
+ ZAP_COMMAND_OBJ_INT = zchan->effective_codec;
+ err = 0;
}
break;
default:
s = select(zchan->sockfd + 1, r, w, e, tvp);
if (s < 0) {
- snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
+ snprintf(zchan->last_error, sizeof(zchan->last_error), "select: %s", strerror(errno));
return ZAP_FAIL;
}
if (s == 0) {
return ZAP_TIMEOUT;
}
-
+
+ return ZAP_SUCCESS;
}
#ifndef __WINDOWS__
msg.msg_iovlen = 2;
msg.msg_iov = iov;
-
bsent = write(zchan->sockfd, &msg, iov[1].iov_len + iov[0].iov_len);
if (bsent > 0){
static ZINT_READ_FUNCTION(wanpipe_read)
{
- ZINT_READ_MUZZLE;
-
+
#ifndef WIN32
return wanpipe_read_unix(zchan, data, datalen);
#endif
-
- return ZAP_FAIL;
+
}
static ZINT_WRITE_FUNCTION(wanpipe_write)
assert(zint != NULL);
memset(&wanpipe_interface, 0, sizeof(wanpipe_interface));
+ wp_globals.codec_ms = 20;
wanpipe_interface.name = "wanpipe";
wanpipe_interface.configure = wanpipe_configure;
wanpipe_interface.open = wanpipe_open;