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

📄 cypress_m8.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	cypress_serial_control(port, baud_mask, data_bits, stop_bits,			parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);	/* we perform a CYPRESS_GET_CONFIG so that the current settings are	 * filled into the private structure this should confirm that all is	 * working if it returns what we just set */	cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);	/* Here we can define custom tty settings for devices; the main tty	 * termios flag base comes from empeg.c */	spin_lock_irqsave(&priv->lock, flags);	if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {		dbg("Using custom termios settings for a baud rate of "				"4800bps.");		/* define custom termios settings for NMEA protocol */		tty->termios->c_iflag /* input modes - */			&= ~(IGNBRK  /* disable ignore break */			| BRKINT     /* disable break causes interrupt */			| PARMRK     /* disable mark parity errors */			| ISTRIP     /* disable clear high bit of input char */			| INLCR      /* disable translate NL to CR */			| IGNCR      /* disable ignore CR */			| ICRNL      /* disable translate CR to NL */			| IXON);     /* disable enable XON/XOFF flow control */		tty->termios->c_oflag /* output modes */			&= ~OPOST;    /* disable postprocess output char */		tty->termios->c_lflag /* line discipline modes */			&= ~(ECHO     /* disable echo input characters */			| ECHONL      /* disable echo new line */			| ICANON      /* disable erase, kill, werase, and rprnt					 special characters */			| ISIG        /* disable interrupt, quit, and suspend					 special characters */			| IEXTEN);    /* disable non-POSIX special characters */	} /* CT_CYPHIDCOM: Application should handle this for device */	linechange = (priv->line_control != oldlines);	spin_unlock_irqrestore(&priv->lock, flags);	/* if necessary, set lines */	if (linechange) {		priv->cmd_ctrl = 1;		cypress_write(port, NULL, 0);	}} /* cypress_set_termios *//* returns amount of data still left in soft buffer */static int cypress_chars_in_buffer(struct usb_serial_port *port){	struct cypress_private *priv = usb_get_serial_port_data(port);	int chars = 0;	unsigned long flags;	dbg("%s - port %d", __FUNCTION__, port->number);		spin_lock_irqsave(&priv->lock, flags);	chars = cypress_buf_data_avail(priv->buf);	spin_unlock_irqrestore(&priv->lock, flags);	dbg("%s - returns %d", __FUNCTION__, chars);	return chars;}static void cypress_throttle (struct usb_serial_port *port){	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);	priv->rx_flags = THROTTLED;	spin_unlock_irqrestore(&priv->lock, flags);}static void cypress_unthrottle (struct usb_serial_port *port){	struct cypress_private *priv = usb_get_serial_port_data(port);	int actually_throttled, result;	unsigned long flags;	dbg("%s - port %d", __FUNCTION__, port->number);	spin_lock_irqsave(&priv->lock, flags);	actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;	priv->rx_flags = 0;	spin_unlock_irqrestore(&priv->lock, flags);	if (actually_throttled) {		port->interrupt_in_urb->dev = port->serial->dev;		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);		if (result)			dev_err(&port->dev, "%s - failed submitting read urb, "					"error %d\n", __FUNCTION__, result);	}}static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct cypress_private *priv = usb_get_serial_port_data(port);	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;	unsigned long flags;	char tty_flag = TTY_NORMAL;	int havedata = 0;	int bytes = 0;	int result;	int i = 0;	dbg("%s - port %d", __FUNCTION__, port->number);	if (urb->status) {		dbg("%s - nonzero read status received: %d", __FUNCTION__,				urb->status);		return;	}	spin_lock_irqsave(&priv->lock, flags);	if (priv->rx_flags & THROTTLED) {		dbg("%s - now throttling", __FUNCTION__);		priv->rx_flags |= ACTUALLY_THROTTLED;		spin_unlock_irqrestore(&priv->lock, flags);		return;	}	spin_unlock_irqrestore(&priv->lock, flags);	tty = port->tty;	if (!tty) {		dbg("%s - bad tty pointer - exiting", __FUNCTION__);		return;	}	spin_lock_irqsave(&priv->lock, flags);	switch(urb->actual_length) {		case 32:			/* This is for the CY7C64013... */			priv->current_status = data[0] & 0xF8;			bytes = data[1] + 2;			i = 2;			if (bytes > 2)				havedata = 1;			break;		case 8:			/* This is for the CY7C63743... */			priv->current_status = data[0] & 0xF8;			bytes = (data[0] & 0x07) + 1;			i = 1;			if (bytes > 1)				havedata = 1;			break;		default:			dbg("%s - wrong packet size - received %d bytes",					__FUNCTION__, urb->actual_length);			spin_unlock_irqrestore(&priv->lock, flags);			goto continue_read;	}	spin_unlock_irqrestore(&priv->lock, flags);	usb_serial_debug_data (debug, &port->dev, __FUNCTION__,			urb->actual_length, data);	spin_lock_irqsave(&priv->lock, flags);	/* check to see if status has changed */	if (priv != NULL) {		if (priv->current_status != priv->prev_status) {			priv->diff_status |= priv->current_status ^				priv->prev_status;			wake_up_interruptible(&priv->delta_msr_wait);			priv->prev_status = priv->current_status;		}	}	spin_unlock_irqrestore(&priv->lock, flags);	/* hangup, as defined in acm.c... this might be a bad place for it	 * though */	if (tty && !(tty->termios->c_cflag & CLOCAL) &&			!(priv->current_status & UART_CD)) {		dbg("%s - calling hangup", __FUNCTION__);		tty_hangup(tty);		goto continue_read;	}	/* There is one error bit... I'm assuming it is a parity error	 * indicator as the generic firmware will set this bit to 1 if a	 * parity error occurs.	 * I can not find reference to any other error events. */	spin_lock_irqsave(&priv->lock, flags);	if (priv->current_status & CYP_ERROR) {		spin_unlock_irqrestore(&priv->lock, flags);		tty_flag = TTY_PARITY;		dbg("%s - Parity Error detected", __FUNCTION__);	} else		spin_unlock_irqrestore(&priv->lock, flags);	/* process read if there is data other than line status */	if (tty && (bytes > i)) {		for (; i < bytes ; ++i) {			dbg("pushing byte number %d - %d - %c", i, data[i],					data[i]);			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {				tty_flip_buffer_push(tty);			}			tty_insert_flip_char(tty, data[i], tty_flag);		}		tty_flip_buffer_push(port->tty);	}	spin_lock_irqsave(&priv->lock, flags);	/* control and status byte(s) are also counted */	priv->bytes_in += bytes;	spin_unlock_irqrestore(&priv->lock, flags);continue_read:	/* Continue trying to always read... unless the port has closed. */	if (port->open_count > 0) {		usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,				usb_rcvintpipe(port->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_ATOMIC);		if (result)			dev_err(&urb->dev->dev, "%s - failed resubmitting "					"read urb, error %d\n", __FUNCTION__,					result);	}	return;} /* cypress_read_int_callback */static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct cypress_private *priv = usb_get_serial_port_data(port);	int result;	dbg("%s - port %d", __FUNCTION__, port->number);		switch (urb->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__, urb->status);			priv->write_urb_in_use = 0;			return;		case -EPIPE: /* no break needed */			usb_clear_halt(port->serial->dev, 0x02);		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__, urb->status);			port->interrupt_out_urb->transfer_buffer_length = 1;			port->interrupt_out_urb->dev = port->serial->dev;			result = usb_submit_urb(port->interrupt_out_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 */	cypress_send(port);}/***************************************************************************** * Write buffer functions - buffering code from pl2303 used *****************************************************************************//* * cypress_buf_alloc * * Allocate a circular buffer and all associated memory. */static struct cypress_buf *cypress_buf_alloc(unsigned int size){	struct cypress_buf *cb;	if (size == 0)		return NULL;	cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);	if (cb == NULL)		return NULL;	cb->buf_buf = kmalloc(size, GFP_KERNEL);	if (cb->buf_buf == NULL) {		kfree(cb);		return NULL;	}	cb->buf_size = size;	cb->buf_get = cb->buf_put = cb->buf_buf;	return cb;}/* * cypress_buf_free * * Free the buffer and all associated memory. */static void cypress_buf_free(struct cypress_buf *cb){	if (cb) {		kfree(cb->buf_buf);		kfree(cb);	}}/* * cypress_buf_clear * * Clear out all data in the circular buffer. */static void cypress_buf_clear(struct cypress_buf *cb){	if (cb != NULL)		cb->buf_get = cb->buf_put;		/* equivalent to a get of all data available */}/* * cypress_buf_data_avail * * Return the number of bytes of data available in the circular * buffer. */static unsigned int cypress_buf_data_avail(struct cypress_buf *cb){	if (cb != NULL)		return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size);	else		return 0;}/* * cypress_buf_space_avail * * Return the number of bytes of space available in the circular * buffer. */static unsigned int cypress_buf_space_avail(struct cypress_buf *cb){	if (cb != NULL)		return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size);	else		return 0;}/* * cypress_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 cypress_buf_put(struct cypress_buf *cb, const char *buf,	unsigned int count){	unsigned int len;	if (cb == NULL)		return 0;	len  = cypress_buf_space_avail(cb);	if (count > len)		count = len;	if (count == 0)		return 0;	len = cb->buf_buf + cb->buf_size - cb->buf_put;	if (count > len) {		memcpy(cb->buf_put, buf, len);		memcpy(cb->buf_buf, buf+len, count - len);		cb->buf_put = cb->buf_buf + count - len;	} else {		memcpy(cb->buf_put, buf, count);		if (count < len)			cb->buf_put += count;		else /* count == len */			cb->buf_put = cb->buf_buf;	}	return count;}/* * cypress_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 cypress_buf_get(struct cypress_buf *cb, char *buf,	unsigned int count){	unsigned int len;	if (cb == NULL)		return 0;	len = cypress_buf_data_avail(cb);	if (count > len)		count = len;	if (count == 0)		return 0;	len = cb->buf_buf + cb->buf_size - cb->buf_get;	if (count > len) {		memcpy(buf, cb->buf_get, len);		memcpy(buf+len, cb->buf_buf, count - len);		cb->buf_get = cb->buf_buf + count - len;	} else {		memcpy(buf, cb->buf_get, count);		if (count < len)			cb->buf_get += count;		else /* count == len */			cb->buf_get = cb->buf_buf;	}	return count;}/***************************************************************************** * Module functions *****************************************************************************/static int __init cypress_init(void){	int retval;		dbg("%s", __FUNCTION__);		retval = usb_serial_register(&cypress_earthmate_device);	if (retval)		goto failed_em_register;	retval = usb_serial_register(&cypress_hidcom_device);	if (retval)		goto failed_hidcom_register;	retval = usb_register(&cypress_driver);	if (retval)		goto failed_usb_register;	info(DRIVER_DESC " " DRIVER_VERSION);	return 0;failed_usb_register:	usb_deregister(&cypress_driver);failed_hidcom_register:	usb_serial_deregister(&cypress_hidcom_device);failed_em_register:	usb_serial_deregister(&cypress_earthmate_device);	return retval;}static void __exit cypress_exit (void){	dbg("%s", __FUNCTION__);	usb_deregister (&cypress_driver);	usb_serial_deregister (&cypress_earthmate_device);	usb_serial_deregister (&cypress_hidcom_device);}module_init(cypress_init);module_exit(cypress_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_VERSION( DRIVER_VERSION );MODULE_LICENSE("GPL");module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug enabled or not");module_param(stats, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(stats, "Enable statistics or not");module_param(interval, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(interval, "Overrides interrupt interval");

⌨️ 快捷键说明

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