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

📄 jpt_driver.c

📁 这是一个LINUX下多串口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
}#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,10))static int nuart_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	int c, total = 0;	unsigned long flags;	if (!tty || !info->xmit_buf || !nuvar_tmp_buf)		return (0);	if (from_user) 	{		down(&nuvar_tmp_buf_sem);		while (1) {			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head));			if (c <= 0)				break;			c -= copy_from_user(nuvar_tmp_buf, buf, c);			if (!c) {				if (!total)					total = -EFAULT;				break;			}			spin_lock_irqsave(&info->lock, flags);			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,				       SERIAL_XMIT_SIZE - info->xmit_head));			memcpy(info->xmit_buf + info->xmit_head, nuvar_tmp_buf, c);			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);			info->xmit_cnt += c;			spin_unlock_irqrestore(&info->lock, flags);			buf += c;			count -= c;			total += c;		}		up(&nuvar_tmp_buf_sem);	} else {		spin_lock_irqsave(&info->lock, flags);		while (1) {			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,SERIAL_XMIT_SIZE - info->xmit_head));			if (c <= 0) {				break;			}			memcpy(info->xmit_buf + info->xmit_head, buf, c);			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);			info->xmit_cnt += c;			buf += c;			count -= c;			total += c;		}		spin_unlock_irqrestore(&info->lock, flags);	}	return (total);}#elsestatic int nuart_write(struct tty_struct *tty, const unsigned char *buf, int count){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	int c, total = 0;	unsigned long flags;	if (!tty || !info->xmit_buf || !nuvar_tmp_buf)		return (0);	spin_lock_irqsave(&info->lock, flags);	while (1) {		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,SERIAL_XMIT_SIZE - info->xmit_head));		if (c <= 0) {			break;		}		memcpy(info->xmit_buf + info->xmit_head, buf, c);		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);		info->xmit_cnt += c;		buf += c;		count -= c;		total += c;	}	spin_unlock_irqrestore(&info->lock, flags);	return (total);}#endifstatic void nuart_put_char(struct tty_struct *tty, unsigned char ch){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	unsigned long flags;	if (!tty || !info->xmit_buf)		return;	spin_lock_irqsave(&info->lock, flags);	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)	{		spin_unlock_irqrestore(&info->lock, flags);		return;	}	info->xmit_buf[info->xmit_head++] = ch;	info->xmit_head &= SERIAL_XMIT_SIZE - 1;	info->xmit_cnt++;	spin_unlock_irqrestore(&info->lock, flags);}static void nuart_flush_chars(struct tty_struct *tty){	return;}static int nuart_write_room(struct tty_struct *tty){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	int ret;	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return (ret);}static int nuart_chars_in_buffer(struct tty_struct *tty){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	return (info->xmit_cnt);}static void nuart_flush_buffer(struct tty_struct *tty){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	unsigned long flags;	spin_lock_irqsave(&info->lock, flags);	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;	spin_unlock_irqrestore(&info->lock, 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 void nuart_send_break(struct nuart_struct *info, int duration){	unsigned long flags;	if (!info->base)		return;	set_current_state(TASK_INTERRUPTIBLE);	spin_lock_irqsave(&info->lock, flags);	nuart_break(info->base, &info->reg, 1);	spin_unlock_irqrestore(&info->lock, flags);	schedule_timeout(duration);	spin_lock_irqsave(&info->lock, flags);	nuart_break(info->base, &info->reg, 0);	spin_unlock_irqrestore(&info->lock, flags);}static int nuart_tiocmget(struct tty_struct * tty, struct file * file){	struct nuart_struct * info = (struct nuart_struct *)tty->driver_data;	unsigned long flags, status;		if(PORTNO(tty) == NUART_PORTS)		return (-ENOIOCTLCMD);	if(tty->flags & (1 << TTY_IO_ERROR))		return (-EIO);	spin_lock_irqsave(&info->lock, flags);	status = nuart_get_stat(info->base);	spin_unlock_irqrestore(&info->lock, flags);	if((status & (NUART_RI | NUART_DSR | NUART_DCD | NUART_CTS)) != 		(info->reg.mpr & (NUART_RI | NUART_DSR | NUART_DCD | NUART_CTS)))	    nuart_check_modem_status(info, status);	info->reg.mpr = status;	return ((status & NUART_DCD) ? TIOCM_CAR : 0) |	    ((status & NUART_RI) ? TIOCM_RNG : 0) |	    ((status & NUART_DSR) ? TIOCM_DSR : 0) |	    ((status & NUART_CTS) ? TIOCM_CTS : 0) |	    ((info->reg.pcr & NUART_DTRC_HIGH) ? TIOCM_DTR : 0) |	    ((info->reg.pcr & NUART_RTSC_HIGH) ? TIOCM_RTS : 0);}static int nuart_tiocmset(struct tty_struct *tty, struct file * file, unsigned int set, unsigned int clear){	struct nuart_struct * info = (struct nuart_struct *)tty->driver_data;	unsigned long flags;	int dtr = 0, rts = 0;	if(PORTNO(tty) == NUART_PORTS)		return (-ENOIOCTLCMD);	if(tty->flags & (1 << TTY_IO_ERROR))		return (-EIO);	if(set & TIOCM_RTS)		rts = 1;	if(set & TIOCM_DTR)		dtr = 1;	if(clear & TIOCM_RTS)		rts = 0;	if(clear & TIOCM_DTR)		dtr = 0;	spin_lock_irqsave(&info->lock, flags);	nuart_dtr(info->base, &info->reg, dtr);	nuart_rts(info->base, &info->reg, rts);	spin_unlock_irqrestore(&info->lock, flags);	return (0);}static int nuart_get_serial_info(struct nuart_struct *info,				 struct serial_struct *retinfo){	struct serial_struct tmp;	if (!retinfo)		return (-EFAULT);	memset(&tmp, 0, sizeof(tmp));	tmp.line = info->port;	tmp.port = info->base;	tmp.flags = info->flags;	tmp.baud_base = info->baud_base;	tmp.close_delay = info->close_delay;	tmp.closing_wait = info->closing_wait;	tmp.hub6 = 0;	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;}static int nuart_set_serial_info(struct nuart_struct *info,				 struct serial_struct *new_info){	struct serial_struct new_serial;	unsigned int flags;	int retval = 0;	if (!new_info || !info->base)		return (-EFAULT);	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))		return -EFAULT;	if ((new_serial.port != info->base) ||	     (new_serial.baud_base != info->baud_base))		return (-EPERM);	flags = info->flags & ASYNC_SPD_MASK;	if (!capable(CAP_SYS_ADMIN)) {		if ((new_serial.baud_base != info->baud_base) ||		    (new_serial.close_delay != info->close_delay) ||		    ((new_serial.flags & ~ASYNC_USR_MASK) !=		     (info->flags & ~ASYNC_USR_MASK)))			return (-EPERM);		info->flags = ((info->flags & ~ASYNC_USR_MASK) |			       (new_serial.flags & ASYNC_USR_MASK));	} else {		/*		 * OK, past this point, all the error checking has been done.
		 * At this point, we start making changes.....
		 */		info->flags = ((info->flags & ~ASYNC_FLAGS) |			       (new_serial.flags & ASYNC_FLAGS));		info->close_delay = new_serial.close_delay * HZ / 100;		info->closing_wait = new_serial.closing_wait * HZ / 100;	}	if (info->flags & ASYNC_INITIALIZED) {		if (flags != (info->flags & ASYNC_SPD_MASK)) {			nuart_change_speed(info, 0);		}	} else		retval = nuart_startup(info);	return (retval);}static int nuart_get_lsr_info(struct nuart_struct *info, unsigned int *value){	unsigned int result;	unsigned long flags;	spin_lock_irqsave(&info->lock, flags);	info->reg.mpr = nuart_get_stat(info->base);	spin_unlock_irqrestore(&info->lock, flags);	result = ((info->reg.mpr & NUART_TBUSY) ? 0 : TIOCSER_TEMT);	return put_user(result, value);}static int nuart_ioctl(struct tty_struct *tty, struct file *file,		       unsigned int cmd, unsigned long arg){	unsigned long flags;	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	int retval, ret;	struct async_icount cprev, cnow;	/* kernel counter temps */	struct serial_icounter_struct *p_cuser;		/* user space */	unsigned long templ;	DECLARE_WAITQUEUE(wait, current);	if (PORTNO(tty) == NUART_PORTS)		return 0;	if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) &&	    (cmd != TIOCGICOUNT)) {		if (tty->flags & (1 << TTY_IO_ERROR))			return (-EIO);	}	switch (cmd) 	{	case TCSBRK:		/* SVID version: non-zero arg --> no break */		retval = tty_check_change(tty);		if (retval)			return (retval);		tty_wait_until_sent(tty, 0);		if (!arg)			nuart_send_break(info, HZ / 4);		/* 1/4 second */		return (0);	case TCSBRKP:		/* support for POSIX tcsendbreak() */		retval = tty_check_change(tty);		if (retval)			return (retval);		tty_wait_until_sent(tty, 0);		nuart_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);		return (0);	case TIOCGSOFTCAR:		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);	case TIOCSSOFTCAR:		if(get_user(templ, (unsigned long *) arg))			return -EFAULT;		arg = templ;		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |					 (arg ? CLOCAL : 0));		return (0);//	case TIOCMGET://		return (nuart_get_modem_info(info, (unsigned int *) arg));//	case TIOCMBIS://	case TIOCMBIC://	case TIOCMSET://		return (nuart_set_modem_info(info, cmd, (unsigned int *) arg));	case TIOCGSERIAL:		return (nuart_get_serial_info(info, (struct serial_struct *) arg));	case TIOCSSERIAL:		return (nuart_set_serial_info(info, (struct serial_struct *) arg));	case TIOCSERGETLSR:	/* Get line status register */		return (nuart_get_lsr_info(info, (unsigned int *) arg));		/*		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change		 * - mask passed in arg for lines of interest		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)		 * Caller should use TIOCGICOUNT to see which one it was		 */	case TIOCMIWAIT:		spin_lock_irqsave(&info->lock, flags);		cprev = info->icount;		spin_unlock_irqrestore(&info->lock, flags);		add_wait_queue(&info->delta_msr_wait, &wait);		while(1)		{			spin_lock_irqsave(&info->lock, flags);			cnow = info->icount;			spin_unlock_irqrestore(&info->lock, flags);			set_current_state(TASK_INTERRUPTIBLE);			if(cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)			{				ret = -EIO;				break;			}			if(((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||			((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||			((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||			((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))			{				ret = 0;				break;			}			schedule();			if(signal_pending(current))			{				ret = -ERESTARTSYS;				break;			}			cprev = cnow;		}		current->state=TASK_RUNNING;		remove_wait_queue(&info->delta_msr_wait, &wait);		return ret;		/* NOT REACHED */		break;	case TIOCGICOUNT:		spin_lock_irqsave(&info->lock, flags);		cnow = info->icount;		spin_unlock_irqrestore(&info->lock, flags);		p_cuser = (struct serial_icounter_struct *)arg;		if(put_user(cnow.cts, &p_cuser->cts))			return -EFAULT;		if(put_user(cnow.dsr, &p_cuser->dsr))			return -EFAULT;		if(put_user(cnow.rng, &p_cuser->rng))			return -EFAULT;		return put_user(cnow.dcd, &p_cuser->dcd);	default:		return (-ENOIOCTLCMD);	}	return (0);}static void nuart_throttle(struct tty_struct *tty){}static void nuart_unthrottle(struct tty_struct *tty){}static void nuart_set_termios(struct tty_struct *tty,			      struct termios *old_termios){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	if ((tty->termios->c_cflag != old_termios->c_cflag) ||	    (RELEVANT_IFLAG(tty->termios->c_iflag) !=	     RELEVANT_IFLAG(old_termios->c_iflag))) 	{		nuart_change_speed(info, old_termios);		if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {			tty->hw_stopped = 0;			nuart_start(tty);		}	}/* Handle sw stopped */	if ((old_termios->c_iflag & IXON) && !(tty->termios->c_iflag & IXON))	{		tty->stopped = 0;		nuart_start(tty);	}}static void nuart_stop(struct tty_struct *tty){	struct nuart_struct * info  = (struct nuart_struct *)tty->driver_data;	if(info->xmit_cnt && info->xmit_buf)		info->lflag &= ~NUART_LFLAG_THRI;}static void nuart_start(struct tty_struct *tty){	struct nuart_struct * info  = (struct nuart_struct *)tty->driver_data;	if(info->xmit_cnt && info->xmit_buf)		info->lflag |= NUART_LFLAG_THRI;}void nuart_hangup(struct tty_struct *tty){	struct nuart_struct *info = (struct nuart_struct *) tty->driver_data;	nuart_flush_buffer(tty);	nuart_shutdown(info);	info->count = 0;	info->event = 0;	info->flags &= ~ASYNC_NORMAL_ACTIVE;	info->tty = 0;	wake_up_interruptible(&info->open_wait);}static void nuart_do_softint(void *private_){	struct nuart_struct *info = (struct nuart_struct *)private_;	struct tty_struct  *tty;		tty = info->tty;	if(tty)	{		if(test_and_clear_bit(NUART_EVENT_TXLOW, &info->event))		{			if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)				(tty->ldisc.write_wakeup)(tty);			wake_up_interruptible(&tty->write_wait);		}		if(test_and_clear_bit(NUART_EVENT_HANGUP, &info->event))			tty_hangup(tty);	}}module_init(nuart_module_init);module_exit(nuart_module_exit);

⌨️ 快捷键说明

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