diff --git a/include/nuttx/wireless/bt_ioctl.h b/include/nuttx/wireless/bt_ioctl.h index fbe52682b9a..8ac42233778 100644 --- a/include/nuttx/wireless/bt_ioctl.h +++ b/include/nuttx/wireless/bt_ioctl.h @@ -475,7 +475,10 @@ struct btreq_s FAR uint8_t *btgrr_rddata; /* Values returned by read */ } btgrr; - /* Read-only data that accompanies the SIOCBTGATTWR command */ + /* Read-only 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. + */ struct { diff --git a/wireless/bluetooth/bt_ioctl.c b/wireless/bluetooth/bt_ioctl.c index e2e0c07a4db..6bf3bdbecf4 100644 --- a/wireless/bluetooth/bt_ioctl.c +++ b/wireless/bluetooth/bt_ioctl.c @@ -593,6 +593,28 @@ static int btnet_read_result(FAR struct btreq_s *btreq) return OK; } +/**************************************************************************** + * Name: bnet_write_callback + * + * Description: + * Result of write operation. + * + * Input Parameters: + * conn - The address of the peer in the MTU exchange + * result - The result of the MTU exchange + * + * Returned Value: + * None + * + ****************************************************************************/ + +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; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1023,7 +1045,51 @@ int btnet_ioctl(FAR struct net_driver_s *netdev, int cmd, unsigned long arg) case SIOCBTGATTWR: { - ret = -ENOSYS; + 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. + */ + + if (g_gattwrresult.br_pending) + { + wlwarn("WARNING: Read pending\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_wrpeer); + if (conn == NULL) + { + wlwarn("WARNING: Peer not connected\n"); + ret = -ENOTCONN; + } + else + { + /* Set up for the write */ + + 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); + } + } } break;