AndroidのBLEラジコンプロポアプリ「BLEPropo」と接続し、RCサーボとDCモータを制御するプログラムです。 mbed HRM1017で動作を確認しています。 BLEPropo → https://github.com/lipoyang/BLEPropo

Dependencies:   BLE_API mbed

Fork of BLE_RCBController2 by Junichi Katsu

BLEを使ったAndroid用ラジコンプロポアプリ「BLEPropo」に対応するmbed HRM1017用ファームウェアです。
BLEPropoは、GitHubにて公開中。
https://github.com/lipoyang/BLEPropo
/media/uploads/lipoyang/blepropo_ui.png
ラジコンは、mbed HRM1017とRCサーボやDCモータを組み合わせて作ります。
/media/uploads/lipoyang/ble_wiring.png

Committer:
jksoft
Date:
Wed Aug 20 13:24:20 2014 +0000
Revision:
1:48f6e08a3ac2
Parent:
BLE_API_Native_IRC/hw/nRF51822n/nordic/ble/ble_advdata.cpp@0:8c643bfe55b7
2014.08.20?????BLE?????????????; ???mbed?????????????????; mbed HRM1017; Nordic nRF51822

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jksoft 0:8c643bfe55b7 1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
jksoft 0:8c643bfe55b7 2 *
jksoft 0:8c643bfe55b7 3 * The information contained herein is property of Nordic Semiconductor ASA.
jksoft 0:8c643bfe55b7 4 * Terms and conditions of usage are described in detail in NORDIC
jksoft 0:8c643bfe55b7 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
jksoft 0:8c643bfe55b7 6 *
jksoft 0:8c643bfe55b7 7 * Licensees are granted free, non-transferable use of the information. NO
jksoft 0:8c643bfe55b7 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
jksoft 0:8c643bfe55b7 9 * the file.
jksoft 0:8c643bfe55b7 10 *
jksoft 0:8c643bfe55b7 11 */
jksoft 0:8c643bfe55b7 12
jksoft 0:8c643bfe55b7 13 #include "ble_advdata.h"
jksoft 0:8c643bfe55b7 14 #include "nordic_common.h"
jksoft 0:8c643bfe55b7 15 #include "nrf_error.h"
jksoft 0:8c643bfe55b7 16 #include "ble_gap.h"
jksoft 0:8c643bfe55b7 17 #include "ble_srv_common.h"
jksoft 0:8c643bfe55b7 18 #include "app_util.h"
jksoft 0:8c643bfe55b7 19
jksoft 0:8c643bfe55b7 20
jksoft 0:8c643bfe55b7 21 // Offset from where advertisement data other than flags information can start.
jksoft 0:8c643bfe55b7 22 #define ADV_FLAG_OFFSET 2
jksoft 0:8c643bfe55b7 23
jksoft 0:8c643bfe55b7 24 // Offset for Advertising Data.
jksoft 0:8c643bfe55b7 25 // Offset is 2 as each Advertising Data contain 1 octet of Adveritising Data Type and
jksoft 0:8c643bfe55b7 26 // one octet Advertising Data Length.
jksoft 0:8c643bfe55b7 27 #define ADV_DATA_OFFSET 2
jksoft 0:8c643bfe55b7 28
jksoft 0:8c643bfe55b7 29 // NOTE: For now, Security Manager TK Value and Security Manager Out of Band Flags (OOB) are omitted
jksoft 0:8c643bfe55b7 30 // from the advertising data.
jksoft 0:8c643bfe55b7 31
jksoft 0:8c643bfe55b7 32
jksoft 0:8c643bfe55b7 33 static uint32_t name_encode(const ble_advdata_t * p_advdata,
jksoft 0:8c643bfe55b7 34 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 35 uint8_t * p_len)
jksoft 0:8c643bfe55b7 36 {
jksoft 0:8c643bfe55b7 37 uint32_t err_code;
jksoft 0:8c643bfe55b7 38 uint16_t rem_adv_data_len;
jksoft 0:8c643bfe55b7 39 uint16_t actual_length;
jksoft 0:8c643bfe55b7 40 uint8_t adv_data_format;
jksoft 0:8c643bfe55b7 41 uint8_t adv_offset;
jksoft 0:8c643bfe55b7 42
jksoft 0:8c643bfe55b7 43 adv_offset = *p_len;
jksoft 0:8c643bfe55b7 44
jksoft 0:8c643bfe55b7 45
jksoft 0:8c643bfe55b7 46 // Check for buffer overflow.
jksoft 0:8c643bfe55b7 47 if ((adv_offset + ADV_DATA_OFFSET > BLE_GAP_ADV_MAX_SIZE) ||
jksoft 0:8c643bfe55b7 48 ((p_advdata->short_name_len + ADV_DATA_OFFSET) > BLE_GAP_ADV_MAX_SIZE))
jksoft 0:8c643bfe55b7 49 {
jksoft 0:8c643bfe55b7 50 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 51 }
jksoft 0:8c643bfe55b7 52 actual_length = rem_adv_data_len = (BLE_GAP_ADV_MAX_SIZE - adv_offset - ADV_FLAG_OFFSET);
jksoft 0:8c643bfe55b7 53
jksoft 0:8c643bfe55b7 54 // Get GAP device name and length
jksoft 0:8c643bfe55b7 55 err_code = sd_ble_gap_device_name_get(&p_encoded_data[adv_offset + ADV_DATA_OFFSET],
jksoft 0:8c643bfe55b7 56 &actual_length);
jksoft 0:8c643bfe55b7 57 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 58 {
jksoft 0:8c643bfe55b7 59 return err_code;
jksoft 0:8c643bfe55b7 60 }
jksoft 0:8c643bfe55b7 61
jksoft 0:8c643bfe55b7 62 // Check if device internd to use short name and it can fit available data size.
jksoft 0:8c643bfe55b7 63 if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
jksoft 0:8c643bfe55b7 64 {
jksoft 0:8c643bfe55b7 65 // Complete device name can fit, setting Complete Name in Adv Data.
jksoft 0:8c643bfe55b7 66 adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
jksoft 0:8c643bfe55b7 67 rem_adv_data_len = actual_length;
jksoft 0:8c643bfe55b7 68 }
jksoft 0:8c643bfe55b7 69 else
jksoft 0:8c643bfe55b7 70 {
jksoft 0:8c643bfe55b7 71 // Else short name needs to be used. Or application has requested use of short name.
jksoft 0:8c643bfe55b7 72 adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
jksoft 0:8c643bfe55b7 73
jksoft 0:8c643bfe55b7 74 // If application has set a preference on the short name size, it needs to be considered,
jksoft 0:8c643bfe55b7 75 // else fit what can be fit.
jksoft 0:8c643bfe55b7 76 if ((p_advdata->short_name_len != 0) && (p_advdata->short_name_len <= rem_adv_data_len))
jksoft 0:8c643bfe55b7 77 {
jksoft 0:8c643bfe55b7 78 // Short name fits available size.
jksoft 0:8c643bfe55b7 79 rem_adv_data_len = p_advdata->short_name_len;
jksoft 0:8c643bfe55b7 80 }
jksoft 0:8c643bfe55b7 81 // Else whatever can fit the data buffer will be packed.
jksoft 0:8c643bfe55b7 82 else
jksoft 0:8c643bfe55b7 83 {
jksoft 0:8c643bfe55b7 84 rem_adv_data_len = actual_length;
jksoft 0:8c643bfe55b7 85 }
jksoft 0:8c643bfe55b7 86 }
jksoft 0:8c643bfe55b7 87
jksoft 0:8c643bfe55b7 88 // Complete name field in encoded data.
jksoft 0:8c643bfe55b7 89 p_encoded_data[adv_offset++] = rem_adv_data_len + 1;
jksoft 0:8c643bfe55b7 90 p_encoded_data[adv_offset++] = adv_data_format;
jksoft 0:8c643bfe55b7 91 (*p_len) += (rem_adv_data_len + ADV_DATA_OFFSET);
jksoft 0:8c643bfe55b7 92
jksoft 0:8c643bfe55b7 93 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 94 }
jksoft 0:8c643bfe55b7 95
jksoft 0:8c643bfe55b7 96
jksoft 0:8c643bfe55b7 97 static uint32_t appearance_encode(uint8_t * p_encoded_data, uint8_t * p_len)
jksoft 0:8c643bfe55b7 98 {
jksoft 0:8c643bfe55b7 99 uint32_t err_code;
jksoft 0:8c643bfe55b7 100 uint16_t appearance;
jksoft 0:8c643bfe55b7 101
jksoft 0:8c643bfe55b7 102 // Check for buffer overflow.
jksoft 0:8c643bfe55b7 103 if ((*p_len) + 4 > BLE_GAP_ADV_MAX_SIZE)
jksoft 0:8c643bfe55b7 104 {
jksoft 0:8c643bfe55b7 105 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 106 }
jksoft 0:8c643bfe55b7 107
jksoft 0:8c643bfe55b7 108 // Get GAP appearance field.
jksoft 0:8c643bfe55b7 109 err_code = sd_ble_gap_appearance_get(&appearance);
jksoft 0:8c643bfe55b7 110 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 111 {
jksoft 0:8c643bfe55b7 112 return err_code;
jksoft 0:8c643bfe55b7 113 }
jksoft 0:8c643bfe55b7 114
jksoft 0:8c643bfe55b7 115 // Encode Length, AD Type and Appearance.
jksoft 0:8c643bfe55b7 116 p_encoded_data[(*p_len)++] = 3;
jksoft 0:8c643bfe55b7 117 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_APPEARANCE;
jksoft 0:8c643bfe55b7 118
jksoft 0:8c643bfe55b7 119 (*p_len) += uint16_encode(appearance, &p_encoded_data[*p_len]);
jksoft 0:8c643bfe55b7 120
jksoft 0:8c643bfe55b7 121 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 122 }
jksoft 0:8c643bfe55b7 123
jksoft 0:8c643bfe55b7 124
jksoft 0:8c643bfe55b7 125 static uint32_t uint8_array_encode(const uint8_array_t * p_uint8_array,
jksoft 0:8c643bfe55b7 126 uint8_t adv_type,
jksoft 0:8c643bfe55b7 127 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 128 uint8_t * p_len)
jksoft 0:8c643bfe55b7 129 {
jksoft 0:8c643bfe55b7 130 // Check parameter consistency.
jksoft 0:8c643bfe55b7 131 if (p_uint8_array->p_data == NULL)
jksoft 0:8c643bfe55b7 132 {
jksoft 0:8c643bfe55b7 133 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 134 }
jksoft 0:8c643bfe55b7 135
jksoft 0:8c643bfe55b7 136 // Check for buffer overflow.
jksoft 0:8c643bfe55b7 137 if ((*p_len) + ADV_DATA_OFFSET + p_uint8_array->size > BLE_GAP_ADV_MAX_SIZE)
jksoft 0:8c643bfe55b7 138 {
jksoft 0:8c643bfe55b7 139 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 140 }
jksoft 0:8c643bfe55b7 141
jksoft 0:8c643bfe55b7 142 // Encode Length and AD Type.
jksoft 0:8c643bfe55b7 143 p_encoded_data[(*p_len)++] = 1 + p_uint8_array->size;
jksoft 0:8c643bfe55b7 144 p_encoded_data[(*p_len)++] = adv_type;
jksoft 0:8c643bfe55b7 145
jksoft 0:8c643bfe55b7 146 // Encode array.
jksoft 0:8c643bfe55b7 147 memcpy(&p_encoded_data[*p_len], p_uint8_array->p_data, p_uint8_array->size);
jksoft 0:8c643bfe55b7 148 (*p_len) += p_uint8_array->size;
jksoft 0:8c643bfe55b7 149
jksoft 0:8c643bfe55b7 150 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 151 }
jksoft 0:8c643bfe55b7 152
jksoft 0:8c643bfe55b7 153
jksoft 0:8c643bfe55b7 154 static uint32_t tx_power_level_encode(int8_t tx_power_level,
jksoft 0:8c643bfe55b7 155 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 156 uint8_t * p_len)
jksoft 0:8c643bfe55b7 157 {
jksoft 0:8c643bfe55b7 158 // Check for buffer overflow.
jksoft 0:8c643bfe55b7 159 if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE)
jksoft 0:8c643bfe55b7 160 {
jksoft 0:8c643bfe55b7 161 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 162 }
jksoft 0:8c643bfe55b7 163
jksoft 0:8c643bfe55b7 164 // Encode TX Power Level.
jksoft 0:8c643bfe55b7 165 p_encoded_data[(*p_len)++] = 2;
jksoft 0:8c643bfe55b7 166 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
jksoft 0:8c643bfe55b7 167 p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level;
jksoft 0:8c643bfe55b7 168
jksoft 0:8c643bfe55b7 169 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 170 }
jksoft 0:8c643bfe55b7 171
jksoft 0:8c643bfe55b7 172
jksoft 0:8c643bfe55b7 173 static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list,
jksoft 0:8c643bfe55b7 174 uint8_t adv_type,
jksoft 0:8c643bfe55b7 175 uint8_t uuid_size,
jksoft 0:8c643bfe55b7 176 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 177 uint8_t * p_len)
jksoft 0:8c643bfe55b7 178 {
jksoft 0:8c643bfe55b7 179 int i;
jksoft 0:8c643bfe55b7 180 bool is_heading_written = false;
jksoft 0:8c643bfe55b7 181 uint8_t start_pos = *p_len;
jksoft 0:8c643bfe55b7 182
jksoft 0:8c643bfe55b7 183 for (i = 0; i < p_uuid_list->uuid_cnt; i++)
jksoft 0:8c643bfe55b7 184 {
jksoft 0:8c643bfe55b7 185 uint32_t err_code;
jksoft 0:8c643bfe55b7 186 uint8_t encoded_size;
jksoft 0:8c643bfe55b7 187 ble_uuid_t uuid = p_uuid_list->p_uuids[i];
jksoft 0:8c643bfe55b7 188
jksoft 0:8c643bfe55b7 189 // Find encoded uuid size.
jksoft 0:8c643bfe55b7 190 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL);
jksoft 0:8c643bfe55b7 191 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 192 {
jksoft 0:8c643bfe55b7 193 return err_code;
jksoft 0:8c643bfe55b7 194 }
jksoft 0:8c643bfe55b7 195
jksoft 0:8c643bfe55b7 196 // Check size.
jksoft 0:8c643bfe55b7 197 if (encoded_size == uuid_size)
jksoft 0:8c643bfe55b7 198 {
jksoft 0:8c643bfe55b7 199 uint8_t heading_bytes = (is_heading_written) ? 0 : 2;
jksoft 0:8c643bfe55b7 200
jksoft 0:8c643bfe55b7 201 // Check for buffer overflow
jksoft 0:8c643bfe55b7 202 if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE)
jksoft 0:8c643bfe55b7 203 {
jksoft 0:8c643bfe55b7 204 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 205 }
jksoft 0:8c643bfe55b7 206
jksoft 0:8c643bfe55b7 207 if (!is_heading_written)
jksoft 0:8c643bfe55b7 208 {
jksoft 0:8c643bfe55b7 209 // Write AD structure heading.
jksoft 0:8c643bfe55b7 210 (*p_len)++;
jksoft 0:8c643bfe55b7 211 p_encoded_data[(*p_len)++] = adv_type;
jksoft 0:8c643bfe55b7 212 is_heading_written = true;
jksoft 0:8c643bfe55b7 213 }
jksoft 0:8c643bfe55b7 214
jksoft 0:8c643bfe55b7 215 // Write UUID.
jksoft 0:8c643bfe55b7 216 err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]);
jksoft 0:8c643bfe55b7 217 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 218 {
jksoft 0:8c643bfe55b7 219 return err_code;
jksoft 0:8c643bfe55b7 220 }
jksoft 0:8c643bfe55b7 221 (*p_len) += encoded_size;
jksoft 0:8c643bfe55b7 222 }
jksoft 0:8c643bfe55b7 223 }
jksoft 0:8c643bfe55b7 224
jksoft 0:8c643bfe55b7 225 if (is_heading_written)
jksoft 0:8c643bfe55b7 226 {
jksoft 0:8c643bfe55b7 227 // Write length.
jksoft 0:8c643bfe55b7 228 p_encoded_data[start_pos] = (*p_len) - (start_pos + 1);
jksoft 0:8c643bfe55b7 229 }
jksoft 0:8c643bfe55b7 230
jksoft 0:8c643bfe55b7 231 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 232 }
jksoft 0:8c643bfe55b7 233
jksoft 0:8c643bfe55b7 234
jksoft 0:8c643bfe55b7 235 static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list,
jksoft 0:8c643bfe55b7 236 uint8_t adv_type_16,
jksoft 0:8c643bfe55b7 237 uint8_t adv_type_128,
jksoft 0:8c643bfe55b7 238 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 239 uint8_t * p_len)
jksoft 0:8c643bfe55b7 240 {
jksoft 0:8c643bfe55b7 241 uint32_t err_code;
jksoft 0:8c643bfe55b7 242
jksoft 0:8c643bfe55b7 243 // Encode 16 bit UUIDs.
jksoft 0:8c643bfe55b7 244 err_code = uuid_list_sized_encode(p_uuid_list,
jksoft 0:8c643bfe55b7 245 adv_type_16,
jksoft 0:8c643bfe55b7 246 sizeof(uint16_le_t),
jksoft 0:8c643bfe55b7 247 p_encoded_data,
jksoft 0:8c643bfe55b7 248 p_len);
jksoft 0:8c643bfe55b7 249 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 250 {
jksoft 0:8c643bfe55b7 251 return err_code;
jksoft 0:8c643bfe55b7 252 }
jksoft 0:8c643bfe55b7 253
jksoft 0:8c643bfe55b7 254 // Encode 128 bit UUIDs.
jksoft 0:8c643bfe55b7 255 err_code = uuid_list_sized_encode(p_uuid_list,
jksoft 0:8c643bfe55b7 256 adv_type_128,
jksoft 0:8c643bfe55b7 257 sizeof(ble_uuid128_t),
jksoft 0:8c643bfe55b7 258 p_encoded_data,
jksoft 0:8c643bfe55b7 259 p_len);
jksoft 0:8c643bfe55b7 260 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 261 {
jksoft 0:8c643bfe55b7 262 return err_code;
jksoft 0:8c643bfe55b7 263 }
jksoft 0:8c643bfe55b7 264
jksoft 0:8c643bfe55b7 265 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 266 }
jksoft 0:8c643bfe55b7 267
jksoft 0:8c643bfe55b7 268
jksoft 0:8c643bfe55b7 269 static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int)
jksoft 0:8c643bfe55b7 270 {
jksoft 0:8c643bfe55b7 271 // Check Minimum Connection Interval.
jksoft 0:8c643bfe55b7 272 if ((p_conn_int->min_conn_interval < 0x0006) ||
jksoft 0:8c643bfe55b7 273 (
jksoft 0:8c643bfe55b7 274 (p_conn_int->min_conn_interval > 0x0c80) &&
jksoft 0:8c643bfe55b7 275 (p_conn_int->min_conn_interval != 0xffff)
jksoft 0:8c643bfe55b7 276 )
jksoft 0:8c643bfe55b7 277 )
jksoft 0:8c643bfe55b7 278 {
jksoft 0:8c643bfe55b7 279 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 280 }
jksoft 0:8c643bfe55b7 281
jksoft 0:8c643bfe55b7 282 // Check Maximum Connection Interval.
jksoft 0:8c643bfe55b7 283 if ((p_conn_int->max_conn_interval < 0x0006) ||
jksoft 0:8c643bfe55b7 284 (
jksoft 0:8c643bfe55b7 285 (p_conn_int->max_conn_interval > 0x0c80) &&
jksoft 0:8c643bfe55b7 286 (p_conn_int->max_conn_interval != 0xffff)
jksoft 0:8c643bfe55b7 287 )
jksoft 0:8c643bfe55b7 288 )
jksoft 0:8c643bfe55b7 289 {
jksoft 0:8c643bfe55b7 290 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 291 }
jksoft 0:8c643bfe55b7 292
jksoft 0:8c643bfe55b7 293 // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval.
jksoft 0:8c643bfe55b7 294 if ((p_conn_int->min_conn_interval != 0xffff) &&
jksoft 0:8c643bfe55b7 295 (p_conn_int->max_conn_interval != 0xffff) &&
jksoft 0:8c643bfe55b7 296 (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval)
jksoft 0:8c643bfe55b7 297 )
jksoft 0:8c643bfe55b7 298 {
jksoft 0:8c643bfe55b7 299 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 300 }
jksoft 0:8c643bfe55b7 301
jksoft 0:8c643bfe55b7 302 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 303 }
jksoft 0:8c643bfe55b7 304
jksoft 0:8c643bfe55b7 305
jksoft 0:8c643bfe55b7 306 static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int,
jksoft 0:8c643bfe55b7 307 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 308 uint8_t * p_len)
jksoft 0:8c643bfe55b7 309 {
jksoft 0:8c643bfe55b7 310 uint32_t err_code;
jksoft 0:8c643bfe55b7 311
jksoft 0:8c643bfe55b7 312 // Check for buffer overflow.
jksoft 0:8c643bfe55b7 313 if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE)
jksoft 0:8c643bfe55b7 314 {
jksoft 0:8c643bfe55b7 315 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 316 }
jksoft 0:8c643bfe55b7 317
jksoft 0:8c643bfe55b7 318 // Check parameters.
jksoft 0:8c643bfe55b7 319 err_code = conn_int_check(p_conn_int);
jksoft 0:8c643bfe55b7 320 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 321 {
jksoft 0:8c643bfe55b7 322 return err_code;
jksoft 0:8c643bfe55b7 323 }
jksoft 0:8c643bfe55b7 324
jksoft 0:8c643bfe55b7 325 // Encode Length and AD Type.
jksoft 0:8c643bfe55b7 326 p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t);
jksoft 0:8c643bfe55b7 327 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE;
jksoft 0:8c643bfe55b7 328
jksoft 0:8c643bfe55b7 329 // Encode Minimum and Maximum Connection Intervals.
jksoft 0:8c643bfe55b7 330 (*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]);
jksoft 0:8c643bfe55b7 331 (*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]);
jksoft 0:8c643bfe55b7 332
jksoft 0:8c643bfe55b7 333 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 334 }
jksoft 0:8c643bfe55b7 335
jksoft 0:8c643bfe55b7 336
jksoft 0:8c643bfe55b7 337 static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data,
jksoft 0:8c643bfe55b7 338 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 339 uint8_t * p_len)
jksoft 0:8c643bfe55b7 340 {
jksoft 0:8c643bfe55b7 341 uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size;
jksoft 0:8c643bfe55b7 342
jksoft 0:8c643bfe55b7 343 // Check for buffer overflow.
jksoft 0:8c643bfe55b7 344 if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE)
jksoft 0:8c643bfe55b7 345 {
jksoft 0:8c643bfe55b7 346 return NRF_ERROR_DATA_SIZE;
jksoft 0:8c643bfe55b7 347 }
jksoft 0:8c643bfe55b7 348
jksoft 0:8c643bfe55b7 349 // Encode Length and AD Type.
jksoft 0:8c643bfe55b7 350 p_encoded_data[(*p_len)++] = 1 + data_size;
jksoft 0:8c643bfe55b7 351 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
jksoft 0:8c643bfe55b7 352
jksoft 0:8c643bfe55b7 353 // Encode Company Identifier.
jksoft 0:8c643bfe55b7 354 (*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]);
jksoft 0:8c643bfe55b7 355
jksoft 0:8c643bfe55b7 356 // Encode additional manufacturer specific data.
jksoft 0:8c643bfe55b7 357 if (p_manuf_sp_data->data.size > 0)
jksoft 0:8c643bfe55b7 358 {
jksoft 0:8c643bfe55b7 359 if (p_manuf_sp_data->data.p_data == NULL)
jksoft 0:8c643bfe55b7 360 {
jksoft 0:8c643bfe55b7 361 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 362 }
jksoft 0:8c643bfe55b7 363 memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size);
jksoft 0:8c643bfe55b7 364 (*p_len) += p_manuf_sp_data->data.size;
jksoft 0:8c643bfe55b7 365 }
jksoft 0:8c643bfe55b7 366
jksoft 0:8c643bfe55b7 367 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 368 }
jksoft 0:8c643bfe55b7 369
jksoft 0:8c643bfe55b7 370
jksoft 0:8c643bfe55b7 371 static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
jksoft 0:8c643bfe55b7 372 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 373 uint8_t * p_len)
jksoft 0:8c643bfe55b7 374 {
jksoft 0:8c643bfe55b7 375 uint8_t i;
jksoft 0:8c643bfe55b7 376
jksoft 0:8c643bfe55b7 377 // Check parameter consistency.
jksoft 0:8c643bfe55b7 378 if (p_advdata->p_service_data_array == NULL)
jksoft 0:8c643bfe55b7 379 {
jksoft 0:8c643bfe55b7 380 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 381 }
jksoft 0:8c643bfe55b7 382
jksoft 0:8c643bfe55b7 383 for (i = 0; i < p_advdata->service_data_count; i++)
jksoft 0:8c643bfe55b7 384 {
jksoft 0:8c643bfe55b7 385 ble_advdata_service_data_t * p_service_data;
jksoft 0:8c643bfe55b7 386 uint8_t data_size;
jksoft 0:8c643bfe55b7 387
jksoft 0:8c643bfe55b7 388 p_service_data = &p_advdata->p_service_data_array[i];
jksoft 0:8c643bfe55b7 389 data_size = sizeof(uint16_le_t) + p_service_data->data.size;
jksoft 0:8c643bfe55b7 390
jksoft 0:8c643bfe55b7 391 // Encode Length and AD Type.
jksoft 0:8c643bfe55b7 392 p_encoded_data[(*p_len)++] = 1 + data_size;
jksoft 0:8c643bfe55b7 393 p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA;
jksoft 0:8c643bfe55b7 394
jksoft 0:8c643bfe55b7 395 // Encode service UUID.
jksoft 0:8c643bfe55b7 396 (*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
jksoft 0:8c643bfe55b7 397
jksoft 0:8c643bfe55b7 398 // Encode additional service data.
jksoft 0:8c643bfe55b7 399 if (p_service_data->data.size > 0)
jksoft 0:8c643bfe55b7 400 {
jksoft 0:8c643bfe55b7 401 if (p_service_data->data.p_data == NULL)
jksoft 0:8c643bfe55b7 402 {
jksoft 0:8c643bfe55b7 403 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 404 }
jksoft 0:8c643bfe55b7 405 memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
jksoft 0:8c643bfe55b7 406 (*p_len) += p_service_data->data.size;
jksoft 0:8c643bfe55b7 407 }
jksoft 0:8c643bfe55b7 408 }
jksoft 0:8c643bfe55b7 409
jksoft 0:8c643bfe55b7 410 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 411 }
jksoft 0:8c643bfe55b7 412
jksoft 0:8c643bfe55b7 413
jksoft 0:8c643bfe55b7 414 static uint32_t adv_data_encode(const ble_advdata_t * p_advdata,
jksoft 0:8c643bfe55b7 415 uint8_t * p_encoded_data,
jksoft 0:8c643bfe55b7 416 uint8_t * p_len)
jksoft 0:8c643bfe55b7 417 {
jksoft 0:8c643bfe55b7 418 uint32_t err_code = NRF_SUCCESS;
jksoft 0:8c643bfe55b7 419
jksoft 0:8c643bfe55b7 420 *p_len = 0;
jksoft 0:8c643bfe55b7 421
jksoft 0:8c643bfe55b7 422 // Encode name.
jksoft 0:8c643bfe55b7 423 if (p_advdata->name_type != BLE_ADVDATA_NO_NAME)
jksoft 0:8c643bfe55b7 424 {
jksoft 0:8c643bfe55b7 425 err_code = name_encode(p_advdata, p_encoded_data, p_len);
jksoft 0:8c643bfe55b7 426 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 427 {
jksoft 0:8c643bfe55b7 428 return err_code;
jksoft 0:8c643bfe55b7 429 }
jksoft 0:8c643bfe55b7 430 }
jksoft 0:8c643bfe55b7 431
jksoft 0:8c643bfe55b7 432 // Encode appearance.
jksoft 0:8c643bfe55b7 433 if (p_advdata->include_appearance)
jksoft 0:8c643bfe55b7 434 {
jksoft 0:8c643bfe55b7 435 err_code = appearance_encode(p_encoded_data, p_len);
jksoft 0:8c643bfe55b7 436 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 437 {
jksoft 0:8c643bfe55b7 438 return err_code;
jksoft 0:8c643bfe55b7 439 }
jksoft 0:8c643bfe55b7 440 }
jksoft 0:8c643bfe55b7 441
jksoft 0:8c643bfe55b7 442 // Encode flags.
jksoft 0:8c643bfe55b7 443 if (p_advdata->flags.size > 0)
jksoft 0:8c643bfe55b7 444 {
jksoft 0:8c643bfe55b7 445 err_code = uint8_array_encode(&p_advdata->flags,
jksoft 0:8c643bfe55b7 446 BLE_GAP_AD_TYPE_FLAGS,
jksoft 0:8c643bfe55b7 447 p_encoded_data,
jksoft 0:8c643bfe55b7 448 p_len);
jksoft 0:8c643bfe55b7 449 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 450 {
jksoft 0:8c643bfe55b7 451 return err_code;
jksoft 0:8c643bfe55b7 452 }
jksoft 0:8c643bfe55b7 453 }
jksoft 0:8c643bfe55b7 454
jksoft 0:8c643bfe55b7 455 // Encode TX power level.
jksoft 0:8c643bfe55b7 456 if (p_advdata->p_tx_power_level != NULL)
jksoft 0:8c643bfe55b7 457 {
jksoft 0:8c643bfe55b7 458 err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len);
jksoft 0:8c643bfe55b7 459 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 460 {
jksoft 0:8c643bfe55b7 461 return err_code;
jksoft 0:8c643bfe55b7 462 }
jksoft 0:8c643bfe55b7 463 }
jksoft 0:8c643bfe55b7 464
jksoft 0:8c643bfe55b7 465 // Encode 'more available' uuid list.
jksoft 0:8c643bfe55b7 466 if (p_advdata->uuids_more_available.uuid_cnt > 0)
jksoft 0:8c643bfe55b7 467 {
jksoft 0:8c643bfe55b7 468 err_code = uuid_list_encode(&p_advdata->uuids_more_available,
jksoft 0:8c643bfe55b7 469 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
jksoft 0:8c643bfe55b7 470 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE,
jksoft 0:8c643bfe55b7 471 p_encoded_data,
jksoft 0:8c643bfe55b7 472 p_len);
jksoft 0:8c643bfe55b7 473 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 474 {
jksoft 0:8c643bfe55b7 475 return err_code;
jksoft 0:8c643bfe55b7 476 }
jksoft 0:8c643bfe55b7 477 }
jksoft 0:8c643bfe55b7 478
jksoft 0:8c643bfe55b7 479 // Encode 'complete' uuid list.
jksoft 0:8c643bfe55b7 480 if (p_advdata->uuids_complete.uuid_cnt > 0)
jksoft 0:8c643bfe55b7 481 {
jksoft 0:8c643bfe55b7 482 err_code = uuid_list_encode(&p_advdata->uuids_complete,
jksoft 0:8c643bfe55b7 483 BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
jksoft 0:8c643bfe55b7 484 BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
jksoft 0:8c643bfe55b7 485 p_encoded_data,
jksoft 0:8c643bfe55b7 486 p_len);
jksoft 0:8c643bfe55b7 487 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 488 {
jksoft 0:8c643bfe55b7 489 return err_code;
jksoft 0:8c643bfe55b7 490 }
jksoft 0:8c643bfe55b7 491 }
jksoft 0:8c643bfe55b7 492
jksoft 0:8c643bfe55b7 493 // Encode 'solicited service' uuid list.
jksoft 0:8c643bfe55b7 494 if (p_advdata->uuids_solicited.uuid_cnt > 0)
jksoft 0:8c643bfe55b7 495 {
jksoft 0:8c643bfe55b7 496 err_code = uuid_list_encode(&p_advdata->uuids_solicited,
jksoft 0:8c643bfe55b7 497 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT,
jksoft 0:8c643bfe55b7 498 BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT,
jksoft 0:8c643bfe55b7 499 p_encoded_data,
jksoft 0:8c643bfe55b7 500 p_len);
jksoft 0:8c643bfe55b7 501 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 502 {
jksoft 0:8c643bfe55b7 503 return err_code;
jksoft 0:8c643bfe55b7 504 }
jksoft 0:8c643bfe55b7 505 }
jksoft 0:8c643bfe55b7 506
jksoft 0:8c643bfe55b7 507 // Encode Slave Connection Interval Range.
jksoft 0:8c643bfe55b7 508 if (p_advdata->p_slave_conn_int != NULL)
jksoft 0:8c643bfe55b7 509 {
jksoft 0:8c643bfe55b7 510 err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len);
jksoft 0:8c643bfe55b7 511 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 512 {
jksoft 0:8c643bfe55b7 513 return err_code;
jksoft 0:8c643bfe55b7 514 }
jksoft 0:8c643bfe55b7 515 }
jksoft 0:8c643bfe55b7 516
jksoft 0:8c643bfe55b7 517 // Encode Manufacturer Specific Data.
jksoft 0:8c643bfe55b7 518 if (p_advdata->p_manuf_specific_data != NULL)
jksoft 0:8c643bfe55b7 519 {
jksoft 0:8c643bfe55b7 520 err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data,
jksoft 0:8c643bfe55b7 521 p_encoded_data,
jksoft 0:8c643bfe55b7 522 p_len);
jksoft 0:8c643bfe55b7 523 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 524 {
jksoft 0:8c643bfe55b7 525 return err_code;
jksoft 0:8c643bfe55b7 526 }
jksoft 0:8c643bfe55b7 527 }
jksoft 0:8c643bfe55b7 528
jksoft 0:8c643bfe55b7 529 // Encode Service Data.
jksoft 0:8c643bfe55b7 530 if (p_advdata->service_data_count > 0)
jksoft 0:8c643bfe55b7 531 {
jksoft 0:8c643bfe55b7 532 err_code = service_data_encode(p_advdata, p_encoded_data, p_len);
jksoft 0:8c643bfe55b7 533 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 534 {
jksoft 0:8c643bfe55b7 535 return err_code;
jksoft 0:8c643bfe55b7 536 }
jksoft 0:8c643bfe55b7 537 }
jksoft 0:8c643bfe55b7 538
jksoft 0:8c643bfe55b7 539 return err_code;
jksoft 0:8c643bfe55b7 540 }
jksoft 0:8c643bfe55b7 541
jksoft 0:8c643bfe55b7 542
jksoft 0:8c643bfe55b7 543 static uint32_t advdata_check(const ble_advdata_t * p_advdata)
jksoft 0:8c643bfe55b7 544 {
jksoft 0:8c643bfe55b7 545 // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set.
jksoft 0:8c643bfe55b7 546 if ((p_advdata->flags.size == 0) ||
jksoft 0:8c643bfe55b7 547 (p_advdata->flags.p_data == NULL) ||
jksoft 0:8c643bfe55b7 548 ((p_advdata->flags.p_data[0] & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)
jksoft 0:8c643bfe55b7 549 )
jksoft 0:8c643bfe55b7 550 {
jksoft 0:8c643bfe55b7 551 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 552 }
jksoft 0:8c643bfe55b7 553
jksoft 0:8c643bfe55b7 554 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 555 }
jksoft 0:8c643bfe55b7 556
jksoft 0:8c643bfe55b7 557
jksoft 0:8c643bfe55b7 558 static uint32_t srdata_check(const ble_advdata_t * p_srdata)
jksoft 0:8c643bfe55b7 559 {
jksoft 0:8c643bfe55b7 560 // Flags shall not be included in the scan response data.
jksoft 0:8c643bfe55b7 561 if (p_srdata->flags.size > 0)
jksoft 0:8c643bfe55b7 562 {
jksoft 0:8c643bfe55b7 563 return NRF_ERROR_INVALID_PARAM;
jksoft 0:8c643bfe55b7 564 }
jksoft 0:8c643bfe55b7 565
jksoft 0:8c643bfe55b7 566 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 567 }
jksoft 0:8c643bfe55b7 568
jksoft 0:8c643bfe55b7 569
jksoft 0:8c643bfe55b7 570 uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata)
jksoft 0:8c643bfe55b7 571 {
jksoft 0:8c643bfe55b7 572 uint32_t err_code;
jksoft 0:8c643bfe55b7 573 uint8_t len_advdata = 0;
jksoft 0:8c643bfe55b7 574 uint8_t len_srdata = 0;
jksoft 0:8c643bfe55b7 575 uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
jksoft 0:8c643bfe55b7 576 uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE];
jksoft 0:8c643bfe55b7 577 uint8_t * p_encoded_advdata;
jksoft 0:8c643bfe55b7 578 uint8_t * p_encoded_srdata;
jksoft 0:8c643bfe55b7 579
jksoft 0:8c643bfe55b7 580 // Encode advertising data (if supplied).
jksoft 0:8c643bfe55b7 581 if (p_advdata != NULL)
jksoft 0:8c643bfe55b7 582 {
jksoft 0:8c643bfe55b7 583 err_code = advdata_check(p_advdata);
jksoft 0:8c643bfe55b7 584 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 585 {
jksoft 0:8c643bfe55b7 586 return err_code;
jksoft 0:8c643bfe55b7 587 }
jksoft 0:8c643bfe55b7 588
jksoft 0:8c643bfe55b7 589 err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata);
jksoft 0:8c643bfe55b7 590 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 591 {
jksoft 0:8c643bfe55b7 592 return err_code;
jksoft 0:8c643bfe55b7 593 }
jksoft 0:8c643bfe55b7 594 p_encoded_advdata = encoded_advdata;
jksoft 0:8c643bfe55b7 595 }
jksoft 0:8c643bfe55b7 596 else
jksoft 0:8c643bfe55b7 597 {
jksoft 0:8c643bfe55b7 598 p_encoded_advdata = NULL;
jksoft 0:8c643bfe55b7 599 }
jksoft 0:8c643bfe55b7 600
jksoft 0:8c643bfe55b7 601 // Encode scan response data (if supplied).
jksoft 0:8c643bfe55b7 602 if (p_srdata != NULL)
jksoft 0:8c643bfe55b7 603 {
jksoft 0:8c643bfe55b7 604 err_code = srdata_check(p_srdata);
jksoft 0:8c643bfe55b7 605 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 606 {
jksoft 0:8c643bfe55b7 607 return err_code;
jksoft 0:8c643bfe55b7 608 }
jksoft 0:8c643bfe55b7 609
jksoft 0:8c643bfe55b7 610 err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata);
jksoft 0:8c643bfe55b7 611 if (err_code != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 612 {
jksoft 0:8c643bfe55b7 613 return err_code;
jksoft 0:8c643bfe55b7 614 }
jksoft 0:8c643bfe55b7 615 p_encoded_srdata = encoded_srdata;
jksoft 0:8c643bfe55b7 616 }
jksoft 0:8c643bfe55b7 617 else
jksoft 0:8c643bfe55b7 618 {
jksoft 0:8c643bfe55b7 619 p_encoded_srdata = NULL;
jksoft 0:8c643bfe55b7 620 }
jksoft 0:8c643bfe55b7 621
jksoft 0:8c643bfe55b7 622 // Pass encoded advertising data and/or scan response data to the stack.
jksoft 0:8c643bfe55b7 623 return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
jksoft 0:8c643bfe55b7 624 }