Ejemplo n.º 1
0
/**
 * \brief Opens Wanpipe channel
 * \param ftdmchan Channel to open
 * \return Success or failure
 */
static FIO_OPEN_FUNCTION(wanpipe_open) 
{

	wanpipe_tdm_api_t tdm_api;

	memset(&tdm_api,0,sizeof(tdm_api));
	sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api);
#ifdef LIBSANGOMA_VERSION
	sangoma_flush_event_bufs(ftdmchan->sockfd, &tdm_api);
#endif

	if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) {
		ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE;
	} else {
		ftdmchan->effective_codec = ftdmchan->native_codec;
		
		sangoma_tdm_set_usr_period(ftdmchan->sockfd, &tdm_api, wp_globals.codec_ms);

		ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL);
		ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms;
		ftdmchan->packet_len = ftdmchan->native_interval * 8;
	}

	return FTDM_SUCCESS;
}
Ejemplo n.º 2
0
/**
 * \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;
}
Ejemplo n.º 3
0
static void *bridge_channel_media(void *channel_data)
{
    unsigned char readframe[MEDIA_BUFFER_SIZE];
    unsigned char writeframe[MEDIA_BUFFER_SIZE];
    char trace_file_name[255];
    char *trace_prefix = NULL;
    wanpipe_tdm_api_t tdm_api;
    sbridge_chan_t *chan = channel_data;
    sangoma_pri_t *spri = &chan->span->spri;
    int32_t channo = chan->channo;

    memset(readframe, 0, sizeof(readframe));
    memset(writeframe, 0, sizeof(writeframe));

    /* need to disable cancellation while registering the cleanup handler
     * if we get cancelled before registering, no harm done
     * once the cleanup handler gets registered, it does not matter
     * at which point of this thread we get cancelled, the cleanup routine
     * will take care of closing sockets or any other resource we eventually allocate
     * */
    if (!sbridge_thread_setcancelstate(SBRIDGE_THREAD_CANCEL_DISABLE, NULL)) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to disable thread cancellation in chanel %d\n", channo);
        sbridge_thread_exit(NULL);
    }
    if (!sbridge_thread_setcanceltype(SBRIDGE_THREAD_CANCEL_DEFERRED, NULL)) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to set deferred cancel type in chanel %d\n", channo);
        sbridge_thread_exit(NULL);
    }

    /* just grab the lock to start once the thread that launched us is done using the channel
     * channel manipulations in this routine do not require the channel lock because the signaling
     * thread does not access the channel once the media thread is launched
     * */
    sbridge_mutex_lock(&chan->lock);
    chan->running = SBRIDGE_TRUE;
    sbridge_mutex_unlock(&chan->lock);

    /* register the cleanup handler */
    sbridge_thread_cleanup_push(clean_thread_data, chan);

    /* restore the cancellation state */
    sbridge_thread_setcancelstate(SBRIDGE_THREAD_CANCEL_ENABLE, NULL);

    /* open sangoma media channel */
    if ((chan->sangoma_sock = sangoma_open_tdmapi_span_chan(spri->span, channo)) < 0) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to open TDM API descriptor for sangoma channel %d\n", channo);
        sbridge_thread_exit(NULL);
    }

    if (!get_tcp_sock(chan)) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to get TCP socket for channel %d\n", channo);
        sbridge_thread_exit(NULL);
    }

    /* open the traces */
    trace_prefix = chan->span->config->trace_prefix;
    if (strlen(trace_prefix)) {
        CHAN_MEDIA_TRACE_OPEN(trace_raw_in);
        CHAN_MEDIA_TRACE_OPEN(trace_raw_out);
    }

    /* set the channel read period */
    if (sangoma_tdm_set_usr_period(chan->sangoma_sock, &tdm_api, SBRIDGE_MEDIA_PERIOD) < 0) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to set sangoma channel read period to %d\n", SBRIDGE_MEDIA_PERIOD);
        sbridge_thread_exit(NULL);
    }

    /* everything will be passed thru as received, WP_NONE */
    if ((sangoma_tdm_set_codec(chan->sangoma_sock, &tdm_api, WP_NONE)) < 0) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to set native driver codec for sangoma channel %d\n", channo);
        sbridge_thread_exit(NULL);
    }

    chan->mtu = sangoma_tdm_get_usr_mtu_mru(chan->sangoma_sock, &tdm_api);
    if (chan->mtu != SBRIDGE_ALAW_MTU) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Unexpected MTU of size %d, cannot handle media\n", chan->mtu);
        sbridge_thread_exit(NULL);
    }

    sbridge_log(SBRIDGE_LOG_NOTICE, "Sangoma socket MTU is %d\n", chan->mtu);

    /* run the proper application depending on the chan mode */
    chan->app_func(chan);

    /* done, let's clean up our mess and notify the signaling thread */
    sbridge_log(SBRIDGE_LOG_NOTICE, "Media thread for channel %d completed application execution\n", channo);

    if (!sbridge_thread_setcancelstate(SBRIDGE_THREAD_CANCEL_DISABLE, NULL)) {
        sbridge_log(SBRIDGE_LOG_ERROR, "Failed to disable thread cancellation when terminating media thread for channel %d\n",
                    channo);
        sbridge_thread_exit(NULL);
    }

    /* this calls the cleanup handler to free resources */
    sbridge_thread_cleanup_pop(SBRIDGE_THREAD_CLEANUP_EXECUTE);

    sbridge_thread_exit(NULL);
    return NULL;
}
Ejemplo n.º 4
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;
}