Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6b03cf9 authored by Marcel Holtmann's avatar Marcel Holtmann
Browse files

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: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 44dd46de
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -190,7 +190,7 @@ struct l2cap_conf_rfc {
#define L2CAP_MODE_RETRANS	0x01
#define L2CAP_MODE_FLOWCTL	0x02
#define L2CAP_MODE_ERTM		0x03
#define L2CAP_MODE_STREAM	0x04
#define L2CAP_MODE_STREAMING	0x04

struct l2cap_disconn_req {
	__le16     dcid;
@@ -271,6 +271,8 @@ struct l2cap_pinfo {
	__u16		imtu;
	__u16		omtu;
	__u16		flush_to;
	__u8		mode;
	__u8		fcs;
	__u8		sec_level;
	__u8		role_switch;
	__u8		force_reliable;
+33 −4
Original line number Diff line number Diff line
@@ -717,12 +717,16 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)

		pi->imtu = l2cap_pi(parent)->imtu;
		pi->omtu = l2cap_pi(parent)->omtu;
		pi->mode = l2cap_pi(parent)->mode;
		pi->fcs  = l2cap_pi(parent)->fcs;
		pi->sec_level = l2cap_pi(parent)->sec_level;
		pi->role_switch = l2cap_pi(parent)->role_switch;
		pi->force_reliable = l2cap_pi(parent)->force_reliable;
	} else {
		pi->imtu = L2CAP_DEFAULT_MTU;
		pi->omtu = 0;
		pi->mode = L2CAP_MODE_BASIC;
		pi->fcs  = L2CAP_FCS_CRC16;
		pi->sec_level = BT_SECURITY_LOW;
		pi->role_switch = 0;
		pi->force_reliable = 0;
@@ -958,6 +962,18 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
		goto done;
	}

	switch (l2cap_pi(sk)->mode) {
	case L2CAP_MODE_BASIC:
		break;
	case L2CAP_MODE_ERTM:
		if (enable_ertm)
			break;
		/* fall through */
	default:
		err = -ENOTSUPP;
		goto done;
	}

	switch (sk->sk_state) {
	case BT_CONNECT:
	case BT_CONNECT2:
@@ -1009,6 +1025,18 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
		goto done;
	}

	switch (l2cap_pi(sk)->mode) {
	case L2CAP_MODE_BASIC:
		break;
	case L2CAP_MODE_ERTM:
		if (enable_ertm)
			break;
		/* fall through */
	default:
		err = -ENOTSUPP;
		goto done;
	}

	if (!l2cap_pi(sk)->psm) {
		bdaddr_t *src = &bt_sk(sk)->src;
		u16 psm;
@@ -1259,7 +1287,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
		opts.imtu     = l2cap_pi(sk)->imtu;
		opts.omtu     = l2cap_pi(sk)->omtu;
		opts.flush_to = l2cap_pi(sk)->flush_to;
		opts.mode     = L2CAP_MODE_BASIC;
		opts.mode     = l2cap_pi(sk)->mode;

		len = min_t(unsigned int, sizeof(opts), optlen);
		if (copy_from_user((char *) &opts, optval, len)) {
@@ -1269,6 +1297,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us

		l2cap_pi(sk)->imtu = opts.imtu;
		l2cap_pi(sk)->omtu = opts.omtu;
		l2cap_pi(sk)->mode = opts.mode;
		break;

	case L2CAP_LM:
@@ -1381,7 +1410,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
		opts.imtu     = l2cap_pi(sk)->imtu;
		opts.omtu     = l2cap_pi(sk)->omtu;
		opts.flush_to = l2cap_pi(sk)->flush_to;
		opts.mode     = L2CAP_MODE_BASIC;
		opts.mode     = l2cap_pi(sk)->mode;

		len = min_t(unsigned int, len, sizeof(opts));
		if (copy_to_user(optval, (char *) &opts, len))