Patched version of nrf51822 FOTA compatible driver, with GPTIO disabled, as it clashed with the mbed definitions...

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_advdata.c Source File

ble_advdata.c

00001 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is property of Nordic Semiconductor ASA.
00004  * Terms and conditions of usage are described in detail in NORDIC
00005  * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *
00011  */
00012 
00013 #include "ble_advdata.h "
00014 #include "nordic_common.h"
00015 #include "nrf_error.h"
00016 #include "ble_gap.h"
00017 #include "ble_srv_common.h "
00018 #include "app_util.h "
00019 
00020 
00021 // Offset from where advertisement data other than flags information can start.
00022 #define ADV_FLAG_OFFSET 2
00023 
00024 // Offset for Advertising Data.
00025 // Offset is 2 as each Advertising Data contain 1 octet of Adveritising Data Type and
00026 // one octet Advertising Data Length.
00027 #define ADV_DATA_OFFSET 2
00028 
00029 // NOTE: For now, Security Manager TK Value and Security Manager Out of Band Flags (OOB) are omitted
00030 //       from the advertising data.
00031 
00032 
00033 static uint32_t name_encode(const ble_advdata_t * p_advdata,
00034                             uint8_t             * p_encoded_data,
00035                             uint8_t             * p_len)
00036 {
00037     uint32_t err_code;
00038     uint16_t rem_adv_data_len;
00039     uint16_t actual_length;
00040     uint8_t  adv_data_format;
00041     uint8_t  adv_offset;
00042 
00043     adv_offset = *p_len;
00044 
00045 
00046     // Check for buffer overflow.
00047     if ((adv_offset + ADV_DATA_OFFSET > BLE_GAP_ADV_MAX_SIZE) ||
00048         ((p_advdata->short_name_len + ADV_DATA_OFFSET) > BLE_GAP_ADV_MAX_SIZE))
00049     {
00050         return NRF_ERROR_DATA_SIZE;
00051     }
00052     actual_length = rem_adv_data_len = (BLE_GAP_ADV_MAX_SIZE - adv_offset - ADV_FLAG_OFFSET);
00053 
00054     // Get GAP device name and length
00055     err_code = sd_ble_gap_device_name_get(&p_encoded_data[adv_offset + ADV_DATA_OFFSET],
00056                                           &actual_length);
00057     if (err_code != NRF_SUCCESS)
00058     {
00059         return err_code;
00060     }
00061     
00062     // Check if device internd to use short name and it can fit available data size.
00063     if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
00064     {
00065         // Complete device name can fit, setting Complete Name in Adv Data.
00066         adv_data_format  = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
00067         rem_adv_data_len = actual_length;
00068     }
00069     else
00070     {
00071         // Else short name needs to be used. Or application has requested use of short name.
00072         adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
00073 
00074         // If application has set a preference on the short name size, it needs to be considered,
00075         // else fit what can be fit.
00076         if ((p_advdata->short_name_len != 0) && (p_advdata->short_name_len <= rem_adv_data_len))
00077         {
00078             // Short name fits available size.
00079             rem_adv_data_len = p_advdata->short_name_len;
00080         }
00081         // Else whatever can fit the data buffer will be packed.
00082         else
00083         {
00084             rem_adv_data_len = actual_length;
00085         }
00086     }
00087 
00088     // Complete name field in encoded data.
00089     p_encoded_data[adv_offset++] = rem_adv_data_len + 1;
00090     p_encoded_data[adv_offset++] = adv_data_format;
00091     (*p_len)                    += (rem_adv_data_len + ADV_DATA_OFFSET);
00092 
00093     return NRF_SUCCESS;
00094 }
00095 
00096 
00097 static uint32_t appearance_encode(uint8_t * p_encoded_data, uint8_t * p_len)
00098 {
00099     uint32_t err_code;
00100     uint16_t appearance;
00101 
00102     // Check for buffer overflow.
00103     if ((*p_len) + 4 > BLE_GAP_ADV_MAX_SIZE)
00104     {
00105         return NRF_ERROR_DATA_SIZE;
00106     }
00107 
00108     // Get GAP appearance field.
00109     err_code = sd_ble_gap_appearance_get(&appearance);
00110     if (err_code != NRF_SUCCESS)
00111     {
00112         return err_code;
00113     }
00114 
00115     // Encode Length, AD Type and Appearance.
00116     p_encoded_data[(*p_len)++] = 3;
00117     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_APPEARANCE;
00118 
00119     (*p_len) += uint16_encode(appearance, &p_encoded_data[*p_len]);
00120 
00121     return NRF_SUCCESS;
00122 }
00123 
00124 
00125 static uint32_t uint8_array_encode(const uint8_array_t * p_uint8_array,
00126                                    uint8_t               adv_type,
00127                                    uint8_t             * p_encoded_data,
00128                                    uint8_t             * p_len)
00129 {
00130     // Check parameter consistency.
00131     if (p_uint8_array->p_data == NULL)
00132     {
00133         return NRF_ERROR_INVALID_PARAM;
00134     }
00135 
00136     // Check for buffer overflow.
00137     if ((*p_len) + ADV_DATA_OFFSET + p_uint8_array->size > BLE_GAP_ADV_MAX_SIZE)
00138     {
00139         return NRF_ERROR_DATA_SIZE;
00140     }
00141 
00142     // Encode Length and AD Type.
00143     p_encoded_data[(*p_len)++] = 1 + p_uint8_array->size;
00144     p_encoded_data[(*p_len)++] = adv_type;
00145 
00146     // Encode array.
00147     memcpy(&p_encoded_data[*p_len], p_uint8_array->p_data, p_uint8_array->size);
00148     (*p_len) += p_uint8_array->size;
00149 
00150     return NRF_SUCCESS;
00151 }
00152 
00153 
00154 static uint32_t tx_power_level_encode(int8_t    tx_power_level,
00155                                       uint8_t * p_encoded_data,
00156                                       uint8_t * p_len)
00157 {
00158     // Check for buffer overflow.
00159     if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE)
00160     {
00161         return NRF_ERROR_DATA_SIZE;
00162     }
00163 
00164     // Encode TX Power Level.
00165     p_encoded_data[(*p_len)++] = 2;
00166     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
00167     p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level;
00168 
00169     return NRF_SUCCESS;
00170 }
00171 
00172 
00173 static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list,
00174                                        uint8_t                         adv_type,
00175                                        uint8_t                         uuid_size,
00176                                        uint8_t                       * p_encoded_data,
00177                                        uint8_t                       * p_len)
00178 {
00179     int     i;
00180     bool    is_heading_written = false;
00181     uint8_t start_pos          = *p_len;
00182 
00183     for (i = 0; i < p_uuid_list->uuid_cnt; i++)
00184     {
00185         uint32_t   err_code;
00186         uint8_t    encoded_size;
00187         ble_uuid_t uuid = p_uuid_list->p_uuids[i];
00188         
00189         // Find encoded uuid size.
00190         err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL);
00191         if (err_code != NRF_SUCCESS)
00192         {
00193             return err_code;
00194         }
00195 
00196         // Check size.
00197         if (encoded_size == uuid_size)
00198         {
00199             uint8_t heading_bytes = (is_heading_written) ? 0 : 2;
00200             
00201             // Check for buffer overflow
00202             if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE)
00203             {
00204                 return NRF_ERROR_DATA_SIZE;
00205             }
00206 
00207             if (!is_heading_written)
00208             {
00209                 // Write AD structure heading.
00210                 (*p_len)++;
00211                 p_encoded_data[(*p_len)++] = adv_type;
00212                 is_heading_written         = true;
00213             }
00214 
00215             // Write UUID.
00216             err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]);
00217             if (err_code != NRF_SUCCESS)
00218             {
00219                 return err_code;
00220             }
00221             (*p_len) += encoded_size;
00222         }
00223     }
00224 
00225     if (is_heading_written)
00226     {
00227         // Write length.
00228         p_encoded_data[start_pos] = (*p_len) - (start_pos + 1);
00229     }
00230 
00231     return NRF_SUCCESS;
00232 }
00233 
00234 
00235 static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list,
00236                                  uint8_t                         adv_type_16,
00237                                  uint8_t                         adv_type_128,
00238                                  uint8_t                       * p_encoded_data,
00239                                  uint8_t                       * p_len)
00240 {
00241     uint32_t err_code;
00242 
00243     // Encode 16 bit UUIDs.
00244     err_code = uuid_list_sized_encode(p_uuid_list,
00245                                       adv_type_16,
00246                                       sizeof(uint16_le_t),
00247                                       p_encoded_data,
00248                                       p_len);
00249     if (err_code != NRF_SUCCESS)
00250     {
00251         return err_code;
00252     }
00253 
00254     // Encode 128 bit UUIDs.
00255     err_code = uuid_list_sized_encode(p_uuid_list,
00256                                       adv_type_128,
00257                                       sizeof(ble_uuid128_t),
00258                                       p_encoded_data,
00259                                       p_len);
00260     if (err_code != NRF_SUCCESS)
00261     {
00262         return err_code;
00263     }
00264 
00265     return NRF_SUCCESS;
00266 }
00267 
00268 
00269 static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int)
00270 {
00271     // Check Minimum Connection Interval.
00272     if ((p_conn_int->min_conn_interval < 0x0006) ||
00273         (
00274             (p_conn_int->min_conn_interval > 0x0c80) &&
00275             (p_conn_int->min_conn_interval != 0xffff)
00276         )
00277        )
00278     {
00279         return NRF_ERROR_INVALID_PARAM;
00280     }
00281 
00282     // Check Maximum Connection Interval.
00283     if ((p_conn_int->max_conn_interval < 0x0006) || 
00284         (
00285             (p_conn_int->max_conn_interval > 0x0c80) && 
00286             (p_conn_int->max_conn_interval != 0xffff)
00287         )
00288        )
00289     {
00290         return NRF_ERROR_INVALID_PARAM;
00291     }
00292 
00293     // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval.
00294     if ((p_conn_int->min_conn_interval != 0xffff) &&
00295         (p_conn_int->max_conn_interval != 0xffff) &&
00296         (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval)
00297         )
00298     {
00299         return NRF_ERROR_INVALID_PARAM;
00300     }
00301 
00302     return NRF_SUCCESS;
00303 }
00304 
00305 
00306 static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int,
00307                                 uint8_t                      * p_encoded_data,
00308                                 uint8_t                      * p_len)
00309 {
00310     uint32_t err_code;
00311 
00312     // Check for buffer overflow.
00313     if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE)
00314     {
00315         return NRF_ERROR_DATA_SIZE;
00316     }
00317 
00318     // Check parameters.
00319     err_code = conn_int_check(p_conn_int);
00320     if (err_code != NRF_SUCCESS)
00321     {
00322         return err_code;
00323     }
00324 
00325     // Encode Length and AD Type.
00326     p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t);
00327     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE;
00328 
00329     // Encode Minimum and Maximum Connection Intervals.
00330     (*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]);
00331     (*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]);
00332 
00333     return NRF_SUCCESS;
00334 }
00335 
00336 
00337 static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data,
00338                                            uint8_t                        * p_encoded_data,
00339                                            uint8_t                        * p_len)
00340 {
00341     uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size;
00342 
00343     // Check for buffer overflow.
00344     if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE)
00345     {
00346         return NRF_ERROR_DATA_SIZE;
00347     }
00348 
00349     // Encode Length and AD Type.
00350     p_encoded_data[(*p_len)++] = 1 + data_size;
00351     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
00352     
00353     // Encode Company Identifier.
00354     (*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]);
00355     
00356     // Encode additional manufacturer specific data.
00357     if (p_manuf_sp_data->data.size > 0)
00358     {
00359         if (p_manuf_sp_data->data.p_data == NULL)
00360         {
00361             return NRF_ERROR_INVALID_PARAM;
00362         }
00363         memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size);
00364         (*p_len) += p_manuf_sp_data->data.size;
00365     }
00366 
00367     return NRF_SUCCESS;
00368 }
00369 
00370 
00371 static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
00372                                     uint8_t             * p_encoded_data,
00373                                     uint8_t             * p_len)
00374 {
00375     uint8_t i;
00376 
00377     // Check parameter consistency.
00378     if (p_advdata->p_service_data_array == NULL)
00379     {
00380         return NRF_ERROR_INVALID_PARAM;
00381     }
00382 
00383     for (i = 0; i < p_advdata->service_data_count; i++)
00384     {
00385         ble_advdata_service_data_t * p_service_data;
00386         uint8_t                      data_size;
00387 
00388         p_service_data = &p_advdata->p_service_data_array[i];
00389         data_size      = sizeof(uint16_le_t) + p_service_data->data.size;
00390 
00391         // Encode Length and AD Type.
00392         p_encoded_data[(*p_len)++] = 1 + data_size;
00393         p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA;
00394 
00395         // Encode service UUID.
00396         (*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
00397 
00398         // Encode additional service data.
00399         if (p_service_data->data.size > 0)
00400         {
00401             if (p_service_data->data.p_data == NULL)
00402             {
00403                 return NRF_ERROR_INVALID_PARAM;
00404             }
00405             memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
00406             (*p_len) += p_service_data->data.size;
00407         }
00408     }
00409 
00410     return NRF_SUCCESS;
00411 }
00412 
00413 
00414 static uint32_t adv_data_encode(const ble_advdata_t * p_advdata,
00415                                 uint8_t             * p_encoded_data,
00416                                 uint8_t             * p_len)
00417 {
00418     uint32_t err_code = NRF_SUCCESS;
00419 
00420     *p_len = 0;
00421 
00422     // Encode name.
00423     if (p_advdata->name_type != BLE_ADVDATA_NO_NAME)
00424     {
00425         err_code = name_encode(p_advdata, p_encoded_data, p_len);
00426         if (err_code != NRF_SUCCESS)
00427         {
00428             return err_code;
00429         }
00430     }
00431 
00432     // Encode appearance.
00433     if (p_advdata->include_appearance)
00434     {
00435         err_code = appearance_encode(p_encoded_data, p_len);
00436         if (err_code != NRF_SUCCESS)
00437         {
00438             return err_code;
00439         }
00440     }
00441 
00442     // Encode flags.
00443     if (p_advdata->flags.size > 0)
00444     {
00445         err_code = uint8_array_encode(&p_advdata->flags,
00446                                       BLE_GAP_AD_TYPE_FLAGS,
00447                                       p_encoded_data,
00448                                       p_len);
00449         if (err_code != NRF_SUCCESS)
00450         {
00451             return err_code;
00452         }
00453     }
00454 
00455     // Encode TX power level.
00456     if (p_advdata->p_tx_power_level != NULL)
00457     {
00458         err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len);
00459         if (err_code != NRF_SUCCESS)
00460         {
00461             return err_code;
00462         }
00463     }
00464     
00465     // Encode 'more available' uuid list.
00466     if (p_advdata->uuids_more_available.uuid_cnt > 0)
00467     {
00468         err_code = uuid_list_encode(&p_advdata->uuids_more_available,
00469                                     BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
00470                                     BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE,
00471                                     p_encoded_data,
00472                                     p_len);
00473         if (err_code != NRF_SUCCESS)
00474         {
00475             return err_code;
00476         }
00477     }
00478 
00479     // Encode 'complete' uuid list.
00480     if (p_advdata->uuids_complete.uuid_cnt > 0)
00481     {
00482         err_code = uuid_list_encode(&p_advdata->uuids_complete,
00483                                     BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
00484                                     BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
00485                                     p_encoded_data,
00486                                     p_len);
00487         if (err_code != NRF_SUCCESS)
00488         {
00489             return err_code;
00490         }
00491     }
00492 
00493     // Encode 'solicited service' uuid list.
00494     if (p_advdata->uuids_solicited.uuid_cnt > 0)
00495     {
00496         err_code = uuid_list_encode(&p_advdata->uuids_solicited,
00497                                     BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT,
00498                                     BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT,
00499                                     p_encoded_data,
00500                                     p_len);
00501         if (err_code != NRF_SUCCESS)
00502         {
00503             return err_code;
00504         }
00505     }
00506 
00507     // Encode Slave Connection Interval Range.
00508     if (p_advdata->p_slave_conn_int != NULL)
00509     {
00510         err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len);
00511         if (err_code != NRF_SUCCESS)
00512         {
00513             return err_code;
00514         }
00515     }
00516 
00517     // Encode Manufacturer Specific Data.
00518     if (p_advdata->p_manuf_specific_data != NULL)
00519     {
00520         err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data,
00521                                               p_encoded_data,
00522                                               p_len);
00523         if (err_code != NRF_SUCCESS)
00524         {
00525             return err_code;
00526         }
00527     }
00528 
00529     // Encode Service Data.
00530     if (p_advdata->service_data_count > 0)
00531     {
00532         err_code = service_data_encode(p_advdata, p_encoded_data, p_len);
00533         if (err_code != NRF_SUCCESS)
00534         {
00535             return err_code;
00536         }
00537     }
00538 
00539     return err_code;
00540 }
00541 
00542 
00543 static uint32_t advdata_check(const ble_advdata_t * p_advdata)
00544 {
00545     // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set.
00546     if ((p_advdata->flags.size == 0)      ||
00547         (p_advdata->flags.p_data == NULL) ||
00548         ((p_advdata->flags.p_data[0] & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)
00549        )
00550     {
00551         return NRF_ERROR_INVALID_PARAM;
00552     }
00553 
00554     return NRF_SUCCESS;
00555 }
00556 
00557 
00558 static uint32_t srdata_check(const ble_advdata_t * p_srdata)
00559 {
00560     // Flags shall not be included in the scan response data.
00561     if (p_srdata->flags.size > 0)
00562     {
00563         return NRF_ERROR_INVALID_PARAM;
00564     }
00565 
00566     return NRF_SUCCESS;
00567 }
00568 
00569 
00570 uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata)
00571 {
00572     uint32_t  err_code;
00573     uint8_t   len_advdata = 0;
00574     uint8_t   len_srdata  = 0;
00575     uint8_t   encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
00576     uint8_t   encoded_srdata[BLE_GAP_ADV_MAX_SIZE];
00577     uint8_t * p_encoded_advdata;
00578     uint8_t * p_encoded_srdata;
00579 
00580     // Encode advertising data (if supplied).
00581     if (p_advdata != NULL)
00582     {
00583         err_code = advdata_check(p_advdata);
00584         if (err_code != NRF_SUCCESS)
00585         {
00586             return err_code;
00587         }
00588 
00589         err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata);
00590         if (err_code != NRF_SUCCESS)
00591         {
00592             return err_code;
00593         }
00594         p_encoded_advdata = encoded_advdata;
00595     }
00596     else
00597     {
00598         p_encoded_advdata = NULL;
00599     }
00600 
00601     // Encode scan response data (if supplied).
00602     if (p_srdata != NULL)
00603     {
00604         err_code = srdata_check(p_srdata);
00605         if (err_code != NRF_SUCCESS)
00606         {
00607             return err_code;
00608         }
00609 
00610         err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata);
00611         if (err_code != NRF_SUCCESS)
00612         {
00613             return err_code;
00614         }
00615         p_encoded_srdata = encoded_srdata;
00616     }
00617     else
00618     {
00619         p_encoded_srdata = NULL;
00620     }
00621 
00622     // Pass encoded advertising data and/or scan response data to the stack.
00623     return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
00624 }