Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF51822 by
custom_helper.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "custom_helper.h" 00018 00019 /* 00020 * The current version of the soft-device doesn't handle duplicate 128-bit UUIDs 00021 * very well. It is therefore necessary to filter away duplicates before 00022 * passing long UUIDs to sd_ble_uuid_vs_add(). The following types and data 00023 * structures involved in maintaining a local cache of 128-bit UUIDs. 00024 */ 00025 typedef struct { 00026 LongUUIDBytes_t uuid; 00027 uint8_t type; 00028 } converted_uuid_table_entry_t; 00029 static const unsigned UUID_TABLE_MAX_ENTRIES = 8; /* This is the maximum number of 128-bit UUIDs with distinct bases that 00030 * we expect to be in use; increase this limit if needed. */ 00031 static unsigned uuidTableEntries = 0; /* current usage of the table */ 00032 converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES]; 00033 00034 /** 00035 * lookup the cache of previously converted 128-bit UUIDs to find a type value. 00036 * @param uuid base 128-bit UUID 00037 * @param recoveredType the type field of the 3-byte nRF's uuid. 00038 * @return true if a match is found. 00039 */ 00040 static bool 00041 lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType) 00042 { 00043 unsigned i; 00044 for (i = 0; i < uuidTableEntries; i++) { 00045 unsigned byteIndex; 00046 for (byteIndex = 0; byteIndex < LENGTH_OF_LONG_UUID; byteIndex++) { 00047 /* Skip bytes 2 and 3, because they contain the shortUUID (16-bit) version of the 00048 * long UUID; and we're comparing against the remainder. */ 00049 if ((byteIndex == 2) || (byteIndex == 3)) { 00050 continue; 00051 } 00052 00053 if (convertedUUIDTable[i].uuid[byteIndex] != uuid[byteIndex]) { 00054 break; 00055 } 00056 } 00057 00058 if (byteIndex == LENGTH_OF_LONG_UUID) { 00059 *recoveredType = convertedUUIDTable[i].type; 00060 return true; 00061 } 00062 } 00063 00064 return false; 00065 } 00066 00067 static void 00068 addToConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t type) 00069 { 00070 if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) { 00071 return; /* recovery needed; or at least the user should be warned about this fact.*/ 00072 } 00073 00074 memcpy(convertedUUIDTable[uuidTableEntries].uuid, uuid, LENGTH_OF_LONG_UUID); 00075 convertedUUIDTable[uuidTableEntries].uuid[2] = 0; 00076 convertedUUIDTable[uuidTableEntries].uuid[3] = 0; 00077 convertedUUIDTable[uuidTableEntries].type = type; 00078 uuidTableEntries++; 00079 } 00080 00081 /** 00082 * The nRF transport has its own 3-byte representation of a UUID. If the user- 00083 * specified UUID is 128-bits wide, then the UUID base needs to be added to the 00084 * soft-device and converted to a 3-byte handle before being used further. This 00085 * function is responsible for this translation of user-specified UUIDs into 00086 * nRF's representation. 00087 * 00088 * @param[in] uuid 00089 * user-specified UUID 00090 * @return nRF 00091 * 3-byte UUID (containing a type and 16-bit UUID) representation 00092 * to be used with SVC calls. 00093 */ 00094 ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid) 00095 { 00096 ble_uuid_t nordicUUID = { 00097 .uuid = uuid.getShortUUID(), 00098 .type = BLE_UUID_TYPE_UNKNOWN /* to be set below */ 00099 }; 00100 00101 if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) { 00102 nordicUUID.type = BLE_UUID_TYPE_BLE; 00103 } else { 00104 if (!lookupConvertedUUIDTable(uuid.getBaseUUID(), &nordicUUID.type)) { 00105 nordicUUID.type = custom_add_uuid_base(uuid.getBaseUUID()); 00106 addToConvertedUUIDTable(uuid.getBaseUUID(), nordicUUID.type); 00107 } 00108 } 00109 00110 return nordicUUID; 00111 } 00112 00113 /**************************************************************************/ 00114 /*! 00115 @brief Adds the base UUID to the custom service. All UUIDs used 00116 by this service are based on this 128-bit UUID. 00117 00118 @note This UUID needs to be added to the SoftDevice stack before 00119 adding the service's primary service via 00120 'sd_ble_gatts_service_add' 00121 00122 @param[in] p_uuid_base A pointer to the 128-bit UUID array (8*16) 00123 00124 @returns The UUID type. 00125 A return value of 0 should be considered an error. 00126 00127 @retval 0x00 BLE_UUID_TYPE_UNKNOWN 00128 @retval 0x01 BLE_UUID_TYPE_BLE 00129 @retval 0x02 BLE_UUID_TYPE_VENDOR_BEGIN 00130 00131 @section EXAMPLE 00132 @code 00133 00134 // Take note that bytes 2/3 are blank since these are used to identify 00135 // the primary service and individual characteristics 00136 #define CFG_CUSTOM_UUID_BASE "\x6E\x40\x00\x00\xB5\xA3\xF3\x93\xE0\xA9\xE5\x0E\x24\xDC\xCA\x9E" 00137 00138 uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE); 00139 ASSERT(uuid_type > 0, ERROR_NOT_FOUND); 00140 00141 // We can now safely add the primary service and any characteristics 00142 // for our custom service ... 00143 00144 @endcode 00145 */ 00146 /**************************************************************************/ 00147 uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base) 00148 { 00149 ble_uuid128_t base_uuid; 00150 uint8_t uuid_type = 0; 00151 00152 /* Reverse the bytes since ble_uuid128_t is LSB */ 00153 for (unsigned i = 0; i < LENGTH_OF_LONG_UUID; i++) { 00154 base_uuid.uuid128[i] = p_uuid_base[LENGTH_OF_LONG_UUID - 1 - i]; 00155 } 00156 00157 ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0); 00158 00159 return uuid_type; 00160 } 00161 00162 /**************************************************************************/ 00163 /*! 00164 00165 */ 00166 /**************************************************************************/ 00167 error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base, 00168 ble_uuid_t *p_uuid) 00169 { 00170 LongUUIDBytes_t uuid_base_le; 00171 00172 /* Reverse the bytes since ble_uuid128_t is LSB */ 00173 for (uint8_t i = 0; i < LENGTH_OF_LONG_UUID; i++) { 00174 uuid_base_le[i] = p_uuid_base[LENGTH_OF_LONG_UUID - 1 - i]; 00175 } 00176 00177 ASSERT_STATUS( sd_ble_uuid_decode(LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid)); 00178 00179 return ERROR_NONE; 00180 } 00181 00182 /**************************************************************************/ 00183 /*! 00184 @brief Adds a new characteristic to the custom service, assigning 00185 properties, a UUID add-on value, etc. 00186 00187 @param[in] service_handle 00188 @param[in] p_uuid The 16-bit value to add to the base UUID 00189 for this characteristic (normally >1 00190 since 1 is typically used by the primary 00191 service). 00192 @param[in] char_props The characteristic properties, as 00193 defined by ble_gatt_char_props_t 00194 @param[in] max_length The maximum length of this characeristic 00195 @param[in] p_char_handle 00196 00197 @returns 00198 @retval ERROR_NONE Everything executed normally 00199 */ 00200 /**************************************************************************/ 00201 error_t custom_add_in_characteristic(uint16_t service_handle, 00202 ble_uuid_t *p_uuid, 00203 uint8_t properties, 00204 uint8_t *p_data, 00205 uint16_t min_length, 00206 uint16_t max_length, 00207 bool readAuthorization, 00208 bool writeAuthorization, 00209 ble_gatts_char_handles_t *p_char_handle) 00210 { 00211 /* Characteristic metadata */ 00212 ble_gatts_attr_md_t cccd_md; 00213 ble_gatt_char_props_t char_props; 00214 00215 memcpy(&char_props, &properties, 1); 00216 00217 if (char_props.notify || char_props.indicate) { 00218 /* Notification requires cccd */ 00219 memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); 00220 cccd_md.vloc = BLE_GATTS_VLOC_STACK; 00221 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); 00222 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); 00223 } 00224 00225 ble_gatts_char_md_t char_md = {0}; 00226 00227 char_md.char_props = char_props; 00228 char_md.p_cccd_md = 00229 (char_props.notify || char_props.indicate) ? &cccd_md : NULL; 00230 00231 /* Attribute declaration */ 00232 ble_gatts_attr_md_t attr_md = {0}; 00233 00234 attr_md.rd_auth = readAuthorization; 00235 attr_md.wr_auth = writeAuthorization; 00236 00237 attr_md.vloc = BLE_GATTS_VLOC_STACK; 00238 attr_md.vlen = (min_length == max_length) ? 0 : 1; 00239 00240 if (char_props.read || char_props.notify || char_props.indicate) { 00241 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); 00242 } 00243 00244 if (char_props.write || char_props.write_wo_resp) { 00245 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); 00246 } 00247 00248 ble_gatts_attr_t attr_char_value = {0}; 00249 00250 attr_char_value.p_uuid = p_uuid; 00251 attr_char_value.p_attr_md = &attr_md; 00252 attr_char_value.init_len = min_length; 00253 attr_char_value.max_len = max_length; 00254 attr_char_value.p_value = p_data; 00255 00256 ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle, 00257 &char_md, 00258 &attr_char_value, 00259 p_char_handle)); 00260 00261 return ERROR_NONE; 00262 } 00263 00264 00265 00266 /**************************************************************************/ 00267 /*! 00268 @brief Adds a new descriptor to the custom service, assigning 00269 value, a UUID add-on value, etc. 00270 00271 @param[in] char_handle 00272 @param[in] p_uuid The 16-bit value to add to the base UUID 00273 for this descriptor (normally >1 00274 since 1 is typically used by the primary 00275 service). 00276 @param[in] max_length The maximum length of this descriptor 00277 00278 @returns 00279 @retval ERROR_NONE Everything executed normally 00280 */ 00281 /**************************************************************************/ 00282 error_t custom_add_in_descriptor(uint16_t char_handle, 00283 ble_uuid_t *p_uuid, 00284 uint8_t *p_data, 00285 uint16_t min_length, 00286 uint16_t max_length, 00287 uint16_t *p_desc_handle) 00288 { 00289 /* Descriptor metadata */ 00290 ble_gatts_attr_md_t desc_md = {0}; 00291 00292 desc_md.vloc = BLE_GATTS_VLOC_STACK; 00293 desc_md.vlen = (min_length == max_length) ? 0 : 1; 00294 00295 /* Make it readable and writable */ 00296 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm); 00297 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm); 00298 00299 ble_gatts_attr_t attr_desc = {0}; 00300 00301 attr_desc.p_uuid = p_uuid; 00302 attr_desc.p_attr_md = &desc_md; 00303 attr_desc.init_len = min_length; 00304 attr_desc.max_len = max_length; 00305 attr_desc.p_value = p_data; 00306 00307 ASSERT_STATUS ( sd_ble_gatts_descriptor_add(char_handle, 00308 &attr_desc, 00309 p_desc_handle)); 00310 00311 return ERROR_NONE; 00312 }
Generated on Tue Jul 12 2022 19:34:26 by
1.7.2
