Commit e1027a7c69700301d14db03d2e049ee60c4f92df

Authored by Marcel Holtmann
1 parent 435fef20ac

Bluetooth: Request L2CAP fixed channel list if available

If the extended features mask indicates support for fixed channels,
request the list of available fixed channels. This also enables the
fixed channel features bit so remote implementations can request
information about it. Currently only the signal channel will be
listed.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

Showing 2 changed files with 32 additions and 9 deletions Side-by-side Diff

include/net/bluetooth/l2cap.h
... ... @@ -185,6 +185,7 @@
185 185 /* info type */
186 186 #define L2CAP_IT_CL_MTU 0x0001
187 187 #define L2CAP_IT_FEAT_MASK 0x0002
  188 +#define L2CAP_IT_FIXED_CHAN 0x0003
188 189  
189 190 /* info result */
190 191 #define L2CAP_IR_SUCCESS 0x0000
net/bluetooth/l2cap.c
... ... @@ -50,9 +50,10 @@
50 50 #include <net/bluetooth/hci_core.h>
51 51 #include <net/bluetooth/l2cap.h>
52 52  
53   -#define VERSION "2.12"
  53 +#define VERSION "2.13"
54 54  
55   -static u32 l2cap_feat_mask = 0x0000;
  55 +static u32 l2cap_feat_mask = 0x0080;
  56 +static u8 l2cap_fixed_chan[8] = { 0x02, };
56 57  
57 58 static const struct proto_ops l2cap_sock_ops;
58 59  
59 60  
... ... @@ -456,10 +457,9 @@
456 457 {
457 458 struct l2cap_conn *conn = (void *) arg;
458 459  
  460 + conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
459 461 conn->info_ident = 0;
460 462  
461   - conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
462   -
463 463 l2cap_conn_start(conn);
464 464 }
465 465  
466 466  
... ... @@ -1793,10 +1793,10 @@
1793 1793  
1794 1794 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1795 1795 cmd->ident == conn->info_ident) {
1796   - conn->info_ident = 0;
1797 1796 del_timer(&conn->info_timer);
1798 1797  
1799 1798 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
  1799 + conn->info_ident = 0;
1800 1800  
1801 1801 l2cap_conn_start(conn);
1802 1802 }
... ... @@ -2165,6 +2165,14 @@
2165 2165 put_unaligned(cpu_to_le32(l2cap_feat_mask), (__le32 *) rsp->data);
2166 2166 l2cap_send_cmd(conn, cmd->ident,
2167 2167 L2CAP_INFO_RSP, sizeof(buf), buf);
  2168 + } else if (type == L2CAP_IT_FIXED_CHAN) {
  2169 + u8 buf[12];
  2170 + struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
  2171 + rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
  2172 + rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
  2173 + memcpy(buf + 4, l2cap_fixed_chan, 8);
  2174 + l2cap_send_cmd(conn, cmd->ident,
  2175 + L2CAP_INFO_RSP, sizeof(buf), buf);
2168 2176 } else {
2169 2177 struct l2cap_info_rsp rsp;
2170 2178 rsp.type = cpu_to_le16(type);
2171 2179  
2172 2180  
... ... @@ -2186,14 +2194,28 @@
2186 2194  
2187 2195 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2188 2196  
2189   - conn->info_ident = 0;
2190   -
2191 2197 del_timer(&conn->info_timer);
2192 2198  
2193 2199 if (type == L2CAP_IT_FEAT_MASK) {
2194 2200 conn->feat_mask = get_unaligned_le32(rsp->data);
2195 2201  
  2202 + if (conn->feat_mask & 0x0080) {
  2203 + struct l2cap_info_req req;
  2204 + req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
  2205 +
  2206 + conn->info_ident = l2cap_get_ident(conn);
  2207 +
  2208 + l2cap_send_cmd(conn, conn->info_ident,
  2209 + L2CAP_INFO_REQ, sizeof(req), &req);
  2210 + } else {
  2211 + conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
  2212 + conn->info_ident = 0;
  2213 +
  2214 + l2cap_conn_start(conn);
  2215 + }
  2216 + } else if (type == L2CAP_IT_FIXED_CHAN) {
2196 2217 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
  2218 + conn->info_ident = 0;
2197 2219  
2198 2220 l2cap_conn_start(conn);
2199 2221 }
... ... @@ -2589,7 +2611,7 @@
2589 2611 goto drop;
2590 2612  
2591 2613 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
2592   - skb->len);
  2614 + skb->len);
2593 2615 conn->rx_len = len - skb->len;
2594 2616 } else {
2595 2617 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
... ... @@ -2611,7 +2633,7 @@
2611 2633 }
2612 2634  
2613 2635 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
2614   - skb->len);
  2636 + skb->len);
2615 2637 conn->rx_len -= skb->len;
2616 2638  
2617 2639 if (!conn->rx_len) {