static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios) { unsigned char *transfer_buffer; unsigned int cflag; int result; u8 baud; dbg(__FUNCTION__ " - port %d", port->number); if ((!port->tty) || (!port->tty->termios)) { dbg(__FUNCTION__" - no tty structures"); return; } cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { dbg(__FUNCTION__ " - nothing to change..."); return; } } /* All we can change is the baud rate */ if (cflag & CBAUD) { dbg (__FUNCTION__ " - asking for baud %d", tty_get_baud_rate(port->tty)); /* * FIXME, we should compare the baud request against the * capability stated in the IR header that we got in the * startup funtion. */ switch (cflag & CBAUD) { case B2400: baud = SPEED_2400; break; case B9600: baud = SPEED_9600; break; case B19200: baud = SPEED_19200; break; case B38400: baud = SPEED_38400; break; case B57600: baud = SPEED_57600; break; case B115200: baud = SPEED_115200; break; case B576000: baud = SPEED_576000; break; case B1152000: baud = SPEED_1152000; break; case B4000000: baud = SPEED_4000000; break; default: err ("ir-usb driver does not support the baudrate (%d) requested", tty_get_baud_rate(port->tty)); return; } /* FIXME need to check to see if our write urb is busy right * now, or use a urb pool. */ /* send the baud change out on an "empty" data packet */ transfer_buffer = port->write_urb->transfer_buffer; transfer_buffer[0] = baud; port->write_urb->transfer_buffer_length = 1; port->write_urb->dev = port->serial->dev; result = usb_submit_urb (port->write_urb); if (result) err(__FUNCTION__ " - failed submitting write urb, error %d", result); } return; }
static void handle_termios(struct tty_struct *tty) { struct nullmodem_end *end = tty->driver_data; speed_t speed = tty_get_baud_rate(tty); if (speed == 0) change_pins(end, 0, TIOCM_DTR|TIOCM_RTS); else change_pins(end, TIOCM_DTR|TIOCM_RTS, 0); unsigned int cflag = tty->termios.c_cflag; end->char_length = 2; switch (cflag & CSIZE) { case CS5: end->char_length +=5; break; case CS6: end->char_length +=6; break; case CS7: end->char_length +=7; break; default: case CS8: end->char_length +=8; break; } if (cflag & PARENB) end->char_length += 1; if (cflag & CSTOPB) end->char_length += 1; end->char_length *= FACTOR; tty->hw_stopped = (tty->termios.c_cflag&CRTSCTS) && !(get_pins(end) & TIOCM_CTS); }
void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) { struct usb_serial_port *port = tty->driver_data; unsigned int bps; unsigned long period; unsigned long expire; bps = tty_get_baud_rate(tty); if (!bps) bps = 9600; /* B0 */ /* * Use a poll-period of roughly the time it takes to send one * character or at least one jiffy. */ period = max_t(unsigned long, (10 * HZ / bps), 1); period = min_t(unsigned long, period, timeout); dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n", __func__, jiffies_to_msecs(timeout), jiffies_to_msecs(period)); expire = jiffies + timeout; while (!port->serial->type->tx_empty(port)) { schedule_timeout_interruptible(period); if (signal_pending(current)) break; if (time_after(jiffies, expire)) break; } }
static void keyspan_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { int baud_rate, device_port; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; unsigned int cflag; p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; cflag = tty->termios->c_cflag; device_port = port->number - port->serial->minor; /* Baud rate calculation takes baud rate as an integer so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(tty); /* If no match or invalid, don't change */ if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { /* FIXME - more to do here to ensure rate changes cleanly */ /* FIXME - calcuate exact rate from divisor ? */ p_priv->baud = baud_rate; } else baud_rate = tty_termios_baud_rate(old_termios); tty_encode_baud_rate(tty, baud_rate, baud_rate); /* set CTS/RTS handshake etc. */ p_priv->cflag = cflag; p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; /* Mark/Space not supported */ tty->termios->c_cflag &= ~CMSPAR; keyspan_send_setup(port, 0); }
/* Old_termios contains the original termios settings and * tty->termios contains the new setting to be used. */ static void ch341_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned baud_rate; unsigned long flags; baud_rate = tty_get_baud_rate(tty); priv->baud_rate = baud_rate; if (baud_rate) { spin_lock_irqsave(&priv->lock, flags); priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); spin_unlock_irqrestore(&priv->lock, flags); ch341_set_baudrate(port->serial->dev, priv); } else { spin_lock_irqsave(&priv->lock, flags); priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS); spin_unlock_irqrestore(&priv->lock, flags); } ch341_set_handshake(port->serial->dev, priv->line_control); /* Unimplemented: * (cflag & CSIZE) : data bits [5, 8] * (cflag & PARENB) : parity {NONE, EVEN, ODD} * (cflag & CSTOPB) : stop bits [1, 2] */ }
static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old) { struct kobil_private * priv; int result; unsigned short urb_val = 0; int c_cflag = port->tty->termios->c_cflag; speed_t speed; void * settings; priv = usb_get_serial_port_data(port); if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) // This device doesn't support ioctl calls return; switch (speed = tty_get_baud_rate(port->tty)) { case 1200: urb_val = SUSBCR_SBR_1200; break; default: speed = 9600; case 9600: urb_val = SUSBCR_SBR_9600; break; } urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; settings = kzalloc(50, GFP_KERNEL); if (! settings) return; sprintf(settings, "%d ", speed); if (c_cflag & PARENB) { if (c_cflag & PARODD) { urb_val |= SUSBCR_SPASB_OddParity; strcat(settings, "Odd Parity"); } else { urb_val |= SUSBCR_SPASB_EvenParity; strcat(settings, "Even Parity"); } } else { urb_val |= SUSBCR_SPASB_NoParity; strcat(settings, "No Parity"); } port->tty->termios->c_cflag &= ~CMSPAR; tty_encode_baud_rate(port->tty, speed, speed); result = usb_control_msg( port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0 ), SUSBCRequest_SetBaudRateParityAndStopBits, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, urb_val, 0, settings, 0, KOBIL_TIMEOUT ); kfree(settings); }
static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty) { unsigned int bps = tty_get_baud_rate(tty); long timeout; if (bps > 1200) { timeout = (HZ * 10 * port->drain_delay) / bps; timeout = max_t(long, timeout, HZ / 10); } else {
static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { struct acm *acm = tty->driver_data; struct ktermios *termios = tty->termios; struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; if (!ACM_READY(acm)) return; newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; switch (termios->c_cflag & CSIZE) { case CS5: newline.bDataBits = 5; break; case CS6: newline.bDataBits = 6; break; case CS7: newline.bDataBits = 7; break; case CS8: default: newline.bDataBits = 8; break; } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); if (!newline.dwDTERate) { newline.dwDTERate = acm->line.dwDTERate; newctrl &= ~ACM_CTRL_DTR; } else newctrl |= ACM_CTRL_DTR; if (newctrl != acm->ctrlout) acm_set_control(acm, acm->ctrlout = newctrl); if (memcmp(&acm->line, &newline, sizeof newline)) { memcpy(&acm->line, &newline, sizeof newline); dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n", __func__, le32_to_cpu(newline.dwDTERate), newline.bCharFormat, newline.bParityType, newline.bDataBits); acm_set_line(acm, &acm->line); } }
static void kobil_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old) { struct kobil_private *priv; int result; unsigned short urb_val = 0; int c_cflag = tty->termios->c_cflag; speed_t speed; priv = usb_get_serial_port_data(port); if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { /* */ *tty->termios = *old; return; } speed = tty_get_baud_rate(tty); switch (speed) { case 1200: urb_val = SUSBCR_SBR_1200; break; default: speed = 9600; case 9600: urb_val = SUSBCR_SBR_9600; break; } urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; if (c_cflag & PARENB) { if (c_cflag & PARODD) urb_val |= SUSBCR_SPASB_OddParity; else urb_val |= SUSBCR_SPASB_EvenParity; } else urb_val |= SUSBCR_SPASB_NoParity; tty->termios->c_cflag &= ~CMSPAR; tty_encode_baud_rate(tty, speed, speed); result = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), SUSBCRequest_SetBaudRateParityAndStopBits, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, urb_val, 0, NULL, 0, KOBIL_TIMEOUT ); }
// called by the kernel when cfsetattr() is called from userspace static void raspicommDriver_set_termios(struct tty_struct* tty, struct ktermios* kt) { int cflag; speed_t baudrate; Databits databits; Parity parity; Stopbits stopbits; LOG("raspicomm: raspicommDriver_set_termios called"); // get the baudrate baudrate = tty_get_baud_rate(tty); // get the cflag cflag = tty->termios->c_cflag; // get the databits switch ( cflag & CSIZE ) { case CS7: databits = DATABITS_7; break; default: case CS8: databits = DATABITS_8; break; } // get the stopbits stopbits = ( cflag & CSTOPB ) ? STOPBITS_TWO : STOPBITS_ONE; // get the parity if ( cflag & PARENB ) // is parity used { ParityIsEven = !( cflag & PARODD ); // is it even or odd? store it for sending parity = PARITY_ON; ParityEnabled = 1; } else { parity = PARITY_OFF; ParityEnabled = 0; } // #if DEBUG // printk ( KERN_INFO "raspicomm: Parity=%i, ParityIsEven = %i", parity, ParityIsEven); // #endif // update the configuration raspicomm_max3140_configure(baudrate, databits, stopbits, parity); raspicomm_max3140_apply_config(); }
int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) { unsigned long flags; spin_lock_irqsave(&port->lock, flags); if (tty_hung_up_p(filp)) { spin_unlock_irqrestore(&port->lock, flags); return 0; } if (tty->count == 1 && port->count != 1) { printk(KERN_WARNING "tty_port_close_start: tty->count = 1 port count = %d.\n", port->count); port->count = 1; } if (--port->count < 0) { printk(KERN_WARNING "tty_port_close_start: count = %d\n", port->count); port->count = 0; } if (port->count) { spin_unlock_irqrestore(&port->lock, flags); if (port->ops->drop) port->ops->drop(port); return 0; } set_bit(ASYNCB_CLOSING, &port->flags); tty->closing = 1; spin_unlock_irqrestore(&port->lock, flags); /* Don't block on a stalled port, just pull the chain */ if (tty->flow_stopped) tty_driver_flush_buffer(tty); if (test_bit(ASYNCB_INITIALIZED, &port->flags) && port->closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent_from_close(tty, port->closing_wait); if (port->drain_delay) { unsigned int bps = tty_get_baud_rate(tty); long timeout; if (bps > 1200) timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, HZ / 10); else
/* Old_termios contains the original termios settings and * tty->termios contains the new setting to be used. */ static void ch341_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) { struct ch341_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; unsigned baud_rate; dbg("ch341_set_termios()"); baud_rate = tty_get_baud_rate(tty); switch (baud_rate) { case 2400: case 4800: case 9600: case 19200: case 38400: case 115200: priv->baud_rate = baud_rate; break; default: dbg("Rate %d not supported, using %d", baud_rate, DEFAULT_BAUD_RATE); priv->baud_rate = DEFAULT_BAUD_RATE; } ch341_set_baudrate(port->serial->dev, priv); /* Unimplemented: * (cflag & CSIZE) : data bits [5, 8] * (cflag & PARENB) : parity {NONE, EVEN, ODD} * (cflag & CSTOPB) : stop bits [1, 2] */ /* Copy back the old hardware settings */ tty_termios_copy_hw(tty->termios, old_termios); /* And re-encode with the new baud */ tty_encode_baud_rate(tty, baud_rate, baud_rate); }
static int get_serial_info(struct usb_serial_port *port, struct serial_struct __user *retinfo) { struct serial_struct tmp; if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); tmp.line = port->serial->minor; tmp.port = port->number; tmp.baud_base = tty_get_baud_rate(port->port.tty); tmp.close_delay = port->port.close_delay / 10; tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : port->port.closing_wait / 10; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; return 0; }
static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { struct acm *acm = tty->driver_data; struct ktermios *termios = tty->termios; struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); if (C_BAUD(tty) == B0) { newline.dwDTERate = acm->line.dwDTERate; newctrl &= ~ACM_CTRL_DTR; } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { newctrl |= ACM_CTRL_DTR; } if (newctrl != acm->ctrlout) acm_set_control(acm, acm->ctrlout = newctrl); if (memcmp(&acm->line, &newline, sizeof newline)) { memcpy(&acm->line, &newline, sizeof newline); dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n", __func__, le32_to_cpu(newline.dwDTERate), newline.bCharFormat, newline.bParityType, newline.bDataBits); acm_set_line(acm, &acm->line); } }
/* * Function ircomm_tty_change_speed (driver) * * Change speed of the driver. If the remote device is a DCE, then this * should make it change the speed of its serial port */ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) { unsigned cflag, cval; int baud; IRDA_DEBUG(2, "%s()\n", __func__ ); if (!self->tty || !self->tty->termios || !self->ircomm) return; cflag = self->tty->termios->c_cflag; /* byte size and parity */ switch (cflag & CSIZE) { case CS5: cval = IRCOMM_WSIZE_5; break; case CS6: cval = IRCOMM_WSIZE_6; break; case CS7: cval = IRCOMM_WSIZE_7; break; case CS8: cval = IRCOMM_WSIZE_8; break; default: cval = IRCOMM_WSIZE_5; break; } if (cflag & CSTOPB) cval |= IRCOMM_2_STOP_BIT; if (cflag & PARENB) cval |= IRCOMM_PARITY_ENABLE; if (!(cflag & PARODD)) cval |= IRCOMM_PARITY_EVEN; /* Determine divisor based on baud rate */ baud = tty_get_baud_rate(self->tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ self->settings.data_rate = baud; ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE); /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { self->flags |= ASYNC_CTS_FLOW; self->settings.flow_control |= IRCOMM_RTS_CTS_IN; /* This got me. Bummer. Jean II */ if (self->service_type == IRCOMM_3_WIRE_RAW) IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__); } else { self->flags &= ~ASYNC_CTS_FLOW; self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; } if (cflag & CLOCAL) self->flags &= ~ASYNC_CHECK_CD; else self->flags |= ASYNC_CHECK_CD; #if 0 /* * Set up parity check flag */ if (I_INPCK(self->tty)) driver->read_status_mask |= LSR_FE | LSR_PE; if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty)) driver->read_status_mask |= LSR_BI; /* * Characters to ignore */ driver->ignore_status_mask = 0; if (I_IGNPAR(driver->tty)) driver->ignore_status_mask |= LSR_PE | LSR_FE; if (I_IGNBRK(self->tty)) { self->ignore_status_mask |= LSR_BI; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(self->tty)) self->ignore_status_mask |= LSR_OE; } #endif self->settings.data_format = cval; ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE); ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE); }
/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ static void change_speed(struct tty_struct *tty, struct serial_state *info, struct ktermios *old_termios) { struct tty_port *port = &info->tport; int quot = 0, baud_base, baud; unsigned cflag, cval = 0; int bits; unsigned long flags; cflag = tty->termios->c_cflag; /* Byte size is always 8 bits plus parity bit if requested */ cval = 3; bits = 10; if (cflag & CSTOPB) { cval |= 0x04; bits++; } if (cflag & PARENB) { cval |= UART_LCR_PARITY; bits++; } if (!(cflag & PARODD)) cval |= UART_LCR_EPAR; #ifdef CMSPAR if (cflag & CMSPAR) cval |= UART_LCR_SPAR; #endif /* Determine divisor based on baud rate */ baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ baud_base = info->baud_base; if (baud == 38400 && (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) quot = info->custom_divisor; else { if (baud == 134) /* Special case since 134 is really 134.5 */ quot = (2*baud_base / 269); else if (baud) quot = baud_base / baud; } /* If the quotient is zero refuse the change */ if (!quot && old_termios) { /* FIXME: Will need updating for new tty in the end */ tty->termios->c_cflag &= ~CBAUD; tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; if (baud == 38400 && (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) quot = info->custom_divisor; else { if (baud == 134) /* Special case since 134 is really 134.5 */ quot = (2*baud_base / 269); else if (baud) quot = baud_base / baud; } } /* As a last resort, if the quotient is zero, default to 9600 bps */ if (!quot) quot = baud_base / 9600; info->quot = quot; info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); info->timeout += HZ/50; /* Add .02 seconds of slop */ /* CTS flow control flag and modem status interrupts */ info->IER &= ~UART_IER_MSI; if (port->flags & ASYNC_HARDPPS_CD) info->IER |= UART_IER_MSI; if (cflag & CRTSCTS) { port->flags |= ASYNC_CTS_FLOW; info->IER |= UART_IER_MSI; } else port->flags &= ~ASYNC_CTS_FLOW; if (cflag & CLOCAL) port->flags &= ~ASYNC_CHECK_CD; else { port->flags |= ASYNC_CHECK_CD; info->IER |= UART_IER_MSI; } /* TBD: * Does clearing IER_MSI imply that we should disable the VBL interrupt ? */ /* * Set up parity check flag */ info->read_status_mask = UART_LSR_OE | UART_LSR_DR; if (I_INPCK(tty)) info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (I_BRKINT(tty) || I_PARMRK(tty)) info->read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ info->ignore_status_mask = 0; if (I_IGNPAR(tty)) info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (I_IGNBRK(tty)) { info->ignore_status_mask |= UART_LSR_BI; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(tty)) info->ignore_status_mask |= UART_LSR_OE; } /* * !!! ignore all characters if CREAD is not set */ if ((cflag & CREAD) == 0) info->ignore_status_mask |= UART_LSR_DR; local_irq_save(flags); { short serper; /* Set up the baud rate */ serper = quot - 1; /* Enable or disable parity bit */ if(cval & UART_LCR_PARITY) serper |= (SERPER_PARENB); custom.serper = serper; mb(); } local_irq_restore(flags); }
static void mxu1_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct mxu1_port *mxport = usb_get_serial_port_data(port); struct mxu1_uart_config *config; tcflag_t cflag, iflag; speed_t baud; int status; unsigned int mcr; dev_dbg(&port->dev, "%s\n", __func__); cflag = tty->termios.c_cflag; iflag = tty->termios.c_iflag; if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios) && tty->termios.c_iflag == old_termios->c_iflag) { dev_dbg(&port->dev, "%s - nothing to change\n", __func__); return; } dev_dbg(&port->dev, "%s - clfag %08x, iflag %08x\n", __func__, cflag, iflag); if (old_termios) { dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n", __func__, old_termios->c_cflag, old_termios->c_iflag); } config = kzalloc(sizeof(*config), GFP_KERNEL); if (!config) return; config->wFlags = 0; /* these flags must be set */ config->wFlags |= MXU1_UART_ENABLE_MS_INTS; config->wFlags |= MXU1_UART_ENABLE_AUTO_START_DMA; if (mxport->mxp_send_break == MXU1_LCR_BREAK) config->wFlags |= MXU1_UART_SEND_BREAK_SIGNAL; config->bUartMode = (u8)(mxport->mxp_uart_mode); switch (C_CSIZE(tty)) { case CS5: config->bDataBits = MXU1_UART_5_DATA_BITS; break; case CS6: config->bDataBits = MXU1_UART_6_DATA_BITS; break; case CS7: config->bDataBits = MXU1_UART_7_DATA_BITS; break; default: case CS8: config->bDataBits = MXU1_UART_8_DATA_BITS; break; } if (C_PARENB(tty)) { config->wFlags |= MXU1_UART_ENABLE_PARITY_CHECKING; if (C_CMSPAR(tty)) { if (C_PARODD(tty)) config->bParity = MXU1_UART_MARK_PARITY; else config->bParity = MXU1_UART_SPACE_PARITY; } else { if (C_PARODD(tty)) config->bParity = MXU1_UART_ODD_PARITY; else config->bParity = MXU1_UART_EVEN_PARITY; } } else { config->bParity = MXU1_UART_NO_PARITY; } if (C_CSTOPB(tty)) config->bStopBits = MXU1_UART_2_STOP_BITS; else config->bStopBits = MXU1_UART_1_STOP_BITS; if (C_CRTSCTS(tty)) { /* RTS flow control must be off to drop RTS for baud rate B0 */ if (C_BAUD(tty) != B0) config->wFlags |= MXU1_UART_ENABLE_RTS_IN; config->wFlags |= MXU1_UART_ENABLE_CTS_OUT; } if (I_IXOFF(tty) || I_IXON(tty)) { config->cXon = START_CHAR(tty); config->cXoff = STOP_CHAR(tty); if (I_IXOFF(tty)) config->wFlags |= MXU1_UART_ENABLE_X_IN; if (I_IXON(tty)) config->wFlags |= MXU1_UART_ENABLE_X_OUT; } baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; config->wBaudRate = MXU1_BAUD_BASE / baud; dev_dbg(&port->dev, "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n", __func__, 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 = mxu1_send_ctrl_data_urb(port->serial, MXU1_SET_CONFIG, 0, MXU1_UART1_PORT, (u8 *)config, sizeof(*config)); if (status) dev_err(&port->dev, "cannot set config: %d\n", status); mutex_lock(&mxport->mxp_mutex); mcr = mxport->mxp_mcr; if (C_BAUD(tty) == B0) mcr &= ~(MXU1_MCR_DTR | MXU1_MCR_RTS); else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) mcr |= ~(MXU1_MCR_DTR | MXU1_MCR_RTS); status = mxu1_set_mcr(port, mcr); if (status) dev_err(&port->dev, "cannot set modem control: %d\n", status); else mxport->mxp_mcr = mcr; mutex_unlock(&mxport->mxp_mutex); kfree(config); }
static void ipoctal_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { unsigned int cflag; unsigned char mr1 = 0; unsigned char mr2 = 0; unsigned char csr = 0; struct ipoctal_channel *channel = tty->driver_data; speed_t baud; cflag = tty->termios.c_cflag; /* Disable and reset everything before change the setup */ iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); /* Set Bits per chars */ switch (cflag & CSIZE) { case CS6: mr1 |= MR1_CHRL_6_BITS; break; case CS7: mr1 |= MR1_CHRL_7_BITS; break; case CS8: default: mr1 |= MR1_CHRL_8_BITS; /* By default, select CS8 */ tty->termios.c_cflag = (cflag & ~CSIZE) | CS8; break; } /* Set Parity */ if (cflag & PARENB) if (cflag & PARODD) mr1 |= MR1_PARITY_ON | MR1_PARITY_ODD; else mr1 |= MR1_PARITY_ON | MR1_PARITY_EVEN; else mr1 |= MR1_PARITY_OFF; /* Mark or space parity is not supported */ tty->termios.c_cflag &= ~CMSPAR; /* Set stop bits */ if (cflag & CSTOPB) mr2 |= MR2_STOP_BITS_LENGTH_2; else mr2 |= MR2_STOP_BITS_LENGTH_1; /* Set the flow control */ switch (channel->board_id) { case IPACK1_DEVICE_ID_SBS_OCTAL_232: if (cflag & CRTSCTS) { mr1 |= MR1_RxRTS_CONTROL_ON; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON; } else { mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; } break; case IPACK1_DEVICE_ID_SBS_OCTAL_422: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; break; case IPACK1_DEVICE_ID_SBS_OCTAL_485: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF; break; default: return; break; } baud = tty_get_baud_rate(tty); tty_termios_encode_baud_rate(&tty->termios, baud, baud); /* Set baud rate */ switch (baud) { case 75: csr |= TX_CLK_75 | RX_CLK_75; break; case 110: csr |= TX_CLK_110 | RX_CLK_110; break; case 150: csr |= TX_CLK_150 | RX_CLK_150; break; case 300: csr |= TX_CLK_300 | RX_CLK_300; break; case 600: csr |= TX_CLK_600 | RX_CLK_600; break; case 1200: csr |= TX_CLK_1200 | RX_CLK_1200; break; case 1800: csr |= TX_CLK_1800 | RX_CLK_1800; break; case 2000: csr |= TX_CLK_2000 | RX_CLK_2000; break; case 2400: csr |= TX_CLK_2400 | RX_CLK_2400; break; case 4800: csr |= TX_CLK_4800 | RX_CLK_4800; break; case 9600: csr |= TX_CLK_9600 | RX_CLK_9600; break; case 19200: csr |= TX_CLK_19200 | RX_CLK_19200; break; case 38400: default: csr |= TX_CLK_38400 | RX_CLK_38400; /* In case of default, we establish 38400 bps */ tty_termios_encode_baud_rate(&tty->termios, 38400, 38400); break; } mr1 |= MR1_ERROR_CHAR; mr1 |= MR1_RxINT_RxRDY; /* Write the control registers */ iowrite8(mr1, &channel->regs->w.mr); iowrite8(mr2, &channel->regs->w.mr); iowrite8(csr, &channel->regs->w.csr); /* Enable again the RX, if it was before */ if (channel->rx_enable) iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); }
static void ir_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct urb *urb; unsigned char *transfer_buffer; int result; speed_t baud; int ir_baud; dbg("%s - port %d", __func__, port->number); baud = tty_get_baud_rate(tty); /* * FIXME, we should compare the baud request against the * capability stated in the IR header that we got in the * startup function. */ switch (baud) { case 2400: ir_baud = USB_IRDA_BR_2400; break; case 9600: ir_baud = USB_IRDA_BR_9600; break; case 19200: ir_baud = USB_IRDA_BR_19200; break; case 38400: ir_baud = USB_IRDA_BR_38400; break; case 57600: ir_baud = USB_IRDA_BR_57600; break; case 115200: ir_baud = USB_IRDA_BR_115200; break; case 576000: ir_baud = USB_IRDA_BR_576000; break; case 1152000: ir_baud = USB_IRDA_BR_1152000; break; case 4000000: ir_baud = USB_IRDA_BR_4000000; break; default: ir_baud = USB_IRDA_BR_9600; baud = 9600; } if (xbof == -1) ir_xbof = ir_xbof_change(ir_add_bof); else ir_xbof = ir_xbof_change(xbof) ; /* Only speed changes are supported */ tty_termios_copy_hw(tty->termios, old_termios); tty_encode_baud_rate(tty, baud, baud); /* * send the baud change out on an "empty" data packet */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { dev_err(&port->dev, "%s - no more urbs\n", __func__); return; } transfer_buffer = kmalloc(1, GFP_KERNEL); if (!transfer_buffer) { dev_err(&port->dev, "%s - out of memory\n", __func__); goto err_buf; } *transfer_buffer = ir_xbof | ir_baud; usb_fill_bulk_urb( urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), transfer_buffer, 1, ir_set_termios_callback, port); urb->transfer_flags = URB_ZERO_PACKET; result = usb_submit_urb(urb, GFP_KERNEL); if (result) { dev_err(&port->dev, "%s - failed to submit urb: %d\n", __func__, result); goto err_subm; } usb_free_urb(urb); return; err_subm: kfree(transfer_buffer); err_buf: usb_free_urb(urb); }
/* close the serial port. We should wait for data sending to device 1st and * then kill all urb. */ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int c_cflag; int bps; long timeout; wait_queue_t wait; int result; dbg("%s - port %d", __func__, port->number); /* wait for data to drain from the buffer */ spin_lock_irqsave(&priv->lock, flags); timeout = SPCP8x5_CLOSING_WAIT; init_waitqueue_entry(&wait, current); add_wait_queue(&port->tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (ringbuf_avail_data(priv->buf) == 0 || timeout == 0 || signal_pending(current)) 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 */ clear_ringbuf(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); /* wait for characters to drain from the device (this is long enough * for the entire all byte spcp8x5 hardware buffer to drain with no * flow control for data rates of 1200 bps or more, for lower rates we * should really know how much data is in the buffer to compute a delay * that is not unnecessarily long) */ bps = tty_get_baud_rate(port->tty); if (bps > 1200) timeout = max((HZ*2560) / bps, HZ/10); else timeout = 2*HZ; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(timeout); /* clear control lines */ if (port->tty) { c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; spin_unlock_irqrestore(&priv->lock, flags); spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type); } } /* kill urb */ if (port->write_urb != NULL) { result = usb_unlink_urb(port->write_urb); if (result) dev_dbg(&port->dev, "usb_unlink_urb(write_urb) = %d\n", result); } result = usb_unlink_urb(port->read_urb); if (result) dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result); }
static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; unsigned int baud = 0, bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); if (!tty) return; tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); /* If the baud rate is to be updated*/ if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { dbg("%s - Setting baud rate to %d baud", __func__, baud); if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { dbg("Baud rate requested not supported by device"); baud = tty_termios_baud_rate(old_termios); } } /* Report back the resulting baud rate */ tty_encode_baud_rate(tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); bits &= ~BITS_DATA_MASK; switch (cflag & CSIZE) { case CS5: bits |= BITS_DATA_5; dbg("%s - data bits = 5", __func__); break; case CS6: bits |= BITS_DATA_6; dbg("%s - data bits = 6", __func__); break; case CS7: bits |= BITS_DATA_7; dbg("%s - data bits = 7", __func__); break; case CS8: bits |= BITS_DATA_8; dbg("%s - data bits = 8", __func__); break; /*case CS9: bits |= BITS_DATA_9; dbg("%s - data bits = 9", __func__); break;*/ default: dbg("cp210x driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of data bits requested " "not supported by device\n"); } if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); bits &= ~BITS_PARITY_MASK; if (cflag & PARENB) { if (cflag & PARODD) { bits |= BITS_PARITY_ODD; dbg("%s - parity = ODD", __func__); } else { bits |= BITS_PARITY_EVEN; dbg("%s - parity = EVEN", __func__); } } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Parity mode not supported " "by device\n"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); bits &= ~BITS_STOP_MASK; if (cflag & CSTOPB) { bits |= BITS_STOP_2; dbg("%s - stop bits = 2", __func__); } else { bits |= BITS_STOP_1; dbg("%s - stop bits = 1", __func__); } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of stop bits requested " "not supported by device\n"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16); dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); if (cflag & CRTSCTS) { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x09; modem_ctl[1] = 0x80; dbg("%s - flow control = CRTSCTS", __func__); } else { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x01; modem_ctl[1] |= 0x40; dbg("%s - flow control = NONE", __func__); } dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); cp210x_set_config(port, CP210X_SET_FLOW, modem_ctl, 16); } }
static void klsi_105_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); unsigned int iflag = tty->termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int cflag = tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; struct klsi_105_port_settings *cfg; unsigned long flags; speed_t baud; cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) { dev_err(&port->dev, "%s - out of memory for config buffer.\n", __func__); return; } /* lock while we are modifying the settings */ spin_lock_irqsave(&priv->lock, flags); /* * Update baud rate */ baud = tty_get_baud_rate(tty); if ((cflag & CBAUD) != (old_cflag & CBAUD)) { /* reassert DTR and (maybe) RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { dbg("%s: baud was B0", __func__); #if 0 priv->control_state |= TIOCM_DTR; /* don't set RTS if using hardware flow control */ if (!(old_cflag & CRTSCTS)) priv->control_state |= TIOCM_RTS; mct_u232_set_modem_ctrl(serial, priv->control_state); #endif } } switch (baud) { case 0: /* handled below */ break; case 1200: priv->cfg.baudrate = kl5kusb105a_sio_b1200; break; case 2400: priv->cfg.baudrate = kl5kusb105a_sio_b2400; break; case 4800: priv->cfg.baudrate = kl5kusb105a_sio_b4800; break; case 9600: priv->cfg.baudrate = kl5kusb105a_sio_b9600; break; case 19200: priv->cfg.baudrate = kl5kusb105a_sio_b19200; break; case 38400: priv->cfg.baudrate = kl5kusb105a_sio_b38400; break; case 57600: priv->cfg.baudrate = kl5kusb105a_sio_b57600; break; case 115200: priv->cfg.baudrate = kl5kusb105a_sio_b115200; break; default: dbg("KLSI USB->Serial converter:" " unsupported baudrate request, using default of 9600"); priv->cfg.baudrate = kl5kusb105a_sio_b9600; baud = 9600; break; } if ((cflag & CBAUD) == B0) { dbg("%s: baud is B0", __func__); /* Drop RTS and DTR */ /* maybe this should be simulated by sending read * disable and read enable messages? */ ; #if 0 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); mct_u232_set_modem_ctrl(serial, priv->control_state); #endif } tty_encode_baud_rate(tty, baud, baud); if ((cflag & CSIZE) != (old_cflag & CSIZE)) { /* set the number of data bits */ switch (cflag & CSIZE) { case CS5: dbg("%s - 5 bits/byte not supported", __func__); spin_unlock_irqrestore(&priv->lock, flags); goto err; case CS6: dbg("%s - 6 bits/byte not supported", __func__); spin_unlock_irqrestore(&priv->lock, flags); goto err; case CS7: priv->cfg.databits = kl5kusb105a_dtb_7; break; case CS8: priv->cfg.databits = kl5kusb105a_dtb_8; break; default: dev_err(&port->dev, "CSIZE was not CS5-CS8, using default of 8\n"); priv->cfg.databits = kl5kusb105a_dtb_8; break; } } /* * Update line control register (LCR) */ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) || (cflag & CSTOPB) != (old_cflag & CSTOPB)) { /* Not currently supported */ tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB); #if 0 priv->last_lcr = 0; /* set the parity */ if (cflag & PARENB) priv->last_lcr |= (cflag & PARODD) ? MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; else priv->last_lcr |= MCT_U232_PARITY_NONE; /* set the number of stop bits */ priv->last_lcr |= (cflag & CSTOPB) ? MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; mct_u232_set_line_ctrl(serial, priv->last_lcr); #endif ; } /* * Set flow control: well, I do not really now how to handle DTR/RTS. * Just do what we have seen with SniffUSB on Win98. */ if ((iflag & IXOFF) != (old_iflag & IXOFF) || (iflag & IXON) != (old_iflag & IXON) || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { /* Not currently supported */ tty->termios->c_cflag &= ~CRTSCTS; /* Drop DTR/RTS if no flow control otherwise assert */ #if 0 if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) priv->control_state |= TIOCM_DTR | TIOCM_RTS; else priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); mct_u232_set_modem_ctrl(serial, priv->control_state); #endif ; } memcpy(cfg, &priv->cfg, sizeof(*cfg)); spin_unlock_irqrestore(&priv->lock, flags); /* now commit changes to device */ klsi_105_chg_port_settings(port, cfg); err: kfree(cfg); }
/* set the serial param for transfer. we should check if we really need to * transfer. then if be set flow contorl we should do this too. */ static void spcp8x5_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag = port->tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned short uartdata; unsigned char buf[2] = {0, 0}; int baud; int i; u8 control; if ((!port->tty) || (!port->tty->termios)) return; /* for the 1st time call this function */ spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); /* check that they really want us to change something */ if (!tty_termios_hw_change(port->tty->termios, old_termios)) return; /* set DTR/RTS active */ spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; if ((old_cflag & CBAUD) == B0) { priv->line_control |= MCR_DTR; if (!(old_cflag & CRTSCTS)) priv->line_control |= MCR_RTS; } if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); spcp8x5_set_ctrlLine(serial->dev, control , priv->type); } else { spin_unlock_irqrestore(&priv->lock, flags); } /* Set Baud Rate */ baud = tty_get_baud_rate(port->tty);; switch (baud) { case 300: buf[0] = 0x00; break; case 600: buf[0] = 0x01; break; case 1200: buf[0] = 0x02; break; case 2400: buf[0] = 0x03; break; case 4800: buf[0] = 0x04; break; case 9600: buf[0] = 0x05; break; case 19200: buf[0] = 0x07; break; case 38400: buf[0] = 0x09; break; case 57600: buf[0] = 0x0a; break; case 115200: buf[0] = 0x0b; break; case 230400: buf[0] = 0x0c; break; case 460800: buf[0] = 0x0d; break; case 921600: buf[0] = 0x0e; break; /* case 1200000: buf[0] = 0x0f; break; */ /* case 2400000: buf[0] = 0x10; break; */ case 3000000: buf[0] = 0x11; break; /* case 6000000: buf[0] = 0x12; break; */ case 0: case 1000000: buf[0] = 0x0b; break; default: err("spcp825 driver does not support the baudrate " "requested, using default of 9600."); } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ if (cflag & CSIZE) { switch (cflag & CSIZE) { case CS5: buf[1] |= SET_UART_FORMAT_SIZE_5; break; case CS6: buf[1] |= SET_UART_FORMAT_SIZE_6; break; case CS7: buf[1] |= SET_UART_FORMAT_SIZE_7; break; default: case CS8: buf[1] |= SET_UART_FORMAT_SIZE_8; break; } } /* Set Stop bit2 : 0:1bit 1:2bit */ buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 : SET_UART_FORMAT_STOP_1; /* Set Parity bit3-4 01:Odd 11:Even */ if (cflag & PARENB) { buf[1] |= (cflag & PARODD) ? SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ; } else buf[1] |= SET_UART_FORMAT_PAR_NONE; uartdata = buf[0] | buf[1]<<8; i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_UART_FORMAT_TYPE, SET_UART_FORMAT, uartdata, 0, NULL, 0, 100); if (i < 0) err("Set UART format %#x failed (error = %d)", uartdata, i); dbg("0x21:0x40:0:0 %d\n", i); if (cflag & CRTSCTS) { /* enable hardware flow control */ spcp8x5_set_workMode(serial->dev, 0x000a, SET_WORKING_MODE_U2C, priv->type); } return; }
static void firm_setup_port(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct whiteheat_port_settings port_settings; unsigned int cflag = tty->termios->c_cflag; port_settings.port = port->number + 1; /* get the byte size */ switch (cflag & CSIZE) { case CS5: port_settings.bits = 5; break; case CS6: port_settings.bits = 6; break; case CS7: port_settings.bits = 7; break; default: case CS8: port_settings.bits = 8; break; } dbg("%s - data bits = %d", __func__, port_settings.bits); /* determine the parity */ if (cflag & PARENB) if (cflag & CMSPAR) if (cflag & PARODD) port_settings.parity = WHITEHEAT_PAR_MARK; else port_settings.parity = WHITEHEAT_PAR_SPACE; else if (cflag & PARODD) port_settings.parity = WHITEHEAT_PAR_ODD; else port_settings.parity = WHITEHEAT_PAR_EVEN; else port_settings.parity = WHITEHEAT_PAR_NONE; dbg("%s - parity = %c", __func__, port_settings.parity); /* figure out the stop bits requested */ if (cflag & CSTOPB) port_settings.stop = 2; else port_settings.stop = 1; dbg("%s - stop bits = %d", __func__, port_settings.stop); /* figure out the flow control settings */ if (cflag & CRTSCTS) port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS); else port_settings.hflow = WHITEHEAT_HFLOW_NONE; dbg("%s - hardware flow control = %s %s %s %s", __func__, (port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "", (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "", (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "", (port_settings.hflow & WHITEHEAT_HFLOW_DTR) ? "DTR" : ""); /* determine software flow control */ if (I_IXOFF(tty)) port_settings.sflow = WHITEHEAT_SFLOW_RXTX; else port_settings.sflow = WHITEHEAT_SFLOW_NONE; dbg("%s - software flow control = %c", __func__, port_settings.sflow); port_settings.xon = START_CHAR(tty); port_settings.xoff = STOP_CHAR(tty); dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff); /* get the baud rate wanted */ port_settings.baud = tty_get_baud_rate(tty); dbg("%s - baud rate = %d", __func__, port_settings.baud); /* fixme: should set validated settings */ tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud); /* handle any settings that aren't specified in the tty structure */ port_settings.lloop = 0; /* now send the message to the device */ firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings)); }
static void ark3116_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; int baud; int ark3116_baud; char *buf; char config; config = 0; dbg("%s - port %d", __func__, port->number); cflag = termios->c_cflag; termios->c_cflag &= ~(CMSPAR|CRTSCTS); buf = kmalloc(1, GFP_KERNEL); if (!buf) { dbg("error kmalloc"); *termios = *old_termios; return; } /* set data bit count (8/7/6/5) */ if (cflag & CSIZE) { switch (cflag & CSIZE) { case CS5: config |= 0x00; dbg("setting CS5"); break; case CS6: config |= 0x01; dbg("setting CS6"); break; case CS7: config |= 0x02; dbg("setting CS7"); break; default: dbg("CSIZE was set but not CS5-CS8, using CS8!"); /* fall through */ case CS8: config |= 0x03; dbg("setting CS8"); break; } } /* set parity (NONE/EVEN/ODD) */ if (cflag & PARENB) { if (cflag & PARODD) { config |= 0x08; dbg("setting parity to ODD"); } else { config |= 0x18; dbg("setting parity to EVEN"); } } else { dbg("setting parity to NONE"); } /* set stop bit (1/2) */ if (cflag & CSTOPB) { config |= 0x04; dbg("setting 2 stop bits"); } else { dbg("setting 1 stop bit"); } /* set baudrate */ baud = tty_get_baud_rate(tty); switch (baud) { case 75: case 150: case 300: case 600: case 1200: case 1800: case 2400: case 4800: case 9600: case 19200: case 38400: case 57600: case 115200: case 230400: case 460800: /* Report the resulting rate back to the caller */ tty_encode_baud_rate(tty, baud, baud); break; /* set 9600 as default (if given baudrate is invalid for example) */ default: tty_encode_baud_rate(tty, 9600, 9600); case 0: baud = 9600; } /* * found by try'n'error, be careful, maybe there are other options * for multiplicator etc! (3.5 for example) */ if (baud == 460800) /* strange, for 460800 the formula is wrong * if using round() then 9600baud is wrong) */ ark3116_baud = 7; else ark3116_baud = 3000000 / baud; /* ? */ ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf); /* offset = buf[0]; */ /* offset = 0x03; */ /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */ /* set baudrate */ dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud); ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); ARK3116_SND(serial, 148, 0xFE, 0x40, (ark3116_baud & 0x00FF), 0x0000); ARK3116_SND(serial, 149, 0xFE, 0x40, (ark3116_baud & 0xFF00) >> 8, 0x0001); ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); /* ? */ ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); /* set data bit count, stop bit count & parity: */ dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config); ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003); if (cflag & CRTSCTS) dbg("CRTSCTS not supported by chipset?!"); /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */ kfree(buf); return; }
static void tiny_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { unsigned int cflag; cflag = tty->termios.c_cflag; /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(tty->termios.c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { printk(KERN_DEBUG " - nothing to change...\n"); return; } } /* get the byte size */ switch (cflag & CSIZE) { case CS5: printk(KERN_DEBUG " - data bits = 5\n"); break; case CS6: printk(KERN_DEBUG " - data bits = 6\n"); break; case CS7: printk(KERN_DEBUG " - data bits = 7\n"); break; default: case CS8: printk(KERN_DEBUG " - data bits = 8\n"); break; } /* determine the parity */ if (cflag & PARENB) if (cflag & PARODD) printk(KERN_DEBUG " - parity = odd\n"); else printk(KERN_DEBUG " - parity = even\n"); else printk(KERN_DEBUG " - parity = none\n"); /* figure out the stop bits requested */ if (cflag & CSTOPB) printk(KERN_DEBUG " - stop bits = 2\n"); else printk(KERN_DEBUG " - stop bits = 1\n"); /* figure out the hardware flow control settings */ if (cflag & CRTSCTS) printk(KERN_DEBUG " - RTS/CTS is enabled\n"); else printk(KERN_DEBUG " - RTS/CTS is disabled\n"); /* determine software flow control */ /* if we are implementing XON/XOFF, set the start and * stop character in the device */ if (I_IXOFF(tty) || I_IXON(tty)) { unsigned char stop_char = STOP_CHAR(tty); unsigned char start_char = START_CHAR(tty); /* if we are implementing INBOUND XON/XOFF */ if (I_IXOFF(tty)) printk(KERN_DEBUG " - INBOUND XON/XOFF is enabled, " "XON = %2x, XOFF = %2x", start_char, stop_char); else printk(KERN_DEBUG" - INBOUND XON/XOFF is disabled"); /* if we are implementing OUTBOUND XON/XOFF */ if (I_IXON(tty)) printk(KERN_DEBUG" - OUTBOUND XON/XOFF is enabled, " "XON = %2x, XOFF = %2x", start_char, stop_char); else printk(KERN_DEBUG" - OUTBOUND XON/XOFF is disabled"); } /* get the baud rate wanted */ printk(KERN_DEBUG " - baud rate = %d", tty_get_baud_rate(tty)); }
void gs_set_termios (struct tty_struct * tty, struct ktermios * old_termios) { struct gs_port *port; int baudrate, tmp, rv; struct ktermios *tiosp; func_enter(); if (!tty) return; port = tty->driver_data; if (!port) return; if (!port->tty) { /* This seems to happen when this is called after gs_close. */ gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->tty is NULL\n"); port->tty = tty; } tiosp = tty->termios; if (gs_debug & GS_DEBUG_TERMIOS) { gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); } /* This is an optimization that is only allowed for dumb cards */ /* Smart cards require knowledge of iflags and oflags too: that might change hardware cooking mode.... */ if (old_termios) { if( (tiosp->c_iflag == old_termios->c_iflag) && (tiosp->c_oflag == old_termios->c_oflag) && (tiosp->c_cflag == old_termios->c_cflag) && (tiosp->c_lflag == old_termios->c_lflag) && (tiosp->c_line == old_termios->c_line) && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) { gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n"); return /* 0 */; } } else gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: " "no optimization\n"); if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); if(tiosp->c_cflag != old_termios->c_cflag) printk("c_cflag changed\n"); if(tiosp->c_lflag != old_termios->c_lflag) printk("c_lflag changed\n"); if(tiosp->c_line != old_termios->c_line) printk("c_line changed\n"); if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); } baudrate = tty_get_baud_rate(tty); if ((tiosp->c_cflag & CBAUD) == B38400) { if ( (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) baudrate = 57600; else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) baudrate = 115200; else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) baudrate = 230400; else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) baudrate = 460800; else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) baudrate = (port->baud_base / port->custom_divisor); } /* I recommend using THIS instead of the mess in termios (and duplicating the above code). Next we should create a clean interface towards this variable. If your card supports arbitrary baud rates, (e.g. CD1400 or 16550 based cards) then everything will be very easy..... */ port->baud = baudrate; /* Two timer ticks seems enough to wakeup something like SLIP driver */ /* Baudrate/10 is cps. Divide by HZ to get chars per tick. */ tmp = (baudrate / 10 / HZ) * 2; if (tmp < 0) tmp = 0; if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1; port->wakeup_chars = tmp; /* We should really wait for the characters to be all sent before changing the settings. -- CAL */ rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT); if (rv < 0) return /* rv */; rv = port->rd->set_real_termios(port); if (rv < 0) return /* rv */; if ((!old_termios || (old_termios->c_cflag & CRTSCTS)) && !( tiosp->c_cflag & CRTSCTS)) { tty->stopped = 0; gs_start(tty); } #ifdef tytso_patch_94Nov25_1726 /* This "makes sense", Why is it commented out? */ if (!(old_termios->c_cflag & CLOCAL) && (tty->termios->c_cflag & CLOCAL)) wake_up_interruptible(&port->gs.open_wait); #endif func_exit(); return /* 0 */; }
static void qt2_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_device *dev = port->serial->dev; struct qt2_port_private *port_priv; struct ktermios *termios = &tty->termios; u16 baud; unsigned int cflag = termios->c_cflag; u16 new_lcr = 0; int status; port_priv = usb_get_serial_port_data(port); if (cflag & PARENB) { if (cflag & PARODD) new_lcr |= UART_LCR_PARITY; else new_lcr |= SERIAL_EVEN_PARITY; } switch (cflag & CSIZE) { case CS5: new_lcr |= UART_LCR_WLEN5; break; case CS6: new_lcr |= UART_LCR_WLEN6; break; case CS7: new_lcr |= UART_LCR_WLEN7; break; default: case CS8: new_lcr |= UART_LCR_WLEN8; break; } baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; status = qt2_set_port_config(dev, port_priv->device_port, baud, new_lcr); if (status < 0) dev_err(&port->dev, "%s - qt2_set_port_config failed: %i\n", __func__, status); if (cflag & CRTSCTS) status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, SERIAL_CRTSCTS, port_priv->device_port); else status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, 0, port_priv->device_port); if (status < 0) dev_err(&port->dev, "%s - set HW flow control failed: %i\n", __func__, status); if (I_IXOFF(tty) || I_IXON(tty)) { u16 x = ((u16) (START_CHAR(tty) << 8) | (u16) (STOP_CHAR(tty))); status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, x, port_priv->device_port); } else status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, 0, port_priv->device_port); if (status < 0) dev_err(&port->dev, "%s - set SW flow control failed: %i\n", __func__, status); }
static void mct_u232_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned long flags; unsigned int control_state; unsigned char last_lcr; /* get a local copy of the current port settings */ spin_lock_irqsave(&priv->lock, flags); control_state = priv->control_state; spin_unlock_irqrestore(&priv->lock, flags); last_lcr = 0; /* * Update baud rate. * Do not attempt to cache old rates and skip settings, * disconnects screw such tricks up completely. * Premature optimization is the root of all evil. */ /* reassert DTR and RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { dbg("%s: baud was B0", __func__); control_state |= TIOCM_DTR | TIOCM_RTS; mct_u232_set_modem_ctrl(serial, control_state); } mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty)); if ((cflag & CBAUD) == B0) { dbg("%s: baud is B0", __func__); /* Drop RTS and DTR */ control_state &= ~(TIOCM_DTR | TIOCM_RTS); mct_u232_set_modem_ctrl(serial, control_state); } /* * Update line control register (LCR) */ /* set the parity */ if (cflag & PARENB) last_lcr |= (cflag & PARODD) ? MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; else last_lcr |= MCT_U232_PARITY_NONE; /* set the number of data bits */ switch (cflag & CSIZE) { case CS5: last_lcr |= MCT_U232_DATA_BITS_5; break; case CS6: last_lcr |= MCT_U232_DATA_BITS_6; break; case CS7: last_lcr |= MCT_U232_DATA_BITS_7; break; case CS8: last_lcr |= MCT_U232_DATA_BITS_8; break; default: dev_err(&port->dev, "CSIZE was not CS5-CS8, using default of 8\n"); last_lcr |= MCT_U232_DATA_BITS_8; break; } termios->c_cflag &= ~CMSPAR; /* set the number of stop bits */ last_lcr |= (cflag & CSTOPB) ? MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; mct_u232_set_line_ctrl(serial, last_lcr); /* save off the modified port settings */ spin_lock_irqsave(&priv->lock, flags); priv->control_state = control_state; priv->last_lcr = last_lcr; spin_unlock_irqrestore(&priv->lock, flags); } /* mct_u232_set_termios */
static void ssu100_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_device *dev = port->serial->dev; struct ktermios *termios = &tty->termios; u16 baud, divisor, remainder; unsigned int cflag = termios->c_cflag; u16 urb_value = 0; /* will hold the new flags */ int result; if (cflag & PARENB) { if (cflag & PARODD) urb_value |= UART_LCR_PARITY; else urb_value |= SERIAL_EVEN_PARITY; } switch (cflag & CSIZE) { case CS5: urb_value |= UART_LCR_WLEN5; break; case CS6: urb_value |= UART_LCR_WLEN6; break; case CS7: urb_value |= UART_LCR_WLEN7; break; default: case CS8: urb_value |= UART_LCR_WLEN8; break; } baud = tty_get_baud_rate(tty); if (!baud) baud = 9600; dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud); divisor = MAX_BAUD_RATE / baud; remainder = MAX_BAUD_RATE % baud; if (((remainder * 2) >= baud) && (baud != 110)) divisor++; urb_value = urb_value << 8; result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value); if (result < 0) dev_dbg(&port->dev, "%s - set uart failed\n", __func__); if (cflag & CRTSCTS) result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, SERIAL_CRTSCTS, 0); else result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, 0, 0); if (result < 0) dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__); if (I_IXOFF(tty) || I_IXON(tty)) { u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty))); result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, x, 0); } else result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, 0, 0); if (result < 0) dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__); }