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

📄 oti6858.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	dbg("%s()", __FUNCTION__);	for (i = 0; i < serial->num_ports; ++i) {		priv = usb_get_serial_port_data(serial->port[i]);		if (priv) {			pl2303_buf_free(priv->buf);			kfree(priv);			usb_set_serial_port_data(serial->port[i], NULL);		}	}}static void oti6858_read_int_callback(struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	struct oti6858_private *priv = usb_get_serial_port_data(port);	int transient = 0, can_recv = 0, resubmit = 1;	int status = urb->status;	dbg("%s(port = %d, status = %d)",				__FUNCTION__, port->number, status);	switch (status) {	case 0:		/* success */		break;	case -ECONNRESET:	case -ENOENT:	case -ESHUTDOWN:		/* this urb is terminated, clean up */		dbg("%s(): urb shutting down with status: %d",					__FUNCTION__, status);		return;	default:		dbg("%s(): nonzero urb status received: %d",					__FUNCTION__, status);		break;	}	if (status == 0 && urb->actual_length == OTI6858_CTRL_PKT_SIZE) {		struct oti6858_control_pkt *xs = urb->transfer_buffer;		unsigned long flags;		spin_lock_irqsave(&priv->lock, flags);		if (!priv->transient) {			if (!OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {				if (xs->rx_bytes_avail == 0) {					priv->transient = 4;					priv->setup_done = 0;					resubmit = 0;					dbg("%s(): scheduling setup_line()",					    __FUNCTION__);					schedule_delayed_work(&priv->delayed_setup_work, 0);				}			}		} else {			if (OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {				priv->transient = 0;			} else if (!priv->setup_done) {				resubmit = 0;			} else if (--priv->transient == 0) {				if (xs->rx_bytes_avail == 0) {					priv->transient = 4;					priv->setup_done = 0;					resubmit = 0;					dbg("%s(): scheduling setup_line()",					    __FUNCTION__);					schedule_delayed_work(&priv->delayed_setup_work, 0);				}			}		}		if (!priv->transient) {			if (xs->pin_state != priv->status.pin_state)				wake_up_interruptible(&priv->intr_wait);			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);		}		if (!priv->transient && xs->rx_bytes_avail != 0) {			can_recv = xs->rx_bytes_avail;			priv->flags.read_urb_in_use = 1;		}		transient = priv->transient;		spin_unlock_irqrestore(&priv->lock, flags);	}	if (can_recv) {		int result;		port->read_urb->dev = port->serial->dev;		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);		if (result != 0) {			priv->flags.read_urb_in_use = 0;			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"					" error %d\n", __FUNCTION__, result);		} else {			resubmit = 0;		}	} else if (!transient) {		unsigned long flags;		spin_lock_irqsave(&priv->lock, flags);		if (priv->flags.write_urb_in_use == 0				&& pl2303_buf_data_avail(priv->buf) != 0) {			schedule_delayed_work(&priv->delayed_write_work,0);			resubmit = 0;		}		spin_unlock_irqrestore(&priv->lock, flags);	}	if (resubmit) {		int result;//		dbg("%s(): submitting interrupt urb", __FUNCTION__);		urb->dev = port->serial->dev;		result = usb_submit_urb(urb, GFP_ATOMIC);		if (result != 0) {			dev_err(&urb->dev->dev,					"%s(): usb_submit_urb() failed with"					" error %d\n", __FUNCTION__, result);		}	}}static void oti6858_read_bulk_callback(struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	struct oti6858_private *priv = usb_get_serial_port_data(port);	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;	unsigned long flags;	int i, result;	int status = urb->status;	char tty_flag;	dbg("%s(port = %d, status = %d)",				__FUNCTION__, port->number, status);	spin_lock_irqsave(&priv->lock, flags);	priv->flags.read_urb_in_use = 0;	spin_unlock_irqrestore(&priv->lock, flags);	if (status != 0) {		if (!port->open_count) {			dbg("%s(): port is closed, exiting", __FUNCTION__);			return;		}		/*		if (status == -EPROTO) {			// PL2303 mysteriously fails with -EPROTO reschedule the read			dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);			result = usb_submit_urb(urb, GFP_ATOMIC);			if (result)				dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);			return;		}		*/		dbg("%s(): unable to handle the error, exiting", __FUNCTION__);		return;	}	// get tty_flag from status	tty_flag = TTY_NORMAL;/* FIXME: probably, errors will be signalled using interrupt pipe! *//*	// break takes precedence over parity,	// which takes precedence over framing errors	if (status & UART_BREAK_ERROR )		tty_flag = TTY_BREAK;	else if (status & UART_PARITY_ERROR)		tty_flag = TTY_PARITY;	else if (status & UART_FRAME_ERROR)		tty_flag = TTY_FRAME;	dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);*/	tty = port->tty;	if (tty != NULL && urb->actual_length > 0) {		tty_buffer_request_room(tty, urb->actual_length);		for (i = 0; i < urb->actual_length; ++i)			tty_insert_flip_char(tty, data[i], tty_flag);		tty_flip_buffer_push(tty);	}	// schedule the interrupt urb if we are still open */	if (port->open_count != 0) {		port->interrupt_in_urb->dev = port->serial->dev;		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);		if (result != 0) {			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"					" error %d\n", __FUNCTION__, result);		}	}}static void oti6858_write_bulk_callback(struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	struct oti6858_private *priv = usb_get_serial_port_data(port);	int status = urb->status;	int result;	dbg("%s(port = %d, status = %d)",				__FUNCTION__, port->number, status);	switch (status) {	case 0:		/* success */		break;	case -ECONNRESET:	case -ENOENT:	case -ESHUTDOWN:		/* this urb is terminated, clean up */		dbg("%s(): urb shutting down with status: %d",					__FUNCTION__, status);		priv->flags.write_urb_in_use = 0;		return;	default:		/* error in the urb, so we have to resubmit it */		dbg("%s(): nonzero write bulk status received: %d",					__FUNCTION__, status);		dbg("%s(): overflow in write", __FUNCTION__);		port->write_urb->transfer_buffer_length = 1;		port->write_urb->dev = port->serial->dev;		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);		if (result) {			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"					" error %d\n", __FUNCTION__, result);		} else {			return;		}	}	priv->flags.write_urb_in_use = 0;	// schedule the interrupt urb if we are still open */	port->interrupt_in_urb->dev = port->serial->dev;	dbg("%s(): submitting interrupt urb", __FUNCTION__);	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);	if (result != 0) {		dev_err(&port->dev, "%s(): failed submitting int urb,"					" error %d\n", __FUNCTION__, result);	}}/* * pl2303_buf_alloc * * Allocate a circular buffer and all associated memory. */static struct pl2303_buf *pl2303_buf_alloc(unsigned int size){	struct pl2303_buf *pb;	if (size == 0)		return NULL;	pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);	if (pb == NULL)		return NULL;	pb->buf_buf = kmalloc(size, GFP_KERNEL);	if (pb->buf_buf == NULL) {		kfree(pb);		return NULL;	}	pb->buf_size = size;	pb->buf_get = pb->buf_put = pb->buf_buf;	return pb;}/* * pl2303_buf_free * * Free the buffer and all associated memory. */static void pl2303_buf_free(struct pl2303_buf *pb){	if (pb) {		kfree(pb->buf_buf);		kfree(pb);	}}/* * pl2303_buf_clear * * Clear out all data in the circular buffer. */static void pl2303_buf_clear(struct pl2303_buf *pb){	if (pb != NULL) {		/* equivalent to a get of all data available */		pb->buf_get = pb->buf_put;	}}/* * pl2303_buf_data_avail * * Return the number of bytes of data available in the circular * buffer. */static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb){	if (pb == NULL)		return 0;	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);}/* * pl2303_buf_space_avail * * Return the number of bytes of space available in the circular * buffer. */static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb){	if (pb == NULL)		return 0;	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);}/* * pl2303_buf_put * * Copy data data from a user buffer and put it into the circular buffer. * Restrict to the amount of space available. * * Return the number of bytes copied. */static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,					unsigned int count){	unsigned int len;	if (pb == NULL)		return 0;	len  = pl2303_buf_space_avail(pb);	if (count > len)		count = len;	if (count == 0)		return 0;	len = pb->buf_buf + pb->buf_size - pb->buf_put;	if (count > len) {		memcpy(pb->buf_put, buf, len);		memcpy(pb->buf_buf, buf+len, count - len);		pb->buf_put = pb->buf_buf + count - len;	} else {		memcpy(pb->buf_put, buf, count);		if (count < len)			pb->buf_put += count;		else /* count == len */			pb->buf_put = pb->buf_buf;	}	return count;}/* * pl2303_buf_get * * Get data from the circular buffer and copy to the given buffer. * Restrict to the amount of data available. * * Return the number of bytes copied. */static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,					unsigned int count){	unsigned int len;	if (pb == NULL)		return 0;	len = pl2303_buf_data_avail(pb);	if (count > len)		count = len;	if (count == 0)		return 0;	len = pb->buf_buf + pb->buf_size - pb->buf_get;	if (count > len) {		memcpy(buf, pb->buf_get, len);		memcpy(buf+len, pb->buf_buf, count - len);		pb->buf_get = pb->buf_buf + count - len;	} else {		memcpy(buf, pb->buf_get, count);		if (count < len)			pb->buf_get += count;		else /* count == len */			pb->buf_get = pb->buf_buf;	}	return count;}/* module description and (de)initialization */static int __init oti6858_init(void){	int retval;	if ((retval = usb_serial_register(&oti6858_device)) == 0) {		if ((retval = usb_register(&oti6858_driver)) != 0)			usb_serial_deregister(&oti6858_device);		else			return 0;	}	return retval;}static void __exit oti6858_exit(void){	usb_deregister(&oti6858_driver);	usb_serial_deregister(&oti6858_device);}module_init(oti6858_init);module_exit(oti6858_exit);MODULE_DESCRIPTION(OTI6858_DESCRIPTION);MODULE_AUTHOR(OTI6858_AUTHOR);MODULE_VERSION(OTI6858_VERSION);MODULE_LICENSE("GPL");module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "enable debug output");

⌨️ 快捷键说明

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