From b06e0aeea2decb117d582e5b411c30df8945587a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 26 May 2007 04:58:35 +0000 Subject: [PATCH] update git-svn-id: http://svn.openzap.org/svn/openzap/trunk@159 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/openzap/Makefile | 16 +- libs/openzap/src/priserver.c | 316 +++++++++++++++++++++++++++++++++ libs/openzap/src/sangoma_pri.c | 240 +++++++++++++++++++++++++ libs/openzap/src/sangoma_pri.h | 100 +++++++++++ 4 files changed, 667 insertions(+), 5 deletions(-) create mode 100644 libs/openzap/src/priserver.c create mode 100644 libs/openzap/src/sangoma_pri.c create mode 100644 libs/openzap/src/sangoma_pri.h diff --git a/libs/openzap/Makefile b/libs/openzap/Makefile index 1c04d82ba0..1fdd40748b 100644 --- a/libs/openzap/Makefile +++ b/libs/openzap/Makefile @@ -65,7 +65,9 @@ PWD=$(shell pwd) INCS=-I$(PWD)/$(SRC)//include -I$(PWD)/$(SRC)//isdn/include CFLAGS=$(ZAP_CFLAGS) $(INCS) MYLIB=libopenzap.a -TMP=-I../libpri-1.2.4 -I$(SRC)/include -I./src -w +LIBPRIA=libpri.a +LIBPRI=./libpri +TMP=-I$(LIBPRI) -I$(SRC)/include -I./src -w include general.makefile $(ZAP_MODS) @@ -84,14 +86,17 @@ testisdn: $(SRC)/testisdn.c $(MYLIB) testanalog: $(SRC)/testanalog.c $(MYLIB) $(CC) $(INCS) -L. $(SRC)/testanalog.c -o testanalog -lopenzap -lm -lpthread -priserver.o: $(SRC)/priserver.c +$(SRC)/priserver.o: $(SRC)/priserver.c $(CC) $(INCS) $(TMP) -c $(SRC)/priserver.c -o $(SRC)/priserver.o $(SRC)/sangoma_pri.o: $(SRC)/sangoma_pri.c $(CC) $(INCS) $(TMP) -c $(SRC)/sangoma_pri.c -o $(SRC)/sangoma_pri.o -priserver: $(MYLIB) $(SRC)/priserver.o $(SRC)/sangoma_pri.o - $(CC) $(SRC)/sangoma_pri.o $(SRC)/priserver.o -L. -o priserver -lopenzap -lm -lpthread ../../libpri-1.2.4/libpri.a +$(LIBPRI)/$(LIBPRIA): + cd libpri && make + +priserver: $(MYLIB) $(SRC)/priserver.o $(SRC)/sangoma_pri.o $(LIBPRI)/$(LIBPRIA) + $(CC) $(SRC)/sangoma_pri.o $(SRC)/priserver.o -L. -o priserver -lopenzap -lm -lpthread $(LIBPRI)/$(LIBPRIA) $(SRC)/zap_io.o: $(SRC)/zap_io.c $(CC) $(MOD_CFLAGS) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@ @@ -117,8 +122,9 @@ mod_openzap-install: mod_openzap cd mod_openzap && make install mod_openzap-clean: - cd mod_openzap && make clean + @if [ -f mod_openzap/mod_openzap.so ] ; then cd mod_openzap && make clean ; fi clean: mod_openzap-clean rm -f $(SRC)/*.o $(SRC)/isdn/*.o $(MYLIB) *~ \#* testapp priserver testisdn testanalog + @if [ -f $(LIBPRI)/$(LIBPRIA) ] ; then cd $(LIBPRI) && make clean ; fi diff --git a/libs/openzap/src/priserver.c b/libs/openzap/src/priserver.c new file mode 100644 index 0000000000..5612e19a15 --- /dev/null +++ b/libs/openzap/src/priserver.c @@ -0,0 +1,316 @@ +/***************************************************************************** + * priserver.c Refactoring of pritest.c + * + * Author(s): Anthony Minessale II + * Nenad Corbic + * + * Copyright: (c) 2005 Anthony Minessale II + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * ============================================================================ + */ + +#include "openzap.h" +#include +#include +#include +#include +#include +#include + +typedef struct { + int pid; + q931_call call; + void *pri; + int ready; +}call_info_t; + + +#define SANGOMA_MAX_CHAN_PER_SPAN 32 + +static call_info_t pidmap[SANGOMA_MAX_CHAN_PER_SPAN]; + +ZIO_EVENT_CB_FUNCTION(my_zap_event_handler) +{ + if (event->e_type = ZAP_EVENT_DTMF) { + char *dtmf = event->data; + printf("DTMF %s\n", dtmf); + } +} + +/* Stupid runtime process to play a file to a b channel*/ +#define BYTES 320 +#define MAX_BYTES 1000 + +static int ready = 1; + +static void handle_SIGINT(int sig) +{ + if (sig) { + ready = 0; + } + + return; +} + +static void launch_channel(struct sangoma_pri *spri, int channo) +{ + pid_t pid; + int fd = 0, file = 0, inlen = 0, outlen = 0; + unsigned char inframe[MAX_BYTES], outframe[MAX_BYTES]; + fd_set readfds; + int mtu_mru=BYTES / 2; + int err; + zap_channel_t *chan; + zap_codec_t codec = ZAP_CODEC_SLIN; + unsigned ms = 20; + unsigned int lead = 50; + int ifd = -1; + zap_tone_type_t tt = ZAP_TONE_DTMF; + char dtmf[] = "1234567890"; + int loops = 0; + + pid = fork(); + + if (pid) { + pidmap[channo-1].pid = pid; + printf("-- Launching process %d to handle channel %d\n", pid, channo); + return; + } + + signal(SIGINT, handle_SIGINT); + + //ifd = open("/nfs/sounds/ptest.raw", O_WRONLY|O_CREAT|O_TRUNC, 777); + + memset(inframe, 0, MAX_BYTES); + memset(outframe, 0, MAX_BYTES); + + if (zap_channel_open("wanpipe", spri->span, channo, &chan) != ZAP_SUCCESS) { + printf("DEBUG cant open fd!\n"); + } + + + +#if 1 + if (zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec) != ZAP_SUCCESS) { + printf("Critical Error: Failed to set driver codec!\n"); + zap_channel_close(&chan); + exit(-1); + } +#endif + +#if 1 + if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_TONE_DETECT, &tt) != ZAP_SUCCESS) { + printf("Critical Error: Failed to set dtmf detect!\n"); + zap_channel_close(&chan); + exit(-1); + } + zap_channel_set_event_callback(chan, my_zap_event_handler); +#endif + + + if (zap_channel_command(chan, ZAP_COMMAND_SET_INTERVAL, &ms) != ZAP_SUCCESS) { + printf("Critical Error: Failed to set codec interval!\n"); + zap_channel_close(&chan); + exit(-1); + } + + file = open("sound.raw", O_RDONLY); + if (file < 0){ + printf("Critical Error: Failed to open sound file!\n"); + zap_channel_close(&chan); + exit(-1); + } + + + while(ready) { + zap_wait_flag_t flags = ZAP_READ; + zap_size_t len; + loops++; + + if (lead) { + lead--; + } + + if (!lead && loops == 300) { +#if 1 + if (zap_channel_command(chan, ZAP_COMMAND_SEND_DTMF, dtmf) != ZAP_SUCCESS) { + printf("Critical Error: Failed to send dtmf\n"); + zap_channel_close(&chan); + exit(-1); + } +#endif + + } + + if (zap_channel_wait(chan, &flags, 2000) != ZAP_SUCCESS) { + printf("wait FAIL! [%s]\n", chan->last_error); + break; + } + + if (flags & ZAP_READ) { + len = MAX_BYTES; + if (zap_channel_read(chan, inframe, &len) == ZAP_SUCCESS) { + //printf("READ: %d\n", len); + //write(ifd, inframe, len); + if(!lead && (outlen = read(file, outframe, len)) <= 0) { + break; + } + + } else { + printf("READ FAIL! %d [%s]\n", len, chan->last_error); + break; + } + if (lead) { + continue; + } + zap_channel_write(chan, outframe, &len); + } else { + printf("BREAK"); + break; + } + } + + printf("loop done\n"); + + //sangoma_get_full_cfg(fd, &tdm_api); + close(file); + //close(ifd); + + + if (zap_channel_close(&chan) != ZAP_SUCCESS) { + printf("Critical Error: Failed to close channel [%s]\n", chan->last_error); + } + + printf("Call Handler: Process Finished\n"); + exit(0); +} + + +/* Event Handlers */ + +static int on_info(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) +{ + printf( "number is: %s\n", event->ring.callednum); + if(strlen(event->ring.callednum) > 3) { + printf( "final number is: %s\n", event->ring.callednum); + pri_answer(spri->pri, event->ring.call, 0, 1); + } + return 0; +} + +static int on_hangup(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) +{ + //pri_hangup(spri->pri, event->hangup.call, event->hangup.cause); + printf("-- Hanging up channel %d\n", event->hangup.channel); + if(pidmap[event->hangup.channel-1].pid) { + pri_hangup(spri->pri, event->hangup.call, 16); + pri_destroycall(spri->pri, event->hangup.call); + kill(pidmap[event->hangup.channel-1].pid, SIGINT); + pidmap[event->hangup.channel-1].pid = 0; + } + return 0; +} + +static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) +{ + printf("-- Ring on channel %d (from %s to %s), answering...\n", event->ring.channel, event->ring.callingnum, event->ring.callednum); + pri_answer(spri->pri, event->ring.call, event->ring.channel, 1); + memcpy(&pidmap[event->ring.channel-1].call, event->ring.call, sizeof(q931_call)); + pidmap[event->ring.channel-1].pri=spri->pri; + pidmap[event->ring.channel-1].call = *event->ring.call; + launch_channel(spri, event->ring.channel); + return 0; +} + +static int on_restart(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) +{ + printf("-- Restarting channel %d\n", event->restart.channel); + return 0; +} + +static int on_anything(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri_event *event) +{ + printf("%s: Caught Event %d (%s)\n", __FUNCTION__, event_type, sangoma_pri_event_str(event_type)); + return 0; +} + +/* Generic Reaper */ +static void chan_ended(int sig) +{ + int status; + int x; + struct rusage rusage; + pid_t pid; + pid = wait4(-1, &status, WNOHANG, &rusage); + + printf("-- PID %d ended\n", pid); + + for (x=0;x -1) { + fprintf(stderr, "--!! Unknown PID %d exited\n", pid); + signal(SIGCHLD, chan_ended); + return; + } +} + +/* Our Program */ +int main(int argc, char *argv[]) +{ + struct sangoma_pri spri; + int debug = 0; + if (argv[1]) { + debug = atoi(argv[1]); + } + + zap_global_set_default_logger(ZAP_LOG_LEVEL_DEBUG); + if (zap_global_init() != ZAP_SUCCESS) { + fprintf(stderr, "Error loading OpenZAP\n"); + exit(-1); + } + + printf("OpenZAP loaded\n"); + + + + if (sangoma_init_pri(&spri, + 1, // span + 24, // dchan + SANGOMA_PRI_SWITCH_DMS100, + SANGOMA_PRI_CPE, + debug) < 0) { + return -1; + } + //spri.pri->debug = (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE); + + //pri_set_debug(&spri.pri, (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)); + + SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_ANY, on_anything); + SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RING, on_ring); + SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP, on_hangup); + SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_HANGUP_REQ, on_hangup); + SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_INFO_RECEIVED, on_info); + SANGOMA_MAP_PRI_EVENT(spri, SANGOMA_PRI_EVENT_RESTART, on_restart); + + signal(SIGCHLD, chan_ended); + sangoma_run_pri(&spri); + return 0; +} + diff --git a/libs/openzap/src/sangoma_pri.c b/libs/openzap/src/sangoma_pri.c new file mode 100644 index 0000000000..b4692216d0 --- /dev/null +++ b/libs/openzap/src/sangoma_pri.c @@ -0,0 +1,240 @@ +/***************************************************************************** + * sangoma_pri.c libpri Sangoma integration + * + * Author(s): Anthony Minessale II + * Nenad Corbic + * + * Copyright: (c) 2005 Anthony Minessale II + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * ============================================================================ + */ + +#include "openzap.h" +#include +#ifndef HAVE_GETTIMEOFDAY + +#ifdef WIN32 +#include + +static __inline int gettimeofday(struct timeval *tp, void *nothing) +{ +#ifdef WITHOUT_MM_LIB + SYSTEMTIME st; + time_t tt; + struct tm tmtm; + /* mktime converts local to UTC */ + GetLocalTime (&st); + tmtm.tm_sec = st.wSecond; + tmtm.tm_min = st.wMinute; + tmtm.tm_hour = st.wHour; + tmtm.tm_mday = st.wDay; + tmtm.tm_mon = st.wMonth - 1; + tmtm.tm_year = st.wYear - 1900; tmtm.tm_isdst = -1; + tt = mktime (&tmtm); + tp->tv_sec = tt; + tp->tv_usec = st.wMilliseconds * 1000; +#else + /** + ** The earlier time calculations using GetLocalTime + ** had a time resolution of 10ms.The timeGetTime, part + ** of multimedia apis offer a better time resolution + ** of 1ms.Need to link against winmm.lib for this + **/ + unsigned long Ticks = 0; + unsigned long Sec =0; + unsigned long Usec = 0; + Ticks = timeGetTime(); + + Sec = Ticks/1000; + Usec = (Ticks - (Sec*1000))*1000; + tp->tv_sec = Sec; + tp->tv_usec = Usec; +#endif /* WITHOUT_MM_LIB */ + (void)nothing; + return 0; +} +#endif /* WIN32 */ +#endif /* HAVE_GETTIMEOFDAY */ + +static struct sangoma_pri_event_list SANGOMA_PRI_EVENT_LIST[] = { + {0, SANGOMA_PRI_EVENT_ANY, "ANY"}, + {1, SANGOMA_PRI_EVENT_DCHAN_UP, "DCHAN_UP"}, + {2, SANGOMA_PRI_EVENT_DCHAN_DOWN, "DCHAN_DOWN"}, + {3, SANGOMA_PRI_EVENT_RESTART, "RESTART"}, + {4, SANGOMA_PRI_EVENT_CONFIG_ERR, "CONFIG_ERR"}, + {5, SANGOMA_PRI_EVENT_RING, "RING"}, + {6, SANGOMA_PRI_EVENT_HANGUP, "HANGUP"}, + {7, SANGOMA_PRI_EVENT_RINGING, "RINGING"}, + {8, SANGOMA_PRI_EVENT_ANSWER, "ANSWER"}, + {9, SANGOMA_PRI_EVENT_HANGUP_ACK, "HANGUP_ACK"}, + {10, SANGOMA_PRI_EVENT_RESTART_ACK, "RESTART_ACK"}, + {11, SANGOMA_PRI_EVENT_FACNAME, "FACNAME"}, + {12, SANGOMA_PRI_EVENT_INFO_RECEIVED, "INFO_RECEIVED"}, + {13, SANGOMA_PRI_EVENT_PROCEEDING, "PROCEEDING"}, + {14, SANGOMA_PRI_EVENT_SETUP_ACK, "SETUP_ACK"}, + {15, SANGOMA_PRI_EVENT_HANGUP_REQ, "HANGUP_REQ"}, + {16, SANGOMA_PRI_EVENT_NOTIFY, "NOTIFY"}, + {17, SANGOMA_PRI_EVENT_PROGRESS, "PROGRESS"}, + {18, SANGOMA_PRI_EVENT_KEYPAD_DIGIT, "KEYPAD_DIGIT"} +}; + +#define LINE "--------------------------------------------------------------------------------" + +char *sangoma_pri_event_str(sangoma_pri_event_t event_id) +{ + return SANGOMA_PRI_EVENT_LIST[event_id].name; +} + +static int __pri_sangoma_read(struct pri *pri, void *buf, int buflen) +{ + struct sangoma_pri *spri = (struct sangoma_pri *) pri->userdata; + zap_size_t len = buflen; + int res; + char bb[4096] = ""; + + + if (zap_channel_read(spri->zdchan, buf, &len) != ZAP_SUCCESS) { + printf("D-READ FAIL! [%s]\n", spri->zdchan->last_error); + return 0; + } + res = (int)len; + memset(&((unsigned char*)buf)[res],0,2); + res+=2; + + print_bits(buf, res-2, bb, sizeof(bb), 1); + zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", res-2, LINE, bb); + + return res; +} + +static int __pri_sangoma_write(struct pri *pri, void *buf, int buflen) +{ + struct sangoma_pri *spri = (struct sangoma_pri *) pri->userdata; + int res; + zap_size_t len = buflen -2; + char bb[4096] = ""; + + if (zap_channel_write(spri->zdchan, buf, &len) != ZAP_SUCCESS) { + printf("D-WRITE FAIL! [%s]\n", spri->zdchan->last_error); + return 0; + } + + print_bits(buf, (int)buflen-2, bb, sizeof(bb), 1); + zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)buflen-2, LINE, bb); + + return (int) buflen; +} + +int sangoma_init_pri(struct sangoma_pri *spri, int span, int dchan, int swtype, int node, int debug) +{ + int ret = -1; + zap_socket_t dfd = 0; + + memset(spri, 0, sizeof(struct sangoma_pri)); + + if (zap_channel_open("wanpipe", span, dchan, &spri->zdchan) != ZAP_SUCCESS) { + fprintf(stderr, "Unable to open DCHAN %d for span %d (%s)\n", dchan, span, strerror(errno)); + } else { + if ((spri->pri = pri_new_cb(spri->zdchan->sockfd, node, swtype, __pri_sangoma_read, __pri_sangoma_write, spri))){ + spri->span = span; + pri_set_debug(spri->pri, debug); + ret = 0; + } else { + fprintf(stderr, "Unable to create PRI\n"); + } + } + return ret; +} + + +int sangoma_one_loop(struct sangoma_pri *spri) +{ + fd_set rfds, efds; + struct timeval now = {0,0}, *next; + pri_event *event; + int sel; + + if (spri->on_loop) { + spri->on_loop(spri); + } + + FD_ZERO(&rfds); + FD_ZERO(&efds); + +#ifdef _MSC_VER +//Windows macro for FD_SET includes a warning C4127: conditional expression is constant +#pragma warning(push) +#pragma warning(disable:4127) +#endif + + FD_SET(spri->pri->fd, &rfds); + FD_SET(spri->pri->fd, &efds); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + if ((next = pri_schedule_next(spri->pri))) { + gettimeofday(&now, NULL); + now.tv_sec = next->tv_sec - now.tv_sec; + now.tv_usec = next->tv_usec - now.tv_usec; + if (now.tv_usec < 0) { + now.tv_usec += 1000000; + now.tv_sec -= 1; + } + if (now.tv_sec < 0) { + now.tv_sec = 0; + now.tv_usec = 0; + } + } + + sel = select(spri->pri->fd + 1, &rfds, NULL, &efds, next ? &now : NULL); + event = NULL; + + if (!sel) { + event = pri_schedule_run(spri->pri); + } else if (sel > 0) { + event = pri_check_event(spri->pri); + } + + if (event) { + event_handler handler; + /* 0 is catchall event handler */ + if ((handler = spri->eventmap[event->e] ? spri->eventmap[event->e] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) { + handler(spri, event->e, event); + } else { + fprintf(stderr,"No event handler found for event %d.\n", event->e); + } + } + + return sel; +} + +int sangoma_run_pri(struct sangoma_pri *spri) +{ + int ret = 0; + + for (;;){ + ret=sangoma_one_loop(spri); + if (ret < 0){ + +#ifndef WIN32 //This needs to be adressed fror WIN32 still + if (errno == EINTR){ + /* Igonore an interrupted system call */ + continue; + } +#endif + printf("Error = %i\n",ret); + perror("Sangoma Run Pri: "); + break; + } + } + + return ret; + +} + diff --git a/libs/openzap/src/sangoma_pri.h b/libs/openzap/src/sangoma_pri.h new file mode 100644 index 0000000000..5ea21eb7b5 --- /dev/null +++ b/libs/openzap/src/sangoma_pri.h @@ -0,0 +1,100 @@ +/***************************************************************************** + * libsangoma.c AFT T1/E1: HDLC API Code Library + * + * Author(s): Anthony Minessale II + * Nenad Corbic + * + * Copyright: (c) 2005 Anthony Minessale II + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * ============================================================================ + */ + +#ifndef _SANGOMA_PRI_H +#define _SANGOMA_PRI_H +#include +#include + + +#define SANGOMA_MAX_CHAN_PER_SPAN 32 + +typedef enum { + SANGOMA_PRI_EVENT_ANY = 0, + SANGOMA_PRI_EVENT_DCHAN_UP = PRI_EVENT_DCHAN_UP, + SANGOMA_PRI_EVENT_DCHAN_DOWN = PRI_EVENT_DCHAN_DOWN, + SANGOMA_PRI_EVENT_RESTART = PRI_EVENT_RESTART, + SANGOMA_PRI_EVENT_CONFIG_ERR = PRI_EVENT_CONFIG_ERR, + SANGOMA_PRI_EVENT_RING = PRI_EVENT_RING, + SANGOMA_PRI_EVENT_HANGUP = PRI_EVENT_HANGUP, + SANGOMA_PRI_EVENT_RINGING = PRI_EVENT_RINGING, + SANGOMA_PRI_EVENT_ANSWER = PRI_EVENT_ANSWER, + SANGOMA_PRI_EVENT_HANGUP_ACK = PRI_EVENT_HANGUP_ACK, + SANGOMA_PRI_EVENT_RESTART_ACK = PRI_EVENT_RESTART_ACK, + SANGOMA_PRI_EVENT_FACNAME = PRI_EVENT_FACNAME, + SANGOMA_PRI_EVENT_INFO_RECEIVED = PRI_EVENT_INFO_RECEIVED, + SANGOMA_PRI_EVENT_PROCEEDING = PRI_EVENT_PROCEEDING, + SANGOMA_PRI_EVENT_SETUP_ACK = PRI_EVENT_SETUP_ACK, + SANGOMA_PRI_EVENT_HANGUP_REQ = PRI_EVENT_HANGUP_REQ, + SANGOMA_PRI_EVENT_NOTIFY = PRI_EVENT_NOTIFY, + SANGOMA_PRI_EVENT_PROGRESS = PRI_EVENT_PROGRESS, + SANGOMA_PRI_EVENT_KEYPAD_DIGIT = PRI_EVENT_KEYPAD_DIGIT +} sangoma_pri_event_t; + +typedef enum { + SANGOMA_PRI_NETWORK = PRI_NETWORK, + SANGOMA_PRI_CPE = PRI_CPE +} sangoma_pri_node_t; + +typedef enum { + SANGOMA_PRI_SWITCH_UNKNOWN = PRI_SWITCH_UNKNOWN, + SANGOMA_PRI_SWITCH_NI2 = PRI_SWITCH_NI2, + SANGOMA_PRI_SWITCH_DMS100 = PRI_SWITCH_DMS100, + SANGOMA_PRI_SWITCH_LUCENT5E = PRI_SWITCH_LUCENT5E, + SANGOMA_PRI_SWITCH_ATT4ESS = PRI_SWITCH_ATT4ESS, + SANGOMA_PRI_SWITCH_EUROISDN_E1 = PRI_SWITCH_EUROISDN_E1, + SANGOMA_PRI_SWITCH_EUROISDN_T1 = PRI_SWITCH_EUROISDN_T1, + SANGOMA_PRI_SWITCH_NI1 = PRI_SWITCH_NI1, + SANGOMA_PRI_SWITCH_GR303_EOC = PRI_SWITCH_GR303_EOC, + SANGOMA_PRI_SWITCH_GR303_TMC = PRI_SWITCH_GR303_TMC, + SANGOMA_PRI_SWITCH_QSIG = PRI_SWITCH_QSIG +} sangoma_pri_switch_t; + +typedef enum { + SANGOMA_PRI_READY = (1 << 0) +} sangoma_pri_flag_t; + +struct sangoma_pri; +typedef int (*event_handler)(struct sangoma_pri *, sangoma_pri_event_t, pri_event *); +typedef int (*loop_handler)(struct sangoma_pri *); +#define MAX_EVENT 18 + +struct sangoma_pri { + struct pri *pri; + int span; + int dchan; + unsigned int flags; + void *private_info; + event_handler eventmap[MAX_EVENT+1]; + loop_handler on_loop; + zap_channel_t *zdchan; +}; + +struct sangoma_pri_event_list { + int event_id; + int pri_event; + char *name; +}; + + + +#define SANGOMA_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func; + +char *sangoma_pri_event_str(sangoma_pri_event_t event_id); +int sangoma_one_loop(struct sangoma_pri *spri); +int sangoma_init_pri(struct sangoma_pri *spri, int span, int dchan, int swtype, int node, int debug); +int sangoma_run_pri(struct sangoma_pri *spri); + +#endif