📄 io_edgeport.c
字号:
} 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 + -