From 5910cd957bd85ad9b087504f818a9f57a19ccc5a Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Fri, 10 Oct 2008 16:02:09 +0000 Subject: [PATCH] OPENZAP-27 add inital CAS support to wanpipe and zt git-svn-id: http://svn.openzap.org/svn/openzap/trunk@592 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/openzap/src/include/openzap.h | 1 + libs/openzap/src/include/zap_config.h | 7 +++ libs/openzap/src/include/zap_types.h | 8 ++- .../src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c | 60 +++++++++++++++++-- libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.c | 51 ++++++++++++++-- libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.h | 13 +++- libs/openzap/src/zap_config.c | 32 +++++++++- libs/openzap/src/zap_io.c | 5 ++ 8 files changed, 165 insertions(+), 12 deletions(-) diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index ae95e34021..e0974326ca 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -448,6 +448,7 @@ struct zap_channel { struct zap_span *span; struct zap_io_interface *zio; zap_hash_t *variable_hash; + unsigned char cas_bits; }; diff --git a/libs/openzap/src/include/zap_config.h b/libs/openzap/src/include/zap_config.h index 0b37208666..f550029388 100644 --- a/libs/openzap/src/include/zap_config.h +++ b/libs/openzap/src/include/zap_config.h @@ -116,6 +116,13 @@ void zap_config_close_file(zap_config_t * cfg); */ int zap_config_next_pair(zap_config_t * cfg, char **var, char **val); +/*! + \brief Retrieve the CAS bits from a configuration string value + \param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx) + \param outbits pointer to aim at the CAS bits +*/ +int zap_config_get_cas_bits(char *strvalue, unsigned char *outbits); + /** @} */ #endif diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index f8ec1ff698..1998465bbb 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -150,9 +150,10 @@ typedef enum { ZAP_OOB_ALARM_TRAP, ZAP_OOB_ALARM_CLEAR, ZAP_OOB_NOOP, + ZAP_OOB_CAS_BITS_CHANGE, ZAP_OOB_INVALID } zap_oob_event_t; -#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "INVALID" +#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "CAS_BITS_CHANGE", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t) typedef enum { @@ -270,6 +271,8 @@ typedef enum { ZAP_COMMAND_DISABLE_ECHOCANCEL, ZAP_COMMAND_ENABLE_ECHOTRAIN, ZAP_COMMAND_DISABLE_ECHOTRAIN, + ZAP_COMMAND_SET_CAS_BITS, + ZAP_COMMAND_GET_CAS_BITS, ZAP_COMMAND_COUNT } zap_command_t; @@ -287,10 +290,11 @@ typedef enum { ZAP_CHAN_TYPE_FXS, ZAP_CHAN_TYPE_FXO, ZAP_CHAN_TYPE_EM, + ZAP_CHAN_TYPE_CAS, ZAP_CHAN_TYPE_COUNT } zap_chan_type_t; -#define CHAN_TYPE_STRINGS "B", "DQ921", "DQ931", "FXS", "FXO", "EM", "INVALID" +#define CHAN_TYPE_STRINGS "B", "DQ921", "DQ931", "FXS", "FXO", "EM", "CAS", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_chan_type, zap_chan_type2str, zap_chan_type_t) typedef enum { diff --git a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c index acf9ab28c0..3be93f2e01 100644 --- a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c +++ b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c @@ -346,10 +346,31 @@ static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm return ZAP_SUCCESS; } -static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number) +static unsigned char wanpipe_swap_bits(unsigned char cas_bits) +{ + unsigned char swapped_bits = 0x0; + if (cas_bits & 0x8) { + swapped_bits |= 0x1; + } + if (cas_bits & 0x4) { + swapped_bits |= 0x2; + } + if (cas_bits & 0x2) { + swapped_bits |= 0x4; + } + if (cas_bits & 0x1) { + swapped_bits |= 0x8; + } + return swapped_bits; +} + +static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number, unsigned char cas_bits) { unsigned configured = 0, x; + if (type == ZAP_CHAN_TYPE_CAS) { + zap_log(ZAP_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits); + } for(x = start; x < end; x++) { zap_channel_t *chan; zap_socket_t sockfd = WP_INVALID_SOCKET; @@ -401,6 +422,12 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW; } } + + if (type == ZAP_CHAN_TYPE_CAS) { + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS; + tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(cas_bits); + wp_tdm_cmd_exec(chan, &tdm_api); + } if (!zap_strlen_zero(name)) { zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name)); @@ -452,8 +479,9 @@ static ZIO_CONFIGURE_FUNCTION(wanpipe_configure) static ZIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span) { int items, i; - char *mydata, *item_list[10]; + char *mydata, *item_list[10]; char *sp, *ch, *mx; + unsigned char cas_bits = 0; int channo; int spanno; int top = 0; @@ -506,8 +534,11 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span) zap_log(ZAP_LOG_ERROR, "Invalid range number %d\n", top); continue; } - - configured += wp_open_range(span, spanno, channo, top, type, name, number); + if (ZAP_CHAN_TYPE_CAS == type && zap_config_get_cas_bits(ch, &cas_bits)) { + zap_log(ZAP_LOG_ERROR, "Failed to get CAS bits in CAS channel\n"); + continue; + } + configured += wp_open_range(span, spanno, channo, top, type, name, number, cas_bits); } @@ -622,6 +653,19 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8); } break; + case ZAP_COMMAND_SET_CAS_BITS: + { + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_WRITE_RBS_BITS; + tdm_api.wp_tdm_cmd.rbs_tx_bits = wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT); + err = wp_tdm_cmd_exec(zchan, &tdm_api); + } + break; + case ZAP_COMMAND_GET_CAS_BITS: + { + /* wanpipe does not has a command to get the CAS bits so we emulate it */ + ZAP_COMMAND_OBJ_INT = zchan->cas_bits; + } + break; default: break; }; @@ -899,6 +943,14 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? ZAP_OOB_ONHOOK : ZAP_OOB_OFFHOOK; } break; + case WP_TDMAPI_EVENT_RBS: + { + event_id = ZAP_OOB_CAS_BITS_CHANGE; + /* save the CAS bits, user should retrieve it with ZAP_COMMAND_GET_CAS_BITS + is there a best play to store this? instead of adding cas_bits member to zap_chan? */ + span->channels[i]->cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); + } + break; default: { zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); diff --git a/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.c b/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.c index 43a662d9fd..4d5c7c7c01 100644 --- a/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.c +++ b/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.c @@ -51,7 +51,7 @@ static zap_socket_t CONTROL_FD = ZT_INVALID_SOCKET; ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event); ZIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event); -static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number) +static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number, unsigned char cas_bits) { unsigned configured = 0, x; char path[] = "/dev/zap/channel"; @@ -59,6 +59,9 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za memset(&ztp, 0, sizeof(ztp)); + if (type == ZAP_CHAN_TYPE_CAS) { + zap_log(ZAP_LOG_DEBUG, "Configuring CAS channels with abcd == 0x%X\n", cas_bits); + } for(x = start; x < end; x++) { zap_channel_t *zchan; zap_socket_t sockfd = ZT_INVALID_SOCKET; @@ -136,6 +139,19 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za } } + if (type == ZAP_CHAN_TYPE_CAS) { + struct zt_chanconfig cc; + memset(&cc, 0, sizeof(cc)); + cc.chan = cc.master = x; + cc.sigtype = ZT_SIG_CAS; + cc.idlebits = cas_bits; + if (ioctl(CONTROL_FD, ZT_CHANCONFIG, &cc)) { + zap_log(ZAP_LOG_ERROR, "failure configuring device %s as OpenZAP device %d:%d fd:%d err:%s", path, zchan->span_id, zchan->chan_id, sockfd, strerror(errno)); + close(sockfd); + continue; + } + } + if (zchan->type != ZAP_CHAN_TYPE_DQ921 && zchan->type != ZAP_CHAN_TYPE_DQ931) { len = zt_globals.codec_ms * 8; if (ioctl(zchan->sockfd, ZT_SET_BLOCKSIZE, &len)) { @@ -224,8 +240,9 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span) { int items, i; - char *mydata, *item_list[10]; + char *mydata, *item_list[10]; char *ch, *mx; + unsigned char cas_bits = 0; int channo; int top = 0; unsigned configured = 0; @@ -266,8 +283,11 @@ static ZIO_CONFIGURE_SPAN_FUNCTION(zt_configure_span) zap_log(ZAP_LOG_ERROR, "Invalid range number %d\n", top); continue; } - - configured += zt_open_range(span, channo, top, type, name, number); + if (ZAP_CHAN_TYPE_CAS == type && zap_config_get_cas_bits(ch, &cas_bits)) { + zap_log(ZAP_LOG_ERROR, "Failed to get CAS bits in CAS channel\n"); + continue; + } + configured += zt_open_range(span, channo, top, type, name, number, cas_bits); } @@ -471,6 +491,18 @@ static ZIO_COMMAND_FUNCTION(zt_command) } } break; + case ZAP_COMMAND_SET_CAS_BITS: + { + int bits = ZAP_COMMAND_OBJ_INT; + err = ioctl(zchan->sockfd, ZT_SETTXBITS, &bits); + } + break; + case ZAP_COMMAND_GET_CAS_BITS: + { + /* probably we should call ZT_GETRXBITS instead? */ + ZAP_COMMAND_OBJ_INT = zchan->cas_bits; + } + break; default: break; }; @@ -663,6 +695,17 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event) event_id = ZAP_OOB_ALARM_CLEAR; } break; + case ZT_EVENT_BITSCHANGED: + { + event_id = ZAP_OOB_CAS_BITS_CHANGE; + int bits = 0; + int err = ioctl(span->channels[i]->sockfd, ZT_GETRXBITS, &bits); + if (err) { + return ZAP_FAIL; + } + span->channels[i]->cas_bits = bits; + } + break; default: { zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", zt_event_id); diff --git a/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.h b/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.h index c3e2067585..d965de4b93 100644 --- a/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.h +++ b/libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.h @@ -226,9 +226,16 @@ ZT_SIG_FXOKS = ((1 << 5) | (1 << 12)), /* FXO, Kewlstart */ ZT_SIG_EM = (1 << 6), /* E&M */ ZT_SIG_CLEAR = (1 << 7), ZT_SIG_HDLCRAW = ((1 << 8) | ZT_SIG_CLEAR), -ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW) +ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW), +ZT_SIG_CAS = (1 << 15) } zt_sigtype_t; +typedef enum { +ZT_DBIT = 1, +ZT_CBIT = 2, +ZT_BBIT = 4, +ZT_ABIT = 8 +} zt_cas_bit_t; /* Defines */ @@ -279,6 +286,10 @@ ZT_SIG_HDLCFCS = ((1 << 9) | ZT_SIG_HDLCRAW) #define ZT_GETCONFMUTE _IOR (ZT_CODE, 49, int) /* Get Conference to mute mode */ #define ZT_ECHOTRAIN _IOW (ZT_CODE, 50, int) /* Control Echo Trainer */ +/* Set/Get CAS bits */ +#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int) +#define ZT_GETRXBITS _IOR (ZT_CODE, 45, int) + #endif diff --git a/libs/openzap/src/zap_config.c b/libs/openzap/src/zap_config.c index cce3507f25..b1f6bd90c4 100644 --- a/libs/openzap/src/zap_config.c +++ b/libs/openzap/src/zap_config.c @@ -53,7 +53,7 @@ int zap_config_open_file(zap_config_t *cfg, const char *file_path) memset(cfg, 0, sizeof(*cfg)); cfg->lockto = -1; - + zap_log(ZAP_LOG_DEBUG, "Configuration file is %s.\n", path); f = fopen(path, "r"); if (!f) { @@ -209,6 +209,36 @@ int zap_config_next_pair(zap_config_t *cfg, char **var, char **val) } +int zap_config_get_cas_bits(char *strvalue, unsigned char *outbits) +{ + char cas_bits[5]; + unsigned char bit = 0x8; + char *double_colon = strchr(strvalue, ':'); + if (!double_colon) { + zap_log(ZAP_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); + return -1; + } + double_colon++; + *outbits = 0; + cas_bits[4] = 0; + if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) { + zap_log(ZAP_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); + return -1; + } + zap_log(ZAP_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits); + int x = 0; + for (; cas_bits[x]; x++) { + if ('1' == cas_bits[x]) { + *outbits |= bit; + } else if ('0' != cas_bits[x]) { + zap_log(ZAP_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n"); + return -1; + } + bit >>= 1; + } + return 0; +} + /* For Emacs: * Local Variables: * mode:c diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index a835a78b62..444f3b85fb 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -2239,9 +2239,13 @@ static zap_status_t load_config(void) configured += zio->configure_span(span, val, qtype, name, number); d++; } + } else if (!strcasecmp(var, "cas-channel")) { + configured += zio->configure_span(span, val, ZAP_CHAN_TYPE_CAS, name, number); } else if (!strcasecmp(var, "dtmf_hangup")) { span->dtmf_hangup = strdup(val); span->dtmf_hangup_len = strlen(val); + } else { + zap_log(ZAP_LOG_ERROR, "unknown span variable '%s'\n", var); } } else { zap_log(ZAP_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val); @@ -2500,6 +2504,7 @@ zap_status_t zap_global_init(void) zap_mutex_create(&globals.mutex); modcount = zap_load_modules(); + zap_log(ZAP_LOG_NOTICE, "Modules configured: %d \n", modcount); if (load_config() == ZAP_SUCCESS) { globals.running = 1;