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

📄 kl5kusb105.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					 * oopses. */					/* usb_unlink_urb(write_urbs[j]); */					if (write_urbs[j]->transfer_buffer)						    kfree(write_urbs[j]->transfer_buffer);					usb_free_urb (write_urbs[j]);				}			}			spin_unlock_irqrestore (&priv->write_urb_pool_lock,					       	flags);			kfree(serial->port[i].private);		}	}} /* klsi_105_shutdown */static int  klsi_105_open (struct usb_serial_port *port, struct file *filp){	struct usb_serial *serial = port->serial;	struct klsi_105_private *priv = (struct klsi_105_private *)port->private;	int retval = 0;	dbg(__FUNCTION__" port %d", port->number);	down (&port->sem);		++port->open_count;	MOD_INC_USE_COUNT;	if (!port->active) {		int rc;		int i;		unsigned long line_state;		port->active = 1;		/* force low_latency on so that our tty_push actually forces		 * the data through		 * port->tty->low_latency = 1; */		/* Do a defined restart:		 * Set up sane default baud rate and send the 'READ_ON'		 * vendor command. 		 * FIXME: set modem line control (how?)		 * Then read the modem line control and store values in		 * priv->line_state.		 */		priv->cfg.pktlen   = 5;		priv->cfg.baudrate = kl5kusb105a_sio_b9600;		priv->cfg.databits = kl5kusb105a_dtb_8;		priv->cfg.unknown1 = 0;		priv->cfg.unknown2 = 1;		klsi_105_chg_port_settings(serial, &(priv->cfg));				/* set up termios structure */		priv->termios.c_iflag = port->tty->termios->c_iflag;		priv->termios.c_oflag = port->tty->termios->c_oflag;		priv->termios.c_cflag = port->tty->termios->c_cflag;		priv->termios.c_lflag = port->tty->termios->c_lflag;		for (i=0; i<NCCS; i++)			priv->termios.c_cc[i] = port->tty->termios->c_cc[i];		/* READ_ON and urb submission */		FILL_BULK_URB(port->read_urb, serial->dev, 			      usb_rcvbulkpipe(serial->dev,					      port->bulk_in_endpointAddress),			      port->read_urb->transfer_buffer,			      port->read_urb->transfer_buffer_length,			      klsi_105_read_bulk_callback,			      port);		port->read_urb->transfer_flags |= USB_QUEUE_BULK;		rc = usb_submit_urb(port->read_urb);		if (rc) {			err(__FUNCTION__ 			    " - failed submitting read urb, error %d", rc);			retval = rc;			goto exit;		}		rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),				     KL5KUSB105A_SIO_CONFIGURE,				     USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,				     KL5KUSB105A_SIO_CONFIGURE_READ_ON,				     0, /* index */				     NULL,				     0,				     KLSI_TIMEOUT);		if (rc < 0) {			err("Enabling read failed (error = %d)", rc);			retval = rc;		} else 			dbg(__FUNCTION__ " - enabled reading");		rc = klsi_105_get_line_state(serial, &line_state);		if (rc >= 0) {			priv->line_state = line_state;			dbg(__FUNCTION__ 			    " - read line state 0x%lx", line_state);			retval = 0;		} else			retval = rc;	}exit:	up (&port->sem);		return retval;} /* klsi_105_open */static void klsi_105_close (struct usb_serial_port *port, struct file *filp){	struct usb_serial *serial;	struct klsi_105_private *priv 		= (struct klsi_105_private *)port->private;	dbg(__FUNCTION__" port %d", port->number);	serial = get_usb_serial (port, __FUNCTION__);	if(!serial)		return;	down (&port->sem);	--port->open_count;	if (port->open_count <= 0) {		/* send READ_OFF */		int rc = usb_control_msg(serial->dev,					 usb_sndctrlpipe(serial->dev, 0),					 KL5KUSB105A_SIO_CONFIGURE,					 USB_TYPE_VENDOR | USB_DIR_OUT,					 KL5KUSB105A_SIO_CONFIGURE_READ_OFF,					 0, /* index */					 NULL, 0,					 KLSI_TIMEOUT);		if (rc < 0)			    err("Disabling read failed (error = %d)", rc);		/* shutdown our bulk reads and writes */		usb_unlink_urb (port->write_urb);		usb_unlink_urb (port->read_urb);		/* unlink our write pool */		/* FIXME */		/* wgg - do I need this? I think so. */		usb_unlink_urb (port->interrupt_in_urb);		port->active = 0;		info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);	}		up (&port->sem);	MOD_DEC_USE_COUNT;} /* klsi_105_close *//* We need to write a complete 64-byte data block and encode the * number actually sent in the first double-byte, LSB-order. That  * leaves at most 62 bytes of payload. */#define KLSI_105_DATA_OFFSET	2   /* in the bulk urb data block */static int klsi_105_write (struct usb_serial_port *port, int from_user,			   const unsigned char *buf, int count){	struct usb_serial *serial = port->serial;	struct klsi_105_private *priv = 		(struct klsi_105_private*) port->private;	int result, size;	int bytes_sent=0;	dbg(__FUNCTION__ " - port %d", port->number);	down (&port->sem);	/* to lock against someone else trying to				   take an URB we just selected from the pool */	while (count > 0) {		/* try to find a free urb (write 0 bytes if none) */		struct urb *urb = NULL;		unsigned long flags;		int i;		/* since the pool is per-port we might not need the spin lock !? */		spin_lock_irqsave (&priv->write_urb_pool_lock, flags);		for (i=0; i<NUM_URBS; i++) {			if (priv->write_urb_pool[i]->status != -EINPROGRESS) {				urb = priv->write_urb_pool[i];				dbg(__FUNCTION__ " - using pool URB %d", i);				break;			}		}		spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);		if (urb==NULL) {			dbg (__FUNCTION__ " - no more free urbs");			goto exit;		}		if (urb->transfer_buffer == NULL) {			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);			if (urb->transfer_buffer == NULL) {				err(__FUNCTION__ " - no more kernel memory...");				goto exit;			}		}		size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET);		size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET);		if (from_user) {			if (copy_from_user(urb->transfer_buffer					   + KLSI_105_DATA_OFFSET, buf, size)) {				up (&port->sem);				return -EFAULT;			}		} else {			memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET,			       	buf, size);		}		/* write payload size into transfer buffer */		((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF);		((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8);		/* set up our urb */		FILL_BULK_URB(urb, serial->dev,			      usb_sndbulkpipe(serial->dev,					      port->bulk_out_endpointAddress),			      urb->transfer_buffer,			      URB_TRANSFER_BUFFER_SIZE,			      klsi_105_write_bulk_callback,			      port);		urb->transfer_flags |= USB_QUEUE_BULK;		/* send the data out the bulk port */		result = usb_submit_urb(urb);		if (result) {			err(__FUNCTION__			    " - failed submitting write urb, error %d", result);			goto exit;		}		buf += size;		bytes_sent += size;		count -= size;	}exit:	up (&port->sem);	priv->bytes_out+=bytes_sent;	return bytes_sent;	/* that's how much we wrote */} /* klsi_105_write */static void klsi_105_write_bulk_callback ( struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = port->serial;	dbg(__FUNCTION__ " - port %d", port->number);		if (!serial) {		dbg(__FUNCTION__ " - bad serial pointer, exiting");		return;	}	if (urb->status) {		dbg(__FUNCTION__ " - nonzero write bulk status received: %d",		    urb->status);		return;	}	/* from generic_write_bulk_callback */	queue_task(&port->tqueue, &tq_immediate);	mark_bh(IMMEDIATE_BH);	return;} /* klsi_105_write_bulk_completion_callback *//* return number of characters currently in the writing process */static int klsi_105_chars_in_buffer (struct usb_serial_port *port){	int chars = 0;	int i;	unsigned long flags;	struct klsi_105_private *priv = 		(struct klsi_105_private*) port->private;	spin_lock_irqsave (&priv->write_urb_pool_lock, flags);	for (i = 0; i < NUM_URBS; ++i) {		if (priv->write_urb_pool[i]->status == -EINPROGRESS) {			chars += URB_TRANSFER_BUFFER_SIZE;		}	}	spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);	dbg (__FUNCTION__ " - returns %d", chars);	return (chars);}static int klsi_105_write_room (struct usb_serial_port *port){	unsigned long flags;	int i;	int room = 0;	struct klsi_105_private *priv = 		(struct klsi_105_private*) port->private;	spin_lock_irqsave (&priv->write_urb_pool_lock, flags);	for (i = 0; i < NUM_URBS; ++i) {		if (priv->write_urb_pool[i]->status != -EINPROGRESS) {			room += URB_TRANSFER_BUFFER_SIZE;		}	}	spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);	dbg(__FUNCTION__ " - returns %d", room);	return (room);}static void klsi_105_read_bulk_callback (struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = port->serial;	struct klsi_105_private *priv = 		(struct klsi_105_private*) port->private;	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;	int rc;        dbg(__FUNCTION__ " - port %d", port->number);	/* The urb might have been killed. */        if (urb->status) {                dbg(__FUNCTION__ " - nonzero read bulk status received: %d",		    urb->status);                return;        }	if (!serial) {		dbg(__FUNCTION__ " - bad serial pointer, exiting");		return;	}		/* The data received is again preceded by a length double-byte in LSB-	 * first order (see klsi_105_write() )	 */	if (urb->actual_length == 0) {		/* empty urbs seem to happen, we ignore them */		/* dbg(__FUNCTION__ " - emtpy URB"); */	       ;	} else if (urb->actual_length <= 2) {		dbg(__FUNCTION__ " - size %d URB not understood",		    urb->actual_length);		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);	} else {		int i;		int bytes_sent = ((__u8 *) data)[0] +				 ((unsigned int) ((__u8 *) data)[1] << 8);		tty = port->tty;		/* we should immediately resubmit the URB, before attempting		 * to pass the data on to the tty layer. But that needs locking		 * against re-entry an then mixed-up data because of		 * intermixed tty_flip_buffer_push()s		 * FIXME		 */ 		usb_serial_debug_data (__FILE__, __FUNCTION__,				       urb->actual_length, data);		if (bytes_sent + 2 > urb->actual_length) {			dbg(__FUNCTION__ 			    " - trying to read more data than available"			    " (%d vs. %d)",			    bytes_sent+2, urb->actual_length);			/* cap at implied limit */

⌨️ 快捷键说明

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