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

📄 oti6858.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	chars = pl2303_buf_data_avail(priv->buf);	spin_unlock_irqrestore(&priv->lock, flags);	return chars;}static void oti6858_set_termios(struct usb_serial_port *port,				struct ktermios *old_termios){	struct oti6858_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	unsigned int cflag;	u8 frame_fmt, control;	u16 divisor;	int br;	dbg("%s(port = %d)", __FUNCTION__, port->number);	if ((!port->tty) || (!port->tty->termios)) {		dbg("%s(): no tty structures", __FUNCTION__);		return;	}	spin_lock_irqsave(&priv->lock, flags);	if (!priv->flags.termios_initialized) {		*(port->tty->termios) = tty_std_termios;		port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;		priv->flags.termios_initialized = 1;	}	spin_unlock_irqrestore(&priv->lock, flags);	cflag = port->tty->termios->c_cflag;	spin_lock_irqsave(&priv->lock, flags);	divisor = priv->pending_setup.divisor;	frame_fmt = priv->pending_setup.frame_fmt;	control = priv->pending_setup.control;	spin_unlock_irqrestore(&priv->lock, flags);	frame_fmt &= ~FMT_DATA_BITS_MASK;	switch (cflag & CSIZE) {		case CS5:			frame_fmt |= FMT_DATA_BITS_5;			break;		case CS6:			frame_fmt |= FMT_DATA_BITS_6;			break;		case CS7:			frame_fmt |= FMT_DATA_BITS_7;			break;		default:		case CS8:			frame_fmt |= FMT_DATA_BITS_8;			break;	}	/* manufacturer claims that this device can work with baud rates	 * up to 3 Mbps; I've tested it only on 115200 bps, so I can't	 * guarantee that any other baud rate will work (especially	 * the higher ones)	 */	br = tty_get_baud_rate(port->tty);	if (br == 0) {		divisor = 0;	} else if (br <= OTI6858_MAX_BAUD_RATE) {		int real_br;		divisor = (96000000 + 8 * br) / (16 * br);		real_br = 96000000 / (16 * divisor);		if ((((real_br - br) * 100 + br - 1) / br) > 2) {			dbg("%s(): baud rate %d is invalid", __FUNCTION__, br);			return;		}		divisor = cpu_to_le16(divisor);	} else {		dbg("%s(): baud rate %d is too high", __FUNCTION__, br);		return;	}	frame_fmt &= ~FMT_STOP_BITS_MASK;	if ((cflag & CSTOPB) != 0) {		frame_fmt |= FMT_STOP_BITS_2;	} else {		frame_fmt |= FMT_STOP_BITS_1;	}	frame_fmt &= ~FMT_PARITY_MASK;	if ((cflag & PARENB) != 0) {		if ((cflag & PARODD) != 0) {			frame_fmt |= FMT_PARITY_ODD;		} else {			frame_fmt |= FMT_PARITY_EVEN;		}	} else {		frame_fmt |= FMT_PARITY_NONE;	}	control &= ~CONTROL_MASK;	if ((cflag & CRTSCTS) != 0)		control |= (CONTROL_DTR_HIGH | CONTROL_RTS_HIGH);	/* change control lines if we are switching to or from B0 */	/* FIXME:	spin_lock_irqsave(&priv->lock, flags);	control = priv->line_control;	if ((cflag & CBAUD) == B0)		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);	else		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);	if (control != priv->line_control) {		control = priv->line_control;		spin_unlock_irqrestore(&priv->lock, flags);		set_control_lines(serial->dev, control);	} else {		spin_unlock_irqrestore(&priv->lock, flags);	}	*/	spin_lock_irqsave(&priv->lock, flags);	if (divisor != priv->pending_setup.divisor			|| control != priv->pending_setup.control			|| frame_fmt != priv->pending_setup.frame_fmt) {		priv->pending_setup.divisor = divisor;		priv->pending_setup.control = control;		priv->pending_setup.frame_fmt = frame_fmt;	}	spin_unlock_irqrestore(&priv->lock, flags);}static int oti6858_open(struct usb_serial_port *port, struct file *filp){	struct oti6858_private *priv = usb_get_serial_port_data(port);	struct ktermios tmp_termios;	struct usb_serial *serial = port->serial;	struct oti6858_control_pkt *buf;	unsigned long flags;	int result;	dbg("%s(port = %d)", __FUNCTION__, port->number);	usb_clear_halt(serial->dev, port->write_urb->pipe);	usb_clear_halt(serial->dev, port->read_urb->pipe);	if (port->open_count != 1)		return 0;	if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {		dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);		return -ENOMEM;	}	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),				OTI6858_REQ_T_GET_STATUS,				OTI6858_REQ_GET_STATUS,				0, 0,				buf, OTI6858_CTRL_PKT_SIZE,				100);	if (result != OTI6858_CTRL_PKT_SIZE) {		/* assume default (after power-on reset) values */		buf->divisor = cpu_to_le16(0x009c);	/* 38400 bps */		buf->frame_fmt = 0x03;	/* 8N1 */		buf->something = 0x43;		buf->control = 0x4c;	/* DTR, RTS */		buf->tx_status = 0x00;		buf->pin_state = 0x5b;	/* RTS, CTS, DSR, DTR, RI, DCD */		buf->rx_bytes_avail = 0x00;	}	spin_lock_irqsave(&priv->lock, flags);	memcpy(&priv->status, buf, OTI6858_CTRL_PKT_SIZE);	priv->pending_setup.divisor = buf->divisor;	priv->pending_setup.frame_fmt = buf->frame_fmt;	priv->pending_setup.control = buf->control;	spin_unlock_irqrestore(&priv->lock, flags);	kfree(buf);	dbg("%s(): submitting interrupt urb", __FUNCTION__);	port->interrupt_in_urb->dev = serial->dev;	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);	if (result != 0) {		dev_err(&port->dev, "%s(): usb_submit_urb() failed"			       " with error %d\n", __FUNCTION__, result);		oti6858_close(port, NULL);		return -EPROTO;	}	/* setup termios */	if (port->tty)		oti6858_set_termios(port, &tmp_termios);	return 0;}static void oti6858_close(struct usb_serial_port *port, struct file *filp){	struct oti6858_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	long timeout;	wait_queue_t wait;	dbg("%s(port = %d)", __FUNCTION__, port->number);	/* wait for data to drain from the buffer */	spin_lock_irqsave(&priv->lock, flags);	timeout = 30 * HZ;	/* PL2303_CLOSING_WAIT */	init_waitqueue_entry(&wait, current);	add_wait_queue(&port->tty->write_wait, &wait);	dbg("%s(): entering wait loop", __FUNCTION__);	for (;;) {		set_current_state(TASK_INTERRUPTIBLE);		if (pl2303_buf_data_avail(priv->buf) == 0		|| timeout == 0 || signal_pending(current)		|| !usb_get_intfdata(port->serial->interface))	/* disconnect */			break;		spin_unlock_irqrestore(&priv->lock, flags);		timeout = schedule_timeout(timeout);		spin_lock_irqsave(&priv->lock, flags);	}	set_current_state(TASK_RUNNING);	remove_wait_queue(&port->tty->write_wait, &wait);	dbg("%s(): after wait loop", __FUNCTION__);	/* clear out any remaining data in the buffer */	pl2303_buf_clear(priv->buf);	spin_unlock_irqrestore(&priv->lock, flags);	/* wait for characters to drain from the device */	/* (this is long enough for the entire 256 byte */	/* pl2303 hardware buffer to drain with no flow */	/* control for data rates of 1200 bps or more, */	/* for lower rates we should really know how much */	/* data is in the buffer to compute a delay */	/* that is not unnecessarily long) */	/* FIXME	bps = tty_get_baud_rate(port->tty);	if (bps > 1200)		timeout = max((HZ*2560)/bps,HZ/10);	else	*/		timeout = 2*HZ;	schedule_timeout_interruptible(timeout);	dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);	/* cancel scheduled setup */	cancel_delayed_work(&priv->delayed_setup_work);	cancel_delayed_work(&priv->delayed_write_work);	flush_scheduled_work();	/* shutdown our urbs */	dbg("%s(): shutting down urbs", __FUNCTION__);	usb_kill_urb(port->write_urb);	usb_kill_urb(port->read_urb);	usb_kill_urb(port->interrupt_in_urb);	/*	if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {		// drop DTR and RTS		spin_lock_irqsave(&priv->lock, flags);		priv->pending_setup.control &= ~CONTROL_MASK;		spin_unlock_irqrestore(&priv->lock, flags);	}	*/}static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,				unsigned int set, unsigned int clear){	struct oti6858_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	u8 control;	dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",				__FUNCTION__, port->number, set, clear);	if (!usb_get_intfdata(port->serial->interface))		return -ENODEV;	/* FIXME: check if this is correct (active high/low) */	spin_lock_irqsave(&priv->lock, flags);	control = priv->pending_setup.control;	if ((set & TIOCM_RTS) != 0)		control |= CONTROL_RTS_HIGH;	if ((set & TIOCM_DTR) != 0)		control |= CONTROL_DTR_HIGH;	if ((clear & TIOCM_RTS) != 0)		control &= ~CONTROL_RTS_HIGH;	if ((clear & TIOCM_DTR) != 0)		control &= ~CONTROL_DTR_HIGH;	if (control != priv->pending_setup.control) {		priv->pending_setup.control = control;	}	spin_unlock_irqrestore(&priv->lock, flags);	return 0;}static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file){	struct oti6858_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	unsigned pin_state;	unsigned result = 0;	dbg("%s(port = %d)", __FUNCTION__, port->number);	if (!usb_get_intfdata(port->serial->interface))		return -ENODEV;	spin_lock_irqsave(&priv->lock, flags);	pin_state = priv->status.pin_state & PIN_MASK;	spin_unlock_irqrestore(&priv->lock, flags);	/* FIXME: check if this is correct (active high/low) */	if ((pin_state & PIN_RTS) != 0)		result |= TIOCM_RTS;	if ((pin_state & PIN_CTS) != 0)		result |= TIOCM_CTS;	if ((pin_state & PIN_DSR) != 0)		result |= TIOCM_DSR;	if ((pin_state & PIN_DTR) != 0)		result |= TIOCM_DTR;	if ((pin_state & PIN_RI) != 0)		result |= TIOCM_RI;	if ((pin_state & PIN_DCD) != 0)		result |= TIOCM_CD;	dbg("%s() = 0x%08x", __FUNCTION__, result);	return result;}static int wait_modem_info(struct usb_serial_port *port, unsigned int arg){	struct oti6858_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	unsigned int prev, status;	unsigned int changed;	spin_lock_irqsave(&priv->lock, flags);	prev = priv->status.pin_state;	spin_unlock_irqrestore(&priv->lock, flags);	while (1) {		wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);		if (signal_pending(current))			return -ERESTARTSYS;		spin_lock_irqsave(&priv->lock, flags);		status = priv->status.pin_state & PIN_MASK;		spin_unlock_irqrestore(&priv->lock, flags);		changed = prev ^ status;		/* FIXME: check if this is correct (active high/low) */		if (	((arg & TIOCM_RNG) && (changed & PIN_RI)) ||			((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||			((arg & TIOCM_CD)  && (changed & PIN_DCD)) ||			((arg & TIOCM_CTS) && (changed & PIN_CTS))) {				return 0;		}		prev = status;	}	/* NOTREACHED */	return 0;}static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,			unsigned int cmd, unsigned long arg){	void __user *user_arg = (void __user *) arg;	unsigned int x;	dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",				__FUNCTION__, port->number, cmd, arg);	switch (cmd) {		case TCFLSH:			/* FIXME */			return 0;		case TIOCMBIS:			if (copy_from_user(&x, user_arg, sizeof(x)))				return -EFAULT;			return oti6858_tiocmset(port, NULL, x, 0);		case TIOCMBIC:			if (copy_from_user(&x, user_arg, sizeof(x)))				return -EFAULT;			return oti6858_tiocmset(port, NULL, 0, x);		case TIOCGSERIAL:			if (copy_to_user(user_arg, port->tty->termios,						sizeof(struct ktermios))) {				return -EFAULT;			}                        return 0;		case TIOCSSERIAL:			if (copy_from_user(port->tty->termios, user_arg,						sizeof(struct ktermios))) {				return -EFAULT;			}			oti6858_set_termios(port, NULL);			return 0;		case TIOCMIWAIT:			dbg("%s(): TIOCMIWAIT", __FUNCTION__);			return wait_modem_info(port, arg);		default:			dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);			break;	}	return -ENOIOCTLCMD;}static void oti6858_break_ctl(struct usb_serial_port *port, int break_state){	int state;	dbg("%s(port = %d)", __FUNCTION__, port->number);	state = (break_state == 0) ? 0 : 1;	dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");	/* FIXME *//*	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state,				  0, NULL, 0, 100);	if (result != 0)		dbg("%s(): error sending break", __FUNCTION__); */}static void oti6858_shutdown(struct usb_serial *serial){	struct oti6858_private *priv;	int i;

⌨️ 快捷键说明

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