/**
 * \brief Destroys a Wanpipe Channel
 * \param ftdmchan Channel to destroy
 * \return Success
 */
static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
{
#ifdef LIBSANGOMA_VERSION
	if (ftdmchan->mod_data) {
		sangoma_wait_obj_t *sangoma_wait_obj;
		sangoma_wait_obj = ftdmchan->mod_data;
		ftdmchan->mod_data = NULL;
		sangoma_wait_obj_delete(&sangoma_wait_obj);
	}
#endif

	if (ftdmchan->sockfd != FTDM_INVALID_SOCKET) {
		/* enable HW DTMF. As odd as it seems. Why enable when the channel is being destroyed and won't be used anymore?
		 * because that way we can transfer the DTMF state back to the driver, if we're being restarted we will set again
		 * the FEATURE_DTMF flag and use HW DTMF, if we don't enable here, then on module restart we won't see
		 * HW DTMF available and will use software */
		if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
			wanpipe_tdm_api_t tdm_api;
			int err;
			memset(&tdm_api, 0, sizeof(tdm_api));
			err = sangoma_tdm_enable_dtmf_events(ftdmchan->sockfd, &tdm_api);
			if (err) {
				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed enabling Sangoma HW DTMF failed on channel destroy\n");
			}
		}
		sangoma_close(&ftdmchan->sockfd);
	}

	return FTDM_SUCCESS;
}
/**
 * \brief Executes an FreeTDM command on a Wanpipe channel
 * \param ftdmchan Channel to execute command on
 * \param command FreeTDM command to execute
 * \param obj Object (unused)
 * \return Success or failure
 */
static FIO_COMMAND_FUNCTION(wanpipe_command)
{
	wanpipe_tdm_api_t tdm_api;
	int err = 0;

	memset(&tdm_api, 0, sizeof(tdm_api));

	switch(command) {
	case FTDM_COMMAND_OFFHOOK:
		{
			err=sangoma_tdm_txsig_offhook(ftdmchan->sockfd,&tdm_api);
			if (err) {
				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "OFFHOOK Failed");
				return FTDM_FAIL;
			}
			ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
		}
		break;
	case FTDM_COMMAND_ONHOOK:
		{
			err=sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api);
			if (err) {
				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed");
				return FTDM_FAIL;
			}
			ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
		}
		break;
	case FTDM_COMMAND_GENERATE_RING_ON:
		{
			err=sangoma_tdm_txsig_start(ftdmchan->sockfd,&tdm_api);
			if (err) {
				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring Failed");
				return FTDM_FAIL;
			}
			ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
			ftdm_set_pflag_locked(ftdmchan, WP_RINGING);
			ftdmchan->ring_time = ftdm_current_time_in_ms() + wp_globals.ring_on_ms;
		}
		break;
	case FTDM_COMMAND_GENERATE_RING_OFF:
		{
			err=sangoma_tdm_txsig_offhook(ftdmchan->sockfd,&tdm_api);
			if (err) {
				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Ring-off Failed");
				return FTDM_FAIL;
			}
			ftdm_clear_pflag_locked(ftdmchan, WP_RINGING);
			ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_RINGING);
		}
		break;
	case FTDM_COMMAND_GET_INTERVAL:
		{
			err=sangoma_tdm_get_usr_period(ftdmchan->sockfd, &tdm_api);
			if (err > 0 ) {
				FTDM_COMMAND_OBJ_INT = err;
				err=0;
			}
		}
		break;
	case FTDM_COMMAND_ENABLE_ECHOCANCEL:
		{
			err=sangoma_tdm_enable_hwec(ftdmchan->sockfd, &tdm_api);
			if (err) {
             			snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Enable Failed");
				return FTDM_FAIL;
			}
		}
		break;
	case FTDM_COMMAND_DISABLE_ECHOCANCEL:
		{
			err=sangoma_tdm_disable_hwec(ftdmchan->sockfd, &tdm_api);
			if (err) {
             			snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HWEC Disable Failed");
				return FTDM_FAIL;
			}
		}
		break;
	case FTDM_COMMAND_ENABLE_DTMF_DETECT:
		{
#ifdef WP_API_FEATURE_DTMF_EVENTS
			err = sangoma_tdm_enable_dtmf_events(ftdmchan->sockfd, &tdm_api);
			if (err) {
				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Enabling of Sangoma HW DTMF failed\n");
             			snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HW DTMF Enable Failed");
				return FTDM_FAIL;
			}
			ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled DTMF events\n");
#else
			return FTDM_NOTIMPL;
#endif
		}
		break;
	case FTDM_COMMAND_DISABLE_DTMF_DETECT:
		{
#ifdef WP_API_FEATURE_DTMF_EVENTS
			err = sangoma_tdm_disable_dtmf_events(ftdmchan->sockfd, &tdm_api);
			if (err) {
				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Disabling of Sangoma HW DTMF failed\n");
             			snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "HW DTMF Disable Failed");
				return FTDM_FAIL;
			}
			ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled DTMF events\n");
#else
			return FTDM_NOTIMPL;
#endif
		}
		break;
	case FTDM_COMMAND_ENABLE_LOOP:
		{
#ifdef WP_API_FEATURE_LOOP
         	err=sangoma_tdm_enable_loop(ftdmchan->sockfd, &tdm_api);
			if (err) {
				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Loop Enable Failed");
				return FTDM_FAIL;
			}
#endif		
		}
		break;
	case FTDM_COMMAND_DISABLE_LOOP:
		{
#ifdef WP_API_FEATURE_LOOP
         	err=sangoma_tdm_disable_loop(ftdmchan->sockfd, &tdm_api);
			if (err) {
				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Loop Disable Failed");
				return FTDM_FAIL;
			}
#endif	 
		}
		break;
	case FTDM_COMMAND_SET_INTERVAL: 
		{
			err=sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, FTDM_COMMAND_OBJ_INT);
			ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
		}
		break;
	case FTDM_COMMAND_SET_CAS_BITS:
		{
#ifdef LIBSANGOMA_VERSION
			err = sangoma_tdm_write_rbs(ftdmchan->sockfd,&tdm_api, ftdmchan->physical_chan_id, wanpipe_swap_bits(FTDM_COMMAND_OBJ_INT));
#else
			err = sangoma_tdm_write_rbs(ftdmchan->sockfd, &tdm_api, wanpipe_swap_bits(FTDM_COMMAND_OBJ_INT));
#endif
		}
		break;
	case FTDM_COMMAND_GET_CAS_BITS:
		{
#ifdef LIBSANGOMA_VERSION
			unsigned char rbsbits;
			err = sangoma_tdm_read_rbs(ftdmchan->sockfd, &tdm_api, ftdmchan->physical_chan_id, &rbsbits);
			if (!err) {
				FTDM_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits);
			}
#else
			// does sangoma_tdm_read_rbs is available here?
			FTDM_COMMAND_OBJ_INT = ftdmchan->rx_cas_bits;
#endif
		}
		break;
	case FTDM_COMMAND_SET_LINK_STATUS:
		{
			ftdm_channel_hw_link_status_t status = FTDM_COMMAND_OBJ_INT;
			char sangoma_status = status == FTDM_HW_LINK_CONNECTED ? FE_CONNECTED : FE_DISCONNECTED;
			err = sangoma_tdm_set_fe_status(ftdmchan->sockfd, &tdm_api, sangoma_status);
		}
		break;
	case FTDM_COMMAND_GET_LINK_STATUS:
		{
			unsigned char sangoma_status = 0;
			err = sangoma_tdm_get_fe_status(ftdmchan->sockfd, &tdm_api, &sangoma_status);
			if (!err) {
				FTDM_COMMAND_OBJ_INT = sangoma_status == FE_CONNECTED ? FTDM_HW_LINK_CONNECTED : FTDM_HW_LINK_DISCONNECTED;
			}
		}
		break;
	default:
		break;
	};

	if (err) {
		snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
		return FTDM_FAIL;
	}


	return FTDM_SUCCESS;
}
Exemple #3
0
/**
 * \brief Executes an Openzap command on a Wanpipe channel
 * \param zchan Channel to execute command on
 * \param command Openzap command to execute
 * \param obj Object (unused)
 * \return Success or failure
 */
static ZIO_COMMAND_FUNCTION(wanpipe_command)
{
    wanpipe_tdm_api_t tdm_api;
    int err = 0;

    memset(&tdm_api, 0, sizeof(tdm_api));

    switch(command) {
    case ZAP_COMMAND_OFFHOOK:
    {
        err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed");
            return ZAP_FAIL;
        }
        zap_set_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
    }
    break;
    case ZAP_COMMAND_ONHOOK:
    {
        err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed");
            return ZAP_FAIL;
        }
        zap_clear_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
    }
    break;
    case ZAP_COMMAND_GENERATE_RING_ON:
    {
        err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
            return ZAP_FAIL;
        }
        zap_set_flag_locked(zchan, ZAP_CHANNEL_RINGING);
        zap_set_pflag_locked(zchan, WP_RINGING);
        zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_on_ms;
    }
    break;
    case ZAP_COMMAND_GENERATE_RING_OFF:
    {
        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);
        zap_clear_flag_locked(zchan, ZAP_CHANNEL_RINGING);
    }
    break;
    case ZAP_COMMAND_GET_INTERVAL:
    {
        err=sangoma_tdm_get_usr_period(zchan->sockfd, &tdm_api);
        if (err > 0 ) {
            ZAP_COMMAND_OBJ_INT = err;
            err=0;
        }
    }
    break;
    case ZAP_COMMAND_ENABLE_ECHOCANCEL:
    {
        err=sangoma_tdm_enable_hwec(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Enable Failed");
            return ZAP_FAIL;
        }
    }
    break;
    case ZAP_COMMAND_DISABLE_ECHOCANCEL:
    {
        err=sangoma_tdm_disable_hwec(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Disable Failed");
            return ZAP_FAIL;
        }
    }
    break;
    case ZAP_COMMAND_ENABLE_DTMF_DETECT:
    {
#ifdef WP_API_FEATURE_DTMF_EVENTS
        err = sangoma_tdm_enable_dtmf_events(zchan->sockfd, &tdm_api);
        if (err) {
            zap_log(ZAP_LOG_WARNING, "Enabling of Sangoma HW DTMF failed\n");
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HW DTMF Enable Failed");
            return ZAP_FAIL;
        }
        zap_log(ZAP_LOG_DEBUG, "Enabled DTMF events on chan %d:%d\n", zchan->span_id, zchan->chan_id);
#else
        return ZAP_NOTIMPL;
#endif
    }
    break;
    case ZAP_COMMAND_DISABLE_DTMF_DETECT:
    {
#ifdef WP_API_FEATURE_DTMF_EVENTS
        err = sangoma_tdm_disable_dtmf_events(zchan->sockfd, &tdm_api);
        if (err) {
            zap_log(ZAP_LOG_WARNING, "Disabling of Sangoma HW DTMF failed\n");
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HW DTMF Disable Failed");
            return ZAP_FAIL;
        }
        zap_log(ZAP_LOG_DEBUG, "Disabled DTMF events on chan %d:%d\n", zchan->span_id, zchan->chan_id);
#else
        return ZAP_NOTIMPL;
#endif
    }
    break;
    case ZAP_COMMAND_ENABLE_LOOP:
    {
#ifdef WP_API_FEATURE_LOOP
        err=sangoma_tdm_enable_loop(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Loop Enable Failed");
            return ZAP_FAIL;
        }
#endif
    }
    break;
    case ZAP_COMMAND_DISABLE_LOOP:
    {
#ifdef WP_API_FEATURE_LOOP
        err=sangoma_tdm_disable_loop(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Loop Disable Failed");
            return ZAP_FAIL;
        }
#endif
    }
    break;
    case ZAP_COMMAND_SET_INTERVAL:
    {
        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:
    {
#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:
    {
#ifdef LIBSANGOMA_VERSION
        unsigned char rbsbits;
        err = sangoma_tdm_read_rbs(zchan->sockfd, &tdm_api, zchan->physical_chan_id, &rbsbits);
        if (!err) {
            ZAP_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits);
        }
#else
        // does sangoma_tdm_read_rbs is available here?
        ZAP_COMMAND_OBJ_INT = zchan->rx_cas_bits;
#endif
    }
    break;
    default:
        break;
    };

    if (err) {
        snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
        return ZAP_FAIL;
    }


    return ZAP_SUCCESS;
}
Exemple #4
0
/**
 * \brief Initialises a range of wanpipe channels
 * \param span Openzap span
 * \param spanno Wanpipe span number
 * \param start Initial wanpipe channel number
 * \param end Final wanpipe channel number
 * \param type Openzap channel type
 * \param name Openzap span name
 * \param number Openzap span number
 * \param cas_bits CAS bits
 * \return number of spans configured
 */
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;
#ifdef LIBSANGOMA_VERSION
    sangoma_status_t sangstatus;
    sangoma_wait_obj_t *sangoma_wait_obj;
#endif

    if (type == ZAP_CHAN_TYPE_CAS) {
        zap_log(ZAP_LOG_DEBUG, "Configuring Wanpipe CAS channels with abcd == 0x%X\n", cas_bits);
    }
    for(x = start; x < end; x++) {
        zap_channel_t *chan;
        zap_socket_t sockfd = ZAP_INVALID_SOCKET;
        const char *dtmf = "none";
        if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == ZAP_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
            sockfd = __tdmv_api_open_span_chan(spanno, x);
#else
            zap_log(ZAP_LOG_ERROR, "span %d channel %d cannot be configured as smg_prid_nfas, you need to compile openzap with newer libsangoma\n", spanno, x);
#endif
        } else {
            sockfd = tdmv_api_open_span_chan(spanno, x);
        }

        if (sockfd == ZAP_INVALID_SOCKET) {
            zap_log(ZAP_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
            continue;
        }

        if (zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
            wanpipe_tdm_api_t tdm_api;
            memset(&tdm_api, 0, sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
            sangstatus = sangoma_wait_obj_create(&sangoma_wait_obj, sockfd, SANGOMA_DEVICE_WAIT_OBJ);
            if (sangstatus != SANG_STATUS_SUCCESS) {
                zap_log(ZAP_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
                continue;
            }
            chan->mod_data = sangoma_wait_obj;
#endif

            chan->physical_span_id = spanno;
            chan->physical_chan_id = x;
            chan->rate = 8000;

            if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) {
                int err;

                dtmf = "software";

                /* FIXME: Handle Error Condition 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 {
                    chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW;
                }

                err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api);
                if (err > 0) {
                    err = sangoma_tdm_enable_dtmf_events(chan->sockfd, &tdm_api);
                    if (err == 0) {
                        zap_channel_set_feature(chan, ZAP_CHANNEL_FEATURE_DTMF_DETECT);
                        dtmf = "hardware";
                    }
                }
            }

#ifdef LIBSANGOMA_VERSION
            if (type == ZAP_CHAN_TYPE_FXS) {
                if (sangoma_tdm_disable_ring_trip_detect_events(chan->sockfd, &tdm_api)) {
                    /* we had problems of on-hook/off-hook detection due to how ring trip events were handled
                     * if this fails, I believe we will still work ok as long as we dont handle them incorrectly */
                    zap_log(ZAP_LOG_WARNING, "Failed to disable ring trip events in channel s%dc%d\n", spanno, x);
                }
            }
#endif
#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 || type == ZAP_CHAN_TYPE_EM) {
#ifdef LIBSANGOMA_VERSION
                sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id, wanpipe_swap_bits(cas_bits));

                /* this should probably be done for old libsangoma but I am not sure if the API is available and I'm lazy to check,
                   The poll rate is hard coded to 100 per second (done in the driver, is the max rate of polling allowed by wanpipe)
                 */
                if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) {
                    zap_log(ZAP_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
                    continue;
                }
                /* probably done by the driver but lets write defensive code this time */
                sangoma_flush_bufs(chan->sockfd, &tdm_api);
#else
                /*
                 * With wanpipe 3.4.4.2 I get failure even though the events are enabled, /var/log/messages said:
                 * wanpipe4: WARNING: Event type 9 is already pending!
                 * wanpipe4: Failed to add new fe event 09 ch_map=FFFFFFFF!
                 * may be we should not send an error until that is fixed in the driver
                 */
                if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) {
                    zap_log(ZAP_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
                }
                /* probably done by the driver but lets write defensive code this time */
                sangoma_tdm_flush_bufs(chan->sockfd, &tdm_api);
                sangoma_tdm_write_rbs(chan->sockfd,&tdm_api, wanpipe_swap_bits(cas_bits));
#endif
            }

            if (!zap_strlen_zero(name)) {
                zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name));
            }

            if (!zap_strlen_zero(number)) {
                zap_copy_string(chan->chan_number, number, sizeof(chan->chan_number));
            }
            configured++;
            zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d DTMF: %s\n",
                    spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf);

        } else {
            zap_log(ZAP_LOG_ERROR, "zap_span_add_channel failed for wanpipe span %d channel %d\n", spanno, x);
        }
    }

    return configured;
}