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

📄 pl2303.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return set_control_lines(port->serial->dev, control);}static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file){	struct pl2303_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	unsigned int mcr;	unsigned int status;	unsigned int result;	dbg("%s (%d)", __FUNCTION__, port->number);	if (!usb_get_intfdata(port->serial->interface))		return -ENODEV;	spin_lock_irqsave(&priv->lock, flags);	mcr = priv->line_control;	status = priv->line_status;	spin_unlock_irqrestore(&priv->lock, flags);	result = ((mcr & CONTROL_DTR)		? TIOCM_DTR : 0)		  | ((mcr & CONTROL_RTS)	? TIOCM_RTS : 0)		  | ((status & UART_CTS)	? TIOCM_CTS : 0)		  | ((status & UART_DSR)	? TIOCM_DSR : 0)		  | ((status & UART_RING)	? TIOCM_RI  : 0)		  | ((status & UART_DCD)	? TIOCM_CD  : 0);	dbg("%s - result = %x", __FUNCTION__, result);	return result;}static int wait_modem_info(struct usb_serial_port *port, unsigned int arg){	struct pl2303_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	unsigned int prevstatus;	unsigned int status;	unsigned int changed;	spin_lock_irqsave(&priv->lock, flags);	prevstatus = priv->line_status;	spin_unlock_irqrestore(&priv->lock, flags);	while (1) {		interruptible_sleep_on(&priv->delta_msr_wait);		/* see if a signal did it */		if (signal_pending(current))			return -ERESTARTSYS;		spin_lock_irqsave(&priv->lock, flags);		status = priv->line_status;		spin_unlock_irqrestore(&priv->lock, flags);		changed=prevstatus^status;		if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||		    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||		    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||		    ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {			return 0;		}		prevstatus = status;	}	/* NOTREACHED */	return 0;}static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,			unsigned int cmd, unsigned long arg){	dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);	switch (cmd) {		case TIOCMIWAIT:			dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);			return wait_modem_info(port, arg);		default:			dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);			break;	}	return -ENOIOCTLCMD;}static void pl2303_break_ctl(struct usb_serial_port *port, int break_state){	struct usb_serial *serial = port->serial;	u16 state;	int result;	dbg("%s - port %d", __FUNCTION__, port->number);	if (break_state == 0)		state = BREAK_OFF;	else		state = BREAK_ON;	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),				 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,				 0, NULL, 0, 100);	if (result)		dbg("%s - error sending break = %d", __FUNCTION__, result);}static void pl2303_shutdown(struct usb_serial *serial){	int i;	struct pl2303_private *priv;	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 pl2303_update_line_status(struct usb_serial_port *port,				      unsigned char *data,				      unsigned int actual_length){	struct pl2303_private *priv = usb_get_serial_port_data(port);	unsigned long flags;	u8 status_idx = UART_STATE;	u8 length = UART_STATE + 1;	u16 idv, idp;	idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);	idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);	if (idv == SIEMENS_VENDOR_ID) {		if (idp == SIEMENS_PRODUCT_ID_X65 ||		    idp == SIEMENS_PRODUCT_ID_SX1 ||		    idp == SIEMENS_PRODUCT_ID_X75) {			length = 1;			status_idx = 0;		}	}	if (actual_length < length)		return;        /* Save off the uart status for others to look at */	spin_lock_irqsave(&priv->lock, flags);	priv->line_status = data[status_idx];	spin_unlock_irqrestore(&priv->lock, flags);	wake_up_interruptible(&priv->delta_msr_wait);}static void pl2303_read_int_callback(struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	unsigned char *data = urb->transfer_buffer;	unsigned int actual_length = urb->actual_length;	int status = urb->status;	int retval;	dbg("%s (%d)", __FUNCTION__, port->number);	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);		goto exit;	}	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,			      urb->actual_length, urb->transfer_buffer);	pl2303_update_line_status(port, data, actual_length);exit:	retval = usb_submit_urb(urb, GFP_ATOMIC);	if (retval)		dev_err(&urb->dev->dev,			"%s - usb_submit_urb failed with result %d\n",			__FUNCTION__, retval);}static void pl2303_read_bulk_callback(struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	struct pl2303_private *priv = usb_get_serial_port_data(port);	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;	unsigned long flags;	int i;	int result;	int status = urb->status;	u8 line_status;	char tty_flag;	dbg("%s - port %d", __FUNCTION__, port->number);	if (status) {		dbg("%s - urb status = %d", __FUNCTION__, status);		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__);			urb->dev = port->serial->dev;			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;	}	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,			      urb->actual_length, data);	/* get tty_flag from status */	tty_flag = TTY_NORMAL;	spin_lock_irqsave(&priv->lock, flags);	line_status = priv->line_status;	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;	spin_unlock_irqrestore(&priv->lock, flags);	wake_up_interruptible(&priv->delta_msr_wait);	/* break takes precedence over parity, */	/* which takes precedence over framing errors */	if (line_status & UART_BREAK_ERROR )		tty_flag = TTY_BREAK;	else if (line_status & UART_PARITY_ERROR)		tty_flag = TTY_PARITY;	else if (line_status & UART_FRAME_ERROR)		tty_flag = TTY_FRAME;	dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);	tty = port->tty;	if (tty && urb->actual_length) {		tty_buffer_request_room(tty, urb->actual_length + 1);		/* overrun is special, not associated with a char */		if (line_status & UART_OVERRUN_ERROR)			tty_insert_flip_char(tty, 0, TTY_OVERRUN);		for (i = 0; i < urb->actual_length; ++i)			tty_insert_flip_char(tty, data[i], tty_flag);		tty_flip_buffer_push(tty);	}	/* Schedule the next read _if_ we are still open */	if (port->open_count) {		urb->dev = port->serial->dev;		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;}static void pl2303_write_bulk_callback(struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	struct pl2303_private *priv = usb_get_serial_port_data(port);	int result;	int status = urb->status;	dbg("%s - port %d", __FUNCTION__, port->number);	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->write_urb_in_use = 0;		return;	default:		/* error in the urb, so we have to resubmit it */		dbg("%s - Overflow in write", __FUNCTION__);		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,		    status);		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(&urb->dev->dev, "%s - failed resubmitting write"				" urb, error %d\n", __FUNCTION__, result);		else			return;	}	priv->write_urb_in_use = 0;	/* send any buffered data */	pl2303_send(port);}/* All of the device info needed for the PL2303 SIO serial converter */static struct usb_serial_driver pl2303_device = {	.driver = {		.owner =	THIS_MODULE,		.name =		"pl2303",	},	.id_table =		id_table,	.usb_driver = 		&pl2303_driver,	.num_interrupt_in =	NUM_DONT_CARE,	.num_bulk_in =		1,	.num_bulk_out =		1,	.num_ports =		1,	.open =			pl2303_open,	.close =		pl2303_close,	.write =		pl2303_write,	.ioctl =		pl2303_ioctl,	.break_ctl =		pl2303_break_ctl,	.set_termios =		pl2303_set_termios,	.tiocmget =		pl2303_tiocmget,	.tiocmset =		pl2303_tiocmset,	.read_bulk_callback =	pl2303_read_bulk_callback,	.read_int_callback =	pl2303_read_int_callback,	.write_bulk_callback =	pl2303_write_bulk_callback,	.write_room =		pl2303_write_room,	.chars_in_buffer =	pl2303_chars_in_buffer,	.attach =		pl2303_startup,	.shutdown =		pl2303_shutdown,};static int __init pl2303_init(void){	int retval;	retval = usb_serial_register(&pl2303_device);	if (retval)		goto failed_usb_serial_register;	retval = usb_register(&pl2303_driver);	if (retval)		goto failed_usb_register;	info(DRIVER_DESC);	return 0;failed_usb_register:	usb_serial_deregister(&pl2303_device);failed_usb_serial_register:	return retval;}static void __exit pl2303_exit(void){	usb_deregister(&pl2303_driver);	usb_serial_deregister(&pl2303_device);}module_init(pl2303_init);module_exit(pl2303_exit);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug enabled or not");

⌨️ 快捷键说明

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