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

📄 isdn_tty.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		cmd.command =CAPI_PUT_MESSAGE;/*		info->dialing = 1;		strcpy(dev->num[i], n);		isdn_info_update();*/		isdn_command(&cmd);	}}static inline intisdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine){#ifdef MODEM_PARANOIA_CHECK	if (!info) {		printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n",		       major(device), minor(device), routine);		return 1;	}	if (info->magic != ISDN_ASYNC_MAGIC) {		printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n",		       major(device), minor(device), routine);		return 1;	}#endif	return 0;}/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */static voidisdn_tty_change_speed(modem_info * info){	uint cflag,	 cval,	 fcr,	 quot;	int i;	if (!info->tty || !info->tty->termios)		return;	cflag = info->tty->termios->c_cflag;	quot = i = cflag & CBAUD;	if (i & CBAUDEX) {		i &= ~CBAUDEX;		if (i < 1 || i > 2)			info->tty->termios->c_cflag &= ~CBAUDEX;		else			i += 15;	}	if (quot) {		info->mcr |= UART_MCR_DTR;		isdn_tty_modem_ncarrier(info);	} else {		info->mcr &= ~UART_MCR_DTR;		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {#ifdef ISDN_DEBUG_MODEM_HUP			printk(KERN_DEBUG "Mhup in changespeed\n");#endif			if (info->online)				info->ncarrier = 1;			isdn_tty_modem_reset_regs(info, 0);			isdn_tty_modem_hup(info, 1);		}		return;	}	/* byte size and parity */	cval = cflag & (CSIZE | CSTOPB);	cval >>= 4;	if (cflag & PARENB)		cval |= UART_LCR_PARITY;	if (!(cflag & PARODD))		cval |= UART_LCR_EPAR;	fcr = 0;	/* CTS flow control flag and modem status interrupts */	if (cflag & CRTSCTS) {		info->flags |= ISDN_ASYNC_CTS_FLOW;	} else		info->flags &= ~ISDN_ASYNC_CTS_FLOW;	if (cflag & CLOCAL)		info->flags &= ~ISDN_ASYNC_CHECK_CD;	else {		info->flags |= ISDN_ASYNC_CHECK_CD;	}}static intisdn_tty_startup(modem_info * info){	ulong flags;	if (info->flags & ISDN_ASYNC_INITIALIZED)		return 0;	save_flags(flags);	cli();	isdn_MOD_INC_USE_COUNT();#ifdef ISDN_DEBUG_MODEM_OPEN	printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);#endif	/*	 * Now, initialize the UART	 */	info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;	if (info->tty)		clear_bit(TTY_IO_ERROR, &info->tty->flags);	/*	 * and set the speed of the serial port	 */	isdn_tty_change_speed(info);	info->flags |= ISDN_ASYNC_INITIALIZED;	info->msr |= (UART_MSR_DSR | UART_MSR_CTS);	info->send_outstanding = 0;	restore_flags(flags);	return 0;}/* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. */static voidisdn_tty_shutdown(modem_info * info){	ulong flags;	if (!(info->flags & ISDN_ASYNC_INITIALIZED))		return;#ifdef ISDN_DEBUG_MODEM_OPEN	printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);#endif	save_flags(flags);	cli();                  /* Disable interrupts */	isdn_MOD_DEC_USE_COUNT();	info->msr &= ~UART_MSR_RI;	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {			isdn_tty_modem_reset_regs(info, 0);#ifdef ISDN_DEBUG_MODEM_HUP			printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");#endif			isdn_tty_modem_hup(info, 1);		}	}	if (info->tty)		set_bit(TTY_IO_ERROR, &info->tty->flags);	info->flags &= ~ISDN_ASYNC_INITIALIZED;	restore_flags(flags);}/* isdn_tty_write() is the main send-routine. It is called from the upper * levels within the kernel to perform sending data. Depending on the * online-flag it either directs output to the at-command-interpreter or * to the lower level. Additional tasks done here: *  - If online, check for escape-sequence (+++) *  - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes. *  - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed. *  - If dialing, abort dial. */static intisdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count){	int c;	int total = 0;	modem_info *info = (modem_info *) tty->driver_data;	atemu *m = &info->emu;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))		return 0;	if (from_user)		down(&info->write_sem);	/* See isdn_tty_senddown() */	atomic_inc(&info->xmit_lock);	while (1) {		c = count;		if (c > info->xmit_size - info->xmit_count)			c = info->xmit_size - info->xmit_count;		if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize)			c = dev->drv[info->isdn_driver]->maxbufsize;		if (c <= 0)			break;		if ((info->online > 1)#ifdef CONFIG_ISDN_AUDIO		    || (info->vonline & 3)#endif			) {#ifdef CONFIG_ISDN_AUDIO			if (!info->vonline)#endif				isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,						   &(m->pluscount),						   &(m->lastplus),						   from_user);			if (from_user)				copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);			else				memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);#ifdef CONFIG_ISDN_AUDIO			if (info->vonline) {				int cc = isdn_tty_handleDLEdown(info, m, c);				if (info->vonline & 2) {					if (!cc) {						/* If DLE decoding results in zero-transmit, but						 * c originally was non-zero, do a wakeup.						 */						if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&						 tty->ldisc.write_wakeup)							(tty->ldisc.write_wakeup) (tty);						wake_up_interruptible(&tty->write_wait);						info->msr |= UART_MSR_CTS;						info->lsr |= UART_LSR_TEMT;					}					info->xmit_count += cc;				}				if ((info->vonline & 3) == 1) {					/* Do NOT handle Ctrl-Q or Ctrl-S					 * when in full-duplex audio mode.					 */					if (isdn_tty_end_vrx(buf, c, from_user)) {						info->vonline &= ~1;#ifdef ISDN_DEBUG_MODEM_VOICE						printk(KERN_DEBUG						       "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n",						       info->line);#endif						isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);					}				}			} else			if (TTY_IS_FCLASS1(info)) {				int cc = isdn_tty_handleDLEdown(info, m, c);								if (info->vonline & 4) { /* ETX seen */					isdn_ctrl c;					c.command = ISDN_CMD_FAXCMD;					c.driver = info->isdn_driver;					c.arg = info->isdn_channel;					c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;					c.parm.aux.subcmd = ETX;					isdn_command(&c);				}				info->vonline = 0;#ifdef ISDN_DEBUG_MODEM_VOICE				printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c);#endif				info->xmit_count += cc;			} else#endif				info->xmit_count += c;		} else {			info->msr |= UART_MSR_CTS;			info->lsr |= UART_LSR_TEMT;			if (info->dialing) {				info->dialing = 0;#ifdef ISDN_DEBUG_MODEM_HUP				printk(KERN_DEBUG "Mhup in isdn_tty_write\n");#endif				isdn_tty_modem_result(RESULT_NO_CARRIER, info);				isdn_tty_modem_hup(info, 1);			} else				c = isdn_tty_edit_at(buf, c, info, from_user);		}		buf += c;		count -= c;		total += c;	}	atomic_dec(&info->xmit_lock);	if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) {		if (m->mdmreg[REG_DXMT] & BIT_DXMT) {			isdn_tty_senddown(info);			isdn_tty_tint(info);		}		isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);	}	if (from_user)		up(&info->write_sem);	return total;}static intisdn_tty_write_room(struct tty_struct *tty){	modem_info *info = (modem_info *) tty->driver_data;	int ret;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write_room"))		return 0;	if (!info->online)		return info->xmit_size;	ret = info->xmit_size - info->xmit_count;	return (ret < 0) ? 0 : ret;}static intisdn_tty_chars_in_buffer(struct tty_struct *tty){	modem_info *info = (modem_info *) tty->driver_data;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_chars_in_buffer"))		return 0;	if (!info->online)		return 0;	return (info->xmit_count);}static voidisdn_tty_flush_buffer(struct tty_struct *tty){	modem_info *info;	unsigned long flags;	save_flags(flags);	cli();	if (!tty) {		restore_flags(flags);		return;	}	info = (modem_info *) tty->driver_data;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer")) {		restore_flags(flags);		return;	}	isdn_tty_cleanup_xmit(info);	info->xmit_count = 0;	restore_flags(flags);	wake_up_interruptible(&tty->write_wait);	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup)		(tty->ldisc.write_wakeup) (tty);}static voidisdn_tty_flush_chars(struct tty_struct *tty){	modem_info *info = (modem_info *) tty->driver_data;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_chars"))		return;	if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))		isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);}/* * ------------------------------------------------------------ * isdn_tty_throttle() * * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ */static voidisdn_tty_throttle(struct tty_struct *tty){	modem_info *info = (modem_info *) tty->driver_data;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_throttle"))		return;	if (I_IXOFF(tty))		info->x_char = STOP_CHAR(tty);	info->mcr &= ~UART_MCR_RTS;}static voidisdn_tty_unthrottle(struct tty_struct *tty){	modem_info *info = (modem_info *) tty->driver_data;	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_unthrottle"))		return;	if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			info->x_char = START_CHAR(tty);	}	info->mcr |= UART_MCR_RTS;}/* * ------------------------------------------------------------ * isdn_tty_ioctl() and friends * ------------------------------------------------------------ *//* * isdn_tty_get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically *          is emptied.  On bus types like RS485, the transmitter must *          release the bus after transmitting. This must be done when *          the transmit shift register is empty, not be done when the *          transmit holding register is empty.  This functionality *          allows RS485 driver to be written in user space. */static intisdn_tty_get_lsr_info(modem_info * info, uint * value){	u_char status;	uint result;	ulong flags;	save_flags(flags);	cli();	status = info->lsr;	restore_flags(flags);	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);	return put_user(result, (uint *) value);}static intisdn_tty_get_modem_info(modem_info * info, uint * value){	u_char control,	 status;	uint result;	ulong flags;	control = info->mcr;	save_flags(flags);	cli();	status = info->msr;	restore_flags(flags);	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)	    | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)	    | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);	return put_user(result, (uint *) value);}static intisdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value){	uint arg;	int pre_dtr;	if (get_user(arg, (uint *) value))		return -EFAULT;	switch (cmd) {		case TIOCMBIS:#ifdef ISDN_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line);#endif			if (arg & TIOCM_RTS) {				info->mcr |= UART_MCR_RTS;			}			if (arg & TIOCM_DTR) {				info->mcr |= UART_MCR_DTR;				isdn_tty_modem_ncarrier(info);			}			break;		case TIOCMBIC:#ifdef ISDN_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line);#endif			if (arg & TIOCM_RTS) {				info->mcr &= ~UART_MCR_RTS;			}			if (arg & TIOCM_DTR) {				info->mcr &= ~UART_MCR_DTR;				if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {					isdn_tty_modem_reset_regs(info, 0);#ifdef ISDN_DEBUG_MODEM_HUP					printk(KERN_DEBUG "Mhup in TIOCMBIC\n");#endif					if (info->online)						info->ncarrier = 1;					isdn_tty_modem_hup(info, 1);				}			}			break;		case TIOCMSET:#ifdef ISDN_DEBUG_MODEM_IOCTL			printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line);#endif			pre_dtr = (info->mcr & UART_MCR_DTR);			info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR))				 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)			       | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));			if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {				if (!(info->mcr & UART_MCR_DTR)) {					if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {						isdn_tty_modem_reset_regs(info, 0);#ifdef ISDN_DEBUG_MODEM_HUP						printk(KERN_DEBUG "Mhup in TIOCMSET\n");#endif						if (info->online)							info->ncarrier = 1;						isdn_tty_modem_hup(info, 1);					}				} else					isdn_tty_modem_ncarrier(info);			}			break;		default:

⌨️ 快捷键说明

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