📄 cypress_m8.c
字号:
spin_lock_irqsave(&priv->lock, flags); ++priv->cmd_count; spin_unlock_irqrestore(&priv->lock, flags); return retval;} /* cypress_serial_control *//* given a baud mask, it will return integer baud on success */static int mask_to_rate (unsigned mask){ int rate; switch (mask) { case B0: rate = 0; break; case B300: rate = 300; break; case B600: rate = 600; break; case B1200: rate = 1200; break; case B2400: rate = 2400; break; case B4800: rate = 4800; break; case B9600: rate = 9600; break; case B19200: rate = 19200; break; case B38400: rate = 38400; break; case B57600: rate = 57600; break; case B115200: rate = 115200; break; default: rate = -1; } return rate;}static unsigned rate_to_mask (int rate){ unsigned mask; switch (rate) { case 0: mask = B0; break; case 300: mask = B300; break; case 600: mask = B600; break; case 1200: mask = B1200; break; case 2400: mask = B2400; break; case 4800: mask = B4800; break; case 9600: mask = B9600; break; case 19200: mask = B19200; break; case 38400: mask = B38400; break; case 57600: mask = B57600; break; case 115200: mask = B115200; break; default: mask = 0x40; } return mask;}/***************************************************************************** * Cypress serial driver functions *****************************************************************************/static int generic_startup (struct usb_serial *serial){ struct cypress_private *priv; dbg("%s - port %d", __FUNCTION__, serial->port[0]->number); priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; spin_lock_init(&priv->lock); priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); if (priv->buf == NULL) { kfree(priv); return -ENOMEM; } init_waitqueue_head(&priv->delta_msr_wait); usb_reset_configuration (serial->dev); interval = 1; priv->cmd_ctrl = 0; priv->line_control = 0; priv->termios_initialized = 0; priv->rx_flags = 0; priv->cbr_mask = B300; usb_set_serial_port_data(serial->port[0], priv); return 0;}static int cypress_earthmate_startup (struct usb_serial *serial){ struct cypress_private *priv; dbg("%s", __FUNCTION__); if (generic_startup(serial)) { dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number); return 1; } priv = usb_get_serial_port_data(serial->port[0]); priv->chiptype = CT_EARTHMATE; return 0;} /* cypress_earthmate_startup */static int cypress_hidcom_startup (struct usb_serial *serial){ struct cypress_private *priv; dbg("%s", __FUNCTION__); if (generic_startup(serial)) { dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number); return 1; } priv = usb_get_serial_port_data(serial->port[0]); priv->chiptype = CT_CYPHIDCOM; return 0;} /* cypress_hidcom_startup */static int cypress_ca42v2_startup (struct usb_serial *serial){ struct cypress_private *priv; dbg("%s", __FUNCTION__); if (generic_startup(serial)) { dbg("%s - Failed setting up port %d", __FUNCTION__, serial->port[0]->number); return 1; } priv = usb_get_serial_port_data(serial->port[0]); priv->chiptype = CT_CA42V2; return 0;} /* cypress_ca42v2_startup */static void cypress_shutdown (struct usb_serial *serial){ struct cypress_private *priv; dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number); /* all open ports are closed at this point */ priv = usb_get_serial_port_data(serial->port[0]); if (priv) { cypress_buf_free(priv->buf); kfree(priv); usb_set_serial_port_data(serial->port[0], NULL); }}static int cypress_open (struct usb_serial_port *port, struct file *filp){ struct cypress_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; unsigned long flags; int result = 0; dbg("%s - port %d", __FUNCTION__, port->number); /* clear halts before open */ usb_clear_halt(serial->dev, 0x81); usb_clear_halt(serial->dev, 0x02); spin_lock_irqsave(&priv->lock, flags); /* reset read/write statistics */ priv->bytes_in = 0; priv->bytes_out = 0; priv->cmd_count = 0; priv->rx_flags = 0; spin_unlock_irqrestore(&priv->lock, flags); /* setting to zero could cause data loss */ port->tty->low_latency = 1; /* raise both lines and set termios */ spin_lock_irqsave(&priv->lock, flags); priv->line_control = CONTROL_DTR | CONTROL_RTS; priv->cmd_ctrl = 1; spin_unlock_irqrestore(&priv->lock, flags); result = cypress_write(port, NULL, 0); if (result) { dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result); return result; } else dbg("%s - success setting the control lines", __FUNCTION__); cypress_set_termios(port, &priv->tmp_termios); /* setup the port and start reading from the device */ if(!port->interrupt_in_urb){ err("%s - interrupt_in_urb is empty!", __FUNCTION__); return(-1); } usb_fill_int_urb(port->interrupt_in_urb, serial->dev, usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, cypress_read_int_callback, port, interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result){ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); } return result;} /* cypress_open */static void cypress_close(struct usb_serial_port *port, struct file * filp){ struct cypress_private *priv = usb_get_serial_port_data(port); unsigned int c_cflag; unsigned long flags; int bps; long timeout; wait_queue_t wait; dbg("%s - port %d", __FUNCTION__, port->number); /* wait for data to drain from buffer */ spin_lock_irqsave(&priv->lock, flags); timeout = CYPRESS_CLOSING_WAIT; init_waitqueue_entry(&wait, current); add_wait_queue(&port->tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (cypress_buf_data_avail(priv->buf) == 0 || timeout == 0 || signal_pending(current) || !usb_get_intfdata(port->serial->interface)) break; spin_unlock_irqrestore(&priv->lock, flags); timeout = schedule_timeout(timeout); spin_lock_irqsave(&priv->lock, flags); } set_current_state(TASK_RUNNING); remove_wait_queue(&port->tty->write_wait, &wait); /* clear out any remaining data in the buffer */ cypress_buf_clear(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); /* wait for characters to drain from device */ bps = tty_get_baud_rate(port->tty); if (bps > 1200) timeout = max((HZ*2560)/bps,HZ/10); else timeout = 2*HZ; schedule_timeout_interruptible(timeout); dbg("%s - stopping urbs", __FUNCTION__); usb_kill_urb (port->interrupt_in_urb); usb_kill_urb (port->interrupt_out_urb); if (port->tty) { c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop dtr and rts */ priv = usb_get_serial_port_data(port); spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; priv->cmd_ctrl = 1; spin_unlock_irqrestore(&priv->lock, flags); cypress_write(port, NULL, 0); } } if (stats) dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", priv->bytes_in, priv->bytes_out, priv->cmd_count);} /* cypress_close */static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count){ struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); /* line control commands, which need to be executed immediately, are not put into the buffer for obvious reasons. */ if (priv->cmd_ctrl) { count = 0; goto finish; } if (!count) return count; spin_lock_irqsave(&priv->lock, flags); count = cypress_buf_put(priv->buf, buf, count); spin_unlock_irqrestore(&priv->lock, flags);finish: cypress_send(port); return count;} /* cypress_write */static void cypress_send(struct usb_serial_port *port){ int count = 0, result, offset, actual_size; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size); spin_lock_irqsave(&priv->lock, flags); if (priv->write_urb_in_use) { dbg("%s - can't write, urb in use", __FUNCTION__); spin_unlock_irqrestore(&priv->lock, flags); return; } spin_unlock_irqrestore(&priv->lock, flags); /* clear buffer */ memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size); spin_lock_irqsave(&priv->lock, flags); switch (port->interrupt_out_size) { case 32: /* this is for the CY7C64013... */ offset = 2; port->interrupt_out_buffer[0] = priv->line_control; break; case 8: /* this is for the CY7C63743... */ offset = 1; port->interrupt_out_buffer[0] = priv->line_control; break; default: dbg("%s - wrong packet size", __FUNCTION__); spin_unlock_irqrestore(&priv->lock, flags); return; } if (priv->line_control & CONTROL_RESET) priv->line_control &= ~CONTROL_RESET; if (priv->cmd_ctrl) { priv->cmd_count++; dbg("%s - line control command being issued", __FUNCTION__); spin_unlock_irqrestore(&priv->lock, flags); goto send; } else spin_unlock_irqrestore(&priv->lock, flags); count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset], port->interrupt_out_size-offset); if (count == 0) { return; } switch (port->interrupt_out_size) { case 32: port->interrupt_out_buffer[1] = count; break; case 8: port->interrupt_out_buffer[0] |= count; } dbg("%s - count is %d", __FUNCTION__, count);send: spin_lock_irqsave(&priv->lock, flags); priv->write_urb_in_use = 1; spin_unlock_irqrestore(&priv->lock, flags); if (priv->cmd_ctrl) actual_size = 1; else actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size, port->interrupt_out_urb->transfer_buffer); port->interrupt_out_urb->transfer_buffer_length = actual_size; port->interrupt_out_urb->dev = port->serial->dev; port->interrupt_out_urb->interval = interval; result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); priv->write_urb_in_use = 0; } spin_lock_irqsave(&priv->lock, flags); if (priv->cmd_ctrl) { priv->cmd_ctrl = 0; } priv->bytes_out += count; /* do not count the line control and size bytes */ spin_unlock_irqrestore(&priv->lock, flags); schedule_work(&port->work);} /* cypress_send */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -