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:
@@ -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"
|
||||
|
@@ -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__
|
||||
|
@@ -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(&_mgr_list_lock);
|
||||
list_for_each_entry(mgr, &_mgr_list, list) {
|
||||
if (test_and_clear_bit(state, &mgr->state)) {
|
||||
amp_mgr_get(mgr);
|
||||
mutex_unlock(&_mgr_list_lock);
|
||||
return mgr;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&_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(&_mgr_list_lock);
|
||||
list_for_each_entry(mgr, &_mgr_list, list) {
|
||||
if (test_and_clear_bit(state, &mgr->state)) {
|
||||
amp_mgr_get(mgr);
|
||||
mutex_unlock(&_mgr_list_lock);
|
||||
return mgr;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&_mgr_list_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
|
||||
{
|
||||
struct amp_mgr *mgr;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user