]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
OPENZAP-27 add inital CAS support to wanpipe and zt
authorMichael Jerris <mike@jerris.com>
Fri, 10 Oct 2008 16:02:09 +0000 (16:02 +0000)
committerMichael Jerris <mike@jerris.com>
Fri, 10 Oct 2008 16:02:09 +0000 (16:02 +0000)
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@592 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/openzap/src/include/openzap.h
libs/openzap/src/include/zap_config.h
libs/openzap/src/include/zap_types.h
libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.c
libs/openzap/src/ozmod/ozmod_zt/ozmod_zt.h
libs/openzap/src/zap_config.c
libs/openzap/src/zap_io.c

index ae95e34021eb90dcfd19ab7ef9cf1609efec0861..e0974326ca8d110de2e750b4fe6f0c32754a8247 100644 (file)
@@ -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;
 };
 
 
index 0b37208666449a2bc187ad1841ea247b4c630298..f5500293888de749f46746f7d360a4568e340154 100644 (file)
@@ -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
index f8ec1ff6982897d4ac2bdc3e1cf9098bec0eff02..1998465bbb51829b9ccb5b80a17d909fe81b56e8 100644 (file)
@@ -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 {
index acf9ab28c0159e0c3346a86a293bc2286ff8e0b6..3be93f2e01b06a1d6d41a67aa94f9dba32e4f980 100644 (file)
@@ -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);
index 43a662d9fdaaa17eb4473e443a388083630310ed..4d5c7c7c014ada47c6416471c000cd6404010e78 100644 (file)
@@ -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);
index c3e206758519c4a900bee12c6cb89aca7302d32f..d965de4b937a8aa611f62f544a62225bdfeb9cd0 100644 (file)
@@ -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
 
index cce3507f25fd50e156fec640976abafb4d0017d6..b1f6bd90c4d29b1f2c0dec029ff9a11b5c57902f 100644 (file)
@@ -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
index a835a78b6278ebe4433d4714fddf2036fea0342d..444f3b85fb33cc753fa85b4c8af3006c9a12f984 100644 (file)
@@ -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;