📄 ti_usb_3410_5052.c
字号:
} /* set up port structures */ for (i = 0; i < serial->num_ports; ++i) { tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL); if (tport == NULL) { dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); status = -ENOMEM; goto free_tports; } memset(tport, 0, sizeof(struct ti_port)); spin_lock_init(&tport->tp_lock); tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0; tport->tp_closing_wait = closing_wait; init_waitqueue_head(&tport->tp_msr_wait); init_waitqueue_head(&tport->tp_write_wait); tport->tp_write_buf = ti_buf_alloc(); if (tport->tp_write_buf == NULL) { dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); kfree(tport); status = -ENOMEM; goto free_tports; } tport->tp_port = serial->port[i]; tport->tp_tdev = tdev; usb_set_serial_port_data(serial->port[i], tport); tport->tp_uart_mode = 0; /* default is RS232 */ } return 0;free_tports: for (--i; i>=0; --i) { tport = usb_get_serial_port_data(serial->port[i]); ti_buf_free(tport->tp_write_buf); kfree(tport); usb_set_serial_port_data(serial->port[i], NULL); }free_tdev: kfree(tdev); usb_set_serial_data(serial, NULL); return status;}static void ti_shutdown(struct usb_serial *serial){ int i; struct ti_device *tdev = usb_get_serial_data(serial); struct ti_port *tport; dbg("%s", __FUNCTION__); for (i=0; i < serial->num_ports; ++i) { tport = usb_get_serial_port_data(serial->port[i]); if (tport) { ti_buf_free(tport->tp_write_buf); kfree(tport); usb_set_serial_port_data(serial->port[i], NULL); } } kfree(tdev); usb_set_serial_data(serial, NULL);}static int ti_open(struct usb_serial_port *port, struct file *file){ struct ti_port *tport = usb_get_serial_port_data(port); struct ti_device *tdev; struct usb_device *dev; struct urb *urb; int port_number; int status; __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS | TI_PIPE_TIMEOUT_ENABLE | (TI_TRANSFER_TIMEOUT << 2)); dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return -ENODEV; dev = port->serial->dev; tdev = tport->tp_tdev; /* only one open on any port on a device at a time */ if (down_interruptible(&tdev->td_open_close_sem)) return -ERESTARTSYS; if (port->tty) port->tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; port_number = port->number - port->serial->minor; memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount)); tport->tp_msr = 0; tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); /* start interrupt urb the first time a port is opened on this device */ if (tdev->td_open_port_count == 0) { dbg("%s - start interrupt in urb", __FUNCTION__); urb = tdev->td_serial->port[0]->interrupt_in_urb; if (!urb) { dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__); status = -EINVAL; goto up_sem; } urb->complete = ti_interrupt_callback; urb->context = tdev; urb->dev = dev; status = usb_submit_urb(urb, GFP_KERNEL); if (status) { dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status); goto up_sem; } } ti_set_termios(port, NULL); dbg("%s - sending TI_OPEN_PORT", __FUNCTION__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot send open command, %d\n", __FUNCTION__, status); goto unlink_int_urb; } dbg("%s - sending TI_START_PORT", __FUNCTION__); status = ti_command_out_sync(tdev, TI_START_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot send start command, %d\n", __FUNCTION__, status); goto unlink_int_urb; } dbg("%s - sending TI_PURGE_PORT", __FUNCTION__); status = ti_command_out_sync(tdev, TI_PURGE_PORT, (__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __FUNCTION__, status); goto unlink_int_urb; } status = ti_command_out_sync(tdev, TI_PURGE_PORT, (__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __FUNCTION__, status); goto unlink_int_urb; } /* reset the data toggle on the bulk endpoints to work around bug in * host controllers where things get out of sync some times */ usb_clear_halt(dev, port->write_urb->pipe); usb_clear_halt(dev, port->read_urb->pipe); ti_set_termios(port, NULL); dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __FUNCTION__, status); goto unlink_int_urb; } dbg("%s - sending TI_START_PORT (2)", __FUNCTION__); status = ti_command_out_sync(tdev, TI_START_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __FUNCTION__, status); goto unlink_int_urb; } /* start read urb */ dbg("%s - start read urb", __FUNCTION__); urb = port->read_urb; if (!urb) { dev_err(&port->dev, "%s - no read urb\n", __FUNCTION__); status = -EINVAL; goto unlink_int_urb; } tport->tp_read_urb_state = TI_READ_URB_RUNNING; urb->complete = ti_bulk_in_callback; urb->context = tport; urb->dev = dev; status = usb_submit_urb(urb, GFP_KERNEL); if (status) { dev_err(&port->dev, "%s - submit read urb failed, %d\n", __FUNCTION__, status); goto unlink_int_urb; } tport->tp_is_open = 1; ++tdev->td_open_port_count; goto up_sem;unlink_int_urb: if (tdev->td_open_port_count == 0) usb_kill_urb(port->serial->port[0]->interrupt_in_urb);up_sem: up(&tdev->td_open_close_sem); dbg("%s - exit %d", __FUNCTION__, status); return status;}static void ti_close(struct usb_serial_port *port, struct file *file){ struct ti_device *tdev; struct ti_port *tport; int port_number; int status; int do_up; dbg("%s - port %d", __FUNCTION__, port->number); tdev = usb_get_serial_data(port->serial); tport = usb_get_serial_port_data(port); if (tdev == NULL || tport == NULL) return; tport->tp_is_open = 0; ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1); usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); tport->tp_write_urb_in_use = 0; port_number = port->number - port->serial->minor; dbg("%s - sending TI_CLOSE_PORT", __FUNCTION__); status = ti_command_out_sync(tdev, TI_CLOSE_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status); /* if down is interrupted, continue anyway */ do_up = !down_interruptible(&tdev->td_open_close_sem); --tport->tp_tdev->td_open_port_count; if (tport->tp_tdev->td_open_port_count <= 0) { /* last port is closed, shut down interrupt urb */ usb_kill_urb(port->serial->port[0]->interrupt_in_urb); tport->tp_tdev->td_open_port_count = 0; } if (do_up) up(&tdev->td_open_close_sem); dbg("%s - exit", __FUNCTION__);}static int ti_write(struct usb_serial_port *port, const unsigned char *data, int count){ struct ti_port *tport = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); if (count == 0) { dbg("%s - write request of 0 bytes", __FUNCTION__); return 0; } if (tport == NULL || !tport->tp_is_open) return -ENODEV; spin_lock_irqsave(&tport->tp_lock, flags); count = ti_buf_put(tport->tp_write_buf, data, count); spin_unlock_irqrestore(&tport->tp_lock, flags); ti_send(tport); return count;}static int ti_write_room(struct usb_serial_port *port){ struct ti_port *tport = usb_get_serial_port_data(port); int room = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return -ENODEV; spin_lock_irqsave(&tport->tp_lock, flags); room = ti_buf_space_avail(tport->tp_write_buf); spin_unlock_irqrestore(&tport->tp_lock, flags); dbg("%s - returns %d", __FUNCTION__, room); return room;}static int ti_chars_in_buffer(struct usb_serial_port *port){ struct ti_port *tport = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return -ENODEV; spin_lock_irqsave(&tport->tp_lock, flags); chars = ti_buf_data_avail(tport->tp_write_buf); spin_unlock_irqrestore(&tport->tp_lock, flags); dbg("%s - returns %d", __FUNCTION__, chars); return chars;}static void ti_throttle(struct usb_serial_port *port){ struct ti_port *tport = usb_get_serial_port_data(port); struct tty_struct *tty; dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return; tty = port->tty; if (!tty) { dbg("%s - no tty", __FUNCTION__); return; } if (I_IXOFF(tty) || C_CRTSCTS(tty)) ti_stop_read(tport, tty);}static void ti_unthrottle(struct usb_serial_port *port){ struct ti_port *tport = usb_get_serial_port_data(port); struct tty_struct *tty; int status; dbg("%s - port %d", __FUNCTION__, port->number); if (tport == NULL) return; tty = port->tty; if (!tty) { dbg("%s - no tty", __FUNCTION__); return; } if (I_IXOFF(tty) || C_CRTSCTS(tty)) { status = ti_restart_read(tport, tty); if (status) dev_err(&port->dev, "%s - cannot restart read, %d\n", __FUNCTION__, status); }}static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg){ struct ti_port *tport = usb_get_serial_port_data(port); struct async_icount cnow; struct async_icount cprev; dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd); if (tport == NULL) return -ENODEV; switch (cmd) { case TIOCGSERIAL: dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number); return ti_get_serial_info(tport, (struct serial_struct __user *)arg); break; case TIOCSSERIAL: dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number); return ti_set_serial_info(tport, (struct serial_struct __user *)arg); break; case TIOCMIWAIT: dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number); cprev = tport->tp_icount; while (1) { interruptible_sleep_on(&tport->tp_msr_wait); if (signal_pending(current)) return -ERESTARTSYS; cnow = tport->tp_icount; if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { return 0; } cprev = cnow; } break; case TIOCGICOUNT: dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, tport->tp_icount.rx, tport->tp_icount.tx); if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount))) return -EFAULT; return 0; } return -ENOIOCTLCMD;}static void ti_set_termios(struct usb_serial_port *port, struct termios *old_termios){ struct ti_port *tport = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; struct ti_uart_config *config; tcflag_t cflag,iflag; int baud; int status; int port_number = port->number - port->serial->minor; unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); if (!tty || !tty->termios) { dbg("%s - no tty or termios", __FUNCTION__); return; } cflag = tty->termios->c_cflag; iflag = tty->termios->c_iflag; if (old_termios && cflag == old_termios->c_cflag && iflag == old_termios->c_iflag) { dbg("%s - nothing to change", __FUNCTION__); return; } dbg("%s - clfag %08x, iflag %08x", __FUNCTION__, cflag, iflag); if (old_termios) dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag); if (tport == NULL) return; config = kmalloc(sizeof(*config), GFP_KERNEL); if (!config) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -