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

📄 isdn_tty.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		return;	if (info->isdn_driver < 0) {		info->xmit_count = 0;		return;	}	skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;#ifdef CONFIG_ISDN_AUDIO	if (info->vonline & 2)		audio_len = buflen * voice_cf[info->emu.vpar[3]];	else		audio_len = 0;	skb = dev_alloc_skb(skb_res + buflen + audio_len);#else	skb = dev_alloc_skb(skb_res + buflen);#endif	if (!skb) {		printk(KERN_WARNING		       "isdn_tty: Out of memory in ttyI%d senddown\n",		       info->line);		return;	}	skb_reserve(skb, skb_res);	memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);	info->xmit_count = 0;#ifdef CONFIG_ISDN_AUDIO	if (info->vonline & 2) {		/* For now, ifmt is fixed to 1 (alaw), since this		 * is used with ISDN everywhere in the world, except		 * US, Canada and Japan.		 * Later, when US-ISDN protocols are implemented,		 * this setting will depend on the D-channel protocol.		 */		int ifmt = 1;		/* voice conversion/decompression */		switch (info->emu.vpar[3]) {			case 2:			case 3:			case 4:				/* adpcm, compatible to ZyXel 1496 modem				 * with ROM revision 6.01				 */				audio_len = isdn_audio_adpcm2xlaw(info->adpcms,								  ifmt,								  skb->data,						    skb_put(skb, audio_len),								  buflen);				skb_pull(skb, buflen);				skb_trim(skb, audio_len);				break;			case 5:				/* a-law */				if (!ifmt)					isdn_audio_alaw2ulaw(skb->data,							     buflen);				break;			case 6:				/* u-law */				if (ifmt)					isdn_audio_ulaw2alaw(skb->data,							     buflen);				break;		}	}#endif                          /* CONFIG_ISDN_AUDIO */	if (info->emu.mdmreg[REG_T70] & BIT_T70) {		/* Add T.70 simplified header */		if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT)			memcpy(skb_push(skb, 2), "\1\0", 2);		else			memcpy(skb_push(skb, 4), "\1\0\1\0", 4);	}	skb_queue_tail(&info->xmit_queue, skb);}/************************************************************ * * Modem-functions * * mostly "stolen" from original Linux-serial.c and friends. * ************************************************************//* The next routine is called once from within timer-interrupt * triggered within isdn_tty_modem_ncarrier(). It calls * isdn_tty_modem_result() to stuff a "NO CARRIER" Message * into the tty's flip-buffer. */static voidisdn_tty_modem_do_ncarrier(unsigned long data){	modem_info *info = (modem_info *) data;	isdn_tty_modem_result(RESULT_NO_CARRIER, info);}/* Next routine is called, whenever the DTR-signal is raised. * It checks the ncarrier-flag, and triggers the above routine * when necessary. The ncarrier-flag is set, whenever DTR goes * low. */static voidisdn_tty_modem_ncarrier(modem_info * info){	if (info->ncarrier) {		info->nc_timer.expires = jiffies + HZ;		info->nc_timer.function = isdn_tty_modem_do_ncarrier;		info->nc_timer.data = (unsigned long) info;		add_timer(&info->nc_timer);	}}/* * return the usage calculated by si and layer 2 protocol */intisdn_calc_usage(int si, int l2){	int usg = ISDN_USAGE_MODEM;#ifdef CONFIG_ISDN_AUDIO	if (si == 1) {		switch(l2) {			case ISDN_PROTO_L2_MODEM: 				usg = ISDN_USAGE_MODEM;				break;#ifdef CONFIG_ISDN_TTY_FAX			case ISDN_PROTO_L2_FAX: 				usg = ISDN_USAGE_FAX;				break;#endif			case ISDN_PROTO_L2_TRANS: 			default:				usg = ISDN_USAGE_VOICE;				break;		}	}#endif	return(usg);}/* isdn_tty_dial() performs dialing of a tty an the necessary * setup of the lower levels before that. */static voidisdn_tty_dial(char *n, modem_info * info, atemu * m){	int usg = ISDN_USAGE_MODEM;	int si = 7;	int l2 = m->mdmreg[REG_L2PROT];	isdn_ctrl cmd;	ulong flags;	int i;	int j;	for (j = 7; j >= 0; j--)		if (m->mdmreg[REG_SI1] & (1 << j)) {			si = bit2si[j];			break;		}	usg = isdn_calc_usage(si, l2);#ifdef CONFIG_ISDN_AUDIO	if ((si == 1) && 		(l2 != ISDN_PROTO_L2_MODEM)#ifdef CONFIG_ISDN_TTY_FAX		&& (l2 != ISDN_PROTO_L2_FAX)#endif		) {		l2 = ISDN_PROTO_L2_TRANS;		usg = ISDN_USAGE_VOICE;	}#endif	m->mdmreg[REG_SI1I] = si2bit[si];	save_flags(flags);	cli();	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);	if (i < 0) {		restore_flags(flags);		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);	} else {		info->isdn_driver = dev->drvmap[i];		info->isdn_channel = dev->chanmap[i];		info->drv_index = i;		dev->m_idx[i] = info->line;		dev->usage[i] |= ISDN_USAGE_OUTGOING;		info->last_dir = 1;		strcpy(info->last_num, n);		isdn_info_update();		restore_flags(flags);		cmd.driver = info->isdn_driver;		cmd.arg = info->isdn_channel;		cmd.command = ISDN_CMD_CLREAZ;		isdn_command(&cmd);		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETEAZ;		isdn_command(&cmd);		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETL2;		info->last_l2 = l2;		cmd.arg = info->isdn_channel + (l2 << 8);		isdn_command(&cmd);		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETL3;		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);#ifdef CONFIG_ISDN_TTY_FAX		if (l2 == ISDN_PROTO_L2_FAX) {			cmd.parm.fax = info->fax;			info->fax->direction = ISDN_TTY_FAX_CONN_OUT;		}#endif		isdn_command(&cmd);		cmd.driver = info->isdn_driver;		cmd.arg = info->isdn_channel;		sprintf(cmd.parm.setup.phone, "%s", n);		sprintf(cmd.parm.setup.eazmsn, "%s",			isdn_map_eaz2msn(m->msn, info->isdn_driver));		cmd.parm.setup.si1 = si;		cmd.parm.setup.si2 = m->mdmreg[REG_SI2];		cmd.command = ISDN_CMD_DIAL;		info->dialing = 1;		info->emu.carrierwait = 0;		strcpy(dev->num[i], n);		isdn_info_update();		isdn_command(&cmd);		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);	}}/* isdn_tty_hangup() disassociates a tty from the real * ISDN-line (hangup). The usage-status is cleared * and some cleanup is done also. */voidisdn_tty_modem_hup(modem_info * info, int local){	isdn_ctrl cmd;	if (!info)		return;#ifdef ISDN_DEBUG_MODEM_HUP	printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);#endif	info->rcvsched = 0;	isdn_tty_flush_buffer(info->tty);	if (info->online) {		info->last_lhup = local;		info->online = 0;		isdn_tty_modem_result(RESULT_NO_CARRIER, info);	}#ifdef CONFIG_ISDN_AUDIO	info->vonline = 0;#ifdef CONFIG_ISDN_TTY_FAX	info->faxonline = 0;	info->fax->phase = ISDN_FAX_PHASE_IDLE;#endif	info->emu.vpar[4] = 0;	info->emu.vpar[5] = 8;	if (info->dtmf_state) {		kfree(info->dtmf_state);		info->dtmf_state = NULL;	}	if (info->silence_state) {		kfree(info->silence_state);		info->silence_state = NULL;	}	if (info->adpcms) {		kfree(info->adpcms);		info->adpcms = NULL;	}	if (info->adpcmr) {		kfree(info->adpcmr);		info->adpcmr = NULL;	}#endif	if ((info->msr & UART_MSR_RI) &&		(info->emu.mdmreg[REG_RUNG] & BIT_RUNG))		isdn_tty_modem_result(RESULT_RUNG, info);	info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);	info->lsr |= UART_LSR_TEMT;	if (info->isdn_driver >= 0) {		if (local) {			cmd.driver = info->isdn_driver;			cmd.command = ISDN_CMD_HANGUP;			cmd.arg = info->isdn_channel;			isdn_command(&cmd);		}		isdn_all_eaz(info->isdn_driver, info->isdn_channel);		info->emu.mdmreg[REG_RINGCNT] = 0;		isdn_free_channel(info->isdn_driver, info->isdn_channel, 0);	}	info->isdn_driver = -1;	info->isdn_channel = -1;	if (info->drv_index >= 0) {		dev->m_idx[info->drv_index] = -1;		info->drv_index = -1;	}}/* * Begin of a CAPI like interface, currently used only for  * supplementary service (CAPI 2.0 part III) */#include "avmb1/capicmd.h"  /* this should be moved in a common place */intisdn_tty_capi_facility(capi_msg *cm) {	return(-1); /* dummy */}/* isdn_tty_suspend() tries to suspend the current tty connection */static voidisdn_tty_suspend(char *id, modem_info * info, atemu * m){	isdn_ctrl cmd;		int l;	if (!info)		return;#ifdef ISDN_DEBUG_MODEM_SERVICES	printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);#endif	l = strlen(id);	if ((info->isdn_driver >= 0)) {		cmd.parm.cmsg.Length = l+18;		cmd.parm.cmsg.Command = CAPI_FACILITY;		cmd.parm.cmsg.Subcommand = CAPI_REQ;		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */		cmd.parm.cmsg.para[1] = 0;		cmd.parm.cmsg.para[2] = l + 3;		cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */		cmd.parm.cmsg.para[4] = 0;		cmd.parm.cmsg.para[5] = l;		strncpy(&cmd.parm.cmsg.para[6], id, l);		cmd.command = CAPI_PUT_MESSAGE;		cmd.driver = info->isdn_driver;		cmd.arg = info->isdn_channel;		isdn_command(&cmd);	}}/* isdn_tty_resume() tries to resume a suspended call * setup of the lower levels before that. unfortunatly here is no * checking for compatibility of used protocols implemented by Q931 * It does the same things like isdn_tty_dial, the last command * is different, may be we can merge it. */static voidisdn_tty_resume(char *id, modem_info * info, atemu * m){	int usg = ISDN_USAGE_MODEM;	int si = 7;	int l2 = m->mdmreg[REG_L2PROT];	isdn_ctrl cmd;	ulong flags;	int i;	int j;	int l;	l = strlen(id);	for (j = 7; j >= 0; j--)		if (m->mdmreg[REG_SI1] & (1 << j)) {			si = bit2si[j];			break;		}	usg = isdn_calc_usage(si, l2);#ifdef CONFIG_ISDN_AUDIO	if ((si == 1) && 		(l2 != ISDN_PROTO_L2_MODEM)#ifdef CONFIG_ISDN_TTY_FAX		&& (l2 != ISDN_PROTO_L2_FAX)#endif		) {		l2 = ISDN_PROTO_L2_TRANS;		usg = ISDN_USAGE_VOICE;	}#endif	m->mdmreg[REG_SI1I] = si2bit[si];	save_flags(flags);	cli();	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);	if (i < 0) {		restore_flags(flags);		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);	} else {		info->isdn_driver = dev->drvmap[i];		info->isdn_channel = dev->chanmap[i];		info->drv_index = i;		dev->m_idx[i] = info->line;		dev->usage[i] |= ISDN_USAGE_OUTGOING;		info->last_dir = 1;//		strcpy(info->last_num, n);		isdn_info_update();		restore_flags(flags);		cmd.driver = info->isdn_driver;		cmd.arg = info->isdn_channel;		cmd.command = ISDN_CMD_CLREAZ;		isdn_command(&cmd);		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETEAZ;		isdn_command(&cmd);		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETL2;		info->last_l2 = l2;		cmd.arg = info->isdn_channel + (l2 << 8);		isdn_command(&cmd);		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETL3;		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);		isdn_command(&cmd);		cmd.driver = info->isdn_driver;		cmd.arg = info->isdn_channel;		cmd.parm.cmsg.Length = l+18;		cmd.parm.cmsg.Command = CAPI_FACILITY;		cmd.parm.cmsg.Subcommand = CAPI_REQ;		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */		cmd.parm.cmsg.para[1] = 0;		cmd.parm.cmsg.para[2] = l+3;		cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */		cmd.parm.cmsg.para[4] = 0;		cmd.parm.cmsg.para[5] = l;		strncpy(&cmd.parm.cmsg.para[6], id, l);		cmd.command =CAPI_PUT_MESSAGE;		info->dialing = 1;//		strcpy(dev->num[i], n);		isdn_info_update();		isdn_command(&cmd);		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);	}}/* isdn_tty_send_msg() sends a message to a HL driver * This is used for hybrid modem cards to send AT commands to it */static voidisdn_tty_send_msg(modem_info * info, atemu * m, char *msg){	int usg = ISDN_USAGE_MODEM;	int si = 7;	int l2 = m->mdmreg[REG_L2PROT];	isdn_ctrl cmd;	ulong flags;	int i;	int j;	int l;	l = strlen(msg);	if (!l) {		isdn_tty_modem_result(RESULT_ERROR, info);		return;	}	for (j = 7; j >= 0; j--)		if (m->mdmreg[REG_SI1] & (1 << j)) {			si = bit2si[j];			break;		}	usg = isdn_calc_usage(si, l2);#ifdef CONFIG_ISDN_AUDIO	if ((si == 1) && 		(l2 != ISDN_PROTO_L2_MODEM)#ifdef CONFIG_ISDN_TTY_FAX		&& (l2 != ISDN_PROTO_L2_FAX)#endif		) {		l2 = ISDN_PROTO_L2_TRANS;		usg = ISDN_USAGE_VOICE;	}#endif	m->mdmreg[REG_SI1I] = si2bit[si];	save_flags(flags);	cli();	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);	if (i < 0) {		restore_flags(flags);		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);	} else {		info->isdn_driver = dev->drvmap[i];		info->isdn_channel = dev->chanmap[i];		info->drv_index = i;		dev->m_idx[i] = info->line;		dev->usage[i] |= ISDN_USAGE_OUTGOING;		info->last_dir = 1;		isdn_info_update();		restore_flags(flags);		cmd.driver = info->isdn_driver;		cmd.arg = info->isdn_channel;		cmd.command = ISDN_CMD_CLREAZ;		isdn_command(&cmd);		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));		cmd.driver = info->isdn_driver;		cmd.command = ISDN_CMD_SETEAZ;

⌨️ 快捷键说明

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