• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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