1 /* 2 * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA - 3 * www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #pragma once 19 20 #include <algorithm> 21 #include <deque> 22 23 #include "os/logging/log_adapter.h" 24 #include "stack/gatt/gatt_int.h" 25 #include "types/raw_address.h" 26 27 #define EATT_MIN_MTU_MPS (64) 28 #define EATT_DEFAULT_MTU (256) 29 #define EATT_MAX_TX_MTU (1024) 30 #define EATT_ALL_CIDS (0xFFFF) 31 32 namespace bluetooth { 33 namespace eatt { 34 35 /* Enums */ 36 enum class EattChannelState : uint8_t { 37 EATT_CHANNEL_PENDING = 0x00, 38 EATT_CHANNEL_OPENED, 39 EATT_CHANNEL_RECONFIGURING, 40 }; 41 42 class EattChannel { 43 public: 44 /* Pointer to EattDevice */ 45 RawAddress bda_; 46 uint16_t cid_; 47 uint16_t tx_mtu_; 48 uint16_t rx_mtu_; 49 EattChannelState state_; 50 51 /* Used to keep server commands */ 52 tGATT_SR_CMD server_outstanding_cmd_; 53 /* Used to veryfy indication confirmation*/ 54 uint16_t indicate_handle_; 55 /* local app confirm to indication timer */ 56 alarm_t* ind_ack_timer_; 57 /* indication confirmation timer */ 58 alarm_t* ind_confirmation_timer_; 59 /* GATT client command queue */ 60 std::deque<tGATT_CMD_Q> cl_cmd_q_; 61 EattChannel(RawAddress & bda,uint16_t cid,uint16_t tx_mtu,uint16_t rx_mtu)62 EattChannel(RawAddress& bda, uint16_t cid, uint16_t tx_mtu, uint16_t rx_mtu) 63 : bda_(bda), 64 cid_(cid), 65 rx_mtu_(rx_mtu), 66 state_(EattChannelState::EATT_CHANNEL_PENDING), 67 indicate_handle_(0), 68 ind_ack_timer_(NULL), 69 ind_confirmation_timer_(NULL) { 70 cl_cmd_q_ = std::deque<tGATT_CMD_Q>(); 71 EattChannelSetTxMTU(tx_mtu); 72 } 73 ~EattChannel()74 ~EattChannel() { 75 if (ind_ack_timer_ != NULL) { 76 alarm_free(ind_ack_timer_); 77 } 78 79 if (ind_confirmation_timer_ != NULL) { 80 alarm_free(ind_confirmation_timer_); 81 } 82 } 83 EattChannelSetState(EattChannelState state)84 void EattChannelSetState(EattChannelState state) { 85 if (state_ == EattChannelState::EATT_CHANNEL_PENDING) { 86 if (state == EattChannelState::EATT_CHANNEL_OPENED) { 87 memset(&server_outstanding_cmd_, 0, sizeof(tGATT_SR_CMD)); 88 char name[64]; 89 sprintf(name, "eatt_ind_ack_timer_%s_cid_0x%04x", 90 ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_); 91 ind_ack_timer_ = alarm_new(name); 92 93 sprintf(name, "eatt_ind_conf_timer_%s_cid_0x%04x", 94 ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_); 95 ind_confirmation_timer_ = alarm_new(name); 96 } 97 } 98 state_ = state; 99 } 100 EattChannelSetTxMTU(uint16_t tx_mtu)101 void EattChannelSetTxMTU(uint16_t tx_mtu) { 102 this->tx_mtu_ = std::min<uint16_t>(tx_mtu, EATT_MAX_TX_MTU); 103 } 104 }; 105 106 /* Interface class */ 107 class EattExtension { 108 public: 109 EattExtension(); 110 EattExtension(const EattExtension&) = delete; 111 EattExtension& operator=(const EattExtension&) = delete; 112 113 virtual ~EattExtension(); 114 GetInstance()115 static EattExtension* GetInstance() { 116 static EattExtension* instance = new EattExtension(); 117 return instance; 118 } 119 120 static void AddFromStorage(const RawAddress& bd_addr); 121 122 /** 123 * Checks if EATT is supported on peer device. 124 * 125 * @param bd_addr peer device address 126 */ 127 virtual bool IsEattSupportedByPeer(const RawAddress& bd_addr); 128 129 /** 130 * Connect at maximum 5 EATT channels to peer device. 131 * 132 * @param bd_addr peer device address 133 */ 134 virtual void Connect(const RawAddress& bd_addr); 135 136 /** 137 * Disconnect all EATT channels to peer device. 138 * 139 * @param bd_addr peer device address 140 * @param cid remote channel id (EATT_ALL_CIDS for all) 141 */ 142 virtual void Disconnect(const RawAddress& bd_addr, 143 uint16_t cid = EATT_ALL_CIDS); 144 145 /** 146 * Reconfigure EATT channel for give CID 147 * 148 * @param bd_addr peer device address 149 * @param cid channel id 150 * @param mtu new maximum transmit unit available of local device 151 */ 152 virtual void Reconfigure(const RawAddress& bd_addr, uint16_t cid, 153 uint16_t mtu); 154 155 /** 156 * Reconfigure all EATT channels to peer device. 157 * 158 * @param bd_addr peer device address 159 * @param mtu new maximum transmit unit available of local device 160 */ 161 virtual void ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu); 162 163 /* Below methods required by GATT implementation */ 164 165 /** 166 * Find EATT channel by cid. 167 * 168 * @param bd_addr peer device address 169 * @param cid channel id 170 * 171 * @return Eatt Channel instance. 172 */ 173 virtual EattChannel* FindEattChannelByCid(const RawAddress& bd_addr, 174 uint16_t cid); 175 176 /** 177 * Find EATT channel by transaction id. 178 * 179 * @param bd_addr peer device address 180 * @param trans_id transaction id 181 * 182 * @return pointer to EATT channel. 183 */ 184 virtual EattChannel* FindEattChannelByTransId(const RawAddress& bd_addr, 185 uint32_t trans_id); 186 187 /** 188 * Check if EATT channel on given handle is waiting for a indication 189 * confirmation 190 * 191 * @param bd_addr peer device address 192 * @param indication_handle handle of the pending indication 193 * 194 * @return true if confirmation is pending false otherwise 195 */ 196 virtual bool IsIndicationPending(const RawAddress& bd_addr, 197 uint16_t indication_handle); 198 199 /** 200 * Get EATT channel available for indication. 201 * 202 * @param bd_addr peer device address 203 * 204 * @return pointer to EATT channel. 205 */ 206 virtual EattChannel* GetChannelAvailableForIndication( 207 const RawAddress& bd_addr); 208 209 /** 210 * Free Resources. 211 * 212 * (Maybe not needed) 213 * @param bd_addr peer device address 214 * 215 */ 216 virtual void FreeGattResources(const RawAddress& bd_addr); 217 218 /** 219 * Check if there is any EATT channels having some msg in its send queue 220 * 221 * @param bd_addr peer device address 222 * 223 * @return true when there is at least one EATT channel ready to send 224 */ 225 virtual bool IsOutstandingMsgInSendQueue(const RawAddress& bd_addr); 226 227 /** 228 * Get EATT channel ready to send. 229 * 230 * @param bd_addr peer device address 231 * 232 * @return pointer to EATT channel. 233 */ 234 virtual EattChannel* GetChannelWithQueuedDataToSend( 235 const RawAddress& bd_addr); 236 237 /** 238 * Get EATT channel available to send GATT request. 239 * 240 * @param bd_addr peer device address 241 * 242 * @return pointer to EATT channel. 243 */ 244 virtual EattChannel* GetChannelAvailableForClientRequest( 245 const RawAddress& bd_addr); 246 247 /** 248 * Start GATT indication timer per CID. 249 * 250 * @param bd_addr peer device address 251 * @param cid channel id 252 */ 253 virtual void StartIndicationConfirmationTimer(const RawAddress& bd_addr, 254 uint16_t cid); 255 256 /** 257 * Stop GATT indication timer per CID. 258 * 259 * @param bd_addr peer device address 260 * @param cid channel id 261 */ 262 virtual void StopIndicationConfirmationTimer(const RawAddress& bd_addr, 263 uint16_t cid); 264 265 /** 266 * Start application time for incoming indication on given CID 267 * 268 * @param bd_addr peer device address 269 * @param cid channel id 270 */ 271 virtual void StartAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 272 273 /** 274 * Stop application time for incoming indication on given CID 275 * 276 * @param bd_addr peer device address 277 * @param cid channel id 278 */ 279 virtual void StopAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 280 281 /** 282 * Starts the EattExtension module 283 */ 284 void Start(); 285 286 /** 287 * Stops the EattExtension module 288 */ 289 void Stop(); 290 291 private: 292 struct impl; 293 std::unique_ptr<impl> pimpl_; 294 }; 295 296 } // namespace eatt 297 } // namespace bluetooth 298