From 701c8abbbb6486908829d0c3b7b7108604663a7e Mon Sep 17 00:00:00 2001 From: Lwazi Dube Date: Sat, 8 Dec 2018 12:58:27 -0600 Subject: [PATCH] wireless/bluetooth and include/nuttx/wireless/bluetooth: Remove unnecessary gatt ioctls --- include/nuttx/wireless/bluetooth/bt_gatt.h | 4 + include/nuttx/wireless/bluetooth/bt_ioctl.h | 98 +-- wireless/bluetooth/bt_conn.h | 4 + wireless/bluetooth/bt_gatt.c | 8 + wireless/bluetooth/bt_ioctl.c | 629 +++++++------------- 5 files changed, 256 insertions(+), 487 deletions(-) diff --git a/include/nuttx/wireless/bluetooth/bt_gatt.h b/include/nuttx/wireless/bluetooth/bt_gatt.h index 0ab23e98fe..c724051768 100644 --- a/include/nuttx/wireless/bluetooth/bt_gatt.h +++ b/include/nuttx/wireless/bluetooth/bt_gatt.h @@ -621,6 +621,10 @@ struct bt_gatt_discover_params_s /* Discover end handle */ uint16_t end_handle; + + /* Private data */ + + FAR void *p_data; }; /**************************************************************************** diff --git a/include/nuttx/wireless/bluetooth/bt_ioctl.h b/include/nuttx/wireless/bluetooth/bt_ioctl.h index f099d19072..7e41145b1d 100644 --- a/include/nuttx/wireless/bluetooth/bt_ioctl.h +++ b/include/nuttx/wireless/bluetooth/bt_ioctl.h @@ -176,31 +176,18 @@ * * SIOCBTEXCHANGE * Exchange MTUs - * SIOCBTEXRESULT - * Get the result of the MTU exchange * SIOCBTDISCOVER * Starts GATT discovery - * SIOCBTDISCGET - * Return discovery results buffered since the call time that the - * SIOCBTDISCGET command was invoked. * SIOCBTGATTRD * Initiate read of GATT data - * SIOCBTGATTRDGET - * Get the result of the GATT data read * SIOCBTGATTWR * Write GATT data - * SIOCBTGATTWRGET - * Get the result of the GATT data write */ #define SIOCBTEXCHANGE _WLIOC(WL_BLUETOOTHFIRST + 16) -#define SIOCBTEXRESULT _WLIOC(WL_BLUETOOTHFIRST + 17) -#define SIOCBTDISCOVER _WLIOC(WL_BLUETOOTHFIRST + 18) -#define SIOCBTDISCGET _WLIOC(WL_BLUETOOTHFIRST + 19) -#define SIOCBTGATTRD _WLIOC(WL_BLUETOOTHFIRST + 20) -#define SIOCBTGATTRDGET _WLIOC(WL_BLUETOOTHFIRST + 21) -#define SIOCBTGATTWR _WLIOC(WL_BLUETOOTHFIRST + 22) -#define SIOCBTGATTWRGET _WLIOC(WL_BLUETOOTHFIRST + 23) +#define SIOCBTDISCOVER _WLIOC(WL_BLUETOOTHFIRST + 17) +#define SIOCBTGATTRD _WLIOC(WL_BLUETOOTHFIRST + 18) +#define SIOCBTGATTWR _WLIOC(WL_BLUETOOTHFIRST + 19) /* Connect/diconnect from a peer */ @@ -241,36 +228,30 @@ #define btr_seclevel btru.btrse.btrse_seclevel #define btr_expeer btru.btmx.btmx_expeer - -#define btr_expending btru.btmxr.br_pending -#define btr_exresult btru.btmxr.br_result +#define btr_exresult btru.btmx.btmx_result #define btr_dtype btru.btrds.btrds_dtype #define btr_dpeer btru.btrds.btrds_dpeer #define btr_duuid16 btru.btrds.btrds_duuid16 #define btr_dstart btru.btrds.btrds_dstart #define btr_dend btru.btrds.btrds_dend - -#define btr_gnrsp btru.btrdg.btrdg_gnrsp -#define btr_grsp btru.btrdg.btrdg_grsp +#define btr_gnrsp btru.btrds.btrds_gnrsp +#define btr_grsp btru.btrds.btrds_grsp +#define btr_indx btru.btrds.btrds_indx #define btr_rdpeer btru.btgrd.btgrd_rdpeer #define btr_rdoffset btru.btgrd.btgrd_rdoffset #define btr_rdnhandles btru.btgrd.btgrd_rdnhandles #define btr_rdhandles btru.btgrd.btgrd_rdhandles - -#define btr_rdpending btru.btgrr.btgrr_rdpending -#define btr_rdresult btru.btgrr.btgrr_rdresult -#define btr_rdsize btru.btgrr.btgrr_rdsize -#define btr_rddata btru.btgrr.btgrr_rddata +#define btr_rdresult btru.btgrd.btgrd_rdresult +#define btr_rdsize btru.btgrd.btgrd_rdsize +#define btr_rddata btru.btgrd.btgrd_rddata #define btr_wrpeer btru.btgwr.btgwr_wrpeer #define btr_wrnbytes btru.btgwr.btgwr_wrnbytes #define btr_wrhandle btru.btgwr.btgwr_wrhandle #define btr_wrdata btru.btgwr.btgwr_wrdata - -#define btr_wrpending btru.btgwrr.br_pending -#define btr_wrresult btru.btgwrr.br_result +#define btr_wrresult btru.btgwr.btgwr_wrresult #define btr_rmtpeer btru.btcon.btcon_peer @@ -320,14 +301,6 @@ struct bt_discresonse_s uint8_t dr_perm; /* Permissions */ }; -/* General result of a pass/fail operation. */ - -struct bt_result_s -{ - bool br_pending; /* True: The operation is not yet complete */ - uint8_t br_result; /* The result of the operation */ -}; - /* Bluetooth statistics */ struct bt_stats_s @@ -434,13 +407,10 @@ struct btreq_s struct { bt_addr_le_t btmx_expeer; /* IN: Peer address for MTU exchange */ + uint8_t btmx_result; /* OUT: The result of the operation */ } btmx; - /* Write result that accompanies SIOCBTEXRESULT command */ - - struct bt_result_s btmxr; - - /* Read-only data that accompanies SIOCBTDISCOVER command */ + /* Write-able data that accompanies SIOCBTDISCOVER command */ struct { @@ -450,23 +420,13 @@ struct btreq_s uint16_t btrds_duuid16; /* IN: Discover UUID type */ uint16_t btrds_dstart; /* IN: Discover start handle */ uint16_t btrds_dend; /* IN: Discover end handle */ + uint8_t btrds_gnrsp; /* IN: Max number of responses + * OUT: Actual number of responses */ + FAR struct bt_discresonse_s *btrds_grsp; + int btrds_indx; /* IN: Index of first entry */ } btrds; - /* Write-able structure that accompanies the SIOCBTDISCGET command. */ - - struct - { - uint8_t btrdg_gnrsp; /* IN: Max number of responses - * OUT: Actual number of responses */ - - /* Reference to a beginning of an array in user memory in which to - * return the discovered data. The size of the array is btrdg_gnrsp. - */ - - FAR struct bt_discresonse_s *btrdg_grsp; - } btrdg; - - /* Read-only data that accompanies the SIOCBTGATTRD command */ + /* Write-able data that accompanies the SIOCBTGATTRD command */ struct { @@ -474,20 +434,13 @@ struct btreq_s uint8_t btgrd_rdnhandles; /* IN: Number of handles in array */ uint16_t btgrd_rdoffset; /* IN: Offset (Only for read single) */ uint16_t btgrd_rdhandles[HCI_GATT_MAXHANDLES]; + uint8_t btgrd_rdresult; /* OUT: Result of the read */ + uint8_t btgrd_rdsize; /* IN: Sizeof rddata[] + * OUT: Number of valid bytes */ + FAR uint8_t *btgrd_rddata; /* OUT: Values returned by read */ } btgrd; - /* Write-able data that accompanies the SIOCBTGATTRDGET command */ - - struct - { - bool btgrr_rdpending; /* OUT: True: Read not yet complete */ - uint8_t btgrr_rdresult; /* OUT: Result of the read */ - uint8_t btgrr_rdsize; /* IN: Sizeof rddata[] - * OUT: Number of valid bytes */ - FAR uint8_t *btgrr_rddata; /* OUT: Values returned by read */ - } btgrr; - - /* Read-only data that accompanies the SIOCBTGATTWR command. + /* Write-able data that accompanies the SIOCBTGATTWR command. * NOTE: The write data provided by the caller is not buffered * and must persist until the completion of the write. */ @@ -498,12 +451,9 @@ struct btreq_s uint8_t btgwr_wrnbytes; /* IN: Number of bytes to write */ uint16_t btgwr_wrhandle; /* IN: GATT handle */ FAR uint8_t btgwr_wrdata[HCI_GATTWR_DATA]; /* IN: Data to be written */ + uint8_t btgwr_wrresult; /* OUT: The result of the operation */ } btgwr; - /* 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. */ diff --git a/wireless/bluetooth/bt_conn.h b/wireless/bluetooth/bt_conn.h index 7a283ada91..dbf2856e76 100644 --- a/wireless/bluetooth/bt_conn.h +++ b/wireless/bluetooth/bt_conn.h @@ -108,6 +108,10 @@ struct bt_conn_s uint8_t le_conn_interval; bt_atomic_t ref; enum bt_conn_state_e state; + + /* Temporary data used by ioctl */ + + void *p_iostate; }; /**************************************************************************** diff --git a/wireless/bluetooth/bt_gatt.c b/wireless/bluetooth/bt_gatt.c index 1b50c5a5b5..7b614a902e 100644 --- a/wireless/bluetooth/bt_gatt.c +++ b/wireless/bluetooth/bt_gatt.c @@ -855,6 +855,14 @@ static void att_read_type_rsp(FAR struct bt_conn_s *conn, uint8_t err, goto done; } + /* Next characteristic shall be after current value handle */ + + params->start_handle = handle; + if (params->start_handle < UINT16_MAX) + { + params->start_handle++; + } + /* Stop if over the requested range */ if (params->start_handle >= params->end_handle) diff --git a/wireless/bluetooth/bt_ioctl.c b/wireless/bluetooth/bt_ioctl.c index eb29110497..7c14e01bd8 100644 --- a/wireless/bluetooth/bt_ioctl.c +++ b/wireless/bluetooth/bt_ioctl.c @@ -83,23 +83,25 @@ 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 */ - 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]; + sem_t bd_donesem; /* Manages exclusive access */ }; /* GATT read state variables. */ struct btnet_rdstate_s { - bool rd_pending; /* True: result not yet received */ + struct btreq_s *rd_btreq; uint8_t rd_result; /* The result of the read */ - uint8_t rd_head; /* Start of data to read */ - uint8_t rd_tail; /* End data to read */ - uint8_t rd_data[HCI_GATTRD_DATA]; /* Data read */ + sem_t rd_donesem; /* Manages exclusive access */ +}; + +/* GATT write state variables. */ + +struct btnet_wrstate_s +{ + struct btreq_s *wr_btreq; + uint8_t wr_result; /* The result of the read */ + sem_t wr_donesem; /* Manages exclusive access */ }; /**************************************************************************** @@ -126,10 +128,6 @@ struct btnet_rdstate_s */ static struct btnet_scanstate_s g_scanstate; -static struct btnet_discoverstate_s g_discoverstate; -static struct bt_result_s g_exchangeresult; -static struct btnet_rdstate_s g_rdstate; -static struct bt_result_s g_gattwrresult; /**************************************************************************** * Private Functions @@ -294,9 +292,9 @@ static int btnet_scan_result(FAR struct bt_scanresponse_s *result, g_scanstate.bs_head = head; if (scanning) - { + { nxsem_post(&g_scanstate.bs_exclsem); - } + } return nrsp; } @@ -318,9 +316,13 @@ static int btnet_scan_result(FAR struct bt_scanresponse_s *result, static void btnet_exchange_rsp(FAR struct bt_conn_s *conn, uint8_t result) { - wlinfo("Exchange %s\n", result == 0 ? "succeeded" : "failed"); - g_exchangeresult.br_pending = false; - g_exchangeresult.br_result = result; + FAR struct btnet_wrstate_s *pstate = conn->p_iostate; + FAR struct btreq_s *btreq = pstate->wr_btreq; + + wlinfo("%s\n", result == 0 ? "succeeded" : "failed"); + + btreq->btr_exresult = result; + nxsem_post(&pstate->wr_donesem); } /**************************************************************************** @@ -342,62 +344,21 @@ static void btnet_exchange_rsp(FAR struct bt_conn_s *conn, uint8_t result) static uint8_t btnet_discover_func(FAR const struct bt_gatt_attr_s *attr, FAR void *arg) { - uint8_t nexttail; - uint8_t head; - uint8_t tail; - int ret; + FAR struct bt_gatt_discover_params_s *params = arg; + FAR struct btreq_s *btreq = (FAR struct btreq_s *)(params->p_data); - wlinfo("Discovered handle %u\n", attr->handle); + wlinfo("Discovered handle %x\n", attr->handle); - if (!g_discoverstate.bd_discovering) + if (btreq->btr_indx >= btreq->btr_gnrsp) { - wlerr("ERROR: Results received while not discovering\n"); + wlerr("ERROR: No space for results\n"); return BT_GATT_ITER_STOP; } - /* Get exclusive access to the discovered data */ + btreq->btr_grsp[btreq->btr_indx].dr_handle = attr->handle; + btreq->btr_grsp[btreq->btr_indx].dr_perm = attr->perm; + btreq->btr_indx++; - while ((ret = nxsem_wait(&g_discoverstate.bd_exclsem)) < 0) - { - DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); - if (ret != -EINTR) - { - return BT_GATT_ITER_STOP; - } - } - - /* Add the discovered data to the cache */ - - tail = g_discoverstate.bd_tail; - nexttail = tail + 1; - - if (nexttail >= CONFIG_BLUETOOTH_MAXSCANRESULT) - { - nexttail = 0; - } - - /* Is the circular buffer full? */ - - head = g_discoverstate.bd_head; - if (nexttail == head) - { - wlerr("ERROR: Too many handles discovered. Data lost.\n"); - - if (++head >= CONFIG_BLUETOOTH_MAXSCANRESULT) - { - head = 0; - } - - g_discoverstate.bd_head = head; - } - - /* Save the newly discovered handle */ - - g_discoverstate.bd_rsp[tail].dr_handle = attr->handle; - g_discoverstate.bd_rsp[tail].dr_perm = attr->perm; - g_discoverstate.bd_tail = nexttail; - - nxsem_post(&g_discoverstate.bd_exclsem); return BT_GATT_ITER_CONTINUE; } @@ -418,92 +379,11 @@ static uint8_t btnet_discover_func(FAR const struct bt_gatt_attr_s *attr, static void btnet_discover_destroy(FAR void *arg) { - FAR struct bt_gatt_discover_params *params = arg; + struct btnet_discoverstate_s *pstate = arg; - /* There is nothing that needs to be down here. The parameters were - * allocated on the stack and are long gone. - */ + wlinfo("Discover destroy\n"); - wlinfo("Discover destroy. params %p\n", params); - DEBUGASSERT(params != NULL && g_discoverstate.bd_discovering); - UNUSED(params); - - memset(&g_discoverstate.bd_params, 0, sizeof(struct btnet_discoverstate_s)); - nxsem_destroy(&g_discoverstate.bd_exclsem); - g_discoverstate.bd_discovering = false; -} - -/**************************************************************************** - * Name: btnet_discover_result - * - * Description: - * This function implements the SIOCBTDISCGET IOCTL command. It returns - * the current, buffered discovered handles. - * - * Input Parameters: - * result - Location to return the discovery result data - * maxrsp - The maximum number of responses that can be returned. - * - * Returned Value: - * On success, the actual number of discovery results obtain is returned. A - * negated errno value is returned on any failure. - * - ****************************************************************************/ - -static int btnet_discover_result(FAR struct bt_discresonse_s *result, - uint8_t maxrsp) -{ - uint8_t head; - uint8_t tail; - uint8_t nrsp; - bool discovering; - int ret; - - 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 (discovering) - { - ret = nxsem_wait(&g_discoverstate.bd_exclsem); - if (ret < 0) - { - DEBUGASSERT(ret == -EINTR || ret == -ECANCELED); - return ret; - } - } - - /* Copy all available results */ - - head = g_discoverstate.bd_head; - tail = g_discoverstate.bd_tail; - - for (nrsp = 0; nrsp < maxrsp && head != tail; nrsp++) - { - /* Copy data from the head index into the user buffer */ - - result[nrsp].dr_handle = g_discoverstate.bd_rsp[head].dr_handle; - result[nrsp].dr_perm = g_discoverstate.bd_rsp[head].dr_perm; - - /* Increment the head index */ - - if (++head >= CONFIG_BLUETOOTH_MAXDISCOVER) - { - head = 0; - } - } - - g_discoverstate.bd_head = head; - - if (discovering) - { - nxsem_post(&g_discoverstate.bd_exclsem); - } - - return nrsp; + nxsem_post(&pstate->bd_donesem); } /**************************************************************************** @@ -526,76 +406,26 @@ static int btnet_discover_result(FAR struct bt_discresonse_s *result, static void btnet_read_callback(FAR struct bt_conn_s *conn, int result, FAR const void *data, uint16_t length) { - wlinfo("Read complete: result %d length %u\n", result, length); + FAR struct btnet_rdstate_s *pstate = conn->p_iostate; + FAR struct btreq_s *btreq = pstate->rd_btreq; - DEBUGASSERT(conn != NULL && g_rdstate.rd_pending); + wlinfo("Read complete: result %d length %u\n", result, length); if (length > HCI_GATTRD_DATA) { - g_rdstate.rd_result = ENFILE; + wlerr("ERROR: Unexpected length %u, result = %d\n", length, result); + btreq->btr_rdresult = ENFILE; } else { DEBUGASSERT((unsigned int)result < UINT8_MAX); - g_rdstate.rd_result = result; - g_rdstate.rd_head = 0; - g_rdstate.rd_tail = length; - memcpy(g_rdstate.rd_data, data, length); + btreq->btr_rdresult = result; + btreq->btr_rdsize = length; + memcpy(btreq->btr_rddata, data, length); } - g_rdstate.rd_pending = false; -} - -/**************************************************************************** - * Name: btnet_read_result - * - * Description: - * Handle network IOCTL commands directed to this device. - * - * Input Parameters: - * btreq - IOCTL command data - * - * Returned Value: - * OK on success; Negated errno on failure. - * - ****************************************************************************/ - -static int btnet_read_result(FAR struct btreq_s *btreq) -{ - int head; - int rdlen; - - DEBUGASSERT(btreq != NULL && btreq->btr_rddata != NULL); - - /* Is the read complete? */ - - btreq->btr_rdpending = g_rdstate.rd_pending; - if (!g_rdstate.rd_pending) - { - return -EBUSY; - } - - /* Yes... return the read data */ - - head = g_rdstate.rd_head; - if (head >= g_rdstate.rd_tail) - { - return -ENODATA; - } - - rdlen = btreq->btr_rdsize; - if (rdlen + head >= g_rdstate.rd_tail) - { - rdlen = g_rdstate.rd_tail - head; - } - - btreq->btr_rdresult = g_rdstate.rd_result; - btreq->btr_rdsize = rdlen; - memcpy(btreq->btr_rddata, &g_rdstate.rd_data[head], rdlen); - - g_rdstate.rd_head = head + rdlen; - return OK; + nxsem_post(&pstate->rd_donesem); } /**************************************************************************** @@ -615,9 +445,13 @@ static int btnet_read_result(FAR struct btreq_s *btreq) static void bnet_write_callback(FAR struct bt_conn_s *conn, uint8_t result) { - wlinfo("Exchange %s\n", result == 0 ? "succeeded" : "failed"); - g_gattwrresult.br_pending = false; - g_gattwrresult.br_result = result; + FAR struct btnet_wrstate_s *pstate = conn->p_iostate; + FAR struct btreq_s *btreq = pstate->wr_btreq; + + wlinfo("%s\n", result == 0 ? "succeeded" : "failed"); + + btreq->btr_wrresult = result; + nxsem_post(&pstate->wr_donesem); } /**************************************************************************** @@ -879,285 +713,254 @@ int btnet_ioctl(FAR struct net_driver_s *netdev, int cmd, unsigned long arg) case SIOCBTEXCHANGE: { - /* Check if we are still waiting for the result of the last exchange */ + FAR struct bt_conn_s *conn; - if (g_exchangeresult.br_pending) + /* Get the connection associated with the provided LE address */ + + conn = bt_conn_lookup_addr_le(&btreq->btr_expeer); + if (conn == NULL) { - wlwarn("WARNING: Last exchange not yet complete\n"); - ret = -EBUSY; + wlwarn("WARNING: Peer not connected\n"); + ret = -ENOTCONN; } else { - FAR struct bt_conn_s *conn; + struct btnet_wrstate_s wrstate; - /* Get the connection associated with the provided LE address */ + memset(&wrstate, 0, sizeof(wrstate)); + wrstate.wr_btreq = btreq; + conn->p_iostate = &wrstate; + nxsem_init(&wrstate.wr_donesem, 0, 0); - conn = bt_conn_lookup_addr_le(&btreq->btr_expeer); - if (conn == NULL) + btreq->btr_wrresult = EBUSY; + + ret = bt_gatt_exchange_mtu(conn, btnet_exchange_rsp); + if (ret < 0) { - wlwarn("WARNING: Peer not connected\n"); - ret = -ENOTCONN; + wlerr("ERROR: Exchange operation failed: %d\n", ret); } else { - ret = bt_gatt_exchange_mtu(conn, btnet_exchange_rsp); - if (ret == OK) - { - g_exchangeresult.br_pending = true; - g_exchangeresult.br_result = EBUSY; - } + /* Wait for callback to complete the exchange */ - bt_conn_release(conn); + ret = nxsem_wait(&wrstate.wr_donesem); } + + nxsem_destroy(&wrstate.wr_donesem); + + bt_conn_release(conn); } } break; - /* SIOCBTEXRESULT: Get the result of the MTU exchange */ - - case SIOCBTEXRESULT: - { - btreq->btr_expending = g_exchangeresult.br_pending; - btreq->btr_exresult = g_exchangeresult.br_result; - ret = OK; - } - break; - /* SIOCBTDISCOVER: Starts GATT discovery */ case SIOCBTDISCOVER: { FAR struct bt_conn_s *conn; - /* Check if discovery is already in progress */ + /* Get the connection associated with the provided LE address */ - if (g_discoverstate.bd_discovering) + conn = bt_conn_lookup_addr_le(&btreq->btr_dpeer); + if (conn == NULL) { - wlwarn("WARNING: Discovery is already in progress\n"); - ret = -EBUSY; + wlwarn("WARNING: Peer not connected\n"); + ret = -ENOTCONN; } else { - /* Get the connection associated with the provided LE address */ + struct btnet_discoverstate_s dstate; + FAR struct bt_gatt_discover_params_s *params; + memset(&dstate, 0, sizeof(dstate)); - conn = bt_conn_lookup_addr_le(&btreq->btr_dpeer); - if (conn == NULL) + /* Set up the query */ + + dstate.bd_uuid.type = BT_UUID_16; + dstate.bd_uuid.u.u16 = btreq->btr_duuid16; + + params = &dstate.bd_params; + params->func = btnet_discover_func; + params->destroy = btnet_discover_destroy; + params->start_handle = btreq->btr_dstart; + params->end_handle = btreq->btr_dend; + params->p_data = (void *)arg; + btreq->btr_indx = 0; + + if (btreq->btr_duuid16 == 0) { - wlwarn("WARNING: Peer not connected\n"); - ret = -ENOTCONN; + params->uuid = NULL; } else { - FAR struct bt_gatt_discover_params_s *params; - - /* Set up the query */ - - g_discoverstate.bd_uuid.type = BT_UUID_16; - g_discoverstate.bd_uuid.u.u16 = btreq->btr_duuid16; - - params = &g_discoverstate.bd_params; - params->uuid = &g_discoverstate.bd_uuid; - params->func = btnet_discover_func; - params->destroy = btnet_discover_destroy; - params->start_handle = btreq->btr_dstart; - params->end_handle = btreq->btr_dend; - - nxsem_init(&g_discoverstate.bd_exclsem, 0, 1); - g_discoverstate.bd_discovering = true; - g_discoverstate.bd_head = 0; - g_discoverstate.bd_tail = 0; - - /* Start the query */ - - switch (btreq->btr_dtype) - { - case GATT_DISCOVER: - ret = bt_gatt_discover(conn, params); - break; - - case GATT_DISCOVER_DESC: - ret = bt_gatt_discover_descriptor(conn, params); - break; - - case GATT_DISCOVER_CHAR: - ret = bt_gatt_discover_characteristic(conn, params); - break; - - default: - wlerr("ERROR: Unrecognized GATT discover type: %u\n", - btreq->btr_dtype); - ret = -EINVAL; - } - - if (ret < 0) - { - wlerr("ERROR: Failed to start discovery: %d\n", ret); - btnet_discover_destroy(params); - } - - bt_conn_release(conn); + params->uuid = &dstate.bd_uuid; } + + nxsem_init(&dstate.bd_donesem, 0, 0); + + /* Start the query */ + + switch (btreq->btr_dtype) + { + case GATT_DISCOVER: + ret = bt_gatt_discover(conn, params); + break; + + case GATT_DISCOVER_DESC: + ret = bt_gatt_discover_descriptor(conn, params); + break; + + case GATT_DISCOVER_CHAR: + ret = bt_gatt_discover_characteristic(conn, params); + break; + + default: + wlerr("ERROR: Unrecognized GATT discover type: %u\n", + btreq->btr_dtype); + ret = -EINVAL; + } + + if (ret < 0) + { + wlerr("ERROR: Failed to start discovery: %d\n", ret); + } + else + { + ret = nxsem_wait(&dstate.bd_donesem); + if (ret == 0) + { + btreq->btr_gnrsp = btreq->btr_indx; + } + } + + nxsem_destroy(&dstate.bd_donesem); + + bt_conn_release(conn); } } break; - /* SIOCBTDISCGET: Return discovered results buffered since the call time - * that the SIOCBTDISCGET command was invoked. - */ - - case SIOCBTDISCGET: - { - ret = btnet_discover_result(btreq->btr_grsp, btreq->btr_gnrsp); - wlinfo("Get discovery results: %d\n", ret); - - if (ret >= 0) - { - btreq->btr_nrsp = ret; - ret = OK; - } - } - break; - - /* SIOCBTGATTRD: Initiate read of GATT data */ + /* SIOCBTGATTRD: Read GATT data */ case SIOCBTGATTRD: { - /* Is there already a read in progress? The current - * implementation can support only one read at a time. - * REVISIT.. see suggested design improvement above. - */ + FAR struct bt_conn_s *conn; - if (g_rdstate.rd_pending) + /* Get the connection associated with the provided LE address */ + + conn = bt_conn_lookup_addr_le(&btreq->btr_rdpeer); + if (conn == NULL) { - wlwarn("WARNING: Read pending\n"); - ret = -EBUSY; + wlwarn("WARNING: Peer not connected\n"); + ret = -ENOTCONN; } else { - FAR struct bt_conn_s *conn; + /* Set up for the read */ - /* Get the connection associated with the provided LE address */ + struct btnet_rdstate_s rdstate; - conn = bt_conn_lookup_addr_le(&btreq->btr_rdpeer); - if (conn == NULL) + memset(&rdstate, 0, sizeof(rdstate)); + rdstate.rd_btreq = btreq; + conn->p_iostate = &rdstate; + nxsem_init(&rdstate.rd_donesem, 0, 0); + + /* Initiate read.. single or multiple? */ + + if (btreq->btr_rdnhandles == 1) { - wlwarn("WARNING: Peer not connected\n"); - ret = -ENOTCONN; + /* Read single */ + + DEBUGASSERT(conn->p_iostate != NULL); + ret = bt_gatt_read(conn, btreq->btr_rdhandles[0], + btreq->btr_rdoffset, + btnet_read_callback); + } + else if (btreq->btr_rdnhandles < HCI_GATT_MAXHANDLES) + { + /* Read multiple */ + + DEBUGASSERT(conn->p_iostate != NULL); + DEBUGASSERT(btreq->btr_rdnhandles > 0); + ret = bt_gatt_read_multiple(conn, btreq->btr_rdhandles, + btreq->btr_rdnhandles, + btnet_read_callback); } else { - /* Set up for the read */ - - g_rdstate.rd_pending = true; - g_rdstate.rd_head = 0; - g_rdstate.rd_tail = 0; - - /* Initiate read.. single or multiple? */ - - if (btreq->btr_rdnhandles == 1) - { - /* Read single */ - - ret = bt_gatt_read(conn, btreq->btr_rdhandles[0], - btreq->btr_rdoffset, - btnet_read_callback); - } - else if (btreq->btr_rdnhandles < HCI_GATT_MAXHANDLES) - { - /* Read multiple */ - - DEBUGASSERT(btreq->btr_rdnhandles > 0); - ret = bt_gatt_read_multiple(conn, btreq->btr_rdhandles, - btreq->btr_rdnhandles, - btnet_read_callback); - } - else - { - ret = -ENFILE; - } - - if (ret < 0) - { - wlerr("ERROR: Read operation failed: %d\n", ret); - } - - bt_conn_release(conn); + ret = -ENFILE; } + + if (ret < 0) + { + wlerr("ERROR: Read operation failed: %d\n", ret); + } + else + { + /* Wait for callback to complete the transfer */ + + ret = nxsem_wait(&rdstate.rd_donesem); + } + + nxsem_destroy(&rdstate.rd_donesem); + + bt_conn_release(conn); } } break; - /* SIOCBTGATTRDGET: Get the result of the GATT data read */ - - case SIOCBTGATTRDGET: - { - ret = btnet_read_result(btreq); - wlinfo("Get read results: %d\n", ret); - } - break; - /* SIOCBTGATTWR: Write GATT data */ case SIOCBTGATTWR: { DEBUGASSERT(btreq->btr_wrdata != NULL); - /* Is there already a write in progress? The current - * implementation can support only one write at a time. - * REVISIT.. see suggested design improvement above. - */ + FAR struct bt_conn_s *conn; - if (g_gattwrresult.br_pending) + /* Get the connection associated with the provided LE address */ + + conn = bt_conn_lookup_addr_le(&btreq->btr_wrpeer); + if (conn == NULL) { - wlwarn("WARNING: Read pending\n"); - ret = -EBUSY; + wlwarn("WARNING: Peer not connected\n"); + ret = -ENOTCONN; } else { - FAR struct bt_conn_s *conn; + /* Set up for the write */ - /* Get the connection associated with the provided LE address */ + struct btnet_wrstate_s wrstate; - conn = bt_conn_lookup_addr_le(&btreq->btr_wrpeer); - if (conn == NULL) + memset(&wrstate, 0, sizeof(wrstate)); + wrstate.wr_btreq = btreq; + conn->p_iostate = &wrstate; + nxsem_init(&wrstate.wr_donesem, 0, 0); + + btreq->btr_wrresult = EBUSY; + + /* Initiate write */ + + ret = bt_gatt_write(conn, btreq->btr_wrhandle, + btreq->btr_wrdata, + btreq->btr_wrnbytes, + bnet_write_callback); + if (ret < 0) { - wlwarn("WARNING: Peer not connected\n"); - ret = -ENOTCONN; + wlerr("ERROR: Write operation failed: %d\n", ret); } else { - /* Set up for the write */ + /* Wait for callback to complete the transfer */ - g_gattwrresult.br_pending = true; - g_gattwrresult.br_result = EBUSY; - - /* Initiate write */ - - ret = bt_gatt_write(conn, btreq->btr_wrhandle, - btreq->btr_wrdata, - btreq->btr_wrnbytes, - bnet_write_callback); - if (ret < 0) - { - wlerr("ERROR: Write operation failed: %d\n", ret); - } - - bt_conn_release(conn); + ret = nxsem_wait(&wrstate.wr_donesem); } + + nxsem_destroy(&wrstate.wr_donesem); + + bt_conn_release(conn); } } break; - /* SIOCBTGATTWRGET: Get the result of the GATT data write */ - - case SIOCBTGATTWRGET: - { - btreq->btr_wrpending = g_gattwrresult.br_pending; - btreq->btr_wrresult = g_gattwrresult.br_result; - ret = OK; - } - break; - default: wlwarn("WARNING: Unrecognized IOCTL command: %02x\n", cmd); ret = -ENOTTY;