From e21ca79927e7a1cd79ad69aa155b6823f36afb4c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 19 May 2007 00:50:50 +0000 Subject: [PATCH] add a bunch of goodies git-svn-id: http://svn.openzap.org/svn/openzap/trunk@35 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/freetdm/src/Makefile | 4 +- libs/freetdm/src/include/openzap.h | 98 ++++++--- libs/freetdm/src/openzap.c | 331 ++++++++++++++++++++++++++++- libs/freetdm/src/testapp.c | 12 +- libs/freetdm/src/wanpipe | 2 +- libs/freetdm/src/zap_wanpipe.c | 133 ++++++------ 6 files changed, 482 insertions(+), 98 deletions(-) diff --git a/libs/freetdm/src/Makefile b/libs/freetdm/src/Makefile index 9c6788826c..301d5836a9 100644 --- a/libs/freetdm/src/Makefile +++ b/libs/freetdm/src/Makefile @@ -30,7 +30,7 @@ # 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 @@ -69,5 +69,5 @@ zap_zt.o: zap_zt.c $(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@ clean: - rm -f *.o $(MYLIB) *~ \#* + rm -f *.o $(MYLIB) *~ \#* testapp priserver diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 08201a2a41..67db68761a 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -101,6 +101,8 @@ typedef int zap_socket_t; 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") ||\ @@ -111,6 +113,11 @@ struct zap_software_interface; #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 @@ -169,18 +176,24 @@ typedef enum { } 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 { @@ -196,33 +209,23 @@ 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) @@ -231,6 +234,8 @@ typedef struct zap_span zap_span_t; #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 ; @@ -239,6 +244,8 @@ typedef zap_status_t (*zint_wait_t) ZINT_WAIT_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 @@ -275,6 +282,47 @@ typedef zap_status_t (*zint_write_t) ZINT_WRITE_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; @@ -293,9 +341,11 @@ struct zap_software_interface { 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); diff --git a/libs/freetdm/src/openzap.c b/libs/freetdm/src/openzap.c index a33bcdbc98..1e215cf785 100644 --- a/libs/freetdm/src/openzap.c +++ b/libs/freetdm/src/openzap.c @@ -177,6 +177,7 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha 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; @@ -185,6 +186,42 @@ zap_status_t zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_cha 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) { @@ -317,6 +354,9 @@ zap_status_t zap_channel_close(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; } } @@ -331,10 +371,50 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo 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; } @@ -348,10 +428,12 @@ zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, unsi 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; } @@ -359,41 +441,282 @@ zap_status_t zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, unsi } +/*******************************/ +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) diff --git a/libs/freetdm/src/testapp.c b/libs/freetdm/src/testapp.c index ab429f0f79..8b9ae692ba 100644 --- a/libs/freetdm/src/testapp.c +++ b/libs/freetdm/src/testapp.c @@ -6,7 +6,8 @@ int main(int argc, char *argv[]) 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); @@ -14,11 +15,12 @@ int main(int argc, char *argv[]) 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); @@ -26,7 +28,7 @@ int main(int argc, char *argv[]) } 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); @@ -54,10 +56,14 @@ int main(int argc, char *argv[]) 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(); } diff --git a/libs/freetdm/src/wanpipe b/libs/freetdm/src/wanpipe index 917220c04e..ae554a11c2 100644 --- a/libs/freetdm/src/wanpipe +++ b/libs/freetdm/src/wanpipe @@ -2,7 +2,7 @@ MOD_CFLAGS +=-DZAP_WANPIPE_SUPPORT 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 diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c index d73a293e96..0cfaa92e49 100644 --- a/libs/freetdm/src/zap_wanpipe.c +++ b/libs/freetdm/src/zap_wanpipe.c @@ -47,6 +47,7 @@ #define WP_INVALID_SOCKET INVALID_HANDLE_VALUE #else #define WP_INVALID_SOCKET -1 +#include #endif #include @@ -67,9 +68,30 @@ #include #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]; @@ -113,6 +135,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, 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); } @@ -188,24 +211,6 @@ static unsigned wp_configure_channel(zap_config_t *cfg, const char *str, zap_spa 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; @@ -223,7 +228,16 @@ static ZINT_CONFIGURE_FUNCTION(wanpipe_configure) } 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; @@ -282,7 +296,28 @@ static ZINT_CONFIGURE_FUNCTION(wanpipe_configure) 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; } @@ -307,7 +342,7 @@ static ZINT_COMMAND_FUNCTION(wanpipe_command) 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; } } @@ -315,51 +350,22 @@ static ZINT_COMMAND_FUNCTION(wanpipe_command) 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: @@ -413,7 +419,7 @@ static ZINT_WAIT_FUNCTION(wanpipe_wait) 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; } @@ -434,7 +440,8 @@ static ZINT_WAIT_FUNCTION(wanpipe_wait) if (s == 0) { return ZAP_TIMEOUT; } - + + return ZAP_SUCCESS; } #ifndef __WINDOWS__ @@ -494,7 +501,6 @@ static ZINT_WRITE_FUNCTION(wanpipe_write_unix) msg.msg_iovlen = 2; msg.msg_iov = iov; - bsent = write(zchan->sockfd, &msg, iov[1].iov_len + iov[0].iov_len); if (bsent > 0){ @@ -510,13 +516,11 @@ static ZINT_WRITE_FUNCTION(wanpipe_write_unix) 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) @@ -535,6 +539,7 @@ zap_status_t wanpipe_init(zap_software_interface_t **zint) 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;