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

📄 io_edgeport.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			}			position += 2;			++portNumber;		}	}}/***************************************************************************** * edge_bulk_in_callback *	this is the callback function for when we have received data on the  *	bulk in endpoint. *****************************************************************************/static void edge_bulk_in_callback (struct urb *urb){	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;	unsigned char		*data = urb->transfer_buffer;	int			status;	__u16			raw_data_length;	dbg(__FUNCTION__);	if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) {		return;	}	if (urb->status) {		dbg(__FUNCTION__" - nonzero read bulk status received: %d", urb->status);		return;	}	if (urb->actual_length) {		raw_data_length = urb->actual_length;		usb_serial_debug_data (__FILE__, __FUNCTION__, raw_data_length, data);		/* decrement our rxBytes available by the number that we just got */		edge_serial->rxBytesAvail -= raw_data_length;		dbg(__FUNCTION__" - Received = %d, rxBytesAvail %d", raw_data_length, edge_serial->rxBytesAvail);		process_rcvd_data (edge_serial, data, urb->actual_length);		/* check to see if there's any more data for us to read */		if ((edge_serial->rxBytesAvail > 0) &&		    (edge_serial->read_urb->status != -EINPROGRESS)) {			dbg(" --- Posting a read");			/* there is, so resubmit our urb */			edge_serial->read_urb->dev = edge_serial->serial->dev;			status = usb_submit_urb(edge_serial->read_urb);			if (status) {				err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);			}		}	}}/***************************************************************************** * edge_bulk_out_data_callback *	this is the callback function for when we have finished sending serial data *	on the bulk out endpoint. *****************************************************************************/static void edge_bulk_out_data_callback (struct urb *urb){	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;	struct tty_struct *tty;	dbg(__FUNCTION__);	if (port_paranoia_check (edge_port->port, __FUNCTION__)) {		return;	}	if (urb->status) {		dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status);	}	tty = edge_port->port->tty;	/* let the tty driver wakeup if it has a special write_wakeup function */	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {		(tty->ldisc.write_wakeup)(tty);	}	/* tell the tty driver that something has changed */	wake_up_interruptible(&tty->write_wait);	// Release the Write URB	edge_port->write_in_progress = FALSE;	// Check if more data needs to be sent	send_more_port_data((struct edgeport_serial *)(edge_port->port->serial->private), edge_port);}/***************************************************************************** * BulkOutCmdCallback *	this is the callback function for when we have finished sending a command *	on the bulk out endpoint. *****************************************************************************/static void edge_bulk_out_cmd_callback (struct urb *urb){	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;	struct tty_struct *tty;	int status = urb->status;	dbg(__FUNCTION__);	CmdUrbs--;	dbg(__FUNCTION__" - FREE URB %p (outstanding %d)", urb, CmdUrbs);	/* clean up the transfer buffer */	if (urb->transfer_buffer != NULL) {		kfree(urb->transfer_buffer);	}	// Free the command urb	usb_unlink_urb (urb);	usb_free_urb   (urb);	if (port_paranoia_check (edge_port->port, __FUNCTION__)) {		return;	}	if (status) {		dbg(__FUNCTION__" - nonzero write bulk status received: %d", status);		return;	}	/* Get pointer to tty */	tty = edge_port->port->tty;	/* tell the tty driver that something has changed */	wake_up_interruptible(&tty->write_wait);	/* we have completed the command */	edge_port->commandPending = FALSE;	wake_up_interruptible(&edge_port->wait_command);}/***************************************************************************** * Driver tty interface functions *****************************************************************************//***************************************************************************** * SerialOpen *	this function is called by the tty driver when a port is opened *	If successful, we return 0 *	Otherwise we return a negative error number. *****************************************************************************/static int edge_open (struct usb_serial_port *port, struct file * filp){	struct edgeport_port *edge_port = (struct edgeport_port *)port->private;	struct usb_serial *serial;	struct edgeport_serial *edge_serial;	int response;	int timeout;	if (port_paranoia_check (port, __FUNCTION__))		return -ENODEV;		dbg(__FUNCTION__ " - port %d", port->number);	if (edge_port == NULL)		return -ENODEV;	++port->open_count;	MOD_INC_USE_COUNT;		if (!port->active) {		port->active = 1;		/* force low_latency on so that our tty_push actually forces the data through, 		   otherwise it is scheduled, and with high data rates (like with OHCI) data		   can get lost. */		port->tty->low_latency = 1;			/* see if we've set up our endpoint info yet (can't set it up in edge_startup		   as the structures were not set up at that time.) */		serial = port->serial;		edge_serial = (struct edgeport_serial *)serial->private;		if (edge_serial == NULL) {			port->active = 0;			port->open_count = 0;			MOD_DEC_USE_COUNT;			return -ENODEV;		}		if (edge_serial->interrupt_in_buffer == NULL) {			struct usb_serial_port *port0 = &serial->port[0];						/* not set up yet, so do it now */			edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;			edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;			edge_serial->interrupt_read_urb = port0->interrupt_in_urb;			edge_serial->bulk_in_buffer = port0->bulk_in_buffer;			edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;			edge_serial->read_urb = port0->read_urb;			edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;					/* set up our interrupt urb */			FILL_INT_URB(edge_serial->interrupt_read_urb,				     serial->dev,				     usb_rcvintpipe(serial->dev,					            port0->interrupt_in_endpointAddress),				     port0->interrupt_in_buffer,				     edge_serial->interrupt_read_urb->transfer_buffer_length,				     edge_interrupt_callback, edge_serial,				     edge_serial->interrupt_read_urb->interval);						/* set up our bulk in urb */			FILL_BULK_URB(edge_serial->read_urb, serial->dev,				      usb_rcvbulkpipe(serial->dev, port0->bulk_in_endpointAddress),				      port0->bulk_in_buffer,				      edge_serial->read_urb->transfer_buffer_length,				      edge_bulk_in_callback, edge_serial);			/* start interrupt read for this edgeport			 * this interrupt will continue as long as the edgeport is connected */			response = usb_submit_urb (edge_serial->interrupt_read_urb);			if (response) {				err(__FUNCTION__" - Error %d submitting control urb", response);			}		}				/* initialize our wait queues */		init_waitqueue_head(&edge_port->wait_open);		init_waitqueue_head(&edge_port->wait_chase);		init_waitqueue_head(&edge_port->delta_msr_wait);		init_waitqueue_head(&edge_port->wait_command);		/* initialize our icount structure */		memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));		/* initialize our port settings */		edge_port->txCredits            = 0;			/* Can't send any data yet */		edge_port->shadowMCR            = MCR_MASTER_IE;	/* Must always set this bit to enable ints! */		edge_port->chaseResponsePending = FALSE;		/* send a open port command */		edge_port->openPending = TRUE;		edge_port->open        = FALSE;		response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);		if (response < 0) {			err(__FUNCTION__" - error sending open port command");			edge_port->openPending = FALSE;			port->active = 0;			port->open_count = 0;			MOD_DEC_USE_COUNT;			return -ENODEV;		}		/* now wait for the port to be completly opened */		timeout = OPEN_TIMEOUT;		while (timeout && edge_port->openPending == TRUE) {			timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout);		}		if (edge_port->open == FALSE) {			/* open timed out */			dbg(__FUNCTION__" - open timedout");			edge_port->openPending = FALSE;			port->active = 0;			port->open_count = 0;			MOD_DEC_USE_COUNT;			return -ENODEV;		}		/* create the txfifo */		edge_port->txfifo.head	= 0;		edge_port->txfifo.tail	= 0;		edge_port->txfifo.count	= 0;		edge_port->txfifo.size	= edge_port->maxTxCredits;		edge_port->txfifo.fifo	= kmalloc (edge_port->maxTxCredits, GFP_KERNEL);		if (!edge_port->txfifo.fifo) {			dbg(__FUNCTION__" - no memory");			edge_close (port, filp);			return -ENOMEM;		}		/* Allocate a URB for the write */		edge_port->write_urb = usb_alloc_urb (0);		if (!edge_port->write_urb) {			dbg(__FUNCTION__" - no memory");			edge_close (port, filp);			return -ENOMEM;		}		dbg(__FUNCTION__"(%d) - Initialize TX fifo to %d bytes", port->number, edge_port->maxTxCredits);	}	dbg(__FUNCTION__" exited");	return 0;}/************************************************************************ * * block_until_chase_response * *	This function will block the close until one of the following: *		1. Response to our Chase comes from Edgeport *		2. A timout of 10 seconds without activity has expired *		   (1K of Edgeport data @ 2400 baud ==> 4 sec to empty) * ************************************************************************/static void block_until_chase_response(struct edgeport_port *edge_port){	__u16 lastCredits;	int timeout = 1*HZ;	int wait = 10;	while (1) {		// Save Last credits		lastCredits = edge_port->txCredits;		// Did we get our Chase response		if (edge_port->chaseResponsePending == FALSE) {			dbg(__FUNCTION__" - Got Chase Response");			// did we get all of our credit back?			if (edge_port->txCredits == edge_port->maxTxCredits ) {				dbg(__FUNCTION__" - Got all credits");				return;			}		}		// Block the thread for a while		interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);		if (lastCredits == edge_port->txCredits) {			// No activity.. count down.			wait--;			if (wait == 0) {				edge_port->chaseResponsePending = FALSE;				dbg(__FUNCTION__" - Chase TIMEOUT");				return;			}		} else {			// Reset timout value back to 10 seconds			dbg(__FUNCTION__" - Last %d, Current %d", lastCredits, edge_port->txCredits);			wait = 10;		}	}}/************************************************************************ * * block_until_tx_empty * *	This function will block the close until one of the following: *		1. TX count are 0 *		2. The edgeport has stopped *		3. A timout of 3 seconds without activity has expired * ************************************************************************/static void block_until_tx_empty (struct edgeport_port *edge_port){	struct TxFifo *fifo = &edge_port->txfifo;	__u32 lastCount;	int timeout = HZ/10;	int wait = 30;	while (1) {		// Save Last count		lastCount = fifo->count;		// Is the Edgeport Buffer empty?		if (lastCount == 0) {			dbg(__FUNCTION__" - TX Buffer Empty");			return;		}		// Block the thread for a while		interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);		dbg(__FUNCTION__ " wait");		if (lastCount == fifo->count) {			// No activity.. count down.			wait--;			if (wait == 0) {				dbg(__FUNCTION__" - TIMEOUT");				return;			}		} else {			// Reset timout value back to seconds			wait = 30;		}	}}/***************************************************************************** * edge_close *	this function is called by the tty driver when a port is closed *****************************************************************************/static void edge_close (struct usb_serial_port *port, struct file * filp){	struct usb_serial *serial;

⌨️ 快捷键说明

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