|
@@ -46,7 +46,6 @@
|
|
|
bool disable_ertm;
|
|
|
|
|
|
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
|
|
|
-static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, };
|
|
|
|
|
|
static LIST_HEAD(chan_list);
|
|
|
static DEFINE_RWLOCK(chan_list_lock);
|
|
@@ -1120,10 +1119,10 @@ static bool __amp_capable(struct l2cap_chan *chan)
|
|
|
struct hci_dev *hdev;
|
|
|
bool amp_available = false;
|
|
|
|
|
|
- if (!conn->hs_enabled)
|
|
|
+ if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
|
|
|
return false;
|
|
|
|
|
|
- if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
|
|
|
+ if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
|
|
|
return false;
|
|
|
|
|
|
read_lock(&hci_dev_list_lock);
|
|
@@ -3096,12 +3095,14 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
|
|
|
|
|
|
static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
|
|
|
{
|
|
|
- return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
|
|
|
+ return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
|
|
|
+ (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
|
|
|
}
|
|
|
|
|
|
static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
|
|
|
{
|
|
|
- return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
|
|
|
+ return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
|
|
|
+ (conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
|
|
|
}
|
|
|
|
|
|
static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
|
|
@@ -3330,7 +3331,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
|
|
|
break;
|
|
|
|
|
|
case L2CAP_CONF_EWS:
|
|
|
- if (!chan->conn->hs_enabled)
|
|
|
+ if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
|
|
|
return -ECONNREFUSED;
|
|
|
|
|
|
set_bit(FLAG_EXT_CTRL, &chan->flags);
|
|
@@ -4334,7 +4335,7 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
|
|
|
if (!disable_ertm)
|
|
|
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
|
|
|
| L2CAP_FEAT_FCS;
|
|
|
- if (conn->hs_enabled)
|
|
|
+ if (conn->local_fixed_chan & L2CAP_FC_A2MP)
|
|
|
feat_mask |= L2CAP_FEAT_EXT_FLOW
|
|
|
| L2CAP_FEAT_EXT_WINDOW;
|
|
|
|
|
@@ -4345,14 +4346,10 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
|
|
|
u8 buf[12];
|
|
|
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
|
|
|
|
|
|
- if (conn->hs_enabled)
|
|
|
- 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));
|
|
|
+ rsp->data[0] = conn->local_fixed_chan;
|
|
|
+ memset(rsp->data + 1, 0, 7);
|
|
|
l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
|
|
|
buf);
|
|
|
} else {
|
|
@@ -4418,7 +4415,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
|
|
|
break;
|
|
|
|
|
|
case L2CAP_IT_FIXED_CHAN:
|
|
|
- conn->fixed_chan_mask = rsp->data[0];
|
|
|
+ conn->remote_fixed_chan = rsp->data[0];
|
|
|
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
|
|
|
conn->info_ident = 0;
|
|
|
|
|
@@ -4442,7 +4439,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
|
|
|
if (cmd_len != sizeof(*req))
|
|
|
return -EPROTO;
|
|
|
|
|
|
- if (!conn->hs_enabled)
|
|
|
+ if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
|
|
|
return -EINVAL;
|
|
|
|
|
|
psm = le16_to_cpu(req->psm);
|
|
@@ -4872,7 +4869,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
|
|
|
|
|
|
BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
|
|
|
|
|
|
- if (!conn->hs_enabled)
|
|
|
+ if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
|
|
|
return -EINVAL;
|
|
|
|
|
|
chan = l2cap_get_chan_by_dcid(conn, icid);
|
|
@@ -6964,9 +6961,11 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
|
|
|
|
|
|
conn->feat_mask = 0;
|
|
|
|
|
|
- if (hcon->type == ACL_LINK)
|
|
|
- conn->hs_enabled = test_bit(HCI_HS_ENABLED,
|
|
|
- &hcon->hdev->dev_flags);
|
|
|
+ conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
|
|
|
+
|
|
|
+ if (hcon->type == ACL_LINK &&
|
|
|
+ test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags))
|
|
|
+ conn->local_fixed_chan |= L2CAP_FC_A2MP;
|
|
|
|
|
|
mutex_init(&conn->ident_lock);
|
|
|
mutex_init(&conn->chan_lock);
|