////////////////////////////////////////////////////////////////////// // sangoma_port_configurator.cpp: implementation of the sangoma_port_configurator class. // // Author : David Rokhvarg ////////////////////////////////////////////////////////////////////// #include "sangoma_port_configurator.h" #define DBG_CFG if(1)printf("PORTCFG:");if(1)printf #define _DBG_CFG if(1)printf #define INFO_CFG if(1)printf("PORTCFG:");if(1)printf #define _INFO_CFG if(1)printf #define ERR_CFG if(1)printf("PORTCFG:");if(1)printf #define _ERR_CFG if(1)printf ////////////////////////////////////////////////////////////////////// //these are recommendations only: #define MIN_RECOMMENDED_BITSTREAM_MTU 256 #define MIN_RECOMMENDED_HDLC_MTU 2048 /*! \brief Brief description * */ static int get_number_of_channels(unsigned int chan_bit_map) { int chan_counter = 0, i; for(i = 0; i < (int)(sizeof(unsigned int)*8); i++){ if(chan_bit_map & (1 << i)){ chan_counter++; } } return chan_counter; } /*! \brief Brief description * */ static int get_recommended_bitstream_mtu(int num_of_channels) { int recommended_mtu = num_of_channels * 32;//<--- will work well in most cases // //Smaller mtu will cause more interrupts. //Recommend at least MIN_RECOMMENDED_BITSTREAM_MTU, user will set to smaller, if timing is important. // while(recommended_mtu < MIN_RECOMMENDED_BITSTREAM_MTU){ recommended_mtu = recommended_mtu * 2; } return recommended_mtu; } /*! \brief Brief description * */ static int check_mtu(int mtu, int hdlc_streaming, unsigned int channel_bitmap) { DBG_CFG("%s(): channel_bitmap: 0x%X\n", __FUNCTION__, channel_bitmap); if(mtu % 4){ ERR_CFG("Invalid MTU (%d). Must be divizible by 4.\n", mtu); return 1; } //if BitStream, check MTU is also divisible by the number of channels (timeslots) in the group if(hdlc_streaming == WANOPT_NO){ int num_of_channels = get_number_of_channels(channel_bitmap); DBG_CFG("num_of_channels in bitmap: %d\n", num_of_channels); if(mtu % num_of_channels){ ERR_CFG("Invalid MTU. For 'BitStream' Must be divisible by 4 AND by the number of\n\ \tchannels in the group (%d). Recommended MTU: %d.\n", num_of_channels, get_recommended_bitstream_mtu(num_of_channels)); return 2; } }//if() return 0; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// /*! \brief Brief description * */ sangoma_port_configurator::sangoma_port_configurator() { #if defined(__WINDOWS__) hPortRegistryKey = (struct HKEY__ *)INVALID_HANDLE_VALUE; #endif } /*! \brief Brief description * */ sangoma_port_configurator::~sangoma_port_configurator() { #if defined(__WINDOWS__) if(hPortRegistryKey != (struct HKEY__ *)INVALID_HANDLE_VALUE){ RegCloseKey(hPortRegistryKey); } #endif } /*! \brief SET new configuration of the API driver. * */ int sangoma_port_configurator::SetPortVolatileConfigurationCommand(port_cfg_t *port_cfg) { int err = sangoma_driver_port_set_config(wp_handle, port_cfg, wp_number); if (err) { err = 1; } return err; } /*! \brief Brief description * */ int sangoma_port_configurator::get_configration(port_cfg_t *port_cfg) { int err = sangoma_driver_port_get_config(wp_handle, port_cfg, wp_number); if (err) { err = 1; } return err; } /*! \brief Function to check correctness of 'port_cfg_t' structure. * */ int sangoma_port_configurator::check_port_cfg_structure(port_cfg_t *port_cfg) { unsigned int i, rc = 0; unsigned long tmp_active_ch = 0; unsigned long cumulutive_active_ch = 0; wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; wanif_conf_t *wanif_conf; DBG_CFG("%s()\n", __FUNCTION__); INFO_CFG("Running Driver Configration structure check...\n"); if(port_cfg->num_of_ifs < 1 || port_cfg->num_of_ifs > NUM_OF_E1_TIMESLOTS){ _INFO_CFG("Invalid number of Timeslot Groups - %d! Should be between %d and %d (including).\n", port_cfg->num_of_ifs, 1, NUM_OF_E1_TIMESLOTS); return 1; } for(i = 0; i < port_cfg->num_of_ifs; i++){ //check all logic channels were configured wanif_conf = &port_cfg->if_cfg[i]; if(wanif_conf->active_ch == 0){ _INFO_CFG("Group %d - no T1/E1 channels specified! Expecting a bitmap of channels.\n", i + 1); rc = 1; break; } //check the channels are valid for media type. if(sdla_fe_cfg->media == WAN_MEDIA_T1){ unsigned int t1_invalid_channels = ~T1_ALL_CHANNELS_BITMAP; if(wanif_conf->active_ch & (t1_invalid_channels)){ _INFO_CFG("Group %d - Invalid channels in Channel BitMap (0x%08X)!\n", i + 1, wanif_conf->active_ch & (t1_invalid_channels)); rc = 2; break; } } //check channels are NOT in use already by another Group if(wanif_conf->active_ch & cumulutive_active_ch){ _INFO_CFG("Group %d - one or more \"T1/E1 channels\" already used by another group!\n", i + 1); rc = 3; break; } //update cumulative channels for the next iteration cumulutive_active_ch |= wanif_conf->active_ch; tmp_active_ch = wanif_conf->active_ch; if(sdla_fe_cfg->media == WAN_MEDIA_E1 && sdla_fe_cfg->frame != WAN_FR_UNFRAMED){ //do not count the bit for channel 0! (valid only for Unframed E1) tmp_active_ch &= (~0x1); } if(check_mtu(wanif_conf->mtu, wanif_conf->hdlc_streaming, tmp_active_ch)){ rc = 4; break; } }//for() INFO_CFG("Driver Configration structure check - %s.\n", (rc == 0 ? "OK":"FAILED")); return rc; } /*! \brief Brief description * */ int sangoma_port_configurator::print_port_cfg_structure(port_cfg_t *port_cfg) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; wanif_conf_t *wanif_conf = &port_cfg->if_cfg[0]; unsigned int i; DBG_CFG("%s()\n", __FUNCTION__); _INFO_CFG("\n================================================\n"); INFO_CFG("Card Type\t: %s(%d)\n", SDLA_DECODE_CARDTYPE(wandev_conf->card_type), wandev_conf->card_type);/* Sangoma Card type - S514, S518 or AFT.*/ INFO_CFG("Number of TimeSlot Groups: %d\n", port_cfg->num_of_ifs); INFO_CFG("MTU\t\t: %d\n", wandev_conf->mtu); print_sdla_fe_cfg_t_structure(sdla_fe_cfg); for(i = 0; i < port_cfg->num_of_ifs; i++){ _INFO_CFG("\n************************************************\n"); _INFO_CFG("Configration of Group Number %d:\n", i); print_wanif_conf_t_structure(&wanif_conf[i]); } return 0; } /*! \brief Brief description * */ int sangoma_port_configurator::print_sdla_fe_cfg_t_structure(sdla_fe_cfg_t *sdla_fe_cfg) { _INFO_CFG("\n################################################\n"); INFO_CFG("MEDIA\t\t: %s\n", MEDIA_DECODE(sdla_fe_cfg)); if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1 || FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_E1){ INFO_CFG("Line CODE\t: %s\n", LCODE_DECODE(sdla_fe_cfg)); INFO_CFG("Framing\t\t: %s\n", FRAME_DECODE(sdla_fe_cfg)); INFO_CFG("Clock Mode\t: %s\n", TECLK_DECODE(sdla_fe_cfg)); INFO_CFG("Clock Reference port: %d (0 - not used)\n", FE_REFCLK(sdla_fe_cfg)); INFO_CFG("Signalling Insertion Mode: %s\n", TE1SIG_DECODE(sdla_fe_cfg)); INFO_CFG("High Impedance Mode: %s\n", (FE_HIMPEDANCE_MODE(sdla_fe_cfg) == WANOPT_YES ? "Yes":"No")); INFO_CFG("FE_RX_SLEVEL: %d\n", FE_RX_SLEVEL(sdla_fe_cfg)); }//if() INFO_CFG("TDMV LAW\t: %s\n", (FE_TDMV_LAW(sdla_fe_cfg) == WAN_TDMV_MULAW ?"MuLaw":"ALaw")); INFO_CFG("TDMV SYNC\t: %d\n", FE_NETWORK_SYNC(sdla_fe_cfg)); switch(FE_MEDIA(sdla_fe_cfg)) { case WAN_MEDIA_T1: INFO_CFG("LBO\t\t: %s\n", LBO_DECODE(sdla_fe_cfg)); break; case WAN_MEDIA_E1: break; default: break; } return 0; } /*! \brief Brief port description * */ int sangoma_port_configurator::print_wanif_conf_t_structure(wanif_conf_t *wanif_conf) { INFO_CFG("Operation Mode\t: %s\n", wanif_conf->usedby); INFO_CFG("Timeslot BitMap\t: 0x%08X\n", wanif_conf->active_ch); INFO_CFG("Line Mode\t: %s\n", (wanif_conf->hdlc_streaming == WANOPT_YES ? "HDLC":"BitStream")); INFO_CFG("MTU\\MRU\t\t: %d\n", wanif_conf->mtu); return 0; } /*! \brief Brief port description * */ int sangoma_port_configurator::set_default_configuration(port_cfg_t *port_cfg) { return set_volatile_configration(port_cfg); } /*! \brief Brief port description * */ int sangoma_port_configurator::set_volatile_configration(port_cfg_t *port_cfg) { int rc; DBG_CFG("%s()\n", __FUNCTION__); ////////////////////////////////////////////////////////////////////////////////////////////////// #if 0 if(check_port_cfg_structure(port_cfg)){ ERR_CFG("Error(s) found in 'port_cfg_t' structure!\n"); return 1; } #endif rc = SetPortVolatileConfigurationCommand(port_cfg); if(rc){ //configration failed INFO_CFG("%s(): Line: %d: return code: %s (%d)\n", __FUNCTION__, __LINE__, SDLA_DECODE_SANG_STATUS(rc), rc); return 2; } INFO_CFG("%s(): return code: %s (%d)\n", __FUNCTION__, SDLA_DECODE_SANG_STATUS(port_cfg->operation_status), port_cfg->operation_status); switch(port_cfg->operation_status) { case SANG_STATUS_DEVICE_BUSY: INFO_CFG("Error: open handles exist for 'wanpipe%d_if\?\?' interfaces!\n", wp_number); return port_cfg->operation_status; case SANG_STATUS_SUCCESS: //OK break; default: //error return 5; } return 0; } /*! \brief Brief port description * */ int sangoma_port_configurator::initialize_t1_tdm_span_voice_api_configration_structure(port_cfg_t *port_cfg, hardware_info_t *hardware_info, int span) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; //sdla_te_cfg_t *te_cfg = &sdla_fe_cfg->cfg.te_cfg; wan_tdmv_conf_t *tdmv_cfg = &wandev_conf->tdmv_conf; wanif_conf_t *wanif_cfg = &port_cfg->if_cfg[0]; // T1 parameters FE_MEDIA(sdla_fe_cfg) = WAN_MEDIA_T1; FE_LCODE(sdla_fe_cfg) = WAN_LCODE_B8ZS; FE_FRAME(sdla_fe_cfg) = WAN_FR_ESF; FE_LINENO(sdla_fe_cfg) = hardware_info->port_number; FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_MULAW; FE_NETWORK_SYNC(sdla_fe_cfg) = 0; FE_LBO(sdla_fe_cfg) = WAN_T1_0_110; FE_REFCLK(sdla_fe_cfg) = 0; FE_HIMPEDANCE_MODE(sdla_fe_cfg) = 0; FE_SIG_MODE(sdla_fe_cfg) = WAN_TE1_SIG_CCS; FE_RX_SLEVEL(sdla_fe_cfg) = WAN_TE1_RX_SLEVEL_12_DB; #if 1 FE_CLK(sdla_fe_cfg) = WAN_NORMAL_CLK; #else /* Use Master clock with a loopback cable or as Telco simulator. */ FE_CLK(sdla_fe_cfg) = WAN_MASTER_CLK; #endif port_cfg->num_of_ifs = 1; wandev_conf->config_id = WANCONFIG_AFT_TE1; wandev_conf->magic = ROUTER_MAGIC; wandev_conf->mtu = 2048; wandev_conf->PCI_slot_no = hardware_info->pci_slot_number; wandev_conf->pci_bus_no = hardware_info->pci_bus_number; wandev_conf->card_type = WANOPT_AFT; //m_DeviceInfoData.card_model; wanif_cfg->magic = ROUTER_MAGIC; wanif_cfg->active_ch = 0x00FFFFFF;//channels 1-24 (starting from bit zero) sprintf(wanif_cfg->usedby,"TDM_SPAN_VOICE_API"); wanif_cfg->u.aft.idle_flag=0xFF; wanif_cfg->mtu = 160; wanif_cfg->u.aft.mtu = 160; wanif_cfg->u.aft.mru = 160; sprintf(wanif_cfg->name,"w%dg1",span); if (hardware_info->max_hw_ec_chans) { /* wan_hwec_conf_t - HWEC configuration for Port */ /*wandev_conf->hwec_conf.dtmf = 1;*/ /* wan_hwec_if_conf_t - HWEC configuration for Interface */ wanif_cfg->hwec.enable = 1; } tdmv_cfg->span_no = (unsigned char)span; /* DCHAN Configuration */ switch(FE_MEDIA(sdla_fe_cfg)) { case WAN_MEDIA_T1: tdmv_cfg->dchan = (1<<23);/* Channel 24. This is a bitmap, not a channel number. */ break; default: printf("%s(): Error: invalid media type!\n", __FUNCTION__); return 1; } printf("T1: tdmv_cfg->dchan bitmap: 0x%X\n", tdmv_cfg->dchan); return 0; } int sangoma_port_configurator::initialize_e1_tdm_span_voice_api_configration_structure(port_cfg_t *port_cfg, hardware_info_t *hardware_info, int span) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; wan_tdmv_conf_t *tdmv_cfg = &wandev_conf->tdmv_conf; wanif_conf_t *wanif_cfg = &port_cfg->if_cfg[0]; // Load media parameters in the registry FE_MEDIA(sdla_fe_cfg) = WAN_MEDIA_E1; FE_LCODE(sdla_fe_cfg) = WAN_LCODE_HDB3; FE_FRAME(sdla_fe_cfg) = WAN_FR_CRC4; FE_LINENO(sdla_fe_cfg) = hardware_info->port_number; FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_ALAW; FE_NETWORK_SYNC(sdla_fe_cfg) = 0; FE_LBO(sdla_fe_cfg) = WAN_E1_120; FE_REFCLK(sdla_fe_cfg) = 0; FE_HIMPEDANCE_MODE(sdla_fe_cfg) = 0; FE_SIG_MODE(sdla_fe_cfg) = WAN_TE1_SIG_CCS; FE_RX_SLEVEL(sdla_fe_cfg) = WAN_TE1_RX_SLEVEL_12_DB; #if 1 FE_CLK(sdla_fe_cfg) = WAN_NORMAL_CLK; #else /* Use Master clock with a loopback cable or as Telco simulator. */ FE_CLK(sdla_fe_cfg) = WAN_MASTER_CLK; #endif port_cfg->num_of_ifs = 1; wandev_conf->config_id = WANCONFIG_AFT_TE1; wandev_conf->magic = ROUTER_MAGIC; wandev_conf->mtu = 2048; wandev_conf->PCI_slot_no = hardware_info->pci_slot_number; wandev_conf->pci_bus_no = hardware_info->pci_bus_number; wandev_conf->card_type = WANOPT_AFT; //m_DeviceInfoData.card_model; wanif_cfg->magic = ROUTER_MAGIC; wanif_cfg->active_ch = 0x7FFFFFFF;// channels 1-31 (starting from bit zero) sprintf(wanif_cfg->usedby,"TDM_SPAN_VOICE_API"); wanif_cfg->u.aft.idle_flag=0xFF; wanif_cfg->mtu = 160; wanif_cfg->u.aft.mtu = 160; wanif_cfg->u.aft.mru = 160; sprintf(wanif_cfg->name,"w%dg1",span); if (hardware_info->max_hw_ec_chans) { /* wan_hwec_conf_t - HWEC configuration for Port */ /*wandev_conf->hwec_conf.dtmf = 1;*/ /* wan_hwec_if_conf_t - HWEC configuration for Interface */ wanif_cfg->hwec.enable = 1; } tdmv_cfg->span_no = (unsigned char)span; /* DCHAN Configuration */ switch(FE_MEDIA(sdla_fe_cfg)) { case WAN_MEDIA_E1: tdmv_cfg->dchan = (1<<15);/* Channel 16. This is a bitmap, not a channel number. */ break; default: printf("%s(): Error: invalid media type!\n", __FUNCTION__); return 1; } printf("E1: tdmv_cfg->dchan bitmap: 0x%X\n", tdmv_cfg->dchan); return 0; } int sangoma_port_configurator::write_configration_on_persistent_storage(port_cfg_t *port_cfg, hardware_info_t *hardware_info, int span) { //all the work is done by libsangoma return sangoma_write_port_config_on_persistent_storage(hardware_info, port_cfg, (unsigned short)span); } int sangoma_port_configurator::control_analog_rm_lcm(port_cfg_t *port_cfg, int control_val) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; if(wandev_conf->card_type == WANOPT_AFT_ANALOG){ //Only valid for Analog cards if(control_val == 1){ sdla_fe_cfg->cfg.remora.rm_lcm = 1; }else if(control_val == 0){ sdla_fe_cfg->cfg.remora.rm_lcm = 0; }else{ printf("%s(): Error: invalid parameter!\n", __FUNCTION__); return -EINVAL; } } else{ return -EINVAL; } return 0; } /**************************************************************/ /*********** Analog Global Gain Setting Functions**************/ /**************************************************************/ //Note: following gain settings are global. It requires drivers to //restart the card. //It is recommended to use dynamic analog txgain/rxgain functions //from libsangoma library:sangoma_set_rm_tx_gain and sangoma_set_rm_rx_gain int sangoma_port_configurator::set_analog_rm_fxo_txgain(port_cfg_t *port_cfg, int txgain) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards sdla_fe_cfg->cfg.remora.fxo_txgain = txgain; } else{ return -EINVAL; } return 0; } int sangoma_port_configurator::set_analog_rm_fxo_rxgain(port_cfg_t *port_cfg, int rxgain) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards sdla_fe_cfg->cfg.remora.fxo_rxgain = rxgain; } else{ return -EINVAL; } return 0; } int sangoma_port_configurator::set_analog_rm_fxs_txgain(port_cfg_t *port_cfg, int txgain) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards sdla_fe_cfg->cfg.remora.fxs_txgain = txgain; } else{ return -EINVAL; } return 0; } int sangoma_port_configurator::set_analog_rm_fxs_rxgain(port_cfg_t *port_cfg, int rxgain) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; if(wandev_conf->card_type == WANOPT_AFT_ANALOG){//Only valid for Analog cards sdla_fe_cfg->cfg.remora.fxs_rxgain = rxgain; } else{ return -EINVAL; } return 0; } /**************************************************************/ /*********** End of Analog Global Gain Setting Functions ******/ /**************************************************************/ int sangoma_port_configurator::set_analog_opermode(port_cfg_t *port_cfg, char *opermode) { wandev_conf_t *wandev_conf = &port_cfg->wandev_conf; sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg; if(wandev_conf->card_type == WANOPT_AFT_ANALOG){ //Only valid for Analog cards if(sizeof(sdla_fe_cfg->cfg.remora.opermode_name) < strlen(opermode)) return -EINVAL; strcpy(sdla_fe_cfg->cfg.remora.opermode_name,opermode); } else{ return -EINVAL; } return 0; }