From bb4b2a9ae38ef3bac69627f35e4f916752631fd1 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:40 +0300 Subject: Bluetooth: mgmt: Managing only BR/EDR HCI controllers Add check that HCI controller is BR/EDR. AMP controller shall not be managed by mgmt interface and consequently user space. Signed-off-by: Andrei Emeltchenko Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_core.c | 6 ++++-- net/bluetooth/mgmt.c | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4de5db18d5..fa974a19d36 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev) hci_dev_hold(hdev); set_bit(HCI_UP, &hdev->flags); hci_notify(hdev, HCI_DEV_UP); - if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { + if (!test_bit(HCI_SETUP, &hdev->dev_flags) && + mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 1); hci_dev_unlock(hdev); @@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) * and no tasks are scheduled. */ hdev->close(hdev); - if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { + if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && + mgmt_valid_hdev(hdev)) { hci_dev_lock(hdev); mgmt_powered(hdev, 0); hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad6613d17ca..2a0f695e33d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = { MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ }; +bool mgmt_valid_hdev(struct hci_dev *hdev) +{ + return hdev->dev_type == HCI_BREDR; +} + static u8 mgmt_status(u8 hci_status) { if (hci_status < ARRAY_SIZE(mgmt_status_table)) @@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, u16 data_len) { struct mgmt_rp_read_index_list *rp; - struct list_head *p; struct hci_dev *d; size_t rp_len; u16 count; @@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, read_lock(&hci_dev_list_lock); count = 0; - list_for_each(p, &hci_dev_list) { + list_for_each_entry(d, &hci_dev_list, list) { + if (!mgmt_valid_hdev(d)) + continue; + count++; } @@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (test_bit(HCI_SETUP, &d->dev_flags)) continue; + if (!mgmt_valid_hdev(d)) + continue; + rp->index[i++] = cpu_to_le16(d->id); BT_DBG("Added hci%u", d->id); } @@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data) int mgmt_index_added(struct hci_dev *hdev) { + if (!mgmt_valid_hdev(hdev)) + return -ENOTSUPP; + return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); } @@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev) { u8 status = MGMT_STATUS_INVALID_INDEX; + if (!mgmt_valid_hdev(hdev)) + return -ENOTSUPP; + mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); -- cgit v1.2.3 From 8e8c7e36fb216d2d072116de3bec6130627ad691 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:41 +0300 Subject: Bluetooth: debug: Fix printing A2MP cmd code format Print A2MP code format according to Bluetooth style. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/a2mp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 4ff0bf3ba9a..57094c13623 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -316,7 +316,7 @@ send_rsp: static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, struct a2mp_cmd *hdr) { - BT_DBG("ident %d code %d", hdr->ident, hdr->code); + BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code); skb_pull(skb, le16_to_cpu(hdr->len)); return 0; @@ -335,7 +335,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) struct a2mp_cmd *hdr = (void *) skb->data; u16 len = le16_to_cpu(hdr->len); - BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len); + BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); skb_pull(skb, sizeof(*hdr)); -- cgit v1.2.3 From d9fc1d54f6f8123909cdee4fa98ab1ebf6c8651c Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:46 +0300 Subject: Bluetooth: Do not shadow hdr variable Fix compile warnings below: ... net/bluetooth/a2mp.c:505:33: warning: symbol 'hdr' shadows an earlier one net/bluetooth/a2mp.c:498:25: originally declared here ... Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/a2mp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 57094c13623..79af661a58d 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -325,15 +325,17 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, /* Handle A2MP signalling */ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { - struct a2mp_cmd *hdr = (void *) skb->data; + struct a2mp_cmd *hdr; struct amp_mgr *mgr = chan->data; int err = 0; amp_mgr_get(mgr); while (skb->len >= sizeof(*hdr)) { - struct a2mp_cmd *hdr = (void *) skb->data; - u16 len = le16_to_cpu(hdr->len); + u16 len; + + hdr = (void *) skb->data; + len = le16_to_cpu(hdr->len); BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); @@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) if (err) { struct a2mp_cmd_rej rej; + rej.reason = __constant_cpu_to_le16(0); + hdr = (void *) skb->data; BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); -- cgit v1.2.3 From 78eb2f985c17eab34a0ef919b3263d6b08064e98 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 19 Jul 2012 17:03:47 +0300 Subject: Bluetooth: Fix processing A2MP chan in security_cfm Do not process A2MP channel in l2cap_security_cfm Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bf..64d88a603f0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -5404,6 +5404,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, state_to_string(chan->state)); + if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { + l2cap_chan_unlock(chan); + continue; + } + if (chan->scid == L2CAP_CID_LE_DATA) { if (!status && encrypt) { chan->sec_level = hcon->sec_level; -- cgit v1.2.3 From ed3fa31f35896b42c54333edabf0a9e986fa952c Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:46 -0300 Subject: Bluetooth: Use lmp_bredr_capable where applicable This patch replaces all LMP_NO_BREDR bit checking by the helper macro lmp_bredr_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2a0f695e33d..990ec6affca 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -383,7 +383,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) if (hdev->features[6] & LMP_SIMPLE_PAIR) settings |= MGMT_SETTING_SSP; - if (!(hdev->features[4] & LMP_NO_BREDR)) { + if (lmp_bredr_capable(hdev)) { settings |= MGMT_SETTING_BREDR; settings |= MGMT_SETTING_LINK_SECURITY; } @@ -413,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) settings |= MGMT_SETTING_PAIRABLE; - if (!(hdev->features[4] & LMP_NO_BREDR)) + if (lmp_bredr_capable(hdev)) settings |= MGMT_SETTING_BREDR; if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) -- cgit v1.2.3 From c383ddc481a1774702473b4bb0d2927aab3f2d5a Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:47 -0300 Subject: Bluetooth: Use lmp_le_capable where applicable This patch replaces all LMP_LE bit checking by the helper macro lmp_le_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ++-- net/bluetooth/mgmt.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f..498d55edcbc 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) * Features Notification */ } - if (hdev->features[4] & LMP_LE) + if (lmp_le_capable(hdev)) events[7] |= 0x20; /* LE Meta-Event */ hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); @@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, break; } - if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) + if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) hci_set_le_support(hdev); done: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 990ec6affca..0351bf27f2b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -391,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) if (enable_hs) settings |= MGMT_SETTING_HS; - if (hdev->features[4] & LMP_LE) + if (lmp_le_capable(hdev)) settings |= MGMT_SETTING_LE; return settings; @@ -1205,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - if (!(hdev->features[4] & LMP_LE)) { + if (!lmp_le_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, MGMT_STATUS_NOT_SUPPORTED); goto unlock; -- cgit v1.2.3 From 9a1a1996d54a92cae2affa1de689cb04ebe7bce1 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:48 -0300 Subject: Bluetooth: Use lmp_ssp_capable where applicable This patch replaces all LMP_SIMPLE_PAIR bit checking by the helper macro lmp_ssp_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- net/bluetooth/mgmt.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 498d55edcbc..b120388678f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -528,7 +528,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[7] & LMP_LSTO) events[6] |= 0x80; /* Link Supervision Timeout Changed */ - if (hdev->features[6] & LMP_SIMPLE_PAIR) { + if (lmp_ssp_capable(hdev)) { events[6] |= 0x01; /* IO Capability Request */ events[6] |= 0x02; /* IO Capability Response */ events[6] |= 0x04; /* User Confirmation Request */ diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0351bf27f2b..a3329cbd3e4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -380,7 +380,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) settings |= MGMT_SETTING_DISCOVERABLE; settings |= MGMT_SETTING_PAIRABLE; - if (hdev->features[6] & LMP_SIMPLE_PAIR) + if (lmp_ssp_capable(hdev)) settings |= MGMT_SETTING_SSP; if (lmp_bredr_capable(hdev)) { @@ -1121,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + if (!lmp_ssp_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, MGMT_STATUS_NOT_SUPPORTED); goto failed; @@ -2201,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, goto unlock; } - if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { + if (!lmp_ssp_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, MGMT_STATUS_NOT_SUPPORTED); goto unlock; -- cgit v1.2.3 From 45db810fb71a94926c10f4dbbb5ca7913983f83b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:49 -0300 Subject: Bluetooth: Use lmp_esco_capable where applicable This patch replaces all LMP_ESCO bit checking by the helper macro lmp_esco_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b120388678f..5722a388ada 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, hdev->esco_type |= (ESCO_HV3); } - if (hdev->features[3] & LMP_ESCO) + if (lmp_esco_capable(hdev)) hdev->esco_type |= (ESCO_EV3); if (hdev->features[4] & LMP_EV4) -- cgit v1.2.3 From 9f92ebf6c72de444801ab4a922965bd1f90834ae Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:50 -0300 Subject: Bluetooth: Use lmp_rswitch_capable where applicable This patch replaces all LMP_RSWITCH bit checking by the helper macro lmp_rswitch_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5722a388ada..5c71c85c87a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -623,7 +623,7 @@ static void hci_setup_link_policy(struct hci_dev *hdev) struct hci_cp_write_def_link_policy cp; u16 link_policy = 0; - if (hdev->features[0] & LMP_RSWITCH) + if (lmp_rswitch_capable(hdev)) link_policy |= HCI_LP_RSWITCH; if (hdev->features[0] & LMP_HOLD) link_policy |= HCI_LP_HOLD; -- cgit v1.2.3 From 6eded1004abb060fbdf69611abc560c717f2bb8b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:51 -0300 Subject: Bluetooth: Use lmp_sniff_capable where applicable This patch replaces all LMP_SNIFF bit checking by the helper macro lmp_sniff_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5c71c85c87a..eb9024a8684 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -627,7 +627,7 @@ static void hci_setup_link_policy(struct hci_dev *hdev) link_policy |= HCI_LP_RSWITCH; if (hdev->features[0] & LMP_HOLD) link_policy |= HCI_LP_HOLD; - if (hdev->features[0] & LMP_SNIFF) + if (lmp_sniff_capable(hdev)) link_policy |= HCI_LP_SNIFF; if (hdev->features[1] & LMP_PARK) link_policy |= HCI_LP_PARK; -- cgit v1.2.3 From 999dcd10a88243ab304966a506b4975ce5f1e3bb Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:52 -0300 Subject: Bluetooth: Use lmp_sniffsubr_capable where applicable This patch replaces all LMP_SNIFF_SUBR bit checking by the helper macro lmp_sniffsubr_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index eb9024a8684..060780c40ba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[3] & LMP_RSSI_INQ) events[4] |= 0x02; /* Inquiry Result with RSSI */ - if (hdev->features[5] & LMP_SNIFF_SUBR) + if (lmp_sniffsubr_capable(hdev)) events[5] |= 0x20; /* Sniff Subrating */ if (hdev->features[5] & LMP_PAUSE_ENC) -- cgit v1.2.3 From c58e810eb0916f9197378435af72136fb7c97f43 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 24 Jul 2012 15:03:53 -0300 Subject: Bluetooth: Use lmp_no_flush_capable where applicable This patch replaces all LMP_NO_FLUSH bit checking by the helper macro lmp_no_flush_capable. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 060780c40ba..2d8761b8b19 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -522,7 +522,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) if (hdev->features[6] & LMP_EXT_INQ) events[5] |= 0x40; /* Extended Inquiry Result */ - if (hdev->features[6] & LMP_NO_FLUSH) + if (lmp_no_flush_capable(hdev)) events[7] |= 0x01; /* Enhanced Flush Complete */ if (hdev->features[7] & LMP_LSTO) -- cgit v1.2.3 From 9e66463127ff7238020c3c4e7f84dfbc23e5c2b5 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 24 Jul 2012 16:06:15 +0300 Subject: Bluetooth: Make connect / disconnect cfm functions return void Return values are never used because callers hci_proto_connect_cfm and hci_proto_disconn_cfm return void. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 6 ++---- net/bluetooth/sco.c | 7 ++----- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 64d88a603f0..8391e057549 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -5329,7 +5329,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) return exact ? lm1 : lm2; } -int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) +void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) { struct l2cap_conn *conn; @@ -5342,7 +5342,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) } else l2cap_conn_del(hcon, bt_to_errno(status)); - return 0; } int l2cap_disconn_ind(struct hci_conn *hcon) @@ -5356,12 +5355,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon) return conn->disc_reason; } -int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) +void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); l2cap_conn_del(hcon, bt_to_errno(reason)); - return 0; } static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff..0ef5a78a889 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) return lm; } -int sco_connect_cfm(struct hci_conn *hcon, __u8 status) +void sco_connect_cfm(struct hci_conn *hcon, __u8 status) { BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); if (!status) { @@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status) sco_conn_ready(conn); } else sco_conn_del(hcon, bt_to_errno(status)); - - return 0; } -int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) +void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); sco_conn_del(hcon, bt_to_errno(reason)); - return 0; } int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) -- cgit v1.2.3 From ee72d150ada90d33cc6e222fbdd7f980c16d974d Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 23 Jul 2012 18:19:04 -0300 Subject: Bluetooth: Remove locking in hci_user_passkey_request_evt This patch removes hdev locking in hci_user_passkey_request_evt since it is not needed. mgmt_user_passkey_request simply calls mgmt_event which does not require hdev locking at all. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2d8761b8b19..0386e1e7227 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3252,12 +3252,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, BT_DBG("%s", hdev->name); - hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); - - hci_dev_unlock(hdev); } static void hci_simple_pair_complete_evt(struct hci_dev *hdev, -- cgit v1.2.3 From 3064837289259843310b266a9422aca5f5b4b9c7 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Fri, 13 Jul 2012 18:17:54 +0530 Subject: Bluetooth: Move l2cap_chan_hold/put to l2cap_core.c Refactor the code in order to use the l2cap_chan_destroy() from l2cap_chan_put() under the refcnt protection. Signed-off-by: Jaganath Kanakkassery Signed-off-by: Syam Sidhardhan Reviewed-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8391e057549..79923d8bbe9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -425,6 +425,21 @@ void l2cap_chan_destroy(struct l2cap_chan *chan) l2cap_chan_put(chan); } +void l2cap_chan_hold(struct l2cap_chan *c) +{ + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + + atomic_inc(&c->refcnt); +} + +void l2cap_chan_put(struct l2cap_chan *c) +{ + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + + if (atomic_dec_and_test(&c->refcnt)) + kfree(c); +} + void l2cap_chan_set_defaults(struct l2cap_chan *chan) { chan->fcs = L2CAP_FCS_CRC16; -- cgit v1.2.3 From 4af66c691f4e5c2db9bb00793669a548e9db1974 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Fri, 13 Jul 2012 18:17:55 +0530 Subject: Bluetooth: Free the l2cap channel list only when refcount is zero Move the l2cap channel list chan->global_l under the refcnt protection and free it based on the refcnt. Signed-off-by: Jaganath Kanakkassery Signed-off-by: Syam Sidhardhan Reviewed-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/a2mp.c | 2 +- net/bluetooth/l2cap_core.c | 8 +++++--- net/bluetooth/l2cap_sock.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 79af661a58d..0760d1fed6f 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -416,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) static void a2mp_chan_close_cb(struct l2cap_chan *chan) { - l2cap_chan_destroy(chan); + l2cap_chan_put(chan); } static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 79923d8bbe9..9f8b29ef5b6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -416,13 +416,15 @@ struct l2cap_chan *l2cap_chan_create(void) return chan; } -void l2cap_chan_destroy(struct l2cap_chan *chan) +static void l2cap_chan_destroy(struct l2cap_chan *chan) { + BT_DBG("chan %p", chan); + write_lock(&chan_list_lock); list_del(&chan->global_l); write_unlock(&chan_list_lock); - l2cap_chan_put(chan); + kfree(chan); } void l2cap_chan_hold(struct l2cap_chan *c) @@ -437,7 +439,7 @@ void l2cap_chan_put(struct l2cap_chan *c) BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); if (atomic_dec_and_test(&c->refcnt)) - kfree(c); + l2cap_chan_destroy(c); } void l2cap_chan_set_defaults(struct l2cap_chan *chan) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427..79350d10087 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -823,7 +823,7 @@ static void l2cap_sock_kill(struct sock *sk) /* Kill poor orphan */ - l2cap_chan_destroy(l2cap_pi(sk)->chan); + l2cap_chan_put(l2cap_pi(sk)->chan); sock_set_flag(sk, SOCK_DEAD); sock_put(sk); } -- cgit v1.2.3 From 256a06c8a85df676e80263af349daad1283e529e Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:26:32 +0900 Subject: Bluetooth: /proc/net/ entries for bluetooth protocols lsof command can tell the type of socket processes are using. Internal lsof uses inode numbers on socket fs to resolve the type of sockets. Files under /proc/net/, such as tcp, udp, unix, etc provides such inode information. Unfortunately bluetooth related protocols don't provide such inode information. This patch series introduces /proc/net files for the protocols. This patch against af_bluetooth.c provides facility to the implementation of protocols. This patch extends bt_sock_list and introduces two exported function bt_procfs_init, bt_procfs_cleanup. The type bt_sock_list is already used in some of implementation of protocols. bt_procfs_init prepare seq_operations which converts protocol own bt_sock_list data to protocol own proc entry when the entry is accessed. What I, lsof user, need is just inode number of bluetooth socket. However, people may want more information. The bt_procfs_init takes a function pointer for customizing the show handler of seq_operations. In v4 patch, __acquires and __releases attributes are added to suppress sparse warning. Suggested by Andrei Emeltchenko. In v5 patch, linux/proc_fs.h is included to use PDE. Build error is reported by Fengguang Wu. Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/af_bluetooth.c | 141 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index f7db5792ec6..58f9762b339 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -28,6 +28,7 @@ #include #include +#include #define VERSION "2.16" @@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) } EXPORT_SYMBOL(bt_sock_wait_state); +#ifdef CONFIG_PROC_FS +struct bt_seq_state { + struct bt_sock_list *l; +}; + +static void *bt_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(seq->private->l->lock) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + read_lock(&l->lock); + return seq_hlist_start_head(&l->head, *pos); +} + +static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + return seq_hlist_next(v, &l->head, pos); +} + +static void bt_seq_stop(struct seq_file *seq, void *v) + __releases(seq->private->l->lock) +{ + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + + read_unlock(&l->lock); +} + +static int bt_seq_show(struct seq_file *seq, void *v) +{ + struct sock *sk; + struct bt_sock *bt; + struct bt_seq_state *s = seq->private; + struct bt_sock_list *l = s->l; + bdaddr_t src_baswapped, dst_baswapped; + + if (v == SEQ_START_TOKEN) { + seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); + + if (l->custom_seq_show) { + seq_putc(seq, ' '); + l->custom_seq_show(seq, v); + } + + seq_putc(seq, '\n'); + } else { + sk = sk_entry(v); + bt = bt_sk(sk); + baswap(&src_baswapped, &bt->src); + baswap(&dst_baswapped, &bt->dst); + + seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", + sk, + atomic_read(&sk->sk_refcnt), + sk_rmem_alloc_get(sk), + sk_wmem_alloc_get(sk), + sock_i_uid(sk), + sock_i_ino(sk), + &src_baswapped, + &dst_baswapped, + bt->parent? sock_i_ino(bt->parent): 0LU); + + if (l->custom_seq_show) { + seq_putc(seq, ' '); + l->custom_seq_show(seq, v); + } + + seq_putc(seq, '\n'); + } + return 0; +} + +static struct seq_operations bt_seq_ops = { + .start = bt_seq_start, + .next = bt_seq_next, + .stop = bt_seq_stop, + .show = bt_seq_show, +}; + +static int bt_seq_open(struct inode *inode, struct file *file) +{ + struct bt_sock_list *sk_list; + struct bt_seq_state *s; + + sk_list = PDE(inode)->data; + s = __seq_open_private(file, &bt_seq_ops, + sizeof(struct bt_seq_state)); + if (s == NULL) + return -ENOMEM; + + s->l = sk_list; + return 0; +} + +int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)) +{ + struct proc_dir_entry * pde; + + sk_list->custom_seq_show = seq_show; + + sk_list->fops.owner = module; + sk_list->fops.open = bt_seq_open; + sk_list->fops.read = seq_read; + sk_list->fops.llseek = seq_lseek; + sk_list->fops.release = seq_release_private; + + pde = proc_net_fops_create(net, name, 0, &sk_list->fops); + if (pde == NULL) + return -ENOMEM; + + pde->data = sk_list; + + return 0; +} + +void bt_procfs_cleanup(struct net *net, const char *name) +{ + proc_net_remove(net, name); +} +#else +int bt_procfs_init(struct module* module, struct net *net, const char *name, + struct bt_sock_list* sk_list, + int (* seq_show)(struct seq_file *, void *)) +{ + return 0; +} + +void bt_procfs_cleanup(struct net *net, const char *name) +{ +} +#endif +EXPORT_SYMBOL(bt_procfs_init); +EXPORT_SYMBOL(bt_procfs_cleanup); + static struct net_proto_family bt_sock_family_ops = { .owner = THIS_MODULE, .family = PF_BLUETOOTH, -- cgit v1.2.3 From 77cf5585a31fdad48c16ddae9be154f5afe22c1c Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:27:35 +0900 Subject: Bluetooth: Added /proc/net/bnep via bt_procfs_init() Added /proc/net/bnep via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/bnep/sock.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5e5f5b410e0..5b6cc0bf4de 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -29,6 +29,10 @@ #include "bnep.h" +static struct bt_sock_list bnep_sk_list = { + .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock) +}; + static int bnep_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&bnep_sk_list, sk); + sock_orphan(sk); sock_put(sk); return 0; @@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&bnep_sk_list, sk); return 0; } @@ -222,19 +229,30 @@ int __init bnep_sock_init(void) return err; err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register BNEP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create BNEP proc file"); + bt_sock_unregister(BTPROTO_BNEP); + goto error; + } + + BT_INFO("BNEP socket layer initialized"); return 0; error: - BT_ERR("Can't register BNEP socket"); proto_unregister(&bnep_proto); return err; } void __exit bnep_sock_cleanup(void) { + bt_procfs_cleanup(&init_net, "bnep"); if (bt_sock_unregister(BTPROTO_BNEP) < 0) BT_ERR("Can't unregister BNEP socket"); -- cgit v1.2.3 From 8c8de589cedd375934d96e073d2b9077a00f10c2 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:28:07 +0900 Subject: Bluetooth: Added /proc/net/cmtp via bt_procfs_init() Added /proc/net/cmtp via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/cmtp/sock.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 311668d1457..d5cacef5274 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -42,6 +42,10 @@ #include "cmtp.h" +static struct bt_sock_list cmtp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock) +}; + static int cmtp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&cmtp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&cmtp_sk_list, sk); + return 0; } @@ -232,19 +240,30 @@ int cmtp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register CMTP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create CMTP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("CMTP socket layer initialized"); return 0; error: - BT_ERR("Can't register CMTP socket"); proto_unregister(&cmtp_proto); return err; } void cmtp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "cmtp"); if (bt_sock_unregister(BTPROTO_CMTP) < 0) BT_ERR("Can't unregister CMTP socket"); -- cgit v1.2.3 From f7c8663789038c4bc71b81e3c858a35c999347a8 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:28:36 +0900 Subject: Bluetooth: Added /proc/net/hci via bt_procfs_init() Added /proc/net/hci via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_sock.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d7..7c3d6c7c6dd 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1100,21 +1100,30 @@ int __init hci_sock_init(void) return err; err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("HCI socket registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HCI proc file"); + bt_sock_unregister(BTPROTO_HCI); + goto error; + } BT_INFO("HCI socket layer initialized"); return 0; error: - BT_ERR("HCI socket registration failed"); proto_unregister(&hci_sk_proto); return err; } void hci_sock_cleanup(void) { + bt_procfs_cleanup(&init_net, "hci"); if (bt_sock_unregister(BTPROTO_HCI) < 0) BT_ERR("HCI socket unregistration failed"); -- cgit v1.2.3 From 5c6ad8eee0a8c5fb4ba8b741008490da9eb66af6 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:00 +0900 Subject: Bluetooth: Added /proc/net/hidp via bt_procfs_init() Added /proc/net/hidp via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/hidp/sock.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a3..eca3889371c 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -25,6 +25,10 @@ #include "hidp.h" +static struct bt_sock_list hidp_sk_list = { + .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) +}; + static int hidp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&hidp_sk_list, sk); + sock_orphan(sk); sock_put(sk); @@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; + bt_sock_link(&hidp_sk_list, sk); + return 0; } @@ -271,8 +279,19 @@ int __init hidp_init_sockets(void) return err; err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("Can't register HIDP socket"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create HIDP proc file"); + bt_sock_unregister(BTPROTO_HIDP); + goto error; + } + + BT_INFO("HIDP socket layer initialized"); return 0; @@ -284,6 +303,7 @@ error: void __exit hidp_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "hidp"); if (bt_sock_unregister(BTPROTO_HIDP) < 0) BT_ERR("Can't unregister HIDP socket"); -- cgit v1.2.3 From 5b28d95c13e876037d2c692e61862bb3e98249af Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:25 +0900 Subject: Bluetooth: Added /proc/net/l2cap via bt_procfs_init() Added /proc/net/l2cap via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_sock.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 79350d10087..13f6a9816fe 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -34,6 +34,10 @@ #include #include +static struct bt_sock_list l2cap_sk_list = { + .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) +}; + static const struct proto_ops l2cap_sock_ops; static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); @@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock) if (!sk) return 0; + bt_sock_unlink(&l2cap_sk_list, sk); + err = l2cap_sock_shutdown(sock, 2); sock_orphan(sk); @@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, return -ENOMEM; l2cap_sock_init(sk, NULL); + bt_sock_link(&l2cap_sk_list, sk); return 0; } @@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void) return err; err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("L2CAP socket registration failed"); goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create L2CAP proc file"); + bt_sock_unregister(BTPROTO_L2CAP); + goto error; + } BT_INFO("L2CAP socket layer initialized"); return 0; error: - BT_ERR("L2CAP socket registration failed"); proto_unregister(&l2cap_proto); return err; } void l2cap_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "l2cap"); if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); -- cgit v1.2.3 From c6f5df16a2710e64090078dfbaa86c54a27c0874 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:29:49 +0900 Subject: Bluetooth: Added /proc/net/rfcomm via bt_procfs_init() Added /proc/net/rfcomm via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/rfcomm/sock.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c0..260821a2d6e 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void) return err; err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); - if (err < 0) + if (err < 0) { + BT_ERR("RFCOMM socket layer registration failed"); + goto error; + } + + err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create RFCOMM proc file"); + bt_sock_unregister(BTPROTO_RFCOMM); goto error; + } if (bt_debugfs) { rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, @@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void) return 0; error: - BT_ERR("RFCOMM socket layer registration failed"); proto_unregister(&rfcomm_proto); return err; } void __exit rfcomm_cleanup_sockets(void) { + bt_procfs_cleanup(&init_net, "rfcomm"); + debugfs_remove(rfcomm_sock_debugfs); if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) -- cgit v1.2.3 From de9b9212c7fd3e87608194f1c73fc06cd6cc7dfb Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 26 Jul 2012 01:30:12 +0900 Subject: Bluetooth: Added /proc/net/sco via bt_procfs_init() Added /proc/net/sco via bt_procfs_init(). Signed-off-by: Masatake YAMATO Signed-off-by: Gustavo Padovan --- net/bluetooth/sco.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 0ef5a78a889..caa109df645 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1023,6 +1023,13 @@ int __init sco_init(void) goto error; } + err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL); + if (err < 0) { + BT_ERR("Failed to create SCO proc file"); + bt_sock_unregister(BTPROTO_SCO); + goto error; + } + if (bt_debugfs) { sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, NULL, &sco_debugfs_fops); @@ -1041,6 +1048,8 @@ error: void __exit sco_exit(void) { + bt_procfs_cleanup(&init_net, "sco"); + debugfs_remove(sco_debugfs); if (bt_sock_unregister(BTPROTO_SCO) < 0) -- cgit v1.2.3 From 230fd16a2333fef9c012b054a127c7d157f7a7af Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:10 -0300 Subject: Bluetooth: Trivial refactoring This patch replaces the unlock-and-return statements by the goto statement. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0386e1e7227..e89d7f24136 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3364,8 +3364,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { BT_ERR("No memory for new connection"); - hci_dev_unlock(hdev); - return; + goto unlock; } conn->dst_type = ev->bdaddr_type; -- cgit v1.2.3 From b9b343d25484bbceaee454ab422daafb1c5eda96 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:11 -0300 Subject: Bluetooth: Fix hci_le_conn_complete_evt We need to check the 'Role' parameter from the LE Connection Complete Event in order to properly set 'out' and 'link_mode' fields from hci_conn structure. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e89d7f24136..8b13cccd50c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3368,6 +3368,11 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } conn->dst_type = ev->bdaddr_type; + + if (ev->role == LE_CONN_ROLE_MASTER) { + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + } } if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) -- cgit v1.2.3 From 847012c5e04544aef485dfec29c1c07dc90615a4 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:12 -0300 Subject: Bluetooth: Remove unneeded code This patch removes some unneeded code from hci_cs_le_create_conn. If the hci_conn is not found, it means this LE connection attempt was triggered by a thrid-party tool (e.g. hcitool). We should not create this new hci_conn in LE Create Connection command status event since it is already properly handled in LE Connection Complete event. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8b13cccd50c..27064beda10 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1638,16 +1638,6 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) hci_proto_connect_cfm(conn, status); hci_conn_del(conn); } - } else { - if (!conn) { - conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); - if (conn) { - conn->dst_type = cp->peer_addr_type; - conn->out = true; - } else { - BT_ERR("No memory for new connection"); - } - } } hci_dev_unlock(hdev); -- cgit v1.2.3 From f00a06ac14becc3d78fecdf2513cc23ee267a96b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:13 -0300 Subject: Bluetooth: Refactor hci_cs_le_create_conn This patch does some code refactoring in hci_cs_le_create_conn function. The hci_conn object is only needed in case of failure, therefore hdev locking and hci_conn lookup were moved to if-statement scope. Also, the conn->state check was removed since we should always close the connection if it fails. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 27064beda10..c0aa9f43699 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1623,24 +1623,26 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) if (!cp) return; - hci_dev_lock(hdev); + if (status) { + hci_dev_lock(hdev); - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); + if (!conn) { + hci_dev_unlock(hdev); + return; + } - BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), - conn); + BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), + conn); - if (status) { - if (conn && conn->state == BT_CONNECT) { - conn->state = BT_CLOSED; - mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, - conn->dst_type, status); - hci_proto_connect_cfm(conn, status); - hci_conn_del(conn); - } - } + conn->state = BT_CLOSED; + mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, + conn->dst_type, status); + hci_proto_connect_cfm(conn, status); + hci_conn_del(conn); - hci_dev_unlock(hdev); + hci_dev_unlock(hdev); + } } static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) -- cgit v1.2.3 From 0c95ab78be36e56ca69e36bc679f9dfd3d25f31e Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:14 -0300 Subject: Bluetooth: Find hci_conn by BT_CONNECT state This patch changes hci_cs_le_create_conn to perform hci_conn lookup by state instead of bdaddr. Since we can have only one LE connection in BT_CONNECT state, we can perform LE hci_conn lookup by state. This way, we don't rely on hci_sent_cmd_data helper to find the hci_conn object. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c0aa9f43699..8dc1f0fbe9c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1614,29 +1614,24 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) { - struct hci_cp_le_create_conn *cp; struct hci_conn *conn; BT_DBG("%s status 0x%2.2x", hdev->name, status); - cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); - if (!cp) - return; - if (status) { hci_dev_lock(hdev); - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); if (!conn) { hci_dev_unlock(hdev); return; } - BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), + BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), conn); conn->state = BT_CLOSED; - mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, + mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, status); hci_proto_connect_cfm(conn, status); hci_conn_del(conn); -- cgit v1.2.3 From b47a09b33a4612ace2958996ce6e0134be23d043 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:15 -0300 Subject: Bluetooth: Lookup hci_conn in hci_le_conn_complete_evt This patch does a trivial code refactoring in hci_conn lookup in hci_le_conn_complete_evt. It performs the hci_conn lookup at the begining of the function since it is used by both flows (error and success). Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8dc1f0fbe9c..92522b470f6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3333,8 +3333,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (ev->status) { - conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); if (!conn) goto unlock; @@ -3346,7 +3347,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) goto unlock; } - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); if (!conn) { conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { -- cgit v1.2.3 From cd17decbd9af41c9548bb108ccf156519f8253ec Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jul 2012 15:10:16 -0300 Subject: Bluetooth: Refactor in hci_le_conn_complete_evt This patch moves the hci_conn check to begining of hci_le_conn_ complete_evt in order to improve code's readability and better error handling. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 92522b470f6..32e21ad36a6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3334,19 +3334,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - - if (ev->status) { - if (!conn) - goto unlock; - - mgmt_connect_failed(hdev, &conn->dst, conn->type, - conn->dst_type, ev->status); - hci_proto_connect_cfm(conn, ev->status); - conn->state = BT_CLOSED; - hci_conn_del(conn); - goto unlock; - } - if (!conn) { conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { @@ -3362,6 +3349,15 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } } + if (ev->status) { + mgmt_connect_failed(hdev, &conn->dst, conn->type, + conn->dst_type, ev->status); + hci_proto_connect_cfm(conn, ev->status); + conn->state = BT_CLOSED; + hci_conn_del(conn); + goto unlock; + } + if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) mgmt_device_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type, 0, NULL, 0, NULL); -- cgit v1.2.3 From 57f5d0d1d9f8e59819cb0ab4b707364c54b5b2d1 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:54 -0300 Subject: Bluetooth: Remove some functions from being exported Some connection related functions are only used inside hci_conn.c so no need to have them exported. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5ad7da21747..724eea98081 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -59,7 +59,7 @@ static void hci_le_connect_cancel(struct hci_conn *conn) hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); } -void hci_acl_connect(struct hci_conn *conn) +static void hci_acl_connect(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -129,7 +129,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); } -void hci_add_sco(struct hci_conn *conn, __u16 handle) +static void hci_add_sco(struct hci_conn *conn, __u16 handle) { struct hci_dev *hdev = conn->hdev; struct hci_cp_add_sco cp; -- cgit v1.2.3 From 1aef866968223ddfd7268457b642a9233f0b8006 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:55 -0300 Subject: Bluetooth: Rename LE and ACL connection functions These names were causing much confusion, so we rename these functions that send HCI commands to be more similar in naming to the actual HCI commands that will be sent. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 724eea98081..c30c507345f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -30,7 +30,7 @@ #include #include -static void hci_le_connect(struct hci_conn *conn) +static void hci_le_create_connection(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; @@ -54,12 +54,12 @@ static void hci_le_connect(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); } -static void hci_le_connect_cancel(struct hci_conn *conn) +static void hci_le_create_connection_cancel(struct hci_conn *conn) { hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); } -static void hci_acl_connect(struct hci_conn *conn) +static void hci_acl_create_connection(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -103,7 +103,7 @@ static void hci_acl_connect(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); } -static void hci_acl_connect_cancel(struct hci_conn *conn) +static void hci_acl_create_connection_cancel(struct hci_conn *conn) { struct hci_cp_create_conn_cancel cp; @@ -245,9 +245,9 @@ static void hci_conn_timeout(struct work_struct *work) case BT_CONNECT2: if (conn->out) { if (conn->type == ACL_LINK) - hci_acl_connect_cancel(conn); + hci_acl_create_connection_cancel(conn); else if (conn->type == LE_LINK) - hci_le_connect_cancel(conn); + hci_le_create_connection_cancel(conn); } break; case BT_CONFIG: @@ -494,7 +494,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, return ERR_PTR(-ENOMEM); le->dst_type = bdaddr_to_le(dst_type); - hci_le_connect(le); + hci_le_create_connection(le); } le->pending_sec_level = sec_level; @@ -518,7 +518,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, acl->sec_level = BT_SECURITY_LOW; acl->pending_sec_level = sec_level; acl->auth_type = auth_type; - hci_acl_connect(acl); + hci_acl_create_connection(acl); } if (type == ACL_LINK) @@ -771,7 +771,7 @@ void hci_conn_check_pending(struct hci_dev *hdev) conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); if (conn) - hci_acl_connect(conn); + hci_acl_create_connection(conn); hci_dev_unlock(hdev); } -- cgit v1.2.3 From d04aef4cccf203fdfd1716e9ba458060cbab0928 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:56 -0300 Subject: Bluetooth: Refactor LE connection into its own function The code that handles LE connection is already quite separated from the rest of the connection procedure, so we can easily put it into its own. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 53 ++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c30c507345f..0a74399dde5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -470,6 +470,33 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) } EXPORT_SYMBOL(hci_get_route); +static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, + u8 dst_type, u8 sec_level, u8 auth_type) +{ + struct hci_conn *le; + + le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); + if (!le) { + le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (le) + return ERR_PTR(-EBUSY); + + le = hci_conn_add(hdev, LE_LINK, dst); + if (!le) + return ERR_PTR(-ENOMEM); + + le->dst_type = bdaddr_to_le(dst_type); + hci_le_create_connection(le); + } + + le->pending_sec_level = sec_level; + le->auth_type = auth_type; + + hci_conn_hold(le); + + return le; +} + /* Create SCO, ACL or LE connection. * Device _must_ be locked */ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, @@ -477,33 +504,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, { struct hci_conn *acl; struct hci_conn *sco; - struct hci_conn *le; BT_DBG("%s dst %s", hdev->name, batostr(dst)); - if (type == LE_LINK) { - le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (!le) { - le = hci_conn_hash_lookup_state(hdev, LE_LINK, - BT_CONNECT); - if (le) - return ERR_PTR(-EBUSY); - - le = hci_conn_add(hdev, LE_LINK, dst); - if (!le) - return ERR_PTR(-ENOMEM); - - le->dst_type = bdaddr_to_le(dst_type); - hci_le_create_connection(le); - } - - le->pending_sec_level = sec_level; - le->auth_type = auth_type; - - hci_conn_hold(le); - - return le; - } + if (type == LE_LINK) + return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { -- cgit v1.2.3 From db4742756ae2a836618cd5acf599522573589149 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Sat, 28 Jul 2012 22:35:59 -0300 Subject: Bluetooth: Refactor ACL connection into its own function The hci_connect() function was starting to get too complicated to be quickly understood. We can separate the creation of a new ACL connection into its own function. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 0a74399dde5..1d70e9fc7a4 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -497,18 +497,10 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, return le; } -/* Create SCO, ACL or LE connection. - * Device _must_ be locked */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 dst_type, __u8 sec_level, __u8 auth_type) +static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, + u8 sec_level, u8 auth_type) { struct hci_conn *acl; - struct hci_conn *sco; - - BT_DBG("%s dst %s", hdev->name, batostr(dst)); - - if (type == LE_LINK) - return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { @@ -526,6 +518,26 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, hci_acl_create_connection(acl); } + return acl; +} + +/* Create SCO, ACL or LE connection. + * Device _must_ be locked */ +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, + __u8 dst_type, __u8 sec_level, __u8 auth_type) +{ + struct hci_conn *acl; + struct hci_conn *sco; + + BT_DBG("%s dst %s", hdev->name, batostr(dst)); + + if (type == LE_LINK) + return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); + + acl = hci_connect_acl(hdev, dst, sec_level, auth_type); + if (IS_ERR(acl)) + return acl; + if (type == ACL_LINK) return acl; -- cgit v1.2.3 From b7d839bfff78a01705f3d7b0acd5257dc7b067c9 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:58 -0300 Subject: Bluetooth: Refactor SCO connection into its own function We can do the same that we did for the other link types, for SCO connections. The only thing that's worth noting is that as SCO links need an ACL link, this functions uses the function that adds an ACL link. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1d70e9fc7a4..de7df88a396 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -521,29 +521,19 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, return acl; } -/* Create SCO, ACL or LE connection. - * Device _must_ be locked */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 dst_type, __u8 sec_level, __u8 auth_type) +static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, + u8 sec_level, u8 auth_type) { struct hci_conn *acl; struct hci_conn *sco; - BT_DBG("%s dst %s", hdev->name, batostr(dst)); - - if (type == LE_LINK) - return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); - acl = hci_connect_acl(hdev, dst, sec_level, auth_type); if (IS_ERR(acl)) return acl; - if (type == ACL_LINK) - return acl; - - sco = hci_conn_hash_lookup_ba(hdev, type, dst); + sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst); if (!sco) { - sco = hci_conn_add(hdev, type, dst); + sco = hci_conn_add(hdev, SCO_LINK, dst); if (!sco) { hci_conn_put(acl); return ERR_PTR(-ENOMEM); @@ -572,6 +562,21 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, return sco; } +/* Create SCO, ACL or LE connection. */ +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, + __u8 dst_type, __u8 sec_level, __u8 auth_type) +{ + BT_DBG("%s dst %s", hdev->name, batostr(dst)); + + if (type == LE_LINK) + return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); + + if (type == ACL_LINK) + return hci_connect_acl(hdev, dst, sec_level, auth_type); + + return hci_connect_sco(hdev, dst, sec_level, auth_type); +} + /* Check link security requirement */ int hci_conn_check_link_mode(struct hci_conn *conn) { -- cgit v1.2.3 From 4cd2d98340b4f03d5532c30fdaeb451b035429cb Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:59 -0300 Subject: Bluetooth: Simplify a the connection type handling Now that we have separate ways of doing connections for each link type, we can do better than an "if" statement to handle each link type. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index de7df88a396..2e7b7765e0e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -568,13 +568,16 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, { BT_DBG("%s dst %s", hdev->name, batostr(dst)); - if (type == LE_LINK) + switch (type) { + case LE_LINK: return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); - - if (type == ACL_LINK) + case ACL_LINK: return hci_connect_acl(hdev, dst, sec_level, auth_type); + case SCO_LINK: + return hci_connect_sco(hdev, dst, sec_level, auth_type); + } - return hci_connect_sco(hdev, dst, sec_level, auth_type); + return ERR_PTR(-EINVAL); } /* Check link security requirement */ -- cgit v1.2.3 From e6dd548b9a3c7b3fcdd2fd97880abf7597e8334b Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:33:00 -0300 Subject: Bluetooth: Add type information to the hci_connect() debug statement Now that we have a "connect" function for each link type, we should be able to indentify which function is going to be called. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2e7b7765e0e..98670b1df17 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -566,7 +566,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 dst_type, __u8 sec_level, __u8 auth_type) { - BT_DBG("%s dst %s", hdev->name, batostr(dst)); + BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); switch (type) { case LE_LINK: -- cgit v1.2.3 From 09d5d4aa647367eeb42352a2bc9d438b9c703670 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 7 Aug 2012 18:05:04 +0300 Subject: Bluetooth: trivial: Shorten variable scope Make code more clear by moving sk and bt vars to the place where they are actually used. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/af_bluetooth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 58f9762b339..1b88fe41f4b 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -567,8 +567,6 @@ static void bt_seq_stop(struct seq_file *seq, void *v) static int bt_seq_show(struct seq_file *seq, void *v) { - struct sock *sk; - struct bt_sock *bt; struct bt_seq_state *s = seq->private; struct bt_sock_list *l = s->l; bdaddr_t src_baswapped, dst_baswapped; @@ -583,8 +581,8 @@ static int bt_seq_show(struct seq_file *seq, void *v) seq_putc(seq, '\n'); } else { - sk = sk_entry(v); - bt = bt_sk(sk); + struct sock *sk = sk_entry(v); + struct bt_sock *bt = bt_sk(sk); baswap(&src_baswapped, &bt->src); baswap(&dst_baswapped, &bt->dst); -- cgit v1.2.3 From 31f470738bf9fefc9399a45710c74322121119ac Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 7 Aug 2012 18:05:06 +0300 Subject: Bluetooth: trivial: Use preferred method for NULL check Use standard bluetooth way to check NULL pointer !var instead of var == NULL. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/af_bluetooth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1b88fe41f4b..9d49ee6d721 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -622,7 +622,7 @@ static int bt_seq_open(struct inode *inode, struct file *file) sk_list = PDE(inode)->data; s = __seq_open_private(file, &bt_seq_ops, sizeof(struct bt_seq_state)); - if (s == NULL) + if (!s) return -ENOMEM; s->l = sk_list; @@ -644,7 +644,7 @@ int bt_procfs_init(struct module* module, struct net *net, const char *name, sk_list->fops.release = seq_release_private; pde = proc_net_fops_create(net, name, 0, &sk_list->fops); - if (pde == NULL) + if (!pde) return -ENOMEM; pde->data = sk_list; -- cgit v1.2.3 From fa1bd91809d58b3c183611556219fafd93c08625 Mon Sep 17 00:00:00 2001 From: Mikel Astiz Date: Thu, 9 Aug 2012 09:52:29 +0200 Subject: Bluetooth: Fix minor coding style in hci_event.c Replace the status checks with the short form of the boolean expression. Signed-off-by: Mikel Astiz Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 32e21ad36a6..bfa9bcc0f5e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -303,7 +303,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (status != 0) { + if (status) { mgmt_write_scan_failed(hdev, param, status); hdev->discov_timeout = 0; goto done; @@ -925,7 +925,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); - if (rp->status != 0) + if (rp->status) goto unlock; cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); @@ -1893,7 +1893,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && (conn->type == ACL_LINK || conn->type == LE_LINK)) { - if (ev->status != 0) + if (ev->status) mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); else @@ -3262,7 +3262,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, * initiated the authentication. A traditional auth_complete * event gets always produced as initiator and is also mapped to * the mgmt_auth_failed event */ - if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) + if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); -- cgit v1.2.3 From f0d6a0ea330617454032d6e2ed48759858a44427 Mon Sep 17 00:00:00 2001 From: Mikel Astiz Date: Thu, 9 Aug 2012 09:52:30 +0200 Subject: Bluetooth: mgmt: Add device disconnect reason MGMT_EV_DEVICE_DISCONNECTED will now expose the disconnection reason to userland, distinguishing four possible values: 0x00 Reason not known or unspecified 0x01 Connection timeout 0x02 Connection terminated by local host 0x03 Connection terminated by remote host Note that the local/remote distinction just determines which side terminated the low-level connection, regardless of the disconnection of the higher-level profiles. This can sometimes be misleading and thus must be used with care. For example, some hardware combinations would report a locally initiated disconnection even if the user turned Bluetooth off in the remote side. Signed-off-by: Mikel Astiz Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 26 +++++++++++++++++++++++--- net/bluetooth/mgmt.c | 9 +++++---- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index bfa9bcc0f5e..48d730228c2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -29,6 +29,7 @@ #include #include +#include /* Handle HCI Event packets */ @@ -1875,6 +1876,22 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) } } +static u8 hci_to_mgmt_reason(u8 err) +{ + switch (err) { + case HCI_ERROR_CONNECTION_TIMEOUT: + return MGMT_DEV_DISCONN_TIMEOUT; + case HCI_ERROR_REMOTE_USER_TERM: + case HCI_ERROR_REMOTE_LOW_RESOURCES: + case HCI_ERROR_REMOTE_POWER_OFF: + return MGMT_DEV_DISCONN_REMOTE; + case HCI_ERROR_LOCAL_HOST_TERM: + return MGMT_DEV_DISCONN_LOCAL_HOST; + default: + return MGMT_DEV_DISCONN_UNKNOWN; + } +} + static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_disconn_complete *ev = (void *) skb->data; @@ -1893,12 +1910,15 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && (conn->type == ACL_LINK || conn->type == LE_LINK)) { - if (ev->status) + if (ev->status) { mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); - else + } else { + u8 reason = hci_to_mgmt_reason(ev->reason); + mgmt_device_disconnected(hdev, &conn->dst, conn->type, - conn->dst_type); + conn->dst_type, reason); + } } if (ev->status == 0) { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a3329cbd3e4..05d4b83a018 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3077,16 +3077,17 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) } int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type) + u8 link_type, u8 addr_type, u8 reason) { - struct mgmt_addr_info ev; + struct mgmt_ev_device_disconnected ev; struct sock *sk = NULL; int err; mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); - bacpy(&ev.bdaddr, bdaddr); - ev.type = link_to_bdaddr(link_type, addr_type); + bacpy(&ev.addr.bdaddr, bdaddr); + ev.addr.type = link_to_bdaddr(link_type, addr_type); + ev.reason = reason; err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk); -- cgit v1.2.3 From ab19516a50b375c11b9fa442954a43454a730950 Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Fri, 27 Jul 2012 23:51:22 +0530 Subject: Bluetooth: debug: Correct the PSM printing Earlier we were printing chan->psm before assigning any value. Signed-off-by: Syam Sidhardhan Acked-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9f8b29ef5b6..dae895e3ca7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1446,7 +1446,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, int err; BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), - dst_type, __le16_to_cpu(chan->psm)); + dst_type, __le16_to_cpu(psm)); hdev = hci_get_route(dst, src); if (!hdev) -- cgit v1.2.3 From 144ad33020a0af66fbb188ef3f13ca91c5326a69 Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Fri, 27 Jul 2012 23:51:21 +0530 Subject: Bluetooth: Use kref for l2cap channel reference counting This patch changes the struct l2cap_chan and associated code to use kref api for object refcounting and freeing. Suggested-by: Andrei Emeltchenko Signed-off-by: Jaganath Kanakkassery Signed-off-by: Syam Sidhardhan Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index dae895e3ca7..9732f03cfbe 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -406,7 +406,7 @@ struct l2cap_chan *l2cap_chan_create(void) chan->state = BT_OPEN; - atomic_set(&chan->refcnt, 1); + kref_init(&chan->kref); /* This flag is cleared in l2cap_chan_ready() */ set_bit(CONF_NOT_COMPLETE, &chan->conf_state); @@ -416,8 +416,10 @@ struct l2cap_chan *l2cap_chan_create(void) return chan; } -static void l2cap_chan_destroy(struct l2cap_chan *chan) +static void l2cap_chan_destroy(struct kref *kref) { + struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); + BT_DBG("chan %p", chan); write_lock(&chan_list_lock); @@ -429,17 +431,16 @@ static void l2cap_chan_destroy(struct l2cap_chan *chan) void l2cap_chan_hold(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); - atomic_inc(&c->refcnt); + kref_get(&c->kref); } void l2cap_chan_put(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); - if (atomic_dec_and_test(&c->refcnt)) - l2cap_chan_destroy(c); + kref_put(&c->kref, l2cap_chan_destroy); } void l2cap_chan_set_defaults(struct l2cap_chan *chan) -- cgit v1.2.3 From f91c8468df97d0ac18132eb38283524a74317901 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 17 Aug 2012 21:37:59 -0300 Subject: Bluetooth: Fix establishing ESCO links Commit 4cd2d98340b4f03d5532c30fdaeb451b035429cb "Bluetooth: Simplify the connection type handling" broke the creation of ESCO links. This patch adds a type parameter to hci_connect_sco() so it creates the connection of the right kind. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 98670b1df17..3e65c021df5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -521,8 +521,8 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, return acl; } -static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, - u8 sec_level, u8 auth_type) +static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, + bdaddr_t *dst, u8 sec_level, u8 auth_type) { struct hci_conn *acl; struct hci_conn *sco; @@ -531,9 +531,9 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, if (IS_ERR(acl)) return acl; - sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst); + sco = hci_conn_hash_lookup_ba(hdev, type, dst); if (!sco) { - sco = hci_conn_add(hdev, SCO_LINK, dst); + sco = hci_conn_add(hdev, type, dst); if (!sco) { hci_conn_put(acl); return ERR_PTR(-ENOMEM); @@ -574,7 +574,8 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, case ACL_LINK: return hci_connect_acl(hdev, dst, sec_level, auth_type); case SCO_LINK: - return hci_connect_sco(hdev, dst, sec_level, auth_type); + case ESCO_LINK: + return hci_connect_sco(hdev, type, dst, sec_level, auth_type); } return ERR_PTR(-EINVAL); -- cgit v1.2.3 From 6b536b5e5e1da32f3ba1e3f42c7bf2f80d37dc6b Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 31 Aug 2012 16:39:28 +0300 Subject: Bluetooth: Remove unneeded zero init hdev is allocated with kzalloc so zero initialization is not needed. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index fa974a19d36..86abe721f48 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1652,6 +1652,7 @@ struct hci_dev *hci_alloc_dev(void) INIT_LIST_HEAD(&hdev->link_keys); INIT_LIST_HEAD(&hdev->long_term_keys); INIT_LIST_HEAD(&hdev->remote_oob_data); + INIT_LIST_HEAD(&hdev->conn_hash.list); INIT_WORK(&hdev->rx_work, hci_rx_work); INIT_WORK(&hdev->cmd_work, hci_cmd_work); @@ -1674,7 +1675,6 @@ struct hci_dev *hci_alloc_dev(void) hci_init_sysfs(hdev); discovery_init(hdev); - hci_conn_hash_init(hdev); return hdev; } -- cgit v1.2.3 From 9472007c62ecc8f21daa2e1e252bf73b67e535fc Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 6 Sep 2012 15:05:43 +0300 Subject: Bluetooth: trivial: Make hci_chan_del return void Return code is not needed in hci_chan_del Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3e65c021df5..59f0344406c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -935,7 +935,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) return chan; } -int hci_chan_del(struct hci_chan *chan) +void hci_chan_del(struct hci_chan *chan) { struct hci_conn *conn = chan->conn; struct hci_dev *hdev = conn->hdev; @@ -948,8 +948,6 @@ int hci_chan_del(struct hci_chan *chan) skb_queue_purge(&chan->data_q); kfree(chan); - - return 0; } void hci_chan_list_flush(struct hci_conn *conn) -- cgit v1.2.3 From 93f71941c6d3ead73ca74d447b4007c6908f6eb5 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 6 Sep 2012 15:05:44 +0300 Subject: Bluetooth: trivial: Remove empty line Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 86abe721f48..9e6574a8e6e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -268,7 +268,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) BT_ERR("Unknown device type %d", hdev->dev_type); break; } - } static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) -- cgit v1.2.3 From e71dfabab03129182a955663cbd53406714d96c0 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 6 Sep 2012 15:05:46 +0300 Subject: Bluetooth: AMP: Add Read Data Block Size to amp_init Add Read Data Block Size HCI cmd to AMP initialization, then it makes possible to send data. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9e6574a8e6e..e4070517ff3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -231,6 +231,9 @@ static void amp_init(struct hci_dev *hdev) /* Read Local AMP Info */ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); + + /* Read Data Blk size */ + hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); } static void hci_init_req(struct hci_dev *hdev, unsigned long opt) -- cgit v1.2.3 From 92a25256f142d55e25f9959441cea6ddeabae57e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 6 Sep 2012 18:39:26 +0300 Subject: Bluetooth: mgmt: Implement support for passkey notification This patch adds support for Secure Simple Pairing with devices that have KeyboardOnly as their IO capability. Such devices will cause a passkey notification on our side and optionally also keypress notifications. Without this patch some keyboards cannot be paired using the mgmt interface. Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/mgmt.c | 17 ++++++++++++ 2 files changed, 84 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 48d730228c2..ccca88fc619 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3263,6 +3263,65 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); } +static void hci_user_passkey_notify_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_user_passkey_notify *ev = (void *) skb->data; + struct hci_conn *conn; + + BT_DBG("%s", hdev->name); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) + return; + + conn->passkey_notify = __le32_to_cpu(ev->passkey); + conn->passkey_entered = 0; + + if (test_bit(HCI_MGMT, &hdev->dev_flags)) + mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, + conn->dst_type, conn->passkey_notify, + conn->passkey_entered); +} + +static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_keypress_notify *ev = (void *) skb->data; + struct hci_conn *conn; + + BT_DBG("%s", hdev->name); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) + return; + + switch (ev->type) { + case HCI_KEYPRESS_STARTED: + conn->passkey_entered = 0; + return; + + case HCI_KEYPRESS_ENTERED: + conn->passkey_entered++; + break; + + case HCI_KEYPRESS_ERASED: + conn->passkey_entered--; + break; + + case HCI_KEYPRESS_CLEARED: + conn->passkey_entered = 0; + break; + + case HCI_KEYPRESS_COMPLETED: + return; + } + + if (test_bit(HCI_MGMT, &hdev->dev_flags)) + mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, + conn->dst_type, conn->passkey_notify, + conn->passkey_entered); +} + static void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { @@ -3627,6 +3686,14 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_user_passkey_request_evt(hdev, skb); break; + case HCI_EV_USER_PASSKEY_NOTIFY: + hci_user_passkey_notify_evt(hdev, skb); + break; + + case HCI_EV_KEYPRESS_NOTIFY: + hci_keypress_notify_evt(hdev, skb); + break; + case HCI_EV_SIMPLE_PAIR_COMPLETE: hci_simple_pair_complete_evt(hdev, skb); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 05d4b83a018..8e1ab59a9ce 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -99,6 +99,7 @@ static const u16 mgmt_events[] = { MGMT_EV_DEVICE_BLOCKED, MGMT_EV_DEVICE_UNBLOCKED, MGMT_EV_DEVICE_UNPAIRED, + MGMT_EV_PASSKEY_NOTIFY, }; /* @@ -3276,6 +3277,22 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, MGMT_OP_USER_PASSKEY_NEG_REPLY); } +int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u32 passkey, + u8 entered) +{ + struct mgmt_ev_passkey_notify ev; + + BT_DBG("%s", hdev->name); + + bacpy(&ev.addr.bdaddr, bdaddr); + ev.addr.type = link_to_bdaddr(link_type, addr_type); + ev.passkey = __cpu_to_le32(passkey); + ev.entered = entered; + + return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); +} + int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status) { -- cgit v1.2.3 From 23b3b1330abc643e1fbb7cfffcb6947e2583cff2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 6 Sep 2012 18:39:27 +0300 Subject: Bluetooth: Update management interface revision For each kernel release where commands or events are added to the management interface, the revision field should be increment by one. The increment should only happen once per kernel release and not for every command/event that gets added. The revision value is for informational purposes only, but this simple policy would make any future debugging a lot simple. Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8e1ab59a9ce..8934343be0e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -35,7 +35,7 @@ bool enable_hs; #define MGMT_VERSION 1 -#define MGMT_REVISION 1 +#define MGMT_REVISION 2 static const u16 mgmt_commands[] = { MGMT_OP_READ_INDEX_LIST, -- cgit v1.2.3