static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { unsigned int mask = 0; poll_wait(file, &tty->read_wait, wait); poll_wait(file, &tty->write_wait, wait); if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty))) mask |= POLLIN | POLLRDNORM; if (tty->packet && tty->link->ctrl_status) mask |= POLLPRI | POLLIN | POLLRDNORM; if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) mask |= POLLHUP; if (tty_hung_up_p(file)) mask |= POLLHUP; if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { if (MIN_CHAR(tty) && !TIME_CHAR(tty)) tty->minimum_to_wake = MIN_CHAR(tty); else tty->minimum_to_wake = 1; } if (tty->ops->write && !tty_is_writelocked(tty) && tty_chars_in_buffer(tty) < WAKEUP_CHARS && tty_write_room(tty) > 0) mask |= POLLOUT | POLLWRNORM; return mask; }
static ssize_t process_output_block(struct tty_struct *tty, const unsigned char *buf, unsigned int nr) { int space; int i; const unsigned char *cp; mutex_lock(&tty->output_lock); space = tty_write_room(tty); if (!space) { mutex_unlock(&tty->output_lock); return 0; } if (nr > space) nr = space; for (i = 0, cp = buf; i < nr; i++, cp++) { unsigned char c = *cp; switch (c) { case '\n': if (O_ONLRET(tty)) tty->column = 0; if (O_ONLCR(tty)) goto break_out; tty->canon_column = tty->column; break; case '\r': if (O_ONOCR(tty) && tty->column == 0) goto break_out; if (O_OCRNL(tty)) goto break_out; tty->canon_column = tty->column = 0; break; case '\t': goto break_out; case '\b': if (tty->column > 0) tty->column--; break; default: if (!iscntrl(c)) { if (O_OLCUC(tty)) goto break_out; if (!is_continuation(c, tty)) tty->column++; } break; } } break_out: i = tty->ops->write(tty, buf, i); mutex_unlock(&tty->output_lock); return i; }
const char *spk_ttyio_synth_immediate(struct spk_synth *synth, const char *buff) { u_char ch; while ((ch = *buff)) { if (ch == '\n') ch = synth->procspeech; if (tty_write_room(speakup_tty) < 1 || !synth->io_ops->synth_out(synth, ch)) return buff; buff++; } return NULL; }
static int process_output(unsigned char c, struct tty_struct *tty) { int space, retval; mutex_lock(&tty->output_lock); space = tty_write_room(tty); retval = do_output_char(c, tty, space); mutex_unlock(&tty->output_lock); if (retval < 0) return -1; else return 0; }
int es705_uart_write(struct es705_priv *es705, const void *buf, int len) { int rc = 0; int count_remain = len; int bytes_wr = 0; mm_segment_t oldfs; loff_t pos = 0; dev_dbg(es705->dev, "%s(): size %d\n", __func__, len); /* * we may call from user context via char dev, so allow * read buffer in kernel address space */ oldfs = get_fs(); set_fs(KERNEL_DS); while (count_remain > 0) { /* block until tx buffer space is available */ while (tty_write_room(es705->uart_dev.tty) < UART_TTY_WRITE_SZ) usleep_range(2000, 2000); rc = vfs_write(es705->uart_dev.file, buf + bytes_wr, min(UART_TTY_WRITE_SZ, count_remain), &pos); if (rc < 0) { bytes_wr = rc; goto err_out; } bytes_wr += rc; count_remain -= rc; } err_out: /* restore old fs context */ set_fs(oldfs); dev_dbg(es705->dev, "%s(): write bytes %d\n", __func__, bytes_wr); return bytes_wr; }
static void transmit_block(struct r3964_info *pInfo) { struct tty_struct *tty = pInfo->tty; struct r3964_block_header *pBlock = pInfo->tx_first; int room = 0; if (tty == NULL || pBlock == NULL) { return; } room = tty_write_room(tty); TRACE_PS("transmit_block %p, room %d, length %d", pBlock, room, pBlock->length); while (pInfo->tx_position < pBlock->length) { if (room < 2) break; if (pBlock->data[pInfo->tx_position] == DLE) { /* send additional DLE char: */ put_char(pInfo, DLE); } put_char(pInfo, pBlock->data[pInfo->tx_position++]); room--; } if ((pInfo->tx_position == pBlock->length) && (room >= 3)) { put_char(pInfo, DLE); put_char(pInfo, ETX); if (pInfo->flags & R3964_BCC) { put_char(pInfo, pInfo->bcc); } pInfo->state = R3964_WAIT_FOR_TX_ACK; mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); } flush(pInfo); }
static int ld_pn_net_xmit(struct sk_buff *skb, struct net_device *dev) { struct ld_phonet *ld_pn; u8 *ptr; BUG_ON(dev == NULL); ld_pn = netdev_priv(dev); /* Add special Pattern before each ISI message */ ptr = skb_push(skb, 6); ptr[0] = 0xdd; ptr[1] = 0x7f; ptr[2] = 0x21; ptr[3] = 0x9a; ptr[4] = skb->data[10]; ptr[5] = skb->data[11]; if (ld_pn->link_up == true) { skb_queue_tail(&ld_pn->head, skb); return ld_pn_handle_tx(ld_pn); } else { if (tty_write_room(ld_pn->tty)) { /* link is up again */ ld_pn->link_up = true; ld_pn->nb_try_to_tx = 0; skb_queue_tail(&ld_pn->head, skb); return ld_pn_handle_tx(ld_pn); } else { if (in_interrupt()) dev_kfree_skb_irq(skb); else kfree_skb(skb); dev->stats.tx_dropped++; return NETDEV_TX_OK; } } }
static void process_echoes(struct tty_struct *tty) { int space, nr; unsigned char c; unsigned char *cp, *buf_end; if (!tty->echo_cnt) return; mutex_lock(&tty->output_lock); mutex_lock(&tty->echo_lock); space = tty_write_room(tty); buf_end = tty->echo_buf + N_TTY_BUF_SIZE; cp = tty->echo_buf + tty->echo_pos; nr = tty->echo_cnt; while (nr > 0) { c = *cp; if (c == ECHO_OP_START) { unsigned char op; unsigned char *opp; int no_space_left = 0; opp = cp + 1; if (opp == buf_end) opp -= N_TTY_BUF_SIZE; op = *opp; switch (op) { unsigned int num_chars, num_bs; case ECHO_OP_ERASE_TAB: if (++opp == buf_end) opp -= N_TTY_BUF_SIZE; num_chars = *opp; if (!(num_chars & 0x80)) num_chars += tty->canon_column; num_bs = 8 - (num_chars & 7); if (num_bs > space) { no_space_left = 1; break; } space -= num_bs; while (num_bs--) { tty_put_char(tty, '\b'); if (tty->column > 0) tty->column--; } cp += 3; nr -= 3; break; case ECHO_OP_SET_CANON_COL: tty->canon_column = tty->column; cp += 2; nr -= 2; break; case ECHO_OP_MOVE_BACK_COL: if (tty->column > 0) tty->column--; cp += 2; nr -= 2; break; case ECHO_OP_START: if (!space) { no_space_left = 1; break; } tty_put_char(tty, ECHO_OP_START); tty->column++; space--; cp += 2; nr -= 2; break; default: if (space < 2) { no_space_left = 1; break; } tty_put_char(tty, '^'); tty_put_char(tty, op ^ 0100); tty->column += 2; space -= 2; cp += 2; nr -= 2; } if (no_space_left) break; } else { if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { int retval = do_output_char(c, tty, space); if (retval < 0) break; space -= retval; } else { if (!space) break; tty_put_char(tty, c); space -= 1; } cp += 1; nr -= 1; } if (cp >= buf_end) cp -= N_TTY_BUF_SIZE; } if (nr == 0) { tty->echo_pos = 0; tty->echo_cnt = 0; tty->echo_overrun = 0; } else { int num_processed = tty->echo_cnt - nr; tty->echo_pos += num_processed; tty->echo_pos &= N_TTY_BUF_SIZE - 1; tty->echo_cnt = nr; if (num_processed > 0) tty->echo_overrun = 0; } mutex_unlock(&tty->echo_lock); mutex_unlock(&tty->output_lock); if (tty->ops->flush_chars) tty->ops->flush_chars(tty); }
static int ld_pn_handle_tx(struct ld_phonet *ld_pn) { struct tty_struct *tty = ld_pn->tty; struct sk_buff *skb; int tty_wr, len, room, i; PN_PRINTK("Write Data in tty\n"); if (tty == NULL) return 0; /* Enter critical section */ if (test_and_set_bit(PHONET_SENDING, &ld_pn->state)) return 0; /* skb_peek is safe because handle_tx is called after skb_queue_tail */ while ((skb = skb_peek(&ld_pn->head)) != NULL) { /* Make sure you don't write too much */ len = skb->len; room = tty_write_room(tty); if (!room) { if (ld_pn->nb_try_to_tx++ > 40) { ld_pn->link_up = false; /* Flush TX queue */ while ((skb = \ skb_dequeue(&ld_pn->head)) != NULL) { skb->dev->stats.tx_dropped++; if (in_interrupt()) dev_kfree_skb_irq(skb); else kfree_skb(skb); } } break; } /* Get room => reset nb_try_to_tx counter */ ld_pn->nb_try_to_tx = 0; if (room > MAX_WRITE_CHUNK) room = MAX_WRITE_CHUNK; if (len > room) len = room; tty_wr = tty->ops->write(tty, skb->data, len); ld_pn->dev->stats.tx_packets++; ld_pn->dev->stats.tx_bytes += tty_wr; PN_DATA_PRINTK("PHONET: write data in tty\n"); for (i = 1; i <= len; i++) { PN_DATA_PRINTK(" %02x", skb->data[i-1]); if ((i%8) == 0) PN_DATA_PRINTK("\n"); } PN_DATA_PRINTK("\n"); /* Error on TTY ?! */ if (tty_wr < 0) goto error; /* Reduce buffer written, and discard if empty */ skb_pull(skb, tty_wr); if (skb->len == 0) { struct sk_buff *tmp = skb_dequeue(&ld_pn->head); BUG_ON(tmp != skb); if (in_interrupt()) dev_kfree_skb_irq(skb); else kfree_skb(skb); } } /* Send flow off if queue is empty */ clear_bit(PHONET_SENDING, &ld_pn->state); return 0; error: clear_bit(PHONET_SENDING, &ld_pn->state); return tty_wr; }