test

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