Index: src/ozmod/ozmod_ss7_boost/sigboost.h =================================================================== --- src/ozmod/ozmod_ss7_boost/sigboost.h (revision 717) +++ src/ozmod/ozmod_ss7_boost/sigboost.h (working copy) @@ -1,5 +1,5 @@ /**************************************************************************** - * sigboost.h $Revision: 1.5 $ + * sigboost.h $Revision: 1.13 $ * * Definitions for the sigboost interface. * @@ -14,6 +14,8 @@ #ifndef _SIGBOOST_H_ #define _SIGBOOST_H_ +#define SIGBOOST_VERSION 100 + #include #include @@ -48,16 +50,24 @@ enum e_sigboost_call_setup_ack_nack_cause_values { - SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* unused Q.850 value */ - SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 118, /* unused Q.850 value */ - SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28, - /* probable elimination */ - //SIGBOOST_CALL_SETUP_RESERVED = 0x00, - //SIGBOOST_CALL_SETUP_CIRCUIT_RESET = 0x10, - //SIGBOOST_CALL_SETUP_NACK_CKT_START_TIMEOUT = 0x11, - //SIGBOOST_CALL_SETUP_NACK_AUTO_CALL_GAP = 0x17, + //SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 34, /* Q.850 value - don't use */ + SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY = 117, /* non Q.850 value indicates local all ckt busy + causing sangoma_mgd to perform automatic call + gapping*/ + SIGBOOST_CALL_SETUP_NACK_TEST_CKT_BUSY = 17, /* Q.850 value */ + SIGBOOST_CALL_SETUP_NACK_INVALID_NUMBER = 28, /* Q.850 value */ + SIGBOOST_CALL_SETUP_CSUPID_DBL_USE = 200, /* unused Q.850 value */ }; + +enum e_sigboost_huntgroup_values +{ + SIGBOOST_HUNTGRP_SEQ_ASC = 0x00, /* sequential with lowest available first */ + SIGBOOST_HUNTGRP_SEQ_DESC = 0x01, /* sequential with highest available first */ + SIGBOOST_HUNTGRP_RR_ASC = 0x02, /* round-robin with lowest available first */ + SIGBOOST_HUNTGRP_RR_DESC = 0x03, /* round-robin with highest available first */ +}; + #define MAX_DIALED_DIGITS 31 /* Next two defines are used to create the range of values for call_setup_id @@ -67,63 +77,73 @@ #define CORE_MAX_CHAN_PER_SPAN 30 #define MAX_PENDING_CALLS CORE_MAX_SPANS * CORE_MAX_CHAN_PER_SPAN /* 0..(MAX_PENDING_CALLS-1) is range of call_setup_id below */ -#define SIZE_RDNIS 128 +#define SIZE_RDNIS 900 + #pragma pack(1) + typedef struct { - uint32_t event_id; + uint8_t capability; + uint8_t uil1p; +}t_sigboost_bearer; + +typedef struct +{ + uint16_t version; + uint32_t event_id; /* delete sequence numbers - SCTP does not need them */ - uint32_t fseqno; - uint32_t bseqno; - uint16_t call_setup_id; - uint32_t trunk_group; - uint8_t span; - uint8_t chan; - struct timeval tv; - uint8_t called_number_digits_count; - char called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */ - uint8_t calling_number_digits_count; /* it's an array */ - char calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */ + uint32_t fseqno; + uint32_t bseqno; + uint16_t call_setup_id; + uint32_t trunk_group; + uint8_t span; + uint8_t chan; + struct timeval tv; + uint8_t called_number_digits_count; + char called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */ + uint8_t calling_number_digits_count; /* it's an array */ + char calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */ /* ref. Q.931 Table 4-11 and Q.951 Section 3 */ - uint8_t calling_number_screening_ind; - uint8_t calling_number_presentation; - char calling_name[MAX_DIALED_DIGITS + 1]; - uint16_t redirection_string_size; - char redirection_string [SIZE_RDNIS]; /* it's a null terminated string */ - /* redir string format: - * http://www.ss7box.com/wiki/tiki-index.php?page=Call+Redirection - * */ + uint8_t calling_number_screening_ind; + uint8_t calling_number_presentation; + char calling_name[MAX_DIALED_DIGITS + 1]; + t_sigboost_bearer bearer; + uint8_t hunt_group; + uint16_t isup_in_rdnis_size; + char isup_in_rdnis [SIZE_RDNIS]; /* it's a null terminated string */ } t_sigboost_callstart; -#define MIN_SIZE_CALLSTART_MSG (sizeof(t_sigboost_callstart) - SIZE_RDNIS) +#define MIN_SIZE_CALLSTART_MSG sizeof(t_sigboost_callstart) - SIZE_RDNIS typedef struct { - uint32_t event_id; + uint16_t version; + uint32_t event_id; /* delete sequence numbers - SCTP does not need them */ - uint32_t fseqno; - uint32_t bseqno; - uint16_t call_setup_id; - uint32_t trunk_group; - uint8_t span; - uint8_t chan; - struct timeval tv; - uint8_t release_cause; + uint32_t fseqno; + uint32_t bseqno; + uint16_t call_setup_id; + uint32_t trunk_group; + uint8_t span; + uint8_t chan; + struct timeval tv; + uint8_t release_cause; } t_sigboost_short; #pragma pack() static inline int boost_full_event(int event_id) { - switch (event_id) { - case SIGBOOST_EVENT_CALL_START: - case SIGBOOST_EVENT_DIGIT_IN: - return 1; - default: - return 0; - } + switch (event_id) { + case SIGBOOST_EVENT_CALL_START: + case SIGBOOST_EVENT_DIGIT_IN: + return 1; + default: + return 0; + } - return 0; + return 0; } + #endif Index: src/ozmod/ozmod_ss7_boost/ss7_boost_client.c =================================================================== --- src/ozmod/ozmod_ss7_boost/ss7_boost_client.c (revision 717) +++ src/ozmod/ozmod_ss7_boost/ss7_boost_client.c (working copy) @@ -73,7 +73,7 @@ { if (event->event_id == SIGBOOST_EVENT_HEARTBEAT) return; - zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "%s EVENT: %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s]\n", + zap_log(file, func, line, ZAP_LOG_LEVEL_WARNING, "%s EVENT: %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s]\n", dir ? "TX":"RX", ss7bc_event_id_name(event->event_id), event->event_id, @@ -91,7 +91,7 @@ { if (event->event_id == SIGBOOST_EVENT_HEARTBEAT) return; - zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "%s EVENT (%s): %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i \n", + zap_log(file, func, line, ZAP_LOG_LEVEL_WARNING, "%s EVENT (%s): %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i \n", dir ? "TX":"RX", priority ? "P":"N", ss7bc_event_id_name(event->event_id), @@ -261,6 +261,10 @@ bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen); + if (mcon->event.version != SIGBOOST_VERSION) { + zap_log(ZAP_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION); + } + /* Must check for < 0 cannot rely on bytes > MIN_SIZE_... compiler issue */ if (bytes < 0) { msg_ok=0; @@ -293,7 +297,7 @@ ss7bc_print_event_short(mcon, (ss7bc_short_event_t*)&mcon->event, 0, 0, file, func, line); } -#if 1 +#if 0 /* NC: NOT USED ANY MORE */ if (mcon->rxseq_reset) { //if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) { @@ -310,15 +314,17 @@ mcon->txwindow = mcon->txseq - mcon->event.bseqno; mcon->rxseq++; +#if 0 if (mcon->rxseq != mcon->event.fseqno) { zap_log(ZAP_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno); return NULL; } +#endif return &mcon->event; } else { if (iteration == 0) { - zap_log(ZAP_LOG_CRIT, "Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event)); + zap_log(ZAP_LOG_CRIT, "NC - Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event)); return NULL; } } @@ -332,6 +338,10 @@ int bytes = 0; bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen); + + if (mcon->event.version != SIGBOOST_VERSION) { + zap_log(ZAP_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION); + } if (bytes == sizeof(ss7bc_short_event_t)) { @@ -356,7 +366,7 @@ int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, const char *file, const char *func, int line) { int err; - int event_size=sizeof(ss7bc_event_t); + int event_size=MIN_SIZE_CALLSTART_MSG+event->isup_in_rdnis_size; if (!event || mcon->socket < 0 || !mcon->mutex) { zap_log(file, func, line, ZAP_LOG_LEVEL_CRIT, "Critical Error: No Event Device\n"); @@ -395,6 +405,7 @@ event->fseqno = mcon->txseq++; } event->bseqno = mcon->rxseq; + event->version = SIGBOOST_VERSION; err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr)); zap_mutex_unlock(mcon->mutex); @@ -432,6 +443,7 @@ gettimeofday(&event->tv, NULL); zap_mutex_lock(mcon->mutex); + event->version = SIGBOOST_VERSION; err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr)); zap_mutex_unlock(mcon->mutex); Index: src/ozmod/ozmod_ss7_boost/ozmod_ss7_boost.c =================================================================== --- src/ozmod/ozmod_ss7_boost/ozmod_ss7_boost.c (revision 717) +++ src/ozmod/ozmod_ss7_boost/ozmod_ss7_boost.c (working copy) @@ -215,7 +215,11 @@ ss7bc_call_init(&event, caller_data->cid_num.digits, caller_data->ani.digits, r); zap_set_string(event.calling_name, caller_data->cid_name); - zap_set_string(event.redirection_string, caller_data->rdnis.digits); + zap_set_string(event.isup_in_rdnis, caller_data->rdnis.digits); + if (strlen(caller_data->rdnis.digits)) { + event.isup_in_rdnis_size = strlen(caller_data->rdnis.digits)+1; + } + event.calling_number_screening_ind = caller_data->screen; event.calling_number_presentation = caller_data->pres; @@ -483,7 +487,7 @@ } zap_set_string(zchan->caller_data.ani.digits, (char *)event->calling_number_digits); zap_set_string(zchan->caller_data.dnis.digits, (char *)event->called_number_digits); - zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->redirection_string); + zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->isup_in_rdnis); zchan->caller_data.screen = event->calling_number_screening_ind; zchan->caller_data.pres = event->calling_number_presentation; zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING); @@ -851,7 +855,7 @@ zap_span_t *span = (zap_span_t *) obj; zap_ss7_boost_data_t *ss7_boost_data = span->signal_data; ss7bc_connection_t *mcon, *pcon; - uint32_t ms = 10, too_long = 20000; + uint32_t ms = 10; //, too_long = 20000; ss7_boost_data->pcon = ss7_boost_data->mcon; @@ -942,6 +946,8 @@ pcon->hb_elapsed = 0; } + +#if 0 if (pcon->hb_elapsed >= too_long) { zap_log(ZAP_LOG_CRIT, "Lost Heartbeat!\n"); zap_set_flag_locked(span, ZAP_SPAN_SUSPENDED); @@ -953,6 +959,7 @@ SIGBOOST_EVENT_SYSTEM_RESTART, 0); } +#endif if (zap_running()) { check_state(span); @@ -1094,7 +1101,7 @@ { zap_ss7_boost_data_t *ss7_boost_data = NULL; const char *local_ip = "127.0.0.65", *remote_ip = "127.0.0.66"; - int local_port = 5300, remote_port = 5300; + int local_port = 53000, remote_port = 53000; char *var, *val; int *intval; Index: src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c =================================================================== --- src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c (revision 717) +++ src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c (working copy) @@ -38,7 +38,7 @@ #include "openzap.h" #include #include -#include "wanpipe_tdm_api_iface.h" +#include "libsangoma.h" typedef enum { WP_RINGING = (1 << 0) @@ -57,196 +57,28 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event); -#define WP_INVALID_SOCKET -1 -/* on windows right now, there is no way to specify if we want to read events here or not, we allways get them here */ -/* we need some what to select if we are reading regular tdm msgs or events */ -/* need to either have 2 functions, 1 for events, 1 for regural read, or a flag on this function to choose */ -/* 2 functions preferred. Need implementation for the event function for both nix and windows that is threadsafe */ -static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen) -{ - /* What do we need to do here to avoid having to do all */ - /* the memcpy's on windows and still maintain api compat with nix */ - uint32_t rx_len=0; -#if defined(__WINDOWS__) - static RX_DATA_STRUCT rx_data; - api_header_t *pri; - wp_tdm_api_rx_hdr_t *tdm_api_rx_hdr; - wp_tdm_api_rx_hdr_t *user_buf = (wp_tdm_api_rx_hdr_t*)hdrbuf; - DWORD ln; +#define WP_INVALID_SOCKET -1 - if (hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){ - return -1; - } - - if (!DeviceIoControl( - fd, - IoctlReadCommand, - (LPVOID)NULL, - 0L, - (LPVOID)&rx_data, - sizeof(RX_DATA_STRUCT), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL - )){ - return -1; - } - - pri = &rx_data.api_header; - tdm_api_rx_hdr = (wp_tdm_api_rx_hdr_t*)rx_data.data; - - user_buf->wp_tdm_api_event_type = pri->operation_status; - - switch(pri->operation_status) - { - case SANG_STATUS_RX_DATA_AVAILABLE: - if (pri->data_length > datalen){ - break; - } - memcpy(databuf, rx_data.data, pri->data_length); - rx_len = pri->data_length; - break; - - default: - break; - } - -#else - struct msghdr msg; - struct iovec iov[2]; - - memset(&msg,0,sizeof(struct msghdr)); - - iov[0].iov_len=hdrlen; - iov[0].iov_base=hdrbuf; - - iov[1].iov_len=datalen; - iov[1].iov_base=databuf; - - msg.msg_iovlen=2; - msg.msg_iov=iov; - - rx_len = read(fd,&msg,datalen+hdrlen); - - if (rx_len <= sizeof(wp_tdm_api_rx_hdr_t)){ - return -EINVAL; - } - - rx_len-=sizeof(wp_tdm_api_rx_hdr_t); -#endif - return rx_len; -} - -static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen) -{ - /* What do we need to do here to avoid having to do all */ - /* the memcpy's on windows and still maintain api compat with nix */ - int bsent = 0; -#if defined(__WINDOWS__) - static TX_DATA_STRUCT local_tx_data; - api_header_t *pri; - DWORD ln; - - /* Are these really not needed or used??? What about for nix?? */ - (void)hdrbuf; - (void)hdrlen; - - pri = &local_tx_data.api_header; - - pri->data_length = datalen; - memcpy(local_tx_data.data, databuf, pri->data_length); - - if (!DeviceIoControl( - fd, - IoctlWriteCommand, - (LPVOID)&local_tx_data, - (ULONG)sizeof(TX_DATA_STRUCT), - (LPVOID)&local_tx_data, - sizeof(TX_DATA_STRUCT), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL - )){ - return -1; - } - - if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) { - bsent = datalen; - } -#else - struct msghdr msg; - struct iovec iov[2]; - - memset(&msg,0,sizeof(struct msghdr)); - - iov[0].iov_len = hdrlen; - iov[0].iov_base = hdrbuf; - - iov[1].iov_len = datalen; - iov[1].iov_base = databuf; - - msg.msg_iovlen = 2; - msg.msg_iov = iov; - - bsent = write(fd, &msg, datalen + hdrlen); - if (bsent > 0){ - bsent -= sizeof(wp_tdm_api_tx_hdr_t); - } -#endif - return bsent; -} - /* a cross platform way to poll on an actual pollset (span and/or list of spans) will probably also be needed for analog */ /* so we can have one analong handler thread that will deal with all the idle analog channels for events */ /* the alternative would be for the driver to provide one socket for all of the oob events for all analog channels */ static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags) { -#if defined(__WINDOWS__) - DWORD ln; - API_POLL_STRUCT api_poll; - - memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT)); - api_poll.user_flags_bitmap = *flags; - api_poll.timeout = timeout; +#ifdef LIBSANGOMA_VERSION + int err; + sangoma_wait_obj_t sangoma_wait_obj; - if (!DeviceIoControl( - fd, - IoctlApiPoll, - (LPVOID)NULL, - 0L, - (LPVOID)&api_poll, - sizeof(API_POLL_STRUCT), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL)) { - return -1; - } + sangoma_init_wait_obj(&sangoma_wait_obj, fd, 1, 1, *flags, SANGOMA_WAIT_OBJ); - *flags = 0; - - switch(api_poll.operation_status) - { - case SANG_STATUS_RX_DATA_AVAILABLE: - break; - - case SANG_STATUS_RX_DATA_TIMEOUT: - return 0; - - default: - return -1; - } - - if (api_poll.poll_events_bitmap == 0){ - return -1; + err=sangoma_socket_waitfor_many(&sangoma_wait_obj,1 , timeout); + if (err > 0) { + *flags=sangoma_wait_obj.flags_out; } + return err; - if (api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT) { - return 0; - } - - *flags = api_poll.poll_events_bitmap; - - return 1; #else - struct pollfd pfds[1]; + struct pollfd pfds[1]; int res; memset(&pfds[0], 0, sizeof(pfds[0])); @@ -265,87 +97,18 @@ return res; #endif + } -#define FNAME_LEN 128 static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan) { - char fname[FNAME_LEN]; - sng_fd_t fd = WP_INVALID_SOCKET; -#if defined(__WINDOWS__) - DWORD ln; - wan_udp_hdr_t wan_udp; - - /* NOTE: under Windows Interfaces are zero based but 'chan' is 1 based. */ - /* Subtract 1 from 'chan'. */ - _snprintf(fname , FNAME_LEN, "\\\\.\\WANPIPE%d_IF%d", span, chan - 1); - - fd = CreateFile( fname, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - (LPSECURITY_ATTRIBUTES)NULL, - OPEN_EXISTING, - FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, - (HANDLE)NULL - ); - - /* make sure that we are the only ones who have this chan open */ - /* is this a threadsafe way to make sure that we are ok and will */ - /* never return a valid handle to more than one thread for the same channel? */ - - wan_udp.wan_udphdr_command = GET_OPEN_HANDLES_COUNTER; - wan_udp.wan_udphdr_data_len = 0; - - DeviceIoControl( - fd, - IoctlManagementCommand, - (LPVOID)&wan_udp, - sizeof(wan_udp_hdr_t), - (LPVOID)&wan_udp, - sizeof(wan_udp_hdr_t), - (LPDWORD)(&ln), - (LPOVERLAPPED)NULL - ); - - if ((wan_udp.wan_udphdr_return_code) || (*(int*)&wan_udp.wan_udphdr_data[0] != 1)){ - /* somone already has this channel, or somthing else is not right. */ - tdmv_api_close_socket(&fd); - } - -#else - /* Does this fail if another thread already has this chan open? */ - /* if not, we need to add some code to make sure it does */ - snprintf(fname, FNAME_LEN, "/dev/wptdm_s%dc%d",span,chan); - - fd = open(fname, O_RDWR); - - if (fd < 0) { - fd = WP_INVALID_SOCKET; - } - -#endif - return fd; + return sangoma_open_tdmapi_span_chan(span, chan); } static zap_io_interface_t wanpipe_interface; -static zap_status_t wp_tdm_cmd_exec(zap_channel_t *zchan, wanpipe_tdm_api_t *tdm_api) -{ - int err; - - /* I'm told the 2nd arg is ignored but i send it as the cmd anyway for good measure */ - err = ioctl(zchan->sockfd, tdm_api->wp_tdm_cmd.cmd, &tdm_api->wp_tdm_cmd); - - if (err) { - snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno)); - return ZAP_FAIL; - } - - return ZAP_SUCCESS; -} - static unsigned char wanpipe_swap_bits(unsigned char cas_bits) { unsigned char swapped_bits = 0x0; @@ -379,43 +142,17 @@ if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) { wanpipe_tdm_api_t tdm_api; + memset(&tdm_api,0,sizeof(tdm_api)); 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); chan->physical_span_id = spanno; chan->physical_chan_id = x; chan->rate = 8000; - if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) { - - -#if 1 - if (type == ZAP_CHAN_TYPE_FXO) { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - wp_tdm_cmd_exec(chan, &tdm_api); - } -#endif - - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_DETECT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - wp_tdm_cmd_exec(chan, &tdm_api); -#if 1 - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_TRIP_DETECT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - wp_tdm_cmd_exec(chan, &tdm_api); -#endif - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RXHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - wp_tdm_cmd_exec(chan, &tdm_api); - - } - if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING; - wp_tdm_cmd_exec(chan, &tdm_api); + int err; + + /* FIXME: Handle Error Conditino Check for return code */ + err= sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api); if (tdm_api.wp_tdm_cmd.hw_tdm_coding) { chan->native_codec = chan->effective_codec = ZAP_CODEC_ALAW; } else { @@ -423,10 +160,24 @@ } } +#if 0 + if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) { + /* Enable FLASH/Wink Events */ + int err=sangoma_set_rm_rxflashtime(chan->sockfd, &tdm_api, wp_globals.flash_ms); + if (err == 0) { + zap_log(ZAP_LOG_ERROR, "flash enabled s%dc%d\n", spanno, x); + } else { + zap_log(ZAP_LOG_ERROR, "flash disabled s%dc%d\n", spanno, x); + } + } +#endif + 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); +#ifdef LIBSANGOMA_VERSION + sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id,wanpipe_swap_bits(cas_bits)); +#else + sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,wanpipe_swap_bits(cas_bits)); +#endif } if (!zap_strlen_zero(name)) { @@ -550,18 +301,31 @@ static ZIO_OPEN_FUNCTION(wanpipe_open) { + int err; wanpipe_tdm_api_t tdm_api; + memset(&tdm_api,0,sizeof(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 { zchan->effective_codec = zchan->native_codec; - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_CODEC; - tdm_api.wp_tdm_cmd.tdm_codec = 0; - 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); + + sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, wp_globals.codec_ms); + + err=sangoma_tdm_get_hw_dtmf(zchan->sockfd, &tdm_api); + if (err > 0) { + err=sangoma_tdm_enable_dtmf_events(zchan->sockfd, &tdm_api); + if (err == 0) { + //zap_log(ZAP_LOG_DEBUG, "Enabling HW DTMF FEATURE\n"); + zap_channel_set_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF_DETECT); + } else { + //zap_log(ZAP_LOG_DEBUG, "NO HW DTMF FEATURE\n"); + } + } else { + //zap_log(ZAP_LOG_DEBUG, "NO HW DTMF FEATURE\n"); + } + zap_channel_set_feature(zchan, ZAP_CHANNEL_FEATURE_INTERVAL); zchan->effective_interval = zchan->native_interval = wp_globals.codec_ms; zchan->packet_len = zchan->native_interval * 8; @@ -585,10 +349,8 @@ switch(command) { case ZAP_COMMAND_OFFHOOK: { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api); + if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed"); return ZAP_FAIL; } @@ -597,10 +359,8 @@ break; case ZAP_COMMAND_ONHOOK: { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api); + if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed"); return ZAP_FAIL; } @@ -609,9 +369,8 @@ break; case ZAP_COMMAND_GENERATE_RING_ON: { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_START; - if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api); + if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed"); return ZAP_FAIL; } @@ -622,9 +381,8 @@ break; case ZAP_COMMAND_GENERATE_RING_OFF: { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK; - if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api); + if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed"); return ZAP_FAIL; } @@ -634,27 +392,26 @@ break; case ZAP_COMMAND_GET_INTERVAL: { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_USR_PERIOD; - - if (!(err = wp_tdm_cmd_exec(zchan, &tdm_api))) { - ZAP_COMMAND_OBJ_INT = tdm_api.wp_tdm_cmd.usr_period; + err=sangoma_tdm_get_usr_period(zchan->sockfd, &tdm_api); + if (err > 0 ) { + ZAP_COMMAND_OBJ_INT = err; + err=0; } - } break; case ZAP_COMMAND_SET_INTERVAL: { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_USR_PERIOD; - tdm_api.wp_tdm_cmd.usr_period = ZAP_COMMAND_OBJ_INT; - err = wp_tdm_cmd_exec(zchan, &tdm_api); + err=sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, ZAP_COMMAND_OBJ_INT); 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); +#ifdef LIBSANGOMA_VERSION + err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,zchan->physical_chan_id,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT)); +#else + err=sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api,wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT)); +#endif } break; case ZAP_COMMAND_GET_CAS_BITS: @@ -683,7 +440,7 @@ memset(&hdrframe, 0, sizeof(hdrframe)); - rx_len = tdmv_api_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen); + rx_len = sangoma_readmsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen,0); *datalen = rx_len; @@ -702,7 +459,7 @@ /* Do we even need the headerframe here? on windows, we don't even pass it to the driver */ memset(&hdrframe, 0, sizeof(hdrframe)); - bsent = tdmv_api_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen)); + bsent = sangoma_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen),0); /* should we be checking if bsent == *datalen here? */ if (bsent > 0) { @@ -759,19 +516,29 @@ return ZAP_SUCCESS; } -#ifndef WIN32 ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event) { +#ifdef LIBSANGOMA_VERSION + sangoma_wait_obj_t pfds[ZAP_MAX_CHANNELS_SPAN]; +#else struct pollfd pfds[ZAP_MAX_CHANNELS_SPAN]; +#endif + uint32_t i, j = 0, k = 0, l = 0; + int objects=0; int r; for(i = 1; i <= span->chan_count; i++) { zap_channel_t *zchan = span->channels[i]; + +#ifdef LIBSANGOMA_VERSION + sangoma_init_wait_obj(&pfds[j], zchan->sockfd , 1, 1, POLLPRI, SANGOMA_WAIT_OBJ); +#else memset(&pfds[j], 0, sizeof(pfds[j])); pfds[j].fd = span->channels[i]->sockfd; pfds[j].events = POLLPRI; - +#endif + objects++; /* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */ if (zap_test_flag(zchan, ZAP_CHANNEL_WINK) || zap_test_flag(zchan, ZAP_CHANNEL_FLASH)) { @@ -789,20 +556,16 @@ int err; memset(&tdm_api, 0, sizeof(tdm_api)); if (zap_test_pflag(zchan, WP_RINGING)) { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_DISABLE; - if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api); + if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed"); return ZAP_FAIL; } zap_clear_pflag_locked(zchan, WP_RINGING); zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_off_ms; } else { - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_START; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api); + if (err) { snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed"); return ZAP_FAIL; } @@ -815,9 +578,12 @@ if (l) { ms = l; } +#ifdef LIBSANGOMA_VERSION + r = sangoma_socket_waitfor_many(pfds,objects,ms); +#else + r = poll(pfds, j, ms); +#endif - r = poll(pfds, j, ms); - if (r == 0) { return l ? ZAP_SUCCESS : ZAP_TIMEOUT; } else if (r < 0) { @@ -828,7 +594,11 @@ for(i = 1; i <= span->chan_count; i++) { zap_channel_t *zchan = span->channels[i]; +#ifdef LIBSANGOMA_VERSION + if (pfds[i-1].flags_out & POLLPRI) { +#else if (pfds[i-1].revents & POLLPRI) { +#endif zap_set_flag(zchan, ZAP_CHANNEL_EVENT); zchan->last_event_time = zap_current_time_in_ms(); k++; @@ -836,15 +606,43 @@ } - return k ? ZAP_SUCCESS : ZAP_FAIL; } + +static ZIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) +{ + wanpipe_tdm_api_t tdm_api; + unsigned int alarms = 0; + int err; + + memset(&tdm_api,0,sizeof(tdm_api)); + +#ifdef LIBSANGOMA_VERSION + if ((err = sangoma_tdm_get_fe_alarms(zchan->sockfd, &tdm_api, &alarms))) { + 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; + } +#else + if ((err = sangoma_tdm_get_fe_alarms(zchan->sockfd, &tdm_api)) < 0){ + 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; + } + alarms = tdm_api.wp_tdm_cmd.fe_alarms; #endif + + zchan->alarm_flags = alarms ? ZAP_ALARM_RED : ZAP_ALARM_NONE; + + return ZAP_SUCCESS; +} + + ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) { - uint32_t i; + uint32_t i,err; zap_oob_event_t event_id; for(i = 1; i <= span->chan_count; i++) { @@ -869,29 +667,43 @@ event_id = ZAP_OOB_ONHOOK; if (span->channels[i]->type == ZAP_CHAN_TYPE_FXO) { + zap_channel_t *zchan = span->channels[i]; wanpipe_tdm_api_t tdm_api; memset(&tdm_api, 0, sizeof(tdm_api)); - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - wp_tdm_cmd_exec(span->channels[i], &tdm_api); + + sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api); } goto event; } } - } + } if (zap_test_flag(span->channels[i], ZAP_CHANNEL_EVENT)) { wanpipe_tdm_api_t tdm_api; + zap_channel_t *zchan = span->channels[i]; memset(&tdm_api, 0, sizeof(tdm_api)); zap_clear_flag(span->channels[i], ZAP_CHANNEL_EVENT); - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_READ_EVENT; - if (wp_tdm_cmd_exec(span->channels[i], &tdm_api) != ZAP_SUCCESS) { + err=sangoma_tdm_read_event(zchan->sockfd,&tdm_api); + if (err != ZAP_SUCCESS) { snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno)); return ZAP_FAIL; } switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { + + case WP_TDMAPI_EVENT_LINK_STATUS: + { + switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { + case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: + event_id = ZAP_OOB_ALARM_CLEAR; + break; + default: + event_id = ZAP_OOB_ALARM_TRAP; + break; + }; + } + break; + case WP_TDMAPI_EVENT_RXHOOK: { if (span->channels[i]->type == ZAP_CHAN_TYPE_FXS) { @@ -918,11 +730,9 @@ continue; } else { int err; - - tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; - if ((err = wp_tdm_cmd_exec(span->channels[i], &tdm_api))) { + zap_channel_t *zchan = span->channels[i]; + err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api); + if (err) { snprintf(span->channels[i]->last_error, sizeof(span->channels[i]->last_error), "ONHOOK Failed"); return ZAP_FAIL; } @@ -948,6 +758,17 @@ span->channels[i]->cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); } break; + case WP_TDMAPI_EVENT_DTMF: + { + char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; + event_id = ZAP_OOB_NOOP; + + //zap_log(ZAP_LOG_DEBUG, "%d:%d queue hardware dtmf %s\n", zchan->span_id, zchan->chan_id, tmp_dtmf); + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { + zap_channel_queue_dtmf(zchan, tmp_dtmf); + } + } + break; default: { zap_log(ZAP_LOG_WARNING, "Unhandled event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); @@ -1005,6 +826,7 @@ #endif wanpipe_interface.next_event = wanpipe_next_event; wanpipe_interface.channel_destroy = wanpipe_channel_destroy; + wanpipe_interface.get_alarms = wanpipe_get_alarms; *zio = &wanpipe_interface; return ZAP_SUCCESS; Index: configure.ac =================================================================== --- configure.ac (revision 717) +++ configure.ac (working copy) @@ -155,6 +155,9 @@ [AS_HELP_STRING([--with-libpri], [Install ozmod_libpri])], [enable_libpri="yes"], [enable_libpri="no"]) AC_SUBST(enable_libpri) +AC_CHECK_LIB([sangoma], [sangoma_span_chan_toif], [have_libsangoma="yes"]) +AM_CONDITIONAL([LIBSANGOMA],[test "${have_libsangoma}" = "yes"]) + AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"]) COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS" Index: Makefile.am =================================================================== --- Makefile.am (revision 717) +++ Makefile.am (working copy) @@ -154,10 +154,12 @@ ozmod_skel_la_LDFLAGS = -module -avoid-version ozmod_skel_la_LIBADD = $(MYLIB) +if LIBSANGOMA ozmod_wanpipe_la_SOURCES = $(SRC)/ozmod/ozmod_wanpipe/ozmod_wanpipe.c -ozmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ozmod_wanpipe_la_LDFLAGS = -module -avoid-version +ozmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe +ozmod_wanpipe_la_LDFLAGS = -module -avoid-version -lsangoma ozmod_wanpipe_la_LIBADD = $(MYLIB) +endif ozmod_isdn_la_SOURCES = \ $(SRC)/isdn/EuroISDNStateNT.c \