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(®_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