xref: /nrf52832-nimble/packages/NimBLE-latest/apps/ext_advertiser/src/ext_advertiser.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <assert.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <errno.h>
24 
25 #include "nimble/npl_shell.h"
26 #include "config/config.h"
27 #include "nimble/ble.h"
28 #include "host/ble_hs.h"
29 #include "host/util/util.h"
30 
31 #include"patterns.h"
32 
33 static uint8_t id_addr_type;
34 
35 static void start_legacy_duration(uint8_t pattern, bool configure);
36 static void start_ext_max_events(uint8_t pattern, bool configure);
37 
38 static int
start_ext_max_events_gap_event(struct ble_gap_event * event,void * arg)39 start_ext_max_events_gap_event(struct ble_gap_event *event, void *arg)
40 {
41     static uint8_t pattern = 1;
42 
43     switch (event->type) {
44     case BLE_GAP_EVENT_ADV_COMPLETE:
45         break;
46     default:
47         assert(0);
48         return 0;
49     }
50 
51     assert(event->adv_complete.instance == 4);
52     assert(event->adv_complete.reason == BLE_HS_ETIMEOUT);
53     assert(event->adv_complete.num_ext_adv_events == 10);
54 
55     console_printf("instance %u terminated\n", event->adv_complete.instance);
56 
57     pattern++;
58 
59     start_ext_max_events(pattern, false);
60 
61     return 0;
62 }
63 
64 /* Starts advertising instance with 100 max events and changing adv data pattern
65  * and SID.
66  */
67 static void
start_ext_max_events(uint8_t pattern,bool configure)68 start_ext_max_events(uint8_t pattern, bool configure)
69 {
70     struct ble_gap_ext_adv_params params;
71     static uint8_t adv_data[600];
72     struct os_mbuf *data;
73     uint8_t instance = 4;
74     ble_addr_t addr;
75     int events = 10;
76     int rc;
77 
78     if (configure) {
79         /* use defaults for non-set params */
80         memset (&params, 0, sizeof(params));
81 
82         /* advertise using random addr */
83         params.own_addr_type = BLE_OWN_ADDR_RANDOM;
84 
85         params.primary_phy = BLE_HCI_LE_PHY_1M;
86         params.secondary_phy = BLE_HCI_LE_PHY_1M;
87         params.tx_power = 127;
88         params.sid = pattern % 16;
89 
90         /* allow larger interval, 400 * 0.625ms with 100 events will give up to
91          * ~2.5 seconds for instance
92          */
93         params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
94         params.itvl_max = 400;
95 
96         /* configure instance 0 */
97         rc = ble_gap_ext_adv_configure(instance, &params, NULL,
98                                         start_ext_max_events_gap_event, NULL);
99         assert (rc == 0);
100 
101         /* set random (NRPA) address for instance */
102         rc = ble_hs_id_gen_rnd(1, &addr);
103         assert (rc == 0);
104 
105         rc = ble_gap_ext_adv_set_addr(instance, &addr );
106         assert (rc == 0);
107     }
108 
109     /* in this case both advertising data and scan response is allowed, but
110      * both are limited to 31 bytes each
111      */
112 
113     /* get mbuf for adv data */
114     data = os_msys_get_pkthdr(600, 0);
115     assert(data);
116 
117     memset(adv_data, pattern, sizeof(adv_data));
118 
119     /* fill mbuf with adv data */
120     rc = os_mbuf_append(data, adv_data, 600);
121     assert(rc == 0);
122 
123    rc = ble_gap_ext_adv_set_data(instance, data);
124    assert (rc == 0);
125 
126    /* start advertising */
127     rc = ble_gap_ext_adv_start(instance, 0, events);
128     assert (rc == 0);
129 
130     console_printf("instance %u started (PDUs with max events %d)\n",
131                                                             instance, events);
132 }
133 
134 static int
start_legacy_duration_gap_event(struct ble_gap_event * event,void * arg)135 start_legacy_duration_gap_event(struct ble_gap_event *event, void *arg)
136 {
137     static uint8_t pattern = 1;
138 
139     switch (event->type) {
140     case BLE_GAP_EVENT_ADV_COMPLETE:
141         break;
142     default:
143         assert(0);
144         return 0;
145     }
146 
147     assert(event->adv_complete.instance == 3);
148     assert(event->adv_complete.reason == BLE_HS_ETIMEOUT);
149 
150     console_printf("instance %u terminated\n", event->adv_complete.instance);
151 
152     pattern++;
153 
154     start_legacy_duration(pattern, false);
155 
156     return 0;
157 }
158 
159 /* Starts advertising instance with 5sec timeout and changing adv data pattern
160  * and SID.
161  */
162 static void
start_legacy_duration(uint8_t pattern,bool configure)163 start_legacy_duration(uint8_t pattern, bool configure)
164 {
165     struct ble_gap_ext_adv_params params;
166     uint8_t adv_data[31];
167     struct os_mbuf *data;
168     uint8_t instance = 3;
169     ble_addr_t addr;
170     int duration = 500; /* 5seconds, 10ms units */
171     int rc;
172 
173     if (configure) {
174         /* use defaults for non-set params */
175         memset (&params, 0, sizeof(params));
176 
177         /* enable advertising using legacy PDUs */
178         params.legacy_pdu = 1;
179 
180         /* advertise using random addr */
181         params.own_addr_type = BLE_OWN_ADDR_RANDOM;
182 
183         params.primary_phy = BLE_HCI_LE_PHY_1M;
184         params.secondary_phy = BLE_HCI_LE_PHY_1M;
185         params.tx_power = 127;
186         params.sid = pattern % 16;
187 
188         /* configure instance 0 */
189         rc = ble_gap_ext_adv_configure(instance, &params, NULL,
190                                         start_legacy_duration_gap_event, NULL);
191         assert (rc == 0);
192 
193         /* set random (NRPA) address for instance */
194         rc = ble_hs_id_gen_rnd(1, &addr);
195         assert (rc == 0);
196 
197         rc = ble_gap_ext_adv_set_addr(instance, &addr );
198         assert (rc == 0);
199     }
200 
201     /* in this case both advertising data and scan response is allowed, but
202      * both are limited to 31 bytes each
203      */
204 
205     /* get mbuf for adv data */
206     data = os_msys_get_pkthdr(31, 0);
207     assert(data);
208 
209     memset(adv_data, pattern, sizeof(adv_data));
210 
211     /* fill mbuf with adv data */
212     rc = os_mbuf_append(data, adv_data, 31);
213     assert(rc == 0);
214 
215    rc = ble_gap_ext_adv_set_data(instance, data);
216    assert (rc == 0);
217 
218    /* start advertising */
219     rc = ble_gap_ext_adv_start(instance, duration, 0);
220     assert (rc == 0);
221 
222     console_printf("instance %u started (legacy PDUs with duration %d)\n",
223                                                             instance, duration);
224 }
225 
226 /* this is simple non-connectable scannable instance using legacy PUDs that
227  * runs forever
228  */
229 static void
start_scannable_legacy_ext(void)230 start_scannable_legacy_ext(void)
231 {
232     struct ble_gap_ext_adv_params params;
233     struct os_mbuf *data;
234     uint8_t instance = 2;
235     ble_addr_t addr;
236     int rc;
237 
238     /* use defaults for non-set params */
239     memset (&params, 0, sizeof(params));
240 
241     /* enable scannable advertising using legacy PDUs */
242     params.scannable = 1;
243     params.legacy_pdu = 1;
244 
245     /* advertise using random addr */
246     params.own_addr_type = BLE_OWN_ADDR_RANDOM;
247 
248     params.primary_phy = BLE_HCI_LE_PHY_1M;
249     params.secondary_phy = BLE_HCI_LE_PHY_1M;
250     params.tx_power = 127;
251     params.sid = 2;
252 
253     /* configure instance 0 */
254     rc = ble_gap_ext_adv_configure(instance, &params, NULL, NULL, NULL);
255     assert (rc == 0);
256 
257     /* set random (NRPA) address for instance */
258     rc = ble_hs_id_gen_rnd(1, &addr);
259     assert (rc == 0);
260 
261     rc = ble_gap_ext_adv_set_addr(instance, &addr );
262     assert (rc == 0);
263 
264     /* in this case both advertising data and scan response is allowed, but
265      * both are limited to 31 bytes each
266      */
267 
268     /* get mbuf for adv data */
269     data = os_msys_get_pkthdr(31, 0);
270     assert(data);
271 
272     /* fill mbuf with adv data */
273     rc = os_mbuf_append(data, ext_adv_pattern_1, 31);
274     assert(rc == 0);
275 
276    rc = ble_gap_ext_adv_set_data(instance, data);
277    assert (rc == 0);
278 
279     /* get mbuf for scan rsp data */
280     data = os_msys_get_pkthdr(31, 0);
281     assert(data);
282 
283     /* fill mbuf with scan rsp data */
284     rc = os_mbuf_append(data, ext_adv_pattern_1 + 31, 31);
285     assert(rc == 0);
286 
287    rc = ble_gap_ext_adv_rsp_set_data(instance, data);
288    assert (rc == 0);
289 
290    /* start advertising */
291     rc = ble_gap_ext_adv_start(instance, 0, 0);
292     assert (rc == 0);
293 
294     console_printf("instance %u started (scannable legacy PDUs)\n", instance);
295 }
296 
297 static int
scannable_ext_gap_event(struct ble_gap_event * event,void * arg)298 scannable_ext_gap_event(struct ble_gap_event *event, void *arg)
299 {
300     switch (event->type) {
301     default:
302         break;
303     }
304 
305     return 0;
306 }
307 
308 /* this is simple scannable instance that runs forever
309  * TODO Get scan request notifications.
310  */
311 static void
start_scannable_ext(void)312 start_scannable_ext(void)
313 {
314     struct ble_gap_ext_adv_params params;
315     struct os_mbuf *data;
316     uint8_t instance = 1;
317     ble_addr_t addr;
318     int rc;
319 
320     /* use defaults for non-set params */
321     memset (&params, 0, sizeof(params));
322 
323     /* enable scannable advertising */
324     params.scannable = 1;
325 
326     /* enable scan request notification */
327     params.scan_req_notif = 1;
328 
329     /* advertise using random addr */
330     params.own_addr_type = BLE_OWN_ADDR_RANDOM;
331 
332     params.primary_phy = BLE_HCI_LE_PHY_1M;
333     params.secondary_phy = BLE_HCI_LE_PHY_1M;
334     params.tx_power = 127;
335     params.sid = 1;
336 
337     /* configure instance 0 */
338     rc = ble_gap_ext_adv_configure(instance, &params, NULL,
339                                    scannable_ext_gap_event, NULL);
340     assert (rc == 0);
341 
342     /* set random (NRPA) address for instance */
343     rc = ble_hs_id_gen_rnd(1, &addr);
344     assert (rc == 0);
345 
346     rc = ble_gap_ext_adv_set_addr(instance, &addr );
347     assert (rc == 0);
348 
349     /* in this case only scan response is allowed */
350 
351     /* get mbuf for scan rsp data */
352     data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
353     assert(data);
354 
355     /* fill mbuf with scan rsp data */
356     rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
357     assert(rc == 0);
358 
359    rc = ble_gap_ext_adv_rsp_set_data(instance, data);
360    assert (rc == 0);
361 
362    /* start advertising */
363     rc = ble_gap_ext_adv_start(instance, 0, 0);
364     assert (rc == 0);
365 
366     console_printf("instance %u started (scannable)\n", instance);
367 }
368 
369 /* this is simple non-connectable instance that runs forever */
370 static void
start_non_connectable_ext(void)371 start_non_connectable_ext(void)
372 {
373     struct ble_gap_ext_adv_params params;
374     struct os_mbuf *data;
375     uint8_t instance = 0;
376     int rc;
377 
378     /* use defaults for non-set params */
379     memset (&params, 0, sizeof(params));
380 
381     /* advertise using ID addr */
382     params.own_addr_type = id_addr_type;
383 
384     params.primary_phy = BLE_HCI_LE_PHY_1M;
385     params.secondary_phy = BLE_HCI_LE_PHY_1M;
386     params.tx_power = 127;
387     params.sid = 0;
388 
389     /* configure instance */
390     rc = ble_gap_ext_adv_configure(instance, &params, NULL, NULL, NULL);
391     assert (rc == 0);
392 
393     /* in this case only advertisign data is allowed */
394 
395     /* get mbuf for adv data */
396     data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
397     assert(data);
398 
399     /* fill mbuf with adv data */
400     rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
401     assert(rc == 0);
402 
403    rc = ble_gap_ext_adv_set_data(instance, data);
404    assert (rc == 0);
405 
406    /* start advertising */
407     rc = ble_gap_ext_adv_start(instance, 0, 0);
408     assert (rc == 0);
409 
410     console_printf("instance %u started (non-con non-scan)\n", instance);
411 }
412 
413 static void
on_sync(void)414 on_sync(void)
415 {
416     int rc;
417 
418     console_printf("Synced, starting advertising\n");
419 
420     /* Make sure we have proper identity address set (public preferred) */
421     rc = ble_hs_util_ensure_addr(0);
422     assert(rc == 0);
423 
424     /* configure global address */
425     rc = ble_hs_id_infer_auto(0, &id_addr_type);
426     assert(rc == 0);
427 
428     start_non_connectable_ext();
429 
430     start_scannable_ext();
431 
432     start_scannable_legacy_ext();
433 
434     start_legacy_duration(0, true);
435 
436     start_ext_max_events(0, true);
437 }
438 
439 /*
440  * main
441  *
442  * The main task for the project. This function initializes the packages,
443  * then starts serving events from default event queue.
444  *
445  * @return int NOTE: this function should never return!
446  */
ext_advertiser_entry(void)447 int ext_advertiser_entry(void)
448 {
449     console_printf("Extended Advertising sample application\n");
450 
451     /* Set sync callback */
452     ble_hs_cfg.sync_cb = on_sync;
453 
454     /* startup bluetooth host stack*/
455     ble_hs_thread_startup();
456 
457     return 0;
458 }
459 MSH_CMD_EXPORT_ALIAS(ext_advertiser_entry, ext_advertiser, "bluetooth external advertiser sample");
460