-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add default Bluetooth HAL implementation
Also added initial target-side functional test. Test: bluetooth_hidl_hal_test Bug: 31972505 Change-Id: I1f574a5b2b53d7fbf65dbb4e1aaa5f8b6c5a9448
- Loading branch information
Andre Eisenbach
committed
Dec 29, 2016
1 parent
73f99f6
commit 89ba528
Showing
15 changed files
with
2,102 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// Copyright (C) 2016 The Android Open Source Project | ||
// | ||
// 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. | ||
|
||
cc_library_shared { | ||
name: "[email protected]", | ||
relative_install_path: "hw", | ||
srcs: [ | ||
"async_fd_watcher.cc", | ||
"bluetooth_hci.cc", | ||
"vendor_interface.cc", | ||
], | ||
shared_libs: [ | ||
"liblog", | ||
"libcutils", | ||
"libhardware", | ||
"libhwbinder", | ||
"libbase", | ||
"libcutils", | ||
"libutils", | ||
"libhidlbase", | ||
"libhidltransport", | ||
"[email protected]", | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# | ||
# Copyright (C) 2016 The Android Open Source Project | ||
# | ||
# 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. | ||
|
||
LOCAL_PATH:= $(call my-dir) | ||
|
||
include $(CLEAR_VARS) | ||
LOCAL_MODULE_RELATIVE_PATH := hw | ||
LOCAL_MODULE := [email protected] | ||
LOCAL_INIT_RC := [email protected] | ||
LOCAL_SRC_FILES := \ | ||
service.cpp | ||
|
||
LOCAL_SHARED_LIBRARIES := \ | ||
liblog \ | ||
libcutils \ | ||
libdl \ | ||
libbase \ | ||
libutils \ | ||
libhardware_legacy \ | ||
libhardware \ | ||
|
||
LOCAL_SHARED_LIBRARIES += \ | ||
libhwbinder \ | ||
libhidlbase \ | ||
libhidltransport \ | ||
[email protected] \ | ||
|
||
include $(BUILD_EXECUTABLE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
service bluetooth-1-0 /system/bin/hw/[email protected] | ||
class hal | ||
user bluetooth | ||
group bluetooth |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// | ||
// Copyright 2016 The Android Open Source Project | ||
// | ||
// 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 "async_fd_watcher.h" | ||
|
||
#include <algorithm> | ||
#include <atomic> | ||
#include <condition_variable> | ||
#include <mutex> | ||
#include <thread> | ||
#include <vector> | ||
#include "fcntl.h" | ||
#include "sys/select.h" | ||
#include "unistd.h" | ||
|
||
namespace android { | ||
namespace hardware { | ||
namespace bluetooth { | ||
namespace V1_0 { | ||
namespace implementation { | ||
|
||
int AsyncFdWatcher::WatchFdForNonBlockingReads( | ||
int file_descriptor, const ReadCallback& on_read_fd_ready_callback) { | ||
// Add file descriptor and callback | ||
{ | ||
std::unique_lock<std::mutex> guard(internal_mutex_); | ||
read_fd_ = file_descriptor; | ||
cb_ = on_read_fd_ready_callback; | ||
} | ||
|
||
// Start the thread if not started yet | ||
int started = tryStartThread(); | ||
if (started != 0) { | ||
return started; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
void AsyncFdWatcher::StopWatchingFileDescriptor() { stopThread(); } | ||
|
||
AsyncFdWatcher::~AsyncFdWatcher() {} | ||
|
||
// Make sure to call this with at least one file descriptor ready to be | ||
// watched upon or the thread routine will return immediately | ||
int AsyncFdWatcher::tryStartThread() { | ||
if (std::atomic_exchange(&running_, true)) return 0; | ||
|
||
// Set up the communication channel | ||
int pipe_fds[2]; | ||
if (pipe2(pipe_fds, O_NONBLOCK)) return -1; | ||
|
||
notification_listen_fd_ = pipe_fds[0]; | ||
notification_write_fd_ = pipe_fds[1]; | ||
|
||
thread_ = std::thread([this]() { ThreadRoutine(); }); | ||
if (!thread_.joinable()) return -1; | ||
|
||
return 0; | ||
} | ||
|
||
int AsyncFdWatcher::stopThread() { | ||
if (!std::atomic_exchange(&running_, false)) return 0; | ||
|
||
notifyThread(); | ||
if (std::this_thread::get_id() != thread_.get_id()) { | ||
thread_.join(); | ||
} | ||
|
||
{ | ||
std::unique_lock<std::mutex> guard(internal_mutex_); | ||
cb_ = nullptr; | ||
read_fd_ = -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int AsyncFdWatcher::notifyThread() { | ||
uint8_t buffer[] = {0}; | ||
if (TEMP_FAILURE_RETRY(write(notification_write_fd_, &buffer, 1)) < 0) { | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
|
||
void AsyncFdWatcher::ThreadRoutine() { | ||
while (running_) { | ||
fd_set read_fds; | ||
FD_ZERO(&read_fds); | ||
FD_SET(notification_listen_fd_, &read_fds); | ||
FD_SET(read_fd_, &read_fds); | ||
|
||
// Wait until there is data available to read on some FD | ||
int nfds = std::max(notification_listen_fd_, read_fd_); | ||
int retval = select(nfds + 1, &read_fds, NULL, NULL, NULL); | ||
if (retval <= 0) continue; // there was some error or a timeout | ||
|
||
// Read data from the notification FD | ||
if (FD_ISSET(notification_listen_fd_, &read_fds)) { | ||
char buffer[] = {0}; | ||
TEMP_FAILURE_RETRY(read(notification_listen_fd_, buffer, 1)); | ||
} | ||
|
||
// Make sure we're still running | ||
if (!running_) break; | ||
|
||
// Invoke the data ready callback if appropriate | ||
if (FD_ISSET(read_fd_, &read_fds)) { | ||
std::unique_lock<std::mutex> guard(internal_mutex_); | ||
if (cb_) cb_(read_fd_); | ||
} | ||
} | ||
} | ||
|
||
} // namespace implementation | ||
} // namespace V1_0 | ||
} // namespace bluetooth | ||
} // namespace hardware | ||
} // namespace android |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// | ||
// Copyright 2016 The Android Open Source Project | ||
// | ||
// 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. | ||
// | ||
|
||
#pragma once | ||
|
||
#include <mutex> | ||
#include <thread> | ||
|
||
namespace android { | ||
namespace hardware { | ||
namespace bluetooth { | ||
namespace V1_0 { | ||
namespace implementation { | ||
|
||
using ReadCallback = std::function<void(int)>; | ||
|
||
class AsyncFdWatcher { | ||
public: | ||
AsyncFdWatcher() = default; | ||
~AsyncFdWatcher(); | ||
|
||
int WatchFdForNonBlockingReads(int file_descriptor, | ||
const ReadCallback& on_read_fd_ready_callback); | ||
void StopWatchingFileDescriptor(); | ||
|
||
private: | ||
AsyncFdWatcher(const AsyncFdWatcher&) = delete; | ||
AsyncFdWatcher& operator=(const AsyncFdWatcher&) = delete; | ||
|
||
int tryStartThread(); | ||
int stopThread(); | ||
int notifyThread(); | ||
void ThreadRoutine(); | ||
|
||
std::atomic_bool running_{false}; | ||
std::thread thread_; | ||
std::mutex internal_mutex_; | ||
|
||
int read_fd_; | ||
int notification_listen_fd_; | ||
int notification_write_fd_; | ||
ReadCallback cb_; | ||
}; | ||
|
||
|
||
} // namespace implementation | ||
} // namespace V1_0 | ||
} // namespace bluetooth | ||
} // namespace hardware | ||
} // namespace android |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// | ||
// Copyright 2016 The Android Open Source Project | ||
// | ||
// 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. | ||
// | ||
|
||
#define LOG_TAG "[email protected]" | ||
#include <utils/Log.h> | ||
|
||
#include "bluetooth_hci.h" | ||
#include "vendor_interface.h" | ||
|
||
namespace android { | ||
namespace hardware { | ||
namespace bluetooth { | ||
namespace V1_0 { | ||
namespace implementation { | ||
|
||
static const uint8_t HCI_DATA_TYPE_COMMAND = 1; | ||
static const uint8_t HCI_DATA_TYPE_ACL = 2; | ||
static const uint8_t HCI_DATA_TYPE_SCO = 3; | ||
|
||
Return<Status> BluetoothHci::initialize( | ||
const ::android::sp<IBluetoothHciCallbacks>& cb) { | ||
ALOGW("BluetoothHci::initialize()"); | ||
event_cb_ = cb; | ||
|
||
bool rc = VendorInterface::Initialize( | ||
[this](HciPacketType type, const hidl_vec<uint8_t>& packet) { | ||
switch (type) { | ||
case HCI_PACKET_TYPE_EVENT: | ||
event_cb_->hciEventReceived(packet); | ||
break; | ||
case HCI_PACKET_TYPE_ACL_DATA: | ||
event_cb_->aclDataReceived(packet); | ||
break; | ||
case HCI_PACKET_TYPE_SCO_DATA: | ||
event_cb_->scoDataReceived(packet); | ||
break; | ||
default: | ||
ALOGE("%s Unexpected event type %d", __func__, type); | ||
break; | ||
} | ||
}); | ||
if (!rc) return Status::INITIALIZATION_ERROR; | ||
|
||
return Status::SUCCESS; | ||
} | ||
|
||
Return<void> BluetoothHci::close() { | ||
ALOGW("BluetoothHci::close()"); | ||
VendorInterface::Shutdown(); | ||
return Void(); | ||
} | ||
|
||
Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& command) { | ||
sendDataToController(HCI_DATA_TYPE_COMMAND, command); | ||
return Void(); | ||
} | ||
|
||
Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& data) { | ||
sendDataToController(HCI_DATA_TYPE_ACL, data); | ||
return Void(); | ||
} | ||
|
||
Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& data) { | ||
sendDataToController(HCI_DATA_TYPE_SCO, data); | ||
return Void(); | ||
} | ||
|
||
void BluetoothHci::sendDataToController(const uint8_t type, | ||
const hidl_vec<uint8_t>& data) { | ||
VendorInterface::get()->Send(&type, 1); | ||
VendorInterface::get()->Send(data.data(), data.size()); | ||
} | ||
|
||
IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) { | ||
return new BluetoothHci(); | ||
} | ||
|
||
} // namespace implementation | ||
} // namespace V1_0 | ||
} // namespace bluetooth | ||
} // namespace hardware | ||
} // namespace android |
Oops, something went wrong.