1 // Copyright 2016 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 "lock.h" 8 #include "device-internal.h" 9 #include "../shared/async-loop-owned-rpc-handler.h" 10 11 #include <ddk/binding.h> 12 #include <ddk/device.h> 13 #include <ddk/driver.h> 14 15 #include <fbl/intrusive_double_list.h> 16 #include <fbl/ref_counted.h> 17 #include <fbl/ref_ptr.h> 18 #include <fbl/string.h> 19 #include <fbl/unique_ptr.h> 20 #include <lib/async/cpp/wait.h> 21 #include <lib/zx/channel.h> 22 #include <zircon/compiler.h> 23 #include <zircon/fidl.h> 24 #include <zircon/thread_annotations.h> 25 #include <zircon/types.h> 26 27 #include <threads.h> 28 #include <stdint.h> 29 30 namespace devmgr { 31 32 struct CreationContext { 33 fbl::RefPtr<zx_device_t> parent; 34 fbl::RefPtr<zx_device_t> child; 35 zx::unowned_channel rpc; 36 }; 37 38 void devhost_set_creation_context(CreationContext* ctx); 39 40 } // namespace devmgr 41 42 // Nothing outside of devmgr/{devmgr,devhost,rpc-device}.c 43 // should be calling devhost_*() APIs, as this could 44 // violate the internal locking design. 45 46 // Safe external APIs are in device.h and device_internal.h 47 48 // Note that this must be a struct to match the public opaque declaration. 49 struct zx_driver : fbl::DoublyLinkedListable<fbl::RefPtr<zx_driver>>, 50 fbl::RefCounted<zx_driver> { 51 static zx_status_t Create(fbl::RefPtr<zx_driver>* out_driver); 52 namezx_driver53 const char* name() const { 54 return name_; 55 } 56 driver_reczx_driver57 zx_driver_rec_t* driver_rec() const { 58 return driver_rec_; 59 } 60 statuszx_driver61 zx_status_t status() const { 62 return status_; 63 } 64 libnamezx_driver65 const fbl::String& libname() const { 66 return libname_; 67 } 68 set_namezx_driver69 void set_name(const char* name) { 70 name_ = name; 71 } 72 set_driver_reczx_driver73 void set_driver_rec(zx_driver_rec_t* driver_rec) { 74 driver_rec_ = driver_rec; 75 } 76 set_opszx_driver77 void set_ops(const zx_driver_ops_t* ops) { 78 ops_ = ops; 79 } 80 set_statuszx_driver81 void set_status(zx_status_t status) { 82 status_ = status; 83 } 84 set_libnamezx_driver85 void set_libname(fbl::StringPiece libname) { 86 libname_ = libname; 87 } 88 89 // Interface to |ops|. These names contain Op in order to not 90 // collide with e.g. RefPtr names. 91 has_init_opzx_driver92 bool has_init_op() const { 93 return ops_->init != nullptr; 94 } 95 has_bind_opzx_driver96 bool has_bind_op() const { 97 return ops_->bind != nullptr; 98 } 99 has_create_opzx_driver100 bool has_create_op() const { 101 return ops_->create != nullptr; 102 } 103 InitOpzx_driver104 zx_status_t InitOp() { 105 return ops_->init(&ctx_); 106 } 107 BindOpzx_driver108 zx_status_t BindOp(devmgr::CreationContext* creation_context, 109 const fbl::RefPtr<zx_device_t>& device) const { 110 devmgr::devhost_set_creation_context(creation_context); 111 auto status = ops_->bind(ctx_, device.get()); 112 devmgr::devhost_set_creation_context(nullptr); 113 return status; 114 } 115 CreateOpzx_driver116 zx_status_t CreateOp(devmgr::CreationContext* creation_context, 117 const fbl::RefPtr<zx_device_t>& parent, const char* name, const char* args, 118 zx_handle_t rpc_channel) const { 119 devmgr::devhost_set_creation_context(creation_context); 120 auto status = ops_->create(ctx_, parent.get(), name, args, rpc_channel); 121 devmgr::devhost_set_creation_context(nullptr); 122 return status; 123 } 124 ReleaseOpzx_driver125 void ReleaseOp() const { 126 // TODO(kulakowski/teisenbe) Consider poisoning the ops_ table on release. 127 ops_->release(ctx_); 128 } 129 130 private: 131 friend fbl::unique_ptr<zx_driver> fbl::make_unique<zx_driver>(); 132 zx_driver() = default; 133 134 const char* name_ = nullptr; 135 zx_driver_rec_t* driver_rec_ = nullptr; 136 const zx_driver_ops_t* ops_ = nullptr; 137 void* ctx_ = nullptr; 138 fbl::String libname_; 139 zx_status_t status_ = ZX_OK; 140 }; 141 142 namespace devmgr { 143 144 extern zx_protocol_device_t device_default_ops; 145 146 zx_status_t devhost_device_add(const fbl::RefPtr<zx_device_t>& dev, 147 const fbl::RefPtr<zx_device_t>& parent, 148 const zx_device_prop_t* props, uint32_t prop_count, 149 const char* proxy_args) REQ_DM_LOCK; 150 // Note that devhost_device_remove() takes a RefPtr rather than a const RefPtr&. 151 // It intends to consume a reference. 152 zx_status_t devhost_device_remove(fbl::RefPtr<zx_device_t> dev) REQ_DM_LOCK; 153 zx_status_t devhost_device_bind(const fbl::RefPtr<zx_device_t>& dev, const char* drv_libname) REQ_DM_LOCK; 154 zx_status_t devhost_device_rebind(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK; 155 zx_status_t devhost_device_unbind(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK; 156 zx_status_t devhost_device_create(zx_driver_t* drv, const fbl::RefPtr<zx_device_t>& parent, 157 const char* name, void* ctx, 158 zx_protocol_device_t* ops, 159 fbl::RefPtr<zx_device_t>* out) REQ_DM_LOCK; 160 zx_status_t devhost_device_open_at(const fbl::RefPtr<zx_device_t>& dev, 161 fbl::RefPtr<zx_device_t>* out, 162 const char* path, uint32_t flags) REQ_DM_LOCK; 163 zx_status_t devhost_device_close(fbl::RefPtr<zx_device_t> dev, uint32_t flags) REQ_DM_LOCK; 164 zx_status_t devhost_device_suspend(const fbl::RefPtr<zx_device_t>& dev, uint32_t flags) REQ_DM_LOCK; 165 void devhost_device_destroy(zx_device_t* dev) REQ_DM_LOCK; 166 167 zx_status_t devhost_load_firmware(const fbl::RefPtr<zx_device_t>& dev, const char* path, 168 zx_handle_t* fw, size_t* size) REQ_DM_LOCK; 169 170 zx_status_t devhost_get_topo_path(const fbl::RefPtr<zx_device_t>& dev, char* path, 171 size_t max, size_t* actual); 172 173 zx_status_t devhost_get_metadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t type, void* buf, 174 size_t buflen, size_t* actual) REQ_DM_LOCK; 175 176 zx_status_t devhost_add_metadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t type, 177 const void* data, size_t length) REQ_DM_LOCK; 178 179 zx_status_t devhost_publish_metadata(const fbl::RefPtr<zx_device_t>& dev, const char* path, 180 uint32_t type, const void* data, size_t length) REQ_DM_LOCK; 181 182 // shared between devhost.c and rpc-device.c 183 struct DevcoordinatorConnection : AsyncLoopOwnedRpcHandler<DevcoordinatorConnection> { 184 DevcoordinatorConnection() = default; 185 186 static void HandleRpc(fbl::unique_ptr<DevcoordinatorConnection> conn, 187 async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status, 188 const zx_packet_signal_t* signal); 189 190 fbl::RefPtr<zx_device_t> dev; 191 }; 192 193 struct DevfsConnection : AsyncLoopOwnedRpcHandler<DevfsConnection> { 194 DevfsConnection() = default; 195 196 static void HandleRpc(fbl::unique_ptr<DevfsConnection> conn, 197 async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status, 198 const zx_packet_signal_t* signal); 199 200 fbl::RefPtr<zx_device_t> dev; 201 size_t io_off = 0; 202 uint32_t flags = 0; 203 }; 204 205 zx_status_t devhost_fidl_handler(fidl_msg_t* msg, fidl_txn_t* txn, void* cookie); 206 207 // Attaches channel |c| to new state representing an open connection to |dev|. 208 // |path_data| and |flags| are forwarded to the |dev|'s |open_at| hook. 209 zx_status_t devhost_device_connect(const fbl::RefPtr<zx_device_t>& dev, uint32_t flags, 210 const char* path_data, size_t path_size, zx::channel c); 211 212 zx_status_t devhost_start_connection(fbl::unique_ptr<DevfsConnection> ios, zx::channel h); 213 214 // routines devhost uses to talk to dev coordinator 215 zx_status_t devhost_add(const fbl::RefPtr<zx_device_t>& dev, 216 const fbl::RefPtr<zx_device_t>& child, const char* proxy_args, 217 const zx_device_prop_t* props, uint32_t prop_count) REQ_DM_LOCK; 218 zx_status_t devhost_remove(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK; 219 void devhost_make_visible(const fbl::RefPtr<zx_device_t>& dev); 220 221 // State that is shared between the zx_device implementation and devhost-core.cpp 222 void devhost_finalize() REQ_DM_LOCK; 223 extern fbl::DoublyLinkedList<zx_device*, zx_device::DeferNode> defer_device_list USE_DM_LOCK; 224 extern int devhost_enumerators USE_DM_LOCK; 225 226 } // namespace devmgr 227