diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2009-05-03 01:31:10 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-08-22 17:50:07 -0400 |
commit | c6b03cf986eab00e20d0dbc852b233bb83472138 (patch) | |
tree | 94fe92aafca068e3eb1cd6f4c53a3c86801fe7e0 /net/bluetooth/l2cap.c | |
parent | 44dd46de325c4d47abfd1361e5d84a548edb8e42 (diff) |
Bluetooth: Allow setting of L2CAP ERTM via socket option
To enable Enhanced Retransmission mode it needs to be set via a socket
option. A different mode can be set on a socket, but on listen() and
connect() the mode is checked and ERTM is only allowed if it is enabled
via the module parameter.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 810a3c1a4188..8a59e57d9df1 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -717,12 +717,16 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
717 | 717 | ||
718 | pi->imtu = l2cap_pi(parent)->imtu; | 718 | pi->imtu = l2cap_pi(parent)->imtu; |
719 | pi->omtu = l2cap_pi(parent)->omtu; | 719 | pi->omtu = l2cap_pi(parent)->omtu; |
720 | pi->mode = l2cap_pi(parent)->mode; | ||
721 | pi->fcs = l2cap_pi(parent)->fcs; | ||
720 | pi->sec_level = l2cap_pi(parent)->sec_level; | 722 | pi->sec_level = l2cap_pi(parent)->sec_level; |
721 | pi->role_switch = l2cap_pi(parent)->role_switch; | 723 | pi->role_switch = l2cap_pi(parent)->role_switch; |
722 | pi->force_reliable = l2cap_pi(parent)->force_reliable; | 724 | pi->force_reliable = l2cap_pi(parent)->force_reliable; |
723 | } else { | 725 | } else { |
724 | pi->imtu = L2CAP_DEFAULT_MTU; | 726 | pi->imtu = L2CAP_DEFAULT_MTU; |
725 | pi->omtu = 0; | 727 | pi->omtu = 0; |
728 | pi->mode = L2CAP_MODE_BASIC; | ||
729 | pi->fcs = L2CAP_FCS_CRC16; | ||
726 | pi->sec_level = BT_SECURITY_LOW; | 730 | pi->sec_level = BT_SECURITY_LOW; |
727 | pi->role_switch = 0; | 731 | pi->role_switch = 0; |
728 | pi->force_reliable = 0; | 732 | pi->force_reliable = 0; |
@@ -958,6 +962,18 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
958 | goto done; | 962 | goto done; |
959 | } | 963 | } |
960 | 964 | ||
965 | switch (l2cap_pi(sk)->mode) { | ||
966 | case L2CAP_MODE_BASIC: | ||
967 | break; | ||
968 | case L2CAP_MODE_ERTM: | ||
969 | if (enable_ertm) | ||
970 | break; | ||
971 | /* fall through */ | ||
972 | default: | ||
973 | err = -ENOTSUPP; | ||
974 | goto done; | ||
975 | } | ||
976 | |||
961 | switch (sk->sk_state) { | 977 | switch (sk->sk_state) { |
962 | case BT_CONNECT: | 978 | case BT_CONNECT: |
963 | case BT_CONNECT2: | 979 | case BT_CONNECT2: |
@@ -1009,6 +1025,18 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
1009 | goto done; | 1025 | goto done; |
1010 | } | 1026 | } |
1011 | 1027 | ||
1028 | switch (l2cap_pi(sk)->mode) { | ||
1029 | case L2CAP_MODE_BASIC: | ||
1030 | break; | ||
1031 | case L2CAP_MODE_ERTM: | ||
1032 | if (enable_ertm) | ||
1033 | break; | ||
1034 | /* fall through */ | ||
1035 | default: | ||
1036 | err = -ENOTSUPP; | ||
1037 | goto done; | ||
1038 | } | ||
1039 | |||
1012 | if (!l2cap_pi(sk)->psm) { | 1040 | if (!l2cap_pi(sk)->psm) { |
1013 | bdaddr_t *src = &bt_sk(sk)->src; | 1041 | bdaddr_t *src = &bt_sk(sk)->src; |
1014 | u16 psm; | 1042 | u16 psm; |
@@ -1259,7 +1287,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
1259 | opts.imtu = l2cap_pi(sk)->imtu; | 1287 | opts.imtu = l2cap_pi(sk)->imtu; |
1260 | opts.omtu = l2cap_pi(sk)->omtu; | 1288 | opts.omtu = l2cap_pi(sk)->omtu; |
1261 | opts.flush_to = l2cap_pi(sk)->flush_to; | 1289 | opts.flush_to = l2cap_pi(sk)->flush_to; |
1262 | opts.mode = L2CAP_MODE_BASIC; | 1290 | opts.mode = l2cap_pi(sk)->mode; |
1263 | 1291 | ||
1264 | len = min_t(unsigned int, sizeof(opts), optlen); | 1292 | len = min_t(unsigned int, sizeof(opts), optlen); |
1265 | if (copy_from_user((char *) &opts, optval, len)) { | 1293 | if (copy_from_user((char *) &opts, optval, len)) { |
@@ -1267,8 +1295,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
1267 | break; | 1295 | break; |
1268 | } | 1296 | } |
1269 | 1297 | ||
1270 | l2cap_pi(sk)->imtu = opts.imtu; | 1298 | l2cap_pi(sk)->imtu = opts.imtu; |
1271 | l2cap_pi(sk)->omtu = opts.omtu; | 1299 | l2cap_pi(sk)->omtu = opts.omtu; |
1300 | l2cap_pi(sk)->mode = opts.mode; | ||
1272 | break; | 1301 | break; |
1273 | 1302 | ||
1274 | case L2CAP_LM: | 1303 | case L2CAP_LM: |
@@ -1381,7 +1410,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us | |||
1381 | opts.imtu = l2cap_pi(sk)->imtu; | 1410 | opts.imtu = l2cap_pi(sk)->imtu; |
1382 | opts.omtu = l2cap_pi(sk)->omtu; | 1411 | opts.omtu = l2cap_pi(sk)->omtu; |
1383 | opts.flush_to = l2cap_pi(sk)->flush_to; | 1412 | opts.flush_to = l2cap_pi(sk)->flush_to; |
1384 | opts.mode = L2CAP_MODE_BASIC; | 1413 | opts.mode = l2cap_pi(sk)->mode; |
1385 | 1414 | ||
1386 | len = min_t(unsigned int, len, sizeof(opts)); | 1415 | len = min_t(unsigned int, len, sizeof(opts)); |
1387 | if (copy_to_user(optval, (char *) &opts, len)) | 1416 | if (copy_to_user(optval, (char *) &opts, len)) |