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; }
/* 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); }
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; }
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); }
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); }
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; }
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; }