fka mod

Fork of BLE_API by Bluetooth Low Energy

Committer:
vcoubard
Date:
Mon Jan 11 08:51:39 2016 +0000
Revision:
1066:980dd95eb920
Parent:
1065:473735376f13
Child:
1070:4f42630b9c9e
Synchronized with git rev e9d0a856
Author: Vincent Coubard
Improve description of class DiscoveredCharacteristic

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 716:11b41f651697 1 /* mbed Microcontroller Library
rgrover1 716:11b41f651697 2 * Copyright (c) 2006-2013 ARM Limited
rgrover1 716:11b41f651697 3 *
rgrover1 716:11b41f651697 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 716:11b41f651697 5 * you may not use this file except in compliance with the License.
rgrover1 716:11b41f651697 6 * You may obtain a copy of the License at
rgrover1 716:11b41f651697 7 *
rgrover1 716:11b41f651697 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 716:11b41f651697 9 *
rgrover1 716:11b41f651697 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 716:11b41f651697 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 716:11b41f651697 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 716:11b41f651697 13 * See the License for the specific language governing permissions and
rgrover1 716:11b41f651697 14 * limitations under the License.
rgrover1 716:11b41f651697 15 */
rgrover1 716:11b41f651697 16
rgrover1 716:11b41f651697 17 #ifndef __DISCOVERED_CHARACTERISTIC_H__
rgrover1 716:11b41f651697 18 #define __DISCOVERED_CHARACTERISTIC_H__
rgrover1 716:11b41f651697 19
rgrover1 716:11b41f651697 20 #include "UUID.h"
rgrover1 716:11b41f651697 21 #include "Gap.h"
rgrover1 716:11b41f651697 22 #include "GattAttribute.h"
rgrover1 716:11b41f651697 23 #include "GattClient.h"
vcoubard 1063:187f9929cb60 24 #include "CharacteristicDescriptorDiscovery.h"
vcoubard 1063:187f9929cb60 25 #include "ble/DiscoveredCharacteristicDescriptor.h"
vcoubard 1063:187f9929cb60 26
rgrover1 716:11b41f651697 27 /**
vcoubard 1066:980dd95eb920 28 * @brief Representation of a characteristic discovered during a GattClient
vcoubard 1066:980dd95eb920 29 * discovery procedure (see GattClient::launchServiceDiscovery ).
vcoubard 1066:980dd95eb920 30 *
vcoubard 1066:980dd95eb920 31 * @detail Provide detailed informations about a discovered characteristic like:
vcoubard 1066:980dd95eb920 32 * - Its UUID (see getUUID).
vcoubard 1066:980dd95eb920 33 * - The most important handles of the characteristic definition
vcoubard 1066:980dd95eb920 34 * (see getDeclHandle, getValueHandle, getLastHandle )
vcoubard 1066:980dd95eb920 35 * - Its properties (see getProperties).
vcoubard 1066:980dd95eb920 36 * This class also provide functions to operate on the characteristic:
vcoubard 1066:980dd95eb920 37 * - Read the characteristic value (see read)
vcoubard 1066:980dd95eb920 38 * - Writing a characteristic value (see write or writeWoResponse)
vcoubard 1066:980dd95eb920 39 * - Discover descriptors inside the characteristic definition. These descriptors
vcoubard 1066:980dd95eb920 40 * extends the characteristic. More information about descriptor usage is
vcoubard 1066:980dd95eb920 41 * available in DiscoveredCharacteristicDescriptor class.
rgrover1 716:11b41f651697 42 */
rgrover1 716:11b41f651697 43 class DiscoveredCharacteristic {
rgrover1 716:11b41f651697 44 public:
rgrover1 716:11b41f651697 45 struct Properties_t {
vcoubard 1048:efb29faf12fc 46 uint8_t _broadcast :1; /**< Broadcasting the value permitted. */
rgrover1 716:11b41f651697 47 uint8_t _read :1; /**< Reading the value permitted. */
rgrover1 716:11b41f651697 48 uint8_t _writeWoResp :1; /**< Writing the value with Write Command permitted. */
rgrover1 716:11b41f651697 49 uint8_t _write :1; /**< Writing the value with Write Request permitted. */
vcoubard 1065:473735376f13 50 uint8_t _notify :1; /**< Notifications of the value permitted. */
rgrover1 716:11b41f651697 51 uint8_t _indicate :1; /**< Indications of the value permitted. */
rgrover1 716:11b41f651697 52 uint8_t _authSignedWrite :1; /**< Writing the value with Signed Write Command permitted. */
rgrover1 716:11b41f651697 53
rgrover1 716:11b41f651697 54 public:
rgrover1 716:11b41f651697 55 bool broadcast(void) const {return _broadcast; }
rgrover1 716:11b41f651697 56 bool read(void) const {return _read; }
rgrover1 716:11b41f651697 57 bool writeWoResp(void) const {return _writeWoResp; }
rgrover1 716:11b41f651697 58 bool write(void) const {return _write; }
rgrover1 716:11b41f651697 59 bool notify(void) const {return _notify; }
rgrover1 716:11b41f651697 60 bool indicate(void) const {return _indicate; }
rgrover1 716:11b41f651697 61 bool authSignedWrite(void) const {return _authSignedWrite;}
rgrover1 716:11b41f651697 62
vcoubard 1065:473735376f13 63 /**
vcoubard 1065:473735376f13 64 * @brief "Equal to" operator for DiscoveredCharacteristic::Properties_t
vcoubard 1065:473735376f13 65 *
vcoubard 1065:473735376f13 66 * @param lhs The left hand side of the equality expression
vcoubard 1065:473735376f13 67 * @param rhs The right hand side of the equality expression
vcoubard 1065:473735376f13 68 *
vcoubard 1065:473735376f13 69 * @return true if operands are equals, false otherwise.
vcoubard 1065:473735376f13 70 */
vcoubard 1065:473735376f13 71 friend bool operator==(Properties_t lhs, Properties_t rhs) {
vcoubard 1063:187f9929cb60 72 return rhs._broadcast == lhs._broadcast &&
vcoubard 1063:187f9929cb60 73 rhs._read == lhs._read &&
vcoubard 1063:187f9929cb60 74 rhs._writeWoResp == lhs._writeWoResp &&
vcoubard 1063:187f9929cb60 75 rhs._write == lhs._write &&
vcoubard 1063:187f9929cb60 76 rhs._notify == lhs._notify &&
vcoubard 1063:187f9929cb60 77 rhs._indicate == lhs._indicate &&
vcoubard 1063:187f9929cb60 78 rhs._authSignedWrite == lhs._authSignedWrite;
vcoubard 1063:187f9929cb60 79 }
vcoubard 1063:187f9929cb60 80
vcoubard 1065:473735376f13 81 /**
vcoubard 1065:473735376f13 82 * @brief "Not equal to" operator for DiscoveredCharacteristic::Properties_t
vcoubard 1065:473735376f13 83 *
vcoubard 1065:473735376f13 84 * @param lhs The right hand side of the expression
vcoubard 1065:473735376f13 85 * @param rhs The left hand side of the expression
vcoubard 1065:473735376f13 86 *
vcoubard 1065:473735376f13 87 * @return true if operands are not equals, false otherwise.
vcoubard 1065:473735376f13 88 */
vcoubard 1065:473735376f13 89 friend bool operator!=(Properties_t lhs, Properties_t rhs) {
vcoubard 1063:187f9929cb60 90 return !(rhs == lhs);
vcoubard 1063:187f9929cb60 91 }
vcoubard 1063:187f9929cb60 92
rgrover1 716:11b41f651697 93 private:
vcoubard 1048:efb29faf12fc 94 operator uint8_t() const; /* Disallow implicit conversion into an integer. */
vcoubard 1048:efb29faf12fc 95 operator unsigned() const; /* Disallow implicit conversion into an integer. */
rgrover1 716:11b41f651697 96 };
rgrover1 716:11b41f651697 97
rgrover1 716:11b41f651697 98 /**
rgrover1 716:11b41f651697 99 * Initiate (or continue) a read for the value attribute, optionally at a
vcoubard 1048:efb29faf12fc 100 * given offset. If the characteristic or descriptor to be read is longer
rgrover1 716:11b41f651697 101 * than ATT_MTU - 1, this function must be called multiple times with
rgrover1 716:11b41f651697 102 * appropriate offset to read the complete value.
rgrover1 716:11b41f651697 103 *
vcoubard 1048:efb29faf12fc 104 * @return BLE_ERROR_NONE if a read has been initiated, or
rgrover1 716:11b41f651697 105 * BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
vcoubard 1048:efb29faf12fc 106 * BLE_STACK_BUSY if some client procedure is already in progress, or
rgrover1 716:11b41f651697 107 * BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
rgrover1 716:11b41f651697 108 */
rgrover1 716:11b41f651697 109 ble_error_t read(uint16_t offset = 0) const;
rgrover1 716:11b41f651697 110
vcoubard 1052:b55e1ad3e1b3 111 ble_error_t read(uint16_t offset, const GattClient::ReadCallback_t& onRead) const;
vcoubard 1052:b55e1ad3e1b3 112
rgrover1 716:11b41f651697 113 /**
rgrover1 716:11b41f651697 114 * Perform a write without response procedure.
rgrover1 716:11b41f651697 115 *
rgrover1 716:11b41f651697 116 * @param length
rgrover1 716:11b41f651697 117 * The amount of data being written.
rgrover1 716:11b41f651697 118 * @param value
rgrover1 716:11b41f651697 119 * The bytes being written.
rgrover1 716:11b41f651697 120 *
rgrover1 716:11b41f651697 121 * @note It is important to note that a write without response will generate
rgrover1 716:11b41f651697 122 * an onDataSent() callback when the packet has been transmitted. There
rgrover1 716:11b41f651697 123 * will be a BLE-stack specific limit to the number of pending
rgrover1 716:11b41f651697 124 * writeWoResponse operations; the user may want to use the onDataSent()
rgrover1 716:11b41f651697 125 * callback for flow-control.
rgrover1 716:11b41f651697 126 *
vcoubard 1048:efb29faf12fc 127 * @retval BLE_ERROR_NONE Successfully started the Write procedure, or
rgrover1 716:11b41f651697 128 * BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
vcoubard 1048:efb29faf12fc 129 * BLE_STACK_BUSY if some client procedure is already in progress, or
rgrover1 716:11b41f651697 130 * BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
rgrover1 716:11b41f651697 131 * BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
rgrover1 716:11b41f651697 132 */
rgrover1 716:11b41f651697 133 ble_error_t writeWoResponse(uint16_t length, const uint8_t *value) const;
rgrover1 716:11b41f651697 134
rgrover1 716:11b41f651697 135 /**
rgrover1 716:11b41f651697 136 * Initiate a GATT Characteristic Descriptor Discovery procedure for descriptors within this characteristic.
rgrover1 716:11b41f651697 137 *
vcoubard 1065:473735376f13 138 * @param onDescriptorDiscovered This callback will be called every time a descriptor is discovered
vcoubard 1063:187f9929cb60 139 * @param onTermination This callback will be called when the discovery process is over.
rgrover1 716:11b41f651697 140 *
vcoubard 1065:473735376f13 141 * @return BLE_ERROR_NONE if descriptor discovery is launched successfully; else an appropriate error.
rgrover1 716:11b41f651697 142 */
vcoubard 1065:473735376f13 143 ble_error_t discoverDescriptors(const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& onDescriptorDiscovered,
vcoubard 1063:187f9929cb60 144 const CharacteristicDescriptorDiscovery::TerminationCallback_t& onTermination) const;
rgrover1 716:11b41f651697 145
rgrover1 716:11b41f651697 146 /**
rgrover1 716:11b41f651697 147 * Perform a write procedure.
rgrover1 716:11b41f651697 148 *
rgrover1 716:11b41f651697 149 * @param length
rgrover1 716:11b41f651697 150 * The amount of data being written.
rgrover1 716:11b41f651697 151 * @param value
rgrover1 716:11b41f651697 152 * The bytes being written.
rgrover1 716:11b41f651697 153 *
rgrover1 716:11b41f651697 154 * @note It is important to note that a write will generate
rgrover1 716:11b41f651697 155 * an onDataWritten() callback when the peer acknowledges the request.
rgrover1 716:11b41f651697 156 *
vcoubard 1048:efb29faf12fc 157 * @retval BLE_ERROR_NONE Successfully started the Write procedure, or
rgrover1 716:11b41f651697 158 * BLE_ERROR_INVALID_STATE if some internal state about the connection is invalid, or
vcoubard 1048:efb29faf12fc 159 * BLE_STACK_BUSY if some client procedure is already in progress, or
rgrover1 716:11b41f651697 160 * BLE_ERROR_NO_MEM if there are no available buffers left to process the request, or
rgrover1 716:11b41f651697 161 * BLE_ERROR_OPERATION_NOT_PERMITTED due to the characteristic's properties.
rgrover1 716:11b41f651697 162 */
rgrover1 716:11b41f651697 163 ble_error_t write(uint16_t length, const uint8_t *value) const;
rgrover1 716:11b41f651697 164
vcoubard 1056:ce2fb3d09929 165 /**
vcoubard 1052:b55e1ad3e1b3 166 * Same as above but register the callback wich will be called once the data has been written
vcoubard 1052:b55e1ad3e1b3 167 */
vcoubard 1052:b55e1ad3e1b3 168 ble_error_t write(uint16_t length, const uint8_t *value, const GattClient::WriteCallback_t& onRead) const;
vcoubard 1052:b55e1ad3e1b3 169
vcoubard 1056:ce2fb3d09929 170 void setupLongUUID(UUID::LongUUIDBytes_t longUUID, UUID::ByteOrder_t order = UUID::MSB) {
vcoubard 1056:ce2fb3d09929 171 uuid.setupLong(longUUID, order);
rgrover1 716:11b41f651697 172 }
rgrover1 716:11b41f651697 173
rgrover1 716:11b41f651697 174 public:
vcoubard 1065:473735376f13 175 /**
vcoubard 1065:473735376f13 176 * @brief Get the UUID of the discovered characteristic
vcoubard 1065:473735376f13 177 * @return the UUID of this characteristic
vcoubard 1065:473735376f13 178 */
rgrover1 741:d6dceefb844e 179 const UUID& getUUID(void) const {
rgrover1 741:d6dceefb844e 180 return uuid;
rgrover1 716:11b41f651697 181 }
rgrover1 716:11b41f651697 182
vcoubard 1065:473735376f13 183 /**
vcoubard 1065:473735376f13 184 * @brief Get the properties of this characteristic
vcoubard 1065:473735376f13 185 * @return the set of properties of this characteristic
vcoubard 1065:473735376f13 186 */
rgrover1 716:11b41f651697 187 const Properties_t& getProperties(void) const {
rgrover1 716:11b41f651697 188 return props;
rgrover1 716:11b41f651697 189 }
rgrover1 716:11b41f651697 190
vcoubard 1065:473735376f13 191 /**
vcoubard 1065:473735376f13 192 * @brief Get the declaration handle of this characteristic.
vcoubard 1065:473735376f13 193 * @detail The declaration handle is the first handle of a characteristic
vcoubard 1065:473735376f13 194 * definition. The value accessible at this handle contains the following
vcoubard 1065:473735376f13 195 * informations:
vcoubard 1065:473735376f13 196 * - The characteristics properties (see Properties_t). This value can
vcoubard 1065:473735376f13 197 * be accessed by using DiscoveredCharacteristic::getProperties .
vcoubard 1065:473735376f13 198 * - The characteristic value attribute handle. This field can be accessed
vcoubard 1065:473735376f13 199 * by using DiscoveredCharacteristic::getValueHandle .
vcoubard 1065:473735376f13 200 * - The characteristic UUID, this value can be accessed by using the
vcoubard 1065:473735376f13 201 * function DiscoveredCharacteristic::getUUID .
vcoubard 1065:473735376f13 202 * @return the declaration handle of this characteristic.
vcoubard 1065:473735376f13 203 */
vcoubard 1063:187f9929cb60 204 GattAttribute::Handle_t getDeclHandle(void) const {
rgrover1 716:11b41f651697 205 return declHandle;
rgrover1 716:11b41f651697 206 }
vcoubard 1063:187f9929cb60 207
vcoubard 1065:473735376f13 208 /**
vcoubard 1065:473735376f13 209 * @brief Return the handle used to access the value of this characteristic.
vcoubard 1065:473735376f13 210 * @details This handle is the one provided in the characteristic declaration
vcoubard 1065:473735376f13 211 * value. Usually, it is equal to <declaration handle> + 1. But it is not always
vcoubard 1065:473735376f13 212 * the case. Anyway, users are allowed to use <declaration handle> + 1 to access
vcoubard 1065:473735376f13 213 * the value of a characteristic.
vcoubard 1065:473735376f13 214 * @return The handle to access the value of this characteristic.
vcoubard 1065:473735376f13 215 */
vcoubard 1063:187f9929cb60 216 GattAttribute::Handle_t getValueHandle(void) const {
rgrover1 716:11b41f651697 217 return valueHandle;
rgrover1 716:11b41f651697 218 }
rgrover1 716:11b41f651697 219
vcoubard 1065:473735376f13 220 /**
vcoubard 1065:473735376f13 221 * @brief Return the last handle of the characteristic definition.
vcoubard 1065:473735376f13 222 * @details A Characteristic definition can contain a lot of handles:
vcoubard 1065:473735376f13 223 * - one for the declaration (see DiscoveredCharacteristic::getDeclHandle)
vcoubard 1065:473735376f13 224 * - one for the value (see DiscoveredCharacteristic::getValueHandle)
vcoubard 1065:473735376f13 225 * - zero of more for the characteristic descriptors.
vcoubard 1065:473735376f13 226 * This handle is the last handle of the characteristic definition.
vcoubard 1065:473735376f13 227 * @return The last handle of this characteristic definition.
vcoubard 1065:473735376f13 228 */
vcoubard 1063:187f9929cb60 229 GattAttribute::Handle_t getLastHandle(void) const {
vcoubard 1063:187f9929cb60 230 return lastHandle;
vcoubard 1063:187f9929cb60 231 }
vcoubard 1063:187f9929cb60 232
vcoubard 1065:473735376f13 233 void setLastHandle(GattAttribute::Handle_t last) {
vcoubard 1063:187f9929cb60 234 lastHandle = last;
vcoubard 1063:187f9929cb60 235 }
vcoubard 1063:187f9929cb60 236
vcoubard 1065:473735376f13 237 /**
vcoubard 1065:473735376f13 238 * @brief Return the GattClient which can operate on this characteristic.
vcoubard 1065:473735376f13 239 * @return The GattClient which can operate on this characteristic.
vcoubard 1065:473735376f13 240 */
vcoubard 1065:473735376f13 241 GattClient* getGattClient() {
vcoubard 1063:187f9929cb60 242 return gattc;
vcoubard 1063:187f9929cb60 243 }
vcoubard 1063:187f9929cb60 244
vcoubard 1065:473735376f13 245 /**
vcoubard 1065:473735376f13 246 * @brief Return the GattClient which can operate on this characteristic.
vcoubard 1065:473735376f13 247 * @return The GattClient which can operate on this characteristic.
vcoubard 1065:473735376f13 248 */
vcoubard 1065:473735376f13 249 const GattClient* getGattClient() const {
vcoubard 1063:187f9929cb60 250 return gattc;
vcoubard 1063:187f9929cb60 251 }
vcoubard 1063:187f9929cb60 252
vcoubard 1065:473735376f13 253 /**
vcoubard 1065:473735376f13 254 * @brief Return the connection handle to the GattServer which contain
vcoubard 1065:473735376f13 255 * this characteristic.
vcoubard 1065:473735376f13 256 * @return the connection handle to the GattServer which contain
vcoubard 1065:473735376f13 257 * this characteristic.
vcoubard 1065:473735376f13 258 */
vcoubard 1063:187f9929cb60 259 Gap::Handle_t getConnectionHandle() const {
vcoubard 1063:187f9929cb60 260 return connHandle;
vcoubard 1063:187f9929cb60 261 }
vcoubard 1063:187f9929cb60 262
vcoubard 1065:473735376f13 263 /**
vcoubard 1065:473735376f13 264 * @brief "Equal to" operator for DiscoveredCharacteristic
vcoubard 1065:473735376f13 265 *
vcoubard 1065:473735376f13 266 * @param lhs The left hand side of the equality expression
vcoubard 1065:473735376f13 267 * @param rhs The right hand side of the equality expression
vcoubard 1065:473735376f13 268 *
vcoubard 1065:473735376f13 269 * @return true if operands are equals, false otherwise.
vcoubard 1065:473735376f13 270 */
vcoubard 1065:473735376f13 271 friend bool operator==(const DiscoveredCharacteristic& lhs, const DiscoveredCharacteristic& rhs) {
vcoubard 1065:473735376f13 272 return lhs.gattc == rhs.gattc &&
vcoubard 1065:473735376f13 273 lhs.uuid == rhs.uuid &&
vcoubard 1065:473735376f13 274 lhs.props == rhs.props &&
vcoubard 1065:473735376f13 275 lhs.declHandle == rhs.declHandle &&
vcoubard 1065:473735376f13 276 lhs.valueHandle == rhs.valueHandle &&
vcoubard 1065:473735376f13 277 lhs.lastHandle == rhs.lastHandle &&
vcoubard 1065:473735376f13 278 lhs.connHandle == rhs.connHandle;
vcoubard 1063:187f9929cb60 279 }
vcoubard 1063:187f9929cb60 280
vcoubard 1065:473735376f13 281 /**
vcoubard 1065:473735376f13 282 * @brief "Not equal to" operator for DiscoveredCharacteristic
vcoubard 1065:473735376f13 283 *
vcoubard 1065:473735376f13 284 * @param lhs The right hand side of the expression
vcoubard 1065:473735376f13 285 * @param rhs The left hand side of the expression
vcoubard 1065:473735376f13 286 *
vcoubard 1065:473735376f13 287 * @return true if operands are not equals, false otherwise.
vcoubard 1065:473735376f13 288 */
vcoubard 1065:473735376f13 289 friend bool operator !=(const DiscoveredCharacteristic& lhs, const DiscoveredCharacteristic& rhs) {
vcoubard 1065:473735376f13 290 return !(lhs == rhs);
vcoubard 1063:187f9929cb60 291 }
vcoubard 1063:187f9929cb60 292
rgrover1 716:11b41f651697 293 public:
rgrover1 716:11b41f651697 294 DiscoveredCharacteristic() : gattc(NULL),
rgrover1 716:11b41f651697 295 uuid(UUID::ShortUUIDBytes_t(0)),
rgrover1 716:11b41f651697 296 props(),
rgrover1 716:11b41f651697 297 declHandle(GattAttribute::INVALID_HANDLE),
vcoubard 1063:187f9929cb60 298 valueHandle(GattAttribute::INVALID_HANDLE),
vcoubard 1063:187f9929cb60 299 lastHandle(GattAttribute::INVALID_HANDLE),
vcoubard 1063:187f9929cb60 300 connHandle() {
rgrover1 716:11b41f651697 301 /* empty */
rgrover1 716:11b41f651697 302 }
rgrover1 716:11b41f651697 303
rgrover1 716:11b41f651697 304 protected:
rgrover1 716:11b41f651697 305 GattClient *gattc;
rgrover1 716:11b41f651697 306
rgrover1 716:11b41f651697 307 protected:
rgrover1 716:11b41f651697 308 UUID uuid;
rgrover1 716:11b41f651697 309 Properties_t props;
rgrover1 716:11b41f651697 310 GattAttribute::Handle_t declHandle;
rgrover1 716:11b41f651697 311 GattAttribute::Handle_t valueHandle;
vcoubard 1063:187f9929cb60 312 GattAttribute::Handle_t lastHandle;
rgrover1 716:11b41f651697 313
rgrover1 716:11b41f651697 314 Gap::Handle_t connHandle;
rgrover1 716:11b41f651697 315 };
rgrover1 716:11b41f651697 316
rgrover1 716:11b41f651697 317 #endif /*__DISCOVERED_CHARACTERISTIC_H__*/