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

📄 cypress_m8.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	usb_clear_halt(serial->dev, 0x81);	usb_clear_halt(serial->dev, 0x02);	spin_lock_irqsave(&priv->lock, flags);	/* reset read/write statistics */	priv->bytes_in = 0;	priv->bytes_out = 0;	priv->cmd_count = 0;	priv->rx_flags = 0;	spin_unlock_irqrestore(&priv->lock, flags);	/* setting to zero could cause data loss */	port->tty->low_latency = 1;	/* raise both lines and set termios */	spin_lock_irqsave(&priv->lock, flags);	priv->line_control = CONTROL_DTR | CONTROL_RTS;	priv->cmd_ctrl = 1;	spin_unlock_irqrestore(&priv->lock, flags);	result = cypress_write(port, NULL, 0);	if (result) {		dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result);		return result;	} else		dbg("%s - success setting the control lines", __FUNCTION__);		cypress_set_termios(port, &priv->tmp_termios);	/* setup the port and start reading from the device */	if(!port->interrupt_in_urb){		err("%s - interrupt_in_urb is empty!", __FUNCTION__);		return(-1);	}	usb_fill_int_urb(port->interrupt_in_urb, serial->dev,		usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),		port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,		cypress_read_int_callback, port, interval);	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);	if (result){		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);	}	return result;} /* cypress_open */static void cypress_close(struct usb_serial_port *port, struct file * filp){	struct cypress_private *priv = usb_get_serial_port_data(port);	unsigned int c_cflag;	unsigned long flags;	int bps;	long timeout;	wait_queue_t wait;	dbg("%s - port %d", __FUNCTION__, port->number);	/* wait for data to drain from buffer */	spin_lock_irqsave(&priv->lock, flags);	timeout = CYPRESS_CLOSING_WAIT;	init_waitqueue_entry(&wait, current);	add_wait_queue(&port->tty->write_wait, &wait);	for (;;) {		set_current_state(TASK_INTERRUPTIBLE);		if (cypress_buf_data_avail(priv->buf) == 0		|| timeout == 0 || signal_pending(current)		|| !usb_get_intfdata(port->serial->interface))			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);	/* clear out any remaining data in the buffer */	cypress_buf_clear(priv->buf);	spin_unlock_irqrestore(&priv->lock, flags);		/* wait for characters to drain from device */	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 - stopping urbs", __FUNCTION__);	usb_kill_urb (port->interrupt_in_urb);	usb_kill_urb (port->interrupt_out_urb);	if (port->tty) {		c_cflag = port->tty->termios->c_cflag;		if (c_cflag & HUPCL) {			/* drop dtr and rts */			priv = usb_get_serial_port_data(port);			spin_lock_irqsave(&priv->lock, flags);			priv->line_control = 0;			priv->cmd_ctrl = 1;			spin_unlock_irqrestore(&priv->lock, flags);			cypress_write(port, NULL, 0);		}	}	if (stats)		dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",		          priv->bytes_in, priv->bytes_out, priv->cmd_count);} /* cypress_close */static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count){	struct cypress_private *priv = usb_get_serial_port_data(port);	unsigned long flags;		dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);	/* line control commands, which need to be executed immediately,	   are not put into the buffer for obvious reasons.	 */	if (priv->cmd_ctrl) {		count = 0;		goto finish;	}		if (!count)		return count;		spin_lock_irqsave(&priv->lock, flags);	count = cypress_buf_put(priv->buf, buf, count);	spin_unlock_irqrestore(&priv->lock, flags);finish:	cypress_send(port);	return count;} /* cypress_write */static void cypress_send(struct usb_serial_port *port){	int count = 0, result, offset, actual_size;	struct cypress_private *priv = usb_get_serial_port_data(port);	unsigned long flags;		dbg("%s - port %d", __FUNCTION__, port->number);	dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);		spin_lock_irqsave(&priv->lock, flags);	if (priv->write_urb_in_use) {		dbg("%s - can't write, urb in use", __FUNCTION__);		spin_unlock_irqrestore(&priv->lock, flags);		return;	}	spin_unlock_irqrestore(&priv->lock, flags);	/* clear buffer */	memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);	spin_lock_irqsave(&priv->lock, flags);	switch (port->interrupt_out_size) {		case 32:			/* this is for the CY7C64013... */			offset = 2;			port->interrupt_out_buffer[0] = priv->line_control;			break;		case 8:			/* this is for the CY7C63743... */			offset = 1;			port->interrupt_out_buffer[0] = priv->line_control;			break;		default:			dbg("%s - wrong packet size", __FUNCTION__);			spin_unlock_irqrestore(&priv->lock, flags);			return;	}	if (priv->line_control & CONTROL_RESET)		priv->line_control &= ~CONTROL_RESET;	if (priv->cmd_ctrl) {		priv->cmd_count++;		dbg("%s - line control command being issued", __FUNCTION__);		spin_unlock_irqrestore(&priv->lock, flags);		goto send;	} else		spin_unlock_irqrestore(&priv->lock, flags);	count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset],				port->interrupt_out_size-offset);	if (count == 0) {		return;	}	switch (port->interrupt_out_size) {		case 32:			port->interrupt_out_buffer[1] = count;			break;		case 8:			port->interrupt_out_buffer[0] |= count;	}	dbg("%s - count is %d", __FUNCTION__, count);send:	spin_lock_irqsave(&priv->lock, flags);	priv->write_urb_in_use = 1;	spin_unlock_irqrestore(&priv->lock, flags);	if (priv->cmd_ctrl)		actual_size = 1;	else		actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1);		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,			      port->interrupt_out_urb->transfer_buffer);	port->interrupt_out_urb->transfer_buffer_length = actual_size;	port->interrupt_out_urb->dev = port->serial->dev;	port->interrupt_out_urb->interval = interval;	result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);	if (result) {		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,			result);		priv->write_urb_in_use = 0;	}	spin_lock_irqsave(&priv->lock, flags);	if (priv->cmd_ctrl) {		priv->cmd_ctrl = 0;	}	priv->bytes_out += count; /* do not count the line control and size bytes */	spin_unlock_irqrestore(&priv->lock, flags);	schedule_work(&port->work);} /* cypress_send *//* returns how much space is available in the soft buffer */static int cypress_write_room(struct usb_serial_port *port){	struct cypress_private *priv = usb_get_serial_port_data(port);	int room = 0;	unsigned long flags;	dbg("%s - port %d", __FUNCTION__, port->number);	spin_lock_irqsave(&priv->lock, flags);	room = cypress_buf_space_avail(priv->buf);	spin_unlock_irqrestore(&priv->lock, flags);	dbg("%s - returns %d", __FUNCTION__, room);	return room;}static int cypress_tiocmget (struct usb_serial_port *port, struct file *file){	struct cypress_private *priv = usb_get_serial_port_data(port);	__u8 status, control;	unsigned int result = 0;	unsigned long flags;		dbg("%s - port %d", __FUNCTION__, port->number);	spin_lock_irqsave(&priv->lock, flags);	control = priv->line_control;	status = priv->current_status;	spin_unlock_irqrestore(&priv->lock, flags);	result = ((control & CONTROL_DTR)        ? TIOCM_DTR : 0)		| ((control & CONTROL_RTS)       ? TIOCM_RTS : 0)		| ((status & UART_CTS)        ? TIOCM_CTS : 0)		| ((status & UART_DSR)        ? TIOCM_DSR : 0)		| ((status & UART_RI)         ? TIOCM_RI  : 0)		| ((status & UART_CD)         ? TIOCM_CD  : 0);	dbg("%s - result = %x", __FUNCTION__, result);	return result;}static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,			       unsigned int set, unsigned int clear){	struct cypress_private *priv = usb_get_serial_port_data(port);	unsigned long flags;		dbg("%s - port %d", __FUNCTION__, port->number);	spin_lock_irqsave(&priv->lock, flags);	if (set & TIOCM_RTS)		priv->line_control |= CONTROL_RTS;	if (set & TIOCM_DTR)		priv->line_control |= CONTROL_DTR;	if (clear & TIOCM_RTS)		priv->line_control &= ~CONTROL_RTS;	if (clear & TIOCM_DTR)		priv->line_control &= ~CONTROL_DTR;	spin_unlock_irqrestore(&priv->lock, flags);	priv->cmd_ctrl = 1;	return cypress_write(port, NULL, 0);}static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg){	struct cypress_private *priv = usb_get_serial_port_data(port);	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);	switch (cmd) {		case TIOCGSERIAL:			if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {				return -EFAULT;			}			return (0);			break;		case TIOCSSERIAL:			if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {				return -EFAULT;			}			/* here we need to call cypress_set_termios to invoke the new settings */			cypress_set_termios(port, &priv->tmp_termios);			return (0);			break;		/* these are called when setting baud rate from gpsd */		case TCGETS:			if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {				return -EFAULT;			}			return (0);			break;		case TCSETS:			if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {				return -EFAULT;			}			/* here we need to call cypress_set_termios to invoke the new settings */			cypress_set_termios(port, &priv->tmp_termios);			return (0);			break;		/* This code comes from drivers/char/serial.c and ftdi_sio.c */		case TIOCMIWAIT:			while (priv != NULL) {				interruptible_sleep_on(&priv->delta_msr_wait);				/* see if a signal did it */				if (signal_pending(current))					return -ERESTARTSYS;				else {					char diff = priv->diff_status;					if (diff == 0) {						return -EIO; /* no change => error */					}										/* consume all events */					priv->diff_status = 0;					/* return 0 if caller wanted to know about these bits */					if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) ||					     ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||					     ((arg & TIOCM_CD) && (diff & UART_CD)) ||					     ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) {						return 0;					}					/* otherwise caller can't care less about what happened,					 * and so we continue to wait for more events.					 */				}			}			return 0;			break;		default:			break;	}	dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd);	return -ENOIOCTLCMD;} /* cypress_ioctl */static void cypress_set_termios (struct usb_serial_port *port,		struct termios *old_termios){	struct cypress_private *priv = usb_get_serial_port_data(port);	struct tty_struct *tty;	int data_bits, stop_bits, parity_type, parity_enable;	unsigned cflag, iflag, baud_mask;	unsigned long flags;	__u8 oldlines;	int linechange = 0;	dbg("%s - port %d", __FUNCTION__, port->number);	tty = port->tty;	if ((!tty) || (!tty->termios)) {		dbg("%s - no tty structures", __FUNCTION__);		return;	}	spin_lock_irqsave(&priv->lock, flags);	if (!priv->termios_initialized) {		if (priv->chiptype == CT_EARTHMATE) {			*(tty->termios) = tty_std_termios;			tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |				CLOCAL;		} else if (priv->chiptype == CT_CYPHIDCOM) {			*(tty->termios) = tty_std_termios;			tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |				CLOCAL;		}		priv->termios_initialized = 1;	}	spin_unlock_irqrestore(&priv->lock, flags);	cflag = tty->termios->c_cflag;	iflag = tty->termios->c_iflag;	/* check if there are new settings */	if (old_termios) {		if ((cflag != old_termios->c_cflag) ||			(RELEVANT_IFLAG(iflag) !=			 RELEVANT_IFLAG(old_termios->c_iflag))) {			dbg("%s - attempting to set new termios settings",					__FUNCTION__);			/* should make a copy of this in case something goes			 * wrong in the function, we can restore it */			spin_lock_irqsave(&priv->lock, flags);			priv->tmp_termios = *(tty->termios);			spin_unlock_irqrestore(&priv->lock, flags);		} else {			dbg("%s - nothing to do, exiting", __FUNCTION__);			return;		}	} else		return;	/* set number of data bits, parity, stop bits */	/* when parity is disabled the parity type bit is ignored */	/* 1 means 2 stop bits, 0 means 1 stop bit */	stop_bits = cflag & CSTOPB ? 1 : 0;	if (cflag & PARENB) {		parity_enable = 1;		/* 1 means odd parity, 0 means even parity */		parity_type = cflag & PARODD ? 1 : 0;	} else		parity_enable = parity_type = 0;	if (cflag & CSIZE) {		switch (cflag & CSIZE) {			case CS5:				data_bits = 0;				break;			case CS6:				data_bits = 1;				break;			case CS7:				data_bits = 2;				break;			case CS8:				data_bits = 3;				break;			default:				err("%s - CSIZE was set, but not CS5-CS8",						__FUNCTION__);				data_bits = 3;		}	} else		data_bits = 3;	spin_lock_irqsave(&priv->lock, flags);	oldlines = priv->line_control;	if ((cflag & CBAUD) == B0) {		/* drop dtr and rts */		dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__);		baud_mask = B0;		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);	} else {		baud_mask = (cflag & CBAUD);		switch(baud_mask) {			case B300:				dbg("%s - setting baud 300bps", __FUNCTION__);				break;			case B600:				dbg("%s - setting baud 600bps", __FUNCTION__);				break;			case B1200:				dbg("%s - setting baud 1200bps", __FUNCTION__);				break;			case B2400:				dbg("%s - setting baud 2400bps", __FUNCTION__);				break;			case B4800:				dbg("%s - setting baud 4800bps", __FUNCTION__);				break;			case B9600:				dbg("%s - setting baud 9600bps", __FUNCTION__);				break;			case B19200:				dbg("%s - setting baud 19200bps", __FUNCTION__);				break;			case B38400:				dbg("%s - setting baud 38400bps", __FUNCTION__);				break;			case B57600:				dbg("%s - setting baud 57600bps", __FUNCTION__);				break;			case B115200:				dbg("%s - setting baud 115200bps", __FUNCTION__);				break;			default:				dbg("%s - unknown masked baud rate", __FUNCTION__);		}		priv->line_control = (CONTROL_DTR | CONTROL_RTS);	}	spin_unlock_irqrestore(&priv->lock, flags);	dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "			"%d data_bits (+5)", __FUNCTION__, stop_bits,			parity_enable, parity_type, data_bits);

⌨️ 快捷键说明

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