/* * functions called from TTY layer */ static int st_tty_open(struct tty_struct *tty) { int err = 0; struct st_data_s *st_gdata; pr_info("%s ", __func__); st_kim_ref(&st_gdata, 0); st_gdata->tty = tty; tty->disc_data = st_gdata; /* don't do an wakeup for now */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); /* mem already allocated */ tty->receive_room = 65536; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); /* * signal to UIM via KIM that - * installation of N_TI_WL ldisc is complete */ st_kim_complete(st_gdata->kim_data); pr_debug("done %s", __func__); return err; }
static int x25_asy_open_tty(struct tty_struct *tty) { struct x25_asy *sl = tty->disc_data; int err; if (tty->ops->write == NULL) return -EOPNOTSUPP; /* */ if (sl && sl->magic == X25_ASY_MAGIC) return -EEXIST; /* */ sl = x25_asy_alloc(); if (sl == NULL) return -ENFILE; sl->tty = tty; tty->disc_data = sl; tty->receive_room = 65536; tty_driver_flush_buffer(tty); tty_ldisc_flush(tty); /* */ sl->dev->type = ARPHRD_X25; /* */ err = x25_asy_open(sl->dev); if (err) return err; /* */ return 0; }
static int x25_asy_open_tty(struct tty_struct *tty) { struct x25_asy *sl; int err; if (tty->ops->write == NULL) return -EOPNOTSUPP; /* OK. Find a free X.25 channel to use. */ sl = x25_asy_alloc(); if (sl == NULL) return -ENFILE; sl->tty = tty; tty->disc_data = sl; tty->receive_room = 65536; tty_driver_flush_buffer(tty); tty_ldisc_flush(tty); /* Restore default settings */ sl->dev->type = ARPHRD_X25; /* Perform the low-level X.25 async init */ err = x25_asy_open(sl->dev); if (err) return err; /* Done. We have linked the TTY line to a channel. */ return 0; }
/* hci_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int hci_uart_tty_open(struct tty_struct *tty) { struct hci_uart *hu; BT_DBG("tty %p", tty); /* Error if the tty has no write op instead of leaving an exploitable hole */ if (tty->ops->write == NULL) return -EOPNOTSUPP; hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL); if (!hu) { BT_ERR("Can't allocate control structure"); return -ENFILE; } tty->disc_data = hu; hu->tty = tty; tty->receive_room = 65536; /* disable alignment support by default */ hu->alignment = 1; hu->padding = 0; INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); /* Flush any pending characters in the driver */ tty_driver_flush_buffer(tty); return 0; }
static int x25_asy_open_tty(struct tty_struct *tty) { struct x25_asy *sl = tty->disc_data; int err; if (tty->ops->write == NULL) return -EOPNOTSUPP; /* First make sure we're not already connected. */ if (sl && sl->magic == X25_ASY_MAGIC) return -EEXIST; /* OK. Find a free X.25 channel to use. */ sl = x25_asy_alloc(); if (sl == NULL) return -ENFILE; sl->tty = tty; tty->disc_data = sl; tty->receive_room = 65536; tty_driver_flush_buffer(tty); tty_ldisc_flush(tty); /* Restore default settings */ sl->dev->type = ARPHRD_X25; /* Perform the low-level X.25 async init */ err = x25_asy_open(sl->dev); if (err) return err; /* Done. We have linked the TTY line to a channel. */ return sl->dev->base_addr; }
/** * uart_tty_open() - Called when UART line discipline changed to N_HCI. * @tty: Pointer to associated TTY instance data. * * Returns: * 0 if there is no error. * Errors from cg2900_register_trans_driver. */ static int uart_tty_open(struct tty_struct *tty) { int err; CG2900_INFO("uart_tty_open"); /* Set the structure pointers and set the UART receive room */ uart_info->tty = tty; tty->disc_data = NULL; tty->receive_room = UART_RECEIVE_ROOM; /* * Flush any pending characters in the driver and line discipline. * Don't use ldisc_ref here as the open path is before the ldisc is * referencable. */ if (tty->ldisc->ops->flush_buffer) tty->ldisc->ops->flush_buffer(tty); tty_driver_flush_buffer(tty); /* Tell CG2900 Core that UART is connected */ err = cg2900_register_trans_driver(&uart_cb, NULL); if (err) CG2900_ERR("Could not register transport driver (%d)", err); return err; }
/* hci_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int hci_uart_tty_open(struct tty_struct *tty) { struct hci_uart *hu = (void *) tty->disc_data; BT_DBG("tty %p", tty); if (hu) return -EEXIST; if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { BT_ERR("Can't allocate control structure"); return -ENFILE; } tty->disc_data = hu; hu->tty = tty; tty->receive_room = 65536; spin_lock_init(&hu->rx_lock); /* Flush any pending characters in the driver and line discipline. */ /* FIXME: why is this needed. Note don't use ldisc_ref here as the open path is before the ldisc is referencable */ if (tty->ldisc->ops->flush_buffer) tty->ldisc->ops->flush_buffer(tty); tty_driver_flush_buffer(tty); return 0; }
/* stp_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int stp_uart_tty_open(struct tty_struct *tty) { UART_DBG_FUNC("stp_uart_tty_opentty: %p\n", tty); tty->receive_room = 65536; tty->low_latency = 1; /* Flush any pending characters in the driver and line discipline. */ /* FIXME: why is this needed. Note don't use ldisc_ref here as the open path is before the ldisc is referencable */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) /* definition changed!! */ if (tty->ldisc->ops->flush_buffer) { tty->ldisc->ops->flush_buffer(tty); } #else if (tty->ldisc.ops->flush_buffer) { tty->ldisc.ops->flush_buffer(tty); } #endif tty_driver_flush_buffer(tty); // init_MUTEX(&buf_mtx); //// spin_lock_init(&buf_lock); rd_idx = wr_idx = 0; stp_tty = tty; mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, mtk_wcn_uart_tx); return 0; }
/** * Prototype : ps_tty_close * Description : called by tty uart when close tty uart from octty * input : tty -> have opened tty * output : not * Calls : * Called By : * * History : * 1.Date : 2012/11/05 * Author : wx144390 * Modification : Created function * */ STATIC void ps_tty_close(struct tty_struct *tty) { struct ps_core_s *ps_core_d = NULL; PS_PRINT_INFO("%s: entered!!!\n", __func__); if ((NULL == tty)||(NULL == tty->disc_data)) { PS_PRINT_ERR("tty or tty->disc_data is NULL\n"); return; } ps_core_d = tty->disc_data; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); ps_core_d->tty = NULL; /* signal to complate that N_HW_BFG ldisc is un-installed */ ps_tty_complete(ps_core_d->pm_data, TTY_LDISC_UNINSTALL); PS_PRINT_INFO("uninstall complete done!\n"); ps_kfree_skb(ps_core_d, TX_HIGH_QUEUE); ps_kfree_skb(ps_core_d, TX_LOW_QUEUE); PS_PRINT_INFO("free tx sbk buf done!\n"); }
/* * The following routines are called from above (user space/tty). */ static int n_xbee_open(struct tty_struct *tty) { // Don't allow more than one tty to be attached if( main_tty != NULL ) return -EPERM; if (!try_module_get(THIS_MODULE)) return -ENODEV; if (tty->ops->stop) tty->ops->stop(tty); main_tty = tty; printk(KERN_ALERT "Attached to a tty!\n\n"); tty_driver_flush_buffer(tty); tty_ldisc_flush(tty); // For kernels < 3.10 it needs to be set tty->receive_room = 4096; /*priv->rbuff = kmalloc(XBEE_MAXFRAME, GFP_KERNEL); priv->rcount = 0; priv->frame_status = UNFRAMED; priv->frame_len = 0;*/ return 0; }
void tty_ldisc_hangup(struct tty_struct *tty) { struct tty_ldisc *ld; int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; int err = 0; /* * FIXME! What are the locking issues here? This may me overdoing * things... This question is especially important now that we've * removed the irqlock. */ ld = tty_ldisc_ref(tty); if (ld != NULL) { /* We may have no line discipline at this point */ if (ld->ops->flush_buffer) ld->ops->flush_buffer(tty); tty_driver_flush_buffer(tty); if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && ld->ops->write_wakeup) ld->ops->write_wakeup(tty); if (ld->ops->hangup) ld->ops->hangup(tty); tty_ldisc_deref(ld); } /* * FIXME: Once we trust the LDISC code better we can wait here for * ldisc completion and fix the driver call race */ wake_up_interruptible_poll(&tty->write_wait, POLLOUT); wake_up_interruptible_poll(&tty->read_wait, POLLIN); /* * Shutdown the current line discipline, and reset it to * N_TTY if need be. * * Avoid racing set_ldisc or tty_ldisc_release */ mutex_lock(&tty->ldisc_mutex); tty_ldisc_halt(tty); /* At this point we have a closed ldisc and we want to reopen it. We could defer this to the next open but it means auditing a lot of other paths so this is a FIXME */ if (tty->ldisc) { /* Not yet closed */ if (reset == 0) { tty_ldisc_reinit(tty, tty->termios->c_line); err = tty_ldisc_open(tty, tty->ldisc); } /* If the re-open fails or we reset then go to N_TTY. The N_TTY open cannot fail */ if (reset || err) { tty_ldisc_reinit(tty, N_TTY); WARN_ON(tty_ldisc_open(tty, tty->ldisc)); } tty_ldisc_enable(tty); } mutex_unlock(&tty->ldisc_mutex); if (reset) tty_reset_termios(tty); }
static inline void isig(int sig, struct tty_struct *tty, int flush) { if (tty->pgrp) kill_pgrp(tty->pgrp, sig, 1); if (flush || !L_NOFLSH(tty)) { n_tty_flush_buffer(tty); tty_driver_flush_buffer(tty); } }
static void st_tty_flush_buffer(struct tty_struct *tty) { struct st_data_s *st_gdata = tty->disc_data; pr_debug("%s ", __func__); kfree_skb(st_gdata->tx_skb); st_gdata->tx_skb = NULL; tty_driver_flush_buffer(tty); return; }
/** * n_tracerouter_close() - close connection * @tty: terminal device to the ldisc. * * Called when a software entity wants to close a connection. */ static void n_tracerouter_close(struct tty_struct *tty) { struct tracerouter_data *tptr = tty->disc_data; mutex_lock(&routelock); WARN_ON(tptr->kref_tty != tr_data->kref_tty); tty_driver_flush_buffer(tty); tty_kref_put(tr_data->kref_tty); tr_data->kref_tty = NULL; tr_data->opencalled = 0; tty->disc_data = NULL; mutex_unlock(&routelock); }
/** * Prototype : ps_change_uart_baud_rate * Description : change arm platform uart baud rate to secend * baud rate for high baud rate when download patch * input : ps_core_d * output : no * Calls : * Called By : * * History : * 1.Date : 2012/11/05 * Author : wx144390 * Modification : Created function * */ int32 ps_change_uart_baud_rate(int64 baud_rate, uint8 enable_flowctl) { struct ps_plat_s *ps_plat_d = NULL; struct ps_core_s *ps_core_d; uint64 timeleft = 0; PS_PRINT_INFO("%s\n", __func__); ps_get_plat_reference(&ps_plat_d); if (unlikely(NULL == ps_plat_d)) { PS_PRINT_ERR("ps_plat_d is NULL\n"); return -EINVAL; } ps_core_d = ps_plat_d->core_data; if (likely(NULL != ps_core_d->tty)) { tty_ldisc_flush(ps_core_d->tty); tty_driver_flush_buffer(ps_core_d->tty); } if (!IS_ERR_OR_NULL(ps_core_d->tty)) { if (tty_chars_in_buffer(ps_core_d->tty)) { PS_PRINT_INFO("uart tx buf is not empty\n"); } } INIT_COMPLETION(ps_plat_d->ldisc_reconfiged); ps_plat_d->flow_cntrl = enable_flowctl; ps_plat_d->baud_rate = baud_rate; ps_plat_d->ldisc_install = TTY_LDISC_RECONFIG; PS_PRINT_INFO("ldisc_install = %d\n", TTY_LDISC_RECONFIG); sysfs_notify(g_sysfs_hi110x_bfgx, NULL, "install"); timeleft = wait_for_completion_timeout(&ps_plat_d->ldisc_reconfiged, msecs_to_jiffies(HISI_LDISC_TIME)); if (!timeleft) { PS_PRINT_ERR("hisi bfgx ldisc reconfig timeout\n"); CHR_EXCEPTION(CHR_GNSS_DRV(CHR_GNSS_DRV_EVENT_PLAT, CHR_PLAT_DRV_ERROR_CFG_UART)); return -EINVAL; } PS_PRINT_SUC("hisi bfgx ldisc reconfig succ\n"); return 0; }
static void st_tty_close(struct tty_struct *tty) { unsigned char i = ST_MAX_CHANNELS; unsigned long flags = 0; struct st_data_s *st_gdata = tty->disc_data; pr_info("%s ", __func__); /* TODO: * if a protocol has been registered & line discipline * un-installed for some reason - what should be done ? */ spin_lock_irqsave(&st_gdata->lock, flags); for (i = 0; i < ST_MAX_CHANNELS; i++) { if (st_gdata->is_registered[i] == true) pr_err("%d not un-registered", i); st_gdata->list[i] = NULL; st_gdata->is_registered[i] = false; } st_gdata->protos_registered = 0; spin_unlock_irqrestore(&st_gdata->lock, flags); /* * signal to UIM via KIM that - * N_TI_WL ldisc is un-installed */ st_kim_complete(st_gdata->kim_data); st_gdata->tty = NULL; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); spin_lock_irqsave(&st_gdata->lock, flags); /* empty out txq and tx_waitq */ skb_queue_purge(&st_gdata->txq); skb_queue_purge(&st_gdata->tx_waitq); /* reset the TTY Rx states of ST */ st_gdata->rx_count = 0; st_gdata->rx_state = ST_W4_PACKET_TYPE; kfree_skb(st_gdata->rx_skb); st_gdata->rx_skb = NULL; spin_unlock_irqrestore(&st_gdata->lock, flags); pm_runtime_put_noidle(st_gdata->tty_dev); if (!pm_runtime_suspended(st_gdata->tty_dev)) __pm_runtime_idle(st_gdata->tty_dev, 0); pr_debug("%s: done ", __func__); }
/* nci_uart_tty_open * * Called when line discipline changed to NCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int nci_uart_tty_open(struct tty_struct *tty) { /* Error if the tty has no write op instead of leaving an exploitable * hole */ if (!tty->ops->write) return -EOPNOTSUPP; tty->disc_data = NULL; tty->receive_room = 65536; /* Flush any pending characters in the driver */ tty_driver_flush_buffer(tty); return 0; }
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
/** * Prototype : ps_tty_open * Description : called by tty uart itself when open tty uart from octty * input : tty -> have opened tty * output : not * Calls : * Called By : * * History : * 1.Date : 2012/11/05 * Author : wx144390 * Modification : Created function * */ STATIC int32 ps_tty_open(struct tty_struct *tty) { uint8 install; struct ps_core_s *ps_core_d = NULL; struct ps_plat_s *ps_plat_d = NULL; PS_PRINT_INFO("%s enter\n", __func__); ps_get_core_reference(&ps_core_d); if (unlikely(NULL == ps_core_d)) { PS_PRINT_ERR("ps_core_d is NULL\n"); return -EINVAL; } ps_core_d->tty = tty; tty->disc_data = ps_core_d; /* don't do an wakeup for now */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); /* set mem already allocated */ tty->receive_room = PUBLIC_BUF_MAX; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); ps_plat_d = (struct ps_plat_s *)ps_core_d->pm_data; install = ps_plat_d->ldisc_install; if (TTY_LDISC_INSTALL == install) { ps_tty_complete(ps_core_d->pm_data, TTY_LDISC_INSTALL); PS_PRINT_INFO("install complete done!\n"); } else if (TTY_LDISC_RECONFIG == install) { ps_tty_complete(ps_core_d->pm_data, TTY_LDISC_RECONFIG); PS_PRINT_INFO("reconfig complete done!\n"); } else { PS_PRINT_ERR("ldisc_install [%d] is error!\n", install); } return 0; }
/* hci_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int hci_uart_tty_open(struct tty_struct *tty) { struct hci_uart *hu = (void *) tty->disc_data; BT_DBG("tty %p", tty); /* FIXME: This btw is bogus, nothing requires the old ldisc to clear the pointer */ if (hu) return -EEXIST; /* Error if the tty has no write op instead of leaving an exploitable hole */ if (tty->ops->write == NULL) return -EOPNOTSUPP; if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { BT_ERR("Can't allocate control structure"); return -ENFILE; } tty->disc_data = hu; hu->tty = tty; tty->receive_room = 65536; spin_lock_init(&hu->rx_lock); /* Flush any pending characters in the driver and line discipline. */ /* FIXME: why is this needed. Note don't use ldisc_ref here as the open path is before the ldisc is referencable */ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) if (tty->ldisc->ops->flush_buffer) tty->ldisc->ops->flush_buffer(tty); #else if (tty->ldisc.ops->flush_buffer) tty->ldisc.ops->flush_buffer(tty); #endif tty_driver_flush_buffer(tty); return 0; }
/* Reset device */ static int hci_uart_flush(struct hci_dev *hdev) { struct hci_uart *hu = (struct hci_uart *) hdev->driver_data; struct tty_struct *tty = hu->tty; BT_DBG("hdev %p tty %p", hdev, tty); if (hu->tx_skb) { kfree_skb(hu->tx_skb); hu->tx_skb = NULL; } /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) hu->proto->flush(hu); return 0; }
/** * n_tracerouter_open() - Called when a tty is opened by a SW entity. * @tty: terminal device to the ldisc. * * Return: * 0 for success. * * Caveats: This should only be opened one time per SW entity. */ static int n_tracerouter_open(struct tty_struct *tty) { int retval = -EEXIST; mutex_lock(&routelock); if (tr_data->opencalled == 0) { tr_data->kref_tty = tty_kref_get(tty); if (tr_data->kref_tty == NULL) { retval = -EFAULT; } else { tr_data->opencalled = 1; tty->disc_data = tr_data; tty->receive_room = RECEIVE_ROOM; tty_driver_flush_buffer(tty); retval = 0; } } mutex_unlock(&routelock); return retval; }
/* stp_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int stp_uart_tty_open(struct tty_struct *tty) { UART_DBG_FUNC("original receive_room(%d) low_latency(%d) in tty(%p)\n", tty->receive_room, tty->low_latency, tty); tty->receive_room = 65536; #if LDISC_LOW_LATENCY tty->low_latency = 1; #endif UART_DBG_FUNC("set receive_room(%d) low_latency(%d) to tty(%p)\n", tty->receive_room, tty->low_latency, tty); /* Flush any pending characters in the driver and line discipline. */ /* FIXME: why is this needed. Note don't use ldisc_ref here as the open path is before the ldisc is referencable */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) /* definition changed!! */ if (tty->ldisc->ops->flush_buffer) { tty->ldisc->ops->flush_buffer(tty); } #else if (tty->ldisc.ops->flush_buffer) { tty->ldisc.ops->flush_buffer(tty); } #endif tty_driver_flush_buffer(tty); stp_uart_fifo_reset(); stp_uart_tty_tx_init(); stp_tty = tty; /* Register to STP-CORE */ mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, mtk_wcn_uart_tx); return 0; }
/** * n_hdlc_tty_open - called when line discipline changed to n_hdlc * @tty - pointer to tty info structure * * Returns 0 if success, otherwise error code */ static int n_hdlc_tty_open (struct tty_struct *tty) { struct n_hdlc *n_hdlc = tty2n_hdlc (tty); if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_open() called (device=%s)\n", __FILE__,__LINE__, tty->name); /* There should not be an existing table for this slot. */ if (n_hdlc) { printk (KERN_ERR"n_hdlc_tty_open:tty already associated!\n" ); return -EEXIST; } n_hdlc = n_hdlc_alloc(); if (!n_hdlc) { printk (KERN_ERR "n_hdlc_alloc failed\n"); return -ENFILE; } tty->disc_data = n_hdlc; n_hdlc->tty = tty; tty->receive_room = 65536; #if defined(TTY_NO_WRITE_SPLIT) /* change tty_io write() to not split large writes into 8K chunks */ set_bit(TTY_NO_WRITE_SPLIT,&tty->flags); #endif /* flush receive data from driver */ tty_driver_flush_buffer(tty); if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__); return 0; } /* end of n_tty_hdlc_open() */
static int n_hdlc_tty_open (struct tty_struct *tty) { struct n_hdlc *n_hdlc = tty2n_hdlc (tty); if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_open() called (device=%s)\n", __FILE__,__LINE__, tty->name); if (n_hdlc) { printk (KERN_ERR"n_hdlc_tty_open:tty already associated!\n" ); return -EEXIST; } n_hdlc = n_hdlc_alloc(); if (!n_hdlc) { printk (KERN_ERR "n_hdlc_alloc failed\n"); return -ENFILE; } tty->disc_data = n_hdlc; n_hdlc->tty = tty; tty->receive_room = 65536; #if defined(TTY_NO_WRITE_SPLIT) set_bit(TTY_NO_WRITE_SPLIT,&tty->flags); #endif tty_driver_flush_buffer(tty); if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__); return 0; }
/* hci_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int hci_uart_tty_open(struct tty_struct *tty) { struct hci_uart *hu; BT_DBG("tty %p", tty); /* Error if the tty has no write op instead of leaving an exploitable hole */ if (tty->ops->write == NULL) return -EOPNOTSUPP; hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL); if (!hu) { BT_ERR("Can't allocate control structure"); return -ENFILE; } tty->disc_data = hu; hu->tty = tty; tty->receive_room = 65536; INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); spin_lock_init(&hu->rx_lock); /* Flush any pending characters in the driver and line discipline. */ /* FIXME: why is this needed. Note don't use ldisc_ref here as the open path is before the ldisc is referencable */ if (tty->ldisc->ops->flush_buffer) tty->ldisc->ops->flush_buffer(tty); tty_driver_flush_buffer(tty); return 0; }
/* * functions called from TTY layer */ static int st_tty_open(struct tty_struct *tty) { int err = 0; struct st_data_s *st_gdata; pr_info("%s ", __func__); st_kim_ref(&st_gdata, 0); st_gdata->tty = tty; tty->disc_data = st_gdata; if (tty->dev->parent) st_gdata->tty_dev = tty->dev->parent; else return -EINVAL; /* Asynchronous Get is enough here since we just want to avoid * interface to be released too early */ pm_runtime_get(st_gdata->tty_dev); /* don't do an wakeup for now */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); /* mem already allocated */ tty->receive_room = 65536; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); /* * signal to UIM via KIM that - * installation of N_TI_WL ldisc is complete */ st_kim_complete(st_gdata->kim_data); pr_debug("done %s", __func__); return err; }
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { unsigned long flags; int parmrk; if (tty->raw) { put_tty_queue(c, tty); return; } if (I_ISTRIP(tty)) c &= 0x7f; if (I_IUCLC(tty) && L_IEXTEN(tty)) c = tolower(c); if (L_EXTPROC(tty)) { put_tty_queue(c, tty); return; } if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { start_tty(tty); process_echoes(tty); } if (tty->closing) { if (I_IXON(tty)) { if (c == START_CHAR(tty)) { start_tty(tty); process_echoes(tty); } else if (c == STOP_CHAR(tty)) stop_tty(tty); } return; } if (!test_bit(c, tty->process_char_map) || tty->lnext) { tty->lnext = 0; parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) { if (L_ECHO(tty)) process_output('\a', tty); return; } if (L_ECHO(tty)) { finish_erasing(tty); if (tty->canon_head == tty->read_head) echo_set_canon_col(tty); echo_char(c, tty); process_echoes(tty); } if (parmrk) put_tty_queue(c, tty); put_tty_queue(c, tty); return; } if (I_IXON(tty)) { if (c == START_CHAR(tty)) { start_tty(tty); process_echoes(tty); return; } if (c == STOP_CHAR(tty)) { stop_tty(tty); return; } } if (L_ISIG(tty)) { int signal; signal = SIGINT; if (c == INTR_CHAR(tty)) goto send_signal; signal = SIGQUIT; if (c == QUIT_CHAR(tty)) goto send_signal; signal = SIGTSTP; if (c == SUSP_CHAR(tty)) { send_signal: if (!L_NOFLSH(tty)) { n_tty_flush_buffer(tty); tty_driver_flush_buffer(tty); } if (I_IXON(tty)) start_tty(tty); if (L_ECHO(tty)) { echo_char(c, tty); process_echoes(tty); } if (tty->pgrp) kill_pgrp(tty->pgrp, signal, 1); return; } } if (c == '\r') { if (I_IGNCR(tty)) return; if (I_ICRNL(tty)) c = '\n'; } else if (c == '\n' && I_INLCR(tty)) c = '\r'; if (tty->icanon) { if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); process_echoes(tty); return; } if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { tty->lnext = 1; if (L_ECHO(tty)) { finish_erasing(tty); if (L_ECHOCTL(tty)) { echo_char_raw('^', tty); echo_char_raw('\b', tty); process_echoes(tty); } } return; } if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { unsigned long tail = tty->canon_head; finish_erasing(tty); echo_char(c, tty); echo_char_raw('\n', tty); while (tail != tty->read_head) { echo_char(tty->read_buf[tail], tty); tail = (tail+1) & (N_TTY_BUF_SIZE-1); } process_echoes(tty); return; } if (c == '\n') { if (tty->read_cnt >= N_TTY_BUF_SIZE) { if (L_ECHO(tty)) process_output('\a', tty); return; } if (L_ECHO(tty) || L_ECHONL(tty)) { echo_char_raw('\n', tty); process_echoes(tty); } goto handle_newline; } if (c == EOF_CHAR(tty)) { if (tty->read_cnt >= N_TTY_BUF_SIZE) return; if (tty->canon_head != tty->read_head) set_bit(TTY_PUSH, &tty->flags); c = __DISABLED_CHAR; goto handle_newline; } if ((c == EOL_CHAR(tty)) || (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) { if (L_ECHO(tty)) process_output('\a', tty); return; } if (L_ECHO(tty)) { if (tty->canon_head == tty->read_head) echo_set_canon_col(tty); echo_char(c, tty); process_echoes(tty); } if (parmrk) put_tty_queue(c, tty); handle_newline: spin_lock_irqsave(&tty->read_lock, flags); set_bit(tty->read_head, tty->read_flags); put_tty_queue_nolock(c, tty); tty->canon_head = tty->read_head; tty->canon_data++; spin_unlock_irqrestore(&tty->read_lock, flags); kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); return; } } parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) { if (L_ECHO(tty)) process_output('\a', tty); return; } if (L_ECHO(tty)) { finish_erasing(tty); if (c == '\n') echo_char_raw('\n', tty); else { if (tty->canon_head == tty->read_head) echo_set_canon_col(tty); echo_char(c, tty); } process_echoes(tty); } if (parmrk) put_tty_queue(c, tty); put_tty_queue(c, tty); }
void tty_ldisc_hangup(struct tty_struct *tty) { struct tty_ldisc *ld; int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; int err = 0; tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); ld = tty_ldisc_ref(tty); if (ld != NULL) { if (ld->ops->flush_buffer) ld->ops->flush_buffer(tty); tty_driver_flush_buffer(tty); if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && ld->ops->write_wakeup) ld->ops->write_wakeup(tty); if (ld->ops->hangup) ld->ops->hangup(tty); tty_ldisc_deref(ld); } wake_up_interruptible_poll(&tty->write_wait, POLLOUT); wake_up_interruptible_poll(&tty->read_wait, POLLIN); tty_unlock(tty); /* * Shutdown the current line discipline, and reset it to * N_TTY if need be. * * Avoid racing set_ldisc or tty_ldisc_release */ tty_ldisc_lock_pair(tty, tty->link); tty_lock(tty); if (tty->ldisc) { /* At this point we have a halted ldisc; we want to close it and reopen a new ldisc. We could defer the reopen to the next open but it means auditing a lot of other paths so this is a FIXME */ if (reset == 0) { if (!tty_ldisc_reinit(tty, tty->termios.c_line)) err = tty_ldisc_open(tty, tty->ldisc); else err = 1; } /* If the re-open fails or we reset then go to N_TTY. The N_TTY open cannot fail */ if (reset || err) { BUG_ON(tty_ldisc_reinit(tty, N_TTY)); WARN_ON(tty_ldisc_open(tty, tty->ldisc)); } } tty_ldisc_enable_pair(tty, tty->link); if (reset) tty_reset_termios(tty); tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc); }
static void n_xbee_flush_buffer(struct tty_struct *tty) { printk(KERN_ALERT "FLUSH_BUFFER CALLED\n"); tty_driver_flush_buffer(tty); }