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