1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hfp_hf_profile.h"
17
18 #include "btm.h"
19 #include "hfp_hf_command_processor.h"
20 #include "hfp_hf_defines.h"
21 #include "hfp_hf_profile_event_sender.h"
22 #include "hfp_hf_sdp_server.h"
23 #include "interface_profile.h"
24 #include "power_manager.h"
25
26 namespace OHOS {
27 namespace bluetooth {
28 #define HFP_HF_RETURN_IF_NOT_CONNECTED(state) \
29 do { \
30 if (!state) { \
31 LOG_ERROR("[HFP HF]%{public}s():SLC connection not established", __FUNCTION__); \
32 return false; \
33 } \
34 } while (0)
35
36 #define HFP_HF_RETURN_IF_NOT_ENABLED(enable) \
37 do { \
38 if (!enable) { \
39 LOG_ERROR("[HFP HF]%{public}s():function not allowed", __FUNCTION__); \
40 return false; \
41 } \
42 } while (0)
43
44 #define HFP_HF_RETURN_IF_NO_FEATURE(feature, mask) \
45 do { \
46 if (!(feature & mask)) { \
47 LOG_ERROR("[HFP HF]%{public}s():feature not supported", __FUNCTION__); \
48 return false; \
49 } \
50 } while (0)
51
52 #define HFP_HF_RETURN_IF_INDICATOR_EQUAL(ind1, ind2) \
53 do { \
54 if (ind1 == ind2) { \
55 LOG_WARN("[HFP HF]%{public}s():Indicator wouldn't be sent for its value not change", __FUNCTION__); \
56 return true; \
57 } \
58 } while (0)
59
RegisterService()60 int HfpHfProfile::RegisterService()
61 {
62 HfpHfDataConnection::Init();
63 HfpHfDataConnectionServer &connectionServer = HfpHfDataConnectionServer::GetInstance();
64 int ret = HfpHfSdpServer::GetInstance().RegisterSdpService(connectionServer.AssignLocalScn());
65 HFP_HF_RETURN_IF_FAIL(ret);
66
67 BTM_AddLocalRfcommScnForLogging(BTM_HCI_LOG_FILTER_MODULE_HFP, connectionServer.GetLocalScn());
68
69 ret = connectionServer.RegisterServer();
70 HFP_HF_RETURN_IF_FAIL(ret);
71
72 ret = HfpHfAudioConnection::Register();
73 HFP_HF_RETURN_IF_FAIL(ret);
74
75 return ret;
76 }
77
DeregisterService()78 int HfpHfProfile::DeregisterService()
79 {
80 HfpHfDataConnectionServer &connectionServer = HfpHfDataConnectionServer::GetInstance();
81 int ret = HfpHfSdpServer::GetInstance().DeregisterSdpService();
82 HFP_HF_RETURN_IF_FAIL(ret);
83
84 BTM_RemoveLocalRfcommScnChannelForLogging(BTM_HCI_LOG_FILTER_MODULE_HFP, connectionServer.GetLocalScn());
85
86 ret = connectionServer.RemoveServer();
87 HFP_HF_RETURN_IF_FAIL(ret);
88
89 ret = HfpHfAudioConnection::Deregister();
90 HFP_HF_RETURN_IF_FAIL(ret);
91
92 HfpHfDataConnection::CleanUp();
93 return ret;
94 }
95
HfpHfProfile(std::string address)96 HfpHfProfile::HfpHfProfile(std::string address) : address_(address)
97 {
98 }
99
Init()100 void HfpHfProfile::Init()
101 {
102 dataConn_.SetRemoteAddr(address_);
103 audioConn_.SetRemoteAddr(address_);
104 commandProcessor_.Init(address_);
105 }
106
DoServiceDiscovery(int role)107 int HfpHfProfile::DoServiceDiscovery(int role)
108 {
109 dataConn_.SetRole(role);
110 return sdpClient_.DoDiscovery(address_, role);
111 }
112
ServiceDiscoveryResult()113 int HfpHfProfile::ServiceDiscoveryResult()
114 {
115 int role = dataConn_.GetRole();
116 if (!sdpClient_.FindAttributes(address_, role)) {
117 LOG_ERROR("[HFP HF]%{public}s():FindAttributes() error", __FUNCTION__);
118 return HFP_HF_FAILURE;
119 }
120 dataConn_.SetSdpInfo(sdpClient_.GetRemoteSdpInfo());
121 if (HFP_HF_INITIATOR == role) {
122 EstablishDataConnection();
123 }
124 return HFP_HF_SUCCESS;
125 }
126
EstablishDataConnection()127 int HfpHfProfile::EstablishDataConnection()
128 {
129 RawAddress rawAddr(address_);
130 BtAddr btAddr;
131 rawAddr.ConvertToUint8(btAddr.addr);
132 btAddr.type = BT_PUBLIC_DEVICE_ADDRESS;
133 BTM_AddRemoteRfcommScnForLogging(BTM_HCI_LOG_FILTER_MODULE_HFP, dataConn_.GetRemoteScn(), &btAddr);
134 return dataConn_.Connect();
135 }
136
ReleaseDataConnection() const137 int HfpHfProfile::ReleaseDataConnection() const
138 {
139 return dataConn_.Disconnect();
140 }
141
AcceptDataConnection(uint16_t handle)142 int HfpHfProfile::AcceptDataConnection(uint16_t handle)
143 {
144 DoServiceDiscovery(HFP_HF_ACCEPTOR);
145 dataServer_.AcceptConnection(handle);
146 dataConn_.SetConnectionHandle(handle);
147 return HFP_HF_SUCCESS;
148 }
149
EstablishServiceLevelConnection()150 int HfpHfProfile::EstablishServiceLevelConnection()
151 {
152 commandProcessor_.ConnectSlc(dataConn_);
153 return HFP_HF_SUCCESS;
154 }
155
ReadData()156 int HfpHfProfile::ReadData()
157 {
158 HfpHfCommandParser::GetInstance().Read(dataConn_, commandProcessor_);
159 return HFP_HF_SUCCESS;
160 }
161
ProcessSlcEstablished()162 void HfpHfProfile::ProcessSlcEstablished()
163 {
164 IPowerManager::GetInstance().StatusUpdate(RequestStatus::CONNECT_ON, PROFILE_NAME_HFP_HF, RawAddress(address_));
165 if (!QuerySubscriberInfo()) {
166 LOG_ERROR("[HFP HF]%{public}s():can't query the subscriber information!", __FUNCTION__);
167 }
168 dataConn_.SetSlcConnectState(true);
169 }
170
SetupCodecConnection()171 int HfpHfProfile::SetupCodecConnection()
172 {
173 if (dataConn_.IsCodecNegotiationSupport()) {
174 isCodecSetupInitiator_ = true;
175 SendBcc();
176 } else {
177 dataConn_.inUseCodec_ = HFP_HF_CODEC_CVSD;
178 EstablishAudioConnection();
179 }
180
181 return HFP_HF_SUCCESS;
182 }
183
EstablishAudioConnection()184 int HfpHfProfile::EstablishAudioConnection()
185 {
186 audioConn_.SetSupportFeatures(dataConn_.IsEscoSupport(), dataConn_.IsEscoS4Support(), dataConn_.inUseCodec_);
187 audioConn_.ConnectAudio();
188 return HFP_HF_SUCCESS;
189 }
190
ReleaseAudioConnection() const191 int HfpHfProfile::ReleaseAudioConnection() const
192 {
193 audioConn_.DisconnectAudio();
194 return HFP_HF_SUCCESS;
195 }
196
AcceptAudioConnection()197 int HfpHfProfile::AcceptAudioConnection()
198 {
199 audioConn_.SetSupportFeatures(dataConn_.IsEscoSupport(), dataConn_.IsEscoS4Support(), dataConn_.inUseCodec_);
200 audioConn_.AcceptAudioConnection();
201 return HFP_HF_SUCCESS;
202 }
203
RejectAudioConnection() const204 int HfpHfProfile::RejectAudioConnection() const
205 {
206 audioConn_.RejectAudioConnection();
207 return HFP_HF_SUCCESS;
208 }
209
ProcessAudioConnReqInAudioConnecting()210 int HfpHfProfile::ProcessAudioConnReqInAudioConnecting()
211 {
212 if (isCodecSetupInitiator_ == false) {
213 return HFP_HF_FAILURE;
214 }
215
216 if (HfpHfAudioConnection::IsAudioConnected() == false) {
217 AcceptAudioConnection();
218 }
219 return HFP_HF_SUCCESS;
220 }
221
RestorCodecSetupRole()222 int HfpHfProfile::RestorCodecSetupRole()
223 {
224 isCodecSetupInitiator_ = false;
225 return HFP_HF_SUCCESS;
226 }
227
QueryCurrentCalls()228 bool HfpHfProfile::QueryCurrentCalls()
229 {
230 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
231
232 std::string cmd("AT+CLCC");
233 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_CLCC_EXECUTER);
234 return true;
235 }
236
QueryOperatorName(bool isQuery)237 bool HfpHfProfile::QueryOperatorName(bool isQuery)
238 {
239 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
240
241 std::string cmd("AT+COPS");
242 int commandId;
243 if (isQuery) {
244 cmd.append("?");
245 commandId = HfpHfCommandProcessor::AT_COPS_GETTER;
246 } else {
247 cmd.append("=3,0");
248 commandId = HfpHfCommandProcessor::AT_COPS_SETTER;
249 }
250 commandProcessor_.SendAtCommand(dataConn_, cmd, commandId);
251 return true;
252 }
253
QuerySubscriberInfo()254 bool HfpHfProfile::QuerySubscriberInfo()
255 {
256 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
257
258 std::string cmd("AT+CNUM");
259 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_CNUM_EXECUTER);
260 return true;
261 }
262
SendDtmf(uint8_t code)263 bool HfpHfProfile::SendDtmf(uint8_t code)
264 {
265 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
266
267 std::string cmd("AT+VTS=");
268 cmd += code;
269 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_VTS_SETTER);
270 return true;
271 }
272
SetHfVolume(int volume,int type)273 bool HfpHfProfile::SetHfVolume(int volume, int type)
274 {
275 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
276
277 // Make sure volume is in the range 0-15
278 int value = (volume > 15) ? 15 : volume;
279 value = (value < 0) ? 0 : value;
280
281 std::string cmd("AT+");
282 int commandId = HfpHfCommandProcessor::AT_COMMAND_NONE;
283 if (type == HFP_HF_VOLUME_TYPE_SPK) {
284 cmd.append("VGS");
285 commandId = HfpHfCommandProcessor::AT_VGS_SETTER;
286 } else if (type == HFP_HF_VOLUME_TYPE_MIC) {
287 cmd.append("VGM");
288 commandId = HfpHfCommandProcessor::AT_VGM_SETTER;
289 } else {
290 LOG_ERROR("[HFP HF]%{public}s():invalid type for volume!", __FUNCTION__);
291 return false;
292 }
293 cmd.append("=" + std::to_string(value));
294 commandProcessor_.SendAtCommand(dataConn_, cmd, commandId);
295 return true;
296 }
297
OpenVoiceRecognition()298 bool HfpHfProfile::OpenVoiceRecognition()
299 {
300 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
301 HFP_HF_RETURN_IF_NO_FEATURE(dataConn_.remoteFeatures_, HFP_HF_AG_FEATURES_VOICE_RECOGNITION);
302
303 std::string cmd("AT+BVRA=1");
304 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_BVRA_1_SETTER);
305 return true;
306 }
307
CloseVoiceRecognition()308 bool HfpHfProfile::CloseVoiceRecognition()
309 {
310 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
311 HFP_HF_RETURN_IF_NO_FEATURE(dataConn_.remoteFeatures_, HFP_HF_AG_FEATURES_VOICE_RECOGNITION);
312
313 std::string cmd("AT+BVRA=0");
314 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_BVRA_0_SETTER);
315 return true;
316 }
317
DialOutCall(const std::string & number)318 bool HfpHfProfile::DialOutCall(const std::string &number)
319 {
320 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
321
322 if (number.length() == 0) {
323 LOG_ERROR("[HFP HF]%{public}s():Invalid call number", __FUNCTION__);
324 return false;
325 }
326
327 std::string cmd("ATD");
328 cmd.append(number + ";");
329 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_ATD_EXECUTER);
330 return true;
331 }
332
DialMemory(int memory)333 bool HfpHfProfile::DialMemory(int memory)
334 {
335 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
336
337 std::string cmd("ATD>");
338 cmd.append(std::to_string(memory) + ";");
339 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_ATD_EXECUTER);
340 return true;
341 }
342
SendVoiceTag(int index)343 bool HfpHfProfile::SendVoiceTag(int index)
344 {
345 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
346
347 std::string cmd("AT+BINP");
348 cmd.append("=" + std::to_string(index));
349 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_BINP_SETTER);
350 return true;
351 }
352
SendKeyPressed()353 bool HfpHfProfile::SendKeyPressed()
354 {
355 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
356
357 std::string cmd("AT+CKPD=200");
358 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_CKPD_SETTER);
359 return true;
360 }
361
362
SendAta()363 bool HfpHfProfile::SendAta()
364 {
365 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
366
367 std::string cmd("ATA");
368 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_ATA_EXECUTER);
369 return true;
370 }
371
SendChld(int action,int idx)372 bool HfpHfProfile::SendChld(int action, int idx)
373 {
374 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
375
376 std::string cmd("AT+CHLD");
377 cmd.append("=" + std::to_string(action));
378 if (idx > 0) {
379 cmd.append(std::to_string(idx));
380 }
381 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_CHLD_SETTER);
382 return true;
383 }
384
SendChup()385 bool HfpHfProfile::SendChup()
386 {
387 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
388
389 std::string cmd("AT+CHUP");
390 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_CHUP_EXECUTER);
391 return true;
392 }
393
SendBtrh(int action)394 bool HfpHfProfile::SendBtrh(int action)
395 {
396 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
397
398 std::string cmd("AT+BTRH");
399 cmd.append("=" + std::to_string(action));
400 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_CHLD_SETTER);
401 return true;
402 }
403
SendBcc()404 bool HfpHfProfile::SendBcc()
405 {
406 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
407
408 std::string cmd("AT+BCC");
409 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_BCC_EXECUTER);
410 return true;
411 }
412
CallLastDialedNumber()413 bool HfpHfProfile::CallLastDialedNumber()
414 {
415 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
416
417 std::string cmd("AT+BLDN");
418 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_BLDN_EXECUTER);
419 return true;
420 }
421
CloseRemoteNrec()422 bool HfpHfProfile::CloseRemoteNrec()
423 {
424 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
425 HFP_HF_RETURN_IF_NO_FEATURE(dataConn_.remoteFeatures_, HFP_HF_AG_FEATURES_ECNR);
426
427 std::string cmd("AT+NREC=0");
428 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_NREC_SETTER);
429 return true;
430 }
431
ReportBatteryLevel(uint32_t battery)432 bool HfpHfProfile::ReportBatteryLevel(uint32_t battery)
433 {
434 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
435 HFP_HF_RETURN_IF_NOT_ENABLED(dataConn_.localHfIndicators_[0].isEnabled);
436 HFP_HF_RETURN_IF_INDICATOR_EQUAL(battery, dataConn_.localHfIndicators_[0].value);
437
438 dataConn_.localHfIndicators_[0].value = battery;
439 return ReportHfIndicator(HFP_HF_INDICATOR_BATTERY_LEVEL, battery);
440 }
441
ReportDriverSafety(uint32_t safety)442 bool HfpHfProfile::ReportDriverSafety(uint32_t safety)
443 {
444 HFP_HF_RETURN_IF_NOT_CONNECTED(dataConn_.slcConnected_);
445 HFP_HF_RETURN_IF_NOT_ENABLED(dataConn_.localHfIndicators_[1].isEnabled);
446 HFP_HF_RETURN_IF_INDICATOR_EQUAL(safety, dataConn_.localHfIndicators_[1].value);
447
448 dataConn_.localHfIndicators_[1].value = safety;
449 return ReportHfIndicator(HFP_HF_INDICATOR_DRIVER_SAFETY, safety);
450 }
451
ReportHfIndicator(int indicator,int value)452 bool HfpHfProfile::ReportHfIndicator(int indicator, int value)
453 {
454 auto it = std::find_if(dataConn_.remoteHfIndicators_.begin(),
455 dataConn_.remoteHfIndicators_.end(),
456 [&](const HfpHfDataConnection::HfIndicator &hfIndicator) {
457 return (hfIndicator.anum == indicator &&
458 (hfIndicator.isEnabled == false || hfIndicator.isSupported == false));
459 });
460
461 if (it != dataConn_.remoteHfIndicators_.end()) {
462 LOG_INFO("[HFP HF]%{public}s():Remote device not support/enable indicator[%{public}d]",
463 __FUNCTION__, indicator);
464 return true;
465 }
466
467 std::string cmd("AT+BIEV=");
468 cmd.append(std::to_string(indicator) + "," + std::to_string(value));
469 commandProcessor_.SendAtCommand(dataConn_, cmd, HfpHfCommandProcessor::AT_BIEV_SETTER);
470 return true;
471 }
472
RemoveStateMachine()473 void HfpHfProfile::RemoveStateMachine()
474 {
475 commandProcessor_.CleanUp();
476 HfpHfProfileEventSender::GetInstance().RemoveSateMachine(address_);
477 }
478
SendAtCommand(int cmdId,const std::string & arg)479 void HfpHfProfile::SendAtCommand(int cmdId, const std::string &arg)
480 {
481 switch (cmdId) {
482 case HfpHfCommandProcessor::AT_NREC_SETTER:
483 CloseRemoteNrec();
484 break;
485 case HfpHfCommandProcessor::AT_ATA_EXECUTER:
486 SendAta();
487 break;
488 case HfpHfCommandProcessor::AT_CLCC_EXECUTER:
489 QueryCurrentCalls();
490 break;
491 case HfpHfCommandProcessor::AT_BLDN_EXECUTER:
492 CallLastDialedNumber();
493 break;
494 case HfpHfCommandProcessor::AT_ATD_EXECUTER:
495 DialMemory(std::stoi(arg));
496 break;
497 default:
498 break;
499 }
500 }
501
ProcessAudioConnectRequest()502 void HfpHfProfile::ProcessAudioConnectRequest()
503 {
504 if (HfpHfAudioConnection::IsAudioConnected()) {
505 RejectAudioConnection();
506 } else {
507 AcceptAudioConnection();
508 }
509 }
510
RemoveRemoteScnLoging() const511 void HfpHfProfile::RemoveRemoteScnLoging() const
512 {
513 if (dataConn_.GetRole() == HFP_HF_INITIATOR) {
514 RawAddress rawAddr(address_);
515 BtAddr btAddr;
516 rawAddr.ConvertToUint8(btAddr.addr);
517 btAddr.type = BT_PUBLIC_DEVICE_ADDRESS;
518 BTM_RemoveRemoteRfcommScnChannelForLogging(BTM_HCI_LOG_FILTER_MODULE_HFP, dataConn_.GetRemoteScn(), &btAddr);
519 }
520 }
521 } // namespace bluetooth
522 } // namespace OHOS
523