From 71b8d408e279d369fea0c209fa254ee5a9cb7f0c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 19 Apr 2018 15:51:40 -0600 Subject: [PATCH] wireless/bluetooth: Add IOCTL commands to support MTU exchange. --- include/nuttx/wireless/bt_ioctl.h | 36 ++++++++++- include/nuttx/wireless/wireless.h | 2 +- wireless/bluetooth/bt_ioctl.c | 101 ++++++++++++++++++++++++++---- 3 files changed, 122 insertions(+), 17 deletions(-) diff --git a/include/nuttx/wireless/bt_ioctl.h b/include/nuttx/wireless/bt_ioctl.h index 7e4ac97a14..23193037ec 100644 --- a/include/nuttx/wireless/bt_ioctl.h +++ b/include/nuttx/wireless/bt_ioctl.h @@ -60,7 +60,7 @@ /* Bluetooth network device IOCTL commands. */ -#if !defined(WL_BLUETOOTHCMDS) || WL_BLUETOOTHCMDS != 18 +#if !defined(WL_BLUETOOTHCMDS) || WL_BLUETOOTHCMDS != 20 # error Incorrect setting for number of Bluetooth IOCTL commands #endif @@ -165,6 +165,10 @@ /* GATT * + * SIOCBTEXCHANGE + * Exchange MTUs + * SIOCBTEXRESULT + * Get the result of the MTU exchange * SIOCBTDISCOVER * Starts GATT discovery * SIOCBTDISCGET @@ -172,8 +176,10 @@ * SIOCBTDISCGET command was invoked. */ -#define SIOCBTDISCOVER _WLIOC(WL_BLUETOOTHFIRST + 16) -#define SIOCBTDISCGET _WLIOC(WL_BLUETOOTHFIRST + 17) +#define SIOCBTEXCHANGE _WLIOC(WL_BLUETOOTHFIRST + 16) +#define SIOCBTEXRESULT _WLIOC(WL_BLUETOOTHFIRST + 17) +#define SIOCBTDISCOVER _WLIOC(WL_BLUETOOTHFIRST + 18) +#define SIOCBTDISCGET _WLIOC(WL_BLUETOOTHFIRST + 19) /* Definitions associated with struct btreg_s *******************************/ /* struct btreq_s union field accessors */ @@ -206,6 +212,11 @@ #define btr_secaddr btru.btrse.btrse_secaddr #define btr_seclevel btru.btrse.btrse_seclevel +#define btr_expeer btru.btmx.btmx_expeer + +#define btr_expending btru.btmxr.mx_pending +#define btr_exresult btru.btmxr.mx_result + #define btr_dtype btru.btrds.btrds_dtype #define btr_dpeer btru.btrds.btrds_dpeer #define btr_duuid16 btru.btrds.btrds_duuid16 @@ -263,6 +274,14 @@ struct bt_discresonse_s uint8_t dr_perm; /* Permissions */ }; +/* MTU exchange state variables. */ + +struct bt_exchangeresult_s +{ + bool mx_pending; /* True: We have not yet received the result */ + uint8_t mx_result; /* The result of the MTU exchange */ +}; + /* Bluetooth statistics */ struct bt_stats_s @@ -362,6 +381,17 @@ struct btreq_s enum bt_security_e btrse_seclevel; /* Security level */ } btrse; + /* Read-only data that accompanies SIOCBTEXCHANGE command */ + + struct + { + bt_addr_le_t btmx_expeer; /* Peer address for MTU exchange */ + } btmx; + + /* Write result that accompanies SIOCBTEXRESULT command */ + + struct bt_exchangeresult_s btmxr; + /* Read-only data that accompanies SIOCBTDISCOVER command */ struct diff --git a/include/nuttx/wireless/wireless.h b/include/nuttx/wireless/wireless.h index 922d255e3c..f17c7335a5 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 (18) +#define WL_BLUETOOTHCMDS (20) #define WL_IBLUETOOTHCMD(cmd) (_WLIOCVALID(cmd) && \ _IOC_NR(cmd) >= WL_BLUETOOTHFIRST && \ _IOC_NR(cmd) < (WL_BLUETOOTHFIRST + WL_BLUETOOTHCMDS)) diff --git a/wireless/bluetooth/bt_ioctl.c b/wireless/bluetooth/bt_ioctl.c index 7d33eecf54..50b5dbbb6b 100644 --- a/wireless/bluetooth/bt_ioctl.c +++ b/wireless/bluetooth/bt_ioctl.c @@ -68,8 +68,8 @@ struct btnet_scanstate_s { sem_t bs_exclsem; /* Manages exclusive access */ - bool bs_scanning; /* True: Scanning in progress */ - uint8_t bs_head; /* Head of circular list (for removal) */ + volatile bool bs_scanning; /* True: Scanning in progress */ + volatile uint8_t bs_head; /* Head of circular list (for removal) */ uint8_t bs_tail; /* Tail of circular list (for addition) */ struct bt_scanresponse_s bs_rsp[CONFIG_BLUETOOTH_MAXSCANRESULT]; @@ -84,9 +84,9 @@ struct btnet_discoverstate_s struct bt_gatt_discover_params_s bd_params; struct bt_uuid_s bd_uuid; /* Discovery UUID */ sem_t bd_exclsem; /* Manages exclusive access */ - bool bd_discovering; /* True: Discovery in progress */ - uint8_t bd_head; /* Head of circular list (for removal) */ - uint8_t bd_tail; /* Tail of circular list (for addition) */ + volatile bool bd_discovering; /* True: Discovery in progress */ + volatile uint8_t bd_head; /* Head of circular list (for removal) */ + volatile uint8_t bd_tail; /* Tail of circular list (for addition) */ struct bt_discresonse_s bd_rsp[CONFIG_BLUETOOTH_MAXDISCOVER]; }; @@ -96,14 +96,15 @@ struct btnet_discoverstate_s ****************************************************************************/ /* At present only a single Bluetooth device is supported. So we can simply - * maintain the scan and the discovery state as globals. + * maintain the scan, MTU exchange, and discovery states as globals. * * NOTE: This limits to a single Bluetooth device with one concurrent scan - * action and one concurrent discovery action. + * action, one concurrent MTU exchange, and one concurrent discovery action. */ static struct btnet_scanstate_s g_scanstate; static struct btnet_discoverstate_s g_discoverstate; +static struct bt_exchangeresult_s g_exchangeresult; /**************************************************************************** * Private Functions @@ -219,15 +220,17 @@ static int btnet_scan_result(FAR struct bt_scanresponse_s *result, uint8_t head; uint8_t tail; uint8_t nrsp; + bool scanning; int ret; - wlinfo("Scanning? %s\n", g_scanstate.bs_scanning ? "YES" : "NO"); + scanning = g_scanstate.bs_scanning; + wlinfo("Scanning? %s\n", scanning ? "YES" : "NO"); /* Get exclusive access to the scan data while we are actively scanning. * The semaphore is uninitialized in other cases. */ - if (g_scanstate.bs_scanning) + if (scanning) { /* Get exclusive access to the scan data */ @@ -265,7 +268,7 @@ static int btnet_scan_result(FAR struct bt_scanresponse_s *result, g_scanstate.bs_head = head; - if (g_scanstate.bs_scanning) + if (scanning) { nxsem_post(&g_scanstate.bs_exclsem); } @@ -273,6 +276,28 @@ static int btnet_scan_result(FAR struct bt_scanresponse_s *result, return nrsp; } +/**************************************************************************** + * Name: bt_exchange_rsp + * + * Description: + * Result of MTU exchange. + * + * Input Parameters: + * conn - The address of the peer in the MTU exchange + * result - The result of the MTU exchange + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void bt_exchange_rsp(FAR struct bt_conn_s *conn, uint8_t result) +{ + wlinfo("Exchange %s\n", result == 0 ? "succeeded" : "failed"); + g_exchangeresult.mx_pending = true; + g_exchangeresult.mx_result = result; +} + /**************************************************************************** * Name: bt_discover_func * @@ -405,15 +430,17 @@ static int btnet_discover_result(FAR struct bt_discresonse_s *result, uint8_t head; uint8_t tail; uint8_t nrsp; + bool discovering; int ret; - wlinfo("Discovering? %s\n", g_discoverstate.bd_discovering ? "YES" : "NO"); + discovering = g_discoverstate.bd_discovering; + wlinfo("Discovering? %s\n", discovering ? "YES" : "NO"); /* Get exclusive access to the discovery data while we are actively * discovering. The semaphore is uninitialized in other cases. */ - if (g_discoverstate.bd_discovering) + if (discovering) { ret = nxsem_wait(&g_discoverstate.bd_exclsem); if (ret < 0) @@ -445,7 +472,7 @@ static int btnet_discover_result(FAR struct bt_discresonse_s *result, g_discoverstate.bd_head = head; - if (g_discoverstate.bd_discovering) + if (discovering) { nxsem_post(&g_discoverstate.bd_exclsem); } @@ -658,6 +685,54 @@ int btnet_ioctl(FAR struct net_driver_s *netdev, int cmd, unsigned long arg) } break; + /* SIOCBTEXCHANGE: Exchange MTUs */ + + case SIOCBTEXCHANGE: + { + /* Check if we are still waiting for the result of the last exchange */ + + if (g_exchangeresult.mx_pending) + { + wlwarn("WARNING: Last exchange not yet complete\n"); + ret = -EBUSY; + } + else + { + FAR struct bt_conn_s *conn; + + /* Get the connection associated with the provided LE address */ + + conn = bt_conn_lookup_addr_le(&btreq->btr_expeer); + if (conn == NULL) + { + wlwarn("WARNING: Peer not connected\n"); + ret = -ENOTCONN; + } + else + { + ret = bt_gatt_exchange_mtu(conn, bt_exchange_rsp); + if (ret == OK) + { + g_exchangeresult.mx_pending = true; + g_exchangeresult.mx_result = EBUSY; + } + + bt_conn_release(conn); + } + } + } + break; + + /* SIOCBTEXRESULT: Get the result of the MTU exchange */ + + case SIOCBTEXRESULT: + { + btreq->btr_expending = g_exchangeresult.mx_pending; + btreq->btr_exresult = g_exchangeresult.mx_result; + ret = OK; + } + break; + /* SIOCBTDISCOVER: Starts GATT discovery */ case SIOCBTDISCOVER: