David Kester / nRF51822

Dependents:   GonioTrainer

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 tx_power_level_encode(int8_t    tx_power_level,
00126                                       uint8_t * p_encoded_data,
00127                                       uint8_t * p_len)
00128 {
00129     // Check for buffer overflow.
00130     if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE)
00131     {
00132         return NRF_ERROR_DATA_SIZE;
00133     }
00134 
00135     // Encode TX Power Level.
00136     p_encoded_data[(*p_len)++] = 2;
00137     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
00138     p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level;
00139 
00140     return NRF_SUCCESS;
00141 }
00142 
00143 
00144 static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list,
00145                                        uint8_t                         adv_type,
00146                                        uint8_t                         uuid_size,
00147                                        uint8_t                       * p_encoded_data,
00148                                        uint8_t                       * p_len)
00149 {
00150     int     i;
00151     bool    is_heading_written = false;
00152     uint8_t start_pos          = *p_len;
00153 
00154     for (i = 0; i < p_uuid_list->uuid_cnt; i++)
00155     {
00156         uint32_t   err_code;
00157         uint8_t    encoded_size;
00158         ble_uuid_t uuid = p_uuid_list->p_uuids[i];
00159         
00160         // Find encoded uuid size.
00161         err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL);
00162         if (err_code != NRF_SUCCESS)
00163         {
00164             return err_code;
00165         }
00166 
00167         // Check size.
00168         if (encoded_size == uuid_size)
00169         {
00170             uint8_t heading_bytes = (is_heading_written) ? 0 : 2;
00171             
00172             // Check for buffer overflow
00173             if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE)
00174             {
00175                 return NRF_ERROR_DATA_SIZE;
00176             }
00177 
00178             if (!is_heading_written)
00179             {
00180                 // Write AD structure heading.
00181                 (*p_len)++;
00182                 p_encoded_data[(*p_len)++] = adv_type;
00183                 is_heading_written         = true;
00184             }
00185 
00186             // Write UUID.
00187             err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]);
00188             if (err_code != NRF_SUCCESS)
00189             {
00190                 return err_code;
00191             }
00192             (*p_len) += encoded_size;
00193         }
00194     }
00195 
00196     if (is_heading_written)
00197     {
00198         // Write length.
00199         p_encoded_data[start_pos] = (*p_len) - (start_pos + 1);
00200     }
00201 
00202     return NRF_SUCCESS;
00203 }
00204 
00205 
00206 static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list,
00207                                  uint8_t                         adv_type_16,
00208                                  uint8_t                         adv_type_128,
00209                                  uint8_t                       * p_encoded_data,
00210                                  uint8_t                       * p_len)
00211 {
00212     uint32_t err_code;
00213 
00214     // Encode 16 bit UUIDs.
00215     err_code = uuid_list_sized_encode(p_uuid_list,
00216                                       adv_type_16,
00217                                       sizeof(uint16_le_t),
00218                                       p_encoded_data,
00219                                       p_len);
00220     if (err_code != NRF_SUCCESS)
00221     {
00222         return err_code;
00223     }
00224 
00225     // Encode 128 bit UUIDs.
00226     err_code = uuid_list_sized_encode(p_uuid_list,
00227                                       adv_type_128,
00228                                       sizeof(ble_uuid128_t),
00229                                       p_encoded_data,
00230                                       p_len);
00231     if (err_code != NRF_SUCCESS)
00232     {
00233         return err_code;
00234     }
00235 
00236     return NRF_SUCCESS;
00237 }
00238 
00239 
00240 static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int)
00241 {
00242     // Check Minimum Connection Interval.
00243     if ((p_conn_int->min_conn_interval < 0x0006) ||
00244         (
00245             (p_conn_int->min_conn_interval > 0x0c80) &&
00246             (p_conn_int->min_conn_interval != 0xffff)
00247         )
00248        )
00249     {
00250         return NRF_ERROR_INVALID_PARAM;
00251     }
00252 
00253     // Check Maximum Connection Interval.
00254     if ((p_conn_int->max_conn_interval < 0x0006) || 
00255         (
00256             (p_conn_int->max_conn_interval > 0x0c80) && 
00257             (p_conn_int->max_conn_interval != 0xffff)
00258         )
00259        )
00260     {
00261         return NRF_ERROR_INVALID_PARAM;
00262     }
00263 
00264     // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval.
00265     if ((p_conn_int->min_conn_interval != 0xffff) &&
00266         (p_conn_int->max_conn_interval != 0xffff) &&
00267         (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval)
00268         )
00269     {
00270         return NRF_ERROR_INVALID_PARAM;
00271     }
00272 
00273     return NRF_SUCCESS;
00274 }
00275 
00276 
00277 static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int,
00278                                 uint8_t                      * p_encoded_data,
00279                                 uint8_t                      * p_len)
00280 {
00281     uint32_t err_code;
00282 
00283     // Check for buffer overflow.
00284     if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE)
00285     {
00286         return NRF_ERROR_DATA_SIZE;
00287     }
00288 
00289     // Check parameters.
00290     err_code = conn_int_check(p_conn_int);
00291     if (err_code != NRF_SUCCESS)
00292     {
00293         return err_code;
00294     }
00295 
00296     // Encode Length and AD Type.
00297     p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t);
00298     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE;
00299 
00300     // Encode Minimum and Maximum Connection Intervals.
00301     (*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]);
00302     (*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]);
00303 
00304     return NRF_SUCCESS;
00305 }
00306 
00307 
00308 static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data,
00309                                            uint8_t                        * p_encoded_data,
00310                                            uint8_t                        * p_len)
00311 {
00312     uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size;
00313 
00314     // Check for buffer overflow.
00315     if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE)
00316     {
00317         return NRF_ERROR_DATA_SIZE;
00318     }
00319 
00320     // Encode Length and AD Type.
00321     p_encoded_data[(*p_len)++] = 1 + data_size;
00322     p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
00323     
00324     // Encode Company Identifier.
00325     (*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]);
00326     
00327     // Encode additional manufacturer specific data.
00328     if (p_manuf_sp_data->data.size > 0)
00329     {
00330         if (p_manuf_sp_data->data.p_data == NULL)
00331         {
00332             return NRF_ERROR_INVALID_PARAM;
00333         }
00334         memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size);
00335         (*p_len) += p_manuf_sp_data->data.size;
00336     }
00337 
00338     return NRF_SUCCESS;
00339 }
00340 
00341 
00342 static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
00343                                     uint8_t             * p_encoded_data,
00344                                     uint8_t             * p_len)
00345 {
00346     uint8_t i;
00347 
00348     // Check parameter consistency.
00349     if (p_advdata->p_service_data_array == NULL)
00350     {
00351         return NRF_ERROR_INVALID_PARAM;
00352     }
00353 
00354     for (i = 0; i < p_advdata->service_data_count; i++)
00355     {
00356         ble_advdata_service_data_t * p_service_data;
00357         uint8_t                      data_size;
00358 
00359         p_service_data = &p_advdata->p_service_data_array[i];
00360         data_size      = sizeof(uint16_le_t) + p_service_data->data.size;
00361 
00362         // Encode Length and AD Type.
00363         p_encoded_data[(*p_len)++] = 1 + data_size;
00364         p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA;
00365 
00366         // Encode service UUID.
00367         (*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
00368 
00369         // Encode additional service data.
00370         if (p_service_data->data.size > 0)
00371         {
00372             if (p_service_data->data.p_data == NULL)
00373             {
00374                 return NRF_ERROR_INVALID_PARAM;
00375             }
00376             memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
00377             (*p_len) += p_service_data->data.size;
00378         }
00379     }
00380 
00381     return NRF_SUCCESS;
00382 }
00383 
00384 
00385 static uint32_t adv_data_encode(const ble_advdata_t * p_advdata,
00386                                 uint8_t             * p_encoded_data,
00387                                 uint8_t             * p_len)
00388 {
00389     uint32_t err_code = NRF_SUCCESS;
00390 
00391     *p_len = 0;
00392 
00393     // Encode name.
00394     if (p_advdata->name_type != BLE_ADVDATA_NO_NAME)
00395     {
00396         err_code = name_encode(p_advdata, p_encoded_data, p_len);
00397         if (err_code != NRF_SUCCESS)
00398         {
00399             return err_code;
00400         }
00401     }
00402 
00403     // Encode appearance.
00404     if (p_advdata->include_appearance)
00405     {
00406         err_code = appearance_encode(p_encoded_data, p_len);
00407         if (err_code != NRF_SUCCESS)
00408         {
00409             return err_code;
00410         }
00411     }
00412 
00413     if(p_advdata->flags != 0 )
00414     {
00415         // Encode flags.
00416         p_encoded_data[(*p_len)++] = 1 + sizeof(uint8_t);
00417         p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_FLAGS;
00418         p_encoded_data[(*p_len)++] = p_advdata->flags;
00419     } 
00420 
00421     // Encode TX power level.
00422     if (p_advdata->p_tx_power_level != NULL)
00423     {
00424         err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len);
00425         if (err_code != NRF_SUCCESS)
00426         {
00427             return err_code;
00428         }
00429     }
00430     
00431     // Encode 'more available' uuid list.
00432     if (p_advdata->uuids_more_available.uuid_cnt > 0)
00433     {
00434         err_code = uuid_list_encode(&p_advdata->uuids_more_available,
00435                                     BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
00436                                     BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE,
00437                                     p_encoded_data,
00438                                     p_len);
00439         if (err_code != NRF_SUCCESS)
00440         {
00441             return err_code;
00442         }
00443     }
00444 
00445     // Encode 'complete' uuid list.
00446     if (p_advdata->uuids_complete.uuid_cnt > 0)
00447     {
00448         err_code = uuid_list_encode(&p_advdata->uuids_complete,
00449                                     BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
00450                                     BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
00451                                     p_encoded_data,
00452                                     p_len);
00453         if (err_code != NRF_SUCCESS)
00454         {
00455             return err_code;
00456         }
00457     }
00458 
00459     // Encode 'solicited service' uuid list.
00460     if (p_advdata->uuids_solicited.uuid_cnt > 0)
00461     {
00462         err_code = uuid_list_encode(&p_advdata->uuids_solicited,
00463                                     BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT,
00464                                     BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT,
00465                                     p_encoded_data,
00466                                     p_len);
00467         if (err_code != NRF_SUCCESS)
00468         {
00469             return err_code;
00470         }
00471     }
00472 
00473     // Encode Slave Connection Interval Range.
00474     if (p_advdata->p_slave_conn_int != NULL)
00475     {
00476         err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len);
00477         if (err_code != NRF_SUCCESS)
00478         {
00479             return err_code;
00480         }
00481     }
00482 
00483     // Encode Manufacturer Specific Data.
00484     if (p_advdata->p_manuf_specific_data != NULL)
00485     {
00486         err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data,
00487                                               p_encoded_data,
00488                                               p_len);
00489         if (err_code != NRF_SUCCESS)
00490         {
00491             return err_code;
00492         }
00493     }
00494 
00495     // Encode Service Data.
00496     if (p_advdata->service_data_count > 0)
00497     {
00498         err_code = service_data_encode(p_advdata, p_encoded_data, p_len);
00499         if (err_code != NRF_SUCCESS)
00500         {
00501             return err_code;
00502         }
00503     }
00504 
00505     return err_code;
00506 }
00507 
00508 
00509 static uint32_t advdata_check(const ble_advdata_t * p_advdata)
00510 {
00511     // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set.
00512     if (
00513         ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)
00514        )
00515     {
00516         return NRF_ERROR_INVALID_PARAM;
00517     }
00518 
00519     return NRF_SUCCESS;
00520 }
00521 
00522 
00523 static uint32_t srdata_check(const ble_advdata_t * p_srdata)
00524 {
00525     // Flags shall not be included in the scan response data.
00526     if (p_srdata->flags)
00527     {
00528         return NRF_ERROR_INVALID_PARAM;
00529     }
00530 
00531     return NRF_SUCCESS;
00532 }
00533 
00534 
00535 uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata)
00536 {
00537     uint32_t  err_code;
00538     uint8_t   len_advdata = 0;
00539     uint8_t   len_srdata  = 0;
00540     uint8_t   encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
00541     uint8_t   encoded_srdata[BLE_GAP_ADV_MAX_SIZE];
00542     uint8_t * p_encoded_advdata;
00543     uint8_t * p_encoded_srdata;
00544 
00545     // Encode advertising data (if supplied).
00546     if (p_advdata != NULL)
00547     {
00548         err_code = advdata_check(p_advdata);
00549         if (err_code != NRF_SUCCESS)
00550         {
00551             return err_code;
00552         }
00553 
00554         err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata);
00555         if (err_code != NRF_SUCCESS)
00556         {
00557             return err_code;
00558         }
00559         p_encoded_advdata = encoded_advdata;
00560     }
00561     else
00562     {
00563         p_encoded_advdata = NULL;
00564     }
00565 
00566     // Encode scan response data (if supplied).
00567     if (p_srdata != NULL)
00568     {
00569         err_code = srdata_check(p_srdata);
00570         if (err_code != NRF_SUCCESS)
00571         {
00572             return err_code;
00573         }
00574 
00575         err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata);
00576         if (err_code != NRF_SUCCESS)
00577         {
00578             return err_code;
00579         }
00580         p_encoded_srdata = encoded_srdata;
00581     }
00582     else
00583     {
00584         p_encoded_srdata = NULL;
00585     }
00586 
00587     // Pass encoded advertising data and/or scan response data to the stack.
00588     return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
00589 }