]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
sync
authorAnthony Minessale <anthony.minessale@gmail.com>
Sat, 23 Jun 2007 18:51:10 +0000 (18:51 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sat, 23 Jun 2007 18:51:10 +0000 (18:51 +0000)
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@288 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/freetdm/Makefile
libs/freetdm/docs/Doxygen.conf
libs/freetdm/src/include/openzap.h
libs/freetdm/src/include/zap_types.h
libs/freetdm/src/testisdn.c
libs/freetdm/src/zap_analog.c
libs/freetdm/src/zap_io.c
libs/freetdm/src/zap_isdn.c
libs/freetdm/src/zap_wanpipe.c
libs/freetdm/src/zap_zt.c

index 17661180d749b423d0626ef41d874d29a6307719..03e8eacefcd68ed54d911ed21ce9feebb98f13cf 100644 (file)
@@ -119,7 +119,7 @@ testtones: $(SRC)/testtones.c $(MYLIB)
        $(CC) $(INCS) -L. $(SRC)/testtones.c -o testtones -lopenzap -lm -lpthread
 
 testisdn: $(SRC)/testisdn.c $(MYLIB)
-       $(CC) $(INCS) -L. $(SRC)/testisdn.c -o testisdn -lopenzap -lm -lpthread
+       $(CC) $(INCS) $(ZAP_CFLAGS) -L. $(SRC)/testisdn.c -o testisdn -lopenzap -lm -lpthread
 
 testanalog: $(SRC)/testanalog.c $(MYLIB)
        $(CC) $(INCS) -L. $(SRC)/testanalog.c -o testanalog -lopenzap -lm -lpthread
index 03800ac6ffe1e819d85365d4ddffb9b5f1174fc1..2e0590e5483002e4882e3c2348bbf6368bf0360d 100644 (file)
@@ -83,7 +83,7 @@ WARN_LOGFILE           =
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
-INPUT                  = .. ../include ../isdn ../isdn/include
+INPUT                  = ../src ../src/include ../src/isdn ../src/isdn/include
 FILE_PATTERNS          = *.c \
                          *.cc \
                          *.cxx \
index cd3c3f920cbb893c92e36ffa8bc192ba5d96c74a..156e02230057acba734efebededc0a24c8b9c104 100644 (file)
 #define zap_test_flag(obj, flag) ((obj)->flags & flag)
 #define zap_test_pflag(obj, flag) ((obj)->pflags & flag)
 
+
+#define zap_set_alarm_flag(obj, flag) (obj)->alarm_flags |= (flag)
+#define zap_clear_alarm_flag(obj, flag) (obj)->alarm_flags &= ~(flag)
+#define zap_test_alarm_flag(obj, flag) ((obj)->alarm_flags & flag)
+
 /*!
   \brief Set a flag on an arbitrary object
   \command obj the object to set the flags on
@@ -324,6 +329,7 @@ struct zap_channel {
        zap_socket_t sockfd;
        zap_channel_flag_t flags;
        uint32_t pflags;
+       zap_alarm_flag_t alarm_flags;
        zap_channel_feature_t features;
        zap_codec_t effective_codec;
        zap_codec_t native_codec;
@@ -423,7 +429,8 @@ struct zap_io_interface {
        zio_configure_t configure;
        zio_open_t open;
        zio_close_t close;
-       zio_destroy_channel_t destroy_channel;
+       zio_channel_destroy_t channel_destroy;
+       zio_get_alarms_t get_alarms;
        zio_command_t command;
        zio_wait_t wait;
        zio_read_t read;
@@ -465,6 +472,7 @@ zap_status_t zap_channel_outgoing_call(zap_channel_t *zchan);
 void zap_channel_rotate_tokens(zap_channel_t *zchan);
 void zap_channel_clear_detected_tones(zap_channel_t *zchan);
 void zap_channel_clear_needed_tones(zap_channel_t *zchan);
+zap_status_t zap_channel_get_alarms(zap_channel_t *zchan);
 zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_t *fsk_data, float db_level);
 zap_status_t zap_channel_clear_token(zap_channel_t *zchan, const char *token);
 zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end);
index 68712f05966786ad34dc84a8a82e15fd767060b7..818fed2af80b37717c5b301abfaecf92c0fd5f3d 100644 (file)
@@ -138,12 +138,24 @@ typedef enum {
        ZAP_OOB_FLASH,
        ZAP_OOB_RING_START,
        ZAP_OOB_RING_STOP,
+       ZAP_OOB_ALARM_TRAP,
+       ZAP_OOB_ALARM_CLEAR,
        ZAP_OOB_NOOP,
        ZAP_OOB_INVALID
 } zap_oob_event_t;
-#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "NOOP", "INVALID"
+#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "INVALID"
 ZAP_STR2ENUM_P(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t)
 
+typedef enum {
+       ZAP_ALARM_NONE = 0,
+       ZAP_ALARM_RECOVER = (1 << 0),
+       ZAP_ALARM_LOOPBACK = (1 << 2),
+       ZAP_ALARM_YELLOW = (1 << 3),
+       ZAP_ALARM_RED = (1 << 4),
+       ZAP_ALARM_BLUE = (1 << 5),
+       ZAP_ALARM_NOTOPEN = ( 1 << 6)
+} zap_alarm_flag_t;
+
 typedef enum {
        ZAP_SIGTYPE_NONE,
        ZAP_SIGTYPE_ISDN,
@@ -162,10 +174,13 @@ typedef enum {
        ZAP_SIGEVENT_PROGRESS_MEDIA,
        ZAP_SIGEVENT_NOTIFY,
        ZAP_SIGEVENT_TONE_DETECTED,
+       ZAP_SIGEVENT_ALARM_TRAP,
+       ZAP_SIGEVENT_ALARM_CLEAR,
        ZAP_SIGEVENT_MISC,
        ZAP_SIGEVENT_INVALID
 } zap_signal_event_t;
-#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "UP", "FLASH", "PROGRESS", "PROGRESS_MEDIA", "NOTIFY", "TONE_DETECTED", "MISC", "INVALID"
+#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "UP", "FLASH", "PROGRESS", \
+               "PROGRESS_MEDIA", "NOTIFY", "TONE_DETECTED", "ALARM_TRAP", "ALARM_CLEAR", "MISC", "INVALID"
 ZAP_STR2ENUM_P(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t)
 
 typedef enum {
@@ -322,9 +337,10 @@ typedef struct zap_span zap_span_t;
 #define ZIO_CONFIGURE_ARGS (const char *category, const char *var, const char *val, int lineno)
 #define ZIO_OPEN_ARGS (zap_channel_t *zchan)
 #define ZIO_CLOSE_ARGS (zap_channel_t *zchan)
-#define ZIO_DESTROY_CHANNEL_ARGS (zap_channel_t *zchan)
+#define ZIO_CHANNEL_DESTROY_ARGS (zap_channel_t *zchan)
 #define ZIO_COMMAND_ARGS (zap_channel_t *zchan, zap_command_t command, void *obj)
 #define ZIO_WAIT_ARGS (zap_channel_t *zchan, zap_wait_flag_t *flags, int32_t to)
+#define ZIO_GET_ALARMS_ARGS (zap_channel_t *zchan)
 #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)
 
@@ -338,7 +354,8 @@ typedef zap_status_t (*zio_configure_span_t) ZIO_CONFIGURE_SPAN_ARGS ;
 typedef zap_status_t (*zio_configure_t) ZIO_CONFIGURE_ARGS ;
 typedef zap_status_t (*zio_open_t) ZIO_OPEN_ARGS ;
 typedef zap_status_t (*zio_close_t) ZIO_CLOSE_ARGS ;
-typedef zap_status_t (*zio_destroy_channel_t) ZIO_DESTROY_CHANNEL_ARGS ;
+typedef zap_status_t (*zio_channel_destroy_t) ZIO_CHANNEL_DESTROY_ARGS ;
+typedef zap_status_t (*zio_get_alarms_t) ZIO_GET_ALARMS_ARGS ;
 typedef zap_status_t (*zio_command_t) ZIO_COMMAND_ARGS ;
 typedef zap_status_t (*zio_wait_t) ZIO_WAIT_ARGS ;
 typedef zap_status_t (*zio_read_t) ZIO_READ_ARGS ;
@@ -354,7 +371,8 @@ typedef zap_status_t (*zio_write_t) ZIO_WRITE_ARGS ;
 #define ZIO_CONFIGURE_FUNCTION(name) zap_status_t name ZIO_CONFIGURE_ARGS
 #define ZIO_OPEN_FUNCTION(name) zap_status_t name ZIO_OPEN_ARGS
 #define ZIO_CLOSE_FUNCTION(name) zap_status_t name ZIO_CLOSE_ARGS
-#define ZIO_DESTROY_CHANNEL_FUNCTION(name) zap_status_t name ZIO_DESTROY_CHANNEL_ARGS
+#define ZIO_CHANNEL_DESTROY_FUNCTION(name) zap_status_t name ZIO_CHANNEL_DESTROY_ARGS
+#define ZIO_GET_ALARMS_FUNCTION(name) zap_status_t name ZIO_GET_ALARMS_ARGS
 #define ZIO_COMMAND_FUNCTION(name) zap_status_t name ZIO_COMMAND_ARGS
 #define ZIO_WAIT_FUNCTION(name) zap_status_t name ZIO_WAIT_ARGS
 #define ZIO_READ_FUNCTION(name) zap_status_t name ZIO_READ_ARGS
index 231215a4b18fccb20d693163411ce231da4df73e..bdfe66a52286d051aae2f9376a4ec08e29d8556d 100644 (file)
@@ -9,9 +9,14 @@ static ZIO_SIGNAL_CB_FUNCTION(on_signal)
 int main(int argc, char *argv[])
 {
        zap_span_t *span;
-
+       
        zap_global_set_default_logger(ZAP_LOG_LEVEL_DEBUG);
 
+       if (argc < 2) {
+               printf("umm no\n");
+               exit(-1);
+       }
+
        if (zap_global_init() != ZAP_SUCCESS) {
                fprintf(stderr, "Error loading OpenZAP\n");
                exit(-1);
@@ -19,7 +24,7 @@ int main(int argc, char *argv[])
 
        printf("OpenZAP loaded\n");
 
-       if (zap_span_find(1, &span) != ZAP_SUCCESS) {
+       if (zap_span_find(atoi(argv[1]), &span) != ZAP_SUCCESS) {
                fprintf(stderr, "Error finding OpenZAP span\n");
                goto done;
        }
index 063fe6a5fae3ba6946bf5308eda4f1ae7ce8b63b..ba87ad1663a3a6fe16f2d9e9cbc04310487302da 100644 (file)
@@ -605,7 +605,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
        return NULL;
 }
 
-static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
+static __inline__ 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;
@@ -708,7 +708,7 @@ static void *zap_analog_run(zap_thread_t *me, void *obj)
                        {
                                zap_event_t *event;
                                while (zap_span_next_event(span, &event) == ZAP_SUCCESS) {
-                                       if (event->e_type == ZAP_OOB_NOOP) {
+                                       if (event->enum_id == ZAP_OOB_NOOP) {
                                                continue;
                                        }
                                        if (process_event(span, event) != ZAP_SUCCESS) {
index 3c05830d2f3b009929888acd1ecbc705216bef78..3b1583d0ebf04babfe7b455bddb4d87b1044ee33 100644 (file)
@@ -211,7 +211,7 @@ static uint32_t hashfromstring(void *ky)
 }
 
 
-static zap_status_t zap_destroy_channel(zap_channel_t *zchan)
+static zap_status_t zap_channel_destroy(zap_channel_t *zchan)
 {
 
        if (zap_test_flag(zchan, ZAP_CHANNEL_CONFIGURED)) {
@@ -226,9 +226,9 @@ static zap_status_t zap_destroy_channel(zap_channel_t *zchan)
                }
 
                
-               if (zchan->span->zio->destroy_channel) {
+               if (zchan->span->zio->channel_destroy) {
                        zap_log(ZAP_LOG_INFO, "Closing channel %u:%u fd:%d\n", zchan->span_id, zchan->chan_id, zchan->sockfd);
-                       if (zchan->span->zio->destroy_channel(zchan) == ZAP_SUCCESS) {
+                       if (zchan->span->zio->channel_destroy(zchan) == ZAP_SUCCESS) {
                                zap_clear_flag_locked(zchan, ZAP_CHANNEL_CONFIGURED);
                        } else {
                                zap_log(ZAP_LOG_ERROR, "Error Closing channel %u:%u fd:%d\n", zchan->span_id, zchan->chan_id, zchan->sockfd);
@@ -239,6 +239,42 @@ static zap_status_t zap_destroy_channel(zap_channel_t *zchan)
        return ZAP_SUCCESS;
 }
 
+
+
+zap_status_t zap_channel_get_alarms(zap_channel_t *zchan)
+{
+       zap_status_t status = ZAP_FAIL;
+
+       if (zap_test_flag(zchan, ZAP_CHANNEL_CONFIGURED)) {
+               if (zchan->span->zio->get_alarms) {
+                       if ((status = zchan->span->zio->get_alarms(zchan)) == ZAP_SUCCESS) {
+                               *zchan->last_error = '\0';
+                               if (zap_test_alarm_flag(zchan, ZAP_ALARM_RED)) {
+                                       snprintf(zchan->last_error + strlen(zchan->last_error), sizeof(zchan->last_error) - strlen(zchan->last_error), "RED/");
+                               }
+                               if (zap_test_alarm_flag(zchan, ZAP_ALARM_YELLOW)) {
+                                       snprintf(zchan->last_error + strlen(zchan->last_error), sizeof(zchan->last_error) - strlen(zchan->last_error), "YELLOW/");
+                               }
+                               if (zap_test_alarm_flag(zchan, ZAP_ALARM_BLUE)) {
+                                       snprintf(zchan->last_error + strlen(zchan->last_error), sizeof(zchan->last_error) - strlen(zchan->last_error), "BLUE/");
+                               }
+                               if (zap_test_alarm_flag(zchan, ZAP_ALARM_LOOPBACK)) {
+                                       snprintf(zchan->last_error + strlen(zchan->last_error), sizeof(zchan->last_error) - strlen(zchan->last_error), "LOOP/");
+                               }
+                               if (zap_test_alarm_flag(zchan, ZAP_ALARM_RECOVER)) {
+                                       snprintf(zchan->last_error + strlen(zchan->last_error), sizeof(zchan->last_error) - strlen(zchan->last_error), "RECOVER/");
+                               }
+                               *(zchan->last_error + strlen(zchan->last_error) - 1) = '\0';
+
+                       }
+               } else {
+                       status = ZAP_NOTIMPL;
+               }
+       }
+       
+       return status;
+}
+
 zap_status_t zap_span_create(zap_io_interface_t *zio, zap_span_t **span)
 {
        zap_span_t *new_span = NULL;
@@ -277,7 +313,7 @@ zap_status_t zap_span_close_all(void)
                span = &globals.spans[i];
 
                for(j = 0; j < span->chan_count; j++) {
-                       zap_destroy_channel(&span->channels[i]);
+                       zap_channel_destroy(&span->channels[i]);
                }
 
                if (span->mutex) {
@@ -1903,7 +1939,7 @@ zap_status_t zap_global_destroy(void)
                        for(j = 1; j <= cur_span->chan_count; j++) {
                                zap_channel_t *cur_chan = &cur_span->channels[j];
                                if (zap_test_flag(cur_chan, ZAP_CHANNEL_CONFIGURED)) {
-                                       zap_destroy_channel(cur_chan);
+                                       zap_channel_destroy(cur_chan);
                                }
                        }
                        zap_mutex_unlock(cur_span->mutex);
index 22d737aa8371d0870127e402a2345be2560aab40..2d1a58c33482d2fb25157454788cbb929bb8cec5 100644 (file)
 
 static L2ULONG zap_time_now()
 {
-#ifdef WIN32
-       return timeGetTime();
-#else
-       struct timeval tv;
-       gettimeofday(&tv, NULL);
-       return ((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
-#endif
+       return zap_current_time_in_ms();
 }
 
 static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call)
@@ -173,9 +167,9 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 static int zap_isdn_921_23(void *pvt, L2UCHAR *msg, L2INT mlen)
 {
        int ret;
-       //char bb[4096] = "";
-       //print_hex_bytes(msg+4, mlen-2, bb, sizeof(bb));
-       //zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen-2, LINE, bb);
+       char bb[4096] = "";
+       print_hex_bytes(msg+4, mlen-2, bb, sizeof(bb));
+       zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen-2, LINE, bb);
 
        ret = Q931Rx23(pvt, msg, mlen);
        if (ret != 0)
@@ -395,6 +389,79 @@ static __inline__ void check_state(zap_span_t *span)
        }
 }
 
+static __inline__ zap_status_t process_event(zap_span_t *span, zap_event_t *event)
+{
+       zap_sigmsg_t sig;
+       zap_isdn_data_t *data = span->isdn_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));
+
+       switch(event->enum_id) {
+       case ZAP_OOB_ALARM_TRAP:
+               {
+                       sig.event_id = ZAP_OOB_ALARM_TRAP;
+                       if (event->channel->state != ZAP_CHANNEL_STATE_DOWN) {
+                               zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_TERMINATING);
+                       }
+                       zap_set_flag(event->channel, ZAP_CHANNEL_SUSPENDED);
+                       zap_channel_get_alarms(event->channel);
+                       data->sig_cb(&sig);
+                       zap_log(ZAP_LOG_WARNING, "channel %d:%d (%d:%d) has alarms [%s]\n", 
+                                       event->channel->span_id, event->channel->chan_id, 
+                                       event->channel->physical_span_id, event->channel->physical_chan_id, 
+                                       event->channel->last_error);
+               }
+               break;
+       case ZAP_OOB_ALARM_CLEAR:
+               {
+                       sig.event_id = ZAP_OOB_ALARM_CLEAR;
+                       zap_clear_flag(event->channel, ZAP_CHANNEL_SUSPENDED);
+                       zap_channel_get_alarms(event->channel);
+                       data->sig_cb(&sig);
+               }
+               break;
+       }
+
+       return ZAP_SUCCESS;
+}
+
+
+static __inline__ void check_events(zap_span_t *span)
+{
+       zap_status_t status;
+
+       status = zap_span_poll_event(span, 5);
+
+       switch(status) {
+       case ZAP_SUCCESS:
+               {
+                       zap_event_t *event;
+                       while (zap_span_next_event(span, &event) == ZAP_SUCCESS) {
+                               if (event->enum_id == ZAP_OOB_NOOP) {
+                                       continue;
+                               }
+                               if (process_event(span, event) != ZAP_SUCCESS) {
+                                       break;
+                               }
+                       }
+               }
+               break;
+       case ZAP_FAIL:
+               {
+                       zap_log(ZAP_LOG_DEBUG, "Event Failure!\n");
+               }
+               break;
+       default:
+               break;
+       }
+}
+
 static void *zap_isdn_run(zap_thread_t *me, void *obj)
 {
        zap_span_t *span = (zap_span_t *) obj;
@@ -417,7 +484,8 @@ static void *zap_isdn_run(zap_thread_t *me, void *obj)
 
                Q921TimerTick(&data->q921);
                check_state(span);
-               
+               check_events(span);
+
                switch(status) {
                case ZAP_FAIL:
                        {
index 3e52568fb105de39e969e6986949bb07249ad170..7a7536f9148015e76c46bad9ba357996c73a88b2 100644 (file)
@@ -914,7 +914,7 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
        
 }
 
-static ZIO_DESTROY_CHANNEL_FUNCTION(wanpipe_destroy_channel)
+static ZIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
 {
        if (zchan->sockfd > -1) {
                close(zchan->sockfd);
@@ -947,7 +947,7 @@ zap_status_t wanpipe_init(zap_io_interface_t **zio)
        wanpipe_interface.poll_event = wanpipe_poll_event;
 #endif
        wanpipe_interface.next_event = wanpipe_next_event;
-       wanpipe_interface.destroy_channel = wanpipe_destroy_channel;
+       wanpipe_interface.channel_destroy = wanpipe_channel_destroy;
        *zio = &wanpipe_interface;
 
        return ZAP_SUCCESS;
index 47a995019ba2c53dfef08a52c56c5ab1500f4a54..5f2a60b0525b5a0c49fe394e62cc49175edab0c7 100644 (file)
@@ -45,19 +45,14 @@ static struct {
 } zt_globals;
 
 #define ZT_INVALID_SOCKET -1
+static const char ctlpath[] = "/dev/zap/ctl";
+static zap_socket_t CONTROL_FD = ZT_INVALID_SOCKET;
 
 static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number)
 {
        unsigned configured = 0, x;
-       const char ctlpath[] = "/dev/zap/ctl";
        char path[] = "/dev/zap/channel";
        zt_params_t ztp;
-       zap_socket_t ctlfd = ZT_INVALID_SOCKET;
-
-       if ((ctlfd = open(ctlpath, O_RDWR)) < 0) {
-               zap_log(ZAP_LOG_ERROR, "Cannot open control device\n");
-               return 0;
-       }
 
        memset(&ztp, 0, sizeof(ztp));
 
@@ -71,7 +66,7 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za
                if (sockfd != ZT_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &zchan) == ZAP_SUCCESS) {
 
                        if (ioctl(sockfd, ZT_SPECIFY, &x)) {
-                               zap_log(ZAP_LOG_ERROR, "failure configuring device %s chan %d fd %d (%s)\n", path, x, ctlfd, strerror(errno));
+                               zap_log(ZAP_LOG_ERROR, "failure configuring device %s chan %d fd %d (%s)\n", path, x, sockfd, strerror(errno));
                                close(sockfd);
                                continue;
                        }
@@ -132,9 +127,9 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za
                                default:
                                        break;
                                }
-                               if (ioctl(ctlfd, ZT_CHANCONFIG, &cc)) {
+                               if (ioctl(CONTROL_FD, ZT_CHANCONFIG, &cc)) {
                                        zap_log(ZAP_LOG_ERROR, "failure configuring device %s chan %d fd %d (%s)\n", 
-                                                       path, x, ctlfd, strerror(errno));
+                                                       path, x, CONTROL_FD, strerror(errno));
                                        close(sockfd);
                                        break;
                                }
@@ -208,7 +203,7 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za
                }
        }
        
-       close(ctlfd);
+
 
        return configured;
 }
@@ -448,6 +443,25 @@ static ZIO_COMMAND_FUNCTION(zt_command)
        return ZAP_SUCCESS;
 }
 
+static ZIO_GET_ALARMS_FUNCTION(zt_get_alarms)
+{
+       struct zt_spaninfo info;
+
+       memset(&info, 0, sizeof(info));
+       info.span_no = zchan->physical_span_id;
+
+       if (ioctl(CONTROL_FD, ZT_SPANSTAT, &info)) {
+               snprintf(zchan->last_error, sizeof(zchan->last_error), "ioctl failed (%s)", strerror(errno));
+               snprintf(zchan->span->last_error, sizeof(zchan->span->last_error), "ioctl failed (%s)", strerror(errno));
+               return ZAP_FAIL;
+       }
+
+       zchan->alarm_flags = info.alarms;
+
+       return ZAP_SUCCESS;
+}
+
+
 static ZIO_WAIT_FUNCTION(zt_wait)
 {
        int32_t inflags = 0;
@@ -478,10 +492,9 @@ static ZIO_WAIT_FUNCTION(zt_wait)
        }
 
        if (result > 0) {
-               *flags = pfds[0].revents;
+               inflags = pfds[0].revents;
        }
 
-
        *flags = ZAP_NO_FLAGS;
 
        if (result < 0){
@@ -595,6 +608,16 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
                                        }
                                }
                                break;
+                       case ZT_EVENT_ALARM:
+                               {
+                                       event_id = ZAP_OOB_ALARM_TRAP;
+                               }
+                               break;
+                       case ZT_EVENT_NOALARM:
+                               {
+                                       event_id = ZAP_OOB_ALARM_CLEAR;
+                               }
+                               break;
                        default:
                                {
                                        zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", zt_event_id);
@@ -655,7 +678,7 @@ static ZIO_WRITE_FUNCTION(zt_write)
        return ZAP_FAIL;
 }
 
-static ZIO_DESTROY_CHANNEL_FUNCTION(zt_destroy_channel)
+static ZIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy)
 {
        close(zchan->sockfd);
        zchan->sockfd = ZT_INVALID_SOCKET;
@@ -671,6 +694,11 @@ zap_status_t zt_init(zap_io_interface_t **zio)
        memset(&zt_interface, 0, sizeof(zt_interface));
        memset(&zt_globals, 0, sizeof(zt_globals));
 
+       if ((CONTROL_FD = open(ctlpath, O_RDWR)) < 0) {
+               zap_log(ZAP_LOG_ERROR, "Cannot open control device\n");
+               return 0;
+       }
+
        zt_globals.codec_ms = 20;
        zt_globals.wink_ms = 150;
        zt_globals.flash_ms = 750;
@@ -688,8 +716,8 @@ zap_status_t zt_init(zap_io_interface_t **zio)
        zt_interface.write = zt_write;
        zt_interface.poll_event = zt_poll_event;
        zt_interface.next_event = zt_next_event;
-       zt_interface.destroy_channel = zt_destroy_channel;
-
+       zt_interface.channel_destroy = zt_channel_destroy;
+       zt_interface.get_alarms = zt_get_alarms;
        *zio = &zt_interface;
 
        return ZAP_SUCCESS;
@@ -697,7 +725,7 @@ zap_status_t zt_init(zap_io_interface_t **zio)
 
 zap_status_t zt_destroy(void)
 {
-
+       close(CONTROL_FD);
        memset(&zt_interface, 0, sizeof(zt_interface));
        return ZAP_SUCCESS;
 }