This is an automated email from the ASF dual-hosted git repository.

janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new 4d01f96d apps/bttester: add support for Periodic Sync Transfer
4d01f96d is described below

commit 4d01f96d7b7507d4404dfa737c99b35fb6b2b952
Author: Krzysztof Kopyściński <krzysztof.kopyscin...@codecoup.pl>
AuthorDate: Mon Aug 1 12:51:54 2022 +0200

    apps/bttester: add support for Periodic Sync Transfer
    
    Added BTP commands required to execute Periodic Advertising tests.
    Added support for using basic functionalities of Extended Advertising.
---
 apps/bttester/src/btp/btp_gap.h |  99 +++++++++
 apps/bttester/src/btp_gap.c     | 448 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 540 insertions(+), 7 deletions(-)

diff --git a/apps/bttester/src/btp/btp_gap.h b/apps/bttester/src/btp/btp_gap.h
index 93b62c48..65b56818 100644
--- a/apps/bttester/src/btp/btp_gap.h
+++ b/apps/bttester/src/btp/btp_gap.h
@@ -70,6 +70,7 @@ struct btp_gap_read_controller_index_list_rp {
 #define BTP_GAP_SETTINGS_PRIVACY        13
 #define BTP_GAP_SETTINGS_CONTROLLER_CONFIG    14
 #define BTP_GAP_SETTINGS_STATIC_ADDRESS    15
+#define BTP_GAP_SETTINGS_PERIODIC_ADVERTISING 18
 
 #define BTP_GAP_READ_CONTROLLER_INFO    0x03
 struct btp_gap_read_controller_info_rp {
@@ -257,6 +258,67 @@ struct btp_gap_set_filter_accept_list_cmd {
     uint8_t list_len;
     ble_addr_t addrs[];
 } __packed;
+
+#define GAP_PADV_CONFIGURE        0x22
+struct gap_periodic_adv_configure_cmd {
+    uint8_t flags;
+    uint16_t itvl_min;
+    uint16_t itvl_max;
+} __packed;
+
+struct btp_gap_periodic_adv_configure_rp {
+    uint32_t current_settings;
+} __packed;
+
+#define GAP_PADV_START            0x23
+struct gap_periodic_adv_start_cmd {
+    uint8_t flags;
+} __packed;
+
+struct btp_gap_periodic_adv_start_rp {
+    uint32_t current_settings;
+} __packed;
+
+#define GAP_PADV_STOP            0x24
+struct btp_gap_periodic_adv_stop_rp {
+    uint32_t current_settings;
+} __packed;
+
+#define GAP_PADV_SET_DATA        0x25
+struct gap_periodic_adv_set_data_cmd {
+    uint16_t adv_data_len;
+    uint8_t adv_data[0];
+} __packed;
+
+#define GAP_PADV_CREATE_SYNC        0x26
+struct gap_periodic_adv_create_sync_cmd {
+    ble_addr_t addr;
+    uint8_t adv_sid;
+    uint16_t skip;
+    uint16_t sync_timeout;
+    uint8_t flags;
+} __packed;
+
+#define GAP_PADV_SYNC_TRANSFER_SET_INFO        0x27
+struct gap_periodic_adv_sync_transfer_set_info_cmd {
+    ble_addr_t addr;
+    uint16_t svc_data;
+} __packed;
+
+#define GAP_PADV_SYNC_TRANSFER_START        0x28
+struct gap_periodic_adv_sync_transfer_start_cmd {
+    uint16_t sync_handle;
+    ble_addr_t addr;
+    uint16_t svc_data;
+} __packed;
+
+#define GAP_PADV_SYNC_TRANSFER_RECV        0x29
+struct gap_periodic_adv_sync_transfer_recv_cmd {
+    ble_addr_t addr;
+    uint16_t skip;
+    uint16_t sync_timeout;
+    uint8_t flags;
+} __packed;
 /* events */
 #define BTP_GAP_EV_NEW_SETTINGS        0x80
 struct btp_gap_new_settings_ev {
@@ -342,3 +404,40 @@ struct btp_gap_sec_pairing_failed_ev {
     ble_addr_t address;
     uint8_t reason;
 } __packed;
+
+#define GAP_EV_PERIODIC_SYNC_ESTABLISHED    0x8d
+struct gap_periodic_sync_est_ev {
+    ble_addr_t peer_addr;
+    uint16_t sync_handle;
+    uint8_t status;
+} __packed;
+
+#define GAP_EV_PERIODIC_SYNC_LOST    0x8e
+struct gap_periodic_sync_lost_ev {
+    uint16_t sync_handle;
+    uint8_t reason;
+} __packed;
+
+#define GAP_EV_PERIODIC_REPORT    0x8f
+struct gap_periodic_report_ev {
+    uint16_t sync_handle;
+    int8_t tx_power;
+    int8_t rssi;
+    uint8_t cte_type;
+    uint8_t data_status;
+    uint8_t data_length;
+    uint8_t data[247];
+} __packed;
+
+#define GAP_EV_PERIODIC_TRANSFER_RECEIVED   0x90
+struct gap_periodic_transfer_recieved_ev {
+    uint8_t status;
+    uint16_t sync_handle;
+    uint16_t conn_handle;
+    uint16_t service_data;
+    uint8_t sid;
+    ble_addr_t adv_addr;
+    uint8_t adv_phy;
+    uint16_t per_adv_itvl;
+    uint8_t adv_clk_accuracy;
+} __packed;
\ No newline at end of file
diff --git a/apps/bttester/src/btp_gap.c b/apps/bttester/src/btp_gap.c
index 8056eaf1..5d30cbb0 100644
--- a/apps/bttester/src/btp_gap.c
+++ b/apps/bttester/src/btp_gap.c
@@ -156,8 +156,24 @@ supported_commands(const void *cmd, uint16_t cmd_len,
     tester_set_bit(rp->data, BTP_GAP_OOB_SC_GET_LOCAL_DATA);
     tester_set_bit(rp->data, BTP_GAP_OOB_SC_SET_REMOTE_DATA);
     tester_set_bit(rp->data, BTP_GAP_SET_MITM);
+    tester_set_bit(rp->data, BTP_GAP_SET_FILTER_ACCEPT_LIST);
+
+    /* octet 4 */
+#if MYNEWT_VAL(BLE_PERIODIC_ADV)
+    tester_set_bit(rp->data, GAP_PADV_CONFIGURE);
+    tester_set_bit(rp->data, GAP_PADV_START);
+    tester_set_bit(rp->data, GAP_PADV_SET_DATA);
+    tester_set_bit(rp->data, GAP_PADV_CREATE_SYNC);
+#endif
+#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
+    tester_set_bit(rp->data, GAP_PADV_SYNC_TRANSFER_SET_INFO);
+    tester_set_bit(rp->data, GAP_PADV_SYNC_TRANSFER_START);
+    tester_set_bit(rp->data, GAP_PADV_SYNC_TRANSFER_START);
+#endif
 
-    *rsp_len = sizeof(*rp) + 4;
+    *rsp_len = sizeof(*rp) + 4 +
+               (MYNEWT_VAL(BLE_PERIODIC_ADV) ||
+                MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) ? 1 : 0);
 
     return BTP_STATUS_SUCCESS;
 }
@@ -247,10 +263,20 @@ controller_info(const void *cmd, uint16_t cmd_len,
     return BTP_STATUS_SUCCESS;
 }
 
+#if MYNEWT_VAL(BLE_EXT_ADV)
+int adv_duration = 0;
+static struct ble_gap_ext_adv_params adv_params = {
+    .primary_phy = BLE_HCI_LE_PHY_1M,
+    .secondary_phy = BLE_HCI_LE_PHY_1M,
+    .sid = 1,
+    .legacy_pdu = 1,
+};
+#else
 static struct ble_gap_adv_params adv_params = {
     .conn_mode = BLE_GAP_CONN_MODE_NON,
     .disc_mode = BLE_GAP_DISC_MODE_NON,
 };
+#endif
 
 #if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA)
 static void rotate_nrpa_cb(struct os_event *ev)
@@ -295,10 +321,20 @@ set_connectable(const void *cmd, uint16_t cmd_len,
 
     if (cp->connectable) {
         current_settings |= BIT(BTP_GAP_SETTINGS_CONNECTABLE);
+#if MYNEWT_VAL(BLE_EXT_ADV)
+        adv_params.connectable = 1;
+        adv_params.scannable = 1;
+#else
         adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
+#endif
     } else {
         current_settings &= ~BIT(BTP_GAP_SETTINGS_CONNECTABLE);
+#if MYNEWT_VAL(BLE_EXT_ADV)
+        adv_params.connectable = 0;
+        adv_params.scannable = 0;
+#else
         adv_params.conn_mode = BLE_GAP_CONN_MODE_NON;
+#endif
     }
 
     rp->current_settings = htole32(current_settings);
@@ -314,6 +350,7 @@ static uint8_t
 set_discoverable(const void *cmd, uint16_t cmd_len,
                  void *rsp, uint16_t *rsp_len)
 {
+#if !MYNEWT_VAL(BLE_EXT_ADV)
     const struct btp_gap_set_discoverable_cmd *cp = cmd;
     struct btp_gap_set_discoverable_rp *rp = rsp;
 
@@ -346,6 +383,9 @@ set_discoverable(const void *cmd, uint16_t cmd_len,
     *rsp_len = sizeof(*rp);
 
     return BTP_STATUS_SUCCESS;
+#else
+    return BTP_STATUS_FAILED;
+#endif
 }
 
 static uint8_t
@@ -457,11 +497,28 @@ start_advertising(const void *cmd, uint16_t cmd_len,
         return BTP_STATUS_FAILED;
     }
 
-    err = ble_gap_adv_set_data(buf, buf_len);
-    if (err != 0) {
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    struct os_mbuf *ad_buf;
+
+    adv_params.own_addr_type = own_addr_type;
+    err = ble_gap_ext_adv_configure(0, &adv_params, NULL, gap_event_cb, NULL);
+    if (err) {
+        SYS_LOG_ERR("Failed to configure extended advertiser; rc=%d", err);
         return BTP_STATUS_FAILED;
     }
 
+    ad_buf = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0);
+
+    if (os_mbuf_append(ad_buf, buf, buf_len)) {
+        os_mbuf_free_chain(ad_buf);
+        return BTP_STATUS_FAILED;
+    }
+
+    err = ble_gap_ext_adv_set_data(0, ad_buf);
+#else
+    err = ble_gap_adv_set_data(buf, buf_len);
+#endif
+
     if (sd_len) {
         buf_len = 0;
 
@@ -478,9 +535,13 @@ start_advertising(const void *cmd, uint16_t cmd_len,
         }
     }
 
+#if !MYNEWT_VAL(BLE_EXT_ADV)
     if (adv_params.disc_mode == BLE_GAP_DISC_MODE_LTD) {
         duration_ms = MYNEWT_VAL(BTTESTER_LTD_ADV_TIMEOUT);
     }
+#else
+    adv_duration = MYNEWT_VAL(BTTESTER_LTD_ADV_TIMEOUT);
+#endif
 
     /* In NimBLE, own_addr_type is configured in `controller_info` function.
      * Let's just verify restrictions for Privacy options.
@@ -513,8 +574,13 @@ start_advertising(const void *cmd, uint16_t cmd_len,
                          OS_TICKS_PER_SEC * MYNEWT_VAL(BTTESTER_NRPA_TIMEOUT));
     }
 #endif
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    err = ble_gap_ext_adv_start(0, duration_ms, 0);
+#else
     err = ble_gap_adv_start(own_addr_type, NULL, duration_ms,
-                            &adv_params, gap_event_cb, NULL);
+                &adv_params, gap_event_cb, NULL);
+#endif
     if (err) {
         SYS_LOG_ERR("Advertising failed: err %d", err);
         return BTP_STATUS_FAILED;
@@ -533,14 +599,18 @@ stop_advertising(const void *cmd, uint16_t cmd_len,
                  void *rsp, uint16_t *rsp_len)
 {
     struct btp_gap_stop_advertising_rp *rp = rsp;
-    int err;
 
     SYS_LOG_DBG("");
 
-    err = ble_gap_adv_stop();
-    if (err != 0) {
+#if MYNEWT_VAL(BLE_EXT_ADV)
+    if (ble_gap_ext_adv_stop(0) != 0) {
+        return BTP_STATUS_FAILED;
+    }
+#else
+    if (ble_gap_adv_stop() != 0) {
         return BTP_STATUS_FAILED;
     }
+#endif
 
     current_settings &= ~BIT(BTP_GAP_SETTINGS_ADVERTISING);
     rp->current_settings = htole32(current_settings);
@@ -1139,6 +1209,71 @@ bond_lost(uint16_t conn_handle)
                  (uint8_t *) &ev, sizeof(ev));
 }
 
+#if MYNEWT_VAL(BLE_PERIODIC_ADV)
+static void
+sync_established(struct ble_gap_event *event)
+{
+    struct gap_periodic_sync_est_ev ev;
+
+    ev.status = event->periodic_sync.status;
+    ev.sync_handle = event->periodic_sync.sync_handle;
+
+    tester_event(BTP_SERVICE_ID_GAP, GAP_EV_PERIODIC_SYNC_ESTABLISHED,
+                 (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+sync_lost(struct ble_gap_event *event)
+{
+    struct gap_periodic_sync_lost_ev ev;
+
+    ev.reason = event->periodic_sync_lost.reason;
+    ev.sync_handle = event->periodic_sync_lost.sync_handle;
+
+    tester_event(BTP_SERVICE_ID_GAP, GAP_EV_PERIODIC_SYNC_LOST,
+                 (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+periodic_report(struct ble_gap_event *event)
+{
+    struct gap_periodic_report_ev ev;
+
+    ev.sync_handle = event->periodic_report.sync_handle;
+    ev.tx_power = event->periodic_report.tx_power;
+    ev.rssi = event->periodic_report.rssi;
+    ev.cte_type = 0xFF;
+    ev.data_status = event->periodic_report.data_status;
+    ev.data_length = event->periodic_report.data_length;
+    memcpy(ev.data, event->periodic_report.data,
+           event->periodic_report.data_length);
+
+    tester_event(BTP_SERVICE_ID_GAP, GAP_EV_PERIODIC_REPORT,
+                 (uint8_t *) &ev, sizeof(ev));
+}
+#endif
+
+#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
+static void
+periodic_transfer_received(struct ble_gap_event *event)
+{
+    struct gap_periodic_transfer_recieved_ev ev;
+
+    ev.status = event->periodic_transfer.status;
+    ev.sync_handle = event->periodic_transfer.sync_handle;
+    ev.conn_handle = event->periodic_transfer.conn_handle;
+    ev.service_data = event->periodic_transfer.service_data;
+    ev.sid = event->periodic_transfer.sid;
+    ev.adv_addr = event->periodic_transfer.adv_addr;
+    ev.adv_phy = event->periodic_transfer.adv_phy;
+    ev.per_adv_itvl = event->periodic_transfer.per_adv_itvl;
+    ev.adv_clk_accuracy = event->periodic_transfer.adv_clk_accuracy;
+
+    tester_event(BTP_SERVICE_ID_GAP, GAP_EV_PERIODIC_TRANSFER_RECEIVED,
+                 (uint8_t *) &ev, sizeof(ev));
+}
+#endif
+
 static void
 print_bytes(const uint8_t *bytes, int len)
 {
@@ -1386,6 +1521,58 @@ gap_event_cb(struct ble_gap_event *event, void *arg)
                               event->pairing_complete.status);
         }
         break;
+#if MYNEWT_VAL(BLE_PERIODIC_ADV)
+    case BLE_GAP_EVENT_PERIODIC_SYNC:
+        console_printf("Periodic Sync established: "
+                       "sync_handle=%d, status=%d sid=%d adv_addr=",
+                       event->periodic_sync.sync_handle,
+                       event->periodic_sync.status, event->periodic_sync.sid);
+        print_addr(event->periodic_sync.adv_addr.val);
+        console_printf("adv_phy=%d per_adv_ival=%d adv_clk_accuracy=%d\n",
+                       event->periodic_sync.adv_phy,
+                       event->periodic_sync.per_adv_ival,
+                       event->periodic_sync.adv_clk_accuracy);
+        sync_established(event);
+        break;
+    case BLE_GAP_EVENT_PERIODIC_REPORT:
+        console_printf("Periodic Sync Report: "
+                       "sync_handle=%d, tx_power=%d rssi=%d data_status=%d"
+                       "data_length=%d data=",
+                       event->periodic_report.sync_handle,
+                       event->periodic_report.tx_power,
+                       event->periodic_report.rssi,
+                       event->periodic_report.data_status,
+                       event->periodic_report.data_length);
+        print_bytes(event->periodic_report.data,
+                    event->periodic_report.data_length);
+        console_printf("\n");
+        periodic_report(event);
+        break;
+    case BLE_GAP_EVENT_PERIODIC_SYNC_LOST:
+        console_printf("Periodic Sync lost: "
+                       "sync_handle=%d, reason=%d\n",
+                       event->periodic_sync_lost.sync_handle,
+                       event->periodic_sync_lost.reason);
+        sync_lost(event);
+        break;
+#endif
+#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
+    case BLE_GAP_EVENT_PERIODIC_TRANSFER:
+        console_printf("Periodic transfer received:"
+                           "status=%d, sync_handle=%d, conn_handle=%d, 
service_data=%d, sid=%d addr=",
+                           event->periodic_transfer.status,
+                           event->periodic_transfer.sync_handle,
+                           event->periodic_transfer.conn_handle,
+                           event->periodic_transfer.service_data,
+                           event->periodic_transfer.sid);
+        print_addr(event->periodic_sync.adv_addr.val);
+        console_printf(" adv_phy=%d, per_adv_itvl=%d, adv_clk_accuracy=%d\n",
+                       event->periodic_transfer.adv_phy,
+                       event->periodic_transfer.per_adv_itvl,
+                       event->periodic_transfer.adv_clk_accuracy);
+        periodic_transfer_received(event);
+        break;
+#endif
     default:
         break;
     }
@@ -1766,6 +1953,213 @@ set_filter_accept_list(const void *cmd, uint16_t 
cmd_len,
     return BTP_STATUS_SUCCESS;
 }
 
+#if MYNEWT_VAL(BLE_PERIODIC_ADV)
+static uint8_t
+periodic_adv_configure(const void *cmd, uint16_t cmd_len,
+                       void *rsp, uint16_t *rsp_len)
+{
+    struct ble_gap_ext_adv_params ext_params = {0};
+    struct ble_gap_periodic_adv_params params = {0};
+    const struct gap_periodic_adv_configure_cmd *cp = cmd;
+    struct btp_gap_periodic_adv_configure_rp *rp = rsp;
+
+    int rc;
+
+    memset(&params, 0, sizeof(params));
+    params.include_tx_power = cp->flags & 0x01;
+    params.itvl_min = cp->itvl_min;
+    params.itvl_max = cp->itvl_max;
+
+    ext_params.connectable = 0;
+    ext_params.scannable = 0;
+    ext_params.legacy_pdu = 0;
+    ext_params.anonymous = 0;
+    ext_params.own_addr_type = own_addr_type;
+    ext_params.primary_phy = BLE_HCI_LE_PHY_1M;
+    ext_params.secondary_phy = BLE_HCI_LE_PHY_1M;
+    ext_params.sid = 1;
+
+    rc = ble_gap_ext_adv_configure(1, &ext_params, NULL, gap_event_cb, NULL);
+    if (rc) {
+        SYS_LOG_ERR("Failed to configure extended advertiser; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    rc = ble_gap_periodic_adv_configure(1, &params);
+    if (rc) {
+        SYS_LOG_ERR("Failed to configure periodic advertiser; rc=%d\n"
+                    "params.itvl_min %d\n"
+                    "params.itvl_max %d\n", rc, params.itvl_min,
+                    params.itvl_max);
+        return BTP_STATUS_FAILED;
+    }
+
+    current_settings |= BIT(BTP_GAP_SETTINGS_PERIODIC_ADVERTISING);
+
+    rp->current_settings = htole32(current_settings);
+    *rsp_len = sizeof(*rp);
+
+    return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+periodic_adv_start(const void *cmd, uint16_t cmd_len,
+                   void *rsp, uint16_t *rsp_len)
+{
+    int rc;
+    struct btp_gap_periodic_adv_start_rp *rp = rsp;
+
+    rc = ble_gap_ext_adv_start(1, 0, 0);
+    if (rc) {
+        SYS_LOG_ERR("Failed to start extended advertiser; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    rc = ble_gap_periodic_adv_start(1);
+    if (rc) {
+        SYS_LOG_ERR("Failed to start periodic advertiser; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    rp->current_settings = htole32(current_settings);
+    *rsp_len = sizeof(*rp);
+    return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+periodic_adv_set_data(const void *cmd, uint16_t cmd_len,
+                      void *rsp, uint16_t *rsp_len)
+{
+    struct os_mbuf *adv_data;
+    const struct gap_periodic_adv_set_data_cmd *cp = cmd;
+    int rc;
+    uint16_t data_len = le16toh(cp->adv_data_len);
+
+    adv_data = os_msys_get_pkthdr(data_len, 0);
+    if (!adv_data) {
+        return BTP_STATUS_FAILED;
+    }
+
+    if (os_mbuf_append(adv_data, cp->adv_data, data_len)) {
+        return BTP_STATUS_FAILED;
+    }
+
+    rc = ble_gap_periodic_adv_set_data(1, adv_data);
+    if (rc) {
+        SYS_LOG_ERR("Failed to set periodic advertiser data; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+periodic_adv_create_sync(const void *cmd, uint16_t cmd_len,
+                         void *rsp, uint16_t *rsp_len)
+{
+    const struct gap_periodic_adv_create_sync_cmd *cp = cmd;
+    struct ble_gap_periodic_sync_params params;
+    struct ble_gap_disc_params scan_params = {0};
+    int rc;
+
+    params.reports_disabled = BIT(0) & cp->flags;
+    params.skip = cp->skip;
+    params.sync_timeout = cp->sync_timeout;
+    SYS_LOG_DBG("\nreports_disabled %d\nskip %d\nsync_timeout %d\n",
+                params.reports_disabled, params.skip, params.sync_timeout);
+
+    scan_params.passive = 0;
+    scan_params.limited = 0;
+    scan_params.filter_duplicates = 0;
+
+    ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &scan_params, NULL, NULL);
+    rc = ble_gap_periodic_adv_sync_create(&cp->addr, cp->adv_sid, &params,
+                                          gap_event_cb, NULL);
+    if (rc) {
+        SYS_LOG_ERR("Failed to create sync; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    return BTP_STATUS_SUCCESS;
+}
+
+#endif
+#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
+static uint8_t
+periodic_adv_sync_transfer_start(const void *cmd, uint16_t cmd_len,
+                                 void *rsp, uint16_t *rsp_len)
+{
+    const struct gap_periodic_adv_sync_transfer_start_cmd *cp = cmd;
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    rc = gap_conn_find_by_addr(&cp->addr, &desc);
+    if (rc) {
+        return BTP_STATUS_FAILED;
+    }
+
+    rc = ble_gap_periodic_adv_sync_transfer(cp->sync_handle, desc.conn_handle,
+                                            cp->svc_data);
+    if (rc) {
+        SYS_LOG_ERR("Failed to initiate sync transfer; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+periodic_adv_sync_transfer_recv(const void *cmd, uint16_t cmd_len,
+                                void *rsp, uint16_t *rsp_len)
+{
+    const struct gap_periodic_adv_sync_transfer_recv_cmd *cp = cmd;
+    struct ble_gap_conn_desc desc;
+    struct ble_gap_periodic_sync_params params;
+    int rc;
+
+    rc = gap_conn_find_by_addr(&cp->addr, &desc);
+    if (rc) {
+        return BTP_STATUS_FAILED;
+    }
+
+    params.reports_disabled = BIT(0) & cp->flags;
+    params.skip = cp->skip;
+    params.sync_timeout = cp->sync_timeout;
+
+    rc = ble_gap_periodic_adv_sync_receive(desc.conn_handle, &params,
+                                           gap_event_cb, NULL);
+    if (rc) {
+        SYS_LOG_ERR("Failed to receive periodic sync; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+periodic_adv_sync_transfer_set_info(const void *cmd, uint16_t cmd_len,
+                                    void *rsp, uint16_t *rsp_len)
+{
+    const struct gap_periodic_adv_sync_transfer_set_info_cmd *cp = cmd;
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    rc = gap_conn_find_by_addr(&cp->addr, &desc);
+    if (rc) {
+        return BTP_STATUS_FAILED;
+    }
+
+    rc = ble_gap_periodic_adv_sync_set_info(1, desc.conn_handle,
+                                            cp->svc_data);
+    if (rc) {
+        SYS_LOG_ERR("Failed to set info; rc=%d", rc);
+        return BTP_STATUS_FAILED;
+    }
+
+    return BTP_STATUS_SUCCESS;
+}
+#endif
+
 static const struct btp_handler handlers[] = {
     {
         .opcode = BTP_GAP_READ_SUPPORTED_COMMANDS,
@@ -1889,6 +2283,46 @@ static const struct btp_handler handlers[] = {
         .expect_len = BTP_HANDLER_LENGTH_VARIABLE,
         .func = set_filter_accept_list,
     },
+#if MYNEWT_VAL(BLE_PERIODIC_ADV)
+    {
+        .opcode = GAP_PADV_CONFIGURE,
+        .expect_len = sizeof(struct gap_periodic_adv_configure_cmd),
+        .func = periodic_adv_configure,
+    },
+    {
+        .opcode = GAP_PADV_START,
+        .expect_len = sizeof(struct gap_periodic_adv_start_cmd),
+        .func = periodic_adv_start,
+    },
+    {
+        .opcode = GAP_PADV_SET_DATA,
+        .expect_len = BTP_HANDLER_LENGTH_VARIABLE,
+        .func = periodic_adv_set_data,
+    },
+    {
+        .opcode = GAP_PADV_CREATE_SYNC,
+        .expect_len = sizeof(struct gap_periodic_adv_create_sync_cmd),
+        .func = periodic_adv_create_sync,
+    },
+#endif
+#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
+    {
+        .opcode = GAP_PADV_SYNC_TRANSFER_SET_INFO,
+        .expect_len =
+            sizeof(struct gap_periodic_adv_sync_transfer_set_info_cmd),
+        .func = periodic_adv_sync_transfer_set_info,
+    },
+    {
+        .opcode = GAP_PADV_SYNC_TRANSFER_START,
+        .expect_len = sizeof(struct gap_periodic_adv_sync_transfer_start_cmd),
+        .func = periodic_adv_sync_transfer_start,
+    },
+    {
+        .opcode = GAP_PADV_SYNC_TRANSFER_RECV,
+        .expect_len = sizeof(struct gap_periodic_adv_sync_transfer_recv_cmd),
+        .func = periodic_adv_sync_transfer_recv,
+    },
+#endif
 };
 
 static void

Reply via email to