All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: Add HCI_AUTO_CONN_DIRECT_REPORT_IND
@ 2014-09-26 14:50 Alfonso Acosta
  0 siblings, 0 replies; only message in thread
From: Alfonso Acosta @ 2014-09-26 14:50 UTC (permalink / raw)
  To: linux-bluetooth

HCI_AUTO_CONN_DIRECT_REPORT_IND (associated to a new autoconnect
action, 0x03) treats advertising reports like a combination of
HCI_AUTO_CONN_DIRECT and HCI_AUTO_CONN_REPORT:

* Autoconnects on ADV_DIRECT_IND reports.
* Notifies userland (MGMT_EV_DEVICE_FOUND) about ADV_IND reports.

This is useful to communicate with autoconnectable devices which
advertise meaningful ADV_IND reports.

HCI_AUTO_CONN_DIRECT_REPORT_IND requires being able to simultaneously
have a pending report and connection action. I merged pend_le_reports
and pend_le_conns into the new pend_le_actions in order to make that
possible while maintaining a unique list_head in hci_conn_parameters
(action). This results in simpler handling of pending actions.

Signed-off-by: Alfonso Acosta <fons@spotify.com>
---
 include/net/bluetooth/hci_core.h |  6 ++---
 net/bluetooth/hci_conn.c         |  2 +-
 net/bluetooth/hci_core.c         | 54 ++++++++++------------------------------
 net/bluetooth/hci_event.c        | 24 ++++++++++++------
 net/bluetooth/mgmt.c             | 30 ++++++++++++++++------
 5 files changed, 56 insertions(+), 60 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 37ff1ae..59393ea 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -317,8 +317,7 @@ struct hci_dev {
  struct list_head remote_oob_data;
  struct list_head le_white_list;
  struct list_head le_conn_params;
- struct list_head pend_le_conns;
- struct list_head pend_le_reports;
+ struct list_head pend_le_actions;

  struct hci_dev_stats stat;

@@ -461,6 +460,7 @@ struct hci_conn_params {
  HCI_AUTO_CONN_DISABLED,
  HCI_AUTO_CONN_REPORT,
  HCI_AUTO_CONN_DIRECT,
+ HCI_AUTO_CONN_DIRECT_REPORT_IND,
  HCI_AUTO_CONN_ALWAYS,
  HCI_AUTO_CONN_LINK_LOSS,
  } auto_connect;
@@ -881,7 +881,7 @@ void hci_conn_params_del(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_clear_all(struct hci_dev *hdev);
 void hci_conn_params_clear_disabled(struct hci_dev *hdev);

-struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
+struct hci_conn_params *hci_pend_le_action_lookup(struct hci_dev *hdev,
   bdaddr_t *addr,
   u8 addr_type);

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b9517bd..f65b705 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -596,7 +596,7 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
  struct hci_dev *hdev = conn->hdev;
  struct hci_conn_params *params;

- params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
+ params = hci_pend_le_action_lookup(&hdev->pend_le_actions, &conn->dst,
    conn->dst_type);
  if (params && params->conn) {
  hci_conn_drop(params->conn);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cb05d7f..980ec2e 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3631,7 +3631,7 @@ static bool is_connected(struct hci_dev *hdev,
bdaddr_t *addr, u8 type)
 }

 /* This function requires the caller holds hdev->lock */
-struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
+struct hci_conn_params *hci_pend_le_action_lookup(struct hci_dev *hdev,
   bdaddr_t *addr, u8 addr_type)
 {
  struct hci_conn_params *param;
@@ -3640,7 +3640,7 @@ struct hci_conn_params
*hci_pend_le_action_lookup(struct list_head *list,
  if (!hci_is_identity_address(addr, addr_type))
  return NULL;

- list_for_each_entry(param, list, action) {
+ list_for_each_entry(param, &hdev->pend_le_actions, action) {
  if (bacmp(&param->addr, addr) == 0 &&
     param->addr_type == addr_type)
  return param;
@@ -3706,13 +3706,14 @@ int hci_conn_params_set(struct hci_dev *hdev,
bdaddr_t *addr, u8 addr_type,
  hci_update_background_scan(hdev);
  break;
  case HCI_AUTO_CONN_REPORT:
- list_add(&params->action, &hdev->pend_le_reports);
+ case HCI_AUTO_CONN_DIRECT_REPORT_IND:
+ list_add(&params->action, &hdev->pend_le_actions);
  hci_update_background_scan(hdev);
  break;
  case HCI_AUTO_CONN_DIRECT:
  case HCI_AUTO_CONN_ALWAYS:
  if (!is_connected(hdev, addr, addr_type)) {
- list_add(&params->action, &hdev->pend_le_conns);
+ list_add(&params->action, &hdev->pend_le_actions);
  hci_update_background_scan(hdev);
  }
  break;
@@ -4020,8 +4021,7 @@ struct hci_dev *hci_alloc_dev(void)
  INIT_LIST_HEAD(&hdev->remote_oob_data);
  INIT_LIST_HEAD(&hdev->le_white_list);
  INIT_LIST_HEAD(&hdev->le_conn_params);
- INIT_LIST_HEAD(&hdev->pend_le_conns);
- INIT_LIST_HEAD(&hdev->pend_le_reports);
+ INIT_LIST_HEAD(&hdev->pend_le_actions);
  INIT_LIST_HEAD(&hdev->conn_hash.list);

  INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -5467,16 +5467,13 @@ static u8 update_white_list(struct hci_request *req)

  /* Go through the current white list programmed into the
  * controller one by one and check if that address is still
- * in the list of pending connections or list of devices to
- * report. If not present in either list, then queue the
- * command to remove it from the controller.
+ * in the list of pending actions list. If not present,
+ * then queue the command to remove it from the controller.
  */
  list_for_each_entry(b, &hdev->le_white_list, list) {
  struct hci_cp_le_del_from_white_list cp;

- if (hci_pend_le_action_lookup(&hdev->pend_le_conns,
-      &b->bdaddr, b->bdaddr_type) ||
-    hci_pend_le_action_lookup(&hdev->pend_le_reports,
+ if (hci_pend_le_action_lookup(hdev,
       &b->bdaddr, b->bdaddr_type)) {
  white_list_entries++;
  continue;
@@ -5490,7 +5487,7 @@ static u8 update_white_list(struct hci_request *req)
  }

  /* Since all no longer valid white list entries have been
- * removed, walk through the list of pending connections
+ * removed, walk through the list of pending actions
  * and ensure that any new device gets programmed into
  * the controller.
  *
@@ -5499,31 +5496,7 @@ static u8 update_white_list(struct hci_request *req)
  * just abort and return filer policy value to not use the
  * white list.
  */
- list_for_each_entry(params, &hdev->pend_le_conns, action) {
- if (hci_bdaddr_list_lookup(&hdev->le_white_list,
-   &params->addr, params->addr_type))
- continue;
-
- if (white_list_entries >= hdev->le_white_list_size) {
- /* Select filter policy to accept all advertising */
- return 0x00;
- }
-
- if (hci_find_irk_by_addr(hdev, &params->addr,
- params->addr_type)) {
- /* White list can not be used with RPAs */
- return 0x00;
- }
-
- white_list_entries++;
- add_to_white_list(req, params);
- }
-
- /* After adding all new pending connections, walk through
- * the list of pending reports and also add these to the
- * white list if there is still space.
- */
- list_for_each_entry(params, &hdev->pend_le_reports, action) {
+ list_for_each_entry(params, &hdev->pend_le_actions, action) {
  if (hci_bdaddr_list_lookup(&hdev->le_white_list,
    &params->addr, params->addr_type))
  continue;
@@ -5593,7 +5566,7 @@ static void
update_background_scan_complete(struct hci_dev *hdev, u8 status)
        "status 0x%2.2x", status);
 }

-/* This function controls the background scanning based on hdev->pend_le_conns
+/* This function controls the background scanning based on
hdev->pend_le_actions
  * list. If there are pending LE connection we start the background scanning,
  * otherwise we stop it.
  *
@@ -5623,8 +5596,7 @@ void hci_update_background_scan(struct hci_dev *hdev)

  hci_req_init(&req, hdev);

- if (list_empty(&hdev->pend_le_conns) &&
-    list_empty(&hdev->pend_le_reports)) {
+ if (list_empty(&hdev->pend_le_actions)) {
  /* If there is no pending LE connections or devices
  * to be scanned for, we should stop the background
  * scanning.
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8b0a2a6..3d669da 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2265,9 +2265,10 @@ static void hci_disconn_complete_evt(struct
hci_dev *hdev, struct sk_buff *skb)
  /* Fall through */

  case HCI_AUTO_CONN_DIRECT:
+ case HCI_AUTO_CONN_DIRECT_REPORT_IND:
  case HCI_AUTO_CONN_ALWAYS:
  list_del_init(&params->action);
- list_add(&params->action, &hdev->pend_le_conns);
+ list_add(&params->action, &hdev->pend_le_actions);
  hci_update_background_scan(hdev);
  break;

@@ -4292,13 +4293,13 @@ static void check_pending_le_conn(struct
hci_dev *hdev, bdaddr_t *addr,
  /* If we're not connectable only connect devices that we have in
  * our pend_le_conns list.
  */
- params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
-   addr, addr_type);
+ params = hci_pend_le_action_lookup(hdev, addr, addr_type);
  if (!params)
  return;

  switch (params->auto_connect) {
  case HCI_AUTO_CONN_DIRECT:
+ case HCI_AUTO_CONN_DIRECT_REPORT_IND:
  /* Only devices advertising with ADV_DIRECT_IND are
  * triggering a connection attempt. This is allowing
  * incoming connections from slave devices.
@@ -4351,6 +4352,7 @@ static void process_adv_report(struct hci_dev
*hdev, u8 type, bdaddr_t *bdaddr,
  struct smp_irk *irk;
  bool match;
  u32 flags;
+ struct hci_conn_params *params;

  /* Check if we need to convert to identity address */
  irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
@@ -4363,17 +4365,25 @@ static void process_adv_report(struct hci_dev
*hdev, u8 type, bdaddr_t *bdaddr,
  check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);

  /* Passive scanning shouldn't trigger any device found events,
- * except for devices marked as CONN_REPORT for which we do send
- * device found events.
+ * except for devices marked as CONN_REPORT or CONN_DIRECT_REPORT_IND
+ * for which we do send device found events.
  */
  if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
  if (type == LE_ADV_DIRECT_IND)
  return;

- if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
-       bdaddr, bdaddr_type))
+ params = hci_pend_le_action_lookup(hdev, bdaddr, bdaddr_type);
+ if (!params)
  return;

+ switch (params->auto_connect) {
+ case HCI_AUTO_CONN_REPORT:
+ case HCI_AUTO_CONN_DIRECT_REPORT_IND:
+  break;
+ default:
+  return;
+ }
+
  if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
  flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
  else
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index efb71b0..adb5248 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5241,7 +5241,7 @@ static int add_device(struct sock *sk, struct
hci_dev *hdev,
     MGMT_STATUS_INVALID_PARAMS,
     &cp->addr, sizeof(cp->addr));

- if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
+ if (cp->action > 0x03)
  return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
     MGMT_STATUS_INVALID_PARAMS,
     &cp->addr, sizeof(cp->addr));
@@ -5272,7 +5272,9 @@ static int add_device(struct sock *sk, struct
hci_dev *hdev,
  else
  addr_type = ADDR_LE_DEV_RANDOM;

- if (cp->action == 0x02)
+ if (cp->action == 0x03)
+ auto_conn = HCI_AUTO_CONN_DIRECT_REPORT_IND;
+ else if (cp->action == 0x02)
  auto_conn = HCI_AUTO_CONN_ALWAYS;
  else if (cp->action == 0x01)
  auto_conn = HCI_AUTO_CONN_DIRECT;
@@ -5838,10 +5840,9 @@ static void restart_le_actions(struct hci_dev *hdev)
  switch (p->auto_connect) {
  case HCI_AUTO_CONN_DIRECT:
  case HCI_AUTO_CONN_ALWAYS:
- list_add(&p->action, &hdev->pend_le_conns);
- break;
+ case HCI_AUTO_CONN_DIRECT_REPORT_IND:
  case HCI_AUTO_CONN_REPORT:
- list_add(&p->action, &hdev->pend_le_reports);
+ list_add(&p->action, &hdev->pend_le_actions);
  break;
  default:
  break;
@@ -6746,16 +6747,29 @@ void mgmt_device_found(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 link_type,
  char buf[512];
  struct mgmt_ev_device_found *ev = (void *) buf;
  size_t ev_size;
+ struct hci_conn_params *params;

  /* Don't send events for a non-kernel initiated discovery. With
- * LE one exception is if we have pend_le_reports > 0 in which
+ * LE one exception is if we have CONN_REPORT in pend_le_actions in which
  * case we're doing passive scanning and want these events.
  */
  if (!hci_discovery_active(hdev)) {
  if (link_type == ACL_LINK)
  return;
- if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
- return;
+ if (link_type == LE_LINK)
+ {
+ params = hci_conn_params_lookup(hdev, bdaddr, addr_type);
+ if(!params)
+  return;
+ switch(params->auto_connect)
+ {
+ case HCI_AUTO_CONN_REPORT:
+ case HCI_AUTO_CONN_DIRECT_REPORT_IND:
+  break;
+ default:
+  return;
+ }
+ }
  }

  /* Make sure that the buffer is big enough. The 5 extra bytes
-- 
1.9.1

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2014-09-26 14:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-26 14:50 [PATCH] Bluetooth: Add HCI_AUTO_CONN_DIRECT_REPORT_IND Alfonso Acosta

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.