Skip to content

Commit 16fc1b4

Browse files
ldubexiaoxiang781216
authored andcommitted
wireless/bluetooth: Support removable bluetooth modules.
This bluetooth stack remains in an inconsistent state when the bluetooth HCI module is removed. This change adds a bt_netdev_unregister function that can be used to clean up after a module is removed. Some global variables are also set to their default values.
1 parent af559a8 commit 16fc1b4

File tree

9 files changed

+238
-7
lines changed

9 files changed

+238
-7
lines changed

include/nuttx/wireless/bluetooth/bt_driver.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,21 @@ struct bt_driver_s
119119

120120
int bt_netdev_register(FAR struct bt_driver_s *btdev);
121121

122+
/****************************************************************************
123+
* Name: bt_netdev_unregister
124+
*
125+
* Description:
126+
* Unregister a network driver registered by bt_netdev_register.
127+
*
128+
* Input Parameters:
129+
* btdev - An instance of the low-level driver interface structure.
130+
*
131+
* Returned Value:
132+
* Zero (OK) is returned on success. Otherwise a negated errno value is
133+
* returned to indicate the nature of the failure.
134+
*
135+
****************************************************************************/
136+
137+
int bt_netdev_unregister(FAR struct bt_driver_s *btdev);
138+
122139
#endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_DRIVER_H */

wireless/bluetooth/bt_att.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,6 +1846,8 @@ void bt_att_initialize(void)
18461846
.disconnected = bt_att_disconnected,
18471847
};
18481848

1849+
memset(g_bt_att_pool, 0, sizeof(g_bt_att_pool));
1850+
18491851
bt_l2cap_chan_register(&chan);
18501852
}
18511853

wireless/bluetooth/bt_conn.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,3 +1078,22 @@ int bt_conn_le_conn_update(FAR struct bt_conn_s *conn, uint16_t min,
10781078

10791079
return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_UPDATE, buf);
10801080
}
1081+
1082+
/****************************************************************************
1083+
* Name: bt_conn_initialize
1084+
*
1085+
* Description:
1086+
* Initialize this module's private data.
1087+
*
1088+
* Input Parameters:
1089+
* None
1090+
*
1091+
* Returned Value:
1092+
* None
1093+
*
1094+
****************************************************************************/
1095+
1096+
void bt_conn_initialize(void)
1097+
{
1098+
memset(g_conns, 0, sizeof(g_conns));
1099+
}

wireless/bluetooth/bt_conn.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,6 @@ int bt_conn_le_conn_update(FAR struct bt_conn_s *conn, uint16_t min,
416416
uint16_t max, uint16_t latency,
417417
uint16_t timeout);
418418

419+
void bt_conn_initialize(void);
420+
419421
#endif /* __WIRELESS_BLUETOOTH_BT_CONN_H */

wireless/bluetooth/bt_hcicore.c

Lines changed: 120 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ static int hci_tx_kthread(int argc, FAR char *argv[])
985985

986986
wlinfo("started\n");
987987

988-
for (; ; )
988+
for (; g_btdev.tx_status == OK; )
989989
{
990990
FAR struct bt_buf_s *buf;
991991

@@ -1016,16 +1016,25 @@ static int hci_tx_kthread(int argc, FAR char *argv[])
10161016
g_btdev.sent_cmd = NULL;
10171017
}
10181018

1019-
g_btdev.sent_cmd = bt_buf_addref(buf);
1019+
/* Allow transmission if module is connected. */
10201020

1021-
wlinfo("Sending command %04x buf %p to driver\n",
1022-
buf->u.hci.opcode, buf);
1021+
if (g_btdev.tx_status == OK)
1022+
{
1023+
g_btdev.sent_cmd = bt_buf_addref(buf);
1024+
1025+
wlinfo("Sending command %04x buf %p to driver\n",
1026+
buf->u.hci.opcode, buf);
1027+
1028+
bt_send(btdev, buf);
1029+
}
10231030

1024-
bt_send(btdev, buf);
10251031
bt_buf_release(buf);
10261032
}
10271033

1028-
return EXIT_SUCCESS; /* Can't get here */
1034+
/* Acknowledge the termination request. */
1035+
1036+
g_btdev.tx_status = ESHUTDOWN;
1037+
return EXIT_SUCCESS;
10291038
}
10301039

10311040
/****************************************************************************
@@ -1425,6 +1434,64 @@ static int hci_initialize(void)
14251434
nxsem_init(&g_btdev.le_pkts_sem, 0, g_btdev.le_pkts);
14261435
return 0;
14271436
}
1437+
1438+
/****************************************************************************
1439+
* Name: cmd_queue_deinit
1440+
*
1441+
* Description:
1442+
* Threads, fifos and semaphores deinitialization
1443+
*
1444+
* Input Parameters:
1445+
* none
1446+
*
1447+
* Returned Value:
1448+
* None
1449+
*
1450+
****************************************************************************/
1451+
1452+
static void cmd_queue_deinit(void)
1453+
{
1454+
int ret;
1455+
FAR struct bt_buf_s *buf;
1456+
1457+
/* Tell the tx thread that the module is disconnected.
1458+
*/
1459+
1460+
g_btdev.tx_status = ENOTCONN;
1461+
1462+
/* Make sure the thread is not blocked by the semaphore.
1463+
*/
1464+
1465+
nxsem_post(&g_btdev.ncmd_sem);
1466+
1467+
/* We create and push a packet into the tx queue to unblock the thread.
1468+
* Any packet will do.
1469+
*/
1470+
1471+
buf = bt_hci_cmd_create(BT_HCI_OP_RESET, 0);
1472+
if (buf)
1473+
{
1474+
ret = bt_queue_send(&g_btdev.tx_queue, buf, BT_NORMAL_PRIO);
1475+
if (ret < 0)
1476+
{
1477+
wlerr("ERROR: bt_queue_send() failed: %d\n", ret);
1478+
}
1479+
}
1480+
1481+
/* Wait for the tx thread to exit gracefully. */
1482+
1483+
while (g_btdev.tx_status == ENOTCONN)
1484+
{
1485+
nxsig_usleep(1000);
1486+
}
1487+
1488+
/* Deinitialization */
1489+
1490+
nxsem_destroy(&g_btdev.ncmd_sem);
1491+
file_mq_close(&g_btdev.tx_queue);
1492+
work_cancel(HPWORK, &g_hp_work);
1493+
work_cancel(LPWORK, &g_lp_work);
1494+
}
14281495
#endif
14291496

14301497
/* threads, fifos and semaphores initialization */
@@ -1444,6 +1511,7 @@ static void cmd_queue_init(void)
14441511
nxsem_init(&g_btdev.ncmd_sem, 0, 1);
14451512

14461513
g_btdev.ncmd = 1;
1514+
g_btdev.tx_status = OK;
14471515
ret = kthread_create("BT HCI Tx", CONFIG_BLUETOOTH_TXCMD_PRIORITY,
14481516
CONFIG_BLUETOOTH_TXCMD_STACKSIZE,
14491517
hci_tx_kthread, NULL);
@@ -1497,6 +1565,14 @@ int bt_initialize(void)
14971565

14981566
wlinfo("btdev %p\n", btdev);
14991567

1568+
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
1569+
g_callback_list = NULL;
1570+
g_scan_dev_found_cb = NULL;
1571+
#endif
1572+
1573+
memset(&g_lp_rxlist, 0, sizeof(g_lp_rxlist));
1574+
memset(&g_hp_rxlist, 0, sizeof(g_hp_rxlist));
1575+
15001576
DEBUGASSERT(btdev != NULL);
15011577
bt_buf_initialize();
15021578

@@ -1505,6 +1581,9 @@ int bt_initialize(void)
15051581
ret = btdev->open(btdev);
15061582
if (ret < 0)
15071583
{
1584+
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
1585+
cmd_queue_deinit();
1586+
#endif
15081587
wlerr("ERROR: HCI driver open failed (%d)\n", ret);
15091588
return ret;
15101589
}
@@ -1513,6 +1592,7 @@ int bt_initialize(void)
15131592
ret = hci_initialize();
15141593
if (ret < 0)
15151594
{
1595+
cmd_queue_deinit();
15161596
wlerr("ERROR: hci_initialize failed: %d\n", ret);
15171597
return ret;
15181598
}
@@ -1523,6 +1603,38 @@ int bt_initialize(void)
15231603
return ret;
15241604
}
15251605

1606+
/****************************************************************************
1607+
* Name: bt_deinitialize
1608+
*
1609+
* Description:
1610+
* Deinitialize Bluetooth.
1611+
*
1612+
* Returned Value:
1613+
* Zero on success or (negative) error code otherwise.
1614+
*
1615+
****************************************************************************/
1616+
1617+
int bt_deinitialize(void)
1618+
{
1619+
#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST
1620+
FAR struct bt_driver_s *btdev = g_btdev.btdev;
1621+
1622+
cmd_queue_deinit();
1623+
1624+
/* Call the bluetooth HCI driver's close function if available. */
1625+
1626+
if (btdev)
1627+
{
1628+
if (btdev->close)
1629+
{
1630+
btdev->close(btdev);
1631+
}
1632+
}
1633+
#endif
1634+
1635+
return OK;
1636+
}
1637+
15261638
/****************************************************************************
15271639
* Name: bt_driver_register
15281640
*
@@ -1552,6 +1664,8 @@ int bt_driver_register(FAR struct bt_driver_s *btdev)
15521664
return -EALREADY;
15531665
}
15541666

1667+
memset(&g_btdev, 0, sizeof(g_btdev));
1668+
15551669
g_btdev.btdev = btdev;
15561670
return 0;
15571671
}

wireless/bluetooth/bt_hcicore.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ struct bt_dev_s
100100
sem_t le_pkts_sem;
101101
#endif
102102

103+
/* TX thread status */
104+
105+
int tx_status;
106+
103107
/* Number of commands controller can accept */
104108

105109
uint8_t ncmd;
@@ -255,6 +259,19 @@ struct bt_eir_s; /* Forward reference */
255259

256260
int bt_initialize(void);
257261

262+
/****************************************************************************
263+
* Name: bt_deinitialize
264+
*
265+
* Description:
266+
* Deinitialize Bluetooth.
267+
*
268+
* Returned Value:
269+
* Zero on success or (negative) error code otherwise.
270+
*
271+
****************************************************************************/
272+
273+
int bt_deinitialize(void);
274+
258275
/****************************************************************************
259276
* Name: bt_driver_register
260277
*

wireless/bluetooth/bt_l2cap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,10 @@ int bt_l2cap_init(void)
454454
.receive = le_sig,
455455
};
456456

457+
g_channels = NULL;
458+
g_default = NULL;
459+
460+
bt_conn_initialize();
457461
bt_att_initialize();
458462

459463
ret = bt_smp_initialize();

wireless/bluetooth/bt_netdev.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1315,9 +1315,63 @@ int bt_netdev_register(FAR struct bt_driver_s *btdev)
13151315

13161316
errout:
13171317

1318+
btnet_ifdown(netdev);
1319+
bt_driver_unregister(btdev);
1320+
13181321
/* Free memory and return the error */
13191322

1320-
kmm_free(priv);
1323+
kmm_free(btdev->bt_net);
1324+
btdev->bt_net = NULL;
1325+
return ret;
1326+
}
1327+
1328+
/****************************************************************************
1329+
* Name: bt_netdev_unregister
1330+
*
1331+
* Description:
1332+
* Unregister a network a driver registered by bt_netdev_register.
1333+
*
1334+
* Input Parameters:
1335+
* btdev - An instance of the low-level driver interface structure.
1336+
*
1337+
* Returned Value:
1338+
* Zero (OK) is returned on success. Otherwise a negated errno value is
1339+
* returned to indicate the nature of the failure.
1340+
*
1341+
****************************************************************************/
1342+
1343+
int bt_netdev_unregister(FAR struct bt_driver_s *btdev)
1344+
{
1345+
int ret;
1346+
FAR struct btnet_driver_s *priv;
1347+
1348+
if (!btdev)
1349+
{
1350+
return -EINVAL;
1351+
}
1352+
1353+
priv = (FAR struct btnet_driver_s *)btdev->bt_net;
1354+
if (!priv)
1355+
{
1356+
nerr("ERROR: bt_driver_s is probably not registered\n");
1357+
return -EINVAL;
1358+
}
1359+
1360+
btnet_ifdown(&priv->bd_dev.r_dev);
1361+
1362+
ret = netdev_unregister(&priv->bd_dev.r_dev);
1363+
if (ret < 0)
1364+
{
1365+
nerr("ERROR: netdev_unregister bfailed: %d\n", ret);
1366+
}
1367+
1368+
bt_deinitialize();
1369+
1370+
bt_driver_unregister(btdev);
1371+
1372+
kmm_free(btdev->bt_net);
1373+
btdev->bt_net = NULL;
1374+
13211375
return ret;
13221376
}
13231377

wireless/bluetooth/bt_smp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,8 @@ int bt_smp_initialize(void)
15841584
.encrypt_change = bt_smp_encrypt_change,
15851585
};
15861586

1587+
memset(g_smp_pool, 0, sizeof(g_smp_pool));
1588+
15871589
bt_l2cap_chan_register(&chan);
15881590

15891591
return smp_self_test();

0 commit comments

Comments
 (0)