Пример #1
0
static int ath_wakeup_ar3k(struct tty_struct *tty)
{
	struct ktermios ktermios;
	int status = tty->driver->ops->tiocmget(tty);

	if (status & TIOCM_CTS)
		return status;

	/* Disable Automatic RTSCTS */
	memcpy(&ktermios, tty->termios, sizeof(ktermios));
	ktermios.c_cflag &= ~CRTSCTS;
	tty_set_termios(tty, &ktermios);

	/* Clear RTS first */
	status = tty->driver->ops->tiocmget(tty);
	tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS);
	mdelay(20);

	/* Set RTS, wake up board */
	status = tty->driver->ops->tiocmget(tty);
	tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00);
	mdelay(20);

	status = tty->driver->ops->tiocmget(tty);

	/* Disable Automatic RTSCTS */
	ktermios.c_cflag |= CRTSCTS;
	status = tty_set_termios(tty, &ktermios);

	return status;
}
Пример #2
0
/* Flow control or un-flow control the device */
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
{
	struct tty_struct *tty = hu->tty;
	struct ktermios ktermios;
	int status;
	unsigned int set = 0;
	unsigned int clear = 0;

	if (enable) {
		/* Disable hardware flow control */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
		ktermios = tty->termios;
#else
		ktermios = *tty->termios;
#endif
		ktermios.c_cflag &= ~CRTSCTS;
		status = tty_set_termios(tty, &ktermios);
		BT_DBG("Disabling hardware flow control: %s",
		       status ? "failed" : "success");

		/* Clear RTS to prevent the device from sending */
		/* Most UARTs need OUT2 to enable interrupts */
		status = tty->driver->ops->tiocmget(tty);
		BT_DBG("Current tiocm 0x%x", status);

		set &= ~(TIOCM_OUT2 | TIOCM_RTS);
		clear = ~set;
		set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
		       TIOCM_OUT2 | TIOCM_LOOP;
		clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
			 TIOCM_OUT2 | TIOCM_LOOP;
		status = tty->driver->ops->tiocmset(tty, set, clear);
		BT_DBG("Clearing RTS: %s", status ? "failed" : "success");
	} else {
		/* Set RTS to allow the device to send again */
		status = tty->driver->ops->tiocmget(tty);
		BT_DBG("Current tiocm 0x%x", status);

		set |= (TIOCM_OUT2 | TIOCM_RTS);
		clear = ~set;
		set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
		       TIOCM_OUT2 | TIOCM_LOOP;
		clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
			 TIOCM_OUT2 | TIOCM_LOOP;
		status = tty->driver->ops->tiocmset(tty, set, clear);
		BT_DBG("Setting RTS: %s", status ? "failed" : "success");

		/* Re-enable hardware flow control */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
		ktermios = tty->termios;
#else
		ktermios = *tty->termios;
#endif
		ktermios.c_cflag |= CRTSCTS;
		status = tty_set_termios(tty, &ktermios);
		BT_DBG("Enabling hardware flow control: %s",
		       status ? "failed" : "success");
	}
}
int es705_configure_tty(struct tty_struct *tty, u32 bps, int stop)
{
	int rc = 0;

	struct ktermios termios;
	termios = *tty->termios;

	dev_dbg(es705_priv.dev, "%s(): Requesting baud %u\n", __func__, bps);

	termios.c_cflag &= ~(CBAUD | CSIZE | PARENB);   /* clear csize, baud */
	termios.c_cflag |= BOTHER;	      /* allow arbitrary baud */
	termios.c_cflag |= CS8;

	if (stop == 2)
		termios.c_cflag |= CSTOPB;

	/* set uart port to raw mode (see termios man page for flags) */
	termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
		| INLCR | IGNCR | ICRNL | IXON);
	termios.c_oflag &= ~(OPOST);
	termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);

	/* set baud rate */
	termios.c_ospeed = bps;
	termios.c_ispeed = bps;

	rc = tty_set_termios(tty, &termios);

	dev_dbg(es705_priv.dev,
		"%s(): New baud %u\n", __func__, tty->termios->c_ospeed);

	return rc;
}
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
	struct tty_struct *tty = hu->tty;
	struct ktermios ktermios;

	ktermios = tty->termios;
	ktermios.c_cflag &= ~CBAUD;
	tty_termios_encode_baud_rate(&ktermios, speed, speed);

	/* tty_set_termios() return not checked as it is always 0 */
	tty_set_termios(tty, &ktermios);

	BT_DBG("%s: New tty speeds: %d/%d", hu->hdev->name,
	       tty->termios.c_ispeed, tty->termios.c_ospeed);
}
Пример #5
0
static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
{
	int ret = 0;
	struct tty_struct *tty;
	struct ktermios tmp_termios;
	dev_t dev;

	ret = get_dev_to_use(synth, &dev);
	if (ret)
		return ret;

	tty = tty_kopen(dev);
	if (IS_ERR(tty))
		return PTR_ERR(tty);

	if (tty->ops->open)
		ret = tty->ops->open(tty, NULL);
	else
		ret = -ENODEV;

	if (ret) {
		tty_unlock(tty);
		return ret;
	}

	clear_bit(TTY_HUPPED, &tty->flags);
	/* ensure hardware flow control is enabled */
	get_termios(tty, &tmp_termios);
	if (!(tmp_termios.c_cflag & CRTSCTS)) {
		tmp_termios.c_cflag |= CRTSCTS;
		tty_set_termios(tty, &tmp_termios);
		/*
		 * check c_cflag to see if it's updated as tty_set_termios may not return
		 * error even when no tty bits are changed by the request.
		 */
		get_termios(tty, &tmp_termios);
		if (!(tmp_termios.c_cflag & CRTSCTS))
			pr_warn("speakup: Failed to set hardware flow control\n");
	}

	tty_unlock(tty);

	ret = tty_set_ldisc(tty, N_SPEAKUP);
	if (ret)
		pr_err("speakup: Failed to set N_SPEAKUP on tty\n");

	return ret;
}
Пример #6
0
void hci_uart_init_tty(struct hci_uart *hu)
{
	struct tty_struct *tty = hu->tty;
	struct ktermios ktermios;

	/* Bring the UART into a known 8 bits no parity hw fc state */
	ktermios = tty->termios;
	ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
			      INLCR | IGNCR | ICRNL | IXON);
	ktermios.c_oflag &= ~OPOST;
	ktermios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	ktermios.c_cflag &= ~(CSIZE | PARENB);
	ktermios.c_cflag |= CS8;
	ktermios.c_cflag |= CRTSCTS;

	/* tty_set_termios() return not checked as it is always 0 */
	tty_set_termios(tty, &ktermios);
}
Пример #7
0
void nci_uart_set_config(struct nci_uart *nu, int baudrate, int flow_ctrl)
{
	struct ktermios new_termios;

	if (!nu->tty)
		return;

	down_read(&nu->tty->termios_rwsem);
	new_termios = nu->tty->termios;
	up_read(&nu->tty->termios_rwsem);
	tty_termios_encode_baud_rate(&new_termios, baudrate, baudrate);

	if (flow_ctrl)
		new_termios.c_cflag |= CRTSCTS;
	else
		new_termios.c_cflag &= ~CRTSCTS;

	tty_set_termios(nu->tty, &new_termios);
}
Пример #8
0
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
	struct tty_struct *tty = hu->tty;
	struct ktermios ktermios;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
	ktermios = tty->termios;
#else
	ktermios = *tty->termios;
#endif
	ktermios.c_cflag &= ~CBAUD;
	tty_termios_encode_baud_rate(&ktermios, speed, speed);

	/* tty_set_termios() return not checked as it is always 0 */
	tty_set_termios(tty, &ktermios);

	BT_DBG("%s: New tty speeds: %d/%d", hu->hdev->name,
	       ktermios.c_ispeed, ktermios.c_ospeed);
}
int es705_configure_tty(struct tty_struct *tty, u32 bps, int stop)
{
	int rc = 0;

	struct ktermios termios;
	termios = *tty->termios;

	dev_dbg(es705_priv.dev, "%s(): Requesting baud %u\n", __func__, bps);

	termios.c_cflag &= ~(CBAUD | CSIZE | PARENB);   /* clear csize, baud */
	termios.c_cflag |= BOTHER;	      /* allow arbitrary baud */
	termios.c_cflag |= CS8;

	if (stop == 2)
		termios.c_cflag |= CSTOPB;

	/* set uart port to raw mode (see termios man page for flags) */
    termios.c_iflag &= ~(PARMRK    /* disable mark parity errors */
                            | ISTRIP    /* disable clear high bit of input characters */
                            | INLCR           /* disable translate NL to CR */
                            | IGNCR           /* disable ignore CR */
                            | ICRNL           /* disable translate CR to NL */
                            | IXON);    /* disable enable XON/XOFF flow control */
	termios.c_iflag |= IGNBRK;    /* enable ignore break */

	termios.c_oflag &= ~(OPOST);
	termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);

	/* set baud rate */
	termios.c_ospeed = bps;
	termios.c_ispeed = bps;

	rc = tty_set_termios(tty, &termios);

	dev_dbg(es705_priv.dev,
		"%s(): New baud %u\n", __func__, tty->termios->c_ospeed);

	return rc;
}
Пример #10
0
UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, wStream* output, UINT32* abort_io)
{
	int purge_mask;
	UINT32 result;
	UINT32 modemstate;
	BYTE immediate;
	UINT32 ret = STATUS_SUCCESS;
	UINT32 length = 0;
	UINT32 pos;

	DEBUG_SVC("in");

	Stream_Seek(output, sizeof(UINT32));

	switch (IoControlCode)
	{
		case IOCTL_SERIAL_SET_BAUD_RATE:
			Stream_Read_UINT32(input, tty->baud_rate);
			tty_set_termios(tty);
			DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate);
			break;

		case IOCTL_SERIAL_GET_BAUD_RATE:
			length = 4;
			Stream_Write_UINT32(output, tty->baud_rate);
			DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate);
			break;

		case IOCTL_SERIAL_SET_QUEUE_SIZE:
			Stream_Read_UINT32(input, tty->queue_in_size);
			Stream_Read_UINT32(input, tty->queue_out_size);
			DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size);
			break;

		case IOCTL_SERIAL_SET_LINE_CONTROL:
			Stream_Read_UINT8(input, tty->stop_bits);
			Stream_Read_UINT8(input, tty->parity);
			Stream_Read_UINT8(input, tty->word_length);
			tty_set_termios(tty);
			DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d",
				tty->stop_bits, tty->parity, tty->word_length);
			break;

		case IOCTL_SERIAL_GET_LINE_CONTROL:
			DEBUG_SVC("SERIAL_GET_LINE_CONTROL");
			length = 3;
			Stream_Write_UINT8(output, tty->stop_bits);
			Stream_Write_UINT8(output, tty->parity);
			Stream_Write_UINT8(output, tty->word_length);
			break;

		case IOCTL_SERIAL_IMMEDIATE_CHAR:
			DEBUG_SVC("SERIAL_IMMEDIATE_CHAR");
			Stream_Read_UINT8(input, immediate);
			tty_write_data(tty, &immediate, 1);
			break;

		case IOCTL_SERIAL_CONFIG_SIZE:
			DEBUG_SVC("SERIAL_CONFIG_SIZE");
			length = 4;
			Stream_Write_UINT32(output, 0);
			break;

		case IOCTL_SERIAL_GET_CHARS:
			DEBUG_SVC("SERIAL_GET_CHARS");
			length = 6;
			Stream_Write(output, tty->chars, 6);
			break;

		case IOCTL_SERIAL_SET_CHARS:
			DEBUG_SVC("SERIAL_SET_CHARS");
			Stream_Read(input, tty->chars, 6);
			tty_set_termios(tty);
			break;

		case IOCTL_SERIAL_GET_HANDFLOW:
			length = 16;
			tty_get_termios(tty);
			Stream_Write_UINT32(output, tty->control);
			Stream_Write_UINT32(output, tty->xonoff);
			Stream_Write_UINT32(output, tty->onlimit);
			Stream_Write_UINT32(output, tty->offlimit);
			DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X",
				tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
			break;

		case IOCTL_SERIAL_SET_HANDFLOW:
			Stream_Read_UINT32(input, tty->control);
			Stream_Read_UINT32(input, tty->xonoff);
			Stream_Read_UINT32(input, tty->onlimit);
			Stream_Read_UINT32(input, tty->offlimit);
			DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X",
				tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
			tty_set_termios(tty);
			break;

		case IOCTL_SERIAL_SET_TIMEOUTS:
			Stream_Read_UINT32(input, tty->read_interval_timeout);
			Stream_Read_UINT32(input, tty->read_total_timeout_multiplier);
			Stream_Read_UINT32(input, tty->read_total_timeout_constant);
			Stream_Read_UINT32(input, tty->write_total_timeout_multiplier);
			Stream_Read_UINT32(input, tty->write_total_timeout_constant);

			/* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section
				http://msdn.microsoft.com/en-us/library/ms885171.aspx */
			if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX)
			{
				tty->read_interval_timeout = 0;
				tty->read_total_timeout_multiplier = 0;
			}

			DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d",
				tty->read_interval_timeout,
				tty->read_total_timeout_multiplier,
				tty->read_total_timeout_constant);
			break;

		case IOCTL_SERIAL_GET_TIMEOUTS:
			DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d",
				tty->read_interval_timeout,
				tty->read_total_timeout_multiplier,
				tty->read_total_timeout_constant);
			length = 20;
			Stream_Write_UINT32(output, tty->read_interval_timeout);
			Stream_Write_UINT32(output, tty->read_total_timeout_multiplier);
			Stream_Write_UINT32(output, tty->read_total_timeout_constant);
			Stream_Write_UINT32(output, tty->write_total_timeout_multiplier);
			Stream_Write_UINT32(output, tty->write_total_timeout_constant);
			break;

		case IOCTL_SERIAL_GET_WAIT_MASK:
			DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask);
			length = 4;
			Stream_Write_UINT32(output, tty->wait_mask);
			break;

		case IOCTL_SERIAL_SET_WAIT_MASK:
			Stream_Read_UINT32(input, tty->wait_mask);
			DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask);
			break;

		case IOCTL_SERIAL_SET_DTR:
			DEBUG_SVC("SERIAL_SET_DTR");
			ioctl(tty->fd, TIOCMGET, &result);
			result |= TIOCM_DTR;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->dtr = 1;
			break;

		case IOCTL_SERIAL_CLR_DTR:
			DEBUG_SVC("SERIAL_CLR_DTR");
			ioctl(tty->fd, TIOCMGET, &result);
			result &= ~TIOCM_DTR;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->dtr = 0;
			break;

		case IOCTL_SERIAL_SET_RTS:
			DEBUG_SVC("SERIAL_SET_RTS");
			ioctl(tty->fd, TIOCMGET, &result);
			result |= TIOCM_RTS;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->rts = 1;
			break;

		case IOCTL_SERIAL_CLR_RTS:
			DEBUG_SVC("SERIAL_CLR_RTS");
			ioctl(tty->fd, TIOCMGET, &result);
			result &= ~TIOCM_RTS;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->rts = 0;
			break;

		case IOCTL_SERIAL_GET_MODEMSTATUS:
			modemstate = 0;
#ifdef TIOCMGET
			ioctl(tty->fd, TIOCMGET, &result);
			if (result & TIOCM_CTS)
				modemstate |= SERIAL_MS_CTS;
			if (result & TIOCM_DSR)
				modemstate |= SERIAL_MS_DSR;
			if (result & TIOCM_RNG)
				modemstate |= SERIAL_MS_RNG;
			if (result & TIOCM_CAR)
				modemstate |= SERIAL_MS_CAR;
			if (result & TIOCM_DTR)
				modemstate |= SERIAL_MS_DTR;
			if (result & TIOCM_RTS)
				modemstate |= SERIAL_MS_RTS;
#endif
			DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate);
			length = 4;
			Stream_Write_UINT32(output, modemstate);
			break;

		case IOCTL_SERIAL_GET_COMMSTATUS:
			length = 18;
			Stream_Write_UINT32(output, 0);	/* Errors */
			Stream_Write_UINT32(output, 0);	/* Hold reasons */

			result = 0;
#ifdef TIOCINQ
			ioctl(tty->fd, TIOCINQ, &result);
#endif
			Stream_Write_UINT32(output, result); /* Amount in in queue */
			if (result)
				DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result);

			result = 0;
#ifdef TIOCOUTQ
			ioctl(tty->fd, TIOCOUTQ, &result);
#endif
			Stream_Write_UINT32(output, result);	/* Amount in out queue */
			DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result);

			Stream_Write_UINT8(output, 0); /* EofReceived */
			Stream_Write_UINT8(output, 0); /* WaitForImmediate */
			break;

		case IOCTL_SERIAL_PURGE:
			Stream_Read_UINT32(input, purge_mask);
			DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask);

		/*	See http://msdn.microsoft.com/en-us/library/ms901431.aspx
			PURGE_TXCLEAR 	Clears the output buffer, if the driver has one.
			PURGE_RXCLEAR 	Clears the input buffer, if the driver has one.

			It clearly states to clear the *driver* buffer, not the port buffer
		*/

#ifdef DEBUG_SVC
			if (purge_mask & SERIAL_PURGE_TXCLEAR)
				DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR");
			if (purge_mask & SERIAL_PURGE_RXCLEAR)
				DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR");
#endif

			if (purge_mask & SERIAL_PURGE_TXABORT)
				*abort_io |= SERIAL_ABORT_IO_WRITE;
			if (purge_mask & SERIAL_PURGE_RXABORT)
				*abort_io |= SERIAL_ABORT_IO_READ;
			break;
		case IOCTL_SERIAL_WAIT_ON_MASK:
			DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask);
			tty->event_pending = 1;
			length = 4;
			if (serial_tty_get_event(tty, &result))
			{
				DEBUG_SVC("WAIT end  event = %X", result);
				Stream_Write_UINT32(output, result);
				break;
			}
			ret = STATUS_PENDING;
			break;

		case IOCTL_SERIAL_SET_BREAK_ON:
			DEBUG_SVC("SERIAL_SET_BREAK_ON");
			tcsendbreak(tty->fd, 0);
			break;

		case IOCTL_SERIAL_RESET_DEVICE:
			DEBUG_SVC("SERIAL_RESET_DEVICE");
			break;

		case IOCTL_SERIAL_SET_BREAK_OFF:
			DEBUG_SVC("SERIAL_SET_BREAK_OFF");
			break;

		case IOCTL_SERIAL_SET_XOFF:
			DEBUG_SVC("SERIAL_SET_XOFF");
			break;

		case IOCTL_SERIAL_SET_XON:
			DEBUG_SVC("SERIAL_SET_XON");
			tcflow(tty->fd, TCION);
			break;

		default:
			DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode);
			return STATUS_INVALID_PARAMETER;
	}

	/* Write OutputBufferLength */
	pos = Stream_GetPosition(output);
	Stream_SetPosition(output, 16);
	Stream_Write_UINT32(output, length);
	Stream_SetPosition(output, pos);

	return ret;
}