| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <lib/driver2/runtime_connector_impl.h> |
| #include <lib/fidl/llcpp/string_view.h> |
| |
| namespace fdf { |
| using namespace fuchsia_driver_framework; |
| } // namespace fdf |
| |
| namespace { |
| |
| class RuntimeProtocolIterator : public fidl::WireServer<fdf::RuntimeProtocolIterator> { |
| public: |
| static constexpr size_t kProtocolsBufferSize = 512; |
| |
| explicit RuntimeProtocolIterator(std::unique_ptr<fidl::Arena<kProtocolsBufferSize>> arena, |
| std::vector<fidl::StringView> list) |
| : arena_(std::move(arena)), list_(std::move(list)) {} |
| |
| void GetNext(GetNextRequestView request, GetNextCompleter::Sync& completer) { |
| constexpr size_t kMaxEntries = fdf::wire::kMaxProtocolsPerBatch; |
| auto result = |
| cpp20::span(list_.begin() + offset_, std::min(kMaxEntries, list_.size() - offset_)); |
| offset_ += result.size(); |
| |
| completer.Reply(fidl::VectorView<fidl::StringView>::FromExternal(result.data(), result.size())); |
| } |
| |
| private: |
| std::unique_ptr<fidl::Arena<kProtocolsBufferSize>> arena_; |
| size_t offset_ = 0; |
| std::vector<fidl::StringView> list_; |
| }; |
| |
| } // namespace |
| |
| namespace driver { |
| |
| void RuntimeConnectorImpl::RegisterProtocol(const std::string protocol_name, |
| RegisterProtocolHandler handler) { |
| protocol_to_handler_[protocol_name] = std::move(handler); |
| } |
| |
| void RuntimeConnectorImpl::ListProtocols(ListProtocolsRequestView request, |
| ListProtocolsCompleter::Sync& completer) { |
| auto arena = std::make_unique<fidl::Arena<RuntimeProtocolIterator::kProtocolsBufferSize>>(); |
| std::vector<fidl::StringView> protocols; |
| |
| for (auto& iter : protocol_to_handler_) { |
| fidl::StringView sv(*arena, iter.first); |
| protocols.push_back(std::move(sv)); |
| } |
| |
| auto iterator = std::make_unique<RuntimeProtocolIterator>(std::move(arena), std::move(protocols)); |
| fidl::BindServer(dispatcher_, std::move(request->iterator), std::move(iterator)); |
| } |
| |
| void RuntimeConnectorImpl::Connect(ConnectRequestView request, ConnectCompleter::Sync& completer) { |
| fdf::Channel channel(request->runtime_protocol.handle); |
| auto protocol_name = std::string(request->protocol_name.data(), request->protocol_name.size()); |
| auto it = protocol_to_handler_.find(protocol_name); |
| if (it == protocol_to_handler_.end()) { |
| completer.ReplyError(ZX_ERR_NOT_SUPPORTED); |
| return; |
| } |
| auto& handler = it->second; |
| zx_status_t status = handler(std::move(channel)); |
| if (status != ZX_OK) { |
| completer.ReplyError(status); |
| return; |
| } |
| completer.ReplySuccess(); |
| } |
| |
| } // namespace driver |