This patch set includes the AMP policy socket option that was
previously discussed and accepted in to bluetooth-testing, and the
signaling framework for AMP channel creation and AMP channel moves.
Next steps:
* L2CAP lockstep configuration
* HCI layer changes for AMP HCI commands and physical/logical links
* The rest of the create channel and move channel code
* Move channel coordination with ERTM
* AMP manager
* ERTM optimizations
Mat Martineau (9):
Bluetooth: Add BT_CHANNEL_POLICY socket option
Bluetooth: Change scope of the enable_hs module parameter
Bluetooth: Add channel policy to getsockopt/setsockopt
Bluetooth: Add AMP-related data and structures for channel signals
Bluetooth: Add signal handlers for channel creation
Bluetooth: Add definitions for L2CAP fixed channels
Bluetooth: Use symbolic values for the fixed channel map
Bluetooth: Add signal handlers for channel moves
Bluetooth: Guarantee BR-EDR device will be registered as hci0
include/net/bluetooth/bluetooth.h | 27 +++++
include/net/bluetooth/l2cap.h | 60 +++++++++++-
net/bluetooth/hci_core.c | 7 +-
net/bluetooth/l2cap_core.c | 196 ++++++++++++++++++++++++++++++++++++-
net/bluetooth/l2cap_sock.c | 35 +++++++
5 files changed, 321 insertions(+), 4 deletions(-)
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Hi Mat,
On Wed, Nov 02, 2011 at 07:23:35AM +0100, Marcel Holtmann wrote:
> Hi Mat,
>
> > This patch set includes the AMP policy socket option that was
> > previously discussed and accepted in to bluetooth-testing, and the
> > signaling framework for AMP channel creation and AMP channel moves.
>
> the whole patch series looks good to me, besides one minor coding style
> damage that I will point out ;)
and ack from me, besides minor style issues.
Best regards
Andrei Emeltchenko
>
> Acked-by: Marcel Holtmann <[email protected]>
>
> Btw. once I acked a patch, feel free to carry that ack after your signed
> of by line (if you have to an updated version). Makes it easier for
> Gustavo to apply patches.
>
> Regards
>
> Marcel
On Tue, Nov 01, 2011 at 03:29:27PM -0700, Mat Martineau wrote:
> AMP channels can be moved between BR/EDR and AMP controllers using a
> sequence of signals. Every attempted channel move involves a series of
> four signals:
>
> Move Initiator Move Responder
> | |
> | Move Channel Request |
> | ----------------------------> |
> | |
> | Move Channel Response |
> | <---------------------------- |
> | |
> | Move Channel Confirm |
> | ----------------------------> |
> | |
> | Move Channel Confirm Response |
> | <---------------------------- |
>
> All four signals are sent even if the move fails.
>
> Signed-off-by: Mat Martineau <[email protected]>
> ---
> net/bluetooth/l2cap_core.c | 141 ++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 141 insertions(+), 0 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index b27b061..152ca66 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -3146,6 +3146,130 @@ static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
> return l2cap_connect_rsp(conn, cmd, data);
> }
>
> +static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
> + u16 icid, u16 result)
> +{
> + struct l2cap_move_chan_rsp rsp;
> +
> + BT_DBG("icid %d, result %d", icid, result);
> +
> + rsp.icid = cpu_to_le16(icid);
> + rsp.result = cpu_to_le16(result);
> +
> + l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
> +}
> +
> +static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
> + struct l2cap_chan *chan, u16 icid, u16 result)
> +{
> + struct l2cap_move_chan_cfm cfm;
> + u8 ident;
> +
> + BT_DBG("icid %d, result %d", icid, result);
> +
> + ident = l2cap_get_ident(conn);
> + if (chan)
> + chan->ident = ident;
> +
> + cfm.icid = cpu_to_le16(icid);
> + cfm.result = cpu_to_le16(result);
> +
> + l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
> +}
> +
> +static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
> + u16 icid)
Shall the last argument be aligned right?
> +{
> + struct l2cap_move_chan_cfm_rsp rsp;
> +
> + BT_DBG("icid %d", icid);
> +
> + rsp.icid = cpu_to_le16(icid);
> + l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
> +}
> +
> +static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
> + struct l2cap_cmd_hdr *cmd, u16 cmd_len,
> + void *data)
Maybe matter of taste but could those 3 lines be reduced to 2 here and
below?
Best regards
Andrei Emeltchenko
> +{
> + struct l2cap_move_chan_req *req = data;
> + u16 icid = 0;
> + u16 result = L2CAP_MR_NOT_ALLOWED;
> +
> + if (cmd_len != sizeof(*req))
> + return -EPROTO;
> +
> + icid = le16_to_cpu(req->icid);
> +
> + BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
> +
> + if (!enable_hs)
> + return -EINVAL;
> +
> + /* Placeholder: Always refuse */
> + l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
> +
> + return 0;
> +}
> +
> +static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
> + struct l2cap_cmd_hdr *cmd, u16 cmd_len,
> + void *data)
> +{
> + struct l2cap_move_chan_rsp *rsp = data;
> + u16 icid, result;
> +
> + if (cmd_len != sizeof(*rsp))
> + return -EPROTO;
> +
> + icid = le16_to_cpu(rsp->icid);
> + result = le16_to_cpu(rsp->result);
> +
> + BT_DBG("icid %d, result %d", icid, result);
> +
> + /* Placeholder: Always unconfirmed */
> + l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
> +
> + return 0;
> +}
> +
> +static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
> + struct l2cap_cmd_hdr *cmd, u16 cmd_len,
> + void *data)
> +{
> + struct l2cap_move_chan_cfm *cfm = data;
> + u16 icid, result;
> +
> + if (cmd_len != sizeof(*cfm))
> + return -EPROTO;
> +
> + icid = le16_to_cpu(cfm->icid);
> + result = le16_to_cpu(cfm->result);
> +
> + BT_DBG("icid %d, result %d", icid, result);
> +
> + l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
> +
> + return 0;
> +}
> +
> +static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
> + struct l2cap_cmd_hdr *cmd, u16 cmd_len,
> + void *data)
> +{
> + struct l2cap_move_chan_cfm_rsp *rsp = data;
> + u16 icid;
> +
> + if (cmd_len != sizeof(*rsp))
> + return -EPROTO;
> +
> + icid = le16_to_cpu(rsp->icid);
> +
> + BT_DBG("icid %d", icid);
> +
> + return 0;
> +}
> +
> static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
> u16 to_multiplier)
> {
> @@ -3266,6 +3390,23 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
> err = l2cap_create_channel_rsp(conn, cmd, data);
> break;
>
> + case L2CAP_MOVE_CHAN_REQ:
> + err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
> + break;
> +
> + case L2CAP_MOVE_CHAN_RSP:
> + err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
> + break;
> +
> + case L2CAP_MOVE_CHAN_CFM:
> + err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
> + break;
> +
> + case L2CAP_MOVE_CHAN_CFM_RSP:
> + err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
> + break;
> +
> +
> default:
> BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
> err = -EINVAL;
> --
> 1.7.7.1
>
> --
> Mat Martineau
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Mat,
> AMP channels can be moved between BR/EDR and AMP controllers using a
> sequence of signals. Every attempted channel move involves a series of
> four signals:
<snip>
> {
> @@ -3266,6 +3390,23 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
> err = l2cap_create_channel_rsp(conn, cmd, data);
> break;
>
> + case L2CAP_MOVE_CHAN_REQ:
> + err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
> + break;
> +
> + case L2CAP_MOVE_CHAN_RSP:
> + err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
> + break;
> +
> + case L2CAP_MOVE_CHAN_CFM:
> + err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
> + break;
> +
> + case L2CAP_MOVE_CHAN_CFM_RSP:
> + err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
> + break;
> +
> +
> default:
> BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
> err = -EINVAL;
and this is the coding style damage. You sneaked in two empty lines
here.
Regards
Marcel
Hi Mat,
> This patch set includes the AMP policy socket option that was
> previously discussed and accepted in to bluetooth-testing, and the
> signaling framework for AMP channel creation and AMP channel moves.
the whole patch series looks good to me, besides one minor coding style
damage that I will point out ;)
Acked-by: Marcel Holtmann <[email protected]>
Btw. once I acked a patch, feel free to carry that ack after your signed
of by line (if you have to an updated version). Makes it easier for
Gustavo to apply patches.
Regards
Marcel
AMP channel creation and channel moves are coordinated using the L2CAP
signaling channel. These definitions cover the "create channel",
"move channel", and "move channel confirm" signals.
Signed-off-by: Mat Martineau <[email protected]>
---
include/net/bluetooth/l2cap.h | 54 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0b021c0..f822ab9 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -97,6 +97,12 @@ struct l2cap_conninfo {
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b
+#define L2CAP_CREATE_CHAN_REQ 0x0c
+#define L2CAP_CREATE_CHAN_RSP 0x0d
+#define L2CAP_MOVE_CHAN_REQ 0x0e
+#define L2CAP_MOVE_CHAN_RSP 0x0f
+#define L2CAP_MOVE_CHAN_CFM 0x10
+#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
@@ -220,14 +226,15 @@ struct l2cap_conn_rsp {
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
-/* connect result */
+/* connect/create channel results */
#define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001
#define L2CAP_CR_BAD_PSM 0x0002
#define L2CAP_CR_SEC_BLOCK 0x0003
#define L2CAP_CR_NO_MEM 0x0004
+#define L2CAP_CR_BAD_AMP 0x0005
-/* connect status */
+/* connect/create channel status */
#define L2CAP_CS_NO_INFO 0x0000
#define L2CAP_CS_AUTHEN_PEND 0x0001
#define L2CAP_CS_AUTHOR_PEND 0x0002
@@ -322,6 +329,49 @@ struct l2cap_info_rsp {
__u8 data[0];
} __packed;
+struct l2cap_create_chan_req {
+ __le16 psm;
+ __le16 scid;
+ __u8 amp_id;
+} __packed;
+
+struct l2cap_create_chan_rsp {
+ __le16 dcid;
+ __le16 scid;
+ __le16 result;
+ __le16 status;
+} __packed;
+
+struct l2cap_move_chan_req {
+ __le16 icid;
+ __u8 dest_amp_id;
+} __packed;
+
+struct l2cap_move_chan_rsp {
+ __le16 icid;
+ __le16 result;
+} __packed;
+
+#define L2CAP_MR_SUCCESS 0x0000
+#define L2CAP_MR_PEND 0x0001
+#define L2CAP_MR_BAD_ID 0x0002
+#define L2CAP_MR_SAME_ID 0x0003
+#define L2CAP_MR_NOT_SUPP 0x0004
+#define L2CAP_MR_COLLISION 0x0005
+#define L2CAP_MR_NOT_ALLOWED 0x0006
+
+struct l2cap_move_chan_cfm {
+ __le16 icid;
+ __le16 result;
+} __packed;
+
+#define L2CAP_MC_CONFIRMED 0x0000
+#define L2CAP_MC_UNCONFIRMED 0x0001
+
+struct l2cap_move_chan_cfm_rsp {
+ __le16 icid;
+} __packed;
+
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
#define L2CAP_IT_FEAT_MASK 0x0002
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
The A2MP fixed channel bit is only set when high-speed mode is enabled.
Signed-off-by: Mat Martineau <[email protected]>
---
net/bluetooth/l2cap_core.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2a49cf3..b27b061 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -60,7 +60,7 @@ int disable_ertm;
int enable_hs;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
-static u8 l2cap_fixed_chan[8] = { 0x02, };
+static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
static LIST_HEAD(chan_list);
static DEFINE_RWLOCK(chan_list_lock);
@@ -3032,6 +3032,12 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
} else if (type == L2CAP_IT_FIXED_CHAN) {
u8 buf[12];
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
+
+ if (enable_hs)
+ l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
+ else
+ l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
+
rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
AMP channels can be moved between BR/EDR and AMP controllers using a
sequence of signals. Every attempted channel move involves a series of
four signals:
Move Initiator Move Responder
| |
| Move Channel Request |
| ----------------------------> |
| |
| Move Channel Response |
| <---------------------------- |
| |
| Move Channel Confirm |
| ----------------------------> |
| |
| Move Channel Confirm Response |
| <---------------------------- |
All four signals are sent even if the move fails.
Signed-off-by: Mat Martineau <[email protected]>
---
net/bluetooth/l2cap_core.c | 141 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 141 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b27b061..152ca66 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3146,6 +3146,130 @@ static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
return l2cap_connect_rsp(conn, cmd, data);
}
+static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
+ u16 icid, u16 result)
+{
+ struct l2cap_move_chan_rsp rsp;
+
+ BT_DBG("icid %d, result %d", icid, result);
+
+ rsp.icid = cpu_to_le16(icid);
+ rsp.result = cpu_to_le16(result);
+
+ l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
+}
+
+static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
+ struct l2cap_chan *chan, u16 icid, u16 result)
+{
+ struct l2cap_move_chan_cfm cfm;
+ u8 ident;
+
+ BT_DBG("icid %d, result %d", icid, result);
+
+ ident = l2cap_get_ident(conn);
+ if (chan)
+ chan->ident = ident;
+
+ cfm.icid = cpu_to_le16(icid);
+ cfm.result = cpu_to_le16(result);
+
+ l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
+}
+
+static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
+ u16 icid)
+{
+ struct l2cap_move_chan_cfm_rsp rsp;
+
+ BT_DBG("icid %d", icid);
+
+ rsp.icid = cpu_to_le16(icid);
+ l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
+}
+
+static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ void *data)
+{
+ struct l2cap_move_chan_req *req = data;
+ u16 icid = 0;
+ u16 result = L2CAP_MR_NOT_ALLOWED;
+
+ if (cmd_len != sizeof(*req))
+ return -EPROTO;
+
+ icid = le16_to_cpu(req->icid);
+
+ BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
+
+ if (!enable_hs)
+ return -EINVAL;
+
+ /* Placeholder: Always refuse */
+ l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
+
+ return 0;
+}
+
+static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ void *data)
+{
+ struct l2cap_move_chan_rsp *rsp = data;
+ u16 icid, result;
+
+ if (cmd_len != sizeof(*rsp))
+ return -EPROTO;
+
+ icid = le16_to_cpu(rsp->icid);
+ result = le16_to_cpu(rsp->result);
+
+ BT_DBG("icid %d, result %d", icid, result);
+
+ /* Placeholder: Always unconfirmed */
+ l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
+
+ return 0;
+}
+
+static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ void *data)
+{
+ struct l2cap_move_chan_cfm *cfm = data;
+ u16 icid, result;
+
+ if (cmd_len != sizeof(*cfm))
+ return -EPROTO;
+
+ icid = le16_to_cpu(cfm->icid);
+ result = le16_to_cpu(cfm->result);
+
+ BT_DBG("icid %d, result %d", icid, result);
+
+ l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
+
+ return 0;
+}
+
+static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ void *data)
+{
+ struct l2cap_move_chan_cfm_rsp *rsp = data;
+ u16 icid;
+
+ if (cmd_len != sizeof(*rsp))
+ return -EPROTO;
+
+ icid = le16_to_cpu(rsp->icid);
+
+ BT_DBG("icid %d", icid);
+
+ return 0;
+}
+
static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
u16 to_multiplier)
{
@@ -3266,6 +3390,23 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
err = l2cap_create_channel_rsp(conn, cmd, data);
break;
+ case L2CAP_MOVE_CHAN_REQ:
+ err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
+ break;
+
+ case L2CAP_MOVE_CHAN_RSP:
+ err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
+ break;
+
+ case L2CAP_MOVE_CHAN_CFM:
+ err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
+ break;
+
+ case L2CAP_MOVE_CHAN_CFM_RSP:
+ err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
+ break;
+
+
default:
BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
err = -EINVAL;
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
It's convenient to use the HCI device index the AMP controller id, but
the spec requires that an AMP controller never has id 0.
Signed-off-by: Mat Martineau <[email protected]>
---
net/bluetooth/hci_core.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f2ec434..cee7f87 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1410,7 +1410,7 @@ int hci_add_adv_entry(struct hci_dev *hdev,
int hci_register_dev(struct hci_dev *hdev)
{
struct list_head *head = &hci_dev_list, *p;
- int i, id = 0, error;
+ int i, id, error;
BT_DBG("%p name %s bus %d owner %p", hdev, hdev->name,
hdev->bus, hdev->owner);
@@ -1418,6 +1418,11 @@ int hci_register_dev(struct hci_dev *hdev)
if (!hdev->open || !hdev->close || !hdev->destruct)
return -EINVAL;
+ /* Do not allow HCI_AMP devices to register at index 0,
+ * so the index can be used as the AMP controller ID.
+ */
+ id = (hdev->dev_type == HCI_BREDR) ? 0 : 1;
+
write_lock_bh(&hci_dev_list_lock);
/* Find first available device id */
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Symbolic fixed channel IDs will be used instead of magic numbers.
Signed-off-by: Mat Martineau <[email protected]>
---
include/net/bluetooth/l2cap.h | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index f822ab9..7f5c854 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -122,6 +122,10 @@ struct l2cap_conninfo {
#define L2CAP_FCS_NONE 0x00
#define L2CAP_FCS_CRC16 0x01
+/* L2CAP fixed channels */
+#define L2CAP_FC_L2CAP 0x02
+#define L2CAP_FC_A2MP 0x08
+
/* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR 0xC000
#define L2CAP_CTRL_REQSEQ 0x3F00
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Handle both "create channel request" and "create channel response".
Signed-off-by: Mat Martineau <[email protected]>
---
net/bluetooth/l2cap_core.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index af3e8c5..2a49cf3 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3101,6 +3101,45 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
return 0;
}
+static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ void *data)
+{
+ struct l2cap_create_chan_req *req = data;
+ struct l2cap_create_chan_rsp rsp;
+ u16 psm, scid;
+
+ if (cmd_len != sizeof(*req))
+ return -EPROTO;
+
+ if (!enable_hs)
+ return -EINVAL;
+
+ psm = le16_to_cpu(req->psm);
+ scid = le16_to_cpu(req->scid);
+
+ BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
+
+ /* Placeholder: Always reject */
+ rsp.dcid = 0;
+ rsp.scid = cpu_to_le16(scid);
+ rsp.result = L2CAP_CR_NO_MEM;
+ rsp.status = L2CAP_CS_NO_INFO;
+
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
+ sizeof(rsp), &rsp);
+
+ return 0;
+}
+
+static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd, void *data)
+{
+ BT_DBG("conn %p", conn);
+
+ return l2cap_connect_rsp(conn, cmd, data);
+}
+
static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
u16 to_multiplier)
{
@@ -3213,6 +3252,14 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
err = l2cap_information_rsp(conn, cmd, data);
break;
+ case L2CAP_CREATE_CHAN_REQ:
+ err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
+ break;
+
+ case L2CAP_CREATE_CHAN_RSP:
+ err = l2cap_create_channel_rsp(conn, cmd, data);
+ break;
+
default:
BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
err = -EINVAL;
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Each channel has a policy to require BR/EDR (the default),
prefer BR/EDR, or prefer AMP.
Check for valid policy value and L2CAP mode.
Signed-off-by: Mat Martineau <[email protected]>
---
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/l2cap_sock.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 77df95e..0b021c0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -370,6 +370,7 @@ struct l2cap_chan {
__u16 flush_to;
__u8 mode;
__u8 chan_type;
+ __u8 chan_policy;
__le16 sport;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 646aefc..2520d2a 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -467,6 +467,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break;
+ case BT_CHANNEL_POLICY:
+ if (!enable_hs) {
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ if (put_user(chan->chan_policy, (u32 __user *) optval))
+ err = -EFAULT;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -690,6 +700,31 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
clear_bit(FLAG_FORCE_ACTIVE, &chan->flags);
break;
+ case BT_CHANNEL_POLICY:
+ if (!enable_hs) {
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (chan->mode != L2CAP_MODE_ERTM &&
+ chan->mode != L2CAP_MODE_STREAMING) {
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ chan->chan_policy = (u8) opt;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Allow control of AMP functionality on L2CAP sockets. By default,
connections will be restricted to BR/EDR. Manipulating the
BT_CHANNEL_POLICY option allows for channels to be moved to or created
on AMP controllers.
Signed-off-by: Mat Martineau <[email protected]>
---
include/net/bluetooth/bluetooth.h | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index fb1acb3..38cd3da 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -77,6 +77,33 @@ struct bt_power {
#define BT_POWER_FORCE_ACTIVE_OFF 0
#define BT_POWER_FORCE_ACTIVE_ON 1
+#define BT_CHANNEL_POLICY 10
+
+/* BR/EDR only (default policy)
+ * AMP controllers cannot be used.
+ * Channel move requests from the remote device are denied.
+ * If the L2CAP channel is currently using AMP, move the channel to BR/EDR.
+ */
+#define BT_CHANNEL_POLICY_BREDR_ONLY 0
+
+/* BR/EDR Preferred
+ * Allow use of AMP controllers.
+ * If the L2CAP channel is currently on AMP, move it to BR/EDR.
+ * Channel move requests from the remote device are allowed.
+ */
+#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1
+
+/* AMP Preferred
+ * Allow use of AMP controllers
+ * If the L2CAP channel is currently on BR/EDR and AMP controller
+ * resources are available, initiate a channel move to AMP.
+ * Channel move requests from the remote device are allowed.
+ * If the L2CAP socket has not been connected yet, try to create
+ * and configure the channel directly on an AMP controller rather
+ * than BR/EDR.
+ */
+#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
+
__attribute__((format (printf, 2, 3)))
int bt_printk(const char *level, const char *fmt, ...);
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
This variable is currently only accessible within l2cap_core.c, but
it is also needed in l2cap_sock.c
Signed-off-by: Mat Martineau <[email protected]>
---
include/net/bluetooth/l2cap.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 5a0a9c8..77df95e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -736,6 +736,7 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan)
}
extern int disable_ertm;
+extern int enable_hs;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
--
1.7.7.1
--
Mat Martineau
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum