📄 ti_usb_3410_5052.c
字号:
dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__); return; } config->wFlags = 0; /* these flags must be set */ config->wFlags |= TI_UART_ENABLE_MS_INTS; config->wFlags |= TI_UART_ENABLE_AUTO_START_DMA; config->bUartMode = (__u8)(tport->tp_uart_mode); switch (cflag & CSIZE) { case CS5: config->bDataBits = TI_UART_5_DATA_BITS; break; case CS6: config->bDataBits = TI_UART_6_DATA_BITS; break; case CS7: config->bDataBits = TI_UART_7_DATA_BITS; break; default: case CS8: config->bDataBits = TI_UART_8_DATA_BITS; break; } if (cflag & PARENB) { if (cflag & PARODD) { config->wFlags |= TI_UART_ENABLE_PARITY_CHECKING; config->bParity = TI_UART_ODD_PARITY; } else { config->wFlags |= TI_UART_ENABLE_PARITY_CHECKING; config->bParity = TI_UART_EVEN_PARITY; } } else { config->wFlags &= ~TI_UART_ENABLE_PARITY_CHECKING; config->bParity = TI_UART_NO_PARITY; } if (cflag & CSTOPB) config->bStopBits = TI_UART_2_STOP_BITS; else config->bStopBits = TI_UART_1_STOP_BITS; if (cflag & CRTSCTS) { /* RTS flow control must be off to drop RTS for baud rate B0 */ if ((cflag & CBAUD) != B0) config->wFlags |= TI_UART_ENABLE_RTS_IN; config->wFlags |= TI_UART_ENABLE_CTS_OUT; } else { tty->hw_stopped = 0; ti_restart_read(tport, tty); } if (I_IXOFF(tty) || I_IXON(tty)) { config->cXon = START_CHAR(tty); config->cXoff = STOP_CHAR(tty); if (I_IXOFF(tty)) config->wFlags |= TI_UART_ENABLE_X_IN; else ti_restart_read(tport, tty); if (I_IXON(tty)) config->wFlags |= TI_UART_ENABLE_X_OUT; } baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; if (tport->tp_tdev->td_is_3410) config->wBaudRate = (__u16)((923077 + baud/2) / baud); else config->wBaudRate = (__u16)((461538 + baud/2) / baud); dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d", __FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode); cpu_to_be16s(&config->wBaudRate); cpu_to_be16s(&config->wFlags); status = ti_command_out_sync(tport->tp_tdev, TI_SET_CONFIG, (__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config, sizeof(*config)); if (status) dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __FUNCTION__, port_number, status); /* SET_CONFIG asserts RTS and DTR, reset them correctly */ mcr = tport->tp_shadow_mcr; /* if baud rate is B0, clear RTS and DTR */ if ((cflag & CBAUD) == B0) mcr &= ~(TI_MCR_DTR | TI_MCR_RTS); status = ti_set_mcr(tport, mcr); if (status) dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __FUNCTION__, port_number, status); kfree(config);}static int ti_tiocmget(struct usb_serial_port *port, struct file *file){ struct ti_port *tport = usb_get_serial_port_data(port); unsigned int result; unsigned int msr; unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return -ENODEV; msr = tport->tp_msr; mcr = tport->tp_shadow_mcr; result = ((mcr & TI_MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & TI_MCR_RTS) ? TIOCM_RTS : 0) | ((mcr & TI_MCR_LOOP) ? TIOCM_LOOP : 0) | ((msr & TI_MSR_CTS) ? TIOCM_CTS : 0) | ((msr & TI_MSR_CD) ? TIOCM_CAR : 0) | ((msr & TI_MSR_RI) ? TIOCM_RI : 0) | ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0); dbg("%s - 0x%04X", __FUNCTION__, result); return result;}static int ti_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear){ struct ti_port *tport = usb_get_serial_port_data(port); unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return -ENODEV; mcr = tport->tp_shadow_mcr; if (set & TIOCM_RTS) mcr |= TI_MCR_RTS; if (set & TIOCM_DTR) mcr |= TI_MCR_DTR; if (set & TIOCM_LOOP) mcr |= TI_MCR_LOOP; if (clear & TIOCM_RTS) mcr &= ~TI_MCR_RTS; if (clear & TIOCM_DTR) mcr &= ~TI_MCR_DTR; if (clear & TIOCM_LOOP) mcr &= ~TI_MCR_LOOP; return ti_set_mcr(tport, mcr);}static void ti_break(struct usb_serial_port *port, int break_state){ struct ti_port *tport = usb_get_serial_port_data(port); int status; dbg("%s - state = %d", __FUNCTION__, break_state); if (tport == NULL) return; ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0); status = ti_write_byte(tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); if (status) dbg("%s - error setting break, %d", __FUNCTION__, status);}static void ti_interrupt_callback(struct urb *urb, struct pt_regs *regs){ struct ti_device *tdev = (struct ti_device *)urb->context; struct usb_serial_port *port; struct usb_serial *serial = tdev->td_serial; struct ti_port *tport; struct device *dev = &urb->dev->dev; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; int port_number; int function; int status; __u8 msr; dbg("%s", __FUNCTION__); switch (urb->status) { case 0: break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status); tdev->td_urb_error = 1; return; default: dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status); tdev->td_urb_error = 1; goto exit; } if (length != 2) { dbg("%s - bad packet size, %d", __FUNCTION__, length); goto exit; } if (data[0] == TI_CODE_HARDWARE_ERROR) { dev_err(dev, "%s - hardware error, %d\n", __FUNCTION__, data[1]); goto exit; } port_number = TI_GET_PORT_FROM_CODE(data[0]); function = TI_GET_FUNC_FROM_CODE(data[0]); dbg("%s - port_number %d, function %d, data 0x%02X", __FUNCTION__, port_number, function, data[1]); if (port_number >= serial->num_ports) { dev_err(dev, "%s - bad port number, %d\n", __FUNCTION__, port_number); goto exit; } port = serial->port[port_number]; tport = usb_get_serial_port_data(port); if (!tport) goto exit; switch (function) { case TI_CODE_DATA_ERROR: dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __FUNCTION__, port_number, data[1]); break; case TI_CODE_MODEM_STATUS: msr = data[1]; dbg("%s - port %d, msr 0x%02X", __FUNCTION__, port_number, msr); ti_handle_new_msr(tport, msr); break; default: dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __FUNCTION__, data[1]); break; }exit: status = usb_submit_urb(urb, GFP_ATOMIC); if (status) dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", __FUNCTION__, status);}static void ti_bulk_in_callback(struct urb *urb, struct pt_regs *regs){ struct ti_port *tport = (struct ti_port *)urb->context; struct usb_serial_port *port = tport->tp_port; struct device *dev = &urb->dev->dev; int status = 0; dbg("%s", __FUNCTION__); switch (urb->status) { case 0: break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); return; default: dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status ); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); } if (urb->status == -EPIPE) goto exit; if (urb->status) { dev_err(dev, "%s - stopping read!\n", __FUNCTION__); return; } if (port->tty && urb->actual_length) { usb_serial_debug_data(debug, dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer); if (!tport->tp_is_open) dbg("%s - port closed, dropping data", __FUNCTION__); else ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer, urb->actual_length); spin_lock(&tport->tp_lock); tport->tp_icount.rx += urb->actual_length; spin_unlock(&tport->tp_lock); }exit: /* continue to read unless stopping */ spin_lock(&tport->tp_lock); if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) { urb->dev = port->serial->dev; status = usb_submit_urb(urb, GFP_ATOMIC); } else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) { tport->tp_read_urb_state = TI_READ_URB_STOPPED; } spin_unlock(&tport->tp_lock); if (status) dev_err(dev, "%s - resubmit read urb failed, %d\n", __FUNCTION__, status);}static void ti_bulk_out_callback(struct urb *urb, struct pt_regs *regs){ struct ti_port *tport = (struct ti_port *)urb->context; struct usb_serial_port *port = tport->tp_port; struct device *dev = &urb->dev->dev; dbg("%s - port %d", __FUNCTION__, port->number); tport->tp_write_urb_in_use = 0; switch (urb->status) { case 0: break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); return; default: dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); } /* send any buffered data */ ti_send(tport);}static void ti_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length){ int cnt; do { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length); return; } } cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); memcpy(tty->flip.char_buf_ptr, data, cnt); memset(tty->flip.flag_buf_ptr, 0, cnt); tty->flip.char_buf_ptr += cnt; tty->flip.flag_buf_ptr += cnt; tty->flip.count += cnt; data += cnt; length -= cnt; } while (length > 0); tty_flip_buffer_push(tty);}static void ti_send(struct ti_port *tport){ int count, result; struct usb_serial_port *port = tport->tp_port; struct tty_struct *tty = port->tty; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&tport->tp_lock, flags); if (tport->tp_write_urb_in_use) { spin_unlock_irqrestore(&tport->tp_lock, flags); return; } count = ti_buf_get(tport->tp_write_buf, port->write_urb->transfer_buffer, port->bulk_out_size); if (count == 0) { spin_unlock_irqrestore(&tport->tp_lock, flags); return; } tport->tp_write_urb_in_use = 1; spin_unlock_irqrestore(&tport->tp_lock, flags); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, count, ti_bulk_out_callback, tport); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, "%s - submit write urb failed, %d\n", __FUNCTION__, result); tport->tp_write_urb_in_use = 0; /* TODO: reschedule ti_send */ } else { spin_lock_irqsave(&tport->tp_lock, flags); tport->tp_icount.tx += count; spin_unlock_irqrestore(&tport->tp_lock, flags); } /* more room in the buffer for new writes, wakeup */ if (tty) tty_wakeup(tty); wake_up_interruptible(&tport->tp_write_wait);}static int ti_set_mcr(struct ti_port *tport, unsigned int mcr){ int status; status = ti_write_byte(tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_MCR, TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr); if (!status) tport->tp_shadow_mcr = mcr; return status;}static int ti_get_lsr(struct ti_port *tport){ int size,status; struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; int port_number = port->number - port->serial->minor; struct ti_port_status *data; dbg("%s - port %d", __FUNCTION__, port->number);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -