Commit e1027a7c69700301d14db03d2e049ee60c4f92df
1 parent
435fef20ac
Exists in
master
and in
7 other branches
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
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) { |