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 <deque> 21 22 #include "stack/gatt/gatt_int.h" 23 #include "types/raw_address.h" 24 25 #define EATT_MIN_MTU_MPS (64) 26 #define EATT_DEFAULT_MTU (256) 27 #define EATT_ALL_CIDS (0xFFFF) 28 29 namespace bluetooth { 30 namespace eatt { 31 32 /* Enums */ 33 enum class EattChannelState : uint8_t { 34 EATT_CHANNEL_PENDING = 0x00, 35 EATT_CHANNEL_OPENED, 36 EATT_CHANNEL_RECONFIGURING, 37 }; 38 39 class EattChannel { 40 public: 41 /* Pointer to EattDevice */ 42 RawAddress bda_; 43 uint16_t cid_; 44 uint16_t tx_mtu_; 45 uint16_t rx_mtu_; 46 EattChannelState state_; 47 48 /* Used to keep server commands */ 49 tGATT_SR_CMD server_outstanding_cmd_; 50 /* Used to veryfy indication confirmation*/ 51 uint16_t indicate_handle_; 52 /* local app confirm to indication timer */ 53 alarm_t* ind_ack_timer_; 54 /* indication confirmation timer */ 55 alarm_t* ind_confirmation_timer_; 56 /* GATT client command queue */ 57 std::deque<tGATT_CMD_Q> cl_cmd_q_; 58 EattChannel(RawAddress & bda,uint16_t cid,uint16_t tx_mtu,uint16_t rx_mtu)59 EattChannel(RawAddress& bda, uint16_t cid, uint16_t tx_mtu, uint16_t rx_mtu) 60 : bda_(bda), 61 cid_(cid), 62 tx_mtu_(tx_mtu), 63 rx_mtu_(rx_mtu), 64 state_(EattChannelState::EATT_CHANNEL_PENDING), 65 indicate_handle_(0), 66 ind_ack_timer_(NULL), 67 ind_confirmation_timer_(NULL) { 68 cl_cmd_q_ = std::deque<tGATT_CMD_Q>(); 69 } 70 ~EattChannel()71 ~EattChannel() { 72 if (ind_ack_timer_ != NULL) { 73 alarm_free(ind_ack_timer_); 74 } 75 76 if (ind_confirmation_timer_ != NULL) { 77 alarm_free(ind_confirmation_timer_); 78 } 79 } 80 EattChannelSetState(EattChannelState state)81 void EattChannelSetState(EattChannelState state) { 82 if (state_ == EattChannelState::EATT_CHANNEL_PENDING) { 83 if (state == EattChannelState::EATT_CHANNEL_OPENED) { 84 memset(&server_outstanding_cmd_, 0, sizeof(tGATT_SR_CMD)); 85 char name[64]; 86 sprintf(name, "eatt_ind_ack_timer_%s_cid_0x%04x", 87 bda_.ToString().c_str(), cid_); 88 ind_ack_timer_ = alarm_new(name); 89 90 sprintf(name, "eatt_ind_conf_timer_%s_cid_0x%04x", 91 bda_.ToString().c_str(), cid_); 92 ind_confirmation_timer_ = alarm_new(name); 93 } 94 } 95 state_ = state; 96 } EattChannelSetTxMTU(uint16_t tx_mtu)97 void EattChannelSetTxMTU(uint16_t tx_mtu) { this->tx_mtu_ = tx_mtu; } 98 }; 99 100 /* Interface class */ 101 class EattExtension { 102 public: 103 EattExtension(); 104 EattExtension(const EattExtension&) = delete; 105 EattExtension& operator=(const EattExtension&) = delete; 106 107 virtual ~EattExtension(); 108 GetInstance()109 static EattExtension* GetInstance() { 110 static EattExtension* instance = new EattExtension(); 111 return instance; 112 } 113 114 static void AddFromStorage(const RawAddress& bd_addr); 115 116 /** 117 * Checks if EATT is supported on peer device. 118 * 119 * @param bd_addr peer device address 120 */ 121 virtual bool IsEattSupportedByPeer(const RawAddress& bd_addr); 122 123 /** 124 * Connect at maximum 5 EATT channels to peer device. 125 * 126 * @param bd_addr peer device address 127 */ 128 virtual void Connect(const RawAddress& bd_addr); 129 130 /** 131 * Disconnect all EATT channels to peer device. 132 * 133 * @param bd_addr peer device address 134 * @param cid remote channel id (EATT_ALL_CIDS for all) 135 */ 136 virtual void Disconnect(const RawAddress& bd_addr, 137 uint16_t cid = EATT_ALL_CIDS); 138 139 /** 140 * Reconfigure EATT channel for give CID 141 * 142 * @param bd_addr peer device address 143 * @param cid channel id 144 * @param mtu new maximum transmit unit available of local device 145 */ 146 virtual void Reconfigure(const RawAddress& bd_addr, uint16_t cid, 147 uint16_t mtu); 148 149 /** 150 * Reconfigure all EATT channels to peer device. 151 * 152 * @param bd_addr peer device address 153 * @param mtu new maximum transmit unit available of local device 154 */ 155 virtual void ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu); 156 157 /* Below methods required by GATT implementation */ 158 159 /** 160 * Find EATT channel by cid. 161 * 162 * @param bd_addr peer device address 163 * @param cid channel id 164 * 165 * @return Eatt Channel instance. 166 */ 167 virtual EattChannel* FindEattChannelByCid(const RawAddress& bd_addr, 168 uint16_t cid); 169 170 /** 171 * Find EATT channel by transaction id. 172 * 173 * @param bd_addr peer device address 174 * @param trans_id transaction id 175 * 176 * @return pointer to EATT channel. 177 */ 178 virtual EattChannel* FindEattChannelByTransId(const RawAddress& bd_addr, 179 uint32_t trans_id); 180 181 /** 182 * Check if EATT channel on given handle is waiting for a indication 183 * confirmation 184 * 185 * @param bd_addr peer device address 186 * @param indication_handle handle of the pending indication 187 * 188 * @return true if confirmation is pending false otherwise 189 */ 190 virtual bool IsIndicationPending(const RawAddress& bd_addr, 191 uint16_t indication_handle); 192 193 /** 194 * Get EATT channel available for indication. 195 * 196 * @param bd_addr peer device address 197 * 198 * @return pointer to EATT channel. 199 */ 200 virtual EattChannel* GetChannelAvailableForIndication( 201 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( 229 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( 239 const RawAddress& bd_addr); 240 241 /** 242 * Start GATT indication timer per CID. 243 * 244 * @param bd_addr peer device address 245 * @param cid channel id 246 */ 247 virtual void StartIndicationConfirmationTimer(const RawAddress& bd_addr, 248 uint16_t cid); 249 250 /** 251 * Stop GATT indication timer per CID. 252 * 253 * @param bd_addr peer device address 254 * @param cid channel id 255 */ 256 virtual void StopIndicationConfirmationTimer(const RawAddress& bd_addr, 257 uint16_t cid); 258 259 /** 260 * Start application time for incoming indication on given CID 261 * 262 * @param bd_addr peer device address 263 * @param cid channel id 264 */ 265 virtual void StartAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 266 267 /** 268 * Stop application time for incoming indication on given CID 269 * 270 * @param bd_addr peer device address 271 * @param cid channel id 272 */ 273 virtual void StopAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid); 274 275 /** 276 * Starts the EattExtension module 277 */ 278 void Start(); 279 280 /** 281 * Stops the EattExtension module 282 */ 283 void Stop(); 284 285 private: 286 struct impl; 287 std::unique_ptr<impl> pimpl_; 288 }; 289 290 } // namespace eatt 291 } // namespace bluetooth 292