diff options
Diffstat (limited to 'net/bluetooth/rfcomm/tty.c')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 206 |
1 files changed, 167 insertions, 39 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 6304590fd36a..1bca860a6109 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -286,7 +286,7 @@ static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *de | |||
286 | skb->destructor = rfcomm_wfree; | 286 | skb->destructor = rfcomm_wfree; |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, int priority) | 289 | static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, unsigned int __nocast priority) |
290 | { | 290 | { |
291 | if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) { | 291 | if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) { |
292 | struct sk_buff *skb = alloc_skb(size, priority); | 292 | struct sk_buff *skb = alloc_skb(size, priority); |
@@ -528,9 +528,14 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig) | |||
528 | struct rfcomm_dev *dev = dlc->owner; | 528 | struct rfcomm_dev *dev = dlc->owner; |
529 | if (!dev) | 529 | if (!dev) |
530 | return; | 530 | return; |
531 | 531 | ||
532 | BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig); | 532 | BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig); |
533 | 533 | ||
534 | if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) { | ||
535 | if (dev->tty && !C_CLOCAL(dev->tty)) | ||
536 | tty_hangup(dev->tty); | ||
537 | } | ||
538 | |||
534 | dev->modem_status = | 539 | dev->modem_status = |
535 | ((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) | | 540 | ((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) | |
536 | ((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) | | 541 | ((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) | |
@@ -740,20 +745,143 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned | |||
740 | return -ENOIOCTLCMD; | 745 | return -ENOIOCTLCMD; |
741 | } | 746 | } |
742 | 747 | ||
743 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
744 | |||
745 | static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) | 748 | static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) |
746 | { | 749 | { |
747 | BT_DBG("tty %p", tty); | 750 | struct termios *new = (struct termios *) tty->termios; |
751 | int old_baud_rate = tty_termios_baud_rate(old); | ||
752 | int new_baud_rate = tty_termios_baud_rate(new); | ||
748 | 753 | ||
749 | if ((tty->termios->c_cflag == old->c_cflag) && | 754 | u8 baud, data_bits, stop_bits, parity, x_on, x_off; |
750 | (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old->c_iflag))) | 755 | u16 changes = 0; |
751 | return; | 756 | |
757 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | ||
758 | |||
759 | BT_DBG("tty %p termios %p", tty, old); | ||
760 | |||
761 | /* Handle turning off CRTSCTS */ | ||
762 | if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) | ||
763 | BT_DBG("Turning off CRTSCTS unsupported"); | ||
764 | |||
765 | /* Parity on/off and when on, odd/even */ | ||
766 | if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) || | ||
767 | ((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) { | ||
768 | changes |= RFCOMM_RPN_PM_PARITY; | ||
769 | BT_DBG("Parity change detected."); | ||
770 | } | ||
771 | |||
772 | /* Mark and space parity are not supported! */ | ||
773 | if (new->c_cflag & PARENB) { | ||
774 | if (new->c_cflag & PARODD) { | ||
775 | BT_DBG("Parity is ODD"); | ||
776 | parity = RFCOMM_RPN_PARITY_ODD; | ||
777 | } else { | ||
778 | BT_DBG("Parity is EVEN"); | ||
779 | parity = RFCOMM_RPN_PARITY_EVEN; | ||
780 | } | ||
781 | } else { | ||
782 | BT_DBG("Parity is OFF"); | ||
783 | parity = RFCOMM_RPN_PARITY_NONE; | ||
784 | } | ||
785 | |||
786 | /* Setting the x_on / x_off characters */ | ||
787 | if (old->c_cc[VSTOP] != new->c_cc[VSTOP]) { | ||
788 | BT_DBG("XOFF custom"); | ||
789 | x_on = new->c_cc[VSTOP]; | ||
790 | changes |= RFCOMM_RPN_PM_XON; | ||
791 | } else { | ||
792 | BT_DBG("XOFF default"); | ||
793 | x_on = RFCOMM_RPN_XON_CHAR; | ||
794 | } | ||
795 | |||
796 | if (old->c_cc[VSTART] != new->c_cc[VSTART]) { | ||
797 | BT_DBG("XON custom"); | ||
798 | x_off = new->c_cc[VSTART]; | ||
799 | changes |= RFCOMM_RPN_PM_XOFF; | ||
800 | } else { | ||
801 | BT_DBG("XON default"); | ||
802 | x_off = RFCOMM_RPN_XOFF_CHAR; | ||
803 | } | ||
804 | |||
805 | /* Handle setting of stop bits */ | ||
806 | if ((old->c_cflag & CSTOPB) != (new->c_cflag & CSTOPB)) | ||
807 | changes |= RFCOMM_RPN_PM_STOP; | ||
808 | |||
809 | /* POSIX does not support 1.5 stop bits and RFCOMM does not | ||
810 | * support 2 stop bits. So a request for 2 stop bits gets | ||
811 | * translated to 1.5 stop bits */ | ||
812 | if (new->c_cflag & CSTOPB) { | ||
813 | stop_bits = RFCOMM_RPN_STOP_15; | ||
814 | } else { | ||
815 | stop_bits = RFCOMM_RPN_STOP_1; | ||
816 | } | ||
817 | |||
818 | /* Handle number of data bits [5-8] */ | ||
819 | if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) | ||
820 | changes |= RFCOMM_RPN_PM_DATA; | ||
821 | |||
822 | switch (new->c_cflag & CSIZE) { | ||
823 | case CS5: | ||
824 | data_bits = RFCOMM_RPN_DATA_5; | ||
825 | break; | ||
826 | case CS6: | ||
827 | data_bits = RFCOMM_RPN_DATA_6; | ||
828 | break; | ||
829 | case CS7: | ||
830 | data_bits = RFCOMM_RPN_DATA_7; | ||
831 | break; | ||
832 | case CS8: | ||
833 | data_bits = RFCOMM_RPN_DATA_8; | ||
834 | break; | ||
835 | default: | ||
836 | data_bits = RFCOMM_RPN_DATA_8; | ||
837 | break; | ||
838 | } | ||
839 | |||
840 | /* Handle baudrate settings */ | ||
841 | if (old_baud_rate != new_baud_rate) | ||
842 | changes |= RFCOMM_RPN_PM_BITRATE; | ||
752 | 843 | ||
753 | /* handle turning off CRTSCTS */ | 844 | switch (new_baud_rate) { |
754 | if ((old->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { | 845 | case 2400: |
755 | BT_DBG("turning off CRTSCTS"); | 846 | baud = RFCOMM_RPN_BR_2400; |
847 | break; | ||
848 | case 4800: | ||
849 | baud = RFCOMM_RPN_BR_4800; | ||
850 | break; | ||
851 | case 7200: | ||
852 | baud = RFCOMM_RPN_BR_7200; | ||
853 | break; | ||
854 | case 9600: | ||
855 | baud = RFCOMM_RPN_BR_9600; | ||
856 | break; | ||
857 | case 19200: | ||
858 | baud = RFCOMM_RPN_BR_19200; | ||
859 | break; | ||
860 | case 38400: | ||
861 | baud = RFCOMM_RPN_BR_38400; | ||
862 | break; | ||
863 | case 57600: | ||
864 | baud = RFCOMM_RPN_BR_57600; | ||
865 | break; | ||
866 | case 115200: | ||
867 | baud = RFCOMM_RPN_BR_115200; | ||
868 | break; | ||
869 | case 230400: | ||
870 | baud = RFCOMM_RPN_BR_230400; | ||
871 | break; | ||
872 | default: | ||
873 | /* 9600 is standard accordinag to the RFCOMM specification */ | ||
874 | baud = RFCOMM_RPN_BR_9600; | ||
875 | break; | ||
876 | |||
756 | } | 877 | } |
878 | |||
879 | if (changes) | ||
880 | rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud, | ||
881 | data_bits, stop_bits, parity, | ||
882 | RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes); | ||
883 | |||
884 | return; | ||
757 | } | 885 | } |
758 | 886 | ||
759 | static void rfcomm_tty_throttle(struct tty_struct *tty) | 887 | static void rfcomm_tty_throttle(struct tty_struct *tty) |
@@ -761,7 +889,7 @@ static void rfcomm_tty_throttle(struct tty_struct *tty) | |||
761 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 889 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
762 | 890 | ||
763 | BT_DBG("tty %p dev %p", tty, dev); | 891 | BT_DBG("tty %p dev %p", tty, dev); |
764 | 892 | ||
765 | rfcomm_dlc_throttle(dev->dlc); | 893 | rfcomm_dlc_throttle(dev->dlc); |
766 | } | 894 | } |
767 | 895 | ||
@@ -770,7 +898,7 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty) | |||
770 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 898 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
771 | 899 | ||
772 | BT_DBG("tty %p dev %p", tty, dev); | 900 | BT_DBG("tty %p dev %p", tty, dev); |
773 | 901 | ||
774 | rfcomm_dlc_unthrottle(dev->dlc); | 902 | rfcomm_dlc_unthrottle(dev->dlc); |
775 | } | 903 | } |
776 | 904 | ||
@@ -841,35 +969,35 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp) | |||
841 | 969 | ||
842 | static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear) | 970 | static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear) |
843 | { | 971 | { |
844 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 972 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
845 | struct rfcomm_dlc *dlc = dev->dlc; | 973 | struct rfcomm_dlc *dlc = dev->dlc; |
846 | u8 v24_sig; | 974 | u8 v24_sig; |
847 | 975 | ||
848 | BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear); | 976 | BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear); |
849 | 977 | ||
850 | rfcomm_dlc_get_modem_status(dlc, &v24_sig); | 978 | rfcomm_dlc_get_modem_status(dlc, &v24_sig); |
851 | 979 | ||
852 | if (set & TIOCM_DSR || set & TIOCM_DTR) | 980 | if (set & TIOCM_DSR || set & TIOCM_DTR) |
853 | v24_sig |= RFCOMM_V24_RTC; | 981 | v24_sig |= RFCOMM_V24_RTC; |
854 | if (set & TIOCM_RTS || set & TIOCM_CTS) | 982 | if (set & TIOCM_RTS || set & TIOCM_CTS) |
855 | v24_sig |= RFCOMM_V24_RTR; | 983 | v24_sig |= RFCOMM_V24_RTR; |
856 | if (set & TIOCM_RI) | 984 | if (set & TIOCM_RI) |
857 | v24_sig |= RFCOMM_V24_IC; | 985 | v24_sig |= RFCOMM_V24_IC; |
858 | if (set & TIOCM_CD) | 986 | if (set & TIOCM_CD) |
859 | v24_sig |= RFCOMM_V24_DV; | 987 | v24_sig |= RFCOMM_V24_DV; |
860 | 988 | ||
861 | if (clear & TIOCM_DSR || clear & TIOCM_DTR) | 989 | if (clear & TIOCM_DSR || clear & TIOCM_DTR) |
862 | v24_sig &= ~RFCOMM_V24_RTC; | 990 | v24_sig &= ~RFCOMM_V24_RTC; |
863 | if (clear & TIOCM_RTS || clear & TIOCM_CTS) | 991 | if (clear & TIOCM_RTS || clear & TIOCM_CTS) |
864 | v24_sig &= ~RFCOMM_V24_RTR; | 992 | v24_sig &= ~RFCOMM_V24_RTR; |
865 | if (clear & TIOCM_RI) | 993 | if (clear & TIOCM_RI) |
866 | v24_sig &= ~RFCOMM_V24_IC; | 994 | v24_sig &= ~RFCOMM_V24_IC; |
867 | if (clear & TIOCM_CD) | 995 | if (clear & TIOCM_CD) |
868 | v24_sig &= ~RFCOMM_V24_DV; | 996 | v24_sig &= ~RFCOMM_V24_DV; |
869 | 997 | ||
870 | rfcomm_dlc_set_modem_status(dlc, v24_sig); | 998 | rfcomm_dlc_set_modem_status(dlc, v24_sig); |
871 | 999 | ||
872 | return 0; | 1000 | return 0; |
873 | } | 1001 | } |
874 | 1002 | ||
875 | /* ---- TTY structure ---- */ | 1003 | /* ---- TTY structure ---- */ |