diff options
author | J. Suter <jsuter@hardwave.de> | 2005-08-09 23:28:46 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:55:03 -0400 |
commit | 3a5e903c09aed19ca4a1bb26d87b8d6461a93818 (patch) | |
tree | b9761b89aaba6537d06893091a2f43c9a8e17c3f | |
parent | 7b9eb9e2099f6f4acd6a36bcd7820d27c3cf5ee3 (diff) |
[Bluetooth]: Implement RFCOMM remote port negotiation
This patch implements the remote port negotiation (RPN) of the RFCOMM
protocol for Bluetooth.
Signed-off-by: J. Suter <jsuter@hardwave.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/bluetooth/rfcomm.h | 12 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 71 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 197 |
3 files changed, 205 insertions, 75 deletions
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 13669bad00b3..3768823d5fd3 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h | |||
@@ -80,9 +80,9 @@ | |||
80 | #define RFCOMM_RPN_STOP_15 1 | 80 | #define RFCOMM_RPN_STOP_15 1 |
81 | 81 | ||
82 | #define RFCOMM_RPN_PARITY_NONE 0x0 | 82 | #define RFCOMM_RPN_PARITY_NONE 0x0 |
83 | #define RFCOMM_RPN_PARITY_ODD 0x4 | 83 | #define RFCOMM_RPN_PARITY_ODD 0x1 |
84 | #define RFCOMM_RPN_PARITY_EVEN 0x5 | 84 | #define RFCOMM_RPN_PARITY_EVEN 0x3 |
85 | #define RFCOMM_RPN_PARITY_MARK 0x6 | 85 | #define RFCOMM_RPN_PARITY_MARK 0x5 |
86 | #define RFCOMM_RPN_PARITY_SPACE 0x7 | 86 | #define RFCOMM_RPN_PARITY_SPACE 0x7 |
87 | 87 | ||
88 | #define RFCOMM_RPN_FLOW_NONE 0x00 | 88 | #define RFCOMM_RPN_FLOW_NONE 0x00 |
@@ -223,6 +223,12 @@ struct rfcomm_dlc { | |||
223 | #define RFCOMM_CFC_DISABLED 0 | 223 | #define RFCOMM_CFC_DISABLED 0 |
224 | #define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS | 224 | #define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS |
225 | 225 | ||
226 | /* ---- RFCOMM SEND RPN ---- */ | ||
227 | int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, | ||
228 | u8 bit_rate, u8 data_bits, u8 stop_bits, | ||
229 | u8 parity, u8 flow_ctrl_settings, | ||
230 | u8 xon_char, u8 xoff_char, u16 param_mask); | ||
231 | |||
226 | /* ---- RFCOMM DLCs (channels) ---- */ | 232 | /* ---- RFCOMM DLCs (channels) ---- */ |
227 | struct rfcomm_dlc *rfcomm_dlc_alloc(int prio); | 233 | struct rfcomm_dlc *rfcomm_dlc_alloc(int prio); |
228 | void rfcomm_dlc_free(struct rfcomm_dlc *d); | 234 | void rfcomm_dlc_free(struct rfcomm_dlc *d); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 27bf5047cd33..52022cc8a2da 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -21,10 +21,6 @@ | |||
21 | SOFTWARE IS DISCLAIMED. | 21 | SOFTWARE IS DISCLAIMED. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | /* | ||
25 | RPN support - Dirk Husemann <hud@zurich.ibm.com> | ||
26 | */ | ||
27 | |||
28 | /* | 24 | /* |
29 | * Bluetooth RFCOMM core. | 25 | * Bluetooth RFCOMM core. |
30 | * | 26 | * |
@@ -115,10 +111,10 @@ static void rfcomm_session_del(struct rfcomm_session *s); | |||
115 | #define __get_mcc_len(b) ((b & 0xfe) >> 1) | 111 | #define __get_mcc_len(b) ((b & 0xfe) >> 1) |
116 | 112 | ||
117 | /* RPN macros */ | 113 | /* RPN macros */ |
118 | #define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x3) << 3)) | 114 | #define __rpn_line_settings(data, stop, parity) ((data & 0x3) | ((stop & 0x1) << 2) | ((parity & 0x7) << 3)) |
119 | #define __get_rpn_data_bits(line) ((line) & 0x3) | 115 | #define __get_rpn_data_bits(line) ((line) & 0x3) |
120 | #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1) | 116 | #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1) |
121 | #define __get_rpn_parity(line) (((line) >> 3) & 0x3) | 117 | #define __get_rpn_parity(line) (((line) >> 3) & 0x7) |
122 | 118 | ||
123 | static inline void rfcomm_schedule(uint event) | 119 | static inline void rfcomm_schedule(uint event) |
124 | { | 120 | { |
@@ -780,10 +776,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d | |||
780 | return rfcomm_send_frame(s, buf, ptr - buf); | 776 | return rfcomm_send_frame(s, buf, ptr - buf); |
781 | } | 777 | } |
782 | 778 | ||
783 | static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, | 779 | int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, |
784 | u8 bit_rate, u8 data_bits, u8 stop_bits, | 780 | u8 bit_rate, u8 data_bits, u8 stop_bits, |
785 | u8 parity, u8 flow_ctrl_settings, | 781 | u8 parity, u8 flow_ctrl_settings, |
786 | u8 xon_char, u8 xoff_char, u16 param_mask) | 782 | u8 xon_char, u8 xoff_char, u16 param_mask) |
787 | { | 783 | { |
788 | struct rfcomm_hdr *hdr; | 784 | struct rfcomm_hdr *hdr; |
789 | struct rfcomm_mcc *mcc; | 785 | struct rfcomm_mcc *mcc; |
@@ -791,9 +787,9 @@ static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, | |||
791 | u8 buf[16], *ptr = buf; | 787 | u8 buf[16], *ptr = buf; |
792 | 788 | ||
793 | BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x" | 789 | BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x" |
794 | "flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", | 790 | " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", |
795 | s, cr, dlci, bit_rate, data_bits, stop_bits, parity, | 791 | s, cr, dlci, bit_rate, data_bits, stop_bits, parity, |
796 | flow_ctrl_settings, xon_char, xoff_char, param_mask); | 792 | flow_ctrl_settings, xon_char, xoff_char, param_mask); |
797 | 793 | ||
798 | hdr = (void *) ptr; ptr += sizeof(*hdr); | 794 | hdr = (void *) ptr; ptr += sizeof(*hdr); |
799 | hdr->addr = __addr(s->initiator, 0); | 795 | 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 | u8 xon_char = 0; | 1261 | u8 xon_char = 0; |
1266 | u8 xoff_char = 0; | 1262 | u8 xoff_char = 0; |
1267 | u16 rpn_mask = RFCOMM_RPN_PM_ALL; | 1263 | u16 rpn_mask = RFCOMM_RPN_PM_ALL; |
1268 | 1264 | ||
1269 | 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", | 1265 | 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", |
1270 | dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl, | 1266 | dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl, |
1271 | rpn->xon_char, rpn->xoff_char, rpn->param_mask); | 1267 | rpn->xon_char, rpn->xoff_char, rpn->param_mask); |
1272 | 1268 | ||
1273 | if (!cr) | 1269 | if (!cr) |
1274 | return 0; | 1270 | return 0; |
1275 | 1271 | ||
1276 | if (len == 1) { | 1272 | if (len == 1) { |
1277 | /* request: return default setting */ | 1273 | /* This is a request, return default settings */ |
1278 | bit_rate = RFCOMM_RPN_BR_115200; | 1274 | bit_rate = RFCOMM_RPN_BR_115200; |
1279 | data_bits = RFCOMM_RPN_DATA_8; | 1275 | data_bits = RFCOMM_RPN_DATA_8; |
1280 | stop_bits = RFCOMM_RPN_STOP_1; | 1276 | 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 | flow_ctrl = RFCOMM_RPN_FLOW_NONE; | 1278 | flow_ctrl = RFCOMM_RPN_FLOW_NONE; |
1283 | xon_char = RFCOMM_RPN_XON_CHAR; | 1279 | xon_char = RFCOMM_RPN_XON_CHAR; |
1284 | xoff_char = RFCOMM_RPN_XOFF_CHAR; | 1280 | xoff_char = RFCOMM_RPN_XOFF_CHAR; |
1285 | |||
1286 | goto rpn_out; | 1281 | goto rpn_out; |
1287 | } | 1282 | } |
1288 | /* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity, | 1283 | |
1289 | no flow control lines, normal XON/XOFF chars */ | 1284 | /* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit, |
1285 | * no parity, no flow control lines, normal XON/XOFF chars */ | ||
1286 | |||
1290 | if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) { | 1287 | if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) { |
1291 | bit_rate = rpn->bit_rate; | 1288 | bit_rate = rpn->bit_rate; |
1292 | if (bit_rate != RFCOMM_RPN_BR_115200) { | 1289 | 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 | rpn_mask ^= RFCOMM_RPN_PM_BITRATE; | 1292 | rpn_mask ^= RFCOMM_RPN_PM_BITRATE; |
1296 | } | 1293 | } |
1297 | } | 1294 | } |
1295 | |||
1298 | if (rpn->param_mask & RFCOMM_RPN_PM_DATA) { | 1296 | if (rpn->param_mask & RFCOMM_RPN_PM_DATA) { |
1299 | data_bits = __get_rpn_data_bits(rpn->line_settings); | 1297 | data_bits = __get_rpn_data_bits(rpn->line_settings); |
1300 | if (data_bits != RFCOMM_RPN_DATA_8) { | 1298 | 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 | rpn_mask ^= RFCOMM_RPN_PM_DATA; | 1301 | rpn_mask ^= RFCOMM_RPN_PM_DATA; |
1304 | } | 1302 | } |
1305 | } | 1303 | } |
1304 | |||
1306 | if (rpn->param_mask & RFCOMM_RPN_PM_STOP) { | 1305 | if (rpn->param_mask & RFCOMM_RPN_PM_STOP) { |
1307 | stop_bits = __get_rpn_stop_bits(rpn->line_settings); | 1306 | stop_bits = __get_rpn_stop_bits(rpn->line_settings); |
1308 | if (stop_bits != RFCOMM_RPN_STOP_1) { | 1307 | 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 | rpn_mask ^= RFCOMM_RPN_PM_STOP; | 1310 | rpn_mask ^= RFCOMM_RPN_PM_STOP; |
1312 | } | 1311 | } |
1313 | } | 1312 | } |
1313 | |||
1314 | if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) { | 1314 | if (rpn->param_mask & RFCOMM_RPN_PM_PARITY) { |
1315 | parity = __get_rpn_parity(rpn->line_settings); | 1315 | parity = __get_rpn_parity(rpn->line_settings); |
1316 | if (parity != RFCOMM_RPN_PARITY_NONE) { | 1316 | 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 | rpn_mask ^= RFCOMM_RPN_PM_PARITY; | 1319 | rpn_mask ^= RFCOMM_RPN_PM_PARITY; |
1320 | } | 1320 | } |
1321 | } | 1321 | } |
1322 | |||
1322 | if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { | 1323 | if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { |
1323 | flow_ctrl = rpn->flow_ctrl; | 1324 | flow_ctrl = rpn->flow_ctrl; |
1324 | if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) { | 1325 | 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 | rpn_mask ^= RFCOMM_RPN_PM_FLOW; | 1328 | rpn_mask ^= RFCOMM_RPN_PM_FLOW; |
1328 | } | 1329 | } |
1329 | } | 1330 | } |
1331 | |||
1330 | if (rpn->param_mask & RFCOMM_RPN_PM_XON) { | 1332 | if (rpn->param_mask & RFCOMM_RPN_PM_XON) { |
1331 | xon_char = rpn->xon_char; | 1333 | xon_char = rpn->xon_char; |
1332 | if (xon_char != RFCOMM_RPN_XON_CHAR) { | 1334 | 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 | rpn_mask ^= RFCOMM_RPN_PM_XON; | 1337 | rpn_mask ^= RFCOMM_RPN_PM_XON; |
1336 | } | 1338 | } |
1337 | } | 1339 | } |
1340 | |||
1338 | if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { | 1341 | if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { |
1339 | xoff_char = rpn->xoff_char; | 1342 | xoff_char = rpn->xoff_char; |
1340 | if (xoff_char != RFCOMM_RPN_XOFF_CHAR) { | 1343 | 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 | } | 1348 | } |
1346 | 1349 | ||
1347 | rpn_out: | 1350 | rpn_out: |
1348 | rfcomm_send_rpn(s, 0, dlci, | 1351 | rfcomm_send_rpn(s, 0, dlci, bit_rate, data_bits, stop_bits, |
1349 | bit_rate, data_bits, stop_bits, parity, flow_ctrl, | 1352 | parity, flow_ctrl, xon_char, xoff_char, rpn_mask); |
1350 | xon_char, xoff_char, rpn_mask); | ||
1351 | 1353 | ||
1352 | return 0; | 1354 | return 0; |
1353 | } | 1355 | } |
@@ -1358,14 +1360,13 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb | |||
1358 | u8 dlci = __get_dlci(rls->dlci); | 1360 | u8 dlci = __get_dlci(rls->dlci); |
1359 | 1361 | ||
1360 | BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status); | 1362 | BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status); |
1361 | 1363 | ||
1362 | if (!cr) | 1364 | if (!cr) |
1363 | return 0; | 1365 | return 0; |
1364 | 1366 | ||
1365 | /* FIXME: We should probably do something with this | 1367 | /* We should probably do something with this information here. But |
1366 | information here. But for now it's sufficient just | 1368 | * for now it's sufficient just to reply -- Bluetooth 1.1 says it's |
1367 | to reply -- Bluetooth 1.1 says it's mandatory to | 1369 | * mandatory to recognise and respond to RLS */ |
1368 | recognise and respond to RLS */ | ||
1369 | 1370 | ||
1370 | rfcomm_send_rls(s, 0, dlci, rls->status); | 1371 | rfcomm_send_rls(s, 0, dlci, rls->status); |
1371 | 1372 | ||
@@ -1381,7 +1382,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb | |||
1381 | BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); | 1382 | BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); |
1382 | 1383 | ||
1383 | d = rfcomm_dlc_get(s, dlci); | 1384 | d = rfcomm_dlc_get(s, dlci); |
1384 | if (!d) | 1385 | if (!d) |
1385 | return 0; | 1386 | return 0; |
1386 | 1387 | ||
1387 | if (cr) { | 1388 | if (cr) { |
@@ -1389,7 +1390,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb | |||
1389 | set_bit(RFCOMM_TX_THROTTLED, &d->flags); | 1390 | set_bit(RFCOMM_TX_THROTTLED, &d->flags); |
1390 | else | 1391 | else |
1391 | clear_bit(RFCOMM_TX_THROTTLED, &d->flags); | 1392 | clear_bit(RFCOMM_TX_THROTTLED, &d->flags); |
1392 | 1393 | ||
1393 | rfcomm_dlc_lock(d); | 1394 | rfcomm_dlc_lock(d); |
1394 | if (d->modem_status) | 1395 | if (d->modem_status) |
1395 | d->modem_status(d, msc->v24_sig); | 1396 | 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 | rfcomm_send_msc(s, 0, dlci, msc->v24_sig); | 1399 | rfcomm_send_msc(s, 0, dlci, msc->v24_sig); |
1399 | 1400 | ||
1400 | d->mscex |= RFCOMM_MSCEX_RX; | 1401 | d->mscex |= RFCOMM_MSCEX_RX; |
1401 | } else | 1402 | } else |
1402 | d->mscex |= RFCOMM_MSCEX_TX; | 1403 | d->mscex |= RFCOMM_MSCEX_TX; |
1403 | 1404 | ||
1404 | return 0; | 1405 | return 0; |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 67d9dd6b0fac..bbc3a44a86f0 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -745,20 +745,143 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned | |||
745 | return -ENOIOCTLCMD; | 745 | return -ENOIOCTLCMD; |
746 | } | 746 | } |
747 | 747 | ||
748 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
749 | |||
750 | 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) |
751 | { | 749 | { |
752 | 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); | ||
753 | 753 | ||
754 | if ((tty->termios->c_cflag == old->c_cflag) && | 754 | u8 baud, data_bits, stop_bits, parity, x_on, x_off; |
755 | (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old->c_iflag))) | 755 | u16 changes = 0; |
756 | 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 | } | ||
757 | 817 | ||
758 | /* handle turning off CRTSCTS */ | 818 | /* Handle number of data bits [5-8] */ |
759 | if ((old->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { | 819 | if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) |
760 | BT_DBG("turning off CRTSCTS"); | 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; | ||
761 | } | 838 | } |
839 | |||
840 | /* Handle baudrate settings */ | ||
841 | if (old_baud_rate != new_baud_rate) | ||
842 | changes |= RFCOMM_RPN_PM_BITRATE; | ||
843 | |||
844 | switch (new_baud_rate) { | ||
845 | case 2400: | ||
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 | |||
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; | ||
762 | } | 885 | } |
763 | 886 | ||
764 | static void rfcomm_tty_throttle(struct tty_struct *tty) | 887 | static void rfcomm_tty_throttle(struct tty_struct *tty) |
@@ -766,7 +889,7 @@ static void rfcomm_tty_throttle(struct tty_struct *tty) | |||
766 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 889 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
767 | 890 | ||
768 | BT_DBG("tty %p dev %p", tty, dev); | 891 | BT_DBG("tty %p dev %p", tty, dev); |
769 | 892 | ||
770 | rfcomm_dlc_throttle(dev->dlc); | 893 | rfcomm_dlc_throttle(dev->dlc); |
771 | } | 894 | } |
772 | 895 | ||
@@ -775,7 +898,7 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty) | |||
775 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 898 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
776 | 899 | ||
777 | BT_DBG("tty %p dev %p", tty, dev); | 900 | BT_DBG("tty %p dev %p", tty, dev); |
778 | 901 | ||
779 | rfcomm_dlc_unthrottle(dev->dlc); | 902 | rfcomm_dlc_unthrottle(dev->dlc); |
780 | } | 903 | } |
781 | 904 | ||
@@ -846,35 +969,35 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp) | |||
846 | 969 | ||
847 | 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) |
848 | { | 971 | { |
849 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 972 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
850 | struct rfcomm_dlc *dlc = dev->dlc; | 973 | struct rfcomm_dlc *dlc = dev->dlc; |
851 | u8 v24_sig; | 974 | u8 v24_sig; |
852 | 975 | ||
853 | 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); |
854 | 977 | ||
855 | rfcomm_dlc_get_modem_status(dlc, &v24_sig); | 978 | rfcomm_dlc_get_modem_status(dlc, &v24_sig); |
856 | 979 | ||
857 | if (set & TIOCM_DSR || set & TIOCM_DTR) | 980 | if (set & TIOCM_DSR || set & TIOCM_DTR) |
858 | v24_sig |= RFCOMM_V24_RTC; | 981 | v24_sig |= RFCOMM_V24_RTC; |
859 | if (set & TIOCM_RTS || set & TIOCM_CTS) | 982 | if (set & TIOCM_RTS || set & TIOCM_CTS) |
860 | v24_sig |= RFCOMM_V24_RTR; | 983 | v24_sig |= RFCOMM_V24_RTR; |
861 | if (set & TIOCM_RI) | 984 | if (set & TIOCM_RI) |
862 | v24_sig |= RFCOMM_V24_IC; | 985 | v24_sig |= RFCOMM_V24_IC; |
863 | if (set & TIOCM_CD) | 986 | if (set & TIOCM_CD) |
864 | v24_sig |= RFCOMM_V24_DV; | 987 | v24_sig |= RFCOMM_V24_DV; |
865 | 988 | ||
866 | if (clear & TIOCM_DSR || clear & TIOCM_DTR) | 989 | if (clear & TIOCM_DSR || clear & TIOCM_DTR) |
867 | v24_sig &= ~RFCOMM_V24_RTC; | 990 | v24_sig &= ~RFCOMM_V24_RTC; |
868 | if (clear & TIOCM_RTS || clear & TIOCM_CTS) | 991 | if (clear & TIOCM_RTS || clear & TIOCM_CTS) |
869 | v24_sig &= ~RFCOMM_V24_RTR; | 992 | v24_sig &= ~RFCOMM_V24_RTR; |
870 | if (clear & TIOCM_RI) | 993 | if (clear & TIOCM_RI) |
871 | v24_sig &= ~RFCOMM_V24_IC; | 994 | v24_sig &= ~RFCOMM_V24_IC; |
872 | if (clear & TIOCM_CD) | 995 | if (clear & TIOCM_CD) |
873 | v24_sig &= ~RFCOMM_V24_DV; | 996 | v24_sig &= ~RFCOMM_V24_DV; |
874 | 997 | ||
875 | rfcomm_dlc_set_modem_status(dlc, v24_sig); | 998 | rfcomm_dlc_set_modem_status(dlc, v24_sig); |
876 | 999 | ||
877 | return 0; | 1000 | return 0; |
878 | } | 1001 | } |
879 | 1002 | ||
880 | /* ---- TTY structure ---- */ | 1003 | /* ---- TTY structure ---- */ |