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

📄 io_edgeport.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (length > 1) {			bytes_avail = data[0] | (data[1] << 8);			if (bytes_avail) {				spin_lock(&edge_serial->es_lock);				edge_serial->rxBytesAvail += bytes_avail;				dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);				if (edge_serial->rxBytesAvail > 0 &&				    !edge_serial->read_in_progress) {					dbg("%s - posting a read", __FUNCTION__);					edge_serial->read_in_progress = TRUE;					/* we have pending bytes on the bulk in pipe, send a request */					edge_serial->read_urb->dev = edge_serial->serial->dev;					result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);					if (result) {						dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result);						edge_serial->read_in_progress = FALSE;					}				}				spin_unlock(&edge_serial->es_lock);			}		}		/* grab the txcredits for the ports if available */		position = 2;		portNumber = 0;		while ((position < length) && (portNumber < edge_serial->serial->num_ports)) {			txCredits = data[position] | (data[position+1] << 8);			if (txCredits) {				port = edge_serial->serial->port[portNumber];				edge_port = usb_get_serial_port_data(port);				if (edge_port->open) {					spin_lock(&edge_port->ep_lock);					edge_port->txCredits += txCredits;					spin_unlock(&edge_port->ep_lock);					dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits);					/* tell the tty driver that something has changed */					if (edge_port->port->tty)						tty_wakeup(edge_port->port->tty);					// Since we have more credit, check if more data can be sent					send_more_port_data(edge_serial, edge_port);				}			}			position += 2;			++portNumber;		}	}exit:	result = usb_submit_urb (urb, GFP_ATOMIC);	if (result) {		dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, result);	}}/***************************************************************************** * 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 pt_regs *regs){	struct edgeport_serial	*edge_serial = (struct edgeport_serial *)urb->context;	unsigned char		*data = urb->transfer_buffer;	int			status;	__u16			raw_data_length;	dbg("%s", __FUNCTION__);	if (urb->status) {		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);		edge_serial->read_in_progress = FALSE;		return;	}	if (urb->actual_length == 0) {		dbg("%s - read bulk callback with no data", __FUNCTION__);		edge_serial->read_in_progress = FALSE;		return;	}	raw_data_length = urb->actual_length;	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data);	spin_lock(&edge_serial->es_lock);	/* decrement our rxBytes available by the number that we just got */	edge_serial->rxBytesAvail -= raw_data_length;	dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, 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) {		dbg("%s - posting a read", __FUNCTION__);		edge_serial->read_urb->dev = edge_serial->serial->dev;		status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);		if (status) {			dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status);			edge_serial->read_in_progress = FALSE;		}	} else {		edge_serial->read_in_progress = FALSE;	}	spin_unlock(&edge_serial->es_lock);}/***************************************************************************** * 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 pt_regs *regs){	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;	struct tty_struct *tty;	dbg("%s", __FUNCTION__);	if (urb->status) {		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);	}	tty = edge_port->port->tty;	if (tty && edge_port->open) {		/* let the tty driver wakeup if it has a special write_wakeup function */		tty_wakeup(tty);	}	// 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 *)(usb_get_serial_data(edge_port->port->serial)), 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 pt_regs *regs){	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;	struct tty_struct *tty;	int status = urb->status;	dbg("%s", __FUNCTION__);	CmdUrbs--;	dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, CmdUrbs);	/* clean up the transfer buffer */	if (urb->transfer_buffer != NULL) {		kfree(urb->transfer_buffer);	}	/* Free the command urb */	usb_free_urb (urb);	if (status) {		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status);		return;	}	/* Get pointer to tty */	tty = edge_port->port->tty;	/* tell the tty driver that something has changed */	if (tty && edge_port->open)		tty_wakeup(tty);	/* 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 = usb_get_serial_port_data(port);	struct usb_serial *serial;	struct edgeport_serial *edge_serial;	int response;	int timeout;	dbg("%s - port %d", __FUNCTION__, port->number);	if (edge_port == NULL)		return -ENODEV;	if (port->tty)		port->tty->low_latency = low_latency;	/* 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 = usb_get_serial_data(serial);	if (edge_serial == NULL) {		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 */		usb_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 */		usb_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);		edge_serial->read_in_progress = FALSE;		/* 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, GFP_KERNEL);		if (response) {			dev_err(&port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, 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) {		dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__);		edge_port->openPending = FALSE;		return -ENODEV;	}	/* now wait for the port to be completely 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("%s - open timedout", __FUNCTION__);		edge_port->openPending = FALSE;		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("%s - no memory", __FUNCTION__);		edge_close (port, filp);		return -ENOMEM;	}	/* Allocate a URB for the write */	edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);	edge_port->write_in_progress = FALSE;	if (!edge_port->write_urb) {		dbg("%s - no memory", __FUNCTION__);		edge_close (port, filp);		return -ENOMEM;	}	dbg("%s(%d) - Initialize TX fifo to %d bytes", __FUNCTION__, port->number, edge_port->maxTxCredits);	dbg("%s exited", __FUNCTION__);	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("%s - Got Chase Response", __FUNCTION__);			// did we get all of our credit back?			if (edge_port->txCredits == edge_port->maxTxCredits ) {				dbg("%s - Got all credits", __FUNCTION__);				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("%s - Chase TIMEOUT", __FUNCTION__);				return;			}		} else {			// Reset timout value back to 10 seconds			dbg("%s - Last %d, Current %d", __FUNCTION__, 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;

⌨️ 快捷键说明

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