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

📄 isdn_tty.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",			       p, isdn_map_eaz2msn(emu->msn, di), tmp);#endif			if (q) {				*q = ';';				p = q;				p++;			}			if (!tmp)				return 0;			if (!q)				break;		}		return ret;	} else {		int tmp;		tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di));#ifdef ISDN_DEBUG_MODEM_ICALL			printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",			       isdn_map_eaz2msn(emu->msn, di), tmp);#endif		return tmp;	}}/* * An incoming call-request has arrived. * Search the tty-devices for an appropriate device and bind * it to the ISDN-Channel. * Return: * *  0 = No matching device found. *  1 = A matching device found. *  3 = No match found, but eventually would match, if *      CID is longer. */intisdn_tty_find_icall(int di, int ch, setup_parm *setup){	char *eaz;	int i;	int wret;	int idx;	int si1;	int si2;	char *nr;	ulong flags;	if (!setup->phone[0]) {		nr = "0";		printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");	} else		nr = setup->phone;	si1 = (int) setup->si1;	si2 = (int) setup->si2;	if (!setup->eazmsn[0]) {		printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");		eaz = "0";	} else		eaz = setup->eazmsn;#ifdef ISDN_DEBUG_MODEM_ICALL	printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);#endif	wret = 0;	spin_lock_irqsave(&dev->lock, flags);	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {		modem_info *info = &dev->mdm.info[i];                if (info->count == 0)                    continue;		if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */		    (info->emu.mdmreg[REG_SI2] == si2))	{         /* SI2 is matching */			idx = isdn_dc2minor(di, ch);#ifdef ISDN_DEBUG_MODEM_ICALL			printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);			printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,			       info->flags, info->isdn_driver, info->isdn_channel,			       dev->usage[idx]);#endif			if (#ifndef FIX_FILE_TRANSFER				(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&#endif				(info->isdn_driver == -1) &&				(info->isdn_channel == -1) &&				(USG_NONE(dev->usage[idx]))) {				int matchret;				if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)					wret = matchret;				if (!matchret) {                  /* EAZ is matching */					info->isdn_driver = di;					info->isdn_channel = ch;					info->drv_index = idx;					dev->m_idx[idx] = info->line;					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;					dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); 					strcpy(dev->num[idx], nr);					strcpy(info->emu.cpn, eaz);					info->emu.mdmreg[REG_SI1I] = si2bit[si1];					info->emu.mdmreg[REG_PLAN] = setup->plan;					info->emu.mdmreg[REG_SCREEN] = setup->screen;					isdn_info_update();					spin_unlock_irqrestore(&dev->lock, flags);					printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,					       info->line);					info->msr |= UART_MSR_RI;					isdn_tty_modem_result(RESULT_RING, info);					isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);					return 1;				}			}		}	}	spin_unlock_irqrestore(&dev->lock, flags);	printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,	       ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");	return (wret == 2)?3:0;}#define TTY_IS_ACTIVE(info) \	(info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))intisdn_tty_stat_callback(int i, isdn_ctrl *c){	int mi;	modem_info *info;	char *e;	if (i < 0)		return 0;	if ((mi = dev->m_idx[i]) >= 0) {		info = &dev->mdm.info[mi];		switch (c->command) {                        case ISDN_STAT_CINF:                                printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);                                info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);                                if (e == (char *)c->parm.num)					info->emu.charge = 0;				                                break;						case ISDN_STAT_BSENT:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);#endif				if ((info->isdn_driver == c->driver) &&				    (info->isdn_channel == c->arg)) {					info->msr |= UART_MSR_CTS;					if (info->send_outstanding)						if (!(--info->send_outstanding))							info->lsr |= UART_LSR_TEMT;					isdn_tty_tint(info);					return 1;				}				break;			case ISDN_STAT_CAUSE:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);#endif				/* Signal cause to tty-device */				strncpy(info->last_cause, c->parm.num, 5);				return 1;			case ISDN_STAT_DISPLAY:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);#endif				/* Signal display to tty-device */				if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && 					!(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {				  isdn_tty_at_cout("\r\n", info);				  isdn_tty_at_cout("DISPLAY: ", info);				  isdn_tty_at_cout(c->parm.display, info);				  isdn_tty_at_cout("\r\n", info);				}				return 1;			case ISDN_STAT_DCONN:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);#endif				if (TTY_IS_ACTIVE(info)) {					if (info->dialing == 1) {						info->dialing = 2;						return 1;					}				}				break;			case ISDN_STAT_DHUP:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);#endif				if (TTY_IS_ACTIVE(info)) {					if (info->dialing == 1) 						isdn_tty_modem_result(RESULT_BUSY, info);					if (info->dialing > 1) 						isdn_tty_modem_result(RESULT_NO_CARRIER, info);					info->dialing = 0;#ifdef ISDN_DEBUG_MODEM_HUP					printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");#endif					isdn_tty_modem_hup(info, 0);					return 1;				}				break;			case ISDN_STAT_BCONN:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);#endif				/* Wake up any processes waiting				 * for incoming call of this device when				 * DCD follow the state of incoming carrier				 */				if (info->blocked_open &&				   (info->emu.mdmreg[REG_DCD] & BIT_DCD)) {					wake_up_interruptible(&info->open_wait);				}				/* Schedule CONNECT-Message to any tty				 * waiting for it and				 * set DCD-bit of its modem-status.				 */				if (TTY_IS_ACTIVE(info) ||				    (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {					info->msr |= UART_MSR_DCD;					info->emu.charge = 0;					if (info->dialing & 0xf)						info->last_dir = 1;					else						info->last_dir = 0;					info->dialing = 0;					info->rcvsched = 1;					if (USG_MODEM(dev->usage[i])) {						if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {							strcpy(info->emu.connmsg, c->parm.num);							isdn_tty_modem_result(RESULT_CONNECT, info);						} else							isdn_tty_modem_result(RESULT_CONNECT64000, info);					}					if (USG_VOICE(dev->usage[i]))						isdn_tty_modem_result(RESULT_VCON, info);					return 1;				}				break;			case ISDN_STAT_BHUP:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line);#endif				if (TTY_IS_ACTIVE(info)) {#ifdef ISDN_DEBUG_MODEM_HUP					printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");#endif					isdn_tty_modem_hup(info, 0);					return 1;				}				break;			case ISDN_STAT_NODCH:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);#endif				if (TTY_IS_ACTIVE(info)) {					if (info->dialing) {						info->dialing = 0;						info->last_l2 = -1;						info->last_si = 0;						sprintf(info->last_cause, "0000");						isdn_tty_modem_result(RESULT_NO_DIALTONE, info);					}					isdn_tty_modem_hup(info, 0);					return 1;				}				break;			case ISDN_STAT_UNLOAD:#ifdef ISDN_TTY_STAT_DEBUG				printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);#endif				for (i = 0; i < ISDN_MAX_CHANNELS; i++) {					info = &dev->mdm.info[i];					if (info->isdn_driver == c->driver) {						if (info->online)							isdn_tty_modem_hup(info, 1);					}				}				return 1;#ifdef CONFIG_ISDN_TTY_FAX			case ISDN_STAT_FAXIND:				if (TTY_IS_ACTIVE(info)) {					isdn_tty_fax_command(info, c); 				}				break;#endif#ifdef CONFIG_ISDN_AUDIO			case ISDN_STAT_AUDIO:				if (TTY_IS_ACTIVE(info)) {					switch(c->parm.num[0]) {						case ISDN_AUDIO_DTMF:							if (info->vonline) {								isdn_audio_put_dle_code(info,									c->parm.num[1]);							}							break;					}				}				break;#endif		}	}	return 0;}/********************************************************************* Modem-Emulator-Routines *********************************************************************/#define cmdchar(c) ((c>=' ')&&(c<=0x7f))/* * Put a message from the AT-emulator into receive-buffer of tty, * convert CR, LF, and BS to values in modem-registers 3, 4 and 5. */voidisdn_tty_at_cout(char *msg, modem_info * info){	struct tty_struct *tty;	atemu *m = &info->emu;	char *p;	char c;	u_long flags;	struct sk_buff *skb = NULL;	char *sp = NULL;	if (!msg) {		printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");		return;	}	spin_lock_irqsave(&info->readlock, flags);	tty = info->tty;	if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {		spin_unlock_irqrestore(&info->readlock, flags);		return;	}	/* use queue instead of direct flip, if online and */	/* data is in queue or flip buffer is full */	if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||	    (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {		skb = alloc_skb(strlen(msg), GFP_ATOMIC);		if (!skb) {			spin_unlock_irqrestore(&info->readlock, flags);			return;		}		sp = skb_put(skb, strlen(msg));#ifdef CONFIG_ISDN_AUDIO		ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;		ISDN_AUDIO_SKB_LOCK(skb) = 0;#endif	}	for (p = msg; *p; p++) {		switch (*p) {			case '\r':				c = m->mdmreg[REG_CR];				break;			case '\n':				c = m->mdmreg[REG_LF];				break;			case '\b':				c = m->mdmreg[REG_BS];				break;			default:				c = *p;		}		if (skb) {			*sp++ = c;		} else {			if (tty->flip.count >= TTY_FLIPBUF_SIZE)				break;			tty_insert_flip_char(tty, c, 0);		}	}	if (skb) {		__skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);		dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;		spin_unlock_irqrestore(&info->readlock, flags);		/* Schedule dequeuing */		if ((dev->modempoll) && (info->rcvsched))			isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);	} else {		spin_unlock_irqrestore(&info->readlock, flags);		schedule_delayed_work(&tty->flip.work, 1);	}}/* * Perform ATH Hangup */static voidisdn_tty_on_hook(modem_info * info){	if (info->isdn_channel >= 0) {#ifdef ISDN_DEBUG_MODEM_HUP		printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");#endif		isdn_tty_modem_hup(info, 1);	}}static voidisdn_tty_off_hook(void){	printk(KERN_DEBUG "isdn_tty_off_hook\n");}#define PLUSWAIT1 (HZ/2)        /* 0.5 sec. */#define PLUSWAIT2 (HZ*3/2)      /* 1.5 sec *//* * Check Buffer for Modem-escape-sequence, activate timer-callback to * isdn_tty_modem_escape() if sequence found. * * Parameters: *   p          pointer to databuffer *   plus       escape-character *   count      length of buffer *   pluscount  count of valid escape-characters so far *   lastplus   timestamp of last character */static voidisdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,		   u_long *lastplus){	if (plus > 127)		return;	if (count > 3) {		p += count - 3;		count = 3;		*pluscount = 0;	}	while (count > 0) {		if (*(p++) == plus) {			if ((*pluscount)++) {				/* Time since last '+' > 0.5 sec. ? */				if (time_after(jiffies, *lastplus + PLUSWAIT1))					*pluscount = 1;			} else {				/* Time since last non-'+' < 1.5 sec. ? */				if (time_before(jiffies, *lastplus + PLUSWAIT2))					*pluscount = 0;			}			if ((*pluscount == 3) && (count == 1))				isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);			if (*pluscount > 3)				*pluscount = 1;		} else			*pluscount = 0;		*lastplus = jiffies;		count--;	}}/* * Return result of AT-emulator to tty-receive-buffer, depending on * modem-register 12, bit 0 and 1. * For CONNECT-messages also switch to online-mode. * For RING-message handle auto-ATA if register 0 != 0 */static voidisdn_tty_modem_result(int code, modem_info * info){	atemu *m = &info->emu;	static char *msg[] =	{"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",	 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",	 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};	char s[ISDN_MSNLEN+10];	switch (code) {		case RESULT_RING:			m->mdmreg[REG_RINGCNT]++;			if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])				/* Automatically accept incoming call */				isdn_tty_cmd_ATA(info);			break;		case RESULT_NO_CARRIER:#ifdef ISDN_DEBUG_MODEM_HUP			printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",			       (info->flags & ISDN_ASYNC_CLOSING),			       (!info->tty));#endif			m->mdmreg[REG_RINGCNT] = 0;			del_timer(&info->nc_timer);			info->ncarrier = 0;			if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {				return;			}#ifdef CONFIG_ISDN_AUDIO			if (info->vonline & 1) {#ifdef ISDN_DEBUG_MODEM_VOICE				printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n",				       info->line);#endif				/* voice-recording, add DLE-ETX */				isdn_tty_at_cout("\020\003", info);	

⌨️ 快捷键说明

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