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 #include <memory> 23 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 verify 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 server_outstanding_cmd_ = tGATT_SR_CMD{}; 88 char name[64]; 89 sprintf(name, "eatt_ind_ack_timer_%s_cid_0x%04x", bda_.ToRedactedStringForLogging().c_str(), 90 cid_); 91 ind_ack_timer_ = alarm_new(name); 92 93 sprintf(name, "eatt_ind_conf_timer_%s_cid_0x%04x", 94 bda_.ToRedactedStringForLogging().c_str(), 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 this->tx_mtu_ = std::max<uint16_t>(tx_mtu, EATT_MIN_MTU_MPS); 104 } 105 }; 106 107 /* Interface class */ 108 class EattExtension { 109 public: 110 EattExtension(); 111 EattExtension(const EattExtension&) = delete; 112 EattExtension& operator=(const EattExtension&) = delete; 113 114 virtual ~EattExtension(); 115 GetInstance()116 static EattExtension* GetInstance() { 117 static EattExtension* instance = new EattExtension(); 118 return instance; 119 } 120 121 static void AddFromStorage(const RawAddress& bd_addr); 122 123 /** 124 * Checks if EATT is supported on peer device. 125 * 126 * @param bd_addr peer device address 127 */ 128 virtual bool IsEattSupportedByPeer(const RawAddress& bd_addr); 129 130 /** 131 * Connect at maximum 5 EATT channels to peer device. 132 * 133 * @param bd_addr peer device address 134 */ 135 virtual void Connect(const RawAddress& bd_addr); 136 137 /** 138 * Disconnect all EATT channels to peer device. 139 * 140 * @param bd_addr peer device address 141 * @param cid remote channel id (EATT_ALL_CIDS for all) 142 */ 143 virtual void Disconnect(const RawAddress& bd_addr, 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, uint16_t mtu); 153 154 /** 155 * Reconfigure all EATT channels to peer device. 156 * 157 * @param bd_addr peer device address 158 * @param mtu new maximum transmit unit available of local device 159 */ 160 virtual void ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu); 161 162 /* Below methods required by GATT implementation */ 163 164 /** 165 * Find EATT channel by cid. 166 * 167 * @param bd_addr peer device address 168 * @param cid channel id 169 * 170 * @return Eatt Channel instance. 171 */ 172 virtual EattChannel* FindEattChannelByCid(const RawAddress& bd_addr, uint16_t cid); 173 174 /** 175 * Find EATT channel by transaction id. 176 * 177 * @param bd_addr peer device address 178 * @param trans_id transaction id 179 * 180 * @return pointer to EATT channel. 181 */ 182 virtual EattChannel* FindEattChannelByTransId(const RawAddress& bd_addr, uint32_t trans_id); 183 184 /** 185 * Check if EATT channel on given handle is waiting for a indication 186 * confirmation 187 * 188 * @param bd_addr peer device address 189 * @param indication_handle handle of the pending indication 190 * 191 * @return true if confirmation is pending false otherwise 192 */ 193 virtual bool IsIndicationPending(const RawAddress& bd_addr, uint16_t indication_handle); 194 195 /** 196 * Get EATT channel available for indication. 197 * 198 * @param bd_addr peer device address 199 * 200 * @return pointer to EATT channel. 201 */ 202 virtual EattChannel* GetChannelAvailableForIndication(const RawAddress& bd_addr); 203 204 /** 205 * Free Resources. 206 * 207 * (Maybe not needed) 208 * @param bd_addr peer device address 209 * 210 */ 211 virtual void FreeGattResources(const RawAddress& bd_addr); 212 213 /** 214 * Check if there is any EATT channels having some msg in its send queue 215 * 216 * @param bd_addr peer device address 217 * 218 * @return true when there is at least one EATT channel ready to send 219 */ 220 virtual bool IsOutstandingMsgInSendQueue(const RawAddress& bd_addr); 221 222 /** 223 * Get EATT channel ready to send. 224 * 225 * @param bd_addr peer device address 226 * 227 * @return pointer to EATT channel. 228 */ 229 virtual EattChannel* GetChannelWithQueuedDataToSend(const RawAddress& bd_addr); 230 231 /** 232 * Get EATT channel available to send GATT request. 233 * 234 * @param bd_addr peer device address 235 * 236 * @return pointer to EATT channel. 237 */ 238 virtual EattChannel* GetChannelAvailableForClientRequest(const RawAddress& bd_addr); 239 240 /** 241 * Start GATT indication timer per CID. 242 * 243 * @param bd_addr peer device address 244 * @param cid channel id 245 */ 246 virtual void StartIndicationConfirmationTimer(const RawAddress& bd_addr, uint16_t cid); 247 248 /** 249 * Stop GATT indication timer per CID. 250 * 251 * @param bd_addr peer device address 252 * @param cid channel id 253 */ 254 virtual void StopIndicationConfirmationTimer(const RawAddress& bd_addr, uint16_t cid); 255 256 /** 257 * Start application time for incoming indication on given CID 258 * 259 * @param bd_addr peer device address 260 * @param cid channel id 261 */ 262 virtual void StartAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 263 264 /** 265 * Stop application time for incoming indication on given CID 266 * 267 * @param bd_addr peer device address 268 * @param cid channel id 269 */ 270 virtual void StopAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 271 272 /** 273 * Starts the EattExtension module 274 */ 275 void Start(); 276 277 /** 278 * Stops the EattExtension module 279 */ 280 void Stop(); 281 282 private: 283 struct impl; 284 std::unique_ptr<impl> pimpl_; 285 }; 286 287 } // namespace eatt 288 } // namespace bluetooth 289