From 501f56b3607a45c6b2ce16966200acbc316e56b4 Mon Sep 17 00:00:00 2001
From: Matthias Ringwald <matthias@ringwald.ch>
Date: Wed, 9 Mar 2016 11:15:47 +0100
Subject: [PATCH] add gap_scan_response_set_data

---
 src/gap.h | 12 ++++++++++++
 src/hci.c | 45 ++++++++++++++++++++++++++++++++-------------
 src/hci.h | 12 ++++++++----
 3 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/src/gap.h b/src/gap.h
index 9f7a66eac..b4ba2c9f7 100644
--- a/src/gap.h
+++ b/src/gap.h
@@ -246,6 +246,18 @@ void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, u
  * @param enabled
  */
 void gap_advertisements_enable(int enabled);
+
+/** 
+ * @brief Set Scan Response Data
+ *
+ * @note For scan response data, scannable undirected advertising (ADV_SCAN_IND) need to be used
+ *
+ * @param advertising_data_length
+ * @param advertising_data (max 31 octets)
+ * @note data is not copied, pointer has to stay valid
+ */
+void gap_scan_response_set_data(uint8_t scan_response_data_length, uint8_t * scan_response_data);
+
 /**
  * @brief Request an update of the connection parameter for a given LE connection
  * @param handle
diff --git a/src/hci.c b/src/hci.c
index 034a72cfa..11599ce4e 100644
--- a/src/hci.c
+++ b/src/hci.c
@@ -2361,12 +2361,18 @@ static void hci_run(void){
                  hci_stack->le_advertisements_filter_policy);
             return;
         }
-        if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_SET_DATA){
-            hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_SET_DATA;
+        if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_SET_ADV_DATA){
+            hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_SET_ADV_DATA;
             hci_send_cmd(&hci_le_set_advertising_data, hci_stack->le_advertisements_data_len,
                 hci_stack->le_advertisements_data);
             return;
         }
+        if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA){
+            hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA;
+            hci_send_cmd(&hci_le_set_scan_response_data, hci_stack->le_scan_response_data_len,
+                hci_stack->le_scan_response_data);
+            return;
+        }
         if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_ENABLE){
             hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_ENABLE;
             hci_send_cmd(&hci_le_set_advertise_enable, 1);
@@ -3328,6 +3334,14 @@ int gap_request_connection_parameter_update(hci_con_handle_t con_handle, uint16_
     return 0;
 }
 
+static void gap_advertisments_changed(void){
+    // disable advertisements before updating adv, scan data, or adv params
+    if (hci_stack->le_advertisements_active){
+        hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE | LE_ADVERTISEMENT_TASKS_ENABLE;
+    }
+    hci_run();
+}
+
 /**
  * @brief Set Advertisement Data
  * @param advertising_data_length
@@ -3337,12 +3351,21 @@ int gap_request_connection_parameter_update(hci_con_handle_t con_handle, uint16_
 void gap_advertisements_set_data(uint8_t advertising_data_length, uint8_t * advertising_data){
     hci_stack->le_advertisements_data_len = advertising_data_length;
     hci_stack->le_advertisements_data = advertising_data;
-    hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_DATA;
-    // disable advertisements before setting data
-    if (hci_stack->le_advertisements_active){
-        hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE | LE_ADVERTISEMENT_TASKS_ENABLE;
-    }
-    hci_run();
+    hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_ADV_DATA;
+    gap_advertisments_changed();
+}
+
+/** 
+ * @brief Set Scan Response Data
+ * @param advertising_data_length
+ * @param advertising_data (max 31 octets)
+ * @note data is not copied, pointer has to stay valid
+ */
+void gap_scan_response_set_data(uint8_t scan_response_data_length, uint8_t * scan_response_data){
+    hci_stack->le_scan_response_data_len = scan_response_data_length;
+    hci_stack->le_scan_response_data = scan_response_data;
+    hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA;
+    gap_advertisments_changed();
 }
 
 /**
@@ -3372,11 +3395,7 @@ void gap_advertisements_set_data(uint8_t advertising_data_length, uint8_t * adve
     memcpy(hci_stack->le_advertisements_direct_address, direct_address, 6);
 
     hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_PARAMS;
-    // disable advertisements before changing params
-    if (hci_stack->le_advertisements_active){
-        hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE | LE_ADVERTISEMENT_TASKS_ENABLE;
-    }
-    hci_run();
+    gap_advertisments_changed();
  }
 
 /**
diff --git a/src/hci.h b/src/hci.h
index b08ab7304..fcd1e1e5b 100644
--- a/src/hci.h
+++ b/src/hci.h
@@ -497,10 +497,11 @@ typedef enum hci_init_state{
 } hci_substate_t;
 
 enum {
-    LE_ADVERTISEMENT_TASKS_DISABLE      = 1 << 0,
-    LE_ADVERTISEMENT_TASKS_SET_DATA     = 1 << 1,
-    LE_ADVERTISEMENT_TASKS_SET_PARAMS   = 1 << 2,
-    LE_ADVERTISEMENT_TASKS_ENABLE       = 1 << 3,
+    LE_ADVERTISEMENT_TASKS_DISABLE       = 1 << 0,
+    LE_ADVERTISEMENT_TASKS_SET_ADV_DATA  = 1 << 1,
+    LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA = 1 << 2,
+    LE_ADVERTISEMENT_TASKS_SET_PARAMS    = 1 << 3,
+    LE_ADVERTISEMENT_TASKS_ENABLE        = 1 << 4,
 };
 
 enum {
@@ -633,6 +634,9 @@ typedef struct {
     uint8_t  * le_advertisements_data;
     uint8_t    le_advertisements_data_len;
 
+    uint8_t  * le_scan_response_data;
+    uint8_t    le_scan_response_data_len;
+
     uint8_t  le_advertisements_active;
     uint8_t  le_advertisements_enabled;
     uint8_t  le_advertisements_todo;