ENDPT_410_DoVrgEndptInit

isEndptDeinitialized = FALSE;	//标记endpt已经初始化
initStatus = 0;				//初始到哪个阶段,有多位宏表示
initThreadPid = current->pid;	//记载当前哪个进程调用了这个模块,当模块出现错误时,给该进程发送信号

//挂载默认断言回调,其中voiceAssertHandler回调函数有向initThreadPid发送信号
xchgAssertSetHandler( voiceAssertHandler );

//参数appinit、appDeinit都为空,主要是里面的监控函数有用
bosAppStart( appInit, appDeinit );
	//初始化
boszcb.appTask.init = appInit;
boszcb.appTask.deinit = appDeinit;
boszcb.appTask.stackSize = (16*1024);
boszcb.appTask.taskClass = BOS_CFG_APP_TASK_PRIORITY;
boszcb.appTask.taskArg = 0;
boszcb.appTask.name = BOS_APPTASK_NAME;

//创建一个内核线程,用于监控所有注册的BOS任务正常退出,下面把AppResetRootTask
//单独放外面写
bosTaskCreate( BOS_ROOTTASK_NAME,
                    (4*1024),
                    BOS_CFG_ROOT_TASK_PRIORITY,
                    AppResetRootTask,
                    0,
                    &boszcb.rootTaskId );
	
	AppResetRootTask
		//设置复位检测模式开启,用于vrgEndptDeinit时判断
//boszcb.resetDetectMode = BOS_RESETDETECT_ENABLED;
		bosAppResetDetectionEnable();
		
		//复位任务启动后阻塞在这里,该任务主要和bosAppReset配合,当有调用
		// bosAppReset时,bosAppReset函数会释放该信号量,复位任务被激活继
		//续向下处理。同时bosAppReset函数被阻塞在复位完成信号量上。
		bosSemTake( &boszcb.appResetSemId );
		
		//通知所有注册到BOS的任务进行复位,如果任务是运行状态,则只改变为
//复位标记,如果任务为SUSPENDED状态,则发向恢复事件,并改变复位标//记,当给所有任务改变为复位标记后,阻塞等待所有任务回应,所有任务在
//发现状态改为复位后,则退出并进行回应
		TaskResetNotifyAll();
		
		boszcb.resetState = BOS_RESETSTATE_NORESET;//复位完成标记
		bosTaskDestroy(&boszcb.rootTaskId);	//BOS根任务销毁
		
		//复位完成,释放完成信号量,保证bosAppReset可以正常退出
		bosSemGive( &boszcb.appResetCompletedSemId );


bosSleep(1000);	//延时

//从用户空间获取参数
copy_from_user( &KArg, (void *)arg, sizeof(KArg) );
copy_from_user( &endptInitCfg, KArg.endptInitCfg, sizeof(endptInitCfg);

//国家码、时钟寄存器的速率
boardHalInitCfg.country = endptInitCfg.country;
boardHalInitCfg.useJapDocsisClock = 0;

//板卡硬件适配层初始化
boardHalInit( &boardHalInitCfg );
	//标记这些服务模块需要初始化
//TPD用于线路测试
//HVGRING 与HVG提供振铃电压有关,当前没有使用
	// MODULE_FASTSLIC 与SLIC快速模式切换有关,当前没有使用
// MODULE_MSPI SPI初始化,上面注释是为LE88276、SI3226,我们当前是LE9530,所//以后面函数是空的
    boardCfgModules = BROADCFG6816_MODULE_TPD        |
                     BROADCFG6816_MODULE_HVGRING    |
                     BROADCFG6816_MODULE_FASTSLIC   |
                     BROADCFG6816_MODULE_MSPI;  /* Added for le88276, si3226 */
	
	// sharedReferencePin最后没看到哪个代码用到
	// enhancedControl 用于节能模式特性,不清楚
	boardHalInitCfg->sharedReferencePin = VRG_FALSE;
boardHalInitCfg->enhancedControl = VRG_FALSE;

boardHalInitUni( boardHalInitCfg, boardCfgModules);
//无源码,上面注释说在分布式的CPU上,将DSP所在的CPU核开启预读数据缓//存,并且给予比HOST核更高的优先级,这里如果HAL运行在CPU0,则DSP就
//在CPU1,反过来一样
		xdrvSetTPDCache( (boardHalRunningOnTP0() == VRG_TRUE) ? 1 : 0 );
		
		//获取语音相关参数,这个在endpoint_init时,已经从FLASH中取到
		voiceParams = boardHalProvGetVoiceParms();
		
		
		//内存分配
		gHalItpcSyncRecvCmd = malloc( sizeof(XDRV_ITPC_CMD) );
		gHalItpcSyncSendCmd = malloc( sizeof(XDRV_ITPC_CMD) );
		gHalItpcRecvStatusReg = malloc( sizeof(XDRV_ITPC_STATUS_REG) );
		gHalItpcSendStatusReg = malloc( sizeof(XDRV_ITPC_STATUS_REG) );
		gHalItpcSharedMemData = malloc( sizeof(XDRV_ITPC_SHARED_MEM_DATA) );
		gHalSpinLock = malloc( sizeof(XDRV_SPIN_LOCK) );
		gHalDspStackPtr = malloc( XDRV_ITPC_DSP_STACK_PTR_MAX * sizeof(XDRV_ITPC_DSP_STACK_PTR) );
		gHalDspStackDump = malloc( sizeof(XDRV_ITPC_DSP_STACK_DUMP) );
		gHalshimConfig = (LHAPI_HALSHIM_CONFIG*)malloc( sizeof(halShimConfig) );
		
		//这里设置硬件适配层芯片参数,就是从上面语语音参数voiceParams中获取,
//设置到gHalshimConfig数组中,该数组是线路级相关参数,如第0个通道为
// halShimConfig->halShimMode = HALSHIM_NARROWBAND_MODE;
// halShimConfig->halShimPcmChannels      = HALSHIM_PCM_CHANNELS_ONE;
// halShimConfig->halShimType = HAL_SHIM_CONFIG_AUDIO;
// halShimConfig->halShimSampleSize       = HALSHIM_SAMPLE_SIZE_16BITS
// halShimConfig->halShimPcmCompMode      = HALSHIM_PCM_COMP_ALAW
// halShimConfig->halShimPcmChannelMute = HALSHIM_PCM_CHANNEL_MUTE_OFF
// halShimConfig->halShimByteOrder        = HALSHIM_BYTE_ORDER_BIG_ENDIAN
//其它通道类似,其中有几个成员是从语音参数中获取的SLIC相关信息
//最后将所有通道总的数量设置到gHalshimEntryCount中
		memset(gHalshimConfig, 0, sizeof(gHalshimConfig));
		gHalshimEntryCount = gHalshimEntryCount = bhiPopulateHalshimConfig( gHalshimConfig );
		
		//获取DSP相关支持参数,存入dspCfg
		boardHalDspGetCfg(&dspCfg);
			//获取当前DSP库的能力及配置,dspImageArchiveGet函数直接从BCM提供的
			//DSP库的头文件数据结构中获取。
			pCap     = &(dspImageArchiveGet()->caps);
			pConfig  = &(dspImageArchiveGet()->config);
			
			//根据头文件中是否支持G711编码进行配置,下面各种编码类似,就不列了
			if ( pCap->g711Support )
			{
				dspCfg->codecCapabilities[CODEC_PCMU] = CODEC_SUPPORTED;
				dspCfg->codecCapabilities[CODEC_PCMA] = CODEC_SUPPORTED;
}

//支持RFC2833
dspCfg->codecCapabilities[CODEC_NTE] = CODEC_SUPPORTED;

//支持RFC2198,最大冗余等级支持2级
dspCfg->codecCapabilities[CODEC_RED] = CODEC_SUPPORTED;
dspCfg->maxRfc2198Level = 2;

//支持两种VBD
vbdCapabilities |= ( EPVBDMODE_LEGACY );
vbdCapabilities |= ( EPVBDMODE_V152 );
dspCfg->vbdCapability = vbdCapabilities;

dspCfg->isIcpEnabled = pCap->icpSupport;	//TRUE(空闲CPU profiler)
dspCfg->isDistributed = pConfig->isHauswareDistributed;//TRUE (分布式)
dspCfg->isWidebandEnabled = pConfig->isWidebandEnabled;//TRUE (开启宽带)
dspCfg->frameSyncSamples = pConfig->frameSyncSamples;	//40 (采样率)
dspCfg->maxEndPts    = pCap->numLineVhds;	//7(最大线路数)
dspCfg->maxFullCnxs  = pCap->numGatewayVhds;	//6(最大连接??)
dspCfg->maxLiteCnxs  = pCap->numConferenceVhds;	//4(最大会议数)

//什么祯补偿相关,如果是G711编码优先用bvc,其它编码用gplc
dspCfg->gplcSupport = pCap->gplcSupport;	//TRUE
dspCfg->bvcSupport = pCap->bvcSupport;	//TRUE

dspCfg->isEquEnabled = pCap->equSupport;	//FALSE(软均衡器)
		
		// 从GPIO寄存器里读取芯片ID进行校验当前是不是6816的板子,不是就报错
		if ( bhiVerifyChipId() != 0 )
		{
			return ( -1 );
}

//使用HVG振铃
if ( initModules & BROADCFG_MODULE_HVGRING )
	bUseHvg = VRG_TRUE;

boardHalApmInit( boardHalInitCfg, XDRV_TRUE, dspCfg.frameSyncSamples, bUseHvg )
	//网络参考时钟,函数已被屏蔽,因为使用了GPON驱动提供,不在需要外部
	ntrInit();
	
	apmCfg.sampleRate = 16;	//采样速率
	apmCfg.packetRate = packetRateSamples >> 3;	//从秒转为毫秒级,转后为5
	apmCfg.useRingGen = useRingGen;	//TRUE(使用APM振铃)
	apmCfg.useJapDocsisClock = boardHalInitCfg->useJapDocsisClock;	//FALSE
	
	
	
	//所有语音芯片
	while ( voiceParams->voiceDevice[deviceId].voiceDeviceType != BP_VD_NONE )
		//判断芯片类型,当前使用的是ZARLINK 9530 SLIC
		switch ( voiceParams->voiceDevice[deviceId].voiceDeviceType )
			//HVG类型为生降压
boardHalInitCfg->hvgDesignType= XDRV_APM_HVG_DESIGN_BUCKBOOST;
apmCfg.hvgType = XDRV_APM_HVG_DESIGN_BUCKBOOST;
devType = BP_VD_ZARLINK_9530;
			
			//指向静态内存
apmCfg.pFlexiCalc = (APM6816_FLEXICALC_CFG*)dynFlexicalc;

//计算机配置参数设置,这里采样为16000,设备类型为BP_VD_ZARLINK_9530
//,用终指针指向flexicalcWBNORTH_AMERICAArchive9530全局数组,里面有
//振铃电压等参数值
apmCfg.pFlexiCalc = flexiCalcGetCfg6816( boardHalInitCfg->country,
								apmCfg.sampleRate * 1000,
								devType );

//共享引脚,这里为FALSE
apmCfg.sharedReferencePin = boardHalInitCfg->sharedReferencePin;

//初始化ATM模块,这里设置了一些ATM的回调及寄存器
apm6816_init( &gApmDriver, PERF, &apmCfg )
	pDrv->pDrvFuncs = &bcm6816ApmDrvFuncs;	//回调
	pDrv->pApm = BCM6816_APM_PTR;	//APM基址寄存器
	pDrv->pIuDma = BCM6816_APM_IUDMA_PTR; //APM的IUDMA寄存器
	pDrv->pIntCtl = pIntCtl; //芯片控制寄存器
	pDrv->Cfg = *cfgp;	//配置参数
	
	//启动APM
	apm6816_start(pDrv);
		//为所有通道开启APM控制块
		pDrv->pIntCtl->blkEnables |= APM_CLK_EN | ACP_A_CLK_EN | ACP_B_CLK_EN | BMU_CLK_EN;
		
		//复拉ACP模块
    PERF->softResetB &= ~SOFT_RST_ACP;
    APM6816_USLEEP(1000);
    PERF->softResetB |=  SOFT_RST_ACP;
    APM6816_USLEEP(1000);
		
		
		//DPLL模块初始化
		apm_pllStart( pDrv->pApm );
		
		//APM寄存器初始化,里面太多寄存器操作,看不懂
		apm6816_regInit( pDrv->pApm, &pDrv->Cfg )
		
		//加载FlexiCalc设置,里面太多寄存器操作,看不懂
		apm6816_flexicalcConfig( pDrv->pApm, pDrv->Cfg.pFlexiCalc )
		
		//DMA模块初始化,里面没怎么看,不懂
		apm6816_dmaInit( pDrv->pApm, pDrv->pIuDma, pDrv->Cfg.sampleRate, pDrv->Cfg.packetRate )
	
	//初始化HVG模块,里面太多寄存器操作,不懂
	hvg6816Init( (XDRV_APM*)&gApmDriver )
		
		//通过之前的deviceChannelMap全局数组参数,填弃chanTsMap变量,记载每个
		//通道的时隙
		bhiPrepareChannelTimeslotMap( chanTsMap );
		
		//目前不支持ISI,也没有DECT芯片,所以supportedPCMPllMode取默认
//值MODE_REG,这里传入的三个参数在函数里都没用到
		pcmInit( chanTsMap, BCM_PCM_CHAN_MASK, supportedPCMPllMode);
			//使用基控制器开启PCM相关时钟
   			PERF->blkEnables |= APM_CLK_EN | ACP_A_CLK_EN | ACP_B_CLK_EN;
   			PERF->blkEnables |= PCM_CLK_EN | NTP_CLK_EN;
			
			//设置PCM相关功能开启(时钟同步、输入、输出、祯同步)
			GPIO->GPIOMode |= GPIO_MODE_APM_CLK | GPIO_MODE_APM_SDIN | GPIO_MODE_APM_SDOUT | GPIO_MODE_APM_FRAME_SYNC;
			
			//设置PCM寄存器,产生PCM时钟,里面好多寄存器操作,看不懂,大概
			//知道有设置时钟频率为2.8147MHz,8倍分频
			pcm6816_clkInit();
			
			//还是一些寄存器操作,头好大,看不懂,返回了各个通道对着的时隙位置
			//以前以为宽带时,一个通道会连续占两个时隙,但代码应该是每个通道间
			//阁的获取时隙
			chan_mask = pcm6816_regInit();
			
			//根据上面通道时隙参数,开启PCM模块操作,及开启通道的收发
			pcm6816_enable( chan_mask );
			
			
			//操作和DMA相关寄存器,这块看不懂
			pcm6816_dmaDescrInit();
			pcm6816_iudmaInit();

		xdrvSpinLockCreate( gHalSpinLock );	//创建自旋锁,用于共享数据互斥操作
		
		//将全局IPC操作成员状态寄存器、收发命令指向之前已经分配好的内存BUG
		//这里状态寄存器用于标识当前命令是否在阻塞处理
		gHalItpcSharedMemData->recvStatusReg = gHalItpcRecvStatusReg;
		gHalItpcSharedMemData->sendStatusReg = gHalItpcSendStatusReg;
		gHalItpcSharedMemData->syncRecvCmd   = gHalItpcSyncRecvCmd;
		gHalItpcSharedMemData->syncSendCmd   = gHalItpcSyncSendCmd;
		
		//封装IPC信号量对象,对象内容主要包括信号量本身,及操作回调
      	memset( &gHalItpcMutex, 0, sizeof( gHalItpcMutex ) );
      	gHalItpcMutex.acquireFunc  = ItpcMutexAcquire;
      	gHalItpcMutex.releaseFunc  = ItpcMutexRelease;
      	gHalItpcMutex.data         = &gHalItpcBosMutex;
      	bosMutexCreate( "ITPC-mutex", &gHalItpcBosMutex );
		
		//复位DSP栈调试相关
      	gHalDspStackDump->stackTraceCount = 0;
      	gHalDspStackDump->stackPtr = gHalDspStackPtr;
		
//ITPC各线程通信模块初始化,使用系统软中断实现,发送命令时,填充命令相关
//结构,触发软中断,中断函数收到中断后,遍历所有注册的IPC命令,并执行对
//应的注册回调函数
      	xdrvItpcInit( INTERRUPT_ID_SOFTWARE_0,
                    gHalItpcSharedMemData,
                    gHalSpinLock,
                    &gHalItpcMutex,
                    &gHalItpcDrv );
		
		//异常处理任务,函数内部创建了一个内核线程,该线程每次会阻塞在自创建的信
		//号量上,同时使用ipc模块机制注册了一个软中断命令,当其它线程触发该软中
		//断命令时,命令对应的回调函数仅仅释放信号量,与让该异常处理任务调用设置
		//的异常处理回调CmtExceptionCallback执行一次
		exceptionHdlrCmtInit( CmtExceptionCallback, NULL, &gHalItpcDrv );
		
		//给动态补偿模块设置了一些回调,但看了一下好像6816产品没有使用
		dlbStubCreate( &gHalDlbDrv );
		
		boardHalDspInit()
			boot6816Init( &gHalItpcDrv )		//添加一个DSP特殊异常IPC软中断,没代码
			//无源码,大概意思就是让DSP第二个线程启动
boot6816LoadImage( NULL, (unsigned int *) NULL);

//初始化DEBUG模块,设置一些回调,注释说用于双核获取DSP核的信息用
debugCmtInterfaceInit(&gHalItpcDrv, &gDebugCmtDrv );

// gIpcSharedMem分配内存
// gIpcSharedMem->chan[i]分配内存
// IPC_gDrv内存清空
// gDuplexDrv内存清空
// gIpcSharedMem->initInfo.newDataFlag = BOARD_HAL_IPC_DATA_READ;标记
boardHalIpcInit(0, 0, 0);
		
		//创建一个5MS触发一次的定时器内核线程,定时器索引为gTickTimer
		//定时器的回调句柄为gTimerCallback,当前定时器还未启动,同时回调
		//句柄为空指针
boardHalDspTaskInit()
	bosTaskCreateEx( DSP_TIMER_TASK_NAME,
                             DSP_TIMER_TASK_STACKSIZE,
                             DSP_TIMER_TASK_PRIORITY,
                             DspTimerTaskInitCB,
                             DspTimerTaskMain,
                             DspTimerTaskDeinitCB,
                             0,
                             &gTimerTaskId );

boardHalSlicInit(boardHalInitCfg, VRG_FALSE)
	boardHalSlicInitApm(boardHalInitCfg, bHighVring);	// bHighVring=FALSE
		//这里遍历所有语音板卡,目前6816上只有一个zarlink9530芯片
		//这里开始初始化SLIC
		boardHalSlicInit9530(boardHalInitCfg, bHighVring);
			//不清楚
		    GPIO->GPIOMode &= ~( GPIO_MODE_PCI_Req1_GPIO_16 |
                        GPIO_MODE_PCI_Gnt1_GPIO_17 |
                        GPIO_MODE_PCI_Intb_GPIO_18 |
                        GPIO_MODE_EBI_CS2_GPIO_26  |
                        GPIO_MODE_SPI_SSN2_GPIO_28 |
                        GPIO_MODE_SPI_SSN3_GPIO_29 );
			
			//获取之前的APM模块,因为HVG模块通过它引用
			pApmDrv = boardHalApmGetDriver( 0 );
			
			//遍历该驱动所有通道,目前有两个
			for ( endpt = 0; endpt < BOARD_HAL_6816_NUM_ENDPTS; endpt++ )
				//引用全局SLIC设备结构,后面操作SLIC驱动时,直接使用
				pDev = &(gSlicDriver[endpt]);
				memset( pDev, 0, sizeof( SLIC_6816_L9530_DRV ) );
				pDev->chan = -1;
				
				//准备初始化SLIC,其中参数分别为
				//pDev 	SLIC设备对象
				//endpt	第几路,从0开始
				// gSlicPinInfo		SLIC引脚信息,共5个脚,三个控制状态,一
				//个用于测试,一个用于查询摘挂机
				//pApmDrv	APM模块对象
				slic6816L9530Init( pDev, endpt, &gSlicPinInfo[endpt], pApmDrv);
					//将引脚信息存入驱动对象
					memcpy( &pDev->pinInfo, pSlicPinInfo, sizeof(pDev->pinInfo) );
					
					//根据引脚信息,设置好GPIO操作的参数信息(读写控
//制,开关,IO位,以方便后面直接IO操作,这些值存
//驱动对象的pDev->slicCfgInfo中)
					SetupGpioControl( pDev, pSlicPinInfo );
					
					//初始化驱动对象
					pDev->chan = chan;
					pDev->pDrvFuncs = &slicDrvFuncs;
					pDev->pApmDrv = pApmDrv;
					pDev->bDrvEnabled = XDRV_TRUE;
					pDev->bRingDCoffsetEnabled = XDRV_FALSE;
					pDev->bEnhancedControl = XDRV_FALSE;
					
					OpenSlic( pDev );
						//拉高状态控制
*pDev->slicCfgInfo.slicIoCtrlp|=
pDev->slicCfgInfo.slicIoStateMask;
//拉高TEST LOAD
*pDev->slicCfgInfo.slicIoTldCtrlp|=
 												pDev->slicCfgInfo.slicIoTldMask;
								//关闭TEST LOAD
								*pDev->slicCfgInfo.slicIoTldDatap&=
 ~pDev->slicCfgInfo.slicIoTldMask;
								//开启摘挂机检测
								*pDev->slicCfgInfo.slicIoNstatCtrlp&=
 ~(pDev->slicCfgInfo.slicIoNstatMask);
								//这个函数首先根据设置状态模式,得到SLIC当前所需
								//电压,然后通过APM的高压生成模块HVG输出电压,
								//如果HVG模块失败,则将SLIC置为断开状态,成功
								//则设置为正常的初始状态
								SetState( pDev, L9530_STATE_INIT )
						
						hvg6816Start(endpt)
							//暂停电流
							hvgp->reg_hvg_duty_cycle &= ~MAX_DUTY_CYCLE;
							hvgp->reg_hvg_duty_cycle |= 0x00000020;
							
							//开启对应线路的HVG控制块
							if( chan == 0 )
								   hvgp->reg_hvg_cha_misc &= ~HVG_SOFT_INIT_0;
							else
								   hvgp->reg_hvg_chb_misc &= ~HVG_SOFT_INIT_0;
							
							bosSleep( 20 );		//保证截流成功
							
							//恢复HUV电流输出
							hvgp->reg_hvg_duty_cycle &= ~MAX_DUTY_CYCLE;
							hvgp->reg_hvg_duty_cycle |= 0x000000A0;
			
			//这里设置SPI控制、复位、继电器的GPIO操作,但因为6816目前都不需要
			//设置这三项,所以这里函数用不到
			setGpios()
			
			//创建用于操作SPI控制的信号量,防止多进程操作SPI
			spiSiInit();
			spiZarInit();
			
			//这里是对所有VOIP板卡(SLIC等)驱动进行初始化,但因为6816使用9530
			//比较特殊,在上面已经初始化完了,这里就不会再执行
		
		//初始化CAS模块,为了摘挂机历史记录
		boardHalCasInit(VRG_FALSE)
			//遍历所以通道
			for ( endpt = 0; endpt < boardHalGetNumEndpoints(); endpt++ )
				//根据当前通道类型,获取对应类型的驱动对象,这里判断什么的都简化
				//了,目前取的是之前创建的9530 SLIC驱动对象
				slicDrv = boardHalSlicGetDriver( endpt );
				
				//初始化CAS驱动对象
				casDriverInit( slicDrv, fastSlicSupported, &gCasDriver[ endpt ]);
				   //历史记录相关参数初始化
   pHistory = &casDriver->casHistory;
   pHistory->debounceIntervalMsec  = 0;
   pHistory->historyEnabled        = XDRV_FALSE;
   pHistory->currentState = XDRV_CAS_UNKNOWN;
   pHistory->currentIntervalMsec = 0;
   pHistory->writep = &pHistory->hookStateBuf[0];
   pHistory->readp  = &pHistory->hookStateBuf[0];
   pHistory->prevp  = &pHistory->hookStateBuf[0];
   
   for(i = 0; i < XDRV_CAS_HIST_BUFFER_SIZE; i++)
   {
      pHistory->hookStateBuf[i] = XDRV_CAS_UNKNOWN;
   }
   
   //引用将SLIC驱动对象,方便CAS直接操作
   casDriver->slicDriver = slicDrv;
   
   //设置SLIC快速状态转换
   casDriver->bFastSlicStateModeSupported = fastSlicSupported;//false
   casDriver->bFastSlicStateModeEnabled = XDRV_FALSE;
   
   //将所有通道的CAS驱动串连起来
   if ( gCasDriverListHead == NULL )
   {
      gCasDriverListHead = casDriver;
      gCasDriverListTail = casDriver;
   }
   else
   {
      gCasDriverListTail->nextDrv = casDriver;
      gCasDriverListTail          = casDriver;
   }
   
   //标记当前通道的CAS驱动对象已经启用
   casDriver->nextDrv = NULL;
   casDriver->bDrvEnabled = XDRV_TRUE;

//启动CAS驱动的摘挂机历史记录功能,参数为
// CAS_BLOCK_RATE_MS	CAS状态机每2MS则触发一次
// BOARD_HAL_VCM_SW_DEBOUNCE_MS		摘挂机防抖动值为15MS
//看函数里面功能宏应该没有开启,所以这个函数没有使用
casDriverStartHistoryLog(CAS_BLOCK_RATE_MS,BOARD_HAL_VCM_SW_DEBOUNCE_MS )
		
		//FXO口驱动初始化
		boardHalDaaInit( boardHalInitCfg->country );
			voiceParams = boardHalProvGetVoiceParms();	//获取语音板卡参数集
			
			//遍历当前所有芯片
			for ( deviceId = 0; voiceParams->voiceDevice[deviceId].voiceDeviceType != 
			BP_VD_NONE; deviceId++ )
				//查找对应FXO芯片类型
				switch ( voiceParams->voiceDevice[deviceId].voiceDeviceType )
				case BP_VD_ZARLINK_88010: 	//假如是VP88010芯片
					//获取当前空的DAA驱动对象
					pDeviceDriver = &gDaaDriverLe88010[daaDriverLe88010index];
					
					//保存SPI设备ID
					pDeviceDriver->mspiId = 
						voiceParams->voiceDevice[deviceId].spiCtrl.spiDevId;
					
					//保存默认PCM为线型模式
					pDeviceDriver->pcmMode = LE88010_PCM_MODE_LINEAR;
					
					//如果当前配置通道采样为8比特,则重新设置PCM模式
					if ( voiceParams->voiceDevice[deviceId].channel[0].sampleSize == 
					BP_VOICE_CHANNEL_SAMPLE_SIZE_8BITS )
						if ( voiceParams->voiceDevice[deviceId].channel[0].pcmCompMode 
						== BP_VOICE_CHANNEL_PCMCOMP_MODE_ULAW )
							pDeviceDriver->pcmMode = LE88010_PCM_MODE_ULAW;
						else if
( voiceParams->voiceDevice[deviceId].channel[0].pcmCompMode
== BP_VOICE_CHANNEL_PCMCOMP_MODE_ALAW )
							pDeviceDriver->pcmMode = LE88010_PCM_MODE_ALAW;
					
					//设置当前通道的收发时隙
					pDeviceDriver->txTimeSlot  = 
						voiceParams->voiceDevice[deviceId].channel[0].txTimeslot * 2;
					pDeviceDriver->rxTimeSlot  =
 voiceParams->voiceDevice[deviceId].channel[0].rxTimeslot * 2;
					
					//驱动初始化
					daaLe88010Init( locale, daaDriverLe88010index, pDeviceDriver, 
					voiceParams->voiceDevice[deviceId].resetGpio );
						pDev->daaId           = daaId;	//通道ID
						//挂载所有通道API回调函数
						pDev->daaInfo.pDrvFuncs = &daaLe88010DrvFuncs;
						
						//根据用户配置,设置临时编码类型变量
						switch ( pDev->pcmMode )
						case LE88010_PCM_MODE_LINEAR:
							codecType = VP_OPTION_LINEAR;
						……
						
						//芯片复位
						daaLe88010Reset(rstGpioPin);
						
						//创建芯片设备对象,主要设置了一些底层API回调函数
						VpMakeDeviceObject(VP_DEV_880_SERIES, pDev->mspiId, 
						&pDaaDevCtx[0], &pDevObj[0]);
						
						//初始化芯片
						VpInitDevice(&pDaaDevCtx[0], DEV_VE880_PROFILE, 
						VP_PTABLE_NULL, DC_25MA_CC, RING_20HZ_SINE,
VP_PTABLE_NULL, VP_PTABLE_NULL);
						
						//等级初始化成功
						for (i = 0; i < DAA_INIT_TIMEOUT; i++)
							status = VpApiTick( &pDaaDevCtx[0], &vpApiEventPending );
							if ( status == VP_STATUS_SUCCESS )
								break;
							bosSleep(10);
						
						//如果芯片还未完成,则等待完成,并标记初始化成功
						if ( vpApiEventPending == TRUE )
							while(VpGetEvent(&pDaaDevCtx[0], &pEvent))
								if (pEvent.eventCategory == VP_EVCAT_RESPONSE)
									if(pEvent.eventId == VP_DEV_EVID_DEV_INIT_CMP)
										daaDeviceInitialized = XDRV_TRUE;
						
						//创建通道对象
						VpMakeLineObject(VP_TERM_FXO_GENERIC, 0 , &pLineCtx[0], 
						&pLineObj[0], &pDaaDevCtx[0]);
						
						//初始化通道
						VpInitLine( &pLineCtx[chanNum], 
                        daaLe88010GetLocale(locale, (VpProfileDataType**)gFXOProfiles), 
daaLe88010GetLocale(locale, (VpProfileDataType**)gFXODialProfiles), VP_PTABLE_NULL );
						
						//设置通道为回路断开状态
						VpSetLineState(&pLineCtx[chanNum], VP_LINE_FXO_LOOP_OPEN );
						
						//设置通道时隙
						timeslot.tx = pDev->txTimeSlot;
						timeslot.rx = pDev->rxTimeSlot;
						VpSetOption( &pLineCtx[chanNum], VP_NULL, 
						VP_OPTION_ID_TIMESLOT, (void*)×lot );
						
						//设置通道编码类型
						VpSetOption( &pLineCtx[chanNum], VP_NULL, 
						VP_OPTION_ID_CODEC, (void*)&codecType );
						
					daaDriverLe88010index++;	//下一个通道索引
					
		//初始化TPD驱动(用于线路测试)
		boardHalTpdInit()
			//遍历所有通道
			for ( endpt = 0; endpt < BOARD_HAL_6816_NUM_ENDPTS; endpt++ )
				//分别获取APM、SLIC、DEBUG驱动对象
				apmDrv = boardHalApmGetDriver( 0 );
				slicDrv = boardHalSlicGetDriver( endpt );
				pDebugDriver = boardHalDspGetDebugDriver();
				
				//仅仅赋予各驱动对象指针
				tpd6816InitChannel( endpt, slicDrv, apmDrv, pDebugDriver );
					pSlicDriver[chan] = slicDrv;
					pApmDriver[chan] = apmDrv;
					pDebugDriver[chan] = debugDrv;

//VRG线路级初始化
vrgEndptInit( &endptInitCfg, endpointdrvEventCB, endpointdrvPacketCB, 
endptProvGetCB, endptProvSetCB, endpointdrvRtpPacketReleaseCB,
endpointdrvTaskShutdownCB );
	//配置初始化,这里先查看配置是否标为不同国家指定属性,如果是,则按当前传入的
	//国家参数进行COPY,否则查看是否默认值有效,如果默认值有效则使用默认值进行
//COPY
	endptProvInitDefaults(country);
	
	//从BCM提供的DSP库的头文件取出DSP相关配置及能力配置到gDspCfg中
	boardHalDspGetCfg( &gDspCfg );
	
	//心跳监控模块,一个比较有意思的模块,监控接管的病人,当所有病人都死了,则进
	//入节能模式,一种设备级的节能(设置一个标记告诉DSP任务需要暂时),一种是线
	//路相关节能(让SLIC停止,但代码中目前不支持),当有一个病人活了时,再退出节
	//能模式。里面用到了BOS模块针对任务事件机制的使用。
	hbInit();
		bosMutexCreate( "hbMu", &hbcb.hbMutex );
		bosTaskCreateEx( "HRTBEAT",
						(4 * 1024),
						HEARTBEAT_CFG_TASK_PRIORITY,
						hbTaskInitCB,
						hbTaskMain,
						hbTaskDeinitCB,
						0,
						0,
						&heartbeatTaskId );
		hbcb.notifiedState = HBSTATE_ACTIVE; //通知方向(都死了告诉活的,活了告诉死的)
		hbcb.endpointState = HBSTATE_ACTIVE; //线路级状态(活的,还是死的)
		hbcb.bInited = VRG_TRUE;//是否初始化标记
		hbcb.bExtDeviceActive = VRG_TRUE;//标记当前外部设备的状态(是活动,还是停止)

endptConfig.country       = country;	//当前为中国
endptConfig.notify        = notifyCallback;	//DTMF按钮等事件回调
endptConfig.packet       = packetCallback;	//RTP发包回调
endptConfig.getProvision  = getProvisionCallback;	//获取配置回调
endptConfig.setProvision  = setProvisionCallback;	//设置配置回调
endptConfig.packetRelease = packetReleaseCallback;	//当前为空
endptConfig.acPowerHBId  = -1;

for( i = 0; i < vrgEndptGetNumEndpoints(); i++)	//遍历所有线路
  memset( &vrgEndpt[i], 0, sizeof( vrgEndpt[i] ));
  vrgEndpt[i].lineVhdHdl      = 0xffff;	//DSP的线路VHD句柄
  vrgEndpt[i].casCtlHandle    = 0xffff;	//CAS控制服务的索引
  vrgEndpt[i].pstnVhdHdl      = 0xffff;	//DSP的FXO类型VHD句柄
  vrgEndpt[i].confCnxVhdHdl   = 0x00;	//会议资源VHD句柄 
  vrgEndpt[i].country         = country;	//中国
  vrgEndpt[i].casCtlBits = EP_CAS_CTL_LCF; //CAS控制模式
  vrgEndpt[i].testMode        = TESTMODE_NONE;	//线路测试用
  vrgEndpt[i].hookStateHBId   = -1;	//心跳监控的关联句柄
  vrgEndpt[i].routedFxsLineId = -1;	//FXS口关联的FXS口ID
vrgEndpt[i].dspNum=i/(VRG_ENDPT_CFG_NUM_ENDPT/VRG_GLOBAL_CFG_MAX_NUM_DSP);		//DSP数量
  vrgEndpt[i].bGR303Support   = VRG_FALSE;	//RFC2833上报摘挂机等事件
  vrgEndpt[i].offhookciding   = VRG_FALSE;	//指示摘机来显还是挂机来显

//资源控制块初始化,不一一写了
for( i = 0; i < VRG_ENDPT_CFG_NUM_CNX; i++)	//遍历所有资源
      memset( &vrgCnxState[i], 0, sizeof( vrgCnxState[i] ));
      vrgCnxState[i].vrgVoiceJBFixed  = VRG_FALSE;
      vrgCnxState[i].vrgVoiceJBMin    = HAPI_PVE_MIN_JITTER_REG_DEFAULT;
      vrgCnxState[i].vrgVoiceJBMax    = HAPI_PVE_MAX_JITTER_REG_DEFAULT;
      vrgCnxState[i].vrgVoiceJBTarget = HAPI_PVE_TARGET_JITTER_REG_DEFAULT;
      vrgCnxState[i].vrgDataJBTarget  = HAPI_PVE_VBD_TARGET_JITTER_REG_DEFAULT;
      vrgCnxState[i].cnxId            = CNX_UNUSED;
      vrgCnxState[i].lineId           = BAD_ENDPTID;
      vrgCnxState[i].mode             = EPCNXMODE_INACT;
      vrgCnxState[i].voiceMode        = VM_IDLE;
      vrgCnxState[i].vhdMode          = NETMODE_IDLE;
      vrgCnxState[i].dataMode         = EPDATAMODE_VBD;
      vrgCnxState[i].cnxStateHBId     = -1;
      vrgCnxState[i].dspNum           = i / (VRG_ENDPT_CFG_NUM_CNX/VRG_GLOBAL_CFG_MAX_NUM_DSP);
      vrgCnxState[i].bMuteAudio       = VRG_FALSE;
      vrgCnxState[i].bMuteT38         = VRG_FALSE;
      vrgCnxState[i].t38param.ecMode  = EPT38EC_UDPREDUNDANCY;
      vrgCnxState[i].VadMode          = -1;
      vrgCnxState[i].CngMode          = -1;
      vrgCnxState[i].PlcMode          = -1;
      vrgCnxState[i].localSsrc        = 0;
      vrgCnxState[i].ajcCustomReg     = HAPI_PVE_AJC_CUSTOM_DEFAULT;
      vrgCnxState[i].faxrCustomReg    = HAPI_FAXR_CUSTOM_DEFAULT;
      RtpInit( &vrgCnxState[i].rtpstate );

//设置每个DSP默认能力
for( i = 0 ; i < VRG_GLOBAL_CFG_MAX_NUM_DSP ; i++ )
	vrgEndptCap[i] = defaultVrgEndptCap;

//向监控模块注册一个电源类型的监管病号,这里根据电源类型来设置病号的初始状态
//态(还活着,还是死了),当前我们传入的电源类型为交流电。如果电源类型为电池
//则需要传入病号状态为活着,以通过临控模块帮忙省电,这里即使是交流电也让注册
//监控病号,注释上说为了可后面切换到电池供电
initPowerState = ( ( endptInitCfg->currentPowerSource ) ? HBSTATE_INACTIVE : HBSTATE_ACTIVE );
hbRegisterPatient( initPowerState, HBPATIENT_TYPE_POWER, HBPATIENT_ALL_ENDPT, &endptConfig.acPowerHBId );

//这里把当前DSP真实能力值设置到vrgEndptCap中,其中gDspCfg是上面从供应商提
//供的DSP库头文件中提出来的能力参数
for( i = 0 ; i < VRG_GLOBAL_CFG_MAX_NUM_DSP ; i++ )
	for (j=0; j<CODEC_MAX_TYPES; j++)
		vrgEndptCap[i].codecCap[j] = gDspCfg.codecCapabilities[j];
	vrgEndptCap[i].vbdCap = gDspCfg.vbdCapability;
	vrgEndptCap[i].redLvl = gDspCfg.maxRfc2198Level;

//初始化环型缓冲对象,创建所需的信号量,并将各成员串起来
memCircBufInit()


lhapiInit( gDspCfg.isDistributed );
	gIsHauswareDistributed = isHauswareDistributed;//true,记载当前是分布式
	//根据是否分布式配置,来设置临界区使用哪种机制,如果是分布式的话
	//设置为信号量机制,如果是非分布式的话,设置为同时关断中断的自旋
	//锁机制(注释上说如果是非分布式的话,DSP数字采样是在中断上下文,
//DSP在处理时,中断需要关闭)
	lhapiCritSecInit();
	
	//创建一个DSP调度任务,用于控制DSP的hausware核的的任务可以触发运行
	lhapiThreadDispatchInit();

//调度处理任务,主要处理上层命令及DSP上报的事件
VrgDispatcherProcessInit()
	//创建两个队列,使用上面的环型缓冲对象机制
	vrgEptCmdQ = VrgQueueCreate( 20, sizeof(VRG_EPT_CMD*) );
	vrgEventQ = VrgQueueCreate( 150, sizeof(VRG_EVT) );
	
	//创建信号量,防止多任务调度
	bosSemCreate("vrgDispSem", 0, 1, &vrgDispSem)
	
	//核心任务函数,最后单拉文档去了解
bosTaskCreateEx( "VRGDISP", (8 * 1024), tskPrio, NULL, VrgDispatcherTaskMain , NULL, 0, &vrgDispProcessTaskId );

//创建所有endpt任务所需信号量
vrgCreateEndptSemaphores();
	bosSemCreate("vrgEptCmdSem", 0, 1, &vrgEptCmdSem);
	bosSemCreate("vrgEptConsoleCmdSem", 0, 1, &vrgEptConsoleCmdSem);
	bosSemCreate("vrgPstnSem", 0, 1, &vrgPstnSem);
	bosSemCreate("vrgMltSem", 0, 1, &vrgMltSem);
	bosSemCreate("vrgNTESem", 0, 1, &vrgNteSem);

//刷新SLIC升压模块
boardHalSlicHvgRefresh();
	//判断是否开启APM模块,当前已经记为开启
	( (boardHalProvGetFlags() & BP_FLAG_DSP_APMHAL_ENABLE) != 0)
		//根据SLIC类型重新触发升压模块
		return boardHalSlicHvgRefreshApm();

//初始化CAS控制任务,其中参数为回调函数,用于CAS控制任务将事件放入上面
//Dispatcher任务的事件队列中
casCtlInit( CasEventCallback )
	memset( &casState, 0, sizeof( casState ));
	casState.numChannels = CAS_CTL_CFG_NUM_ENDPTS;
	casState.callback    = callback;	//设置外部事件处理回调
	
	for( i = 0; i < CAS_CTL_CFG_NUM_ENDPTS; i++ )
		memset( &casState.service[i], 0, sizeof (CASSRV) );
		casState.service[i].callbackp = EventCallback;	//该回调函数最终调用callback
		//配置CAS线路,主要设置如下
		// casState.service[chan].localmem.channelinfo.castype = CASTYPE_FXO
		// casState.service[chan].localmem. channelinfo.channelnum = i
		// casState.service[chan].localmem. channelinfo.state = FXOBITS_IDLE
		// casState.service[chan].localmem. channelinfo.substate = FXO_STARTUP_IDLE;
		// casState.service[chan].localmem. channelinfo.statechange = VRG_FALSE;
		casCmd( i, (VRG_UINT16)CAS_CONFIG, (VRG_UINT32)CASTYPE_FXO, i );
	
	//分配CAS控制命令队列
	memCircBufAlloc(&casCtlCmdQ, 10*sizeof(CASCMD)
	
	bosSemCreate("casSynCmdSem", 0, 1, &casSynCmdSem);
	
	核心任务函数,最后单拉文档去了解
bosTaskCreateEx("HCAS", (8 * 1024), tskPrio, casTaskInitCB, casTaskMain, casTaskDeinitCB, 0, &casState.taskId );
	
	//线路诊断任务初始化
	mltInit( MltCallback );
		//TDP线路诊断任务初始化
		tpdCtlInit(tpdCtlCallback);
			// 将MltCallback回调函数注册,该回调函数仅启到中转的作用,而线路诊断
			//任务直接调用该回调,该回调再去调用mltCallback回调。
			tpdState.callback = callback;
			
			for (i=0; i<TPD_NUM_LINES; i++)
				tpdState.isEndptEnabled[i] = VRG_TRUE;
				hbRegisterPatient( HBSTATE_INACTIVE, HBPATIENT_TYPE_TPD, i, 
				&tpdState.hbId[i] );	//向监控注册TDP病人
			
			//创建TDP任务,其中tpdTaskInitCB仅仅创建一个消息队列,tpdTaskDeinitCB
			//销销消息队列,tdpTaskMain为主任务函数,详见《EDPT_410_tpdTaskMain》
			bosTaskCreateEx( "TPD",(8 * 1024), tskPrio, tpdTaskInitCB, tpdTaskMain,
				tpdTaskDeinitCB, 0, &tpdState.taskId );
		
//将MltCallback回调函数注册,该回调主要将线路诊断结果放置到vrgEventQ队列//中,有VrgDispatcherTaskMain任务统一处理。
		mltCallback = callback;
	
//DSP模块初始化
//资源管理回调函数RmEventCallback,该回调函数判断如果是HAPI_ICP_STATS_EVT事
//件(IDEL CPU 分析状态),则先停止ICP,然后打印出ICP统计信息,然后再复位ICP
//,否则为其它事件,则放到事件队列中,由Dispatcher任务去处理,看了一下在
//Dispatcher任务处理RM相关事件,仅仅是打印一些信息,没有做实际动作。
hdspInit( RmEventCallback, VRG_GLOBAL_CFG_MAX_NUM_DSP );
	hapiInit( eventCallback, dspNum );	//初始化DSP硬件,没代码
	hdspErrorInit( eventCallback );	//初始化DSP出错句柄模块,仅挂了一个回调

//查看是否要加载均衡器,当前为FALSE
Provision( NULL, EPPROV_LoadBalancing, &provItem );

//开启动态加载均衡器,当前应该是不支持的,里面函数为空
xdrvDlbEnable( dlbDrv, provItem );

//通知DSP,IPC已经可用,里面没代码
for( i = 0 ; i < VRG_GLOBAL_CFG_MAX_NUM_DSP ; i++ )
	boardHalIpcReady( i );

//给定时器任务注册定时器超时处理回调lhapi_ProcessEntrySync,这函数没代码,不清
//楚做什么用
boardHalDspRegisterCallback( lhapi_ProcessEntrySync );

//启动5MS的定时器任务,这个定时器在上面很早就建立了,在这里才被触发
boardHalDspTaskStartTimer();

for ( j = 0 ; j < VRG_GLOBAL_CFG_MAX_NUM_DSP ; j++ )	//当前DSP总数为1
	for ( i = 0; i < VRG_ENDPT_CFG_NUM_CNX/VRG_GLOBAL_CFG_MAX_NUM_DSP; i++ )
		VRG_BOOL  bLiteWeightCnx = VRG_FALSE;	//标记非轻量级资源
if(i>=((VRG_ENDPT_CFG_NUM_CNX-VRG_ENDPT_CFG_NUM_LITE_CNX)/VRG_GLO	BAL_CFG_MAX_NUM_DSP) )
{
	bLiteWeightCnx = VRG_TRUE;		//如果i值得到轻量级索引,则更新标记
}

InitCnxVhd( &vrgCnxState[i],  bLiteWeightCnx,  country );
	//根据是否轻量级CNX确定VHD类型
	if ( bLiteWeightCnx )
		vhdType = HAPI_CONFERENCE_VHD;
	else
		vhdType = HAPI_GATEWAY_VHD;
	
	//分别为
	//DTMF CID特定参数
	//最小能量值检测
	//外部进来的声音
	pteAdmin = HAPI_PTE_ADM_GENERAL;	
	Provision(NULL, EPPROV_PteMinDetectPower, &minDetectPower); 
	Provision(NULL, EPPROV_PveEgressVolume, &pveEgressVolume);
	
	//创建一个VHD连接,其中CnxVhdEventCallback回调用于DSP
	//向外发向数据包(RTP/RTCP/T38),并上报一些资源相关事件(如传真
//信号等)。该回调最后调用的是上面传来的endpointdrvPacketCB回
//调来发送数据包,并把事件存入事件队列,让DISP任务去
//来针对CNX相关事件进行处理。CnxVhdEventCallback后面单独
	//拉个文档来写
	hdspVhdOpen( vhdType, CnxVhdEventCallback, cnx->dspNum,
						pteAdmin, minDetectPower, pveEgressVolume,
						&(cnx->vhdhdl) );
		//最小能最值检测校正
pteMinDetectPower=hdspVhdAdjustIngressPowerLevel( pteMinDetectPower*10 ) / 10;

//在DSP开启一个通道,无代码
*vhdhdl = hapiOpen( vhdType, callbackp, dspNum )

//根据当前VHD类型为会议或网关类型,来向DSP设置detectAdmin、
// minDetectPower、pveEgressVolume,这里没粘代码,都是HAPI不
//开源代码,没写
				
				//获取网络寄存器配置
				hdspSendCmdData( cnx->vhdhdl, HAPINET_CONFIG_GETREGS, HSCMDRESP,
										sizeof( netregs ), &netregs);
				
				//去除DTMF中继传输
				netregs.hsxPtePacketVoiceOptions &= (~HSNET_PTE_OPTION_DIG_RELAY);
				//去除DTMF事件上报
				netregs.hsxPtePacketVoiceOptions &= (~HSNET_PTE_OPTION_DIG_EVT);
				//去除自切换
				netregs.hsxNetOptions&= ~(HSNET_NET_OPTION_AUTO_ENC_SWITCH |
										HSNET_NET_OPTION_ECAN_CONTROL |
										HSNET_NET_OPTION_FAXRELAY);
				//去除DTMF事件上报
netregs.hsxPteCallSetupOptions   &= (~HSNET_PTE_OPTION_DIG_EVT);
//开启一些MODEM、自定义声音检测
				netregs.hsxCallDOptions          |= ( HSNET_CDIS_OPTION_V18ACTIVE |
											HSNET_CDIS_OPTION_BELL103ACTIVE |
										HSNET_CDIS_OPTION_CUSTOMTONEACTIVE );
				//使能上面的配置项
				cnx->netRegs = netregs;
				hdspSendCmdData( cnx->vhdhdl, HAPINET_CONFIG_SETREGS,
								HSCMDEXTDATA_SYNC, sizeof( netregs ), &netregs);
	
//如果DSP支持T38						 if(vrgEndptCap[cnx->dspNum].codecCap[CODEC_T38]==CODEC_SUPPORTED )
		//设置T38冗余
		SetT38EcMode( cnx, &(cnx->t38param) );
		//设置T38服务发送传真事件
		hdspSendCmd( cnx->vhdhdl, HAPINET_FAXR_SETREG1, HSCMDDATA,
			OFFSETOF( HSZFAXRREGS, hsxfaxrsendevents ), 1 );
		
		//设置T38服务自定义寄存器
		hdspSendCmd( cnx->vhdhdl, HAPINET_FAXR_SETREG1, HSCMDDATA,
		OFFSETOF( HSZFAXRREGS, hsxcustomfeatures ), cnx->faxrCustomReg );
	
	//配置在以下事件检测到时自动切到VBD
	hdspSendCmdAsync( cnx->vhdhdl, HAPI_NET_VBD_AUTOSWITCH_MASK,
		HSCMDDATA,
		(HAPI_NET_AUTOSWITCH_MASK_V18_BAUDOT|
HAPI_NET_AUTOSWITCH_MASK_V18_PREAMBLE),
0 );
				
				cnx->bLiteWeight = bLiteWeightCnx;	//备份当前轻量级标记
				
SetVoiceMode( cnx, VM_IDLE );
	//如果之前是空闲模式,或者新值是空闲模式,复位
	//VBD状态
	if (( mode == VM_IDLE ) || ( cnx->voiceMode == VM_IDLE ))
		ResetVBDataState( &cnx->vbData );
	vhdMode = NETMODE_IDLE;	//这里switch根据入参仅执行这行
	//向DSP设置通道模式
	hdspVhdSetMode( cnx->vhdhdl, vhdMode, initMode );
	cnx->voiceMode = mode;	//保存模式

//向监控任务托管一个病号,病号初始值为死去
hbRegisterPatient( HBSTATE_INACTIVE, HBPATIENT_TYPE_CNX,
		HBPATIENT_UNKNOWN_ENDPT, &cnx->cnxStateHBId );

//设置JITTER BUFFER
hdspVhdSetJitterBuffer( cnx->vhdhdl, cnx->vrgVoiceJBFixed,
		cnx->vrgVoiceJBMin, cnx->vrgVoiceJBMax,
		cnx->vrgVoiceJBTarget, cnx->vrgDataJBTarget, cnx->ajcCustomReg );
	
	if ( vrgEndptGetNumFxoEndpoints() > 0 )	//如果存在FXO口
		//PSTN控制任务初始化,其中回调函数PstnEventCallback把FXO口相关处理信息
		//发送到消息处理队列vrgEventQ中,由消息处理任务VrgDispatcherTaskMain来处
		//理。
		pstnCtlInit( endptConfig.country, PstnEventCallback );
			//保存PSTN事件回调及国家码
			pstnCtlState.callback = callback;
			pstnCtlState.country = country;
			
			//复位状态信息
			for(i = 0; i < PSTN_CTL_MAX_CHANNELS; i++)
				pstnCtlState.chanState[i].state = PSTN_CTL_CHAN_STATE_IDLE;
				pstnCtlState.chanState[i].vhdHdl = 0xFF;
				pstnCtlState.chanState[i].timeoutCount = 0;
			
			//创建PSTN事件信号量
			bosSemCreate("pstnEvtQSem", 0, 1, &pstnEvtQSem);
			
			//创建PSTN控制事件消息队列
			pstnCtlState.evtQ = eventQueueCreate( PSTN_CTL_MAX_CHANNELS * 2 );
			
			//创建PSTN任务,详见《ENDPT_410_pstnCtlTaskMain》
			bosTaskCreateEx( "PSTN", (8 * 1024), PSTN_CTL_CFG_TASK_PRIORITY, NULL,
			pstnCtlTaskMain, NULL, 0, &pstnCtlState.taskId ))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值