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 if (memcmp(convertedUUIDTable[i].uuid, uuid, LENGTH_OF_LONG_UUID) == 0) { 00046 *recoveredType = convertedUUIDTable[i].type; 00047 return true; 00048 } 00049 } 00050 00051 return false; 00052 } 00053 00054 static void 00055 addToConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t type) 00056 { 00057 if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) { 00058 return; /* recovery needed; or at least the user should be warned about this fact.*/ 00059 } 00060 00061 memcpy(convertedUUIDTable[uuidTableEntries].uuid, uuid,LENGTH_OF_LONG_UUID); 00062 convertedUUIDTable[uuidTableEntries].type = type; 00063 uuidTableEntries++; 00064 } 00065 00066 /** 00067 * The nRF transport has its own 3-byte representation of a UUID. If the user- 00068 * specified UUID is 128-bits wide, then the UUID base needs to be added to the 00069 * soft-device and converted to a 3-byte handle before being used further. This 00070 * function is responsible for this translation of user-specified UUIDs into 00071 * nRF's representation. 00072 * 00073 * @param[in] uuid 00074 * user-specified UUID 00075 * @return nRF 00076 * 3-byte UUID (containing a type and 16-bit UUID) representation 00077 * to be used with SVC calls. 00078 */ 00079 ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid) 00080 { 00081 ble_uuid_t nordicUUID = { 00082 .uuid = uuid.getShortUUID(), 00083 .type = BLE_UUID_TYPE_UNKNOWN /* to be set below */ 00084 }; 00085 00086 if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) { 00087 nordicUUID.type = BLE_UUID_TYPE_BLE; 00088 } else { 00089 if (!lookupConvertedUUIDTable(uuid.getBaseUUID(), &nordicUUID.type)) { 00090 nordicUUID.type = custom_add_uuid_base(uuid.getBaseUUID()); 00091 addToConvertedUUIDTable(uuid.getBaseUUID(), nordicUUID.type); 00092 } 00093 } 00094 00095 return nordicUUID; 00096 } 00097 00098 /**************************************************************************/ 00099 /*! 00100 @brief Adds the base UUID to the custom service. All UUIDs used 00101 by this service are based on this 128-bit UUID. 00102 00103 @note This UUID needs to be added to the SoftDevice stack before 00104 adding the service's primary service via 00105 'sd_ble_gatts_service_add' 00106 00107 @param[in] p_uuid_base A pointer to the 128-bit UUID array (8*16) 00108 00109 @returns The UUID type. 00110 A return value of 0 should be considered an error. 00111 00112 @retval 0x00 BLE_UUID_TYPE_UNKNOWN 00113 @retval 0x01 BLE_UUID_TYPE_BLE 00114 @retval 0x02 BLE_UUID_TYPE_VENDOR_BEGIN 00115 00116 @section EXAMPLE 00117 @code 00118 00119 // Take note that bytes 2/3 are blank since these are used to identify 00120 // the primary service and individual characteristics 00121 #define CFG_CUSTOM_UUID_BASE "\x6E\x40\x00\x00\xB5\xA3\xF3\x93\xE0\xA9\xE5\x0E\x24\xDC\xCA\x9E" 00122 00123 uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE); 00124 ASSERT(uuid_type > 0, ERROR_NOT_FOUND); 00125 00126 // We can now safely add the primary service and any characteristics 00127 // for our custom service ... 00128 00129 @endcode 00130 */ 00131 /**************************************************************************/ 00132 uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base) 00133 { 00134 ble_uuid128_t base_uuid; 00135 uint8_t uuid_type = 0; 00136 00137 /* Reverse the bytes since ble_uuid128_t is LSB */ 00138 for (uint8_t i = 0; i<16; i++) { 00139 base_uuid.uuid128[i] = p_uuid_base[15 - i]; 00140 } 00141 00142 ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0); 00143 00144 return uuid_type; 00145 } 00146 00147 /**************************************************************************/ 00148 /*! 00149 00150 */ 00151 /**************************************************************************/ 00152 error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base, 00153 ble_uuid_t *p_uuid) 00154 { 00155 LongUUIDBytes_t uuid_base_le; 00156 00157 /* Reverse the bytes since ble_uuid128_t is LSB */ 00158 for (uint8_t i = 0; i<16; i++) { 00159 uuid_base_le[i] = p_uuid_base[15 - i]; 00160 } 00161 00162 ASSERT_STATUS( sd_ble_uuid_decode(16, uuid_base_le, p_uuid)); 00163 00164 return ERROR_NONE; 00165 } 00166 00167 /**************************************************************************/ 00168 /*! 00169 @brief Adds a new characteristic to the custom service, assigning 00170 properties, a UUID add-on value, etc. 00171 00172 @param[in] service_handle 00173 @param[in] p_uuid The 16-bit value to add to the base UUID 00174 for this characteristic (normally >1 00175 since 1 is typically used by the primary 00176 service). 00177 @param[in] char_props The characteristic properties, as 00178 defined by ble_gatt_char_props_t 00179 @param[in] max_length The maximum length of this characeristic 00180 @param[in] p_char_handle 00181 00182 @returns 00183 @retval ERROR_NONE Everything executed normally 00184 */ 00185 /**************************************************************************/ 00186 error_t custom_add_in_characteristic(uint16_t service_handle, 00187 ble_uuid_t *p_uuid, 00188 uint8_t properties, 00189 uint8_t *p_data, 00190 uint16_t min_length, 00191 uint16_t max_length, 00192 bool readAuthorization, 00193 bool writeAuthorization, 00194 ble_gatts_char_handles_t *p_char_handle) 00195 { 00196 /* Characteristic metadata */ 00197 ble_gatts_attr_md_t cccd_md; 00198 ble_gatt_char_props_t char_props; 00199 00200 memcpy(&char_props, &properties, 1); 00201 00202 if (char_props.notify || char_props.indicate) { 00203 /* Notification requires cccd */ 00204 memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); 00205 cccd_md.vloc = BLE_GATTS_VLOC_STACK; 00206 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); 00207 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); 00208 } 00209 00210 ble_gatts_char_md_t char_md = {0}; 00211 00212 char_md.char_props = char_props; 00213 char_md.p_cccd_md = 00214 (char_props.notify || char_props.indicate) ? &cccd_md : NULL; 00215 00216 /* Attribute declaration */ 00217 ble_gatts_attr_md_t attr_md = {0}; 00218 00219 attr_md.rd_auth = readAuthorization; 00220 attr_md.wr_auth = writeAuthorization; 00221 00222 attr_md.vloc = BLE_GATTS_VLOC_STACK; 00223 attr_md.vlen = (min_length == max_length) ? 0 : 1; 00224 00225 if (char_props.read || char_props.notify || char_props.indicate) { 00226 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); 00227 } 00228 00229 if (char_props.write || char_props.write_wo_resp) { 00230 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); 00231 } 00232 00233 ble_gatts_attr_t attr_char_value = {0}; 00234 00235 attr_char_value.p_uuid = p_uuid; 00236 attr_char_value.p_attr_md = &attr_md; 00237 attr_char_value.init_len = min_length; 00238 attr_char_value.max_len = max_length; 00239 attr_char_value.p_value = p_data; 00240 00241 ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle, 00242 &char_md, 00243 &attr_char_value, 00244 p_char_handle)); 00245 00246 return ERROR_NONE; 00247 } 00248 00249 00250 00251 /**************************************************************************/ 00252 /*! 00253 @brief Adds a new descriptor to the custom service, assigning 00254 value, a UUID add-on value, etc. 00255 00256 @param[in] char_handle 00257 @param[in] p_uuid The 16-bit value to add to the base UUID 00258 for this descriptor (normally >1 00259 since 1 is typically used by the primary 00260 service). 00261 @param[in] max_length The maximum length of this descriptor 00262 00263 @returns 00264 @retval ERROR_NONE Everything executed normally 00265 */ 00266 /**************************************************************************/ 00267 error_t custom_add_in_descriptor(uint16_t char_handle, 00268 ble_uuid_t *p_uuid, 00269 uint8_t *p_data, 00270 uint16_t min_length, 00271 uint16_t max_length, 00272 uint16_t *p_desc_handle) 00273 { 00274 /* Descriptor metadata */ 00275 ble_gatts_attr_md_t desc_md = {0}; 00276 00277 desc_md.vloc = BLE_GATTS_VLOC_STACK; 00278 desc_md.vlen = (min_length == max_length) ? 0 : 1; 00279 00280 /* Make it readable and writable */ 00281 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm); 00282 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm); 00283 00284 ble_gatts_attr_t attr_desc = {0}; 00285 00286 attr_desc.p_uuid = p_uuid; 00287 attr_desc.p_attr_md = &desc_md; 00288 attr_desc.init_len = min_length; 00289 attr_desc.max_len = max_length; 00290 attr_desc.p_value = p_data; 00291 00292 ASSERT_STATUS ( sd_ble_gatts_descriptor_add(char_handle, 00293 &attr_desc, 00294 p_desc_handle)); 00295 00296 return ERROR_NONE; 00297 }
Generated on Tue Jul 12 2022 15:04:23 by
1.7.2
