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 ---- */ |
