Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2015-03-02

Here's the first bluetooth-next pull request targeting the 4.1 kernel:

 - ieee802154/6lowpan cleanups
 - SCO routing to host interface support for the btmrvl driver
 - AMP code cleanups
 - Fixes to AMP HCI init sequence
 - Refactoring of the HCI callback mechanism
 - Added shutdown routine for Intel controllers in the btusb driver
 - New config option to enable/disable Bluetooth debugfs information
 - Fix for early data reception on L2CAP fixed channels

Please let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2015-03-02 14:47:12 -05:00
38 changed files with 1286 additions and 492 deletions

View File

@@ -91,4 +91,12 @@ config BT_SELFTEST_SMP
Run test cases for SMP cryptographic functionality, including both
legacy SMP as well as the Secure Connections features.
config BT_DEBUGFS
bool "Export Bluetooth internals in debugfs"
depends on BT && DEBUG_FS
default y
help
Provide extensive information about internal Bluetooth states
in debugfs.
source "drivers/bluetooth/Kconfig"

View File

@@ -13,8 +13,9 @@ bluetooth_6lowpan-y := 6lowpan.o
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
a2mp.o amp.o ecc.o hci_request.o hci_debugfs.o
a2mp.o amp.o ecc.o hci_request.o
bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o
bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o
subdir-ccflags-y += -D__CHECK_ENDIAN__

View File

@@ -19,9 +19,11 @@
#include "a2mp.h"
#include "amp.h"
#define A2MP_FEAT_EXT 0x8000
/* Global AMP Manager list */
LIST_HEAD(amp_mgr_list);
DEFINE_MUTEX(amp_mgr_list_lock);
static LIST_HEAD(amp_mgr_list);
static DEFINE_MUTEX(amp_mgr_list_lock);
/* A2MP build & send command helper functions */
static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
@@ -43,7 +45,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
return cmd;
}
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
{
struct l2cap_chan *chan = mgr->a2mp_chan;
struct a2mp_cmd *cmd;
@@ -67,7 +69,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
kfree(cmd);
}
u8 __next_ident(struct amp_mgr *mgr)
static u8 __next_ident(struct amp_mgr *mgr)
{
if (++mgr->ident == 0)
mgr->ident = 1;
@@ -75,6 +77,23 @@ u8 __next_ident(struct amp_mgr *mgr)
return mgr->ident;
}
static struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
{
struct amp_mgr *mgr;
mutex_lock(&amp_mgr_list_lock);
list_for_each_entry(mgr, &amp_mgr_list, list) {
if (test_and_clear_bit(state, &mgr->state)) {
amp_mgr_get(mgr);
mutex_unlock(&amp_mgr_list_lock);
return mgr;
}
}
mutex_unlock(&amp_mgr_list_lock);
return NULL;
}
/* hci_dev_list shall be locked */
static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl)
{
@@ -860,23 +879,6 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
return mgr->a2mp_chan;
}
struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
{
struct amp_mgr *mgr;
mutex_lock(&amp_mgr_list_lock);
list_for_each_entry(mgr, &amp_mgr_list, list) {
if (test_and_clear_bit(state, &mgr->state)) {
amp_mgr_get(mgr);
mutex_unlock(&amp_mgr_list_lock);
return mgr;
}
}
mutex_unlock(&amp_mgr_list_lock);
return NULL;
}
void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
{
struct amp_mgr *mgr;

View File

@@ -17,8 +17,6 @@
#include <net/bluetooth/l2cap.h>
#define A2MP_FEAT_EXT 0x8000
enum amp_mgr_state {
READ_LOC_AMP_INFO,
READ_LOC_AMP_ASSOC,
@@ -131,16 +129,10 @@ struct a2mp_physlink_rsp {
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
extern struct list_head amp_mgr_list;
extern struct mutex amp_mgr_list_lock;
struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
u8 __next_ident(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
void a2mp_discover_amp(struct l2cap_chan *chan);
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);

View File

@@ -309,7 +309,7 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
else
hci_add_sco(sco, conn->handle);
} else {
hci_proto_connect_cfm(sco, status);
hci_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
@@ -618,7 +618,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
status);
hci_proto_connect_cfm(conn, status);
hci_connect_cfm(conn, status);
hci_conn_del(conn);
@@ -733,6 +733,14 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
struct hci_request req;
int err;
/* Let's make sure that le is enabled.*/
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
if (lmp_le_capable(hdev))
return ERR_PTR(-ECONNREFUSED);
return ERR_PTR(-EOPNOTSUPP);
}
/* Some devices send ATT messages as soon as the physical link is
* established. To be able to handle these ATT messages, the user-
* space first establishes the connection and then starts the pairing
@@ -856,8 +864,12 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
{
struct hci_conn *acl;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
if (lmp_bredr_capable(hdev))
return ERR_PTR(-ECONNREFUSED);
return ERR_PTR(-EOPNOTSUPP);
}
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
@@ -1139,7 +1151,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
list_for_each_entry_safe(c, n, &h->list, list) {
c->state = BT_CLOSED;
hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
hci_conn_del(c);
}
}

View File

@@ -51,7 +51,7 @@ DEFINE_RWLOCK(hci_dev_list_lock);
/* HCI callback list */
LIST_HEAD(hci_cb_list);
DEFINE_RWLOCK(hci_cb_list_lock);
DEFINE_MUTEX(hci_cb_list_lock);
/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);
@@ -390,7 +390,7 @@ static void bredr_init(struct hci_request *req)
hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
}
static void amp_init(struct hci_request *req)
static void amp_init1(struct hci_request *req)
{
req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
@@ -400,9 +400,6 @@ static void amp_init(struct hci_request *req)
/* Read Local Supported Commands */
hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
/* Read Local Supported Features */
hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local AMP Info */
hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
@@ -416,6 +413,16 @@ static void amp_init(struct hci_request *req)
hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL);
}
static void amp_init2(struct hci_request *req)
{
/* Read Local Supported Features. Not all AMP controllers
* support this so it's placed conditionally in the second
* stage init.
*/
if (req->hdev->commands[14] & 0x20)
hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
}
static void hci_init1_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
@@ -432,7 +439,7 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt)
break;
case HCI_AMP:
amp_init(req);
amp_init1(req);
break;
default:
@@ -578,6 +585,9 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
if (hdev->dev_type == HCI_AMP)
return amp_init2(req);
if (lmp_bredr_capable(hdev))
bredr_setup(req);
else
@@ -896,17 +906,17 @@ static int __hci_init(struct hci_dev *hdev)
&dut_mode_fops);
}
/* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
* BR/EDR/LE type controllers. AMP controllers only need the
* first stage init.
*/
if (hdev->dev_type != HCI_BREDR)
return 0;
err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
/* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
* BR/EDR/LE type controllers. AMP controllers only need the
* first two stages of init.
*/
if (hdev->dev_type != HCI_BREDR)
return 0;
err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
@@ -1591,6 +1601,12 @@ static int hci_dev_do_close(struct hci_dev *hdev)
{
BT_DBG("%s %p", hdev->name, hdev);
if (!test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
/* Execute vendor specific shutdown routine */
if (hdev->shutdown)
hdev->shutdown(hdev);
}
cancel_delayed_work(&hdev->power_off);
hci_req_cancel(hdev, ENODEV);
@@ -3448,9 +3464,9 @@ int hci_register_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
write_lock(&hci_cb_list_lock);
list_add(&cb->list, &hci_cb_list);
write_unlock(&hci_cb_list_lock);
mutex_lock(&hci_cb_list_lock);
list_add_tail(&cb->list, &hci_cb_list);
mutex_unlock(&hci_cb_list_lock);
return 0;
}
@@ -3460,9 +3476,9 @@ int hci_unregister_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
write_lock(&hci_cb_list_lock);
mutex_lock(&hci_cb_list_lock);
list_del(&cb->list);
write_unlock(&hci_cb_list_lock);
mutex_unlock(&hci_cb_list_lock);
return 0;
}

View File

@@ -20,7 +20,29 @@
SOFTWARE IS DISCLAIMED.
*/
#if IS_ENABLED(CONFIG_BT_DEBUGFS)
void hci_debugfs_create_common(struct hci_dev *hdev);
void hci_debugfs_create_bredr(struct hci_dev *hdev);
void hci_debugfs_create_le(struct hci_dev *hdev);
void hci_debugfs_create_conn(struct hci_conn *conn);
#else
static inline void hci_debugfs_create_common(struct hci_dev *hdev)
{
}
static inline void hci_debugfs_create_bredr(struct hci_dev *hdev)
{
}
static inline void hci_debugfs_create_le(struct hci_dev *hdev)
{
}
static inline void hci_debugfs_create_conn(struct hci_conn *conn)
{
}
#endif

View File

@@ -1537,7 +1537,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
if (conn && conn->state == BT_CONNECT) {
if (status != 0x0c || conn->attempt > 2) {
conn->state = BT_CLOSED;
hci_proto_connect_cfm(conn, status);
hci_connect_cfm(conn, status);
hci_conn_del(conn);
} else
conn->state = BT_CONNECT2;
@@ -1581,7 +1581,7 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
if (sco) {
sco->state = BT_CLOSED;
hci_proto_connect_cfm(sco, status);
hci_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
@@ -1608,7 +1608,7 @@ static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
@@ -1635,7 +1635,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
@@ -1811,7 +1811,7 @@ static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
@@ -1838,7 +1838,7 @@ static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
@@ -1873,7 +1873,7 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
if (sco) {
sco->state = BT_CLOSED;
hci_proto_connect_cfm(sco, status);
hci_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
@@ -2255,10 +2255,10 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_sco_setup(conn, ev->status);
if (ev->status) {
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
hci_conn_del(conn);
} else if (ev->link_type != ACL_LINK)
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
unlock:
hci_dev_unlock(hdev);
@@ -2366,7 +2366,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
&cp);
} else {
conn->state = BT_CONNECT2;
hci_proto_connect_cfm(conn, 0);
hci_connect_cfm(conn, 0);
}
}
@@ -2444,7 +2444,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
type = conn->type;
hci_proto_disconn_cfm(conn, ev->reason);
hci_disconn_cfm(conn, ev->reason);
hci_conn_del(conn);
/* Re-enable advertising if necessary, since it might
@@ -2501,7 +2501,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
&cp);
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
}
} else {
@@ -2629,12 +2629,12 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) &&
(!test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) {
hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
hci_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE);
hci_conn_drop(conn);
goto unlock;
}
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
} else
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
@@ -2707,7 +2707,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
}
@@ -3679,7 +3679,7 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
}
@@ -3738,7 +3738,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
break;
}
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
if (ev->status)
hci_conn_del(conn);
@@ -3849,7 +3849,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
if (!ev->status)
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
} else {
hci_auth_cfm(conn, ev->status);
@@ -4512,7 +4512,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_debugfs_create_conn(conn);
hci_conn_add_sysfs(conn);
hci_proto_connect_cfm(conn, ev->status);
hci_connect_cfm(conn, ev->status);
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
conn->dst_type);

View File

@@ -46,9 +46,9 @@ struct hci_pinfo {
unsigned short channel;
};
static inline int hci_test_bit(int nr, void *addr)
static inline int hci_test_bit(int nr, const void *addr)
{
return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
return *((const __u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
}
/* Security filter */
@@ -183,12 +183,13 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
kfree_skb(skb_copy);
}
/* Send frame to control socket */
void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk)
/* Send frame to sockets with specific channel */
void hci_send_to_channel(unsigned short channel, struct sk_buff *skb,
struct sock *skip_sk)
{
struct sock *sk;
BT_DBG("len %d", skb->len);
BT_DBG("channel %u len %d", channel, skb->len);
read_lock(&hci_sk_list.lock);
@@ -202,35 +203,7 @@ void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk)
if (sk->sk_state != BT_BOUND)
continue;
if (hci_pi(sk)->channel != HCI_CHANNEL_CONTROL)
continue;
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
continue;
if (sock_queue_rcv_skb(sk, nskb))
kfree_skb(nskb);
}
read_unlock(&hci_sk_list.lock);
}
static void queue_monitor_skb(struct sk_buff *skb)
{
struct sock *sk;
BT_DBG("len %d", skb->len);
read_lock(&hci_sk_list.lock);
sk_for_each(sk, &hci_sk_list.head) {
struct sk_buff *nskb;
if (sk->sk_state != BT_BOUND)
continue;
if (hci_pi(sk)->channel != HCI_CHANNEL_MONITOR)
if (hci_pi(sk)->channel != channel)
continue;
nskb = skb_clone(skb, GFP_ATOMIC);
@@ -290,7 +263,7 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
hdr->index = cpu_to_le16(hdev->id);
hdr->len = cpu_to_le16(skb->len);
queue_monitor_skb(skb_copy);
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy, NULL);
kfree_skb(skb_copy);
}
@@ -397,7 +370,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event)
skb = create_monitor_event(hdev, event);
if (skb) {
queue_monitor_skb(skb);
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb, NULL);
kfree_skb(skb);
}
}

View File

@@ -1244,6 +1244,13 @@ static void l2cap_move_done(struct l2cap_chan *chan)
static void l2cap_chan_ready(struct l2cap_chan *chan)
{
/* The channel may have already been flagged as connected in
* case of receiving data before the L2CAP info req/rsp
* procedure is complete.
*/
if (chan->state == BT_CONNECTED)
return;
/* This clears all conf flags, including CONF_NOT_COMPLETE */
chan->conf_state = 0;
__clear_chan_timer(chan);
@@ -6785,6 +6792,13 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
BT_DBG("chan %p, len %d", chan, skb->len);
/* If we receive data on a fixed channel before the info req/rsp
* procdure is done simply assume that the channel is supported
* and mark it as ready.
*/
if (chan->chan_type == L2CAP_CHAN_FIXED)
l2cap_chan_ready(chan);
if (chan->state != BT_CONNECTED)
goto drop;
@@ -7238,13 +7252,16 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
return NULL;
}
void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{
struct hci_dev *hdev = hcon->hdev;
struct l2cap_conn *conn;
struct l2cap_chan *pchan;
u8 dst_type;
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
return;
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (status) {
@@ -7307,8 +7324,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
return conn->disc_reason;
}
void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
return;
BT_DBG("hcon %p reason %d", hcon, reason);
l2cap_conn_del(hcon, bt_to_errno(reason));
@@ -7331,13 +7351,13 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
}
}
int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
{
struct l2cap_conn *conn = hcon->l2cap_data;
struct l2cap_chan *chan;
if (!conn)
return 0;
return;
BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
@@ -7420,8 +7440,6 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
}
mutex_unlock(&conn->chan_lock);
return 0;
}
int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
@@ -7529,6 +7547,13 @@ drop:
return 0;
}
static struct hci_cb l2cap_cb = {
.name = "L2CAP",
.connect_cfm = l2cap_connect_cfm,
.disconn_cfm = l2cap_disconn_cfm,
.security_cfm = l2cap_security_cfm,
};
static int l2cap_debugfs_show(struct seq_file *f, void *p)
{
struct l2cap_chan *c;
@@ -7570,6 +7595,8 @@ int __init l2cap_init(void)
if (err < 0)
return err;
hci_register_cb(&l2cap_cb);
if (IS_ERR_OR_NULL(bt_debugfs))
return 0;
@@ -7587,6 +7614,7 @@ int __init l2cap_init(void)
void l2cap_exit(void)
{
debugfs_remove(l2cap_debugfs);
hci_unregister_cb(&l2cap_cb);
l2cap_cleanup_sockets();
}

View File

@@ -29,6 +29,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/hci_sock.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>
@@ -242,7 +243,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
/* Time stamp */
__net_timestamp(skb);
hci_send_to_control(skb, skip_sk);
hci_send_to_channel(HCI_CHANNEL_CONTROL, skb, skip_sk);
kfree_skb(skb);
return 0;
@@ -2116,8 +2117,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
goto failed;
}
if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_BUSY);
goto failed;
@@ -2176,6 +2176,12 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_dev_lock(hdev);
if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_BUSY);
goto unlock;
}
if (cp->val) {
changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
} else {
@@ -3249,6 +3255,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
if (PTR_ERR(conn) == -EBUSY)
status = MGMT_STATUS_BUSY;
else if (PTR_ERR(conn) == -EOPNOTSUPP)
status = MGMT_STATUS_NOT_SUPPORTED;
else if (PTR_ERR(conn) == -ECONNREFUSED)
status = MGMT_STATUS_REJECTED;
else
status = MGMT_STATUS_CONNECT_FAILED;
@@ -6654,7 +6664,7 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
ev.key.master = csrk->master;
ev.key.type = csrk->type;
memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);

View File

@@ -1083,9 +1083,13 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
return lm;
}
void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return;
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (!status) {
struct sco_conn *conn;
@@ -1096,8 +1100,11 @@ void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
sco_conn_del(hcon, bt_to_errno(status));
}
void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
{
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return;
BT_DBG("hcon %p reason %d", hcon, reason);
sco_conn_del(hcon, bt_to_errno(reason));
@@ -1122,6 +1129,12 @@ drop:
return 0;
}
static struct hci_cb sco_cb = {
.name = "SCO",
.connect_cfm = sco_connect_cfm,
.disconn_cfm = sco_disconn_cfm,
};
static int sco_debugfs_show(struct seq_file *f, void *p)
{
struct sock *sk;
@@ -1203,6 +1216,8 @@ int __init sco_init(void)
BT_INFO("SCO socket layer initialized");
hci_register_cb(&sco_cb);
if (IS_ERR_OR_NULL(bt_debugfs))
return 0;
@@ -1222,6 +1237,8 @@ void __exit sco_exit(void)
debugfs_remove(sco_debugfs);
hci_unregister_cb(&sco_cb);
bt_sock_unregister(BTPROTO_SCO);
proto_unregister(&sco_proto);

View File

@@ -1252,7 +1252,10 @@ static void smp_distribute_keys(struct smp_chan *smp)
csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
if (csrk) {
csrk->master = 0x00;
if (hcon->sec_level > BT_SECURITY_MEDIUM)
csrk->type = MGMT_CSRK_LOCAL_AUTHENTICATED;
else
csrk->type = MGMT_CSRK_LOCAL_UNAUTHENTICATED;
memcpy(csrk->val, sign.csrk, sizeof(csrk->val));
}
smp->slave_csrk = csrk;
@@ -2352,7 +2355,10 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
if (csrk) {
csrk->master = 0x01;
if (conn->hcon->sec_level > BT_SECURITY_MEDIUM)
csrk->type = MGMT_CSRK_REMOTE_AUTHENTICATED;
else
csrk->type = MGMT_CSRK_REMOTE_UNAUTHENTICATED;
memcpy(csrk->val, rp->csrk, sizeof(csrk->val));
}
smp->csrk = csrk;
@@ -2951,24 +2957,14 @@ create_chan:
l2cap_chan_set_defaults(chan);
if (cid == L2CAP_CID_SMP) {
/* If usage of static address is forced or if the devices
* does not have a public address, then listen on the static
* address.
*
* In case BR/EDR has been disabled on a dual-mode controller
* and a static address has been configued, then listen on
* the static address instead.
*/
if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY) ||
(!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
bacmp(&hdev->static_addr, BDADDR_ANY))) {
bacpy(&chan->src, &hdev->static_addr);
chan->src_type = BDADDR_LE_RANDOM;
} else {
bacpy(&chan->src, &hdev->bdaddr);
u8 bdaddr_type;
hci_copy_identity_address(hdev, &chan->src, &bdaddr_type);
if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
chan->src_type = BDADDR_LE_PUBLIC;
}
else
chan->src_type = BDADDR_LE_RANDOM;
} else {
bacpy(&chan->src, &hdev->bdaddr);
chan->src_type = BDADDR_BREDR;