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 #include "eatt_impl.h"
19 #include "stack/l2cap/l2c_int.h"
20 
21 using bluetooth::eatt::eatt_impl;
22 
23 namespace bluetooth {
24 namespace eatt {
25 
26 struct EattExtension::impl {
27   impl() = default;
28   ~impl() = default;
29 
Startbluetooth::eatt::EattExtension::impl30   void Start() {
31     if (eatt_impl_) {
32       LOG(ERROR) << "Eatt already started";
33       return;
34     };
35 
36     /* Register server for Eatt */
37     memset(&reg_info_, 0, sizeof(reg_info_));
38     reg_info_.pL2CA_CreditBasedConnectInd_Cb = eatt_connect_ind;
39     reg_info_.pL2CA_CreditBasedConnectCfm_Cb = eatt_connect_cfm;
40     reg_info_.pL2CA_CreditBasedReconfigCompleted_Cb = eatt_reconfig_completed;
41     reg_info_.pL2CA_DisconnectInd_Cb = eatt_disconnect_ind;
42     reg_info_.pL2CA_Error_Cb = eatt_error_cb;
43     reg_info_.pL2CA_DataInd_Cb = eatt_data_ind;
44 
45     if (L2CA_RegisterLECoc(BT_PSM_EATT, reg_info_, BTM_SEC_NONE, {}) == 0) {
46       LOG(ERROR) << __func__ << " cannot register EATT";
47     } else {
48       eatt_impl_ = std::make_unique<eatt_impl>();
49     }
50   }
51 
Stopbluetooth::eatt::EattExtension::impl52   void Stop() {
53     if (!eatt_impl_) {
54       LOG(ERROR) << "Eatt not started";
55       return;
56     }
57     eatt_impl_.reset(nullptr);
58     L2CA_DeregisterLECoc(BT_PSM_EATT);
59   }
60 
IsRunningbluetooth::eatt::EattExtension::impl61   bool IsRunning() { return eatt_impl_ ? true : false; }
62 
GetImplInstancebluetooth::eatt::EattExtension::impl63   static eatt_impl* GetImplInstance(void) {
64     auto* instance = EattExtension::GetInstance();
65     return instance->pimpl_->eatt_impl_.get();
66   }
67 
eatt_connect_indbluetooth::eatt::EattExtension::impl68   static void eatt_connect_ind(const RawAddress& bda,
69                                std::vector<uint16_t>& lcids, uint16_t psm,
70                                uint16_t peer_mtu, uint8_t identifier) {
71     auto p_eatt_impl = GetImplInstance();
72     if (p_eatt_impl)
73       p_eatt_impl->eatt_l2cap_connect_ind(bda, lcids, psm, peer_mtu,
74                                           identifier);
75   }
76 
eatt_connect_cfmbluetooth::eatt::EattExtension::impl77   static void eatt_connect_cfm(const RawAddress& bda, uint16_t lcid,
78                                uint16_t peer_mtu, uint16_t result) {
79     auto p_eatt_impl = GetImplInstance();
80     if (p_eatt_impl)
81       p_eatt_impl->eatt_l2cap_connect_cfm(bda, lcid, peer_mtu, result);
82   }
83 
eatt_reconfig_completedbluetooth::eatt::EattExtension::impl84   static void eatt_reconfig_completed(const RawAddress& bda, uint16_t lcid,
85                                       bool is_local_cfg,
86                                       tL2CAP_LE_CFG_INFO* p_cfg) {
87     auto p_eatt_impl = GetImplInstance();
88     if (p_eatt_impl)
89       p_eatt_impl->eatt_l2cap_reconfig_completed(bda, lcid, is_local_cfg,
90                                                  p_cfg);
91   }
92 
eatt_error_cbbluetooth::eatt::EattExtension::impl93   static void eatt_error_cb(uint16_t lcid, uint16_t reason) {
94     auto p_eatt_impl = GetImplInstance();
95     if (p_eatt_impl) p_eatt_impl->eatt_l2cap_error_cb(lcid, reason);
96   }
97 
eatt_disconnect_indbluetooth::eatt::EattExtension::impl98   static void eatt_disconnect_ind(uint16_t lcid, bool please_confirm) {
99     auto p_eatt_impl = GetImplInstance();
100     if (p_eatt_impl)
101       p_eatt_impl->eatt_l2cap_disconnect_ind(lcid, please_confirm);
102   }
103 
eatt_data_indbluetooth::eatt::EattExtension::impl104   static void eatt_data_ind(uint16_t lcid, BT_HDR* data_p) {
105     auto p_eatt_impl = GetImplInstance();
106     if (p_eatt_impl) p_eatt_impl->eatt_l2cap_data_ind(lcid, data_p);
107   }
108 
109   std::unique_ptr<eatt_impl> eatt_impl_;
110   tL2CAP_APPL_INFO reg_info_;
111 };
112 
AddFromStorage(const RawAddress & bd_addr)113 void EattExtension::AddFromStorage(const RawAddress& bd_addr) {
114   eatt_impl* p_eatt_impl = EattExtension::impl::GetImplInstance();
115   if (p_eatt_impl) p_eatt_impl->add_from_storage(bd_addr);
116 }
117 
EattExtension()118 EattExtension::EattExtension() : pimpl_(std::make_unique<impl>()) {}
119 
IsEattSupportedByPeer(const RawAddress & bd_addr)120 bool EattExtension::IsEattSupportedByPeer(const RawAddress& bd_addr) {
121   return pimpl_->eatt_impl_->is_eatt_supported_by_peer(bd_addr);
122 }
123 
Connect(const RawAddress & bd_addr)124 void EattExtension::Connect(const RawAddress& bd_addr) {
125   pimpl_->eatt_impl_->connect(bd_addr);
126 }
127 
Disconnect(const RawAddress & bd_addr)128 void EattExtension::Disconnect(const RawAddress& bd_addr) {
129   pimpl_->eatt_impl_->disconnect(bd_addr);
130 }
131 
Reconfigure(const RawAddress & bd_addr,uint16_t cid,uint16_t mtu)132 void EattExtension::Reconfigure(const RawAddress& bd_addr, uint16_t cid,
133                                 uint16_t mtu) {
134   pimpl_->eatt_impl_->reconfigure(bd_addr, cid, mtu);
135 }
ReconfigureAll(const RawAddress & bd_addr,uint16_t mtu)136 void EattExtension::ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu) {
137   pimpl_->eatt_impl_->reconfigure_all(bd_addr, mtu);
138 }
139 
FindEattChannelByCid(const RawAddress & bd_addr,uint16_t cid)140 EattChannel* EattExtension::FindEattChannelByCid(const RawAddress& bd_addr,
141                                                  uint16_t cid) {
142   return pimpl_->eatt_impl_->find_eatt_channel_by_cid(bd_addr, cid);
143 }
144 
FindEattChannelByTransId(const RawAddress & bd_addr,uint32_t trans_id)145 EattChannel* EattExtension::FindEattChannelByTransId(const RawAddress& bd_addr,
146                                                      uint32_t trans_id) {
147   return pimpl_->eatt_impl_->find_eatt_channel_by_transid(bd_addr, trans_id);
148 }
149 
IsIndicationPending(const RawAddress & bd_addr,uint16_t indication_handle)150 bool EattExtension::IsIndicationPending(const RawAddress& bd_addr,
151                                         uint16_t indication_handle) {
152   return pimpl_->eatt_impl_->is_indication_pending(bd_addr, indication_handle);
153 }
154 
GetChannelAvailableForIndication(const RawAddress & bd_addr)155 EattChannel* EattExtension::GetChannelAvailableForIndication(
156     const RawAddress& bd_addr) {
157   return pimpl_->eatt_impl_->get_channel_available_for_indication(bd_addr);
158 }
159 
FreeGattResources(const RawAddress & bd_addr)160 void EattExtension::FreeGattResources(const RawAddress& bd_addr) {
161   pimpl_->eatt_impl_->free_gatt_resources(bd_addr);
162 }
163 
IsOutstandingMsgInSendQueue(const RawAddress & bd_addr)164 bool EattExtension::IsOutstandingMsgInSendQueue(const RawAddress& bd_addr) {
165   return pimpl_->eatt_impl_->is_outstanding_msg_in_send_queue(bd_addr);
166 }
167 
GetChannelWithQueuedData(const RawAddress & bd_addr)168 EattChannel* EattExtension::GetChannelWithQueuedData(
169     const RawAddress& bd_addr) {
170   return pimpl_->eatt_impl_->get_channel_with_queued_data(bd_addr);
171 }
172 
GetChannelAvailableForClientRequest(const RawAddress & bd_addr)173 EattChannel* EattExtension::GetChannelAvailableForClientRequest(
174     const RawAddress& bd_addr) {
175   return pimpl_->eatt_impl_->get_channel_available_for_client_request(bd_addr);
176 }
177 
178 /* Start stop GATT indication timer per CID */
StartIndicationConfirmationTimer(const RawAddress & bd_addr,uint16_t cid)179 void EattExtension::StartIndicationConfirmationTimer(const RawAddress& bd_addr,
180                                                      uint16_t cid) {
181   pimpl_->eatt_impl_->start_indication_confirm_timer(bd_addr, cid);
182 }
183 
StopIndicationConfirmationTimer(const RawAddress & bd_addr,uint16_t cid)184 void EattExtension::StopIndicationConfirmationTimer(const RawAddress& bd_addr,
185                                                     uint16_t cid) {
186   pimpl_->eatt_impl_->stop_indication_confirm_timer(bd_addr, cid);
187 }
188 
189 /* Start stop application indication timeout */
StartAppIndicationTimer(const RawAddress & bd_addr,uint16_t cid)190 void EattExtension::StartAppIndicationTimer(const RawAddress& bd_addr,
191                                             uint16_t cid) {
192   pimpl_->eatt_impl_->start_app_indication_timer(bd_addr, cid);
193 }
194 
StopAppIndicationTimer(const RawAddress & bd_addr,uint16_t cid)195 void EattExtension::StopAppIndicationTimer(const RawAddress& bd_addr,
196                                            uint16_t cid) {
197   pimpl_->eatt_impl_->stop_app_indication_timer(bd_addr, cid);
198 }
199 
Start()200 void EattExtension::Start() { pimpl_->Start(); }
201 
Stop()202 void EattExtension::Stop() { pimpl_->Stop(); }
203 
204 EattExtension::~EattExtension() = default;
205 
206 }  // namespace eatt
207 }  // namespace bluetooth
208