aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/rfcomm
diff options
context:
space:
mode:
authorGianluca Anzolin <gianluca@sottospazio.it>2013-07-29 11:08:11 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-08-21 10:47:07 -0400
commitcad348a17e170451ea8688b532a6ca3e98c63b60 (patch)
tree3fb0be283c7ae30a0ca1810da3c6922a7cb1948b /net/bluetooth/rfcomm
parent54b926a1434e817ca84cb090f36b56763e192470 (diff)
Bluetooth: Implement .activate, .shutdown and .carrier_raised methods
Implement .activate, .shutdown and .carrier_raised methods of tty_port to manage the dlc, moving the code from rfcomm_tty_install() and rfcomm_tty_cleanup() functions. At the same time the tty .open()/.close() and .hangup() methods are changed to use the tty_port helpers that properly call the aforementioned tty_port methods. Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it> Reviewed-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth/rfcomm')
-rw-r--r--net/bluetooth/rfcomm/tty.c117
1 files changed, 47 insertions, 70 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 73dd61530130..583f7135c811 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -58,7 +58,6 @@ struct rfcomm_dev {
58 uint modem_status; 58 uint modem_status;
59 59
60 struct rfcomm_dlc *dlc; 60 struct rfcomm_dlc *dlc;
61 wait_queue_head_t wait;
62 61
63 struct device *tty_dev; 62 struct device *tty_dev;
64 63
@@ -104,8 +103,39 @@ static void rfcomm_dev_destruct(struct tty_port *port)
104 module_put(THIS_MODULE); 103 module_put(THIS_MODULE);
105} 104}
106 105
106/* device-specific initialization: open the dlc */
107static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
108{
109 struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
110
111 return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
112}
113
114/* we block the open until the dlc->state becomes BT_CONNECTED */
115static int rfcomm_dev_carrier_raised(struct tty_port *port)
116{
117 struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
118
119 return (dev->dlc->state == BT_CONNECTED);
120}
121
122/* device-specific cleanup: close the dlc */
123static void rfcomm_dev_shutdown(struct tty_port *port)
124{
125 struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
126
127 if (dev->tty_dev->parent)
128 device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
129
130 /* close the dlc */
131 rfcomm_dlc_close(dev->dlc, 0);
132}
133
107static const struct tty_port_operations rfcomm_port_ops = { 134static const struct tty_port_operations rfcomm_port_ops = {
108 .destruct = rfcomm_dev_destruct, 135 .destruct = rfcomm_dev_destruct,
136 .activate = rfcomm_dev_activate,
137 .shutdown = rfcomm_dev_shutdown,
138 .carrier_raised = rfcomm_dev_carrier_raised,
109}; 139};
110 140
111static struct rfcomm_dev *__rfcomm_dev_get(int id) 141static struct rfcomm_dev *__rfcomm_dev_get(int id)
@@ -228,7 +258,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
228 258
229 tty_port_init(&dev->port); 259 tty_port_init(&dev->port);
230 dev->port.ops = &rfcomm_port_ops; 260 dev->port.ops = &rfcomm_port_ops;
231 init_waitqueue_head(&dev->wait);
232 261
233 skb_queue_head_init(&dev->pending); 262 skb_queue_head_init(&dev->pending);
234 263
@@ -563,9 +592,12 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
563 BT_DBG("dlc %p dev %p err %d", dlc, dev, err); 592 BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
564 593
565 dev->err = err; 594 dev->err = err;
566 wake_up_interruptible(&dev->wait); 595 if (dlc->state == BT_CONNECTED) {
596 device_move(dev->tty_dev, rfcomm_get_device(dev),
597 DPM_ORDER_DEV_AFTER_PARENT);
567 598
568 if (dlc->state == BT_CLOSED) { 599 wake_up_interruptible(&dev->port.open_wait);
600 } else if (dlc->state == BT_CLOSED) {
569 tty = tty_port_tty_get(&dev->port); 601 tty = tty_port_tty_get(&dev->port);
570 if (!tty) { 602 if (!tty) {
571 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { 603 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
@@ -640,17 +672,10 @@ static void rfcomm_tty_cleanup(struct tty_struct *tty)
640{ 672{
641 struct rfcomm_dev *dev = tty->driver_data; 673 struct rfcomm_dev *dev = tty->driver_data;
642 674
643 if (dev->tty_dev->parent)
644 device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
645
646 /* Close DLC and dettach TTY */
647 rfcomm_dlc_close(dev->dlc, 0);
648
649 clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags); 675 clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
650 676
651 rfcomm_dlc_lock(dev->dlc); 677 rfcomm_dlc_lock(dev->dlc);
652 tty->driver_data = NULL; 678 tty->driver_data = NULL;
653 dev->port.tty = NULL;
654 rfcomm_dlc_unlock(dev->dlc); 679 rfcomm_dlc_unlock(dev->dlc);
655 680
656 tty_port_put(&dev->port); 681 tty_port_put(&dev->port);
@@ -662,7 +687,6 @@ static void rfcomm_tty_cleanup(struct tty_struct *tty)
662 */ 687 */
663static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) 688static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
664{ 689{
665 DECLARE_WAITQUEUE(wait, current);
666 struct rfcomm_dev *dev; 690 struct rfcomm_dev *dev;
667 struct rfcomm_dlc *dlc; 691 struct rfcomm_dlc *dlc;
668 int err; 692 int err;
@@ -676,72 +700,30 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
676 /* Attach TTY and open DLC */ 700 /* Attach TTY and open DLC */
677 rfcomm_dlc_lock(dlc); 701 rfcomm_dlc_lock(dlc);
678 tty->driver_data = dev; 702 tty->driver_data = dev;
679 dev->port.tty = tty;
680 rfcomm_dlc_unlock(dlc); 703 rfcomm_dlc_unlock(dlc);
681 set_bit(RFCOMM_TTY_ATTACHED, &dev->flags); 704 set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
682 705
683 /* install the tty_port */ 706 /* install the tty_port */
684 err = tty_port_install(&dev->port, driver, tty); 707 err = tty_port_install(&dev->port, driver, tty);
685 if (err < 0) 708 if (err)
686 goto error_no_dlc; 709 rfcomm_tty_cleanup(tty);
687
688 err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
689 if (err < 0)
690 goto error_no_dlc;
691 710
692 /* Wait for DLC to connect */
693 add_wait_queue(&dev->wait, &wait);
694 while (1) {
695 set_current_state(TASK_INTERRUPTIBLE);
696
697 if (dlc->state == BT_CLOSED) {
698 err = -dev->err;
699 break;
700 }
701
702 if (dlc->state == BT_CONNECTED)
703 break;
704
705 if (signal_pending(current)) {
706 err = -EINTR;
707 break;
708 }
709
710 tty_unlock(tty);
711 schedule();
712 tty_lock(tty);
713 }
714 set_current_state(TASK_RUNNING);
715 remove_wait_queue(&dev->wait, &wait);
716
717 if (err < 0)
718 goto error_no_connection;
719
720 device_move(dev->tty_dev, rfcomm_get_device(dev),
721 DPM_ORDER_DEV_AFTER_PARENT);
722 return 0;
723
724error_no_connection:
725 rfcomm_dlc_close(dlc, err);
726error_no_dlc:
727 clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
728 tty_port_put(&dev->port);
729 return err; 711 return err;
730} 712}
731 713
732static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) 714static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
733{ 715{
734 struct rfcomm_dev *dev = tty->driver_data; 716 struct rfcomm_dev *dev = tty->driver_data;
735 unsigned long flags; 717 int err;
736 718
737 BT_DBG("tty %p id %d", tty, tty->index); 719 BT_DBG("tty %p id %d", tty, tty->index);
738 720
739 BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst, 721 BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst,
740 dev->channel, dev->port.count); 722 dev->channel, dev->port.count);
741 723
742 spin_lock_irqsave(&dev->port.lock, flags); 724 err = tty_port_open(&dev->port, tty, filp);
743 dev->port.count++; 725 if (err)
744 spin_unlock_irqrestore(&dev->port.lock, flags); 726 return err;
745 727
746 /* 728 /*
747 * FIXME: rfcomm should use proper flow control for 729 * FIXME: rfcomm should use proper flow control for
@@ -758,7 +740,6 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
758static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) 740static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
759{ 741{
760 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; 742 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
761 unsigned long flags;
762 743
763 if (!dev) 744 if (!dev)
764 return; 745 return;
@@ -766,14 +747,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
766 BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, 747 BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
767 dev->port.count); 748 dev->port.count);
768 749
769 spin_lock_irqsave(&dev->port.lock, flags); 750 tty_port_close(&dev->port, tty, filp);
770 if (!--dev->port.count) {
771 spin_unlock_irqrestore(&dev->port.lock, flags);
772 751
773 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) 752 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
774 tty_port_put(&dev->port); 753 tty_port_put(&dev->port);
775 } else
776 spin_unlock_irqrestore(&dev->port.lock, flags);
777} 754}
778 755
779static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) 756static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -1076,7 +1053,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
1076 if (!dev) 1053 if (!dev)
1077 return; 1054 return;
1078 1055
1079 rfcomm_tty_flush_buffer(tty); 1056 tty_port_hangup(&dev->port);
1080 1057
1081 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { 1058 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
1082 if (rfcomm_dev_get(dev->id) == NULL) 1059 if (rfcomm_dev_get(dev->id) == NULL)
@@ -1166,7 +1143,7 @@ int __init rfcomm_init_ttys(void)
1166 rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL; 1143 rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
1167 rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 1144 rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
1168 rfcomm_tty_driver->init_termios = tty_std_termios; 1145 rfcomm_tty_driver->init_termios = tty_std_termios;
1169 rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; 1146 rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
1170 rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; 1147 rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
1171 tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); 1148 tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
1172 1149