📄 cypress_m8.c
字号:
/* returns how much space is available in the soft buffer */static int cypress_write_room(struct usb_serial_port *port){ struct cypress_private *priv = usb_get_serial_port_data(port); int room = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); room = cypress_buf_space_avail(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - returns %d", __FUNCTION__, room); return room;}static int cypress_tiocmget (struct usb_serial_port *port, struct file *file){ struct cypress_private *priv = usb_get_serial_port_data(port); __u8 status, control; unsigned int result = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; status = priv->current_status; spin_unlock_irqrestore(&priv->lock, flags); result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) | ((control & CONTROL_RTS) ? TIOCM_RTS : 0) | ((status & UART_CTS) ? TIOCM_CTS : 0) | ((status & UART_DSR) ? TIOCM_DSR : 0) | ((status & UART_RI) ? TIOCM_RI : 0) | ((status & UART_CD) ? TIOCM_CD : 0); dbg("%s - result = %x", __FUNCTION__, result); return result;}static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear){ struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); if (set & TIOCM_RTS) priv->line_control |= CONTROL_RTS; if (set & TIOCM_DTR) priv->line_control |= CONTROL_DTR; if (clear & TIOCM_RTS) priv->line_control &= ~CONTROL_RTS; if (clear & TIOCM_DTR) priv->line_control &= ~CONTROL_DTR; spin_unlock_irqrestore(&priv->lock, flags); priv->cmd_ctrl = 1; return cypress_write(port, NULL, 0);}static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg){ struct cypress_private *priv = usb_get_serial_port_data(port); dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); switch (cmd) { case TIOCGSERIAL: if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) { return -EFAULT; } return (0); break; case TIOCSSERIAL: if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) { return -EFAULT; } /* here we need to call cypress_set_termios to invoke the new settings */ cypress_set_termios(port, &priv->tmp_termios); return (0); break; /* these are called when setting baud rate from gpsd */ case TCGETS: if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) { return -EFAULT; } return (0); break; case TCSETS: if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) { return -EFAULT; } /* here we need to call cypress_set_termios to invoke the new settings */ cypress_set_termios(port, &priv->tmp_termios); return (0); break; /* This code comes from drivers/char/serial.c and ftdi_sio.c */ case TIOCMIWAIT: while (priv != NULL) { interruptible_sleep_on(&priv->delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; else { char diff = priv->diff_status; if (diff == 0) { return -EIO; /* no change => error */ } /* consume all events */ priv->diff_status = 0; /* return 0 if caller wanted to know about these bits */ if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) || ((arg & TIOCM_DSR) && (diff & UART_DSR)) || ((arg & TIOCM_CD) && (diff & UART_CD)) || ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) { return 0; } /* otherwise caller can't care less about what happened, * and so we continue to wait for more events. */ } } return 0; break; default: break; } dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd); return -ENOIOCTLCMD;} /* cypress_ioctl */static void cypress_set_termios (struct usb_serial_port *port, struct termios *old_termios){ struct cypress_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; int data_bits, stop_bits, parity_type, parity_enable; unsigned cflag, iflag, baud_mask; unsigned long flags; __u8 oldlines; int linechange = 0; dbg("%s - port %d", __FUNCTION__, port->number); tty = port->tty; if ((!tty) || (!tty->termios)) { dbg("%s - no tty structures", __FUNCTION__); return; } spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { if (priv->chiptype == CT_EARTHMATE) { *(tty->termios) = tty_std_termios; tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL; } else if (priv->chiptype == CT_CYPHIDCOM) { *(tty->termios) = tty_std_termios; tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; } else if (priv->chiptype == CT_CA42V2) { *(tty->termios) = tty_std_termios; tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; } priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); cflag = tty->termios->c_cflag; iflag = tty->termios->c_iflag; /* check if there are new settings */ if (old_termios) { if ((cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { dbg("%s - attempting to set new termios settings", __FUNCTION__); /* should make a copy of this in case something goes * wrong in the function, we can restore it */ spin_lock_irqsave(&priv->lock, flags); priv->tmp_termios = *(tty->termios); spin_unlock_irqrestore(&priv->lock, flags); } else { dbg("%s - nothing to do, exiting", __FUNCTION__); return; } } else return; /* set number of data bits, parity, stop bits */ /* when parity is disabled the parity type bit is ignored */ /* 1 means 2 stop bits, 0 means 1 stop bit */ stop_bits = cflag & CSTOPB ? 1 : 0; if (cflag & PARENB) { parity_enable = 1; /* 1 means odd parity, 0 means even parity */ parity_type = cflag & PARODD ? 1 : 0; } else parity_enable = parity_type = 0; if (cflag & CSIZE) { switch (cflag & CSIZE) { case CS5: data_bits = 0; break; case CS6: data_bits = 1; break; case CS7: data_bits = 2; break; case CS8: data_bits = 3; break; default: err("%s - CSIZE was set, but not CS5-CS8", __FUNCTION__); data_bits = 3; } } else data_bits = 3; spin_lock_irqsave(&priv->lock, flags); oldlines = priv->line_control; if ((cflag & CBAUD) == B0) { /* drop dtr and rts */ dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__); baud_mask = B0; priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); } else { baud_mask = (cflag & CBAUD); switch(baud_mask) { case B300: dbg("%s - setting baud 300bps", __FUNCTION__); break; case B600: dbg("%s - setting baud 600bps", __FUNCTION__); break; case B1200: dbg("%s - setting baud 1200bps", __FUNCTION__); break; case B2400: dbg("%s - setting baud 2400bps", __FUNCTION__); break; case B4800: dbg("%s - setting baud 4800bps", __FUNCTION__); break; case B9600: dbg("%s - setting baud 9600bps", __FUNCTION__); break; case B19200: dbg("%s - setting baud 19200bps", __FUNCTION__); break; case B38400: dbg("%s - setting baud 38400bps", __FUNCTION__); break; case B57600: dbg("%s - setting baud 57600bps", __FUNCTION__); break; case B115200: dbg("%s - setting baud 115200bps", __FUNCTION__); break; default: dbg("%s - unknown masked baud rate", __FUNCTION__); } priv->line_control = (CONTROL_DTR | CONTROL_RTS); } spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, " "%d data_bits (+5)", __FUNCTION__, stop_bits, parity_enable, parity_type, data_bits); cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable, parity_type, 0, CYPRESS_SET_CONFIG); /* we perform a CYPRESS_GET_CONFIG so that the current settings are * filled into the private structure this should confirm that all is * working if it returns what we just set */ cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG); /* Here we can define custom tty settings for devices; the main tty * termios flag base comes from empeg.c */ spin_lock_irqsave(&priv->lock, flags); if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) { dbg("Using custom termios settings for a baud rate of " "4800bps."); /* define custom termios settings for NMEA protocol */ tty->termios->c_iflag /* input modes - */ &= ~(IGNBRK /* disable ignore break */ | BRKINT /* disable break causes interrupt */ | PARMRK /* disable mark parity errors */ | ISTRIP /* disable clear high bit of input char */ | INLCR /* disable translate NL to CR */ | IGNCR /* disable ignore CR */ | ICRNL /* disable translate CR to NL */ | IXON); /* disable enable XON/XOFF flow control */ tty->termios->c_oflag /* output modes */ &= ~OPOST; /* disable postprocess output char */ tty->termios->c_lflag /* line discipline modes */ &= ~(ECHO /* disable echo input characters */ | ECHONL /* disable echo new line */ | ICANON /* disable erase, kill, werase, and rprnt special characters */ | ISIG /* disable interrupt, quit, and suspend special characters */ | IEXTEN); /* disable non-POSIX special characters */ } /* CT_CYPHIDCOM: Application should handle this for device */ linechange = (priv->line_control != oldlines); spin_unlock_irqrestore(&priv->lock, flags); /* if necessary, set lines */ if (linechange) { priv->cmd_ctrl = 1; cypress_write(port, NULL, 0); }} /* cypress_set_termios *//* returns amount of data still left in soft buffer */static int cypress_chars_in_buffer(struct usb_serial_port *port){ struct cypress_private *priv = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); chars = cypress_buf_data_avail(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - returns %d", __FUNCTION__, chars); return chars;}static void cypress_throttle (struct usb_serial_port *port){ struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); priv->rx_flags = THROTTLED; spin_unlock_irqrestore(&priv->lock, flags);}static void cypress_unthrottle (struct usb_serial_port *port){ struct cypress_private *priv = usb_get_serial_port_data(port); int actually_throttled, result; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; priv->rx_flags = 0; spin_unlock_irqrestore(&priv->lock, flags); if (actually_throttled) { port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed submitting read urb, " "error %d\n", __FUNCTION__, result); }}static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct cypress_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; char tty_flag = TTY_NORMAL; int havedata = 0; int bytes = 0; int result; int i = 0; dbg("%s - port %d", __FUNCTION__, port->number);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -