From 28f005997222be5e825d6cf78c87feb077f40800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=8C=E8=90=8C=E8=90=8C=E6=96=B0?= Date: Tue, 13 May 2025 16:38:28 +0800 Subject: [PATCH] add hid,hfp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 萌萌萌新 --- bundle.json | 21 ++ frameworks/cj/BUILD.gn | 3 + frameworks/cj/hfp/BUILD.gn | 69 ++++++ .../cj/hfp/include/bluetooth_hfp_ag_impl.h | 40 ++++ frameworks/cj/hfp/include/bluetooth_hfp_ffi.h | 27 +++ .../include/bluetooth_hfp_hf_observer_impl.h | 49 ++++ .../cj/hfp/include/bluetooth_hfp_utils.h | 33 +++ .../cj/hfp/src/bluetooth_hfp_ag_impl.cpp | 123 ++++++++++ frameworks/cj/hfp/src/bluetooth_hfp_ffi.cpp | 44 ++++ .../src/bluetooth_hfp_hf_observer_impl.cpp | 52 +++++ frameworks/cj/hfp/src/bluetooth_hfp_utils.cpp | 33 +++ frameworks/cj/hid/BUILD.gn | 69 ++++++ .../cj/hid/include/bluetooth_hid_host_ffi.h | 27 +++ .../cj/hid/include/bluetooth_hid_host_impl.h | 38 ++++ .../bluetooth_hid_host_observer_impl.h | 41 ++++ .../cj/hid/include/bluetooth_hid_host_utils.h | 33 +++ .../cj/hid/src/bluetooth_hid_host_ffi.cpp | 44 ++++ .../cj/hid/src/bluetooth_hid_host_impl.cpp | 125 +++++++++++ .../src/bluetooth_hid_host_observer_impl.cpp | 52 +++++ .../cj/hid/src/bluetooth_hid_host_utils.cpp | 33 +++ frameworks/cj/socket/BUILD.gn | 68 ++++++ .../include/bluetooth_spp_client_impl.h | 86 +++++++ .../cj/socket/include/bluetooth_spp_ffi.h | 39 ++++ .../include/bluetooth_spp_server_impl.h | 40 ++++ .../cj/socket/include/bluetooth_spp_utils.h | 27 +++ .../socket/src/bluetooth_spp_client_impl.cpp | 212 ++++++++++++++++++ .../cj/socket/src/bluetooth_spp_ffi.cpp | 83 +++++++ .../socket/src/bluetooth_spp_server_impl.cpp | 112 +++++++++ .../cj/socket/src/bluetooth_spp_utils.cpp | 33 +++ 29 files changed, 1656 insertions(+) create mode 100644 frameworks/cj/hfp/BUILD.gn create mode 100644 frameworks/cj/hfp/include/bluetooth_hfp_ag_impl.h create mode 100644 frameworks/cj/hfp/include/bluetooth_hfp_ffi.h create mode 100644 frameworks/cj/hfp/include/bluetooth_hfp_hf_observer_impl.h create mode 100644 frameworks/cj/hfp/include/bluetooth_hfp_utils.h create mode 100644 frameworks/cj/hfp/src/bluetooth_hfp_ag_impl.cpp create mode 100644 frameworks/cj/hfp/src/bluetooth_hfp_ffi.cpp create mode 100644 frameworks/cj/hfp/src/bluetooth_hfp_hf_observer_impl.cpp create mode 100644 frameworks/cj/hfp/src/bluetooth_hfp_utils.cpp create mode 100644 frameworks/cj/hid/BUILD.gn create mode 100644 frameworks/cj/hid/include/bluetooth_hid_host_ffi.h create mode 100644 frameworks/cj/hid/include/bluetooth_hid_host_impl.h create mode 100644 frameworks/cj/hid/include/bluetooth_hid_host_observer_impl.h create mode 100644 frameworks/cj/hid/include/bluetooth_hid_host_utils.h create mode 100644 frameworks/cj/hid/src/bluetooth_hid_host_ffi.cpp create mode 100644 frameworks/cj/hid/src/bluetooth_hid_host_impl.cpp create mode 100644 frameworks/cj/hid/src/bluetooth_hid_host_observer_impl.cpp create mode 100644 frameworks/cj/hid/src/bluetooth_hid_host_utils.cpp create mode 100644 frameworks/cj/socket/BUILD.gn create mode 100644 frameworks/cj/socket/include/bluetooth_spp_client_impl.h create mode 100644 frameworks/cj/socket/include/bluetooth_spp_ffi.h create mode 100644 frameworks/cj/socket/include/bluetooth_spp_server_impl.h create mode 100644 frameworks/cj/socket/include/bluetooth_spp_utils.h create mode 100644 frameworks/cj/socket/src/bluetooth_spp_client_impl.cpp create mode 100644 frameworks/cj/socket/src/bluetooth_spp_ffi.cpp create mode 100644 frameworks/cj/socket/src/bluetooth_spp_server_impl.cpp create mode 100644 frameworks/cj/socket/src/bluetooth_spp_utils.cpp diff --git a/bundle.json b/bundle.json index b77272fd..100865c5 100644 --- a/bundle.json +++ b/bundle.json @@ -221,6 +221,27 @@ "header_files": [] }, "name": "//foundation/communication/bluetooth/frameworks/cj/connection:cj_bluetooth_connection_ffi" + }, + { + "header": { + "header_base": "//foundation/communication/bluetooth/frameworks/cj/hfp/include", + "header_files": [] + }, + "name": "//foundation/communication/bluetooth/frameworks/cj/hfp:cj_bluetooth_hfp_ffi" + }, + { + "header": { + "header_base": "//foundation/communication/bluetooth/frameworks/cj/hid/include", + "header_files": [] + }, + "name": "//foundation/communication/bluetooth/frameworks/cj/hid:cj_bluetooth_hid_ffi" + }, + { + "header": { + "header_base": "//foundation/communication/bluetooth/frameworks/cj/socket/include", + "header_files": [] + }, + "name": "//foundation/communication/bluetooth/frameworks/cj/socket:cj_bluetooth_socket_ffi" } ] } diff --git a/frameworks/cj/BUILD.gn b/frameworks/cj/BUILD.gn index d31cef2a..af4d3c91 100644 --- a/frameworks/cj/BUILD.gn +++ b/frameworks/cj/BUILD.gn @@ -19,5 +19,8 @@ group("bluetooth_ffi") { "$SUBSYSTEM_DIR/bluetooth/frameworks/cj/access:cj_bluetooth_access_ffi", "$SUBSYSTEM_DIR/bluetooth/frameworks/cj/ble:cj_bluetooth_ble_ffi", "$SUBSYSTEM_DIR/bluetooth/frameworks/cj/connection:cj_bluetooth_connection_ffi", + "$SUBSYSTEM_DIR/bluetooth/frameworks/cj/hfp:cj_bluetooth_hfp_ffi", + "$SUBSYSTEM_DIR/bluetooth/frameworks/cj/hid:cj_bluetooth_hid_ffi", + "$SUBSYSTEM_DIR/bluetooth/frameworks/cj/socket:cj_bluetooth_socket_ffi", ] } diff --git a/frameworks/cj/hfp/BUILD.gn b/frameworks/cj/hfp/BUILD.gn new file mode 100644 index 00000000..de30240c --- /dev/null +++ b/frameworks/cj/hfp/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (C) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("cj_bluetooth_hfp_ffi") { + branch_protector_ret = "pac_ret" # Enable PAC CFI + sanitize = { + cfi = true # Enable/disable control flow integrity detection + boundary_sanitize = true # Enable boundary san detection + cfi_cross_dso = true # Cross-SO CFI Checks + integer_overflow = true # Enable integer overflow detection + ubsan = true # Enable some Ubsan options + debug = false + } + + if (!defined(defines)) { + defines = [] + } + include_dirs = [ + "include", + "../../js/napi/include", + "../../../frameworks/inner/include", + ] + + deps = [ + "../../../frameworks/inner:btframework", + "../../../frameworks/js/napi/src/common:bt_napi_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "napi:ace_napi", + "napi:cj_bind_ffi", + "napi:cj_bind_native", + ] + + sources = [ + "src/bluetooth_hfp_ag_impl.cpp", + "src/bluetooth_hfp_ffi.cpp", + "src/bluetooth_hfp_hf_observer_impl.cpp", + "src/bluetooth_hfp_utils.cpp", + ] + + if (is_ohos) { + defines += [ "OHOS_PLATFORM" ] + } + + if (is_mingw) { + defines += [ "WINDOWS_PLATFORM" ] + } + + innerapi_tags = [ "platformsdk" ] + + part_name = "bluetooth" + subsystem_name = "communication" +} diff --git a/frameworks/cj/hfp/include/bluetooth_hfp_ag_impl.h b/frameworks/cj/hfp/include/bluetooth_hfp_ag_impl.h new file mode 100644 index 00000000..fe49fc6a --- /dev/null +++ b/frameworks/cj/hfp/include/bluetooth_hfp_ag_impl.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HFP_AG_IMPL_H +#define BLUETOOTH_HFP_AG_IMPL_H + +#include "bluetooth_hfp_ag.h" +#include "bluetooth_hfp_hf_observer_impl.h" +#include "cj_common_ffi.h" +#include "ffi_remote_data.h" + +namespace OHOS { +namespace Bluetooth { +class HandsFreeAudioGatewayImpl : public OHOS::FFI::FFIData { + DECL_TYPE(HandsFreeAudioGatewayImpl, OHOS::FFI::FFIData) +public: + explicit HandsFreeAudioGatewayImpl() {}; + ~HandsFreeAudioGatewayImpl() {}; + static CArrString GetConnectionDevices(int32_t* errCode); + static int32_t GetConnectionState(char* device, int32_t* errCode); + static void On(int32_t type, int64_t id, int32_t* errCode); + static std::shared_ptr observer_; + static bool isRegistered_; +}; + +} // namespace Bluetooth +} // namespace OHOS +#endif /* BLUETOOTH_HFP_AG_IMPL_H */ \ No newline at end of file diff --git a/frameworks/cj/hfp/include/bluetooth_hfp_ffi.h b/frameworks/cj/hfp/include/bluetooth_hfp_ffi.h new file mode 100644 index 00000000..3188d4f5 --- /dev/null +++ b/frameworks/cj/hfp/include/bluetooth_hfp_ffi.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HFP_FFI_H +#define BLUETOOTH_HFP_FFI_H + +#include "cj_common_ffi.h" + +extern "C" { +FFI_EXPORT CArrString FfiBluetoothHfpGetConnectedDevices(int32_t* errCode); +FFI_EXPORT int32_t FfiBluetoothHfpGetConnectionState(char* device, int32_t* errCode); +FFI_EXPORT void FfiBluetoothHfpOn(int32_t type, int64_t id, int32_t* errCode); +} + +#endif diff --git a/frameworks/cj/hfp/include/bluetooth_hfp_hf_observer_impl.h b/frameworks/cj/hfp/include/bluetooth_hfp_hf_observer_impl.h new file mode 100644 index 00000000..1a08934a --- /dev/null +++ b/frameworks/cj/hfp/include/bluetooth_hfp_hf_observer_impl.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HFP_HF_OBSERVER_IMPL_H +#define BLUETOOTH_HFP_HF_OBSERVER_IMPL_H + +#include + +#include "bluetooth_hfp_ag.h" +#include "bluetooth_hfp_utils.h" +#include "ffi_remote_data.h" + +namespace OHOS { +namespace Bluetooth { +const char* const STR_BT_HANDS_FREE_UNIT_OBSERVER_CONNECTION_STATE_CHANGE = "connectionStateChange"; + +class HandsFreeUnitObserverImpl : public HandsFreeAudioGatewayObserver, public OHOS::FFI::FFIData { + DECL_TYPE(HandsFreeUnitObserverImpl, OHOS::FFI::FFIData); + +public: + HandsFreeUnitObserverImpl() {}; + ~HandsFreeUnitObserverImpl() override = default; + void RegisterStateChangeFunc(std::function cjCallback); + void OnConnectionStateChanged(const BluetoothRemoteDevice& device, int state, int cause) override; + void OnScoStateChanged(const BluetoothRemoteDevice& device, int state, int reason = 0) override {}; + + void OnActiveDeviceChanged(const BluetoothRemoteDevice& device) override {} + void OnHfEnhancedDriverSafetyChanged(const BluetoothRemoteDevice& device, int indValue) override {} + void OnHfpStackChanged(const BluetoothRemoteDevice& device, int action) override {} + +private: + std::function stateChangeFunc { nullptr }; +}; + +} // namespace Bluetooth +} // namespace OHOS +#endif /* BLUETOOTH_HFP_HF_OBSERVER_IMPL_H */ \ No newline at end of file diff --git a/frameworks/cj/hfp/include/bluetooth_hfp_utils.h b/frameworks/cj/hfp/include/bluetooth_hfp_utils.h new file mode 100644 index 00000000..adbab5ad --- /dev/null +++ b/frameworks/cj/hfp/include/bluetooth_hfp_utils.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HFP_UTILS_H +#define BLUETOOTH_HFP_UTILS_H + +#include + +namespace OHOS { +namespace Bluetooth { +char* MallocCString(const std::string& origin); + +struct StateChangeParam { + char* deviceId; + int32_t state; + int32_t cause; +}; +} // namespace Bluetooth +} // namespace OHOS + +#endif // BLUETOOTH_HFP_UTILS_H \ No newline at end of file diff --git a/frameworks/cj/hfp/src/bluetooth_hfp_ag_impl.cpp b/frameworks/cj/hfp/src/bluetooth_hfp_ag_impl.cpp new file mode 100644 index 00000000..8ee904f7 --- /dev/null +++ b/frameworks/cj/hfp/src/bluetooth_hfp_ag_impl.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_hfp_ag" +#endif + +#include "bluetooth_hfp_ag_impl.h" + +#include + +#include "bluetooth_errorcode.h" +#include "bluetooth_utils.h" +#include "cj_lambda.h" +#include "napi_bluetooth_utils.h" + +using namespace OHOS::FFI; + +namespace OHOS { +namespace Bluetooth { +std::shared_ptr HandsFreeAudioGatewayImpl::observer_ = + std::make_shared(); +bool HandsFreeAudioGatewayImpl::isRegistered_ = false; + +CArrString HandsFreeAudioGatewayImpl::GetConnectionDevices(int32_t* errCode) +{ + HILOGD("enter"); + HandsFreeAudioGateway* profile = HandsFreeAudioGateway::GetProfile(); + if (profile == nullptr) { + HILOGE("profile is nullptr."); + *errCode = BT_ERR_INTERNAL_ERROR; + return CArrString { 0 }; + } + std::vector devices; + int errorCode = profile->GetConnectedDevices(devices); + if (errorCode != BT_NO_ERROR) { + HILOGE("bluetooth assert failed."); + *errCode = static_cast(errorCode); + return CArrString { 0 }; + } + if (devices.size() <= 0) { + return CArrString { 0 }; + } + char** deviceVector = static_cast(malloc(sizeof(char*) * devices.size())); + if (deviceVector == nullptr) { + HILOGE("deviceVector malloc failed."); + *errCode = BT_ERR_INTERNAL_ERROR; + return CArrString { 0 }; + } + int64_t i = 0; + for (auto& device : devices) { + deviceVector[i] = MallocCString(device.GetDeviceAddr()); + i++; + } + CArrString ret = CArrString { .head = deviceVector, .size = i }; + return ret; +} + +int32_t HandsFreeAudioGatewayImpl::GetConnectionState(char* device, int32_t* errCode) +{ + HILOGD("enter"); + int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED; + std::string remoteAddr = device; + if (!IsValidAddress(remoteAddr)) { + HILOGE("Invalid addr"); + *errCode = static_cast(BT_ERR_INVALID_PARAM); + return profileState; + } + HandsFreeAudioGateway* profile = HandsFreeAudioGateway::GetProfile(); + if (profile == nullptr) { + HILOGE("profile is nullptr."); + *errCode = BT_ERR_INTERNAL_ERROR; + return profileState; + } + BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR); + int32_t state = static_cast(BTConnectState::DISCONNECTED); + int32_t errorCode = profile->GetDeviceState(remoteDevice, state); + if (errorCode != BT_NO_ERROR) { + HILOGE("bluetooth assert failed."); + *errCode = errorCode; + return profileState; + } + profileState = GetProfileConnectionState(state); + return profileState; +} + +void HandsFreeAudioGatewayImpl::On(int32_t type, int64_t id, int32_t* errCode) +{ + if (observer_) { + auto observerFunc = CJLambda::Create(reinterpret_cast(id)); + if (!observerFunc) { + HILOGE("Register state change event failed"); + *errCode = BT_ERR_INVALID_PARAM; + return; + } + observer_->RegisterStateChangeFunc(observerFunc); + } + + if (!isRegistered_) { + HandsFreeAudioGateway* profile = HandsFreeAudioGateway::GetProfile(); + if (profile == nullptr) { + HILOGE("profile is nullptr."); + *errCode = BT_ERR_INVALID_PARAM; + return; + } + profile->RegisterObserver(observer_); + isRegistered_ = true; + } + return; +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hfp/src/bluetooth_hfp_ffi.cpp b/frameworks/cj/hfp/src/bluetooth_hfp_ffi.cpp new file mode 100644 index 00000000..db56b343 --- /dev/null +++ b/frameworks/cj/hfp/src/bluetooth_hfp_ffi.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_hfp_ffi" +#endif + +#include "bluetooth_hfp_ffi.h" + +#include "bluetooth_hfp_ag_impl.h" + +using namespace OHOS::FFI; + +namespace OHOS { +namespace Bluetooth { +extern "C" { +CArrString FfiBluetoothHfpGetConnectedDevices(int32_t* errCode) +{ + return HandsFreeAudioGatewayImpl::GetConnectionDevices(errCode); +} + +int32_t FfiBluetoothHfpGetConnectionState(char* device, int32_t* errCode) +{ + return HandsFreeAudioGatewayImpl::GetConnectionState(device, errCode); +} + +void FfiBluetoothHfpOn(int32_t type, int64_t id, int32_t* errCode) +{ + HandsFreeAudioGatewayImpl::On(type, id, errCode); +} +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hfp/src/bluetooth_hfp_hf_observer_impl.cpp b/frameworks/cj/hfp/src/bluetooth_hfp_hf_observer_impl.cpp new file mode 100644 index 00000000..a9869fa9 --- /dev/null +++ b/frameworks/cj/hfp/src/bluetooth_hfp_hf_observer_impl.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_hfp_ag_observer" +#endif + +#include "bluetooth_hfp_hf_observer_impl.h" + +#include "bluetooth_log.h" +#include "bluetooth_utils.h" + +namespace OHOS { +namespace Bluetooth { +void HandsFreeUnitObserverImpl::RegisterStateChangeFunc(std::function cjCallback) +{ + stateChangeFunc = cjCallback; +} + +void HandsFreeUnitObserverImpl::OnConnectionStateChanged(const BluetoothRemoteDevice& device, int state, int cause) +{ + HILOGD("enter, remote device address: %{public}s, state: %{public}d, cause: %{public}d", GET_ENCRYPT_ADDR(device), + state, cause); + if (!stateChangeFunc) { + HILOGE("failed to register state change callback"); + return; + } + char* deviceId = MallocCString(device.GetDeviceAddr()); + if (deviceId == nullptr) { + HILOGE("failed to malloc memory"); + return; + } + StateChangeParam param = StateChangeParam { + .deviceId = deviceId, .state = static_cast(state), .cause = static_cast(cause) + }; + stateChangeFunc(param); + free(deviceId); + return; +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hfp/src/bluetooth_hfp_utils.cpp b/frameworks/cj/hfp/src/bluetooth_hfp_utils.cpp new file mode 100644 index 00000000..98fe6333 --- /dev/null +++ b/frameworks/cj/hfp/src/bluetooth_hfp_utils.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bluetooth_hfp_utils.h" + +namespace OHOS { +namespace Bluetooth { +char* MallocCString(const std::string& origin) +{ + if (origin.empty()) { + return nullptr; + } + auto len = origin.length() + 1; + char* res = static_cast(malloc(sizeof(char) * len)); + if (res == nullptr) { + return nullptr; + } + return std::char_traits::copy(res, origin.c_str(), len); +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hid/BUILD.gn b/frameworks/cj/hid/BUILD.gn new file mode 100644 index 00000000..e4e55ddb --- /dev/null +++ b/frameworks/cj/hid/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (C) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("cj_bluetooth_hid_ffi") { + branch_protector_ret = "pac_ret" # Enable PAC CFI + sanitize = { + cfi = true # Enable/disable control flow integrity detection + boundary_sanitize = true # Enable boundary san detection + cfi_cross_dso = true # Cross-SO CFI Checks + integer_overflow = true # Enable integer overflow detection + ubsan = true # Enable some Ubsan options + debug = false + } + + if (!defined(defines)) { + defines = [] + } + include_dirs = [ + "include", + "../../js/napi/include", + "../../../frameworks/inner/include", + ] + + deps = [ + "../../../frameworks/inner:btframework", + "../../../frameworks/js/napi/src/common:bt_napi_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "napi:ace_napi", + "napi:cj_bind_ffi", + "napi:cj_bind_native", + ] + + sources = [ + "src/bluetooth_hid_host_ffi.cpp", + "src/bluetooth_hid_host_impl.cpp", + "src/bluetooth_hid_host_observer_impl.cpp", + "src/bluetooth_hid_host_utils.cpp", + ] + + if (is_ohos) { + defines += [ "OHOS_PLATFORM" ] + } + + if (is_mingw) { + defines += [ "WINDOWS_PLATFORM" ] + } + + innerapi_tags = [ "platformsdk" ] + + part_name = "bluetooth" + subsystem_name = "communication" +} diff --git a/frameworks/cj/hid/include/bluetooth_hid_host_ffi.h b/frameworks/cj/hid/include/bluetooth_hid_host_ffi.h new file mode 100644 index 00000000..3b41d389 --- /dev/null +++ b/frameworks/cj/hid/include/bluetooth_hid_host_ffi.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HID_HOST_FFI_H +#define BLUETOOTH_HID_HOST_FFI_H + +#include "cj_common_ffi.h" + +extern "C" { +FFI_EXPORT CArrString FfiBluetoothHidHostGetConnectedDevices(int32_t* errCode); +FFI_EXPORT int32_t FfiBluetoothHidHostGetConnectionState(char* device, int32_t* errCode); +FFI_EXPORT void FfiBluetoothHidHostOn(int32_t type, int64_t id, int32_t* errCode); +} + +#endif diff --git a/frameworks/cj/hid/include/bluetooth_hid_host_impl.h b/frameworks/cj/hid/include/bluetooth_hid_host_impl.h new file mode 100644 index 00000000..40367ccb --- /dev/null +++ b/frameworks/cj/hid/include/bluetooth_hid_host_impl.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BLUETOOTH_HID_HOST_IMPL_H +#define BLUETOOTH_HID_HOST_IMPL_H + +#include "bluetooth_hid_host.h" +#include "bluetooth_hid_host_observer_impl.h" +#include "cj_common_ffi.h" +#include "ffi_remote_data.h" + +namespace OHOS { +namespace Bluetooth { +class BluetoothHidHostImpl : public OHOS::FFI::FFIData { + DECL_TYPE(BluetoothHidHostImpl, OHOS::FFI::FFIData) +public: + explicit BluetoothHidHostImpl() {}; + ~BluetoothHidHostImpl() {}; + static CArrString GetConnectionDevices(int32_t* errCode); + static int32_t GetConnectionState(char* device, int32_t* errCode); + static void On(int32_t type, int64_t id, int32_t* errCode); + static std::shared_ptr observer_; + static bool isRegistered_; +}; +} // namespace Bluetooth +} // namespace OHOS +#endif // BLUETOOTH_HID_HOST_IMPL_H \ No newline at end of file diff --git a/frameworks/cj/hid/include/bluetooth_hid_host_observer_impl.h b/frameworks/cj/hid/include/bluetooth_hid_host_observer_impl.h new file mode 100644 index 00000000..54d163a3 --- /dev/null +++ b/frameworks/cj/hid/include/bluetooth_hid_host_observer_impl.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HID_HOST_OBSERVER_IMPL_H +#define BLUETOOTH_HID_HOST_OBSERVER_IMPL_H + +#include "bluetooth_hid_host.h" +#include "bluetooth_hid_host_utils.h" +#include "ffi_remote_data.h" + +namespace OHOS { +namespace Bluetooth { +const char* const STR_BT_HID_HOST_OBSERVER_CONNECTION_STATE_CHANGE = "connectionStateChange"; + +class BluetoothHidHostObserverImpl : public HidHostObserver, public OHOS::FFI::FFIData { + DECL_TYPE(BluetoothHidHostObserverImpl, OHOS::FFI::FFIData); + +public: + BluetoothHidHostObserverImpl() {}; + ~BluetoothHidHostObserverImpl() override = default; + void RegisterStateChangeFunc(std::function cjCallback); + void OnConnectionStateChanged(const BluetoothRemoteDevice& device, int state, int cause) override; + +private: + std::function stateChangeFunc { nullptr }; +}; +} // namespace Bluetooth +} // namespace OHOS +#endif // BLUETOOTH_HID_HOST_OBSERVER_IMPL_H diff --git a/frameworks/cj/hid/include/bluetooth_hid_host_utils.h b/frameworks/cj/hid/include/bluetooth_hid_host_utils.h new file mode 100644 index 00000000..a1527aa9 --- /dev/null +++ b/frameworks/cj/hid/include/bluetooth_hid_host_utils.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HID_HOST_UTILS_H +#define BLUETOOTH_HID_HOST_UTILS_H + +#include + +namespace OHOS { +namespace Bluetooth { +char* MallocCString(const std::string& origin); + +struct StateChangeParam { + char* deviceId; + int32_t state; + int32_t cause; +}; +} // namespace Bluetooth +} // namespace OHOS + +#endif // BLUETOOTH_HID_HOST_UTILS_H \ No newline at end of file diff --git a/frameworks/cj/hid/src/bluetooth_hid_host_ffi.cpp b/frameworks/cj/hid/src/bluetooth_hid_host_ffi.cpp new file mode 100644 index 00000000..9c8a7f0d --- /dev/null +++ b/frameworks/cj/hid/src/bluetooth_hid_host_ffi.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_hid_host_ffi" +#endif + +#include "bluetooth_hid_host_ffi.h" + +#include "bluetooth_hid_host_impl.h" + +using namespace OHOS::FFI; + +namespace OHOS { +namespace Bluetooth { +extern "C" { +CArrString FfiBluetoothHidHostGetConnectedDevices(int32_t* errCode) +{ + return BluetoothHidHostImpl::GetConnectionDevices(errCode); +} + +int32_t FfiBluetoothHidHostGetConnectionState(char* device, int32_t* errCode) +{ + return BluetoothHidHostImpl::GetConnectionState(device, errCode); +} + +void FfiBluetoothHidHostOn(int32_t type, int64_t id, int32_t* errCode) +{ + BluetoothHidHostImpl::On(type, id, errCode); +} +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hid/src/bluetooth_hid_host_impl.cpp b/frameworks/cj/hid/src/bluetooth_hid_host_impl.cpp new file mode 100644 index 00000000..eeb848c7 --- /dev/null +++ b/frameworks/cj/hid/src/bluetooth_hid_host_impl.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_hid_host" +#endif + +#include "bluetooth_hid_host_impl.h" + +#include + +#include "bluetooth_errorcode.h" +#include "bluetooth_hid_host_utils.h" +#include "bluetooth_utils.h" +#include "cj_lambda.h" +#include "napi_bluetooth_utils.h" + +using namespace OHOS::FFI; + +namespace OHOS { +namespace Bluetooth { +std::shared_ptr BluetoothHidHostImpl::observer_ = + std::make_shared(); +bool BluetoothHidHostImpl::isRegistered_ = false; + +CArrString BluetoothHidHostImpl::GetConnectionDevices(int32_t* errCode) +{ + HILOGD("enter"); + HidHost* profile = HidHost::GetProfile(); + if (profile == nullptr) { + HILOGE("profile is nullptr."); + *errCode = BT_ERR_INTERNAL_ERROR; + return CArrString { 0 }; + } + std::vector states = { static_cast(BTConnectState::CONNECTED) }; + std::vector devices; + int errorCode = profile->GetDevicesByStates(states, devices); + if (errorCode != BT_NO_ERROR) { + HILOGE("bluetooth assert failed."); + *errCode = static_cast(errorCode); + return CArrString { 0 }; + } + if (devices.size() <= 0) { + return CArrString { 0 }; + } + char** deviceVector = static_cast(malloc(sizeof(char*) * devices.size())); + if (deviceVector == nullptr) { + HILOGE("deviceVector malloc failed."); + *errCode = BT_ERR_INTERNAL_ERROR; + return CArrString { 0 }; + } + int64_t i = 0; + for (auto& device : devices) { + deviceVector[i] = MallocCString(device.GetDeviceAddr()); + i++; + } + CArrString ret = CArrString { .head = deviceVector, .size = i }; + return ret; +} + +int32_t BluetoothHidHostImpl::GetConnectionState(char* device, int32_t* errCode) +{ + HILOGD("enter"); + int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED; + std::string remoteAddr = device; + if (!IsValidAddress(remoteAddr)) { + HILOGE("Invalid addr"); + *errCode = static_cast(BT_ERR_INVALID_PARAM); + return profileState; + } + HidHost* profile = HidHost::GetProfile(); + if (profile == nullptr) { + HILOGE("profile is nullptr."); + *errCode = BT_ERR_INTERNAL_ERROR; + return profileState; + } + BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR); + int32_t state = static_cast(BTConnectState::DISCONNECTED); + int32_t errorCode = profile->GetDeviceState(remoteDevice, state); + if (errorCode != BT_NO_ERROR) { + HILOGE("bluetooth assert failed."); + *errCode = errorCode; + return profileState; + } + profileState = GetProfileConnectionState(state); + return profileState; +} + +void BluetoothHidHostImpl::On(int32_t type, int64_t id, int32_t* errCode) +{ + if (observer_) { + auto observerFunc = CJLambda::Create(reinterpret_cast(id)); + if (!observerFunc) { + HILOGD("Register state change event failed"); + *errCode = BT_ERR_INVALID_PARAM; + return; + } + observer_->RegisterStateChangeFunc(observerFunc); + } + + if (!isRegistered_) { + HidHost* profile = HidHost::GetProfile(); + if (profile == nullptr) { + HILOGE("profile is nullptr."); + *errCode = BT_ERR_INVALID_PARAM; + return; + } + profile->RegisterObserver(observer_); + isRegistered_ = true; + } + return; +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hid/src/bluetooth_hid_host_observer_impl.cpp b/frameworks/cj/hid/src/bluetooth_hid_host_observer_impl.cpp new file mode 100644 index 00000000..6955f02e --- /dev/null +++ b/frameworks/cj/hid/src/bluetooth_hid_host_observer_impl.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_hid_host_observer" +#endif + +#include "bluetooth_hid_host_observer_impl.h" + +#include "bluetooth_log.h" +#include "bluetooth_utils.h" + +namespace OHOS { +namespace Bluetooth { +void BluetoothHidHostObserverImpl::RegisterStateChangeFunc(std::function cjCallback) +{ + stateChangeFunc = cjCallback; +} + +void BluetoothHidHostObserverImpl::OnConnectionStateChanged(const BluetoothRemoteDevice& device, int state, int cause) +{ + HILOGD("enter, remote device address: %{public}s, state: %{public}d, cause: %{public}d", GET_ENCRYPT_ADDR(device), + state, cause); + if (!stateChangeFunc) { + HILOGE("failed to register state change callback"); + return; + } + char* deviceId = MallocCString(device.GetDeviceAddr()); + if (deviceId == nullptr) { + HILOGE("failed to malloc memory"); + return; + } + StateChangeParam param = StateChangeParam { + .deviceId = deviceId, .state = static_cast(state), .cause = static_cast(cause) + }; + stateChangeFunc(param); + free(deviceId); + return; +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/hid/src/bluetooth_hid_host_utils.cpp b/frameworks/cj/hid/src/bluetooth_hid_host_utils.cpp new file mode 100644 index 00000000..8d263c96 --- /dev/null +++ b/frameworks/cj/hid/src/bluetooth_hid_host_utils.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bluetooth_hid_host_utils.h" + +namespace OHOS { +namespace Bluetooth { +char* MallocCString(const std::string& origin) +{ + if (origin.empty()) { + return nullptr; + } + auto len = origin.length() + 1; + char* res = static_cast(malloc(sizeof(char) * len)); + if (res == nullptr) { + return nullptr; + } + return std::char_traits::copy(res, origin.c_str(), len); +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/socket/BUILD.gn b/frameworks/cj/socket/BUILD.gn new file mode 100644 index 00000000..119280c3 --- /dev/null +++ b/frameworks/cj/socket/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (C) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +ohos_shared_library("cj_bluetooth_socket_ffi") { + branch_protector_ret = "pac_ret" # Enable PAC CFI + sanitize = { + cfi = true # Enable/disable control flow integrity detection + boundary_sanitize = true # Enable boundary san detection + cfi_cross_dso = true # Cross-SO CFI Checks + integer_overflow = true # Enable integer overflow detection + ubsan = true # Enable some Ubsan options + debug = false + } + + if (!defined(defines)) { + defines = [] + } + include_dirs = [ + "include", + "../../js/napi/include", + "../../../frameworks/inner/include", + ] + + deps = [ + "../../../frameworks/inner:btframework", + "../../../frameworks/js/napi/src/common:bt_napi_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "napi:ace_napi", + "napi:cj_bind_ffi", + "napi:cj_bind_native", + ] + + sources = [ + "src/bluetooth_spp_client_impl.cpp", + "src/bluetooth_spp_ffi.cpp", + "src/bluetooth_spp_server_impl.cpp", + "src/bluetooth_spp_utils.cpp", + ] + + if (is_ohos) { + defines += [ "OHOS_PLATFORM" ] + } + + if (is_mingw) { + defines += [ "WINDOWS_PLATFORM" ] + } + + innerapi_tags = [ "platformsdk" ] + + part_name = "bluetooth" + subsystem_name = "communication" +} diff --git a/frameworks/cj/socket/include/bluetooth_spp_client_impl.h b/frameworks/cj/socket/include/bluetooth_spp_client_impl.h new file mode 100644 index 00000000..f0ff7e21 --- /dev/null +++ b/frameworks/cj/socket/include/bluetooth_spp_client_impl.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BLUETOOTH_SPP_CLIENT_IMPL_H +#define BLUETOOTH_SPP_CLIENT_IMPL_H + +#include +#include +#include + +#include "bluetooth_socket.h" +#include "bluetooth_spp_utils.h" +#include "cj_common_ffi.h" +#include "napi_bluetooth_utils.h" + +namespace OHOS { +namespace Bluetooth { +struct CjBluetoothCallbackInfo { + int64_t callback_ = 0; + std::string deviceId_; +}; + +struct SppCallbackBuffer { + ssize_t len_; + char data_[1024]; +}; + +struct BufferCallbackInfo : public CjBluetoothCallbackInfo { + void PushData(const std::shared_ptr& data) + { + std::lock_guard lock(bufferLock_); + buffer_.push(data); + } + + std::shared_ptr PopData() + { + std::lock_guard lock(bufferLock_); + if (buffer_.empty()) { + return nullptr; + } + std::shared_ptr ret = buffer_.front(); + buffer_.pop(); + return ret; + } + +private: + std::mutex bufferLock_; + std::queue> buffer_; +}; + +constexpr const char* REGISTER_SPP_READ_TYPE = "sppRead"; + +struct SppClientImpl { + static int32_t SppConnect(std::string deviceId, SppOption sppOption, int32_t* errCode); + static int32_t SppCloseClientSocket(int32_t socket); + static int32_t SppWrite(int32_t clientSocket, CArrUI8 data); + static int32_t On(std::string type, int32_t clientSocket, int64_t cbId); + static int32_t Off(std::string type, int32_t clientSocket, int64_t cbId); + static void SppRead(int id); + static std::string GetDeviceId(int32_t clientSocket, int32_t* errCode); + + static int count; + static std::map> clientMap; + + int id_ = -1; + bool sppReadFlag = false; + std::map> callbackInfos_ = {}; + + std::shared_ptr client_ = nullptr; + std::shared_ptr device_ = nullptr; + std::shared_ptr thread_; +}; +} // namespace Bluetooth +} // namespace OHOS +#endif /* BLUETOOTH_SPP_CLIENT_IMPL_H */ \ No newline at end of file diff --git a/frameworks/cj/socket/include/bluetooth_spp_ffi.h b/frameworks/cj/socket/include/bluetooth_spp_ffi.h new file mode 100644 index 00000000..253cdc86 --- /dev/null +++ b/frameworks/cj/socket/include/bluetooth_spp_ffi.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_SPP_FFI_H +#define BLUETOOTH_SPP_FFI_H + +#include "cj_common_ffi.h" + +extern "C" { +struct CSppOption { + char* uuid; + bool secure; + int32_t type; +}; + +FFI_EXPORT int32_t FfiBluetoothSocketSppListen(char* name, CSppOption options, int32_t* errCode); +FFI_EXPORT int32_t FfiBluetoothSocketSppAccept(int32_t serverSocket, int32_t* errCode); +FFI_EXPORT int32_t FfiBluetoothSocketSppConnect(char* deviceId, CSppOption options, int32_t* errCode); +FFI_EXPORT char* FfiBluetoothSocketGetDeviceId(int32_t clientSocket, int32_t* errCode); +FFI_EXPORT void FfiBluetoothSocketSppCloseServerSocket(int32_t socket, int32_t* errCode); +FFI_EXPORT void FfiBluetoothSocketSppCloseClientSocket(int32_t socket, int32_t* errCode); +FFI_EXPORT void FfiBluetoothSocketSppWrite(int32_t clientSocket, CArrUI8 data, int32_t* errCode); +FFI_EXPORT void FfiBluetoothSocketOn(char* type, int32_t clientSocket, int64_t cbId, int32_t* errCode); +FFI_EXPORT void FfiBluetoothSocketOff(char* type, int32_t clientSocket, int64_t cbId, int32_t* errCode); +} + +#endif diff --git a/frameworks/cj/socket/include/bluetooth_spp_server_impl.h b/frameworks/cj/socket/include/bluetooth_spp_server_impl.h new file mode 100644 index 00000000..9a8f4904 --- /dev/null +++ b/frameworks/cj/socket/include/bluetooth_spp_server_impl.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BLUETOOTH_SPP_SERVER_IMPL_H +#define BLUETOOTH_SPP_SERVER_IMPL_H + +#include + +#include "bluetooth_socket.h" +#include "bluetooth_spp_client_impl.h" + +namespace OHOS { +namespace Bluetooth { +struct SppServerImpl { + static int32_t SppListen(std::string name, SppOption sppOption, int32_t* errCode); + static int32_t SppAccept(int32_t serverSocket, int32_t* errCode); + static int32_t SppCloseServerSocket(int32_t socket); + static int32_t RegisterSocketObserver(std::string type, int32_t clientSocket, int64_t cbId); + static int32_t DeRegisterSocketObserver(std::string type, int32_t clientSocket, int64_t cbId); + + static std::map> serverMap; + static int count; + + std::shared_ptr server_ = nullptr; + int id_ = -1; +}; +} // namespace Bluetooth +} // namespace OHOS +#endif /* BLUETOOTH_SPP_SERVER_IMPL_H */ \ No newline at end of file diff --git a/frameworks/cj/socket/include/bluetooth_spp_utils.h b/frameworks/cj/socket/include/bluetooth_spp_utils.h new file mode 100644 index 00000000..af49b7d7 --- /dev/null +++ b/frameworks/cj/socket/include/bluetooth_spp_utils.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_HID_HOST_UTILS_H +#define BLUETOOTH_HID_HOST_UTILS_H + +#include + +namespace OHOS { +namespace Bluetooth { +char* MallocCString(const std::string& origin); +} // namespace Bluetooth +} // namespace OHOS + +#endif // BLUETOOTH_HID_HOST_UTILS_H \ No newline at end of file diff --git a/frameworks/cj/socket/src/bluetooth_spp_client_impl.cpp b/frameworks/cj/socket/src/bluetooth_spp_client_impl.cpp new file mode 100644 index 00000000..80f11776 --- /dev/null +++ b/frameworks/cj/socket/src/bluetooth_spp_client_impl.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_socket_spp_client" +#endif + +#include "bluetooth_spp_client_impl.h" + +#include "bluetooth_errorcode.h" +#include "bluetooth_host.h" +#include "cj_lambda.h" +#include "datetime_ex.h" +#include "napi_bluetooth_utils.h" +#include "securec.h" + +namespace OHOS { +namespace Bluetooth { +std::map> SppClientImpl::clientMap; +int SppClientImpl::count = 0; +const int SOCKET_BUFFER_SIZE = 1024; + +int32_t SppClientImpl::SppConnect(std::string deviceId, SppOption sppOption, int32_t* errCode) +{ + HILOGD("enter"); + std::shared_ptr device_ = std::make_shared(deviceId, 0); + std::shared_ptr client_ = + std::make_shared(*device_, UUID::FromString(sppOption.uuid_), sppOption.type_, sppOption.secure_); + int errorCode = client_->Connect(SPP_SOCKET_PSM_VALUE); + if (errorCode != BtStatus::BT_SUCCESS) { + HILOGE("SppConnect failed"); + *errCode = errorCode; + return -1; + } + std::shared_ptr client = std::make_shared(); + client->device_ = device_; + client->id_ = SppClientImpl::count++; + client->client_ = client_; + clientMap.insert(std::make_pair(client->id_, client)); + HILOGD("SppConnect execute back successfully"); + return client->id_; +} + +int32_t SppClientImpl::SppCloseClientSocket(int32_t socket) +{ + HILOGD("enter"); + std::shared_ptr client = nullptr; + bool isOK = false; + + if (clientMap[socket]) { + client = clientMap[socket]; + } else { + HILOGE("invalid socket."); + return BT_ERR_INVALID_PARAM; + } + + if (client->client_) { + client->client_->Close(); + isOK = true; + } + clientMap.erase(socket); + return isOK ? 0 : BT_ERR_INVALID_PARAM; +} + +int32_t SppClientImpl::SppWrite(int32_t clientSocket, CArrUI8 data) +{ + HILOGD("enter"); + BluetoothHost* host = &BluetoothHost::GetDefaultHost(); + auto prohibitedTime = host->GetRefusePolicyProhibitedTime(); + if (prohibitedTime < 0 || prohibitedTime > GetSecondsSince1970ToNow()) { + HILOGE("socket refuse because of Refuse Policy"); + return BT_ERR_INVALID_PARAM; + } + auto client = clientMap[clientSocket]; + if (client == nullptr) { + HILOGE("client is nullptr."); + return BT_ERR_INVALID_PARAM; + } + if (client->client_ == nullptr) { + HILOGE("client_ is nullptr."); + return BT_ERR_INVALID_PARAM; + } + std::shared_ptr outputStream = client->client_->GetOutputStream(); + size_t totalSize = static_cast(data.size); + bool isOK = false; + while (totalSize) { + int result = outputStream->Write(data.head, totalSize); + if (result <= 0) { + HILOGE("outputStream.Write failed, ret = %{public}d", result); + return BT_ERR_SPP_IO; + } + totalSize = totalSize - static_cast(result); + data.head += static_cast(result); + isOK = true; + } + return isOK ? 0 : BT_ERR_INVALID_PARAM; +} + +int32_t SppClientImpl::On(std::string type, int32_t clientSocket, int64_t cbId) +{ + HILOGD("enter"); + std::shared_ptr callbackInfo = std::make_shared(); + callbackInfo->callback_ = cbId; + std::shared_ptr client = SppClientImpl::clientMap[clientSocket]; + if (client == nullptr) { + HILOGE("client is nullptr."); + return BT_ERR_INVALID_PARAM; + } + if (client->sppReadFlag) { + HILOGE("client is reading... please off first"); + return BT_ERR_INVALID_PARAM; + } + client->sppReadFlag = true; + client->callbackInfos_[type] = callbackInfo; + client->thread_ = std::make_shared(SppClientImpl::SppRead, clientSocket); + client->thread_->detach(); + return 0; +} + +int32_t SppClientImpl::Off(std::string type, int32_t clientSocket, int64_t cbId) +{ + HILOGD("enter"); + std::shared_ptr client = SppClientImpl::clientMap[clientSocket]; + if (client == nullptr) { + HILOGE("client is nullptr."); + return BT_ERR_INVALID_PARAM; + } + client->callbackInfos_[type] = nullptr; + client->sppReadFlag = false; + return 0; +} + +void SppClientImpl::SppRead(int id) +{ + auto client = clientMap[id]; + if (client == nullptr || !client->sppReadFlag || client->callbackInfos_[REGISTER_SPP_READ_TYPE] == nullptr) { + HILOGE("thread start failed."); + return; + } + std::shared_ptr inputStream = client->client_->GetInputStream(); + uint8_t buf[SOCKET_BUFFER_SIZE]; + + while (true) { + HILOGD("thread start."); + (void)memset_s(buf, SOCKET_BUFFER_SIZE, 0, SOCKET_BUFFER_SIZE); + int ret = inputStream->Read(buf, sizeof(buf)); + if (ret <= 0) { + HILOGE("inputStream.Read failed, ret = %{public}d", ret); + return; + } else { + if (client == nullptr || !client->sppReadFlag || !client->callbackInfos_[REGISTER_SPP_READ_TYPE]) { + HILOGE("failed"); + return; + } + std::shared_ptr callbackInfo = + std::static_pointer_cast(client->callbackInfos_[REGISTER_SPP_READ_TYPE]); + if (callbackInfo == nullptr) { + HILOGE("callbackInfo nullptr"); + return; + } + + CArrUI8 buffer {}; + buffer.head = static_cast(malloc(sizeof(uint8_t) * ret)); + if (buffer.head == nullptr) { + HILOGE("malloc failed!"); + return; + } + buffer.size = ret; + if (memcpy_s(buffer.head, ret, buf, ret) != EOK) { + HILOGE("memcpy_s failed!"); + free(buffer.head) + return; + } + + auto cFunc = reinterpret_cast(callbackInfo->callback_); + std::function func = CJLambda::Create(cFunc); + func(buffer); + free(buffer.head); + } + } + return; +} + +std::string SppClientImpl::GetDeviceId(int32_t clientSocket, int32_t* errCode) +{ + HILOGD("enter"); + auto client = clientMap[clientSocket]; + if (client == nullptr) { + *errCode = BT_ERR_INVALID_PARAM; + return std::string(); + } + if (client->client_ == nullptr) { + *errCode = BT_ERR_INVALID_PARAM; + return std::string(); + } + BluetoothRemoteDevice remoteDevice = client->client_->GetRemoteDevice(); + std::string addr = remoteDevice.GetDeviceAddr(); + return addr; +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/socket/src/bluetooth_spp_ffi.cpp b/frameworks/cj/socket/src/bluetooth_spp_ffi.cpp new file mode 100644 index 00000000..251f29b7 --- /dev/null +++ b/frameworks/cj/socket/src/bluetooth_spp_ffi.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_socket_spp_ffi" +#endif + +#include "bluetooth_spp_ffi.h" + +#include "bluetooth_spp_server_impl.h" +#include "bluetooth_spp_utils.h" + +namespace OHOS { +namespace Bluetooth { +extern "C" { +static SppOption parseCSppOptions(CSppOption options) +{ + SppOption ret = { .uuid_ = options.uuid, .secure_ = options.secure, .type_ = BtSocketType(options.type) }; + return ret; +} + +int32_t FfiBluetoothSocketSppListen(char* name, CSppOption options, int32_t* errCode) +{ + return SppServerImpl::SppListen(name, parseCSppOptions(options), errCode); +} + +int32_t FfiBluetoothSocketSppAccept(int32_t serverSocket, int32_t* errCode) +{ + return SppServerImpl::SppAccept(serverSocket, errCode); +} + +int32_t FfiBluetoothSocketSppConnect(char* deviceId, CSppOption options, int32_t* errCode) +{ + return SppClientImpl::SppConnect(deviceId, parseCSppOptions(options), errCode); +} + +char* FfiBluetoothSocketGetDeviceId(int32_t clientSocket, int32_t* errCode) +{ + std::string deviceId = SppClientImpl::GetDeviceId(clientSocket, errCode); + if (*errCode != SUCCESS_CODE) { + return nullptr; + } + return MallocCString(deviceId); +} + +void FfiBluetoothSocketSppCloseServerSocket(int32_t socket, int32_t* errCode) +{ + *errCode = SppServerImpl::SppCloseServerSocket(socket); +} + +void FfiBluetoothSocketSppCloseClientSocket(int32_t socket, int32_t* errCode) +{ + *errCode = SppClientImpl::SppCloseClientSocket(socket); +} + +void FfiBluetoothSocketSppWrite(int32_t clientSocket, CArrUI8 data, int32_t* errCode) +{ + *errCode = SppClientImpl::SppWrite(clientSocket, data); +} + +void FfiBluetoothSocketOn(char* type, int32_t clientSocket, int64_t cbId, int32_t* errCode) +{ + *errCode = SppServerImpl::RegisterSocketObserver(type, clientSocket, cbId); +} + +void FfiBluetoothSocketOff(char* type, int32_t clientSocket, int64_t cbId, int32_t* errCode) +{ + *errCode = SppServerImpl::DeRegisterSocketObserver(type, clientSocket, cbId); +} +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/socket/src/bluetooth_spp_server_impl.cpp b/frameworks/cj/socket/src/bluetooth_spp_server_impl.cpp new file mode 100644 index 00000000..2d8ab6b2 --- /dev/null +++ b/frameworks/cj/socket/src/bluetooth_spp_server_impl.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LOG_TAG +#define LOG_TAG "bt_cj_socket_spp_server" +#endif + +#include "bluetooth_spp_server_impl.h" + +#include "bluetooth_errorcode.h" +#include "napi_bluetooth_utils.h" + +namespace OHOS { +namespace Bluetooth { +const int NUM_20 = 20; +int SppServerImpl::count = 0; +std::map> SppServerImpl::serverMap; + +int32_t SppServerImpl::SppListen(std::string name, SppOption sppOption, int32_t* errCode) +{ + HILOGD("enter"); + std::shared_ptr server_ = + std::make_shared(name, UUID::FromString(sppOption.uuid_), sppOption.type_, sppOption.secure_); + int errorCode = server_->Listen(); + if (server_->GetStringTag() != "") { + HILOGD("SppListen execute listen success"); + } else { + HILOGE("SppListen execute listen failed"); + *errCode = static_cast(errorCode); + return -1; + } + std::shared_ptr server = std::make_shared(); + server->id_ = SppServerImpl::count++; + server->server_ = server_; + serverMap.insert(std::make_pair(server->id_, server)); + return static_cast(server->id_); +} + +int32_t SppServerImpl::SppAccept(int32_t serverSocket, int32_t* errCode) +{ + HILOGD("enter"); + std::shared_ptr server = SppServerImpl::serverMap[serverSocket]; + if (!server) { + HILOGE("server is null"); + *errCode = BT_ERR_INVALID_PARAM; + return -1; + } + std::shared_ptr server_ = server->server_; + std::shared_ptr client_ = server_->Accept(NUM_20); + if (client_ == nullptr) { + HILOGE("client_ is null"); + *errCode = BT_ERR_INVALID_PARAM; + return -1; + } + std::shared_ptr client = std::make_shared(); + client->id_ = SppClientImpl::count++; + client->client_ = client_; + SppClientImpl::clientMap.insert(std::make_pair(client->id_, client)); + return static_cast(client->id_); +} + +int32_t SppServerImpl::RegisterSocketObserver(std::string type, int32_t clientSocket, int64_t cbId) +{ + return SppClientImpl::On(type, clientSocket, cbId); +} + +int32_t SppServerImpl::DeRegisterSocketObserver(std::string type, int32_t clientSocket, int64_t cbId) +{ + return SppClientImpl::Off(type, clientSocket, cbId); +} + +int32_t SppServerImpl::SppCloseServerSocket(int32_t socket) +{ + HILOGD("enter"); + bool isOK = false; + + std::shared_ptr server = nullptr; + std::shared_ptr client = nullptr; + if (SppClientImpl::clientMap[socket] != nullptr) { + client = SppClientImpl::clientMap[socket]; + if (client->client_) { + client->client_->Close(); + SppClientImpl::clientMap.erase(socket); + } + } else { + HILOGE("invalid socket."); + } + if (serverMap[socket] != nullptr) { + server = serverMap[socket]; + if (server->server_) { + server->server_->Close(); + serverMap.erase(socket); + isOK = true; + } + } else { + HILOGE("invalid socket."); + } + return isOK ? 0 : BT_ERR_INVALID_PARAM; +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/cj/socket/src/bluetooth_spp_utils.cpp b/frameworks/cj/socket/src/bluetooth_spp_utils.cpp new file mode 100644 index 00000000..79d2b985 --- /dev/null +++ b/frameworks/cj/socket/src/bluetooth_spp_utils.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bluetooth_spp_utils.h" + +namespace OHOS { +namespace Bluetooth { +char* MallocCString(const std::string& origin) +{ + if (origin.empty()) { + return nullptr; + } + auto len = origin.length() + 1; + char* res = static_cast(malloc(sizeof(char) * len)); + if (res == nullptr) { + return nullptr; + } + return std::char_traits::copy(res, origin.c_str(), len); +} +} // namespace Bluetooth +} // namespace OHOS \ No newline at end of file -- Gitee