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

📄 mos7840.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return status;}/***************************************************************************** * mos7840_change_port_settings *	This routine is called to set the UART on the device to match *      the specified new settings. *****************************************************************************/static void mos7840_change_port_settings(struct moschip_port *mos7840_port,					 struct ktermios *old_termios){	struct tty_struct *tty;	int baud;	unsigned cflag;	unsigned iflag;	__u8 lData;	__u8 lParity;	__u8 lStop;	int status;	__u16 Data;	struct usb_serial_port *port;	struct usb_serial *serial;	if (mos7840_port == NULL)		return;	port = (struct usb_serial_port *)mos7840_port->port;	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return;	}	if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {		dbg("%s", "Invalid Serial \n");		return;	}	serial = port->serial;	dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);	if (!mos7840_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	tty = mos7840_port->port->tty;	dbg("%s", "Entering .......... \n");	lData = LCR_BITS_8;	lStop = LCR_STOP_1;	lParity = LCR_PAR_NONE;	cflag = tty->termios->c_cflag;	iflag = tty->termios->c_iflag;	/* Change the number of bits */	if (cflag & CSIZE) {		switch (cflag & CSIZE) {		case CS5:			lData = LCR_BITS_5;			break;		case CS6:			lData = LCR_BITS_6;			break;		case CS7:			lData = LCR_BITS_7;			break;		default:		case CS8:			lData = LCR_BITS_8;			break;		}	}	/* Change the Parity bit */	if (cflag & PARENB) {		if (cflag & PARODD) {			lParity = LCR_PAR_ODD;			dbg("%s - parity = odd", __FUNCTION__);		} else {			lParity = LCR_PAR_EVEN;			dbg("%s - parity = even", __FUNCTION__);		}	} else {		dbg("%s - parity = none", __FUNCTION__);	}	if (cflag & CMSPAR) {		lParity = lParity | 0x20;	}	/* Change the Stop bit */	if (cflag & CSTOPB) {		lStop = LCR_STOP_2;		dbg("%s - stop bits = 2", __FUNCTION__);	} else {		lStop = LCR_STOP_1;		dbg("%s - stop bits = 1", __FUNCTION__);	}	/* Update the LCR with the correct value */	mos7840_port->shadowLCR &=	    ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);	mos7840_port->shadowLCR |= (lData | lParity | lStop);	dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n",	    mos7840_port->shadowLCR);	/* Disable Interrupts */	Data = 0x00;	mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);	Data = 0x00;	mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);	Data = 0xcf;	mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);	/* Send the updated LCR value to the mos7840 */	Data = mos7840_port->shadowLCR;	mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);	Data = 0x00b;	mos7840_port->shadowMCR = Data;	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);	Data = 0x00b;	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);	/* set up the MCR register and send it to the mos7840 */	mos7840_port->shadowMCR = MCR_MASTER_IE;	if (cflag & CBAUD) {		mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);	}	if (cflag & CRTSCTS) {		mos7840_port->shadowMCR |= (MCR_XON_ANY);	} else {		mos7840_port->shadowMCR &= ~(MCR_XON_ANY);	}	Data = mos7840_port->shadowMCR;	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);	/* Determine divisor based on baud rate */	baud = tty_get_baud_rate(tty);	if (!baud) {		/* pick a default, any default... */		dbg("%s\n", "Picked default baud...");		baud = 9600;	}	dbg("%s - baud rate = %d", __FUNCTION__, baud);	status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);	/* Enable Interrupts */	Data = 0x0c;	mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);	if (mos7840_port->read_urb->status != -EINPROGRESS) {		mos7840_port->read_urb->dev = serial->dev;		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);		if (status) {			dbg(" usb_submit_urb(read bulk) failed, status = %d",			    status);		}	}	wake_up(&mos7840_port->delta_msr_wait);	mos7840_port->delta_msr_cond = 1;	dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n",	    mos7840_port->shadowLCR);	return;}/***************************************************************************** * mos7840_set_termios *	this function is called by the tty driver when it wants to change *	the termios structure *****************************************************************************/static void mos7840_set_termios(struct usb_serial_port *port,				struct ktermios *old_termios){	int status;	unsigned int cflag;	struct usb_serial *serial;	struct moschip_port *mos7840_port;	struct tty_struct *tty;	dbg("mos7840_set_termios: START\n");	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return;	}	serial = port->serial;	if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {		dbg("%s", "Invalid Serial \n");		return;	}	mos7840_port = mos7840_get_port_private(port);	if (mos7840_port == NULL)		return;	tty = port->tty;	if (!mos7840_port->open) {		dbg("%s - port not opened", __FUNCTION__);		return;	}	dbg("%s\n", "setting termios - ");	cflag = tty->termios->c_cflag;	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,	    tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));	dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,	    old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));	dbg("%s - port %d", __FUNCTION__, port->number);	/* change the port settings to the new ones specified */	mos7840_change_port_settings(mos7840_port, old_termios);	if (!mos7840_port->read_urb) {		dbg("%s", "URB KILLED !!!!!\n");		return;	}	if (mos7840_port->read_urb->status != -EINPROGRESS) {		mos7840_port->read_urb->dev = serial->dev;		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);		if (status) {			dbg(" usb_submit_urb(read bulk) failed, status = %d",			    status);		}	}	return;}/***************************************************************************** * mos7840_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 an RS485 driver to be written in user space. *****************************************************************************/static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,				unsigned int __user *value){	int count;	unsigned int result = 0;	count = mos7840_chars_in_buffer(mos7840_port->port);	if (count == 0) {		dbg("%s -- Empty", __FUNCTION__);		result = TIOCSER_TEMT;	}	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}/***************************************************************************** * mos7840_set_modem_info *      function to set modem info *****************************************************************************/static int mos7840_set_modem_info(struct moschip_port *mos7840_port,				  unsigned int cmd, unsigned int __user *value){	unsigned int mcr;	unsigned int arg;	__u16 Data;	int status;	struct usb_serial_port *port;	if (mos7840_port == NULL)		return -1;	port = (struct usb_serial_port *)mos7840_port->port;	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return -1;	}	mcr = mos7840_port->shadowMCR;	if (copy_from_user(&arg, value, sizeof(int)))		return -EFAULT;	switch (cmd) {	case TIOCMBIS:		if (arg & TIOCM_RTS)			mcr |= MCR_RTS;		if (arg & TIOCM_DTR)			mcr |= MCR_RTS;		if (arg & TIOCM_LOOP)			mcr |= MCR_LOOPBACK;		break;	case TIOCMBIC:		if (arg & TIOCM_RTS)			mcr &= ~MCR_RTS;		if (arg & TIOCM_DTR)			mcr &= ~MCR_RTS;		if (arg & TIOCM_LOOP)			mcr &= ~MCR_LOOPBACK;		break;	case TIOCMSET:		/* turn off the RTS and DTR and LOOPBACK		 * and then only turn on what was asked to */		mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);		mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);		mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);		mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);		break;	}	mos7840_port->shadowMCR = mcr;	Data = mos7840_port->shadowMCR;	status = 0;	status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);	if (status < 0) {		dbg("setting MODEM_CONTROL_REGISTER Failed\n");		return -1;	}	return 0;}/***************************************************************************** * mos7840_get_modem_info *      function to get modem info *****************************************************************************/static int mos7840_get_modem_info(struct moschip_port *mos7840_port,				  unsigned int __user *value){	unsigned int result = 0;	__u16 msr;	unsigned int mcr = mos7840_port->shadowMCR;	int status = 0;	status =	    mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,				 &msr);	result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)	/* 0x002 */	    |((mcr & MCR_RTS) ? TIOCM_RTS : 0)	/* 0x004 */	    |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)	/* 0x020 */	    |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)	/* 0x040 */	    |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)	/* 0x080 */	    |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);	/* 0x100 */	dbg("%s -- %x", __FUNCTION__, result);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}/***************************************************************************** * mos7840_get_serial_info *      function to get information about serial port *****************************************************************************/static int mos7840_get_serial_info(struct moschip_port *mos7840_port,				   struct serial_struct __user *retinfo){	struct serial_struct tmp;	if (mos7840_port == NULL)		return -1;	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type = PORT_16550A;	tmp.line = mos7840_port->port->serial->minor;	tmp.port = mos7840_port->port->number;	tmp.irq = 0;	tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;	tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;	tmp.baud_base = 9600;	tmp.close_delay = 5 * HZ;	tmp.closing_wait = 30 * HZ;	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))		return -EFAULT;	return 0;}/***************************************************************************** * SerialIoctl *	this function handles any ioctl calls to the driver *****************************************************************************/static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,			 unsigned int cmd, unsigned long arg){	void __user *argp = (void __user *)arg;	struct moschip_port *mos7840_port;	struct tty_struct *tty;	struct async_icount cnow;	struct async_icount cprev;	struct serial_icounter_struct icount;	int mosret = 0;	if (mos7840_port_paranoia_check(port, __FUNCTION__)) {		dbg("%s", "Invalid port \n");		return -1;	}	mos7840_port = mos7840_get_port_private(port);	if (mos7840_port == NULL)		return -1;	tty = mos7840_port->port->tty;	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);	switch (cmd) {		/* return number of bytes available */	case TIOCSERGETLSR:		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);		return mos7840_get_lsr_info(mos7840_port, argp);		return 0;	case TIOCMBIS:	case TIOCMBIC:	case TIOCMSET:		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,		    port->number);		mosret =		    mos7840_set_modem_info(mos7840_port, cmd, argp);		return mosret;	case TIOCMGET:		dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);		return mos7840_get_modem_info(mos7840_port, argp);	case TIOCGSERIAL:		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);		return mos7840_get_serial_info(mos7840_port, argp);	case TIOCSSERIAL:		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);		break;	case TIOCMIWAIT:		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);		cprev = mos7840_port->icount;		while (1) {			//interruptible_sleep_on(&mos7840_port->

⌨️ 快捷键说明

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