diff --git a/include/nuttx/wireless/bluetooth/bt_ioctl.h b/include/nuttx/wireless/bluetooth/bt_ioctl.h index 408435ccf0..f099d19072 100644 --- a/include/nuttx/wireless/bluetooth/bt_ioctl.h +++ b/include/nuttx/wireless/bluetooth/bt_ioctl.h @@ -69,7 +69,7 @@ /* Bluetooth network device IOCTL commands. */ -#if !defined(WL_BLUETOOTHCMDS) || WL_BLUETOOTHCMDS != 24 +#if !defined(WL_BLUETOOTHCMDS) || WL_BLUETOOTHCMDS != 26 # error Incorrect setting for number of Bluetooth IOCTL commands #endif @@ -202,6 +202,11 @@ #define SIOCBTGATTWR _WLIOC(WL_BLUETOOTHFIRST + 22) #define SIOCBTGATTWRGET _WLIOC(WL_BLUETOOTHFIRST + 23) +/* Connect/diconnect from a peer */ + +#define SIOCBTCONNECT _WLIOC(WL_BLUETOOTHFIRST + 24) +#define SIOCBTDISCONNECT _WLIOC(WL_BLUETOOTHFIRST + 25) + /* Definitions associated with struct btreg_s *******************************/ /* struct btreq_s union field accessors */ @@ -267,6 +272,8 @@ #define btr_wrpending btru.btgwrr.br_pending #define btr_wrresult btru.btgwrr.br_result +#define btr_rmtpeer btru.btcon.btcon_peer + /* btr_flags */ #define BTF_UP (1 << 0) /* Unit is up */ @@ -496,6 +503,16 @@ struct btreq_s /* Write result that accompanies SIOCBTGATTWRGET command */ struct bt_result_s btgwrr; /* OUT: Result of the write */ + + /* Read-only data that accompanies the SIOCBTCONNECT and + * SIOCBTDISCONNECT commands. + */ + + struct + { + bt_addr_le_t btcon_peer; /* IN: Peer address */ + } btcon; + } btru; }; diff --git a/include/nuttx/wireless/wireless.h b/include/nuttx/wireless/wireless.h index 01b7235b6f..dc81f6ce65 100644 --- a/include/nuttx/wireless/wireless.h +++ b/include/nuttx/wireless/wireless.h @@ -160,7 +160,7 @@ /* Reserved for Bluetooth network devices (see bt_ioctls.h) */ #define WL_BLUETOOTHFIRST (WL_NETFIRST + WL_NNETCMDS) -#define WL_BLUETOOTHCMDS (24) +#define WL_BLUETOOTHCMDS (26) #define WL_IBLUETOOTHCMD(cmd) (_WLIOCVALID(cmd) && \ _IOC_NR(cmd) >= WL_BLUETOOTHFIRST && \ _IOC_NR(cmd) < (WL_BLUETOOTHFIRST + WL_BLUETOOTHCMDS)) diff --git a/wireless/bluetooth/bt_conn.c b/wireless/bluetooth/bt_conn.c index 94870b2782..f3d65ef3fe 100644 --- a/wireless/bluetooth/bt_conn.c +++ b/wireless/bluetooth/bt_conn.c @@ -132,6 +132,7 @@ static int conn_tx_kthread(int argc, FAR char *argv[]) { FAR struct bt_conn_s *conn; FAR struct bt_buf_s *buf; + struct mq_attr attr; int ret; /* Get the connection instance */ @@ -189,6 +190,23 @@ static int conn_tx_kthread(int argc, FAR char *argv[]) do { buf = NULL; + + /* Make sure the thread is not blocked forever on an empty queue. + * SIOCBTCONNECT will fail if preceding SIOCBTDISCONNECT does not + * result in a successful termination of this thread. + */ + + ret = mq_getattr(conn->tx_queue, &attr); + if (ret != OK) + { + break; + } + + if (attr.mq_curmsgs == 0) + { + break; + } + ret = bt_queue_receive(conn->tx_queue, &buf); if (ret >= 0) { @@ -201,6 +219,9 @@ static int conn_tx_kthread(int argc, FAR char *argv[]) bt_conn_reset_rx_state(conn); wlinfo("handle %u exiting\n", conn->handle); + + /* Release reference taken when thread was created */ + bt_conn_release(conn); return EXIT_SUCCESS; } diff --git a/wireless/bluetooth/bt_ioctl.c b/wireless/bluetooth/bt_ioctl.c index 2cba4fb0cc..eb29110497 100644 --- a/wireless/bluetooth/bt_ioctl.c +++ b/wireless/bluetooth/bt_ioctl.c @@ -659,6 +659,56 @@ int btnet_ioctl(FAR struct net_driver_s *netdev, int cmd, unsigned long arg) switch (cmd) { + case SIOCBTCONNECT: + { + FAR struct bt_conn_s *conn; + conn = bt_conn_create_le(&btreq->btr_rmtpeer); + + if (!conn) + { + wlerr("Connection failed\n"); + ret = -ENOTCONN; + } + else + { + wlinfo("Connection pending\n"); + ret = OK; + } + } + break; + + case SIOCBTDISCONNECT: + { + FAR struct bt_conn_s *conn; + + conn = bt_conn_lookup_addr_le(&btreq->btr_rmtpeer); + if (!conn) + { + wlerr("Peer not connected\n"); + ret = -ENOTCONN; + } + else + { + ret = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (ret == -ENOTCONN) + { + wlerr("Already disconnected\n"); + } + else + { + /* Release reference taken in bt_conn_create_le */ + + bt_conn_release(conn); + ret = OK; + } + + /* Release reference taken in bt_conn_lookup_addr_le */ + + bt_conn_release(conn); + } + } + break; + /* SIOCGBTINFO: Get Bluetooth device Info. Given the device name, * fill in the btreq_s structure. *