summaryrefslogtreecommitdiff
path: root/mesh/mesh-io-generic.c
diff options
context:
space:
mode:
authorInga Stotland <inga.stotland@intel.com>2020-05-15 10:41:56 -0700
committerBrian Gix <brian.gix@intel.com>2020-05-17 08:12:20 -0700
commit2cd067b8b74c34a76ec08d2ccf3396fa9d24e838 (patch)
tree680438345298e99612a5f6816a9728c4f35d3912 /mesh/mesh-io-generic.c
parentd18cb97bb5cada101a5786d34241508d85227ba4 (diff)
downloadbluez-2cd067b8b74c34a76ec08d2ccf3396fa9d24e838.tar.gz
mesh: Fix segfault caused by re-enabling of HCI controller
This fixes the crash that occurs when a controller used by bluetooth-meshd is removed and then added back again. Also, correctly restart scanning when the controller is re-enabled. Backtrace: 0x00005618e754d040 in ?? () 0x00005618e6e12d9a in io_ready_callback () at mesh/mesh.c:174 0x00005618e6e3d2c8 in l_queue_foreach () at ell/queue.c:441 0x00005618e6e37927 in request_complete () at src/shared/mgmt.c:261
Diffstat (limited to 'mesh/mesh-io-generic.c')
-rw-r--r--mesh/mesh-io-generic.c135
1 files changed, 79 insertions, 56 deletions
diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
index 2efd32f12..3ad130567 100644
--- a/mesh/mesh-io-generic.c
+++ b/mesh/mesh-io-generic.c
@@ -287,10 +287,86 @@ static void configure_hci(struct mesh_io_private *io)
sizeof(cmd), hci_generic_callback, NULL, NULL);
}
+static void scan_enable_rsp(const void *buf, uint8_t size,
+ void *user_data)
+{
+ uint8_t status = *((uint8_t *) buf);
+
+ if (status)
+ l_error("LE Scan enable failed (0x%02x)", status);
+}
+
+static void set_recv_scan_enable(const void *buf, uint8_t size,
+ void *user_data)
+{
+ struct mesh_io_private *pvt = user_data;
+ struct bt_hci_cmd_le_set_scan_enable cmd;
+
+ cmd.enable = 0x01; /* Enable scanning */
+ cmd.filter_dup = 0x00; /* Report duplicates */
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &cmd, sizeof(cmd), scan_enable_rsp, pvt, NULL);
+}
+
+static void scan_disable_rsp(const void *buf, uint8_t size,
+ void *user_data)
+{
+ struct bt_hci_cmd_le_set_scan_parameters cmd;
+ struct mesh_io_private *pvt = user_data;
+ uint8_t status = *((uint8_t *) buf);
+
+ if (status)
+ l_error("LE Scan disable failed (0x%02x)", status);
+
+ cmd.type = pvt->active ? 0x01 : 0x00; /* Passive/Active scanning */
+ cmd.interval = L_CPU_TO_LE16(0x0010); /* 10 ms */
+ cmd.window = L_CPU_TO_LE16(0x0010); /* 10 ms */
+ cmd.own_addr_type = 0x01; /* ADDR_TYPE_RANDOM */
+ cmd.filter_policy = 0x00; /* Accept all */
+
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
+ &cmd, sizeof(cmd),
+ set_recv_scan_enable, pvt, NULL);
+}
+
+static bool find_active(const void *a, const void *b)
+{
+ const struct pvt_rx_reg *rx_reg = a;
+
+ /* Mesh specific AD types do *not* require active scanning,
+ * so do not turn on Active Scanning on their account.
+ */
+ if (rx_reg->filter[0] < MESH_AD_TYPE_PROVISION ||
+ rx_reg->filter[0] > MESH_AD_TYPE_BEACON)
+ return true;
+
+ return false;
+}
+
+static void restart_scan(struct mesh_io_private *pvt)
+{
+ struct bt_hci_cmd_le_set_scan_enable cmd;
+
+ if (l_queue_isempty(pvt->rx_regs))
+ return;
+
+ pvt->active = l_queue_find(pvt->rx_regs, find_active, NULL);
+ cmd.enable = 0x00; /* Disable scanning */
+ cmd.filter_dup = 0x00; /* Report duplicates */
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &cmd, sizeof(cmd), scan_disable_rsp, pvt, NULL);
+}
+
static void hci_init(void *user_data)
{
struct mesh_io *io = user_data;
bool result = true;
+ bool restarted = false;
+
+ if (io->pvt->hci) {
+ restarted = true;
+ bt_hci_unref(io->pvt->hci);
+ }
io->pvt->hci = bt_hci_new_user_channel(io->pvt->index);
if (!io->pvt->hci) {
@@ -306,6 +382,9 @@ static void hci_init(void *user_data)
event_callback, io, NULL);
l_debug("Started mesh on hci %u", io->pvt->index);
+
+ if (restarted)
+ restart_scan(io->pvt);
}
if (io->pvt->ready_callback)
@@ -713,62 +792,6 @@ static bool find_by_filter(const void *a, const void *b)
return !memcmp(rx_reg->filter, filter, rx_reg->len);
}
-static void scan_enable_rsp(const void *buf, uint8_t size,
- void *user_data)
-{
- uint8_t status = *((uint8_t *) buf);
-
- if (status)
- l_error("LE Scan enable failed (0x%02x)", status);
-}
-
-static void set_recv_scan_enable(const void *buf, uint8_t size,
- void *user_data)
-{
- struct mesh_io_private *pvt = user_data;
- struct bt_hci_cmd_le_set_scan_enable cmd;
-
- cmd.enable = 0x01; /* Enable scanning */
- cmd.filter_dup = 0x00; /* Report duplicates */
- bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
- &cmd, sizeof(cmd), scan_enable_rsp, pvt, NULL);
-}
-
-static void scan_disable_rsp(const void *buf, uint8_t size,
- void *user_data)
-{
- struct bt_hci_cmd_le_set_scan_parameters cmd;
- struct mesh_io_private *pvt = user_data;
- uint8_t status = *((uint8_t *) buf);
-
- if (status)
- l_error("LE Scan disable failed (0x%02x)", status);
-
- cmd.type = pvt->active ? 0x01 : 0x00; /* Passive/Active scanning */
- cmd.interval = L_CPU_TO_LE16(0x0010); /* 10 ms */
- cmd.window = L_CPU_TO_LE16(0x0010); /* 10 ms */
- cmd.own_addr_type = 0x01; /* ADDR_TYPE_RANDOM */
- cmd.filter_policy = 0x00; /* Accept all */
-
- bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
- &cmd, sizeof(cmd),
- set_recv_scan_enable, pvt, NULL);
-}
-
-static bool find_active(const void *a, const void *b)
-{
- const struct pvt_rx_reg *rx_reg = a;
-
- /* Mesh specific AD types do *not* require active scanning,
- * so do not turn on Active Scanning on their account.
- */
- if (rx_reg->filter[0] < MESH_AD_TYPE_PROVISION ||
- rx_reg->filter[0] > MESH_AD_TYPE_BEACON)
- return true;
-
- return false;
-}
-
static bool recv_register(struct mesh_io *io, const uint8_t *filter,
uint8_t len, mesh_io_recv_func_t cb, void *user_data)
{