diff options
author | Benn Pörscke <benn.porscke@stericsson.com> | 2011-10-07 15:31:57 +0200 |
---|---|---|
committer | Benn Pörscke <benn.porscke@stericsson.com> | 2011-10-07 15:31:57 +0200 |
commit | 47a4dbf83a75014d6b3467be18997894f1c617db (patch) | |
tree | 7f5d116db48205309fbc4ae0954f20ab8a651e46 /drivers/bluetooth/hci_ldisc.c | |
parent | ea8a52f9f4bcc3420c38ae07f8378a2f18443970 (diff) |
Squashandroid-20111012
Change-Id: If0ae9fa8067740ab2ede33703c79ec134f204a5e
Diffstat (limited to 'drivers/bluetooth/hci_ldisc.c')
-rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 107 |
1 files changed, 99 insertions, 8 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 76a1abb8f21..c73b1dbd3ef 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -46,7 +46,10 @@ #include "hci_uart.h" -#define VERSION "2.2" +#define VERSION "2.3" + +#define TTY_BREAK_ON (-1) +#define TTY_BREAK_OFF (0) static int reset = 0; @@ -90,6 +93,9 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) { struct hci_dev *hdev = hu->hdev; + if (!hdev) + return; + /* Update HCI stat counters */ switch (pkt_type) { case HCI_COMMAND_PKT: @@ -139,7 +145,8 @@ restart: set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); len = tty->ops->write(tty, skb->data, skb->len); - hdev->stat.byte_tx += len; + if (hdev) + hdev->stat.byte_tx += len; skb_pull(skb, len); if (skb->len) { @@ -158,6 +165,70 @@ restart: return 0; } +int hci_uart_set_break(struct hci_uart *hu, bool break_on) +{ + struct tty_struct *tty = hu->tty; + int state = TTY_BREAK_OFF; + + if (break_on) + state = TTY_BREAK_ON; + + if (tty->ops->break_ctl) + return tty->ops->break_ctl(tty, state); + else + return -EOPNOTSUPP; +} + +void hci_uart_flow_ctrl(struct hci_uart *hu, bool flow_on) +{ + if (flow_on) + tty_unthrottle(hu->tty); + else + tty_throttle(hu->tty); +} + +int hci_uart_set_baudrate(struct hci_uart *hu, int baud) +{ + struct ktermios old_termios; + struct tty_struct *tty = hu->tty; + + if (!tty->ops->set_termios) + return -EOPNOTSUPP; + + mutex_lock(&(tty->termios_mutex)); + /* Start by storing the old termios. */ + memcpy(&old_termios, tty->termios, sizeof(old_termios)); + + tty_encode_baud_rate(tty, baud, baud); + + /* Finally inform the driver */ + tty->ops->set_termios(tty, &old_termios); + + mutex_unlock(&(tty->termios_mutex)); + + return 0; +} + +int hci_uart_tiocmget(struct hci_uart *hu) +{ + struct tty_struct *tty = hu->tty; + + if (!tty->ops->tiocmget || !hu->fd) + return -EOPNOTSUPP; + + return tty->ops->tiocmget(tty, hu->fd); +} + +void hci_uart_flush_buffer(struct hci_uart *hu) +{ + tty_driver_flush_buffer(hu->tty); +} + +int hci_uart_chars_in_buffer(struct hci_uart *hu) +{ + return tty_chars_in_buffer(hu->tty); +} + /* ------- Interface to HCI layer ------ */ /* Initialize device */ static int hci_uart_open(struct hci_dev *hdev) @@ -261,6 +332,9 @@ static int hci_uart_tty_open(struct tty_struct *tty) if (hu) return -EEXIST; + if (!tty->ops->write) + return -ENOTTY; + if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { BT_ERR("Can't allocate control structure"); return -ENFILE; @@ -306,8 +380,11 @@ static void hci_uart_tty_close(struct tty_struct *tty) if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { hu->proto->close(hu); - hci_unregister_dev(hdev); - hci_free_dev(hdev); + + if (hdev) { + hci_unregister_dev(hdev); + hci_free_dev(hdev); + } } } } @@ -362,7 +439,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f spin_lock(&hu->rx_lock); hu->proto->recv(hu, (void *) data, count); - hu->hdev->stat.byte_rx += count; + if (hu->hdev) + hu->hdev->stat.byte_rx += count; spin_unlock(&hu->rx_lock); tty_unthrottle(tty); @@ -415,11 +493,18 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) if (!p) return -EPROTONOSUPPORT; + hu->proto = p; + err = p->open(hu); if (err) return err; - hu->proto = p; + /* + * Protocol might register hdev by itself. + * In that case, there is no need to register it here. + */ + if (!hu->proto->register_hci_dev) + return 0; err = hci_uart_register_dev(hu); if (err) { @@ -463,6 +548,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, clear_bit(HCI_UART_PROTO_SET, &hu->flags); return err; } + /* Keep file descriptor.*/ + hu->fd = file; } else return -EBUSY; break; @@ -473,8 +560,12 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, return -EUNATCH; case HCIUARTGETDEVICE: - if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) - return hu->hdev->id; + if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) { + if (hu->hdev) + return hu->hdev->id; + else + return -ENOMSG; + } return -EUNATCH; default: |