📄 io_edgeport.c
字号:
struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; int status; if (port_paranoia_check (port, __FUNCTION__)) return; dbg(__FUNCTION__ " - port %d", port->number); serial = get_usb_serial (port, __FUNCTION__); if (!serial) return; edge_serial = (struct edgeport_serial *)serial->private; edge_port = (struct edgeport_port *)port->private; if ((edge_serial == NULL) || (edge_port == NULL)) return; --port->open_count; if (port->open_count <= 0) { if (serial->dev) { // block until tx is empty block_until_tx_empty(edge_port); edge_port->closePending = TRUE; /* flush and chase */ edge_port->chaseResponsePending = TRUE; dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT"); status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); if (status == 0) { // block until chase finished block_until_chase_response(edge_port); } else { edge_port->chaseResponsePending = FALSE; } /* close the port */ dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT"); send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0); //port->close = TRUE; edge_port->closePending = FALSE; edge_port->open = FALSE; edge_port->openPending = FALSE; if (edge_port->write_urb) { usb_unlink_urb (edge_port->write_urb); } } if (edge_port->write_urb) { /* if this urb had a transfer buffer already (old transfer) free it */ if (edge_port->write_urb->transfer_buffer != NULL) { kfree(edge_port->write_urb->transfer_buffer); } usb_free_urb (edge_port->write_urb); } if (edge_port->txfifo.fifo) { kfree(edge_port->txfifo.fifo); } port->active = 0; port->open_count = 0; } MOD_DEC_USE_COUNT; dbg(__FUNCTION__" exited");} /***************************************************************************** * SerialWrite * this function is called by the tty driver when data should be written to * the port. * If successful, we return the number of bytes written, otherwise we return * a negative error number. *****************************************************************************/static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count){ struct edgeport_port *edge_port = (struct edgeport_port *)port->private; struct TxFifo *fifo; int copySize; int bytesleft; int firsthalf; int secondhalf; dbg(__FUNCTION__ " - port %d", port->number); if (edge_port == NULL) return -ENODEV; // get a pointer to the Tx fifo fifo = &edge_port->txfifo; // calculate number of bytes to put in fifo copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count)); dbg(__FUNCTION__"(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", port->number, count, edge_port->txCredits - fifo->count, copySize); /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */ if (copySize == 0) { dbg (__FUNCTION__" - copySize = Zero"); return 0; } // queue the data // since we can never overflow the buffer we do not have to check for full condition // the copy is done is two parts -- first fill to the end of the buffer // then copy the reset from the start of the buffer bytesleft = fifo->size - fifo->head; firsthalf = min (bytesleft, copySize); dbg (__FUNCTION__" - copy %d bytes of %d into fifo ", firsthalf, bytesleft); /* now copy our data */ if (from_user) { if (copy_from_user(&fifo->fifo[fifo->head], data, firsthalf)) return -EFAULT; } else { memcpy(&fifo->fifo[fifo->head], data, firsthalf); } // update the index and size fifo->head += firsthalf; fifo->count += firsthalf; // wrap the index if (fifo->head == fifo->size) { fifo->head = 0; } secondhalf = copySize-firsthalf; if (secondhalf) { dbg (__FUNCTION__" - copy rest of data %d", secondhalf); if (from_user) { if (copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf)) return -EFAULT; } else { memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); } // update the index and size fifo->count += secondhalf; fifo->head += secondhalf; // No need to check for wrap since we can not get to end of fifo in this part } if (copySize) { usb_serial_debug_data (__FILE__, __FUNCTION__, copySize, data); } send_more_port_data((struct edgeport_serial *)port->serial->private, edge_port); dbg(__FUNCTION__" wrote %d byte(s) TxCredits %d, Fifo %d", copySize, edge_port->txCredits, fifo->count); return copySize; }/************************************************************************ * * send_more_port_data() * * This routine attempts to write additional UART transmit data * to a port over the USB bulk pipe. It is called (1) when new * data has been written to a port's TxBuffer from higher layers * (2) when the peripheral sends us additional TxCredits indicating * that it can accept more Tx data for a given port; and (3) when * a bulk write completes successfully and we want to see if we * can transmit more. * ************************************************************************/static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port){ struct TxFifo *fifo = &edge_port->txfifo; struct urb *urb; unsigned char *buffer; int status; int count; int bytesleft; int firsthalf; int secondhalf; dbg(__FUNCTION__"(%d)", edge_port->port->number); if (edge_port->write_in_progress || !edge_port->open || (fifo->count == 0)) { dbg(__FUNCTION__"(%d) EXIT - fifo %d, PendingWrite = %d", edge_port->port->number, fifo->count, edge_port->write_in_progress); return; } // since the amount of data in the fifo will always fit into the // edgeport buffer we do not need to check the write length // Do we have enough credits for this port to make it worthwhile // to bother queueing a write. If it's too small, say a few bytes, // it's better to wait for more credits so we can do a larger // write. if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) { dbg(__FUNCTION__"(%d) Not enough credit - fifo %d TxCredit %d", edge_port->port->number, fifo->count, edge_port->txCredits ); return; } // lock this write edge_port->write_in_progress = TRUE; // get a pointer to the write_urb urb = edge_port->write_urb; /* if this urb had a transfer buffer already (old transfer) free it */ if (urb->transfer_buffer != NULL) { kfree(urb->transfer_buffer); urb->transfer_buffer = NULL; } /* build the data header for the buffer and port that we are about to send out */ count = fifo->count; buffer = kmalloc (count+2, GFP_KERNEL); if (buffer == NULL) { err(__FUNCTION__" - no more kernel memory..."); edge_port->write_in_progress = FALSE; return; } buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number, count); buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number, count); /* now copy our data */ bytesleft = fifo->size - fifo->tail; firsthalf = min (bytesleft, count); memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf); fifo->tail += firsthalf; fifo->count -= firsthalf; if (fifo->tail == fifo->size) { fifo->tail = 0; } secondhalf = count-firsthalf; if (secondhalf) { memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf); fifo->tail += secondhalf; fifo->count -= secondhalf; } if (count) { usb_serial_debug_data (__FILE__, __FUNCTION__, count, &buffer[2]); } /* fill up the urb with all of our data and submit it */ FILL_BULK_URB (urb, edge_serial->serial->dev, usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint), buffer, count+2, edge_bulk_out_data_callback, edge_port); /* set the USB_BULK_QUEUE flag so that we can shove a bunch of urbs at once down the pipe */ urb->transfer_flags |= USB_QUEUE_BULK; urb->dev = edge_serial->serial->dev; status = usb_submit_urb(urb); if (status) { /* something went wrong */ dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed"); edge_port->write_in_progress = FALSE; } else { /* decrement the number of credits we have by the number we just sent */ edge_port->txCredits -= count; edge_port->icount.tx += count; } dbg(__FUNCTION__" wrote %d byte(s) TxCredit %d, Fifo %d", count, edge_port->txCredits, fifo->count);}/***************************************************************************** * edge_write_room * this function is called by the tty driver when it wants to know how many * bytes of data we can accept for a specific port. * If successful, we return the amount of room that we have for this port * (the txCredits), * Otherwise we return a negative error number. *****************************************************************************/static int edge_write_room (struct usb_serial_port *port){ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); int room; dbg(__FUNCTION__); if (edge_port == NULL) return -ENODEV; if (edge_port->closePending == TRUE) return -ENODEV; dbg(__FUNCTION__" - port %d", port->number); if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return -EINVAL; } // total of both buffers is still txCredit room = edge_port->txCredits - edge_port->txfifo.count; dbg(__FUNCTION__" - returns %d", room); return room;}/***************************************************************************** * edge_chars_in_buffer * this function is called by the tty driver when it wants to know how many * bytes of data we currently have outstanding in the port (data that has * been written, but hasn't made it out the port yet) * If successful, we return the number of bytes left to be written in the * system, * Otherwise we return a negative error number. *****************************************************************************/static int edge_chars_in_buffer (struct usb_serial_port *port){ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); int num_chars; dbg(__FUNCTION__); if (edge_port == NULL) return -ENODEV; if (edge_port->closePending == TRUE) return -ENODEV; if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return -EINVAL; } num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count; if (num_chars) { dbg(__FUNCTION__"(port %d) - returns %d", port->number, num_chars); } return num_chars;}/***************************************************************************** * SerialThrottle * this function is called by the tty driver when it wants to stop the data * being read from the port. *****************************************************************************/static void edge_throttle (struct usb_serial_port *port){ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); struct tty_struct *tty; int status; dbg(__FUNCTION__" - port %d", port->number); if (edge_port == NULL) return; if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return; } tty = port->tty; /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); status = edge_write (port, 0, &stop_char, 1); if (status <= 0) { return; } } /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios->c_cflag & CRTSCTS) { edge_port->shadowMCR &= ~MCR_RTS; status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); if (status != 0) { return; } } return;}/***************************************************************************** * edge_unthrottle * this function is called by the tty driver when it wants to resume the data * being read from the port (called after SerialThrottle is called) *****************************************************************************/static void edge_unthrottle (struct usb_serial_port *port){ struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); struct tty_struct *tty; int status; dbg(__FUNCTION__" - port %d", port->number); if (edge_port == NULL) return; if (!edge_port->open) { dbg (__FUNCTION__" - port not opened"); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -