Contiki-NG
ble-beacond.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /**
31  * \addtogroup cc13xx-cc26xx-rf-ble
32  * @{
33  *
34  * \file
35  * Implementation for the CC13xx/CC26xx BLE Beacon Daemon.
36  * \author
37  * Edvard Pettersen <e.pettersen@ti.com>
38  */
39 /*---------------------------------------------------------------------------*/
40 #include "contiki.h"
41 #include "sys/cc.h"
42 #include "sys/clock.h"
43 #include "sys/etimer.h"
44 #include "sys/process.h"
45 #include "net/linkaddr.h"
46 #include "net/netstack.h"
47 /*---------------------------------------------------------------------------*/
48 #include <ti/devices/DeviceFamily.h>
49 #include DeviceFamily_constructPath(driverlib/chipinfo.h)
50 #include DeviceFamily_constructPath(driverlib/rf_ble_cmd.h)
51 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
52 
53 #include <ti/drivers/rf/RF.h>
54 /*---------------------------------------------------------------------------*/
55 #include "rf/rf.h"
56 #include "rf/sched.h"
57 #include "rf/ble-addr.h"
58 #include "rf/ble-beacond.h"
59 #include "rf/tx-power.h"
60 #include "rf/settings.h"
61 /*---------------------------------------------------------------------------*/
62 #include <stdbool.h>
63 #include <stdint.h>
64 #include <stdio.h>
65 #include <string.h>
66 /*---------------------------------------------------------------------------*/
67 /* Log configuration */
68 #include "sys/log.h"
69 #define LOG_MODULE "Radio"
70 #define LOG_LEVEL LOG_LEVEL_NONE
71 /*---------------------------------------------------------------------------*/
72 #if RF_CONF_BLE_BEACON_ENABLE
73 /*---------------------------------------------------------------------------*/
74 /* Maximum BLE advertisement size. Not to be changed by the user. */
75 #define BLE_ADV_MAX_SIZE 31
76 /*---------------------------------------------------------------------------*/
77 /*
78  * BLE Intervals: Send a burst of advertisements every BLE_ADV_INTERVAL
79  * specified in milliseconds.
80  */
81 #define BLE_ADV_INTERVAL ((100 * CLOCK_SECOND) / 1000)
82 
83 /* GAP Advertisement data types */
84 #define BLE_ADV_TYPE_FLAGS 0x01
85 #define BLE_ADV_TYPE_16BIT_MORE 0x02
86 #define BLE_ADV_TYPE_16BIT_COMPLETE 0x03
87 #define BLE_ADV_TYPE_32BIT_MORE 0x04
88 #define BLE_ADV_TYPE_32BIT_COMPLETE 0x05
89 #define BLE_ADV_TYPE_128BIT_MORE 0x06
90 #define BLE_ADV_TYPE_128BIT_COMPLETE 0x07
91 #define BLE_ADV_TYPE_LOCAL_NAME_SHORT 0x08
92 #define BLE_ADV_TYPE_LOCAL_NAME_COMPLETE 0x09
93 #define BLE_ADV_TYPE_POWER_LEVEL 0x0A
94 #define BLE_ADV_TYPE_OOB_CLASS_OF_DEVICE 0x0D
95 #define BLE_ADV_TYPE_OOB_SIMPLE_PAIRING_HASHC 0x0E
96 #define BLE_ADV_TYPE_OOB_SIMPLE_PAIRING_RANDR 0x0F
97 #define BLE_ADV_TYPE_SM_TK 0x10
98 #define BLE_ADV_TYPE_SM_OOB_FLAG 0x11
99 #define BLE_ADV_TYPE_SLAVE_CONN_INTERVAL_RANGE 0x12
100 #define BLE_ADV_TYPE_SIGNED_DATA 0x13
101 #define BLE_ADV_TYPE_SERVICE_LIST_16BIT 0x14
102 #define BLE_ADV_TYPE_SERVICE_LIST_128BIT 0x15
103 #define BLE_ADV_TYPE_SERVICE_DATA 0x16
104 #define BLE_ADV_TYPE_PUBLIC_TARGET_ADDR 0x17
105 #define BLE_ADV_TYPE_RANDOM_TARGET_ADDR 0x18
106 #define BLE_ADV_TYPE_APPEARANCE 0x19
107 #define BLE_ADV_TYPE_ADV_INTERVAL 0x1A
108 #define BLE_ADV_TYPE_LE_BD_ADDR 0x1B
109 #define BLE_ADV_TYPE_LE_ROLE 0x1C
110 #define BLE_ADV_TYPE_SIMPLE_PAIRING_HASHC_256 0x1D
111 #define BLE_ADV_TYPE_SIMPLE_PAIRING_RANDR_256 0x1E
112 #define BLE_ADV_TYPE_SERVICE_DATA_32BIT 0x20
113 #define BLE_ADV_TYPE_SERVICE_DATA_128BIT 0x21
114 #define BLE_ADV_TYPE_3D_INFO_DATA 0x3D
115 #define BLE_ADV_TYPE_MANUFACTURER_SPECIFIC 0xFF
116 
117 /* GAP Advertisement data type flags */
118 
119 /* Discovery Mode: LE Limited Discoverable Mode */
120 #define BLE_ADV_TYPE_FLAGS_LIMITED 0x01
121 /* Discovery Mode: LE General Discoverable Mode */
122 #define BLE_ADV_TYPE_FLAGS_GENERAL 0x02
123 /* Discovery Mode: BR/EDR Not Supported */
124 #define BLE_ADV_TYPE_FLAGS_BREDR_NOT_SUPPORTED 0x04
125 
126 #define BLE_ADV_NAME_BUF_LEN BLE_ADV_MAX_SIZE
127 #define BLE_ADV_PAYLOAD_BUF_LEN 64
128 #define BLE_UUID_SIZE 16
129 /*---------------------------------------------------------------------------*/
130 typedef struct {
131  /* Outgoing frame buffer */
132  uint8_t tx_buf[BLE_ADV_PAYLOAD_BUF_LEN] CC_ALIGN(4);
133 
134  /* Config data */
135  size_t adv_name_len;
136  char adv_name[BLE_ADV_NAME_BUF_LEN];
137 
138  /* Indicates whether deamon is active or not */
139  bool is_active;
140 
141  /* Periodic timer for sending out BLE advertisements */
142  clock_time_t ble_adv_interval;
143  struct etimer ble_adv_et;
144 
145  /* RF driver */
146  RF_Handle rf_handle;
147 
148  /* BLE command specific structures. Common accross BLE and BLE5. */
149  uint8_t ble_mac_addr[6];
150  rfc_bleAdvPar_t ble_adv_par;
151  rfc_bleAdvOutput_t ble_adv_output;
152 } ble_beacond_t;
153 
154 static ble_beacond_t ble_beacond;
155 /*---------------------------------------------------------------------------*/
156 PROCESS(ble_beacond_process, "RF BLE Beacon Daemon Process");
157 /*---------------------------------------------------------------------------*/
158 rf_ble_beacond_result_t
160 {
161  ble_cmd_radio_setup.config.frontEndMode = RF_2_4_GHZ_FRONT_END_MODE;
162  ble_cmd_radio_setup.config.biasMode = RF_2_4_GHZ_BIAS_MODE;
163 
164  RF_Params rf_params;
165  RF_Params_init(&rf_params);
166 
167  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
168 
169  ble_beacond.rf_handle = ble_open(&rf_params);
170 
171  if(ble_beacond.rf_handle == NULL) {
172  return RF_BLE_BEACOND_ERROR;
173  }
174 
175  /*
176  * It is important that the contents of the BLE MAC address is copied into
177  * RAM, as the System CPU, and subsequently flash, goes idle when pending
178  * on an RF command. This causes pend to hang forever.
179  */
180  ble_addr_le_cpy(ble_beacond.ble_mac_addr);
181  ble_beacond.ble_adv_par.pDeviceAddress = (uint16_t *)ble_beacond.ble_mac_addr;
182  ble_beacond.ble_adv_par.endTrigger.triggerType = TRIG_NEVER;
183 
184  rf_ble_cmd_ble_adv_nc.pParams = &ble_beacond.ble_adv_par;
185  rf_ble_cmd_ble_adv_nc.pOutput = &ble_beacond.ble_adv_output;
186 
187  return RF_BLE_BEACOND_OK;
188 }
189 /*---------------------------------------------------------------------------*/
190 rf_ble_beacond_result_t
191 rf_ble_beacond_config(clock_time_t interval, const char *name)
192 {
193  rf_ble_beacond_result_t res;
194 
195  res = RF_BLE_BEACOND_ERROR;
196 
197  if(interval > 0) {
198  ble_beacond.ble_adv_interval = interval;
199 
200  res = RF_BLE_BEACOND_OK;
201  } else {
202  ble_beacond.ble_adv_interval = BLE_ADV_INTERVAL;
203  }
204 
205  if(name != NULL) {
206  const size_t name_len = strlen(name);
207 
208  if((0 < name_len) && (name_len < BLE_ADV_NAME_BUF_LEN)) {
209  ble_beacond.adv_name_len = name_len;
210  memcpy(ble_beacond.adv_name, name, name_len);
211 
212  res = RF_BLE_BEACOND_OK;
213  }
214  }
215 
216  return res;
217 }
218 /*---------------------------------------------------------------------------*/
219 rf_ble_beacond_result_t
221 {
222  if(ble_beacond.is_active) {
223  return RF_BLE_BEACOND_OK;
224  }
225 
226  ble_beacond.is_active = true;
227 
228  process_start(&ble_beacond_process, NULL);
229 
230  return RF_BLE_BEACOND_OK;
231 }
232 /*---------------------------------------------------------------------------*/
233 rf_ble_beacond_result_t
235 {
236  if(!ble_beacond.is_active) {
237  return RF_BLE_BEACOND_OK;
238  }
239 
240  ble_beacond.is_active = false;
241 
242  process_exit(&ble_beacond_process);
243 
244  return RF_BLE_BEACOND_OK;
245 }
246 /*---------------------------------------------------------------------------*/
247 int8_t
248 rf_ble_is_active(void)
249 {
250  return (int8_t)ble_beacond.is_active;
251 }
252 /*---------------------------------------------------------------------------*/
253 rf_ble_beacond_result_t
254 rf_ble_set_tx_power(int8_t dbm)
255 {
256  rf_result_t res;
257 
258  if(!tx_power_in_range(dbm, ble_tx_power_table, ble_tx_power_table_size)) {
259  return RADIO_RESULT_INVALID_VALUE;
260  }
261 
262  res = rf_set_tx_power(ble_beacond.rf_handle, ble_tx_power_table, dbm);
263 
264  return (res == RF_RESULT_OK)
265  ? RF_BLE_BEACOND_OK
266  : RF_BLE_BEACOND_ERROR;
267 }
268 /*---------------------------------------------------------------------------*/
269 int8_t
271 {
272  rf_result_t res;
273 
274  int8_t dbm;
275  res = rf_get_tx_power(ble_beacond.rf_handle, ble_tx_power_table, &dbm);
276 
277  if(res != RF_RESULT_OK) {
278  return RF_TxPowerTable_INVALID_DBM;
279  }
280 
281  return dbm;
282 }
283 /*---------------------------------------------------------------------------*/
284 PROCESS_THREAD(ble_beacond_process, ev, data)
285 {
286  size_t len;
287 
288  PROCESS_BEGIN();
289 
290  while(1) {
291  etimer_set(&ble_beacond.ble_adv_et, ble_beacond.ble_adv_interval);
292  PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ble_beacond.ble_adv_et) ||
293  (ev == PROCESS_EVENT_EXIT));
294 
295  if(ev == PROCESS_EVENT_EXIT) {
296  PROCESS_EXIT();
297  }
298 
299  /* Device info */
300  /* Set the adv payload each pass: The device name may have changed */
301  len = 0;
302 
303  #define append_byte(x) ble_beacond.tx_buf[len++] = (uint8_t)((x))
304 
305  /* 2 bytes */
306  append_byte(2);
307  append_byte(BLE_ADV_TYPE_FLAGS);
308  /* LE general discoverable + BR/EDR not supported */
309  append_byte(BLE_ADV_TYPE_FLAGS_GENERAL |
310  BLE_ADV_TYPE_FLAGS_BREDR_NOT_SUPPORTED);
311 
312  /* 1 + len(name) bytes (excluding zero termination) */
313  append_byte(1 + ble_beacond.adv_name_len);
314  append_byte(BLE_ADV_TYPE_LOCAL_NAME_COMPLETE);
315 
316  memcpy(ble_beacond.tx_buf + len, ble_beacond.adv_name, ble_beacond.adv_name_len);
317  len += ble_beacond.adv_name_len;
318 
319  #undef append_byte
320 
321  /* Send advertisements on all three channels */
322  ble_beacond.ble_adv_par.advLen = len;
323  ble_beacond.ble_adv_par.pAdvData = ble_beacond.tx_buf;
324 
325  ble_sched_beacons(BLE_ADV_CHANNEL_ALL);
326  }
327  PROCESS_END();
328 }
329 /*---------------------------------------------------------------------------*/
330 #else /* RF_CONF_BLE_BEACON_ENABLE */
331 /*---------------------------------------------------------------------------*/
332 rf_ble_beacond_result_t
334 {
335  return RF_BLE_BEACOND_DISABLED;
336 }
337 /*---------------------------------------------------------------------------*/
338 rf_ble_beacond_result_t
339 rf_ble_beacond_config(clock_time_t interval, const char *name)
340 {
341  (void)interval;
342  (void)name;
343  return RF_BLE_BEACOND_DISABLED;
344 }
345 /*---------------------------------------------------------------------------*/
346 rf_ble_beacond_result_t
348 {
349  return RF_BLE_BEACOND_DISABLED;
350 }
351 
352 /*---------------------------------------------------------------------------*/
353 rf_ble_beacond_result_t
355 {
356  return RF_BLE_BEACOND_DISABLED;
357 }
358 /*---------------------------------------------------------------------------*/
359 int8_t
361 {
362  return -1;
363 }
364 /*---------------------------------------------------------------------------*/
365 rf_ble_beacond_result_t
366 rf_ble_set_tx_power(int8_t power)
367 {
368  (void)power;
369  return RF_BLE_BEACOND_DISABLED;
370 }
371 /*---------------------------------------------------------------------------*/
372 int8_t
374 {
375  return ~(int8_t)(0);
376 }
377 /*---------------------------------------------------------------------------*/
378 #endif /* RF_CONF_BLE_BEACON_ENABLE */
379 /*---------------------------------------------------------------------------*/
380 /** @} */
rf_ble_beacond_result_t rf_ble_beacond_start(void)
Start the BLE advertisement/beacon daemon.
Definition: ble-beacond.c:347
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
Header file of TX power functionality of CC13xx/CC26xx.
Header file for the CC13xx/CC26xx BLE Beacon Daemon.
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
Header file for the link-layer address representation
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
Definition: process.h:157
rf_ble_beacond_result_t rf_ble_beacond_config(clock_time_t interval, const char *name)
Set the device name to use with the BLE advertisement/beacon daemon.
Definition: ble-beacond.c:339
int8_t rf_ble_get_tx_power(void)
Get TX power for BLE advertisements.
Definition: ble-beacond.c:373
rf_ble_beacond_result_t rf_ble_beacond_stop(void)
Stop the BLE advertisement/beacon daemon.
Definition: ble-beacond.c:354
void process_exit(struct process *p)
Cause a process to exit.
Definition: process.c:202
rf_ble_beacond_result_t rf_ble_set_tx_power(int8_t power)
Set TX power for BLE advertisements.
Definition: ble-beacond.c:366
Header file of the CC13xx/CC26xx RF scheduler.
Event timer header file.
int8_t rf_ble_is_active(void)
Check whether the BLE beacond is currently active.
Definition: ble-beacond.c:360
#define RF_CONF_INACTIVITY_TIMEOUT
2 ms
int ble_addr_le_cpy(uint8_t *dst)
Copy the node&#39;s factory BLE address to a destination memory area in little-endian (le) order...
Definition: ble-addr.c:105
Header file for the Contiki process interface.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:213
rf_ble_beacond_result_t rf_ble_beacond_init(void)
Initialize the BLE advertisement/beacon daemon.
Definition: ble-beacond.c:333
A timer.
Definition: etimer.h:76
Header file of RF settings for CC13xx/CC26xx.
Header file of common CC13xx/CC26xx RF functionality.
Include file for the Contiki low-layer network stack (NETSTACK)
Default definitions of C compiler quirk work-arounds.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1107
Header file for the logging system
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PROCESS_EXIT()
Exit the currently running process.
Definition: process.h:200