Commit 3a5e903c authored by J. Suter's avatar J. Suter Committed by David S. Miller

[Bluetooth]: Implement RFCOMM remote port negotiation

This patch implements the remote port negotiation (RPN) of the RFCOMM
protocol for Bluetooth.
Signed-off-by: default avatarJ. Suter <jsuter@hardwave.de>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7b9eb9e2
...@@ -80,9 +80,9 @@ ...@@ -80,9 +80,9 @@
#define RFCOMM_RPN_STOP_15 1 #define RFCOMM_RPN_STOP_15 1
#define RFCOMM_RPN_PARITY_NONE 0x0 #define RFCOMM_RPN_PARITY_NONE 0x0
#define RFCOMM_RPN_PARITY_ODD 0x4 #define RFCOMM_RPN_PARITY_ODD 0x1
#define RFCOMM_RPN_PARITY_EVEN 0x5 #define RFCOMM_RPN_PARITY_EVEN 0x3
#define RFCOMM_RPN_PARITY_MARK 0x6 #define RFCOMM_RPN_PARITY_MARK 0x5
#define RFCOMM_RPN_PARITY_SPACE 0x7 #define RFCOMM_RPN_PARITY_SPACE 0x7
#define RFCOMM_RPN_FLOW_NONE 0x00 #define RFCOMM_RPN_FLOW_NONE 0x00
...@@ -223,6 +223,12 @@ struct rfcomm_dlc { ...@@ -223,6 +223,12 @@ struct rfcomm_dlc {
#define RFCOMM_CFC_DISABLED 0 #define RFCOMM_CFC_DISABLED 0
#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS #define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
/* ---- RFCOMM SEND RPN ---- */
int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 bit_rate, u8 data_bits, u8 stop_bits,
u8 parity, u8 flow_ctrl_settings,
u8 xon_char, u8 xoff_char, u16 param_mask);
/* ---- RFCOMM DLCs (channels) ---- */ /* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(int prio); struct rfcomm_dlc *rfcomm_dlc_alloc(int prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d); void rfcomm_dlc_free(struct rfcomm_dlc *d);
......
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
SOFTWARE IS DISCLAIMED. SOFTWARE IS DISCLAIMED.
*/ */
/*
RPN support - Dirk Husemann <hud@zurich.ibm.com>
*/
/* /*
* Bluetooth RFCOMM core. * Bluetooth RFCOMM core.
* *
...@@ -115,10 +111,10 @@ static void rfcomm_session_del(struct rfcomm_session *s); ...@@ -115,10 +111,10 @@ static void rfcomm_session_del(struct rfcomm_session *s);
#define __get_mcc_len(b) ((b & 0xfe) >> 1) #define __get_mcc_len(b) ((b & 0xfe) >> 1)
/* RPN macros */ /* RPN macros */
#define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x3) << 3)) #define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x7) << 3))
#define __get_rpn_data_bits(line) ((line) & 0x3) #define __get_rpn_data_bits(line) ((line) & 0x3)
#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1) #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
#define __get_rpn_parity(line) (((line) >> 3) & 0x3) #define __get_rpn_parity(line) (((line) >> 3) & 0x7)
static inline void rfcomm_schedule(uint event) static inline void rfcomm_schedule(uint event)
{ {
...@@ -780,10 +776,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d ...@@ -780,10 +776,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
return rfcomm_send_frame(s, buf, ptr - buf); return rfcomm_send_frame(s, buf, ptr - buf);
} }
static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 bit_rate, u8 data_bits, u8 stop_bits, u8 bit_rate, u8 data_bits, u8 stop_bits,
u8 parity, u8 flow_ctrl_settings, u8 parity, u8 flow_ctrl_settings,
u8 xon_char, u8 xoff_char, u16 param_mask) u8 xon_char, u8 xoff_char, u16 param_mask)
{ {
struct rfcomm_hdr *hdr; struct rfcomm_hdr *hdr;
struct rfcomm_mcc *mcc; struct rfcomm_mcc *mcc;
...@@ -791,9 +787,9 @@ static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, ...@@ -791,9 +787,9 @@ static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 buf[16], *ptr = buf; u8 buf[16], *ptr = buf;
BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x" BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x"
"flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x",
s, cr, dlci, bit_rate, data_bits, stop_bits, parity, s, cr, dlci, bit_rate, data_bits, stop_bits, parity,
flow_ctrl_settings, xon_char, xoff_char, param_mask); flow_ctrl_settings, xon_char, xoff_char, param_mask);
hdr = (void *) ptr; ptr += sizeof(*hdr); hdr = (void *) ptr; ptr += sizeof(*hdr);
hdr->addr = __addr(s->initiator, 0); hdr->addr = __addr(s->initiator, 0);
...@@ -1265,16 +1261,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1265,16 +1261,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
u8 xon_char = 0; u8 xon_char = 0;
u8 xoff_char = 0; u8 xoff_char = 0;
u16 rpn_mask = RFCOMM_RPN_PM_ALL; u16 rpn_mask = RFCOMM_RPN_PM_ALL;
BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x", BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl, dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
rpn->xon_char, rpn->xoff_char, rpn->param_mask); rpn->xon_char, rpn->xoff_char, rpn->param_mask);
if (!cr) if (!cr)
return 0; return 0;
if (len == 1) { if (len == 1) {
/* request: return default setting */ /* This is a request, return default settings */
bit_rate = RFCOMM_RPN_BR_115200; bit_rate = RFCOMM_RPN_BR_115200;
data_bits = RFCOMM_RPN_DATA_8; data_bits = RFCOMM_RPN_DATA_8;
stop_bits = RFCOMM_RPN_STOP_1; stop_bits = RFCOMM_RPN_STOP_1;
...@@ -1282,11 +1278,12 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1282,11 +1278,12 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
flow_ctrl = RFCOMM_RPN_FLOW_NONE; flow_ctrl = RFCOMM_RPN_FLOW_NONE;
xon_char = RFCOMM_RPN_XON_CHAR; xon_char = RFCOMM_RPN_XON_CHAR;
xoff_char = RFCOMM_RPN_XOFF_CHAR; xoff_char = RFCOMM_RPN_XOFF_CHAR;
goto rpn_out; goto rpn_out;
} }
/* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity,
no flow control lines, normal XON/XOFF chars */ /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
* no parity, no flow control lines, normal XON/XOFF chars */
if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) { if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) {
bit_rate = rpn->bit_rate; bit_rate = rpn->bit_rate;
if (bit_rate != RFCOMM_RPN_BR_115200) { if (bit_rate != RFCOMM_RPN_BR_115200) {
...@@ -1295,6 +1292,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1295,6 +1292,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_BITRATE; rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_DATA) { if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
data_bits = __get_rpn_data_bits(rpn->line_settings); data_bits = __get_rpn_data_bits(rpn->line_settings);
if (data_bits != RFCOMM_RPN_DATA_8) { if (data_bits != RFCOMM_RPN_DATA_8) {
...@@ -1303,6 +1301,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1303,6 +1301,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_DATA; rpn_mask ^= RFCOMM_RPN_PM_DATA;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_STOP) { if (rpn->param_mask & RFCOMM_RPN_PM_STOP) {
stop_bits = __get_rpn_stop_bits(rpn->line_settings); stop_bits = __get_rpn_stop_bits(rpn->line_settings);
if (stop_bits != RFCOMM_RPN_STOP_1) { if (stop_bits != RFCOMM_RPN_STOP_1) {
...@@ -1311,6 +1310,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1311,6 +1310,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_STOP; rpn_mask ^= RFCOMM_RPN_PM_STOP;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) { if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) {
parity = __get_rpn_parity(rpn->line_settings); parity = __get_rpn_parity(rpn->line_settings);
if (parity != RFCOMM_RPN_PARITY_NONE) { if (parity != RFCOMM_RPN_PARITY_NONE) {
...@@ -1319,6 +1319,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1319,6 +1319,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_PARITY; rpn_mask ^= RFCOMM_RPN_PM_PARITY;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
flow_ctrl = rpn->flow_ctrl; flow_ctrl = rpn->flow_ctrl;
if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) { if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
...@@ -1327,6 +1328,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1327,6 +1328,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_FLOW; rpn_mask ^= RFCOMM_RPN_PM_FLOW;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_XON) { if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
xon_char = rpn->xon_char; xon_char = rpn->xon_char;
if (xon_char != RFCOMM_RPN_XON_CHAR) { if (xon_char != RFCOMM_RPN_XON_CHAR) {
...@@ -1335,6 +1337,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1335,6 +1337,7 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
rpn_mask ^= RFCOMM_RPN_PM_XON; rpn_mask ^= RFCOMM_RPN_PM_XON;
} }
} }
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
xoff_char = rpn->xoff_char; xoff_char = rpn->xoff_char;
if (xoff_char != RFCOMM_RPN_XOFF_CHAR) { if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
...@@ -1345,9 +1348,8 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ ...@@ -1345,9 +1348,8 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
} }
rpn_out: rpn_out:
rfcomm_send_rpn(s, 0, dlci, rfcomm_send_rpn(s, 0, dlci, bit_rate, data_bits, stop_bits,
bit_rate, data_bits, stop_bits, parity, flow_ctrl, parity, flow_ctrl, xon_char, xoff_char, rpn_mask);
xon_char, xoff_char, rpn_mask);
return 0; return 0;
} }
...@@ -1358,14 +1360,13 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1358,14 +1360,13 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
u8 dlci = __get_dlci(rls->dlci); u8 dlci = __get_dlci(rls->dlci);
BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status); BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
if (!cr) if (!cr)
return 0; return 0;
/* FIXME: We should probably do something with this /* We should probably do something with this information here. But
information here. But for now it's sufficient just * for now it's sufficient just to reply -- Bluetooth 1.1 says it's
to reply -- Bluetooth 1.1 says it's mandatory to * mandatory to recognise and respond to RLS */
recognise and respond to RLS */
rfcomm_send_rls(s, 0, dlci, rls->status); rfcomm_send_rls(s, 0, dlci, rls->status);
...@@ -1381,7 +1382,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1381,7 +1382,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
d = rfcomm_dlc_get(s, dlci); d = rfcomm_dlc_get(s, dlci);
if (!d) if (!d)
return 0; return 0;
if (cr) { if (cr) {
...@@ -1389,7 +1390,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1389,7 +1390,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
set_bit(RFCOMM_TX_THROTTLED, &d->flags); set_bit(RFCOMM_TX_THROTTLED, &d->flags);
else else
clear_bit(RFCOMM_TX_THROTTLED, &d->flags); clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
rfcomm_dlc_lock(d); rfcomm_dlc_lock(d);
if (d->modem_status) if (d->modem_status)
d->modem_status(d, msc->v24_sig); d->modem_status(d, msc->v24_sig);
...@@ -1398,7 +1399,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1398,7 +1399,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
rfcomm_send_msc(s, 0, dlci, msc->v24_sig); rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
d->mscex |= RFCOMM_MSCEX_RX; d->mscex |= RFCOMM_MSCEX_RX;
} else } else
d->mscex |= RFCOMM_MSCEX_TX; d->mscex |= RFCOMM_MSCEX_TX;
return 0; return 0;
......
...@@ -745,20 +745,143 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned ...@@ -745,20 +745,143 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old) static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old)
{ {
BT_DBG("tty %p", tty); struct termios *new = (struct termios *) tty->termios;
int old_baud_rate = tty_termios_baud_rate(old);
int new_baud_rate = tty_termios_baud_rate(new);
if ((tty->termios->c_cflag == old->c_cflag) && u8 baud, data_bits, stop_bits, parity, x_on, x_off;
(RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old->c_iflag))) u16 changes = 0;
return;
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
BT_DBG("tty %p termios %p", tty, old);
/* Handle turning off CRTSCTS */
if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
BT_DBG("Turning off CRTSCTS unsupported");
/* Parity on/off and when on, odd/even */
if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) ||
((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) {
changes |= RFCOMM_RPN_PM_PARITY;
BT_DBG("Parity change detected.");
}
/* Mark and space parity are not supported! */
if (new->c_cflag & PARENB) {
if (new->c_cflag & PARODD) {
BT_DBG("Parity is ODD");
parity = RFCOMM_RPN_PARITY_ODD;
} else {
BT_DBG("Parity is EVEN");
parity = RFCOMM_RPN_PARITY_EVEN;
}
} else {
BT_DBG("Parity is OFF");
parity = RFCOMM_RPN_PARITY_NONE;
}
/* Setting the x_on / x_off characters */
if (old->c_cc[VSTOP] != new->c_cc[VSTOP]) {
BT_DBG("XOFF custom");
x_on = new->c_cc[VSTOP];
changes |= RFCOMM_RPN_PM_XON;
} else {
BT_DBG("XOFF default");
x_on = RFCOMM_RPN_XON_CHAR;
}
if (old->c_cc[VSTART] != new->c_cc[VSTART]) {
BT_DBG("XON custom");
x_off = new->c_cc[VSTART];
changes |= RFCOMM_RPN_PM_XOFF;
} else {
BT_DBG("XON default");
x_off = RFCOMM_RPN_XOFF_CHAR;
}
/* Handle setting of stop bits */
if ((old->c_cflag & CSTOPB) != (new->c_cflag & CSTOPB))
changes |= RFCOMM_RPN_PM_STOP;
/* POSIX does not support 1.5 stop bits and RFCOMM does not
* support 2 stop bits. So a request for 2 stop bits gets
* translated to 1.5 stop bits */
if (new->c_cflag & CSTOPB) {
stop_bits = RFCOMM_RPN_STOP_15;
} else {
stop_bits = RFCOMM_RPN_STOP_1;
}
/* handle turning off CRTSCTS */ /* Handle number of data bits [5-8] */
if ((old->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
BT_DBG("turning off CRTSCTS"); changes |= RFCOMM_RPN_PM_DATA;
switch (new->c_cflag & CSIZE) {
case CS5:
data_bits = RFCOMM_RPN_DATA_5;
break;
case CS6:
data_bits = RFCOMM_RPN_DATA_6;
break;
case CS7:
data_bits = RFCOMM_RPN_DATA_7;
break;
case CS8:
data_bits = RFCOMM_RPN_DATA_8;
break;
default:
data_bits = RFCOMM_RPN_DATA_8;
break;
} }
/* Handle baudrate settings */
if (old_baud_rate != new_baud_rate)
changes |= RFCOMM_RPN_PM_BITRATE;
switch (new_baud_rate) {
case 2400:
baud = RFCOMM_RPN_BR_2400;
break;
case 4800:
baud = RFCOMM_RPN_BR_4800;
break;
case 7200:
baud = RFCOMM_RPN_BR_7200;
break;
case 9600:
baud = RFCOMM_RPN_BR_9600;
break;
case 19200:
baud = RFCOMM_RPN_BR_19200;
break;
case 38400:
baud = RFCOMM_RPN_BR_38400;
break;
case 57600:
baud = RFCOMM_RPN_BR_57600;
break;
case 115200:
baud = RFCOMM_RPN_BR_115200;
break;
case 230400:
baud = RFCOMM_RPN_BR_230400;
break;
default:
/* 9600 is standard accordinag to the RFCOMM specification */
baud = RFCOMM_RPN_BR_9600;
break;
}
if (changes)
rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,
data_bits, stop_bits, parity,
RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
return;
} }
static void rfcomm_tty_throttle(struct tty_struct *tty) static void rfcomm_tty_throttle(struct tty_struct *tty)
...@@ -766,7 +889,7 @@ static void rfcomm_tty_throttle(struct tty_struct *tty) ...@@ -766,7 +889,7 @@ static void rfcomm_tty_throttle(struct tty_struct *tty)
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
BT_DBG("tty %p dev %p", tty, dev); BT_DBG("tty %p dev %p", tty, dev);
rfcomm_dlc_throttle(dev->dlc); rfcomm_dlc_throttle(dev->dlc);
} }
...@@ -775,7 +898,7 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty) ...@@ -775,7 +898,7 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty)
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
BT_DBG("tty %p dev %p", tty, dev); BT_DBG("tty %p dev %p", tty, dev);
rfcomm_dlc_unthrottle(dev->dlc); rfcomm_dlc_unthrottle(dev->dlc);
} }
...@@ -846,35 +969,35 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp) ...@@ -846,35 +969,35 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear) static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear)
{ {
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
struct rfcomm_dlc *dlc = dev->dlc; struct rfcomm_dlc *dlc = dev->dlc;
u8 v24_sig; u8 v24_sig;
BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear); BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear);
rfcomm_dlc_get_modem_status(dlc, &v24_sig); rfcomm_dlc_get_modem_status(dlc, &v24_sig);
if (set & TIOCM_DSR || set & TIOCM_DTR) if (set & TIOCM_DSR || set & TIOCM_DTR)
v24_sig |= RFCOMM_V24_RTC; v24_sig |= RFCOMM_V24_RTC;
if (set & TIOCM_RTS || set & TIOCM_CTS) if (set & TIOCM_RTS || set & TIOCM_CTS)
v24_sig |= RFCOMM_V24_RTR; v24_sig |= RFCOMM_V24_RTR;
if (set & TIOCM_RI) if (set & TIOCM_RI)
v24_sig |= RFCOMM_V24_IC; v24_sig |= RFCOMM_V24_IC;
if (set & TIOCM_CD) if (set & TIOCM_CD)
v24_sig |= RFCOMM_V24_DV; v24_sig |= RFCOMM_V24_DV;
if (clear & TIOCM_DSR || clear & TIOCM_DTR) if (clear & TIOCM_DSR || clear & TIOCM_DTR)
v24_sig &= ~RFCOMM_V24_RTC; v24_sig &= ~RFCOMM_V24_RTC;
if (clear & TIOCM_RTS || clear & TIOCM_CTS) if (clear & TIOCM_RTS || clear & TIOCM_CTS)
v24_sig &= ~RFCOMM_V24_RTR; v24_sig &= ~RFCOMM_V24_RTR;
if (clear & TIOCM_RI) if (clear & TIOCM_RI)
v24_sig &= ~RFCOMM_V24_IC; v24_sig &= ~RFCOMM_V24_IC;
if (clear & TIOCM_CD) if (clear & TIOCM_CD)
v24_sig &= ~RFCOMM_V24_DV; v24_sig &= ~RFCOMM_V24_DV;
rfcomm_dlc_set_modem_status(dlc, v24_sig); rfcomm_dlc_set_modem_status(dlc, v24_sig);
return 0; return 0;
} }
/* ---- TTY structure ---- */ /* ---- TTY structure ---- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment