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 "os/logging/log_adapter.h" 25 #include "stack/gatt/gatt_int.h" 26 #include "types/raw_address.h" 27 28 #define EATT_MIN_MTU_MPS (64) 29 #define EATT_DEFAULT_MTU (256) 30 #define EATT_MAX_TX_MTU (1024) 31 #define EATT_ALL_CIDS (0xFFFF) 32 33 namespace bluetooth { 34 namespace eatt { 35 36 /* Enums */ 37 enum class EattChannelState : uint8_t { 38 EATT_CHANNEL_PENDING = 0x00, 39 EATT_CHANNEL_OPENED, 40 EATT_CHANNEL_RECONFIGURING, 41 }; 42 43 class EattChannel { 44 public: 45 /* Pointer to EattDevice */ 46 RawAddress bda_; 47 uint16_t cid_; 48 uint16_t tx_mtu_; 49 uint16_t rx_mtu_; 50 EattChannelState state_; 51 52 /* Used to keep server commands */ 53 tGATT_SR_CMD server_outstanding_cmd_; 54 /* Used to verify indication confirmation*/ 55 uint16_t indicate_handle_; 56 /* local app confirm to indication timer */ 57 alarm_t* ind_ack_timer_; 58 /* indication confirmation timer */ 59 alarm_t* ind_confirmation_timer_; 60 /* GATT client command queue */ 61 std::deque<tGATT_CMD_Q> cl_cmd_q_; 62 EattChannel(RawAddress & bda,uint16_t cid,uint16_t tx_mtu,uint16_t rx_mtu)63 EattChannel(RawAddress& bda, uint16_t cid, uint16_t tx_mtu, uint16_t rx_mtu) 64 : bda_(bda), 65 cid_(cid), 66 rx_mtu_(rx_mtu), 67 state_(EattChannelState::EATT_CHANNEL_PENDING), 68 indicate_handle_(0), 69 ind_ack_timer_(NULL), 70 ind_confirmation_timer_(NULL) { 71 cl_cmd_q_ = std::deque<tGATT_CMD_Q>(); 72 EattChannelSetTxMTU(tx_mtu); 73 } 74 ~EattChannel()75 ~EattChannel() { 76 if (ind_ack_timer_ != NULL) { 77 alarm_free(ind_ack_timer_); 78 } 79 80 if (ind_confirmation_timer_ != NULL) { 81 alarm_free(ind_confirmation_timer_); 82 } 83 } 84 EattChannelSetState(EattChannelState state)85 void EattChannelSetState(EattChannelState state) { 86 if (state_ == EattChannelState::EATT_CHANNEL_PENDING) { 87 if (state == EattChannelState::EATT_CHANNEL_OPENED) { 88 server_outstanding_cmd_ = tGATT_SR_CMD{}; 89 char name[64]; 90 sprintf(name, "eatt_ind_ack_timer_%s_cid_0x%04x", 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", ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_); 94 ind_confirmation_timer_ = alarm_new(name); 95 } 96 } 97 state_ = state; 98 } 99 EattChannelSetTxMTU(uint16_t tx_mtu)100 void EattChannelSetTxMTU(uint16_t tx_mtu) { 101 this->tx_mtu_ = std::min<uint16_t>(tx_mtu, EATT_MAX_TX_MTU); 102 this->tx_mtu_ = std::max<uint16_t>(tx_mtu, EATT_MIN_MTU_MPS); 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, uint16_t cid = EATT_ALL_CIDS); 143 144 /** 145 * Reconfigure EATT channel for give CID 146 * 147 * @param bd_addr peer device address 148 * @param cid channel id 149 * @param mtu new maximum transmit unit available of local device 150 */ 151 virtual void Reconfigure(const RawAddress& bd_addr, uint16_t cid, uint16_t mtu); 152 153 /** 154 * Reconfigure all EATT channels to peer device. 155 * 156 * @param bd_addr peer device address 157 * @param mtu new maximum transmit unit available of local device 158 */ 159 virtual void ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu); 160 161 /* Below methods required by GATT implementation */ 162 163 /** 164 * Find EATT channel by cid. 165 * 166 * @param bd_addr peer device address 167 * @param cid channel id 168 * 169 * @return Eatt Channel instance. 170 */ 171 virtual EattChannel* FindEattChannelByCid(const RawAddress& bd_addr, uint16_t cid); 172 173 /** 174 * Find EATT channel by transaction id. 175 * 176 * @param bd_addr peer device address 177 * @param trans_id transaction id 178 * 179 * @return pointer to EATT channel. 180 */ 181 virtual EattChannel* FindEattChannelByTransId(const RawAddress& bd_addr, uint32_t trans_id); 182 183 /** 184 * Check if EATT channel on given handle is waiting for a indication 185 * confirmation 186 * 187 * @param bd_addr peer device address 188 * @param indication_handle handle of the pending indication 189 * 190 * @return true if confirmation is pending false otherwise 191 */ 192 virtual bool IsIndicationPending(const RawAddress& bd_addr, uint16_t indication_handle); 193 194 /** 195 * Get EATT channel available for indication. 196 * 197 * @param bd_addr peer device address 198 * 199 * @return pointer to EATT channel. 200 */ 201 virtual EattChannel* GetChannelAvailableForIndication(const RawAddress& bd_addr); 202 203 /** 204 * Free Resources. 205 * 206 * (Maybe not needed) 207 * @param bd_addr peer device address 208 * 209 */ 210 virtual void FreeGattResources(const RawAddress& bd_addr); 211 212 /** 213 * Check if there is any EATT channels having some msg in its send queue 214 * 215 * @param bd_addr peer device address 216 * 217 * @return true when there is at least one EATT channel ready to send 218 */ 219 virtual bool IsOutstandingMsgInSendQueue(const RawAddress& bd_addr); 220 221 /** 222 * Get EATT channel ready to send. 223 * 224 * @param bd_addr peer device address 225 * 226 * @return pointer to EATT channel. 227 */ 228 virtual EattChannel* GetChannelWithQueuedDataToSend(const RawAddress& bd_addr); 229 230 /** 231 * Get EATT channel available to send GATT request. 232 * 233 * @param bd_addr peer device address 234 * 235 * @return pointer to EATT channel. 236 */ 237 virtual EattChannel* GetChannelAvailableForClientRequest(const RawAddress& bd_addr); 238 239 /** 240 * Start GATT indication timer per CID. 241 * 242 * @param bd_addr peer device address 243 * @param cid channel id 244 */ 245 virtual void StartIndicationConfirmationTimer(const RawAddress& bd_addr, uint16_t cid); 246 247 /** 248 * Stop GATT indication timer per CID. 249 * 250 * @param bd_addr peer device address 251 * @param cid channel id 252 */ 253 virtual void StopIndicationConfirmationTimer(const RawAddress& bd_addr, uint16_t cid); 254 255 /** 256 * Start application time for incoming indication on given CID 257 * 258 * @param bd_addr peer device address 259 * @param cid channel id 260 */ 261 virtual void StartAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 262 263 /** 264 * Stop application time for incoming indication on given CID 265 * 266 * @param bd_addr peer device address 267 * @param cid channel id 268 */ 269 virtual void StopAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 270 271 /** 272 * Starts the EattExtension module 273 */ 274 void Start(); 275 276 /** 277 * Stops the EattExtension module 278 */ 279 void Stop(); 280 281 private: 282 struct impl; 283 std::unique_ptr<impl> pimpl_; 284 }; 285 286 } // namespace eatt 287 } // namespace bluetooth 288