1 // Copyright 2017 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <ddk/protocol/platform/proxy.h> 8 #include <ddktl/device.h> 9 #include <fbl/intrusive_wavl_tree.h> 10 #include <fbl/ref_counted.h> 11 #include <fbl/ref_ptr.h> 12 #include <fbl/unique_ptr.h> 13 #include <fbl/vector.h> 14 #include <lib/zx/channel.h> 15 16 #include "platform-proxy-device.h" 17 #include "proxy-protocol.h" 18 19 namespace platform_bus { 20 21 class ProxyDevice; 22 23 class PlatformProxy; 24 using PlatformProxyType = ddk::Device<PlatformProxy>; 25 26 // This is the main class for the proxy side platform bus driver. 27 // It handles RPC communication with the main platform bus driver in the root devhost. 28 // It also manages a collection of protocol clients for vendor or SOC-specific protocols. 29 // In the case where these protocols exist, this class loads the protocol client drivers 30 // before starting the platform device driver. 31 class PlatformProxy : public PlatformProxyType, public fbl::RefCounted<PlatformProxy> { 32 public: 33 static zx_status_t Create(zx_device_t* parent, zx_handle_t rpc_channel); 34 35 // Device protocol implementation. 36 void DdkRelease(); 37 38 zx_status_t Rpc(uint32_t device_id, const platform_proxy_req_t* req, size_t req_length, 39 platform_proxy_rsp_t* resp, size_t resp_length, const zx_handle_t* in_handles, 40 size_t in_handle_count, zx_handle_t* out_handles, size_t out_handle_count, 41 size_t* out_actual); 42 Rpc(uint32_t device_id,const platform_proxy_req_t * req,size_t req_length,platform_proxy_rsp_t * resp,size_t resp_length)43 inline zx_status_t Rpc(uint32_t device_id, const platform_proxy_req_t* req, size_t req_length, 44 platform_proxy_rsp_t* resp, size_t resp_length) { 45 return Rpc(device_id, req, req_length, resp, resp_length, nullptr, 0, nullptr, 0, nullptr); 46 } 47 48 zx_status_t GetProtocol(uint32_t proto_id, void* out); 49 zx_status_t RegisterProtocol(uint32_t proto_id, const void* protocol); 50 void UnregisterProtocol(uint32_t proto_id); 51 zx_status_t Proxy( 52 const void* req_buffer, size_t req_size, const zx_handle_t* req_handle_list, 53 size_t req_handle_count, void* out_resp_buffer, size_t resp_size, size_t* out_resp_actual, 54 zx_handle_t* out_resp_handle_list, size_t resp_handle_count, 55 size_t* out_resp_handle_actual); 56 57 private: 58 // This class is a wrapper for a protocol added via platform_proxy_register_protocol(). 59 // It also is the element type for the protocols_ WAVL tree. 60 class PlatformProtocol : public fbl::WAVLTreeContainable<fbl::unique_ptr<PlatformProtocol>> { 61 public: PlatformProtocol(uint32_t proto_id,const ddk::AnyProtocol * protocol)62 PlatformProtocol(uint32_t proto_id, const ddk::AnyProtocol* protocol) 63 : proto_id_(proto_id), protocol_(*protocol) {} 64 GetKey()65 inline uint32_t GetKey() const { return proto_id_; } GetProtocol(void * out)66 inline void GetProtocol(void* out) const { memcpy(out, &protocol_, sizeof(protocol_)); } 67 68 private: 69 const uint32_t proto_id_; 70 ddk::AnyProtocol protocol_; 71 }; 72 73 friend class fbl::RefPtr<PlatformProxy>; 74 friend class fbl::internal::MakeRefCountedHelper<PlatformProxy>; 75 PlatformProxy(zx_device_t * parent,zx_handle_t rpc_channel)76 explicit PlatformProxy(zx_device_t* parent, zx_handle_t rpc_channel) 77 : PlatformProxyType(parent), rpc_channel_(rpc_channel) {} 78 79 DISALLOW_COPY_ASSIGN_AND_MOVE(PlatformProxy); 80 81 zx_status_t Init(zx_device_t* parent); 82 83 const zx::channel rpc_channel_; 84 fbl::WAVLTree<uint32_t, fbl::unique_ptr<PlatformProtocol>> protocols_; 85 uint32_t protocol_count_; 86 }; 87 88 } // namespace platform_bus 89 90 __BEGIN_CDECLS 91 zx_status_t platform_proxy_create(void* ctx, zx_device_t* parent, const char* name, 92 const char* args, zx_handle_t rpc_channel); 93 __END_CDECLS 94