You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.5 KiB
183 lines
5.5 KiB
// |
|
// Copyright 2017 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 "android.hardware.bluetooth@1.0.sim" |
|
|
|
#include "bluetooth_hci.h" |
|
|
|
#include <base/logging.h> |
|
#include <string.h> |
|
#include <utils/Log.h> |
|
|
|
#include "hci_internals.h" |
|
|
|
namespace android { |
|
namespace hardware { |
|
namespace bluetooth { |
|
namespace V1_0 { |
|
namespace sim { |
|
|
|
using android::hardware::hidl_vec; |
|
using test_vendor_lib::AsyncManager; |
|
using test_vendor_lib::AsyncTaskId; |
|
using test_vendor_lib::CommandPacket; |
|
using test_vendor_lib::DualModeController; |
|
using test_vendor_lib::EventPacket; |
|
using test_vendor_lib::TaskCallback; |
|
using test_vendor_lib::TestChannelTransport; |
|
|
|
class BluetoothDeathRecipient : public hidl_death_recipient { |
|
public: |
|
BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {} |
|
|
|
virtual void serviceDied( |
|
uint64_t /* cookie */, |
|
const wp<::android::hidl::base::V1_0::IBase>& /* who */) { |
|
ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died"); |
|
has_died_ = true; |
|
mHci->close(); |
|
} |
|
sp<IBluetoothHci> mHci; |
|
bool getHasDied() const { return has_died_; } |
|
void setHasDied(bool has_died) { has_died_ = has_died; } |
|
|
|
private: |
|
bool has_died_; |
|
}; |
|
|
|
BluetoothHci::BluetoothHci() |
|
: death_recipient_(new BluetoothDeathRecipient(this)) {} |
|
|
|
Return<void> BluetoothHci::initialize(const sp<IBluetoothHciCallbacks>& cb) { |
|
ALOGI("%s", __func__); |
|
|
|
if (cb == nullptr) { |
|
ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)"); |
|
return Void(); |
|
} |
|
|
|
death_recipient_->setHasDied(false); |
|
cb->linkToDeath(death_recipient_, 0); |
|
|
|
test_channel_transport_.RegisterCommandHandler( |
|
[this](const std::string& name, const std::vector<std::string>& args) { |
|
async_manager_.ExecAsync( |
|
std::chrono::milliseconds(0), [this, name, args]() { |
|
controller_.HandleTestChannelCommand(name, args); |
|
}); |
|
}); |
|
|
|
controller_.RegisterEventChannel([cb](std::unique_ptr<EventPacket> event) { |
|
size_t header_bytes = event->GetHeaderSize(); |
|
size_t payload_bytes = event->GetPayloadSize(); |
|
hidl_vec<uint8_t> hci_event; |
|
hci_event.resize(header_bytes + payload_bytes); |
|
memcpy(hci_event.data(), event->GetHeader().data(), header_bytes); |
|
memcpy(hci_event.data() + header_bytes, event->GetPayload().data(), |
|
payload_bytes); |
|
|
|
cb->hciEventReceived(hci_event); |
|
}); |
|
|
|
/* RegisterAcl and RegisterSco |
|
cb->aclDataReceived(hci_packet); |
|
cb->scoDataReceived(hci_packet); |
|
*/ |
|
|
|
controller_.RegisterTaskScheduler( |
|
[this](std::chrono::milliseconds delay, const TaskCallback& task) { |
|
return async_manager_.ExecAsync(delay, task); |
|
}); |
|
|
|
controller_.RegisterPeriodicTaskScheduler( |
|
[this](std::chrono::milliseconds delay, std::chrono::milliseconds period, |
|
const TaskCallback& task) { |
|
return async_manager_.ExecAsyncPeriodically(delay, period, task); |
|
}); |
|
|
|
controller_.RegisterTaskCancel( |
|
[this](AsyncTaskId task) { async_manager_.CancelAsyncTask(task); }); |
|
|
|
SetUpTestChannel(6111); |
|
|
|
unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) { |
|
if (death_recipient->getHasDied()) |
|
ALOGI("Skipping unlink call, service died."); |
|
else |
|
cb->unlinkToDeath(death_recipient); |
|
}; |
|
|
|
cb->initializationComplete(Status::SUCCESS); |
|
return Void(); |
|
} |
|
|
|
Return<void> BluetoothHci::close() { |
|
ALOGI("%s", __func__); |
|
return Void(); |
|
} |
|
|
|
Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& packet) { |
|
async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { |
|
uint16_t opcode = packet[0] | (packet[1] << 8); |
|
std::unique_ptr<CommandPacket> command = |
|
std::unique_ptr<CommandPacket>(new CommandPacket(opcode)); |
|
for (size_t i = 3; i < packet.size(); i++) |
|
command->AddPayloadOctets1(packet[i]); |
|
|
|
controller_.HandleCommand(std::move(command)); |
|
}); |
|
return Void(); |
|
} |
|
|
|
Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& /* packet */) { |
|
CHECK(false) << __func__ << " not yet implemented"; |
|
return Void(); |
|
} |
|
|
|
Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& /* packet */) { |
|
CHECK(false) << __func__ << " not yet implemented"; |
|
return Void(); |
|
} |
|
|
|
void BluetoothHci::SetUpTestChannel(int port) { |
|
int socket_fd = test_channel_transport_.SetUp(port); |
|
|
|
if (socket_fd == -1) { |
|
ALOGE("Test channel SetUp(%d) failed.", port); |
|
return; |
|
} |
|
|
|
ALOGI("Test channel SetUp() successful"); |
|
async_manager_.WatchFdForNonBlockingReads(socket_fd, [this](int socket_fd) { |
|
int conn_fd = test_channel_transport_.Accept(socket_fd); |
|
if (conn_fd < 0) { |
|
ALOGE("Error watching test channel fd."); |
|
return; |
|
} |
|
ALOGI("Test channel connection accepted."); |
|
async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) { |
|
test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() { |
|
async_manager_.StopWatchingFileDescriptor(conn_fd); |
|
}); |
|
}); |
|
}); |
|
} |
|
|
|
} // namespace gce |
|
} // namespace V1_0 |
|
} // namespace bluetooth |
|
} // namespace hardware |
|
} // namespace android
|
|
|