⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asyin.c.demo

📁 170话费查询系统
💻 DEMO
📖 第 1 页 / 共 2 页
字号:
/********************************************************
 *			Dial into D/300SC-E1 Demo program for Windows NT
 *			Dialogic Corporation, Beijing
 *			All Rights Reserved
 *			JUNE, 1997
 *			Environment: Windows NT 3.51/4.0
 *			Asynchronous Mode
 *			Compiler: Visual C++ 4.0
 ********************************************************/
#include<windows.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<time.h>
#include<fcntl.h>
#include<srllib.h>
#include<dxxxlib.h>
#include<dtilib.h>
#include<sctools.h>

#define MAXCHAN  30   //最大通道数 
#define DNIS_LEN  3   //The Dialed Number Identification Number Service length, can change
                      //内部电话号码长度
#define ANI_LEN   7   //The Automatic Number identification length, can change
                      //主叫号码长度。

#define DEBUG 0
#define PLAY_TIME 20  //seconds to play sample.vox after connection


char *voxchannels[] = {
   "dxxxB1C1" , "dxxxB1C2" , "dxxxB1C3" , "dxxxB1C4",
   "dxxxB2C1" , "dxxxB2C2" , "dxxxB2C3" , "dxxxB2C4",
   "dxxxB3C1" , "dxxxB3C2" , "dxxxB3C3" , "dxxxB3C4",
   "dxxxB4C1" , "dxxxB4C2" , "dxxxB4C3" , "dxxxB4C4",
   "dxxxB5C1" , "dxxxB5C2" , "dxxxB5C3" , "dxxxB5C4",
   "dxxxB6C1" , "dxxxB6C2" , "dxxxB6C3" , "dxxxB6C4",
   "dxxxB7C1" , "dxxxB7C2" , "dxxxB7C3" , "dxxxB7C4",
   "dxxxB8C1" , "dxxxB8C2" , 
	NULL,
};

char *dtichannels[] = {
   "dtiB1T1" , "dtiB1T2" , "dtiB1T3" , "dtiB1T4",
   "dtiB1T5" , "dtiB1T6" , "dtiB1T7" , "dtiB1T8",
   "dtiB1T9" , "dtiB1T10", "dtiB1T11", "dtiB1T12",
   "dtiB1T13", "dtiB1T14", "dtiB1T15", "dtiB1T16",
   "dtiB1T17", "dtiB1T18", "dtiB1T19", "dtiB1T20",
   "dtiB1T21", "dtiB1T22", "dtiB1T23", "dtiB1T24",
   "dtiB1T25", "dtiB1T26", "dtiB1T27", "dtiB1T28",
   "dtiB1T29", "dtiB1T30", 
	NULL,
};

typedef struct channel{
	int  vox;	//voice handle 语音卡端口句柄
	int  dti;	//dti handle   数字中继端口句柄
	char voxname[20];
	char dtiname[20];
	char dnis[20];
	char ani[20];
	int  state;
	int  number;
	time_t start_t;
} CHANNEL;
CHANNEL dev[MAXCHAN];

/* Defines for states */
#define ST_SZ_ACK    1
#define ST_MFC       2
#define ST_PLAYFILE  3        	//播放语音
#define ST_HUNGUP    4        	//用户挂机

/* Other defines */
DV_TPT  play_tpt[2];		// DV_TPT	终止条件表
DX_IOTT play_iott;		// DX_IOTT	数据传输表(语音播放,或者录音)
DX_XPB xpb;     /*        I/O transfer parameter block */

int EventType; //Dialogic Event Type;

/* voice file handles */
//extern int r2_creatfsig();	// 定义语音卡端口,使之能够监听来自交换机的R2MF前向信号(Forward 
				// signal
//extern int r2_playbsig();	// R2MF play backward signal; 发送一个(双音)反向信号给交换机。
				// This function calls the dx_blddt(? function to 
				// create the template. User-defined tone IDs 101 
				// through 115 are used by this function. 

/// add by chenxu 测试语音卡读键功能
int digit_handler();
DV_TPT tpt[3];
DV_DIGIT digp[256];

// add complete

/* Function Declaration */
int  process_event(int);
int  check_event(int,int);
int  end_prog(void);
int  promptfh;
int  dt_mfc(int);
int  dt_playf(int);
int  dt_fwaoff(int);
int  dt_fwaon(int);
int  dt_bwaon(int);
int  dt_pltone(int);
int  chan_init(int);
int  chktmout();
int  printts(int);
void wait_event();
void printstart(void);

/* Structure for look up table */
typedef struct 				//状态机表
{
	int current_state;		//当前状态
	int event;			//事件
	int next_state;			//next 状态
	int (*funcptr)(int);		//事件处理函数指针
}TABLE;

#define TABLE_SIZE   4
TABLE table[TABLE_SIZE]=
      {/*current_state    event        next_stat    function */
      { ST_SZ_ACK,        DTMM_AOFF,   ST_MFC,      dt_fwaoff },
      { ST_MFC,           DE_TONEON,   ST_MFC,      dt_mfc    },
      { ST_MFC,           TM_TONE,     ST_MFC,      dt_pltone },
      { ST_PLAYFILE,      TM_EOD,      ST_SZ_ACK,   dt_bwaon  },
};


char myrecv[100];

/******************************************************************************
* Name: ReadUserKey()
* Function: To show the RX and TX bits.
*
******************************************************************************/

int  ReadUserKey(int i)
{
	int numdigs, cnt;
    int TONGBU = 1;

   printf("\n通道%s进入读键状态...",dev[i].voxname);
   dx_clrtpt(tpt,3);

   tpt[0].tp_type   = IO_CONT;
   tpt[0].tp_termno = DX_MAXDTMF;       /* Maximum number of digits */
   tpt[0].tp_length = 4;                /* terminate on 4 digits */
   tpt[0].tp_flags  = TF_MAXDTMF;       /* terminate if already in buf. */
   
   tpt[1].tp_type   = IO_CONT;
   tpt[1].tp_termno = DX_LCOFF;         /* LC off termination */
   tpt[1].tp_length = 3;                /* Use 30 ms (10 ms resolution                                         * timer) */
   tpt[1].tp_flags  = TF_LCOFF|TF_10MS; /* level triggered, clear history,
                                         * 10 ms resolution */

   tpt[2].tp_type   = IO_EOT;
   tpt[2].tp_termno = DX_MAXTIME;       /* Function Time */
   tpt[2].tp_length = 100;              /* 10 seconds (100 ms resolution                                        * timer) */
   tpt[2].tp_flags  = TF_MAXTIME;       /* Edge-triggered */


   /* clear previously entered digits */
   if (dx_clrdigbuf(dev[i].vox) == -1) {
          /* process error */
   }
   
   //读键
   if (TONGBU) {	//同步
		if ((numdigs = dx_getdig(dev[i].vox,tpt, &digp[i], EV_SYNC)) == -1) {
			 printf( "The last error on the device was '%s'\n", ATDV_ERRMSGP( dev[i].vox));
		}
		for (cnt=0; cnt < numdigs; cnt++) {
			printf("\nDigit received = %c, digit type = %d",	digp[i].dg_value[cnt], digp[i].dg_type[cnt]);
		}
   }
   else				//异步 
   {			
	   if (dx_getdig(dev[i].vox, tpt, &digp[i], EV_ASYNC) == -1) {
          printf( "The last error on the device was '%s'\n", ATDV_ERRMSGP( dev[i].vox));
       }
   }

}

/***************************************************************************
 *        NAME: void sysinit()
 * DESCRIPTION: Start System  设备初始化
 ***************************************************************************/
void sysinit(void)
{
	int mode;
	int i;
   /* Set the Device to Polled Mode  设置语音卡为轮询问模式*/
   mode = SR_POLLMODE;
   if (sr_setparm(SRL_DEVICE,SR_MODEID,&mode )==-1) {  //sr_setparm( ) function allows the application to set 
   							//the value of an SRL(Standard Runtime Library) parameter
		printf("sr_setparm()\n");
		exit(0);
   }
	promptfh=dx_fileopen("sample.vox",O_RDONLY|O_BINARY);
	if(promptfh<=0){
		printf("File SAMPLE.VOX not found, please  copy it to the current directory.\n");
		exit(0);
	}
	for (i = 0; i < MAXCHAN; i++) {
		//打开语音卡端口
		strcpy(dev[i].voxname,voxchannels[i]);		
		if ((dev[i].vox = dx_open(dev[i].voxname, 0)) == -1) {
			printf("%s: Error opening this channel\n",dev[i].voxname);
			exit(1);
		}
		//打开中继卡端口
		strcpy(dev[i].dtiname,dtichannels[i]);
		if ((dev[i].dti = dt_open(dev[i].dtiname, 0)) == -1) {
			printf("%s: Error opening this channel\n",dev[i].dtiname);
			exit(1);
		}
		//
		//连接语音卡和中继卡两种设备。这里涉及到 SCBus,SCBus是Dialogic公司的一种硬件
		//技术,用于连接不同的DEVICE. D300/SC-E1卡其实就是用SCBus连接一个30路语音卡
		//和一个30口中继卡为一体的产品。
		// nr_nr_scunroute()函数的作用在于断开 dit 和 voice之间的连接。
		if(nr_scunroute(dev[i].dti,SC_DTI,dev[i].vox,SC_VOX,SC_FULLDUP)==-1){
			printf("%s <=== UnRoute Failed ===> %s\n",dev[i].voxname,dev[i].dtiname);
			exit(1);
		}
		//重建 dti 和voice之间的连接。(全双工连接)
		if(nr_scroute(dev[i].dti,SC_DTI,dev[i].vox,SC_VOX,SC_FULLDUP)==-1){
			printf("%s <=== Route Failed ===> %s\n",dev[i].voxname,dev[i].dtiname);
			exit(1);
		}
		//语音卡要监听来自交换机的前向信号( R2MF, forward signal),必须调用 r2_createfsig
		//建立一个模板(template),指定监听哪些signal, dx_deltons()则是清除这个template.
		if(dx_deltones(dev[i].vox)==-1){
			printf("%s: dx_deltones()\n",dev[i].voxname);
			exit(1);
		}
		//重建template,指定端口监听所有的(forward signal)
		if(r2_creatfsig(dev[i].vox,R2_ALLFSIG)==-1){
			printf("%s: r2_creatfsig()\n",dev[i].voxname);
			exit(1);
		}
		//数字设备上有一个传输信号字节Bitmask,用于表示事件,其bitmask有如下
		/* DTB_AON - "A" signaling bit on 
		   DTB_AOFF - "A" signaling bit off 
		   DTB_BON - "B" signaling bit on 
		   DTB_BOFF - "B" signaling bit off 
		   DTB_CON - "C" signaling bit on (E-1 only) 
		   DTB_COFF - "C" signaling bit off (E-1 only) 
		   DTB_DON - "D" signaling bit on (E-1 only) 
		   DTB_DOFF - "D" signaling bit off (E-1 only) */		   
		if(dt_settssigsim(dev[i].dti,DTB_AON|DTB_BOFF|DTB_CON|DTB_DON)==-1){
			printf("dt_settssig() in dt_onhook(1)\n");
			exit(1);
		}
		
		chan_init(i);
		/*chan_init(){
			if(DEBUG) printf("%s: In chan_init()\n",dev[i].voxname);
			strcpy(dev[i].dnis,"");
			strcpy(dev[i].ani,"");
			dev[i].number=0;
			dev[i].state=ST_SZ_ACK;
			dt_settssigsim(dev[i].dti,DTB_AON|DTB_BOFF|DTB_CON|DTB_DON);
		}
		*/
		//接收信号事件,对于SC设备 AON和AOFF同时要设置。
		if(dt_setevtmsk(dev[i].dti,DTG_SIGEVT,DTMM_AON|DTMM_AOFF,DTA_SETMSK)==-1){
			printf("%s: dt_setevtmsk()\n",dev[i].dtiname);
			exit(1);
		}
		printf(".");
	}
	printf("\nAll Channels opened, dial in now.\n");
}

/***************************************************************************
 * Name:   int dx_intro( channum )
 * Des:    Set up play_iott and play_tpt's and Initiate the Play-Back and update
 *         the child window.
 * Input : int channel number;   
 * Output: Starts the play-back        
 ***************************************************************************/
int dt_playf(int i)
{
	
	if(DEBUG) printf("%s: In dt_playf()\n",dev[i].voxname);
	memset(play_tpt,0,sizeof(play_tpt));
   // Terminate Play on Receiving any DTMF tone 终止条件1:用户按任何键。
   play_tpt[0].tp_type = IO_CONT;
   play_tpt[0].tp_termno = DX_MAXDTMF;
   play_tpt[0].tp_length = 1;
   play_tpt[0].tp_flags = TF_MAXDTMF;

   // Terminate  on MAXTIME 
   play_tpt[1].tp_type = IO_EOT;
   play_tpt[1].tp_termno = DX_MAXTIME;
   play_tpt[1].tp_length = PLAY_TIME * 10;
   play_tpt[1].tp_flags = TF_MAXTIME;

	play_iott.io_type=IO_DEV|IO_LINK;
	play_iott.io_bufp=0;
	play_iott.io_offset=0;
	play_iott.io_length=-1;
	play_iott.io_fhandle=promptfh;
	play_iott.io_nextp=&play_iott;
	
    xpb.wFileFormat = FILE_FORMAT_VOX;
	xpb.wDataFormat = DATA_FORMAT_DIALOGIC_ADPCM;
	xpb.nSamplesPerSec = DRT_8KHZ;
	xpb.wBitsPerSample = 4;

   dx_clrdigbuf(dev[i].vox);
	/* Play VOX File on D/4x Channel, Normal Play Back */
   if (dx_playiottdata(dev[i].vox,&play_iott,play_tpt,&xpb,/*PM_TONE|*/EV_ASYNC)==-1 ){
      printf("%s: %s in dx_play()\n",dev[i].voxname,ATDV_ERRMSGP(dev[i].vox));
		return -1;
   }
	printf("%s: playing...\n",dev[i].voxname);
	return 0;
}

/******************************************************************************
* Name:  check_event()
* Input: int channel number
*                int voice/msi events
* Des:   It checks the current state of a channel, look up in the state 
*                for the next state of the channel depanding on the event received
*                sets the next state and initiates the apprpriate func.
*
*
*******************************************************************************/
int check_event(int channel, int event)
{
   int i;
   int (*func_ptr)(int);

   //首先检测挂机事件(Hangup detection is the first priority )
   if((EventType==DTEV_SIG)&&(event==DTMM_AON)) {
   		// Abit跳1,表明有一方挂断,如果当前状态是ST_SZ_ACK,表明是语音卡主动挂机
   		// 通话结束工作留给交换机去完成,语音卡回到初始状态。
   		// 如果是交换机先挂,则要返回一个用户断也挂的backward signal,然后才能回到
   		// 初始状态,这个工作则是由  dt_fwaon()函数完成的。
		if(dev[channel].state==ST_SZ_ACK) chan_init(channel);
		else dt_fwaon(channel);
      return 0;
   }

   for (i=0; i< TABLE_SIZE; i++)
      if((dev[channel].state==table[i].current_state) && 
				    (table[i].event==event)){
			func_ptr = table[i].funcptr;
			if(DEBUG) printf("%s: Current State =%d, Event Function Number is (%d)\n",dev[channel].voxname,dev[channel].state,i);
			dev[channel].state = table[i].next_state;
			return (*func_ptr)(channel);
			break;
      }
	return -1;
}


/****************************************************************************
* Name:   process_event
* Input:  int channel number
* output: returns a voice event
* Des:    It retreives voice events on a channel by calling sr_getevttype()
*                 sr_getevtdatap() and returns it to the wait_event()
*
*
*****************************************************************************/
int process_event(int channel)
{
	int index;
	int *datap;
   long term;
   DX_CST *cstp;

   int chfd;
   int cnt, numdigs;
   
   //EventType = sr_getevttype(dev[channel].vox);
   EventType = sr_getevttype();   //原来的语句
   switch(EventType){
   	case DTEV_SIG: //DTI 上的信号事件,datap是事件的bitmask(ABCD);
		datap=(int*)sr_getevtdatap();
		for(index=0;index<4;index++){
			switch (*datap&(0x1111<<index)){
			case DTMM_AON:
				//if(DEBUG) printf("%s: EVENT DATA: DTMM_AON\n",dev[channel].voxname);
				return DTMM_AON;
				break;
			case DTMM_AOFF:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_AOFF\n",dev[channel].voxname);
				return DTMM_AOFF;
				break;
			case DTMM_BON:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_BON\n",dev[channel].voxname);
				return DTMM_BON;
				break;
			case DTMM_BOFF:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_BOFF\n",dev[channel].voxname);
				return DTMM_BOFF;
				break;
			case DTMM_CON:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_CON\n",dev[channel].voxname);
				return DTMM_CON;
				break;
			case DTMM_COFF:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_COFF\n",dev[channel].voxname);
				return DTMM_COFF;
				break;
			case DTMM_DON:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_DON\n",dev[channel].voxname);
				return DTMM_DON;
				break;
			case DTMM_DOFF:
				if(DEBUG) printf("%s: EVENT DATA: DTMM_DOFF\n",dev[channel].voxname);
				return DTMM_DOFF;
				break;
			}
		}
		break; 
	case TDX_CST: //Vocie上的状态事件
		if(DEBUG) printf("%s: EVENT TYPE: TDX_CST\n",dev[channel].voxname);
		cstp=(DX_CST*)sr_getevtdatap();
		switch (cstp->cst_event){
		case DE_TONEON:
			//if(DEBUG) printf("%s: EVENT DATA: DE_TONEON\n",dev[channel].voxname);
			return DE_TONEON;
			break;
		case DE_TONEOFF:
			//if(DEBUG) printf("%s: EVENT DATA: DE_TONEOFF\n",dev[channel].voxname);
			return -1;  //
			break;
		}
	case TDX_GETDIG:
		    // ###
			printf("通道%s读键完\n",dev[channel].voxname);
			numdigs = strlen(digp[channel].dg_value);
			for(cnt=0; cnt < numdigs; cnt++) {
				printf("\nDigit received = %c, digit type = %d", digp[channel].dg_value[cnt], digp[channel].dg_type[cnt]);
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -