📄 ti_usb_3410_5052.c
字号:
size = sizeof(struct ti_port_status); data = kmalloc(size, GFP_KERNEL); if (!data) { dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS, (__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size); if (status) { dev_err(&port->dev, "%s - get port status command failed, %d\n", __FUNCTION__, status); goto free_data; } dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR); tport->tp_lsr = data->bLSR;free_data: kfree(data); return status;}static int ti_get_serial_info(struct ti_port *tport, struct serial_struct __user *ret_arg){ struct usb_serial_port *port = tport->tp_port; struct serial_struct ret_serial; if (!ret_arg) return -EFAULT; memset(&ret_serial, 0, sizeof(ret_serial)); ret_serial.type = PORT_16550A; ret_serial.line = port->serial->minor; ret_serial.port = port->number - port->serial->minor; ret_serial.flags = tport->tp_flags; ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; ret_serial.closing_wait = tport->tp_closing_wait; if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg))) return -EFAULT; return 0;}static int ti_set_serial_info(struct ti_port *tport, struct serial_struct __user *new_arg){ struct usb_serial_port *port = tport->tp_port; struct serial_struct new_serial; if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) return -EFAULT; tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; if (port->tty) port->tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; tport->tp_closing_wait = new_serial.closing_wait; return 0;}static void ti_handle_new_msr(struct ti_port *tport, __u8 msr){ struct async_icount *icount; struct tty_struct *tty; unsigned long flags; dbg("%s - msr 0x%02X", __FUNCTION__, msr); if (msr & TI_MSR_DELTA_MASK) { spin_lock_irqsave(&tport->tp_lock, flags); icount = &tport->tp_icount; if (msr & TI_MSR_DELTA_CTS) icount->cts++; if (msr & TI_MSR_DELTA_DSR) icount->dsr++; if (msr & TI_MSR_DELTA_CD) icount->dcd++; if (msr & TI_MSR_DELTA_RI) icount->rng++; wake_up_interruptible(&tport->tp_msr_wait); spin_unlock_irqrestore(&tport->tp_lock, flags); } tport->tp_msr = msr & TI_MSR_MASK; /* handle CTS flow control */ tty = tport->tp_port->tty; if (tty && C_CRTSCTS(tty)) { if (msr & TI_MSR_CTS) { tty->hw_stopped = 0; tty_wakeup(tty); } else { tty->hw_stopped = 1; } }}static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush){ struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; wait_queue_t wait; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&tport->tp_lock, flags); /* wait for data to drain from the buffer */ tdev->td_urb_error = 0; init_waitqueue_entry(&wait, current); add_wait_queue(&tport->tp_write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (ti_buf_data_avail(tport->tp_write_buf) == 0 || timeout == 0 || signal_pending(current) || tdev->td_urb_error || !usb_get_intfdata(port->serial->interface)) /* disconnect */ break; spin_unlock_irqrestore(&tport->tp_lock, flags); timeout = schedule_timeout(timeout); spin_lock_irqsave(&tport->tp_lock, flags); } set_current_state(TASK_RUNNING); remove_wait_queue(&tport->tp_write_wait, &wait); /* flush any remaining data in the buffer */ if (flush) ti_buf_clear(tport->tp_write_buf); spin_unlock_irqrestore(&tport->tp_lock, flags); /* wait for data to drain from the device */ /* wait for empty tx register, plus 20 ms */ timeout += jiffies; tport->tp_lsr &= ~TI_LSR_TX_EMPTY; while ((long)(jiffies - timeout) < 0 && !signal_pending(current) && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error && usb_get_intfdata(port->serial->interface)) { /* not disconnected */ if (ti_get_lsr(tport)) break; msleep_interruptible(20); }}static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty){ unsigned long flags; spin_lock_irqsave(&tport->tp_lock, flags); if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) tport->tp_read_urb_state = TI_READ_URB_STOPPING; spin_unlock_irqrestore(&tport->tp_lock, flags);}static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty){ struct urb *urb; int status = 0; unsigned long flags; spin_lock_irqsave(&tport->tp_lock, flags); if (tport->tp_read_urb_state == TI_READ_URB_STOPPED) { urb = tport->tp_port->read_urb; urb->complete = ti_bulk_in_callback; urb->context = tport; urb->dev = tport->tp_port->serial->dev; status = usb_submit_urb(urb, GFP_KERNEL); } tport->tp_read_urb_state = TI_READ_URB_RUNNING; spin_unlock_irqrestore(&tport->tp_lock, flags); return status;}static int ti_command_out_sync(struct ti_device *tdev, __u8 command, __u16 moduleid, __u16 value, __u8 *data, int size){ int status; status = usb_control_msg(tdev->td_serial->dev, usb_sndctrlpipe(tdev->td_serial->dev, 0), command, (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT), value, moduleid, data, size, 1000); if (status == size) status = 0; if (status > 0) status = -ECOMM; return status;}static int ti_command_in_sync(struct ti_device *tdev, __u8 command, __u16 moduleid, __u16 value, __u8 *data, int size){ int status; status = usb_control_msg(tdev->td_serial->dev, usb_rcvctrlpipe(tdev->td_serial->dev, 0), command, (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN), value, moduleid, data, size, 1000); if (status == size) status = 0; if (status > 0) status = -ECOMM; return status;}static int ti_write_byte(struct ti_device *tdev, unsigned long addr, __u8 mask, __u8 byte){ int status; unsigned int size; struct ti_write_data_bytes *data; struct device *dev = &tdev->td_serial->dev->dev; dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __FUNCTION__, addr, mask, byte); size = sizeof(struct ti_write_data_bytes) + 2; data = kmalloc(size, GFP_KERNEL); if (!data) { dev_err(dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } data->bAddrType = TI_RW_DATA_ADDR_XDATA; data->bDataType = TI_RW_DATA_BYTE; data->bDataCounter = 1; data->wBaseAddrHi = cpu_to_be16(addr>>16); data->wBaseAddrLo = cpu_to_be16(addr); data->bData[0] = mask; data->bData[1] = byte; status = ti_command_out_sync(tdev, TI_WRITE_DATA, TI_RAM_PORT, 0, (__u8 *)data, size); if (status < 0) dev_err(dev, "%s - failed, %d\n", __FUNCTION__, status); kfree(data); return status;}static int ti_download_firmware(struct ti_device *tdev, unsigned char *firmware, unsigned int firmware_size){ int status = 0; int buffer_size; int pos; int len; int done; __u8 cs = 0; __u8 *buffer; struct usb_device *dev = tdev->td_serial->dev; struct ti_firmware_header *header; unsigned int pipe = usb_sndbulkpipe(dev, tdev->td_serial->port[0]->bulk_out_endpointAddress); buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header); buffer = kmalloc(buffer_size, GFP_KERNEL); if (!buffer) { dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } memcpy(buffer, firmware, firmware_size); memset(buffer+firmware_size, 0xff, buffer_size-firmware_size); for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++) cs = (__u8)(cs + buffer[pos]); header = (struct ti_firmware_header *)buffer; header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header))); header->bCheckSum = cs; dbg("%s - downloading firmware", __FUNCTION__); for (pos = 0; pos < buffer_size; pos += done) { len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000); if (status) break; } kfree(buffer); if (status) { dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __FUNCTION__, status); return status; } dbg("%s - download successful", __FUNCTION__); return 0;}/* Circular Buffer Functions *//* * ti_buf_alloc * * Allocate a circular buffer and all associated memory. */static struct circ_buf *ti_buf_alloc(void){ struct circ_buf *cb; cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL); if (cb == NULL) return NULL; cb->buf = kmalloc(TI_WRITE_BUF_SIZE, GFP_KERNEL); if (cb->buf == NULL) { kfree(cb); return NULL; } ti_buf_clear(cb); return cb;}/* * ti_buf_free * * Free the buffer and all associated memory. */static void ti_buf_free(struct circ_buf *cb){ kfree(cb->buf); kfree(cb);}/* * ti_buf_clear * * Clear out all data in the circular buffer. */static void ti_buf_clear(struct circ_buf *cb){ cb->head = cb->tail = 0;}/* * ti_buf_data_avail * * Return the number of bytes of data available in the circular * buffer. */static int ti_buf_data_avail(struct circ_buf *cb){ return CIRC_CNT(cb->head,cb->tail,TI_WRITE_BUF_SIZE);}/* * ti_buf_space_avail * * Return the number of bytes of space available in the circular * buffer. */static int ti_buf_space_avail(struct circ_buf *cb){ return CIRC_SPACE(cb->head,cb->tail,TI_WRITE_BUF_SIZE);}/* * ti_buf_put * * Copy data data from a user buffer and put it into the circular buffer. * Restrict to the amount of space available. * * Return the number of bytes copied. */static int ti_buf_put(struct circ_buf *cb, const char *buf, int count){ int c, ret = 0; while (1) { c = CIRC_SPACE_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(cb->buf + cb->head, buf, c); cb->head = (cb->head + c) & (TI_WRITE_BUF_SIZE-1); buf += c; count -= c; ret += c; } return ret;}/* * ti_buf_get * * Get data from the circular buffer and copy to the given buffer. * Restrict to the amount of data available. * * Return the number of bytes copied. */static int ti_buf_get(struct circ_buf *cb, char *buf, int count){ int c, ret = 0; while (1) { c = CIRC_CNT_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(buf, cb->buf + cb->tail, c); cb->tail = (cb->tail + c) & (TI_WRITE_BUF_SIZE-1); buf += c; count -= c; ret += c; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -