コード例 #1
0
ファイル: ir-usb.c プロジェクト: liexusong/Linux-2.4.16
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;
}
コード例 #2
0
ファイル: nullmodem.c プロジェクト: dugoh/nullmodem
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);
}
コード例 #3
0
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;
	}
}
コード例 #4
0
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);
}
コード例 #5
0
ファイル: ch341.c プロジェクト: aywq2008/omniplay
/* 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]
	 */
}
コード例 #6
0
ファイル: kobil_sct.c プロジェクト: maraz/linux-2.6
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);
}
コード例 #7
0
ファイル: tty_port.c プロジェクト: AshishNamdev/linux
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 {
コード例 #8
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;

	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);
	}
}
コード例 #9
0
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
		);
}
コード例 #10
0
ファイル: module.c プロジェクト: moregeek/raspicomm-module
// 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();
}
コード例 #11
0
ファイル: tty_port.c プロジェクト: markleppa/linux
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
コード例 #12
0
ファイル: ch341.c プロジェクト: maraz/linux-2.6
/* 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);
}
コード例 #13
0
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;
}
コード例 #14
0
ファイル: cdc-acm.c プロジェクト: pierdebeer/Audax_Kernel
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);
	}
}
コード例 #15
0
ファイル: ircomm_tty_ioctl.c プロジェクト: CSCLOG/beaglebone
/*
 * 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);
}
コード例 #16
0
ファイル: amiserial.c プロジェクト: kprog/linux
/*
 * 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);
}
コード例 #17
0
ファイル: mxu11x0.c プロジェクト: efferre79/mxu11x0
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);
}
コード例 #18
0
ファイル: ipoctal.c プロジェクト: 03199618/linux
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);
}
コード例 #19
0
ファイル: ir-usb.c プロジェクト: 33d/linux-2.6.21-hh20
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);
}
コード例 #20
0
ファイル: spcp8x5.c プロジェクト: maraz/linux-2.6
/* 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);
}
コード例 #21
0
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);
	}

}
コード例 #22
0
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);
}
コード例 #23
0
ファイル: spcp8x5.c プロジェクト: maraz/linux-2.6
/* 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;
}
コード例 #24
0
ファイル: whiteheat.c プロジェクト: dgarnier/linux
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));
}
コード例 #25
0
ファイル: ark3116.c プロジェクト: 325116067/semc-qsd8x50
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;
}
コード例 #26
0
ファイル: tiny_tty.c プロジェクト: 174high/ldd3
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));
}
コード例 #27
0
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 */;
}
コード例 #28
0
ファイル: quatech2.c プロジェクト: asmalldev/linux
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);

}
コード例 #29
0
ファイル: mct_u232.c プロジェクト: flwh/Alcatel_OT_985_kernel
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 */
コード例 #30
0
ファイル: ssu100.c プロジェクト: CoerWatt/linux
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__);

}