diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c6f9a448eb7fb8cad82464e2037ee1b0992bd590 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode/settings.json diff --git a/frameworks/inner/src/bluetooth_socket.cpp b/frameworks/inner/src/bluetooth_socket.cpp index 2c6b8a82f2de7b30180fea46f6f1b5bddb9850cb..7b510076c41bed77e85241c4556e0a6fbd2b6c13 100644 --- a/frameworks/inner/src/bluetooth_socket.cpp +++ b/frameworks/inner/src/bluetooth_socket.cpp @@ -555,6 +555,12 @@ bool ClientSocket::IsAllowSocketConnect(int socketType) return isAllowed; } +BtSocketType ClientSocket::GetType() +{ + HILOGD("enter"); + return pimpl->type_; +} + struct ServerSocket::impl { impl(const std::string &name, UUID uuid, BtSocketType type, bool encrypt, int psm); ~impl() diff --git a/frameworks/inner/src/bluetooth_socket_inputstream.cpp b/frameworks/inner/src/bluetooth_socket_inputstream.cpp index 093d07fa81474de35117d0f15340ceffefa387b6..f159849fbf702dd120e202b11c53f8854d81ec4c 100644 --- a/frameworks/inner/src/bluetooth_socket_inputstream.cpp +++ b/frameworks/inner/src/bluetooth_socket_inputstream.cpp @@ -22,6 +22,7 @@ #include "bluetooth_socket_inputstream.h" #include #include "sys/socket.h" +#include namespace OHOS { namespace Bluetooth { @@ -31,6 +32,20 @@ InputStream::InputStream(int socketFd) : socketFd_(socketFd) InputStream::~InputStream() {} +int InputStream::PollWait() +{ + struct pollfd fd[1]; + int availableBytes = 0; + fd[0].fd = socketFd_; + fd[0].events = POLLIN; + if ((poll(fd, 1, -1) > 0) && (fd[0].revents & POLLIN)) { + if (ioctl(socketFd_, FIONREAD, &availableBytes) == 0) { + return availableBytes; + } + } + return -1; +} + ssize_t InputStream::Read(uint8_t *buf, size_t length) { if (socketFd_ == -1) { diff --git a/frameworks/js/napi/include/napi_bluetooth_spp_client.h b/frameworks/js/napi/include/napi_bluetooth_spp_client.h index 34d25d0b940c2f03a135a63cd47b12c19dc2bae2..8be5f7f9ccfd9d8b4190d8c3fb5a7d72103e30e5 100644 --- a/frameworks/js/napi/include/napi_bluetooth_spp_client.h +++ b/frameworks/js/napi/include/napi_bluetooth_spp_client.h @@ -31,8 +31,36 @@ struct SppConnectCallbackInfo : public AsyncCallbackInfo { }; struct SppCallbackBuffer { + SppCallbackBuffer(int length):len_(length) { + data_ = new char[length]; + } + + SppCallbackBuffer():len_(1024) { + data_ = new char[1024]; + } + + SppCallbackBuffer(const SppCallbackBuffer& other) { + len_ = other.len_; + data_ = new char[len_]; + memcpy_s(data_, len_, other.data_, other.len_); + } + + SppCallbackBuffer& operator=(const SppCallbackBuffer& other) { + if (this == &other) { + return *this; + } + delete[] data_; + len_ = other.len_; + data_ = new char[len_]; + memcpy_s(data_, len_, other.data_, other.len_); + return *this; + } + + ~SppCallbackBuffer() { + delete[] data_; + } ssize_t len_; - char data_[1024]; + char* data_; }; struct BufferCallbackInfo : public BluetoothCallbackInfo { @@ -66,6 +94,9 @@ struct NapiSppClient { static napi_value SppWrite(napi_env env, napi_callback_info info); static napi_value On(napi_env env, napi_callback_info info); static napi_value Off(napi_env env, napi_callback_info info); + static void ProcessRfcommRead(std::shared_ptr client, int id); + static void ProcessL2capRead(std::shared_ptr client, int id); + static void ProcessReceivedData(std::shared_ptr client, uint8* buf, int length, int ret); static void SppRead(int id); static napi_value SppWriteAsync(napi_env env, napi_callback_info info); static napi_value SppReadAsync(napi_env env, napi_callback_info info); diff --git a/frameworks/js/napi/src/socket/napi_bluetooth_spp_client.cpp b/frameworks/js/napi/src/socket/napi_bluetooth_spp_client.cpp index 15cd9b0f2f101b2970350161a4b624af92540abe..69c4cd825816141b4ec42773e0727423ae4c7188 100644 --- a/frameworks/js/napi/src/socket/napi_bluetooth_spp_client.cpp +++ b/frameworks/js/napi/src/socket/napi_bluetooth_spp_client.cpp @@ -39,7 +39,8 @@ namespace OHOS { namespace Bluetooth { std::map> NapiSppClient::clientMap; int NapiSppClient::count = 0; -const int SOCKET_BUFFER_SIZE = 1024; +const int RFCOMM_SOCKET_BUFFER_SIZE = 1024; +const int L2CAP_SOCKET_BUFFER_SIZE = 65535; static napi_status CheckSppConnectParams( napi_env env, napi_callback_info info, std::string &deviceId, SppConnectCallbackInfo *callbackInfo) @@ -357,7 +358,7 @@ static void NapiThreadSafeFuncCallJs(napi_env, napi_value jsCallback, void *cont HILOGE("callbackInfo->PopData return nullptr"); return; } - if (buffer->len_ < 0 || buffer->len_ > SOCKET_BUFFER_SIZE) { + if (buffer->len_ < 0 || buffer->len_ > L2CAP_SOCKET_BUFFER_SIZE) { HILOGE("buffer->len_ invalid"); return; } @@ -482,18 +483,36 @@ napi_value NapiSppClient::Off(napi_env env, napi_callback_info info) return NapiGetUndefinedRet(env); } -void NapiSppClient::SppRead(int id) +void NapiSppClient::ProcessRfcommRead(std::shared_ptr client, 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]; + uint8_t buf[RFCOMM_SOCKET_BUFFER_SIZE]; + while (true) { + HILOGI("thread start."); + (void)memset_s(buf, sizeof(buf), 0, sizeof(buf)); + HILOGI("inputStream.Read start"); + int ret = inputStream->Read(buf, sizeof(buf)); + HILOGI("inputStream.Read end"); + if (ret <= 0) { + HILOGI("inputStream.Read failed, ret = %{public}d", ret); + return; + } else { + ProcessReceivedData(client, buf, RFCOMM_SOCKET_BUFFER_SIZE, ret); + } + } +} +void NapiSppClient::ProcessL2capRead(std::shared_ptr client, int id) +{ + std::shared_ptr inputStream = client->client_->GetInputStream(); while (true) { HILOGI("thread start."); + int length = InputStream->PollWait(); + if (length <= 0) { + continue; + } + + uint8_t buf[length]; (void)memset_s(buf, sizeof(buf), 0, sizeof(buf)); HILOGI("inputStream.Read start"); int ret = inputStream->Read(buf, sizeof(buf)); @@ -502,47 +521,67 @@ void NapiSppClient::SppRead(int id) HILOGI("inputStream.Read failed, ret = %{public}d", ret); return; } else { - HILOGI("callback read data to jshap begin"); - 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; - } + ProcessReceivedData(client, buf, length, ret); + } + } +} - std::shared_ptr buffer = std::make_shared(); - buffer->len_ = ret; - if (memcpy_s(buffer->data_, sizeof(buffer->data_), buf, ret) != EOK) { - HILOGE("memcpy_s failed!"); - return; - } - callbackInfo->PushData(buffer); +void NapiSppClient::ProcessReceivedData(std::shared_ptr client, uint8* buf, int length, int ret) +{ + HILOGI("callback read data to jshap begin"); + 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; + } - auto status = napi_acquire_threadsafe_function(client->sppReadThreadSafeFunc_); - if (status != napi_ok) { - HILOGE("napi_acquire_threadsafe_function failed, status: %{public}d", status); - return; - } + std::shared_ptr buffer = std::make_shared(length); + buffer->len_ = ret; + if (memcpy_s(buffer->data_, buffer->len_, buf, ret) != EOK) { + HILOGE("memcpy_s failed!"); + return; + } + callbackInfo->PushData(buffer); - status = napi_call_threadsafe_function( - client->sppReadThreadSafeFunc_, static_cast(callbackInfo.get()), napi_tsfn_blocking); - if (status != napi_ok) { - HILOGE("napi_call_threadsafe_function failed, status: %{public}d", status); - return; - } + auto status = napi_acquire_threadsafe_function(client->sppReadThreadSafeFunc_); + if (status != napi_ok) { + HILOGE("napi_acquire_threadsafe_function failed, status: %{public}d", status); + return; + } - status = napi_release_threadsafe_function(client->sppReadThreadSafeFunc_, napi_tsfn_release); - if (status != napi_ok) { - HILOGE("napi_release_threadsafe_function failed, status: %{public}d", status); - return; - } - } + status = napi_call_threadsafe_function( + client->sppReadThreadSafeFunc_, static_cast(callbackInfo.get()), napi_tsfn_blocking); + if (status != napi_ok) { + HILOGE("napi_call_threadsafe_function failed, status: %{public}d", status); + return; + } + + status = napi_release_threadsafe_function(client->sppReadThreadSafeFunc_, napi_tsfn_release); + if (status != napi_ok) { + HILOGE("napi_release_threadsafe_function failed, status: %{public}d", status); + return; + } +} + + + +void NapiSppClient::SppRead(int id) +{ + auto client = clientMap[id]; + if (client == nullptr || !client->sppReadFlag || client->callbackInfos_[REGISTER_SPP_READ_TYPE] == nullptr) { + HILOGE("thread start failed."); + return; + } + if (client->client_->GetType() == TYPE_RFCOMM) { + ProcessRfcommRead(client, id); + } else { + ProcessL2capRead(client, id); } - return; } static int WriteDataLoop(std::shared_ptr outputStream, uint8_t* totalBuf, size_t totalSize) @@ -632,10 +671,23 @@ napi_value NapiSppClient::SppReadAsync(napi_env env, napi_callback_info info) NAPI_BT_ASSERT_RETURN_UNDEF(env, !client->sppReadFlag, BT_ERR_INVALID_PARAM); client->sppReadFlag = true; std::shared_ptr inputStream = client->client_->GetInputStream(); - auto func = [inputStream, id] { + BtSocketType type = client->client_->GetType(); + auto func = [inputStream, id, type] { int err = 0; SppCallbackBuffer buffer; - err = ReadData(inputStream, SOCKET_BUFFER_SIZE, buffer); + if(type == TYPE_RFCOMM) { + buffer = SppCallbackBuffer(RFCOMM_SOCKET_BUFFER_SIZE); + err = ReadData(inputStream, RFCOMM_SOCKET_BUFFER_SIZE, buffer); + } else { + int length = -1; + while (length < 0) { + length = inputStream->PollWait(); + } + if(length > 0) { + buffer = SppCallbackBuffer(length); + err = ReadData(inputStream, length, buffer); + } + } auto object = std::make_shared(buffer); auto client = clientMap[id]; if (client == nullptr) { diff --git a/interfaces/inner_api/include/bluetooth_socket.h b/interfaces/inner_api/include/bluetooth_socket.h index d44bbc33b17fde7b852e63793109ddabab7480ea..ec4f1c56237e72d3d8221499d1ffdab220baedae 100644 --- a/interfaces/inner_api/include/bluetooth_socket.h +++ b/interfaces/inner_api/include/bluetooth_socket.h @@ -264,6 +264,15 @@ public: */ bool IsAllowSocketConnect(int socketType); + /** + * @brief Get the connection type of the socket type + * + * @param socketType socketType. + * @return return BtSocketType socket type + * @since 20 + */ + BtSocketType GetType(); + private: ClientSocket() = delete; BLUETOOTH_DECLARE_IMPL(); diff --git a/interfaces/inner_api/include/bluetooth_socket_inputstream.h b/interfaces/inner_api/include/bluetooth_socket_inputstream.h index d2039a80d370462719aeab62050cf8b7e5ec31fc..215db9faf26a40e3e24d450acc99ff32f585922d 100644 --- a/interfaces/inner_api/include/bluetooth_socket_inputstream.h +++ b/interfaces/inner_api/include/bluetooth_socket_inputstream.h @@ -36,6 +36,7 @@ #include "bluetooth_def.h" #include "bluetooth_types.h" +#include namespace OHOS { namespace Bluetooth { @@ -73,6 +74,15 @@ public: */ ssize_t Read(uint8_t *buf, size_t length); + /** + * @brief poll() for sockets: efficiently manage socket connections for data reception. + * + * @return Returns the length greater than 0 as read the actual length. + * Returns -1 if the operation fails. + * @since 20 + */ + int PollWait(); + private: int socketFd_; InputStream() = delete;