blob: 0fa016dd769f0f589f2ecc555cbe769f42b380d6 [file] [log] [blame]
/***********************************************************************
* Copyright (C) 2001, ZTE Corporation.
*
* File Name: si_adt.c
* File Mark:
* Description: siliconlab lib adapter.
* History :
* Date : 2010-04-07
* Version :1.0
* Author : duanzhw 182073
* Modification:
**********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <linux/fcntl.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/signal.h>
//#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include "si_voice_datatypes.h"
#include "proslic_mlt.h"
#include "proslic_mlt_math.h"
#include "timer_adt.h"
#ifdef SI3217X
#include "si3217x.h"
#include "si3217x_constants.h"
#endif
#ifdef SI3218X
#include "si3218x.h"
#include "si3218x_constants.h"
#endif
#include "112.h"
#include "usr_line.h"
//#include "generic-ability.h"
/**************************port map****************************/
static USL_PORT_MAP port_map[MAX_PORT_NUM] = {
/*flg, cs , chan, port , type, tx, rx*/
{0, 0, 0, 0, 0, 0, 0}
// {0, 0, 0, 0, 0, 1, 1},
// {0, 0, 0, 0, 0, 2, 2},
// {0, 0, 0, 0, 0, 3, 3},
};
/**************************************************************/
ctrl_S spiGciObj[MAX_PORT_NUM]; /* User¡¯s control interface object, can be consider as the port number */
systemTimer_S timerObj; /* User¡¯s timer object */
controlInterfaceType *ProHWIntf[MAX_PORT_NUM];
/* Define array of ProSLIC device objects */
ProslicDeviceType *ProSLICDevices[MAX_PORT_NUM];
/* Define array of ProSLIC channel object pointers */
proslicChanType_ptr arrayOfProslicChans[MAX_PORT_NUM];
/* 112 test */
//ProSLICMLTType SLICMLT;
//ProSLIC_mlt_foreign_voltages_state vState;
//ProSLIC_mlt_rmeas_state rMeas;
//ProSLIC_mlt_capacitance_state CapState;
//ProSLIC_mlt_ren_state RenState;
long RingVol[MAX_RING_CNT]= {0}, RingCnt = 0;
//TestResult_t ResBuf;
/* board cfg */
static SILAB_CFG_CHIP_t BoardCfg[MAX_PORT_NUM] = {{0}};
/* As for one board, using one signal to avoid the conflict */
static const u8 pcmcfg[] = {0x4,0x1,0x3};
static Port_t ports[MAX_PORT_NUM];
//extern u8 init_flg;
extern slic_state current_state;
extern USL_PORT *pstUslPort;
extern int dtmf_mute;
extern u8 slic_offhook;
static s8 si_signal_ctrl(Port_t *pPort, const void *signal_attr,const u8 flag);
static s8 si_timeslot_set(Port_t *pPort, const u8 TxTs, const u8 RxTs);
static s8 si_timeslot_release(Port_t *pPort);
static s8 si_chip_reset(Port_t *pPort, u16 port);
static s8 si_polarity_reverse(Port_t *pPort, const u16 port);
static s8 si_parm_set(Port_t *pPort, u8 *parm, const u8 size);
static s8 si_parm_get(Port_t *pPort, u8 *parm, const u8 size );
static s8 si_ram_set(Port_t *pPort, u8 *parm, const u8 size);
static s8 si_ram_get(Port_t *pPort, u8 *parm, const u8 size );
static s8 si_time_cfg(Port_t *pPort, const USL_CONFIG *Slc_Time_Cfg);
static s8 si_slctool_time_cfg(Port_t *pPort, SLIC_IOCTL_CMD cmd, u16 wTime);
static s8 si_time_print(Port_t *pPort);
static s8 si_dial_set(Port_t *pPort, u8 bDialEn);
static s8 si_electric_set(Port_t *pPort, const u16 port, const ELECTRIC_CFG_CUSTOMIZED *buf);
static s8 si_start_test(Port_t *pPort, const WriteCmd_t *Cmd);
static s8 si_stop_test(Port_t *pPort );
static s8 si_read_result(Port_t *pPort, TestResult_t *pstResult);
static void ScanSiBoard(USL_PORT *pUslPort);
static void StartSiLineTest(Port_t *pPort, uInt8 TestId);
static s8 StartLineConnectTest(Port_t *pPort);
static void SiScanSignals(USL_PORT *usl_port, u8 hook);
static void SiUpdatePort(Port_t *data, u16 port, u8 event);
static s8 si_update_dcpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 vol_param, u8 cur_param);
static s8 si_update_ringpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 ringvol_param);
static int setUserMode (proslicChanType_ptr hProslic, BOOLEAN on);
USL_PORT_MAP *get_port_item(u8 port, u8 type);
int InitSiliconBoard(void);
int SiRemoveBoard(void);
void InitSiliconChip(Port_t *pPort);
int SiSetSemaphore(void *pHCtrl, int s);
int ProSLIC_PCMEnable(proslicChanType_ptr hProslic, u8 enable);
int ProSLIC_GetLinefeedStatus (proslicChanType_ptr hProslic, uInt8 *pLinefeed);
int VerifyChipID(ctrl_S *hCtrl, u8 chan);
void MLTClearSettings(ProSLICMLTType *pProSLICMLT);
void MLTClearResults(ProSLICMLTType *pProSLICMLT);
void SiMltScan(Port_t *pPort);
void SiSendResultVol(Port_t *pPort, ProSLICMLTType *pMlt);
void SiSendResultCap(Port_t *pPort, ProSLICMLTType *pMlt);
void SiSendResultRes(Port_t *pPort, ProSLICMLTType *pMlt);
void SiSendResultDCFeedSt(Port_t *pPort);
void SiSendResultBatteryVol(Port_t *pPort);
void SiSendResultRingtouser(Port_t *pPort);
void SiRen(Port_t *pPort, ProSLICMLTType *pMlt);
void SiSendResultHook(Port_t *pPort);
long ChangeData(unsigned long n);
long lldivde(long long x, long y);
long longfabs(long x);
#define FSK_DEPTH_TRIG 4
#define DISABLE_FSK_CID
//extern int spi_chipid_get(u8 port, u8 *cs, u8 *ch);
//extern const s8 *board_type_acquire(u32 *type);
/***************************************************************************/
static CODEC_OPS si_ops = {
.codec_signal_ctrl = si_signal_ctrl,
.codec_timeslot_set = si_timeslot_set,
.codec_timeslot_release = si_timeslot_release,
.codec_reset = si_chip_reset,
.codec_polarity_reverse = si_polarity_reverse,
.codec_parm_cfg = si_parm_set,
.codec_parm_get = si_parm_get,
.codec_ram_cfg = si_ram_set,
.codec_ram_get = si_ram_get,
.codec_time_cfg = si_time_cfg,
.codec_slctool_time_cfg = si_slctool_time_cfg,
.codec_time_print = si_time_print,
.codec_dial_set = si_dial_set,
.codec_electric_cfg = si_electric_set,
.codec_start_test = si_start_test,
.codec_stop_test = si_stop_test,
.codec_read_reslult = si_read_result,
.codec_scan = ScanSiBoard,
};
/****************** public func *******************/
USL_PORT_MAP * get_port_item(u8 port, u8 type)
{
u8 i = 0;
for( i = 0; i < MAX_PORT_NUM; i++ )
{
if( port_map[i].flg == 0 ) continue;
if( port == port_map[i].port && type == port_map[i].type )
{
return &port_map[i];
}
}
return NULL;
}
void make_port_map(void)
{
u8 cs = 0, chan = 0;
u8 i = 0;
int ret = 0;
for( i = 0; i < MAX_PORT_NUM; i++ )
{
//ret = spi_chipid_get(i, &cs, &chan);
if( 0 == ret )
{
#ifdef DEBUG_SLIC_ON
USLPUT0("Find a port:%d with chan %d cs %d\n", i, chan, cs);
#endif
port_map[i].flg = 1;
port_map[i].cs = cs;
port_map[i].chan = chan;
port_map[i].port = i;
port_map[i].type = SLIC_PORT_TYPE;
port_map[i].tx = i;
port_map[i].rx = i;
}
else
{
#ifdef DEBUG_SLIC_ON
USLPUT0("cann't Find a port:%d\n", i);
#endif
port_map[i].flg = 0;
}
}
}
void SlicCfgParaBasedBoardType(void)
{
//u32 dwBoardType = 0;
u32 dwPort = 0;
//board_type_acquire(&dwBoardType);
for (dwPort=0; dwPort<MAX_PORT_NUM; dwPort++)
{
#ifdef SI3217X
/*switch(dwBoardType)
{
default:
USLPUT0("Board default NO PTC\n");*/
BoardCfg[dwPort].ePTC = NOPTC;
// break;
//}
//#if defined (SILAB_SUPPORT_BUCKBOOST)
// BoardCfg[dwPort].generel_cfg = 0;
//#elif defined (SILAB_SUPPORT_LCQC)
// BoardCfg[dwPort].generel_cfg = 3;
//#else
BoardCfg[dwPort].generel_cfg = 2;
//#endif
BoardCfg[dwPort].ring = RING_F20_45VRMS_0VDC_LPR_SHORTTIME;//RING_F20_45VRMS_0VDC_LPR;
BoardCfg[dwPort].dc = DCFEED_48V_20MA;
BoardCfg[dwPort].tone = TONEGEN_FCC_DIAL;
BoardCfg[dwPort].Impe = ZSYN_600_0_0_30_0;
BoardCfg[dwPort].meter = DEFAULT_PULSE_METERING;
BoardCfg[dwPort].bLineOpen100msEn = 0;
BoardCfg[dwPort].bDisablePowerSave = 0;
BoardCfg[dwPort].a_u_law = PCM_16LIN;
BoardCfg[dwPort].cid = ITU_FSK;
BoardCfg[dwPort].linestaus = LF_FWD_ACTIVE;
BoardCfg[dwPort].wide = 2;
BoardCfg[dwPort].offset = 1;
BoardCfg[dwPort].rxgain = 0;
BoardCfg[dwPort].txgain = 0;
#endif
#ifdef SI3218X
BoardCfg[dwPort].ePTC = NOPTC;
BoardCfg[dwPort].generel_cfg = 0;
BoardCfg[dwPort].ring = RING_F20_45VRMS_0VDC_LPR;//RING_F20_45VRMS_0VDC_LPR;RING_F20_45VRMS_0VDC_LPR_SHORTTIME
BoardCfg[dwPort].dc = DCFEED_48V_20MA;
BoardCfg[dwPort].tone = TONEGEN_FCC_DIAL;
BoardCfg[dwPort].Impe = ZSYN_600_0_0_30_0;
BoardCfg[dwPort].meter = DEFAULT_PULSE_METERING;
BoardCfg[dwPort].bLineOpen100msEn = 0;
BoardCfg[dwPort].bDisablePowerSave = 0;
BoardCfg[dwPort].a_u_law = PCM_16LIN;
BoardCfg[dwPort].cid = ITU_FSK;
BoardCfg[dwPort].linestaus = LF_FWD_ACTIVE;
BoardCfg[dwPort].wide = 2;
BoardCfg[dwPort].offset = 1;
BoardCfg[dwPort].rxgain = 0;
BoardCfg[dwPort].txgain = 0;
#endif
}
return;
}
int InitSlicChip(void)
{
int ret = 0;
make_port_map();
ret = InitSiliconBoard();
return ret;
}
void DeinitSlicChip(void)
{
SiRemoveBoard();
return;
}
void SendErrorTest(Port_t *pPort, int err)
{
USLPUT2(" Test Error %d.\n", err );
pPort->stLineTestPara.pstResult->flg = TEST_ERROR;
pPort->stLineTestPara.pstResult->err_num = err; /*´íÎóºÅ*/
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE, 0, 0);
return;
}
void slic_inf_precfg(SLCINF_CFG *ptCfg)
{
if (NULL == ptCfg)
{
USLPUT0("%s ptCfg NULL \n", __FUNCTION__);
return;
}
if (ptCfg->bPort >= MAX_PORT_NUM)
{
USLPUT0("%s port:%d is bigger than MAX_PORT_NUM:%d\n", __FUNCTION__, ptCfg->bPort, MAX_PORT_NUM);
return;
}
si_update_dcpara(&BoardCfg[ptCfg->bPort], ptCfg->bCusDcVol, ptCfg->bCusDcLoopCurr);
si_update_ringpara(&BoardCfg[ptCfg->bPort], ptCfg->bCusRingVpk);
BoardCfg[ptCfg->bPort].bLineOpen100msEn = ptCfg->bLineOpen100msEn;
BoardCfg[ptCfg->bPort].bDisablePowerSave = ptCfg->bDisablePowerSave;
switch(ptCfg->dwImpe)
{
#if 0
case 600:
BoardCfg[ptCfg->bPort].Impe = ZSYN_600+BoardCfg[ptCfg->bPort].ePTC;
break;
case 680:
BoardCfg[ptCfg->bPort].Impe = ZSYN_200_680+BoardCfg[ptCfg->bPort].ePTC;
break;
#endif
default:
BoardCfg[ptCfg->bPort].Impe = ZSYN_600_0_0_30_0;
break;
}
BoardCfg[ptCfg->bPort].rxgain = ptCfg->i32Rxgain;
BoardCfg[ptCfg->bPort].txgain = ptCfg->i32Txgain;
USLPUT3("port:%d Dc:%d U:%d A:%d Ring:%d VPK:%d 100msEn:%d, DisPowerSave:%d impe:%d ePTC:%d dwImpe:%d rxgain(D-A):%d, txgain(A-D):%d\n",
ptCfg->bPort,
BoardCfg[ptCfg->bPort].dc, ptCfg->bCusDcVol, ptCfg->bCusDcLoopCurr,
BoardCfg[ptCfg->bPort].ring, ptCfg->bCusRingVpk,
BoardCfg[ptCfg->bPort].bLineOpen100msEn, BoardCfg[ptCfg->bPort].bDisablePowerSave,
BoardCfg[ptCfg->bPort].Impe, BoardCfg[ptCfg->bPort].ePTC, ptCfg->dwImpe,
BoardCfg[ptCfg->bPort].rxgain, BoardCfg[ptCfg->bPort].txgain);
return;
}
/****************** end *******************/
/****************** func for si_ops ****************/
static void si_tone_init(Port_t *pPort, SIGNAL_DATA *signal_attr)
{
u8 bToneIndex = signal_attr->tone_type;
u8 bOscillator2En = 0;
/* modified by zhanghuan for new SIGNAL_DATA struct */
#if 0
if (0 != signal_attr->cadence[0].freq2)
{
bOscillator2En = 1;
}
switch(signal_attr->cadence[0].freq1)
{
default:
bToneIndex = TONEGEN_450_N18DB_350_N18DB;
break;
}
#endif
/* modified by zhanghuan for new SIGNAL_DATA struct */
/*use preset tone type */
printk("ProSLIC_ToneGenSetup %d \n", bToneIndex);
ProSLIC_ToneGenSetup(pPort->ProObj, bToneIndex);
return;
}
uInt8 checkSum(char *str)
{
int i=0;
uInt8 sum = 0;
while(str[i] != 0)
{
sum += str[i++];
}
return -sum;
}
/*****************************************************************************************************/
/* Wait for FSK buffer to be available... */
void waitForCIDDone(SiVoiceChanType_ptr pChan)
{
int tmp = 0;
do
{
ProSLIC_CheckCIDBuffer(pChan, &tmp);
}
while(tmp == 0);
}
void sendFSKData(proslicChanType_ptr hProslic, char *stream, int preamble_enable)
{
uInt8 csum;
int buff_timeout;
int cid_remainder;
int baud_rate = 1200;
int bits = 10; /* 1 start + 8 data + 1 stop */
int i;
const uInt8 cid_preamble[] = {'U','U','U','U','U','U','U','U'};
buff_timeout = ((8 - FSK_DEPTH_TRIG) * (10000*bits)/baud_rate)/10;
/*
** SEND CID HERE
*/
/* Clear FSK buffer */
if((stream[1]+3)%FSK_DEPTH_TRIG)
{
cid_remainder = 1;
}
else
{
cid_remainder = 0;
}
ProSLIC_EnableCID(hProslic);
msleep(133); /* > 130ms of mark bits */
/* Enable FSKBUF interrupt so we can check it later. */
SiVoice_WriteReg(hProslic,PROSLIC_REG_IRQEN1,0x40);
(void)SiVoice_ReadReg(hProslic,
PROSLIC_REG_IRQ1); /* Clear IRQ1 */
printk("howard fsk cid send preamble\n");
if(preamble_enable)
{
/* Send preamble */
for(i=0; i<30; i+=FSK_DEPTH_TRIG)
{
if(i >= 8) /* The FIFO depth is 8 bytes, start waiting for it to empty */
{
waitForCIDDone(hProslic);
}
ProSLIC_SendCID(hProslic,cid_preamble,FSK_DEPTH_TRIG);
}
if (30%FSK_DEPTH_TRIG)
{
waitForCIDDone(hProslic);
}
ProSLIC_SendCID(hProslic,cid_preamble,30%FSK_DEPTH_TRIG);
waitForCIDDone(hProslic);
/* Delay > 130ms for idle mark bits */
msleep(133);
}
/* Send Message */
printk("howard fsk cid send message\n");
csum = checkSum(stream);
stream[stream[1]+2] = csum;
for(i=0; i<(stream[1]+3); i+=FSK_DEPTH_TRIG)
{
if(i>=8)
{
waitForCIDDone(hProslic);
}
ProSLIC_SendCID(hProslic,&(stream[i]),FSK_DEPTH_TRIG);
}
if(cid_remainder)
{
waitForCIDDone(hProslic);
ProSLIC_SendCID(hProslic,
&(stream[((stream[1]+3)/FSK_DEPTH_TRIG)*FSK_DEPTH_TRIG]),
(stream[1]+3)%FSK_DEPTH_TRIG);
}
waitForCIDDone(hProslic);
/* Make sure the last byte is shifted out prior to disabling CID */
msleep(buff_timeout);
ProSLIC_DisableCID(hProslic);
}
/*****************************************************************************************************/
/*
** Sequential (blocking) example of CID transmission
*/
void sendCIDStream(proslicChanType_ptr hProslic)
{
char cid_msg[] =
"\x80" /* MDMF Type */
"\x27" /* Message Length */
"\x01" /* Date/Time Param */
"\x08" /* 8-byte Date/Time */
"07040815" /* July 4th 08:15 am */
"\x02" /* Calling Number Param */
"\x0A" /* 10-byte Calling Number */
"5124168500" /* Phone Number */
"\x07" /* Calling Name Param */
"\x0F" /* 15-byte Calling Name */
"Nice" /* Calling Name */
"\x20" /* Calling Name (whitespace) */
"ProSLIC!!!" /* Calling Name */
"\x00" /* Placeholder for Checksum */
"\x00" /* Markout */
;
uInt8 reg_tmp;
ProSLIC_FSKSetup(hProslic,0);
ProSLIC_RingSetup(hProslic,1);
reg_tmp =SiVoice_ReadReg(hProslic,PROSLIC_REG_RINGCON);
SiVoice_WriteReg(hProslic,PROSLIC_REG_RINGCON,reg_tmp&0xF0);
/* Ensure OFFHOOK Active */
//ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE);
//msleep(500);
/* 1st Ring Burst */
ProSLIC_SetLinefeedStatus(hProslic,LF_RINGING);
msleep(2500);
/* OHT - the alternative is to have the configuration for ringing set OHT mode automatically... */
//ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_OHT); /* no need if RINGCON is set to 0x58*/
//msleep(500); /* Delay 250 to 3600ms */
sendFSKData(hProslic, cid_msg, 1);
}
static s8 si_signal_ctrl(Port_t *pPort, const void *signal_attr,const u8 flag)
{
static unsigned long int jiffies_save;
int ret = -1;
if(NULL == pPort)
{
USLPUT0("si_signal_ctrl pPort NULL \n");
return -1;
}
switch(flag)
{
/* play ring */
case RING_SIGNAL_INIT:
jiffies_save = jiffies;
USLPUT3("RING_SIGNAL_INIT\n");
break;
case RING_SIGNAL_ON:
//printk("start play ring ProSLIC_Init_MultiBOM\n");
//ProSLIC_Init_MultiBOM(&(pPort->ProObj),1,3);
/* ring and cid is moved to ioctl */
#if 0
printk("start play ring\n");
#ifdef DISABLE_FSK_CID
pPort->ProObj->channelType = PROSLIC;
ret = ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_RINGING);
USLPUT3("RING_SIGNAL_ON %lu, ret %d\n", jiffies - jiffies_save, ret);
jiffies_save = jiffies;
#else
/* add by zhanghuan for FSK CID */
sendCIDStream(pPort->ProObj);
#endif
current_state = RINGING;
#endif
break;
case RING_SIGNAL_OFF:
ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_FWD_OHT);
USLPUT3("RING_SIGNAL_OFF %lu\n", jiffies - jiffies_save);
jiffies_save = jiffies;
current_state = NONE;
break;
case RING_SIGNAL_OFF_REVERSED:
ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_REV_OHT);
USLPUT3("RING_SIGNAL_OFF_REVERSED %lu\n", jiffies - jiffies_save);
jiffies_save = jiffies;
break;
case RING_SIGNAL_CLEAN_OFF:
case RING_SIGNAL_CLEAN_ON:
ProSLIC_SetLinefeedStatus( pPort->ProObj, LF_FWD_ACTIVE);
USLPUT3("RING_SIGNAL_CLEAN_ON %lu\n", jiffies - jiffies_save);
jiffies_save = jiffies;
current_state = NONE;
break;
/* play tone */
case TONE_SIGNAL_INIT:
ProSLIC_ToneGenStop(pPort->ProObj);
current_state = NONE;
si_tone_init(pPort, (SIGNAL_DATA *)signal_attr);
break;
case TONE_SIGNAL_ON:
printk("start play tone\n");
if(TONE_DIAL != ((SIGNAL_DATA *)signal_attr)->tone_type)
{
ProSLIC_ToneGenStart(pPort->ProObj, 1); // Only DIAL TONE play continusely
}
else
{
ProSLIC_ToneGenStart(pPort->ProObj, 0);
}
current_state = PLAYING_TONE;
break;
case TONE_SIGNAL_OFF:
ProSLIC_ToneGenStop(pPort->ProObj);
current_state = NONE;
break;
case TONE_SIGNAL_CLEAN:
ProSLIC_ToneGenStop(pPort->ProObj);
current_state = NONE;
break;
default:
break;
}
return 0;
}
static s8 si_timeslot_set(Port_t *pPort, const u8 TxTs, const u8 RxTs)
{
u16 tx = 0;
u16 rx = 0;
if( NULL == pPort )
{
USLPUT0("leg_timeslot_set pPort NULL \n");
return -1;
}
tx = TxTs * 8 * pPort->pPreCfg->wide + pPort->pPreCfg->offset;
rx = RxTs * 8 * pPort->pPreCfg->wide + pPort->pPreCfg->offset;
USLPUT2("si_timeslot_set tx %d rx %d. \n",tx,rx);
ProSLIC_PCMTimeSlotSetup( pPort->ProObj, rx , tx );
ProSLIC_PCMEnable( pPort->ProObj, 1);
return 0;
}
static s8 si_timeslot_release(Port_t *pPort)
{
if( NULL == pPort )
{
USLPUT0("si_timeslot_release line NULL \n");
return -1;
}
ProSLIC_PCMEnable( pPort->ProObj, 0);
ProSLIC_PCMTimeSlotSetup( pPort->ProObj, MAX_PORT_NUM * 8 , MAX_PORT_NUM * 8 );
return 0;
}
static s8 si_chip_reset(Port_t *pPort, u16 port)
{
if( NULL == pPort )
{
USLPUT0("si_chip_reset pPort NULL \n");
return -1;
}
if( HOOKOFF == pPort->hook_state )
{
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
USLPUT3("ProSLIC_SetLinefeedStatus %d LF_FWD_ACTIVE\n",port);
usrline_report(port, EV_FXS_HOOKON, 0 , 0);
}
pPort->hook_state = HOOKON;
pPort->pulse_dig = 0;
pPort->stLineTestPara.si_item = 0xff;
pPort->stLineTestPara.test_flg = NOT_TEST;
pPort->stLineTestPara.cnt = 0;
pPort->low_len = 0;
pPort->high_len = 0;
pPort->bDialEn = EV_DIAL_STOP;
return 0;
}
static s8 si_polarity_reverse(Port_t *pPort, const u16 port)
{
u8 state = 0;
u8 new_state = 0;
if( NULL == pPort )
{
USLPUT0("si_polarity_reverse pPort NULL \n");
return -1;
}
ProSLIC_GetLinefeedStatus(pPort->ProObj, &state);
switch(state)
{
case LF_REV_ACTIVE:
case LF_FWD_ACTIVE:
case LF_FWD_OHT:
case LF_REV_OHT:
new_state = state ^ 0x4 ;
break;
default:
USLPUT0("reverse error at state% d\n",state);
return -1;
}
if((1 == pPort->pPreCfg->bLineOpen100msEn)&& (LF_REV_ACTIVE == state))
{
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN);
msleep(100);
USLPUT2("SLIC set line feed status from OPEN to %d\n",new_state);
}
ProSLIC_SetLinefeedStatus( pPort->ProObj, new_state );
return 0;
}
static s8 si_parm_set( Port_t *pPort, u8 *parm, const u8 size)
{
if( NULL == pPort )
{
USLPUT0("si_parm_set pPort NULL \n");
return -1;
}
ctrl_WriteRegisterWrapper( pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel,parm[0],parm[1]);
return 0;
}
static s8 si_parm_get( Port_t *pPort, u8 *parm, const u8 size )
{
u8 addr = 0;
if( NULL == pPort )
{
USLPUT0("si_parm_get pPort NULL \n");
return -1;
}
addr = parm[0];
*parm = ctrl_ReadRegisterWrapper( pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, addr);
USLPUT3("addr %d, data 0x%x\n", addr, parm[0]);
return 0;
}
static s8 si_ram_set( Port_t *pPort, u8 *parm, const u8 size)
{
u8 *temp_p = NULL;
u32 ram = 0;
u32 write_value = 0;
u32 read_value = 0;
if((NULL == pPort) || (NULL == parm))
{
USLPUT0("si_ram_set pPort/parm NULL \n");
return -1;
}
temp_p = (u8*) parm;
ram = *temp_p & 0xff;
temp_p++;
ram = ram | ((u8)(*temp_p)<<8);
temp_p++;
write_value = *temp_p;
temp_p++;
write_value = write_value | ((u8)(*temp_p)<<8);
temp_p++;
write_value = write_value | ((u8)(*temp_p)<<16);
temp_p++;
write_value = write_value | ((u8)(*temp_p)<<24);
USLPUT3("write: ram:%d value:0x%x.\n", ram, write_value);
setUserMode(pPort->ProObj, TRUE);
ctrl_WriteRAMWrapper (pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, ram, write_value);
read_value = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, ram);
setUserMode(pPort->ProObj, FALSE);
USLPUT3("read: ram:%d value:0x%x.\n", ram, read_value);
return 0;
}
static s8 si_ram_get( Port_t *pPort, u8 *parm, const u8 size)
{
u32 temp = 0;
u16 addr = 0;
if(NULL == pPort)
{
USLPUT0("si_ram_get pPort NULL \n");
return -1;
}
addr = *(u16 *)parm;
printk("SLIC read ram %d\n", addr);
setUserMode(pPort->ProObj, TRUE);
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, addr);
*((u32 *)parm) = temp;
setUserMode(pPort->ProObj, FALSE);
USLPUT3("addr %d, data 0x%x\n", addr, temp);
return 0;
}
static s8 si_update_ringpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 ringvol_param)
{
u32 dwNewRing = RING_F20_45VRMS_0VDC_LPR;
switch (ringvol_param)
{
#if 0
case RING_VOLTAGE_55VPK:
dwNewRing = RING_F25_40VRMS_0VDC_BAL; /* 40vrms */
break;
case RING_VOLTAGE_65VPK:
dwNewRing = RING_F25_45VRMS_0VDC_BAL; /* 45vrms */
break;
case RING_VOLTAGE_70VPK:
dwNewRing = RING_F25_50VRMS_0VDC_BAL; /* 50vrms */
break;
case RING_VOLTAGE_75VPK:
dwNewRing = RING_F25_55VRMS_0VDC_BAL; /* 55vrms */
break;
case RING_VOLTAGE_85VPK:
dwNewRing = RING_F25_60VRMS_0VDC_BAL; /* 60vrms */
break;
#endif
default:
dwNewRing = RING_F20_45VRMS_0VDC_LPR; /* 50vrms */
break;
}
if (dwNewRing != ptOldCfg->ring)
{
ptOldCfg->ring = dwNewRing;
return 1;
}
return 0;
}
static s8 si_ring_cfg(Port_t *pPort, u8 ringvol_param)
{
if(NULL == pPort)
{
USLPUT0("si3217x cfg ringvpk with NULL pointer pPort!\n");
return -1;
}
if (1 == si_update_ringpara(pPort->pPreCfg, ringvol_param))
{
ProSLIC_RingSetup(pPort->ProObj, pPort->pPreCfg->ring);
}
return 0;
}
static s8 si_update_dcpara(SILAB_CFG_CHIP_t *ptOldCfg, u8 vol_param, u8 cur_param)
{
u32 dwNewDc = DCFEED_48V_20MA;
switch (vol_param)
{
case DC_VOLTAGE_48V:
switch (cur_param)
{
#if 0
case DC_CURRENT_20MA:
dwNewDc = DCFEED_48V_20MA; /* 48v20mA */
break;
case DC_CURRENT_24MA:
dwNewDc = DCFEED_48V_24MA; /* 48v24mA */
break;
case DC_CURRENT_28MA:
dwNewDc = DCFEED_48V_28MA; /* 48v28mA */
break;
case DC_CURRENT_32MA:
dwNewDc = DCFEED_48V_32MA; /* 48v32mA */
break;
#endif
default:
dwNewDc = DCFEED_48V_25MA; /* 48v25mA */
break;
}
break;
case DC_VOLTAGE_52V:
switch (cur_param)
{
#if 0
case DC_CURRENT_20MA:
dwNewDc = DCFEED_52V_20MA; /* 52v20mA */
break;
case DC_CURRENT_24MA:
dwNewDc = DCFEED_52V_24MA; /* 52v24mA */
break;
case DC_CURRENT_28MA:
dwNewDc = DCFEED_52V_28MA; /* 52v28mA */
break;
case DC_CURRENT_32MA:
dwNewDc = DCFEED_52V_32MA; /* 52v32mA */
break;
#endif
default:
dwNewDc = DCFEED_48V_25MA; /* 48v25mA */
break;
}
break;
default:
dwNewDc = DCFEED_48V_25MA; /* 48v25mA */
break;
}
if (dwNewDc != ptOldCfg->dc)
{
ptOldCfg->dc = dwNewDc;
return 1;
}
return 0;
}
static s8 si_dcfeed_cfg(Port_t *pPort, u8 vol_param, u8 cur_param)
{
if(pPort == NULL)
{
USLPUT0("si3217x cfg dcfeed with NULL pointer pPort!\n");
return -1;
}
if (1 == si_update_dcpara(pPort->pPreCfg, vol_param, cur_param))
{
ProSLIC_DCFeedSetup(pPort->ProObj, pPort->pPreCfg->dc);
}
return 0;
}
static s8 si_disable_powersave(Port_t *pPort)
{
u8 bData = 0;
bData = ctrl_ReadRegisterWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel, SI3217X_COM_REG_ENHANCE);
bData &= ~0x10;
ctrl_WriteRegisterWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl, pPort->ProObj->channel,SI3217X_COM_REG_ENHANCE, bData);
return 0;
}
static s8 si_electric_set(Port_t *pPort, const u16 port, const ELECTRIC_CFG_CUSTOMIZED *buf)
{
s8 ret = 0;
u8 bRingVol = 0;
u8 bDcVol = 0;
u8 bDcCur = 0;
if((NULL == pPort) || (buf == NULL))
{
USLPUT0("si_electric_set pPort/buf NULL \n");
return -1;
}
bRingVol = buf->bCusRingVpk;
bDcVol = buf->bCusDcVol;
bDcCur = buf->bCusDcLoopCurr;
#if 0
switch(buf->bScene)
{
case DB_SLC_SINGLEPHONE_SHORTLOOP:
bRingVol = RING_VOLTAGE_70VPK;
bDcVol = DC_VOLTAGE_48V;
bDcCur = DC_CURRENT_20MA;
break;
case DB_SLC_MULTIPHONES_SHORTLOOP:
bRingVol = RING_VOLTAGE_70VPK;
bDcVol = DC_VOLTAGE_48V;
bDcCur = DC_CURRENT_32MA;
break;
case DB_SLC_LONGLOOP:
bRingVol = RING_VOLTAGE_85VPK;
bDcVol = DC_VOLTAGE_52V;
bDcCur = DC_CURRENT_20MA;
break;
case DB_SLC_ORIGINAL_FACTORY:
bRingVol = RING_VOLTAGE_70VPK;
bDcVol = DC_VOLTAGE_48V;
bDcCur = DC_CURRENT_20MA;
break;
case DB_SLC_CUSTOMIZED:
/* use customized parameters */
break;
default:
USLPUT0("\n Not support scence:%d \n", buf->bScene);
break;
}
#endif
USLPUT3("si_electric_set Ring_vol: %d Dc_vol: %d Dc_cur: %d\n", bRingVol, bDcVol, bDcCur);
ret = si_dcfeed_cfg(pPort, bDcVol, bDcCur);
if(ret)
{
USLPUT0("si_dcfeed_cfg fail !!! \n");
}
ret = si_ring_cfg(pPort, bRingVol);
if(ret)
{
USLPUT0("si_ring_cfg fail !!! \n");
}
return 0;
}
static s8 si_time_cfg(Port_t *pPort, const USL_CONFIG *Slc_Time_Cfg)
{
if((NULL == pPort) || (NULL == Slc_Time_Cfg))
{
USLPUT0("si_time_cfg pPort/Slc_Time_Cfg NULL \n");
return -1;
}
pPort->stUslConf.hookonmin = MS2JIFF(Slc_Time_Cfg->hookonmin, 10) + 2;
pPort->stUslConf.hookoffmin = MS2JIFF(Slc_Time_Cfg->hookoffmin, 10) - 2;
pPort->stUslConf.prehookoff = MS2JIFF(Slc_Time_Cfg->prehookoff, 10) - 2;
pPort->stUslConf.flash_low_min = MS2JIFF(Slc_Time_Cfg->flash_low_min, 10) - 2;
pPort->stUslConf.flash_low_max = MS2JIFF(Slc_Time_Cfg->hookonmin, 10) + 2;
pPort->stUslConf.flash_high_fix = MS2JIFF(Slc_Time_Cfg->flash_high_fix, 10) - 2;
pPort->stUslConf.dial_high_min = MS2JIFF(Slc_Time_Cfg->dial_high_min, 10) - 2;
pPort->stUslConf.dial_high_max = MS2JIFF(Slc_Time_Cfg->dial_high_max, 10) + 2;
pPort->stUslConf.dial_low_min = MS2JIFF(Slc_Time_Cfg->dial_low_min, 10) - 2;
pPort->stUslConf.dial_low_max = MS2JIFF(Slc_Time_Cfg->dial_low_max, 10) + 2;
return 0;
}
static s8 si_slctool_time_cfg(Port_t *pPort, SLIC_IOCTL_CMD cmd, u16 wTime)
{
if(NULL == pPort)
{
USLPUT0("si_slctool_time_cfg pPort NULL \n");
return -1;
}
switch(cmd)
{
case SLIC_CFG_HOOK_LOWLEN:
case SLIC_CFG_FLASH_LMAX:
pPort->stUslConf.hookonmin = MS2JIFF(wTime, 10) + 2;
pPort->stUslConf.flash_low_max = MS2JIFF(wTime, 10) + 2;
break;
case SLIC_CFG_HOOK_HIGLEN:
pPort->stUslConf.hookoffmin = MS2JIFF(wTime, 10) - 2;
break;
case SLIC_CFG_PREHOOK_HIGLEN:
pPort->stUslConf.prehookoff = MS2JIFF(wTime, 10) - 2;
break;
case SLIC_CFG_FLASH_LMIN:
pPort->stUslConf.flash_low_min = MS2JIFF(wTime, 10) - 2;
break;
case SLIC_CFG_FLASH_HFIX:
pPort->stUslConf.flash_high_fix = MS2JIFF(wTime, 10) - 2;
break;
case SLIC_CFG_DIAL_HMIN:
pPort->stUslConf.dial_high_min = MS2JIFF(wTime, 10) - 2;
break;
case SLIC_CFG_DIAL_HMAX:
pPort->stUslConf.dial_high_max = MS2JIFF(wTime, 10) + 2;
break;
case SLIC_CFG_DIAL_LMIN:
pPort->stUslConf.dial_low_min = MS2JIFF(wTime, 10) - 2;
break;
case SLIC_CFG_DIAL_LMAX:
pPort->stUslConf.dial_low_max = MS2JIFF(wTime, 10) + 2;
break;
default:
USLPUT0("cmd=%d not found!\n", cmd);
break;
}
return 0;
}
static void InitPortsData(int port)
{
if (port >= MAX_PORT_NUM)
{
USLPUT0("InitPortsData port %d fail\n", port);
return;
}
ports[port].hook_state = HOOKON;
ports[port].pulse_dig = 0;
ports[port].stLineTestPara.si_item = 0xff;
ports[port].stLineTestPara.test_flg = NOT_TEST;
ports[port].stLineTestPara.cnt = 0;
ports[port].low_len = 0;
ports[port].high_len = 0;
ports[port].stUslConf.hookonmin = MS2JIFF(100, 10)/10;
ports[port].stUslConf.hookoffmin = MS2JIFF(10, 10)/10;
ports[port].stUslConf.prehookoff = MS2JIFF(6, 10)/10;
ports[port].stUslConf.flash_low_min = MS2JIFF(4, 10)/10;
ports[port].stUslConf.flash_low_max = MS2JIFF(40, 10)/10;
ports[port].stUslConf.flash_high_fix = MS2JIFF(25, 10)/10;
ports[port].stUslConf.dial_high_min = MS2JIFF(3, 10)/10;
ports[port].stUslConf.dial_high_max = MS2JIFF(12, 10)/10;
ports[port].stUslConf.dial_low_min = MS2JIFF(4, 10)/10;
ports[port].stUslConf.dial_low_max = MS2JIFF(15, 10)/10;
/* add slic inf pre cfg to port struct */
ports[port].pPreCfg = &BoardCfg[port];
return;
}
int InitSiliconBoard(void)
{
int i = 0;
int dwInitCh = 0;
int devtpye = -1;
int ret = 0;
USL_PORT_MAP *p = NULL;
SlicHardReset();
for(i = 0; i < MAX_PORT_NUM; i++)
{
p = get_port_item(i, SLIC_PORT_TYPE );
if(NULL != p)
{
#ifdef DEBUG_SLIC_ON
USLPUT0("Init port %d\n", i);
#endif
spiGciObj[i].port = p->cs;
ProSLIC_createControlInterface(&ProHWIntf[i]);
ProSLIC_createDevice(&(ProSLICDevices[i]));
ProSLIC_createChannel(&ports[i].ProObj);
devtpye = VerifyChipID(&spiGciObj[i], p->chan);
if(-1 != devtpye)
{
ProSLIC_SWInitChan(ports[i].ProObj,p->chan,devtpye,ProSLICDevices[i],ProHWIntf[i]);
ProSLIC_setSWDebugMode(ports[i].ProObj,true); /* optional */
ProSLIC_setControlInterfaceCtrlObj (ProHWIntf[i], &spiGciObj[i]);
ProSLIC_setControlInterfaceReset (ProHWIntf[i], ctrl_ResetWrapper);
ProSLIC_setControlInterfaceWriteRegister (ProHWIntf[i], ctrl_WriteRegisterWrapper);
ProSLIC_setControlInterfaceReadRegister (ProHWIntf[i], ctrl_ReadRegisterWrapper);
ProSLIC_setControlInterfaceWriteRAM (ProHWIntf[i], ctrl_WriteRAMWrapper);
ProSLIC_setControlInterfaceReadRAM (ProHWIntf[i], ctrl_ReadRAMWrapper);
ProSLIC_setControlInterfaceTimerObj (ProHWIntf[i], &timerObj);
ProSLIC_setControlInterfaceDelay (ProHWIntf[i], time_DelayWrapper);
ProSLIC_setControlInterfaceTimeElapsed (ProHWIntf[i], time_TimeElapsedWrapper);
ProSLIC_setControlInterfaceGetTime (ProHWIntf[i], time_GetTimeWrapper);
ProSLIC_setControlInterfaceSemaphore (ProHWIntf[i], SiSetSemaphore);
ProSLIC_Reset(ports[i].ProObj);
arrayOfProslicChans[i] = ports[i].ProObj;
#ifdef SI3218X
(arrayOfProslicChans[i])->deviceId->chipType=SI32185;
#endif
dwInitCh++;
}
else
{
#ifdef DEBUG_SLIC_ON
USLPUT0("No Siliconlab chip was found!!\n");
#endif
}
}
}
if (0 == dwInitCh)
{
USLPUT0("No Siliconlab chip need to be initialized!!\n");
return -1;
}
#ifdef SIVOICE_MULTI_BOM_SUPPORT
printk("ProSLIC_Init_MultiBOM\n");
ret = ProSLIC_Init_MultiBOM(arrayOfProslicChans,dwInitCh,BoardCfg[0].generel_cfg);
#else
printk("ProSLIC_Init\n");
ret = ProSLIC_Init(arrayOfProslicChans,dwInitCh);
#endif
if(0 != ret)
{
printk("howard ProSLIC_Init_MultiBOM return %d\n", ret);
return ret;
}
/* as to 32260 can make some phone crash, and no need to do this for short subscriber line, so don't use it again */
//ProSLIC_LBCal(arrayOfProslicChans,dwInitCh);
for(i = 0; i < dwInitCh; i++)
{
USLPUT3("get_port_item port:%d.\n",i);
p = get_port_item(i, SLIC_PORT_TYPE );
if (NULL != p)
{
USLPUT3("channelEnable:%d.\n",ports[i].ProObj->channelEnable);
if( 1 == ports[i].ProObj->channelEnable )
{
USLPUT3("Register the port:%d.\n",i);
InitPortsData(i);
InitSiliconChip(&ports[i]);
usrline_port_register(p->port, p->type, &si_ops, &ports[i]);
}
else
{
USLPUT0("port:%d disabled.\n",i);
return -1;
}
}
}
//init_flg = 1;
return 0;
}
int SiSetSemaphore(void *pHCtrl, int s)
{
/* Only slic use spi */
return 1;
}
/* handle the event */
int HandleSiEvent(Port_t *pPort, proslicIntType *pIntData)
{
int i = 0;
ProslicInt IntData ;
i = pIntData->number;
while(i--)
{
IntData = pIntData->irqs[i];
#ifdef DEBUG_SLIC_ON
switch(IntData)
{
case IRQ_VBAT:
/* The sensed battery voltage differs from the nominal VBAT value by an amount exceeding a programmed threshold. */
USLPUT2(" Error:VBAT_IA.\n");
break;
case IRQ_RING_TRIP:
break;
case IRQ_LOOP_STATUS:
/* Hookoff */
break;
case IRQ_LONG_STAT:
/* LONG_HI_IA */
USLPUT2(" Error: LONG_HI_IA.\n");
break;
case IRQ_VOC_TRACK:
/* The sensed battery voltage cannot support the programmed differential voltage. */
USLPUT2(" Error: VOC_TRACK_IA.\n");
break;
case IRQ_MADC_FS:
break;
case IRQ_P_HVIC:
/* a hardware power alarm based on the total chip power dissipation by the HVIC. */
USLPUT2(" Error:IRQ_P_HVIC.\n");
break;
case IRQ_P_THERM:
/* A hardware power alarm. */
USLPUT2(" Error:P_THERM_IA.\n");
break;
case IRQ_OSC1_T1:
case IRQ_OSC1_T2:
case IRQ_OSC2_T1:
case IRQ_OSC2_T2:
case IRQ_RING_T1:
case IRQ_RING_T2:
case IRQ_PM_T1:
case IRQ_PM_T2:
case IRQ_FSKBUF_AVAIL:
case IRQ_P_OFFLD:
case IRQ_DTMF:
case IRQ_INDIRECT:
case IRQ_TXMDM:
case IRQ_RXMDM:
case IRQ_PQ1:
case IRQ_PQ2:
case IRQ_PQ3:
case IRQ_PQ4:
case IRQ_PQ5:
case IRQ_PQ6:
case IRQ_RING_FAIL:
case IRQ_CM_BAL:
case IRQ_USER_0:
case IRQ_USER_1:
case IRQ_USER_2:
case IRQ_USER_3:
case IRQ_USER_4:
case IRQ_USER_5:
case IRQ_USER_6:
case IRQ_USER_7:
case IRQ_DSP:
break;
default:
break;
}
#endif
}
return 0;
}
void SiScanSignals(USL_PORT *usl_port, u8 hook)
{
Port_t *data = usl_port->pLine;
SiUpdatePort(data, usl_port->port, hook);
switch(data->hook_state)
{
case HOOKON:
break;
case HOOKOFFING:
if ( data->high_len == data->stUslConf.prehookoff )
{
/* User Pre HookOff! report */
}
if ( data->high_len < data->stUslConf.hookoffmin )
{
return;
}
//usrline_report(usl_port->port, EV_FXS_PRE_HOOKOFF, 0, usl_port->event_mask);
/* Finished. change state to HOOKOFF */
data->hook_state = HOOKOFF;
/* User HookOff! report */
//ProSLIC_SetLinefeedStatus( data->ProObj, LF_FWD_ACTIVE );??
usrline_report(usl_port->port,EV_FXS_HOOKOFF,0, usl_port->event_mask);
slic_offhook = 1;
break;
case HOOKOFF:
if (data->high_len == data->stUslConf.flash_high_fix &&
data->low_len < data->stUslConf.hookonmin && data->low_len >= data->stUslConf.dial_low_min )
{
if (data->pulse_dig == FLASH_EV_FLG)
{
USLPUT2("EV_FXS_FLASH: line=%d,low=%d. high %d\n",usl_port->port, data->low_len,data->high_len);
usrline_report(usl_port->port,EV_FXS_FLASH,0, usl_port->event_mask);
}
else if (( 1 <= data->pulse_dig ) && ( 10 >= data->pulse_dig ))
{
USLPUT2("EV_FXS_COLLECT_DIG: line=%d,low=%d. high %d\n",usl_port->port, data->low_len,data->high_len);
usrline_report(usl_port->port,EV_FXS_COLLECT_DIG,data->pulse_dig%10, usl_port->event_mask);
}
else
{
USLPUT2("drop dig:%d! line=%d, low %d, high %d\n", usl_port->port, data->pulse_dig, data->low_len, data->high_len);
}
data->pulse_dig = 0;
}
break;
case HOOKONING:
if (data->low_len < data->stUslConf.hookonmin)
{
//printk("low_len %d < hookonmin %d, return\n", data->low_len, data->stUslConf.hookonmin);
return;
}
/* Finished. change state to HOOKON */
//printk("low_len %d < hookonmin %d\n", data->low_len, data->stUslConf.hookonmin);
data->hook_state = HOOKON;
/* User HookOn! report */
data->pulse_dig = 0;
data->bDialEn = EV_DIAL_STOP;
usrline_report(usl_port->port,EV_FXS_HOOKON,0,usl_port->event_mask);
slic_offhook = 0;
break;
default:
break;
}
}
void SiUpdatePort(Port_t *data, u16 port, u8 event)
{
if (event == EV_LOW)
{
data->low_len++;
switch (data->hook_state)
{
case HOOKOFFING:
/* short pulse filter */
if (data->low_len > PULSE_FILTER_TIME)
{
data->hook_state = HOOKON;
data->low_len = 0;
}
else
{
data->high_len++;
}
break;
case HOOKOFF:
if (data->low_len > PULSE_FILTER_TIME)
{
data->hook_state = HOOKONING;
data->low_len = 0;
}
else
{
data->high_len++;
}
break;
default:
break;
}
}
else
{
data->high_len++;
switch (data->hook_state)
{
case HOOKON:
if (data->high_len > PULSE_FILTER_TIME)
{
data->hook_state = HOOKOFFING;
data->high_len = 0;
}
else
{
data->low_len++;
}
break;
case HOOKONING:
if (data->high_len > PULSE_FILTER_TIME)
{
data->hook_state = HOOKOFF;
/* To Judge if there is a pulse occured */
if((EV_DIAL_START == data->bDialEn) && (data->low_len >= data->stUslConf.dial_low_min) &&
(data->low_len < data->stUslConf.dial_low_max))
{
data->pulse_dig++;
USLPUT3("port:%d pulse_dig++! low %d, high %d, dig %d\n", port, data->low_len, data->high_len, data->pulse_dig);
}
else if(data->low_len >= data->stUslConf.flash_low_min)
{
data->pulse_dig = FLASH_EV_FLG;
USLPUT3("port:%d Flash! low %d, high %d\n", port, data->low_len, data->high_len);
}
else
{
USLPUT3("port:%d Pulse not dientfied! low %d, high %d\n", port, data->low_len, data->high_len);
}
data->high_len = 0;
}
else
{
data->low_len++;
}
break;
default:
break;
}
}
}
void InitSiliconChip(Port_t *pPort)
{
/* DC */
ProSLIC_DCFeedSetup(pPort->ProObj, pPort->pPreCfg->dc);
//ProSLIC_SetLinefeedStatus(pPort->ProObj, pPort->pPreCfg->linestaus);
/* Ring init */
ProSLIC_RingSetup(pPort->ProObj, pPort->pPreCfg->ring);
/* PCM init */
ProSLIC_PCMSetup(pPort->ProObj, pPort->pPreCfg->a_u_law);
ProSLIC_PCMTimeSlotSetup(pPort->ProObj,0x1,0x1);
ProSLIC_ZsynthSetup(pPort->ProObj, pPort->pPreCfg->Impe);
ProSLIC_ToneGenSetup(pPort->ProObj, pPort->pPreCfg->tone);
/* Meter init */
//ProSLIC_PulseMeterSetup(pPort->ProObj, pPort->pPreCfg->meter);
ProSLIC_FSKSetup(pPort->ProObj, ITU_FSK);
ProSLIC_AudioGainSetup(pPort->ProObj, pPort->pPreCfg->rxgain, pPort->pPreCfg->txgain, pPort->pPreCfg->Impe);
/* Active the line */
ProSLIC_EnableInterrupts(pPort->ProObj);
ProSLIC_SetLinefeedStatus(pPort->ProObj,LF_FWD_ACTIVE);
if (1 == pPort->pPreCfg->bDisablePowerSave)
{
si_disable_powersave(pPort);
}
return;
}
int SiRemoveBoard(void)
{
int i = 0;
USL_PORT_MAP *p = NULL;
for( i = 0; i <MAX_PORT_NUM; i++ )
{
p = get_port_item(i, SLIC_PORT_TYPE);
if(p != NULL)
{
if (1 == ports[i].ProObj->channelEnable)
{
USLPUT3("shutdown port:%d, ch:%d\n", i, ports[i].ProObj->channel);
/* reset chip */
ProSLIC_Reset(ports[i].ProObj);
}
p->cs = 0;
p->chan = 0;
p->port = 0;
/* free chip related memory */
ProSLIC_destroyChannel(&ports[i].ProObj);
ProSLIC_destroyDevice(&(ProSLICDevices[i]));
ProSLIC_destroyControlInterface(&ProHWIntf[i]);
}
}
return 0;
}
int ProSLIC_DTMFValid (proslicChanType_ptr pProslic)
{
int valid_tone = 0;
if(pProslic->channelType != PROSLIC)
{
return RC_IGNORE;
}
valid_tone = ctrl_ReadRegisterWrapper( pProslic->deviceId->ctrlInterface->hCtrl,
pProslic->channel,PROSLIC_REG_TONDTMF ) & 0x10;
if(valid_tone)
return 1;
else
return 0;
}
void ScanSiBoard(USL_PORT *pUslPort)
{
u8 hook = 0;
int ret = 0;
switch (pUslPort->pLine->stLineTestPara.test_flg)
{
case NOT_TEST:
if(dtmf_mute)
{
ret = ProSLIC_DTMFValid(pUslPort->pLine->ProObj);
if(!ret)
{
//ProSLIC_SetMuteStatus(pUslPort->pLine->ProObj,PROSLIC_MUTE_NONE);
dtmf_mute = 0;
}
}
//ProSLIC_ReadHookStatus(pUslPort->pLine->ProObj,&hook);
hook = slic_offhook;
SiScanSignals(pUslPort, hook);
break;
case TEST_STARTING:
case TEST_STOPING:
USLPUT3("change state:%d,do nothing\n", pUslPort->pLine->stLineTestPara.test_flg);
break;
case TESTING:
SiMltScan(pUslPort->pLine);
break;
default:
USLPUT0("unknow test state:%d\n", pUslPort->pLine->stLineTestPara.test_flg);
break;
}
return;
}
int VerifyChipID(ctrl_S *hCtrl, u8 chan)
{
u8 id = 0;
int devtype = 0;
id = ctrl_ReadRegisterWrapper(hCtrl, chan,SI3217X_COM_REG_ID);
printk("Siliconlab chip cs:%d ch:%d id! 0x%x \n",hCtrl->port, chan, id);
USLPUT0("Siliconlab chip cs:%d ch:%d id! 0x%x \n", hCtrl->port, chan, id);
#if 0
if (0xFF == id)
{
USLPUT0("Siliconlab chip cs:%d ch:%d id error! 0x%x \n", hCtrl->port, chan, id);
return devtype;
}
switch(id&0xc0)
{
case 0x80:
devtype = SI3217X_TYPE;
USLPUT0("Siliconlab chip Si3217x found! id:0x%x\n", id);
break;
case 0xc0:
devtype = SI3226X_TYPE;
USLPUT0("Siliconlab chip Si3226x found! id:0x%x\n", id);
break;
default:
USLPUT0("Siliconlab chip id error! 0x%x \n",id);
break;
}
#endif
#if 0
switch( (id & 0x38) >> 3 )
{
case 0:/* Si32171 */
#ifdef DEBUG_SLIC_ON
printk("Siliconlab chip Si32171 found!\n");
#endif
break;
case 3:/* Si32175 */
#ifdef DEBUG_SLIC_ON
printk("Siliconlab chip Si32175 found!\n");
#endif
break;
case 4:/* Si32176 */
#ifdef DEBUG_SLIC_ON
printk("Siliconlab chip Si32176 found!\n");
#endif
break;
case 5:/* Si32177 */
#ifdef DEBUG_SLIC_ON
printk("Siliconlab chip Si32177 found!\n");
#endif
break;
case 6:/* Si32178 */
#ifdef DEBUG_SLIC_ON
printk("Siliconlab chip Si32178 found!\n");
#endif
break;
default:
printk("Siliconlab chip id error! 0x%x \n",id);
return -1;
}
#endif
return SI3217X_TYPE;
}
int ProSLIC_PCMCfg (proslicChanType_ptr hProslic,u8 preset)
{
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_PCMMODE,pcmcfg[preset]);
return 0;
}
int ProSLIC_PCMEnable (proslicChanType_ptr hProslic, u8 enable )
{
u8 data = 0;
data = ctrl_ReadRegisterWrapper( hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_PCMMODE );
if( enable )
{
data |= 0x10;
}
else
{
data &= 0xef;
}
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_PCMMODE, data);
return 0;
}
int ProSLIC_GetLinefeedStatus (proslicChanType_ptr hProslic, uInt8 *pLinefeed)
{
u8 data = 0;
data = ctrl_ReadRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_LINEFEED);
*pLinefeed = data&0xf;
return 1;
}
static int setUserMode (proslicChanType_ptr hProslic, BOOLEAN on)
{
u8 data;
data = ctrl_ReadRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL);
if (((data&1) != 0) == on)
return 0;
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 2);
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 8);
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 0xe);
ctrl_WriteRegisterWrapper(hProslic->deviceId->ctrlInterface->hCtrl,hProslic->channel,SI3217X_COM_REG_TEST_CNTL, 0);
return 0;
}
static void StartSiLineTest(Port_t *pPort, uInt8 TestId)
{
if(NULL == pPort)
{
USLPUT0("StartSiLineTest error input NULL pointer.\n");
return;
}
USLPUT2("StartSiLineTest: line %d item %d!\n", pPort->stLineTestPara.pstResult->port, TestId);
pPort->stLineTestPara.pstMlt->Mlt.pProslic = pPort->ProObj;
MLTClearSettings(&pPort->stLineTestPara.pstMlt->Mlt);
MLTClearResults(&pPort->stLineTestPara.pstMlt->Mlt);
switch(TestId)
{
case TI_LineVolt:
/* Call test state initalization function */
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN);
pPort->stLineTestPara.si_item = TI_LineVolt;
ProSLIC_mlt_init_foreign_voltages(&pPort->stLineTestPara.pstMlt->vState,30);
pPort->stLineTestPara.test_flg = TESTING;
break;
/*case ROH_TEST:
id = LT_TID_ROH; Receiver Off-Hook indication
break; */
case TI_LineCap:
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN);
pPort->stLineTestPara.si_item = TI_LineCap;
ProSLIC_mlt_init_capacitance(&pPort->stLineTestPara.pstMlt->CapState);
pPort->stLineTestPara.test_flg = TESTING;
break;
case TI_LineRes:
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN);
pPort->stLineTestPara.si_item = TI_LineRes; /* Resistive Fault */
/* Call test state initalization function */
ProSLIC_mlt_init_resistive_faults(&pPort->stLineTestPara.pstMlt->rMeas);
pPort->stLineTestPara.test_flg = TESTING;
break;
case TI_LineRes_reverse:
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN);
pPort->stLineTestPara.si_item = TI_LineRes_reverse; /* Resistive Fault */
/* Call test state initalization function */
ProSLIC_mlt_init_resistive_faults(&pPort->stLineTestPara.pstMlt->rMeas);
pPort->stLineTestPara.test_flg = TESTING;
break;/**/
/*case GR_909:
id = LT_TID_ALL_GR_909; All GR-909 fault tests in predefined order
break;*/
/*case LOOP_BACK:
id = LT_TID_LOOPBACK; Loopback test
break;*/
case TI_LoopCircuitAndRes:
pPort->stLineTestPara.si_item = TI_LoopCircuitAndRes;
/* DC Feed Self Test */
pPort->stLineTestPara.test_flg = TEST_STOPING;
SiSendResultDCFeedSt(pPort);
break;
case TI_InLoopCurrent:
pPort->stLineTestPara.si_item = TI_InLoopCurrent;
/* DC Feed Self Test */
pPort->stLineTestPara.test_flg = TEST_STOPING;
SiSendResultDCFeedSt(pPort);
break;
case TI_BatteryVolt:
/* DC VOLTAGE Test */
pPort->stLineTestPara.si_item = TI_BatteryVolt;
pPort->stLineTestPara.test_flg = TEST_STOPING;
SiSendResultBatteryVol(pPort);
break;
case TI_RingVolt:
/* Ringing Self Test */
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_RINGING);
pPort->stLineTestPara.si_item = TI_RingVolt;
pPort->stLineTestPara.test_flg = TESTING;
RingCnt = 0;
/**/
break;
case ROH_TEST:
/* On/Off hook Self Test */
pPort->stLineTestPara.si_item = TI_Hook;
pPort->stLineTestPara.test_flg = TEST_STOPING;
SiSendResultHook(pPort);
break;
case TI_REN:
ProSLIC_mlt_init_ren(&pPort->stLineTestPara.pstMlt->RenState);
ProSLIC_mlt_init_ren_cal(&pPort->stLineTestPara.pstMlt->Mlt);
pPort->stLineTestPara.si_item = TI_REN;
pPort->stLineTestPara.test_flg = TESTING;
break;
/*case QUICKTEST:
id = LT_TID_PRE_LINE_V; Pre Line Voltage Test
break;*/
/*case 13:
id = LT_TID_FLT_DSCRM; Fault Discrimination Test
break;*/
case TI_Outside12:
/*step 1: Line Voltage Test */
/* Call test state initalization function */
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_OPEN);
pPort->stLineTestPara.si_item = TI_LineVolt;
ProSLIC_mlt_init_foreign_voltages(&pPort->stLineTestPara.pstMlt->vState,30);
pPort->stLineTestPara.test_flg = TESTING;
break;
case TI_LineConnect:
/*Line Connectivity Test */
StartLineConnectTest(pPort);
break;
default:
USLPUT1("The item is not surpported!\n");
SendErrorTest(pPort, NOT_SURPPORT);
return;
}
return;
}
static s8 si_start_test(Port_t *pPort, const WriteCmd_t *Cmd)
{
if((NULL == pPort) || (NULL == Cmd))
{
USLPUT0("si_start_test pPort/Cmd NULL pointer.\n");
return -1;
}
if (TEST_STARTING == pPort->stLineTestPara.test_flg || TESTING == pPort->stLineTestPara.test_flg)
{
USLPUT0("%s is under testing item:%d\n",__FUNCTION__, pPort->stLineTestPara.si_item);
return 0;
}
/* get test result memory */
pPort->stLineTestPara.pstResult = (TestResult_t *)kmalloc(sizeof(TestResult_t), GFP_KERNEL);
if (NULL == pPort->stLineTestPara.pstResult)
{
USLPUT0("%s port %d get TestResult memory failed!\n",__FUNCTION__, Cmd->port);
return -1;
}
memset(pPort->stLineTestPara.pstResult, 0, sizeof(TestResult_t));
/* save test message */
pPort->stLineTestPara.pstResult->port = Cmd->port;
pPort->stLineTestPara.pstResult->port_type = Cmd->port_type;
pPort->stLineTestPara.pstResult->item = Cmd->item;
pPort->stLineTestPara.pstResult->obligate = Cmd->obligate;
pPort->stLineTestPara.pstResult->num = Cmd->num;
pPort->stLineTestPara.pstResult->omci_item = Cmd->omci_item;
pPort->stLineTestPara.pstResult->flg = TEST_SUCC;
pPort->stLineTestPara.cnt = 0;
if((HOOKOFF == pPort->hook_state) && (0 == pPort->stLineTestPara.pstResult->obligate))
{
USLPUT1("The user is bust now!\n");
SendErrorTest(pPort, TEST_USER_BUSY);
return -1;
}
/* get memory to save testing data */
pPort->stLineTestPara.pstMlt = (ProSLICMLT *)kmalloc(sizeof(ProSLICMLT), GFP_KERNEL);
if (NULL == pPort->stLineTestPara.pstMlt)
{
USLPUT0("%s port %d get Mlt memory failed!\n",__FUNCTION__, Cmd->port);
kfree(pPort->stLineTestPara.pstResult);
pPort->stLineTestPara.pstResult = NULL;
return -1;
}
memset(pPort->stLineTestPara.pstMlt, 0, sizeof(ProSLICMLT));
pPort->stLineTestPara.test_flg = TEST_STARTING;
StartSiLineTest(pPort, pPort->stLineTestPara.pstResult->item);
return 0;
}
static s8 si_stop_test(Port_t *pPort)
{
if(NULL == pPort)
{
USLPUT0("si_stop_test pPort NULL \n");
return -1;
}
if (TESTING == pPort->stLineTestPara.test_flg)
{
pPort->stLineTestPara.test_flg = TEST_STOPING;
InitSiliconChip(pPort);
}
if (NULL != pPort->stLineTestPara.pstMlt)
{
kfree(pPort->stLineTestPara.pstMlt);
}
pPort->stLineTestPara.pstMlt = NULL;
if (NULL != pPort->stLineTestPara.pstResult)
{
kfree(pPort->stLineTestPara.pstResult);
}
pPort->stLineTestPara.pstResult = NULL;
pPort->stLineTestPara.test_flg = NOT_TEST;
return 0;
}
static s8 si_read_result(Port_t *pPort, TestResult_t *pstResult)
{
if((NULL == pPort) || (NULL == pstResult))
{
USLPUT0("leg_read_result pPort/pstResult NULL pointer.\n");
return -1;
}
if (NULL != pPort->stLineTestPara.pstMlt)
{
kfree(pPort->stLineTestPara.pstMlt);
}
pPort->stLineTestPara.pstMlt = NULL;
if (NULL != pPort->stLineTestPara.pstResult)
{
memcpy(pstResult, pPort->stLineTestPara.pstResult, sizeof(TestResult_t));
kfree(pPort->stLineTestPara.pstResult);
}
pPort->stLineTestPara.pstResult = NULL;
pPort->stLineTestPara.test_flg = NOT_TEST;
USLPUT3("\npPort->stLineTestPara.cnt=%d\n", pPort->stLineTestPara.cnt);
return 0;
}
static s8 StartLineConnectTest(Port_t *pPort)
{
if(NULL == pPort)
{
USLPUT1("StartLineConnectTest pPort NULL.\n");
return -1;
}
if(HOOKOFF == pPort->hook_state)//Õª»ú£¬Ôò±¨Óл°»ú
{
pPort->stLineTestPara.pstResult->user_flg = 1;
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0);
}
else //¹Ò»ú£¬Ôò²âREN
{
pPort->stLineTestPara.pstResult->user_flg = 0;
ProSLIC_mlt_init_ren(&pPort->stLineTestPara.pstMlt->RenState);
ProSLIC_mlt_init_ren_cal(&pPort->stLineTestPara.pstMlt->Mlt);
pPort->stLineTestPara.si_item = TI_REN;
pPort->stLineTestPara.test_flg = TESTING;
}
return 0;
}
static s8 si_time_print(Port_t *pLine)
{
USLPUT0("si32xxx times:\n");
USLPUT0("hookonmin: %d\n",pLine->stUslConf.hookonmin);
USLPUT0("hookoffmin: %d\n",pLine->stUslConf.hookoffmin);
USLPUT0("prehookoff: %d\n",pLine->stUslConf.prehookoff);
USLPUT0("flash_low_min: %d\n",pLine->stUslConf.flash_low_min);
USLPUT0("flash_high_fix:%d\n",pLine->stUslConf.flash_high_fix);
USLPUT0("dial_high_min: %d\n",pLine->stUslConf.dial_high_min);
USLPUT0("dial_high_max: %d\n",pLine->stUslConf.dial_high_max);
USLPUT0("dial_low_min: %d\n",pLine->stUslConf.dial_low_min);
USLPUT0("dial_low_max: %d\n",pLine->stUslConf.dial_low_max);
USLPUT0("dial_enable: %d\n",pLine->bDialEn);
return 0;
}
static s8 si_dial_set(Port_t *pPort, u8 bDialEn)
{
if(NULL == pPort)
{
USLPUT1("si_dial_set pPort NULL.\n");
return -1;
}
pPort->bDialEn = bDialEn;
return 0;
}
/*
** Clears REN cal flag
*/
void MLTClearSettings(ProSLICMLTType *pProSLICMLT)
{
pProSLICMLT->ren.renCalFlag = 0;
}
/*
** Clears any previous GR909 test results CDP move this to proslic_mlt.c
*/
void MLTClearResults(ProSLICMLTType *pProSLICMLT)
{
pProSLICMLT->hazVAC.measTG = 0;
pProSLICMLT->hazVAC.measTR = 0;
pProSLICMLT->hazVAC.measRG = 0;
pProSLICMLT->hazVAC.resultsValid = 0;
pProSLICMLT->hazVDC.measTG = 0;
pProSLICMLT->hazVDC.measTR = 0;
pProSLICMLT->hazVDC.measRG = 0;
pProSLICMLT->hazVDC.resultsValid = 0;
pProSLICMLT->resFaults.measTG = 10000000;
pProSLICMLT->resFaults.measTR = 10000000;
pProSLICMLT->resFaults.measRG = 10000000;
pProSLICMLT->resFaults.resultsValid = 0;
pProSLICMLT->roh.rohTrue = RC_MLT_ROH_NOFAULT;
pProSLICMLT->roh.resultsValid = 0;
pProSLICMLT->ren.renValue = 0;
pProSLICMLT->ren.resultsValid = 0;
}
void SiMltScan(Port_t *pPort)
{
int done = 0;
pPort->stLineTestPara.cnt++;
if( pPort->stLineTestPara.cnt > MAX_TEST_TIMEOUT ) /* Test time out */
{
pPort->stLineTestPara.test_flg = TEST_STOPING;
InitSiliconChip(pPort);
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
SendErrorTest(pPort, TESTITEM_TIMEOVER);
return;
}
switch( pPort->stLineTestPara.si_item )
{
case TI_LineVolt:
/* Call test function - will return 1 when complete */
done = ProSLIC_mlt_foreign_voltages(&pPort->stLineTestPara.pstMlt->Mlt,&pPort->stLineTestPara.pstMlt->vState);
if(1 == done)
{
pPort->stLineTestPara.test_flg = TEST_STOPING;
/* */
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
msleep(200); /* need more than 150ms to normal feed state */
SiSendResultVol(pPort, &pPort->stLineTestPara.pstMlt->Mlt);
}
break;
case TI_LineCap:
done = ProSLIC_mlt_capacitance(&pPort->stLineTestPara.pstMlt->Mlt,&pPort->stLineTestPara.pstMlt->CapState);
if(1 == done)
{
pPort->stLineTestPara.test_flg = TEST_STOPING;
#ifdef DEBUG_SLIC_ON
USLPUT2("InitSiChip port: %d.\n",pPort->stLineTestPara.pstResult->port);
#endif
InitSiliconChip(pPort); //added by fandi,because after the cap test, dsp can't receive 1 4 7 5 8.
if(HOOKOFF == pPort->hook_state)//Õª»ú״̬£¬ÖØÐÂÉèÖÃʱ϶
{
si_timeslot_set(pPort, pPort->stLineTestPara.pstResult->port, pPort->stLineTestPara.pstResult->port);
}
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
msleep(200); /* need more than 150ms to normal feed state */
SiSendResultCap(pPort, &pPort->stLineTestPara.pstMlt->Mlt); /* Ringers test per FCC Part 68 REN def.*/
}
break;
case TI_LineRes:
case TI_LineRes_reverse:
/* Call test function - will return 1 when complete */
done = ProSLIC_mlt_resistive_faults(&pPort->stLineTestPara.pstMlt->Mlt,&pPort->stLineTestPara.pstMlt->rMeas);
if(1 == done)
{
pPort->stLineTestPara.test_flg = TEST_STOPING;
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
msleep(200); /* need more than 150ms to normal feed state */
SiSendResultRes(pPort, &pPort->stLineTestPara.pstMlt->Mlt);
}
break;
case TI_LoopCircuitAndRes:
case TI_InLoopCurrent:
break;
case TI_BatteryVolt:
break;
case TI_RingVolt:
USLPUT1("%s: %d .\n", __FUNCTION__, __LINE__);
RingVol[RingCnt%MAX_RING_CNT] = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_MADC_VBAT);
RingCnt++;
if( RingCnt > (MAX_RING_CNT - 1))
{
RingCnt = 0;
pPort->stLineTestPara.test_flg = TEST_STOPING;
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
SiSendResultRingtouser(pPort);
}
break;
case TI_Hook:
break;
case TI_REN:
done = ProSLIC_mlt_ren(&pPort->stLineTestPara.pstMlt->Mlt, &pPort->stLineTestPara.pstMlt->RenState);
if( 1 == done )
{
pPort->stLineTestPara.test_flg = TEST_STOPING;
ProSLIC_SetLinefeedStatus(pPort->ProObj, LF_FWD_ACTIVE);
SiRen(pPort, &pPort->stLineTestPara.pstMlt->Mlt);
}
break;
/* case POWER_SUP_VOLT:
break;*/
case TI_Outside12:
break;
case TI_LineConnect:
break;
default:
return ;
}
}
void SiSendResultVol(Port_t *pPort, ProSLICMLTType *pMlt)
{
USLPUT2("V_TR:DC %d, AC %d\n",pMlt->hazVDC.measTR , (pMlt->hazVAC.measTR) / 10);
USLPUT2("V_TG:DC %d, AC %d\n",pMlt->hazVDC.measTG , (pMlt->hazVAC.measTG) / 10);
USLPUT2("V_RG:DC %d, AC %d\n",pMlt->hazVDC.measRG , (pMlt->hazVAC.measRG) / 10);
pPort->stLineTestPara.pstResult->vac_tr = pMlt->hazVAC.measTR;
pPort->stLineTestPara.pstResult->vac_tg = pMlt->hazVAC.measTG;
pPort->stLineTestPara.pstResult->vac_rg = pMlt->hazVAC.measRG;
pPort->stLineTestPara.pstResult->vdc_tr = pMlt->hazVDC.measTR;
pPort->stLineTestPara.pstResult->vdc_tg = pMlt->hazVDC.measTG;
pPort->stLineTestPara.pstResult->vdc_rg = pMlt->hazVDC.measRG;
if(TI_Outside12 == pPort->stLineTestPara.pstResult->item)
{
StartSiLineTest(pPort, TI_LineCap);
}
else
{
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0, 0);
}
}
void SiSendResultCap(Port_t *pPort, ProSLICMLTType *pMlt)
{
USLPUT2 ("RG Capacitance = %d.%d nF ***\n",pMlt->capFaults.measRG/10,pMlt->capFaults.measRG%10);
USLPUT2 ("TG Capacitance = %d.%d nF ***\n",pMlt->capFaults.measTG/10,pMlt->capFaults.measTG%10);
USLPUT2 ("TR Capacitance = %d.%d nF ***\n",pMlt->capFaults.measTR/10,pMlt->capFaults.measTR%10);
pPort->stLineTestPara.pstResult->cap_tr = pMlt->capFaults.measTR/10;
pPort->stLineTestPara.pstResult->cap_tg = pMlt->capFaults.measTG/10;
pPort->stLineTestPara.pstResult->cap_rg = pMlt->capFaults.measRG/10;
if(TI_Outside12 == pPort->stLineTestPara.pstResult->item)
{
StartSiLineTest(pPort, TI_LineRes);
}
else
{
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE,0, 0);
}
}
void SiSendResultRes(Port_t *pPort, ProSLICMLTType *pMlt)
{
signed long temp;
temp = pMlt->resFaults.measTR;
USLPUT2("tr = %ld.%ld Ohm\n",temp/10, temp % 10);
temp = pMlt->resFaults.measRG;
USLPUT2("rg = %ld.%ld Ohm\n",temp/10, temp % 10);
temp = pMlt->resFaults.measTG;
USLPUT2("tg = %ld.%ld Ohm\n",temp/10, temp % 10);
pPort->stLineTestPara.pstResult->res_tr = pMlt->resFaults.measTR/10;
pPort->stLineTestPara.pstResult->res_tg = pMlt->resFaults.measTG/10;
pPort->stLineTestPara.pstResult->res_rg = pMlt->resFaults.measRG/10;
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE, 0, 0);
}
void SiSendResultDCFeedSt( Port_t *pPort )
{
signed long data = 0, temp = 0;
long long vtr = 0, iloop = 0;
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_MADC_ILOOP);
USLPUT2(" battary %ld.\n", temp);
data = ChangeData(temp);
iloop = data;
iloop = iloop * 1676;
USLPUT2(" iloop %lld \n", iloop);
data = lldivde( iloop, 1000000000); /* mA */
USLPUT2(" iloop %ld \n", data);
pPort->stLineTestPara.pstResult->loop_curent = data;
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_VDIFF_SENSE);
data = ChangeData(temp);
vtr = data;
vtr = vtr * 931323;
USLPUT2(" Vol %lld \n", vtr);
data = lldivde( vtr, 1000000000 ); /* mV */
USLPUT2(" Vol %ld \n", data);
if( 0 != pPort->stLineTestPara.pstResult->loop_curent )
{
pPort->stLineTestPara.pstResult->loop_res = longfabs(data/pPort->stLineTestPara.pstResult->loop_curent);
}
else
{
pPort->stLineTestPara.pstResult->loop_res = 100000000;/* consider the res as 100M ohm */
}
if(TI_InLoopCurrent == pPort->stLineTestPara.si_item)
{
pPort->stLineTestPara.pstResult->loop_res = 0;
}
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0);
}
void SiSendResultBatteryVol(Port_t *pPort)
{
signed long data = 0, temp = 0;
long long vtr = 0;
temp = ctrl_ReadRAMWrapper(pPort->ProObj->deviceId->ctrlInterface->hCtrl,pPort->ProObj->channel,SI3217X_COM_RAM_MADC_VBAT);
USLPUT2(" battary %ld.%d\n", temp, sizeof(temp));
data = ChangeData(temp);
USLPUT2(" battary %ld.\n", data);
vtr = data;
vtr = vtr * 931323;
USLPUT2(" vtr %lld.\n", vtr);
data = lldivde( vtr, 1000000000 ); /* mV */
pPort->stLineTestPara.pstResult->battary = data;
USLPUT2(" battary %ld.\n", data);
usrline_report(pPort->stLineTestPara.pstResult->port, EV_FXS_TEST_DONE,0,0);
}
void SiSendResultHook( Port_t *pPort )
{
if( pPort->hook_state == HOOKOFF )
{
pPort->stLineTestPara.pstResult->user_flg = 1;
}
else
{
pPort->stLineTestPara.pstResult->user_flg = 0;
}
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0);
}
void SiSendResultRingtouser( Port_t *pPort )
{
long data = 0, vtr = 0;
long long temp = 0, vtr2 = 0;
u8 i = 0;
for( i = 0; i < MAX_RING_CNT; i++ )
{
data = ChangeData(RingVol[i]);
temp = data;
temp = temp * 931323;
USLPUT2("Ring[%d] = %ld, tem %lld\n", i, data, temp);
data = lldivde( temp, 1000000000 );
USLPUT2("Ring[%d] = %ld\n", i, data);
vtr += data;
vtr2 += data;
}
USLPUT2("vtr = %ld, vtr2 = %lld\n", vtr, vtr2);
vtr = vtr * 1000 / MAX_RING_CNT/ 1414;
pPort->stLineTestPara.pstResult->ring_vol = vtr;
USLPUT2(" vol %ld.\n", vtr);
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0);
}
void SiRen( Port_t *pPort, ProSLICMLTType *pMlt )
{
USLPUT2(" REN %d.\n", pMlt->ren.renValue);
pPort->stLineTestPara.pstResult->ren = pMlt->ren.renValue;
if(TI_LineConnect == pPort->stLineTestPara.pstResult->item)
{
pPort->stLineTestPara.pstResult->user_flg = pPort->hook_state;
USLPUT2(" user_flg %d.\n", pPort->stLineTestPara.pstResult->user_flg);
}
usrline_report(pPort->stLineTestPara.pstResult->port,EV_FXS_TEST_DONE,0,0);
}
long ChangeData(unsigned long n)
{
long t = 0;
unsigned long m = 0;
if( 0x1 & n>>28 )
{
m = (~n & 0x1fffffff) + 1;
t = -m;
}
else
{
t = n;
}
return t;
}
long lldivde(long long x, long y)
{
int s = 1;
long n = 0;
long long m = 0;
m = x;
if( m < 0 )
{
s = -1;
m = -m;
}
while(1)
{
m = m - y ;
if( m < 0 ) break;
n++;
}
return n*s ;
}
long longfabs( long x )
{
if( x < 0 ) return -x;
return x;
}