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