[format] Format devhost codebase
Change-Id: I71617a5c39d1bae6fe2837c1e4bf4990ec06ba44
diff --git a/zircon/system/core/devmgr/devhost/api.cc b/zircon/system/core/devmgr/devhost/api.cc
index b60a604..5647f6d 100644
--- a/zircon/system/core/devmgr/devhost/api.cc
+++ b/zircon/system/core/devmgr/devhost/api.cc
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <ddk/debug.h>
+#include <ddk/device.h>
+#include <stdarg.h>
+#include <stdio.h>
#include <zircon/compiler.h>
+#include <zircon/device/vfs.h>
+
+#include <utility>
#include "devhost.h"
#include "scheduler_profile.h"
-#include <ddk/debug.h>
-#include <ddk/device.h>
-#include <zircon/device/vfs.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <utility>
using namespace devmgr;
@@ -24,248 +23,243 @@
// LibDriver Device Interface
-#define ALLOWED_FLAGS \
- (DEVICE_ADD_NON_BINDABLE | DEVICE_ADD_INSTANCE | DEVICE_ADD_MUST_ISOLATE | DEVICE_ADD_INVISIBLE)
+#define ALLOWED_FLAGS \
+ (DEVICE_ADD_NON_BINDABLE | DEVICE_ADD_INSTANCE | DEVICE_ADD_MUST_ISOLATE | DEVICE_ADD_INVISIBLE)
__EXPORT zx_status_t device_add_from_driver(zx_driver_t* drv, zx_device_t* parent,
device_add_args_t* args, zx_device_t** out) {
- zx_status_t r;
- fbl::RefPtr<zx_device_t> dev;
+ zx_status_t r;
+ fbl::RefPtr<zx_device_t> dev;
- if (!parent) {
- return ZX_ERR_INVALID_ARGS;
+ if (!parent) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ fbl::RefPtr<zx_device> parent_ref(parent);
+
+ if (!args || args->version != DEVICE_ADD_ARGS_VERSION) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ if (!args->ops || args->ops->version != DEVICE_OPS_VERSION) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ if (args->flags & ~ALLOWED_FLAGS) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ if ((args->flags & DEVICE_ADD_INSTANCE) &&
+ (args->flags & (DEVICE_ADD_MUST_ISOLATE | DEVICE_ADD_INVISIBLE))) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ // If the device will be added in the same devhost and visible,
+ // we can connect the client immediately after adding the device.
+ // Otherwise we will pass this channel to the devcoordinator via devhost_device_add.
+ zx::channel client_remote(args->client_remote);
+
+ {
+ ApiAutoLock lock;
+ r = devhost_device_create(drv, args->name, args->ctx, args->ops, &dev);
+ if (r != ZX_OK) {
+ return r;
+ }
+ if (args->proto_id) {
+ dev->protocol_id = args->proto_id;
+ dev->protocol_ops = args->proto_ops;
+ }
+ if (args->flags & DEVICE_ADD_NON_BINDABLE) {
+ dev->flags |= DEV_FLAG_UNBINDABLE;
+ }
+ if (args->flags & DEVICE_ADD_INVISIBLE) {
+ dev->flags |= DEV_FLAG_INVISIBLE;
}
- fbl::RefPtr<zx_device> parent_ref(parent);
-
- if (!args || args->version != DEVICE_ADD_ARGS_VERSION) {
- return ZX_ERR_INVALID_ARGS;
- }
- if (!args->ops || args->ops->version != DEVICE_OPS_VERSION) {
- return ZX_ERR_INVALID_ARGS;
- }
- if (args->flags & ~ALLOWED_FLAGS) {
- return ZX_ERR_INVALID_ARGS;
- }
- if ((args->flags & DEVICE_ADD_INSTANCE) &&
- (args->flags & (DEVICE_ADD_MUST_ISOLATE | DEVICE_ADD_INVISIBLE))) {
- return ZX_ERR_INVALID_ARGS;
+ // out must be set before calling devhost_device_add().
+ // devhost_device_add() may result in child devices being created before it returns,
+ // and those children may call ops on the device before device_add() returns.
+ // This leaked-ref will be accounted below.
+ if (out) {
+ *out = dev.get();
}
- // If the device will be added in the same devhost and visible,
- // we can connect the client immediately after adding the device.
- // Otherwise we will pass this channel to the devcoordinator via devhost_device_add.
- zx::channel client_remote(args->client_remote);
-
- {
- ApiAutoLock lock;
- r = devhost_device_create(drv, args->name, args->ctx, args->ops, &dev);
- if (r != ZX_OK) {
- return r;
- }
- if (args->proto_id) {
- dev->protocol_id = args->proto_id;
- dev->protocol_ops = args->proto_ops;
- }
- if (args->flags & DEVICE_ADD_NON_BINDABLE) {
- dev->flags |= DEV_FLAG_UNBINDABLE;
- }
- if (args->flags & DEVICE_ADD_INVISIBLE) {
- dev->flags |= DEV_FLAG_INVISIBLE;
- }
-
- // out must be set before calling devhost_device_add().
- // devhost_device_add() may result in child devices being created before it returns,
- // and those children may call ops on the device before device_add() returns.
- // This leaked-ref will be accounted below.
- if (out) {
- *out = dev.get();
- }
-
- if (args->flags & DEVICE_ADD_MUST_ISOLATE) {
- r = devhost_device_add(dev, parent_ref, args->props, args->prop_count, args->proxy_args,
- std::move(client_remote));
- } else if (args->flags & DEVICE_ADD_INSTANCE) {
- dev->flags |= DEV_FLAG_INSTANCE | DEV_FLAG_UNBINDABLE;
- r = devhost_device_add(dev, parent_ref, nullptr, 0, nullptr,
- zx::channel() /* client_remote */);
- } else {
- bool pass_client_remote = args->flags & DEVICE_ADD_INVISIBLE;
- r = devhost_device_add(dev, parent_ref, args->props, args->prop_count, nullptr,
- pass_client_remote ? std::move(client_remote) : zx::channel());
- }
- if (r != ZX_OK) {
- if (out) {
- *out = nullptr;
- }
- dev.reset();
- }
- }
-
- if (dev && client_remote.is_valid()) {
- // This needs to be called outside the ApiAutoLock, as device_open will be called
- devhost_device_connect(dev, ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
- std::move(client_remote));
-
- // Leak the reference that was written to |out|, it will be recovered in device_remove().
- // For device instances we mimic the behavior of |open| by not leaking the reference,
- // effectively passing owenership to the new connection.
- if (!(args->flags & DEVICE_ADD_INSTANCE)) {
- __UNUSED auto ptr = dev.leak_ref();
- }
+ if (args->flags & DEVICE_ADD_MUST_ISOLATE) {
+ r = devhost_device_add(dev, parent_ref, args->props, args->prop_count, args->proxy_args,
+ std::move(client_remote));
+ } else if (args->flags & DEVICE_ADD_INSTANCE) {
+ dev->flags |= DEV_FLAG_INSTANCE | DEV_FLAG_UNBINDABLE;
+ r = devhost_device_add(dev, parent_ref, nullptr, 0, nullptr,
+ zx::channel() /* client_remote */);
} else {
- // Leak the reference that was written to |out|, it will be recovered in device_remove().
- __UNUSED auto ptr = dev.leak_ref();
+ bool pass_client_remote = args->flags & DEVICE_ADD_INVISIBLE;
+ r = devhost_device_add(dev, parent_ref, args->props, args->prop_count, nullptr,
+ pass_client_remote ? std::move(client_remote) : zx::channel());
}
+ if (r != ZX_OK) {
+ if (out) {
+ *out = nullptr;
+ }
+ dev.reset();
+ }
+ }
- return r;
+ if (dev && client_remote.is_valid()) {
+ // This needs to be called outside the ApiAutoLock, as device_open will be called
+ devhost_device_connect(dev, ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
+ std::move(client_remote));
+
+ // Leak the reference that was written to |out|, it will be recovered in device_remove().
+ // For device instances we mimic the behavior of |open| by not leaking the reference,
+ // effectively passing owenership to the new connection.
+ if (!(args->flags & DEVICE_ADD_INSTANCE)) {
+ __UNUSED auto ptr = dev.leak_ref();
+ }
+ } else {
+ // Leak the reference that was written to |out|, it will be recovered in device_remove().
+ __UNUSED auto ptr = dev.leak_ref();
+ }
+
+ return r;
}
__EXPORT zx_status_t device_remove(zx_device_t* dev) {
- ApiAutoLock lock;
- // This recovers the leaked reference that happened in
- // device_add_from_driver() above.
- auto dev_ref = fbl::internal::MakeRefPtrNoAdopt(dev);
- return devhost_device_remove(std::move(dev_ref));
+ ApiAutoLock lock;
+ // This recovers the leaked reference that happened in
+ // device_add_from_driver() above.
+ auto dev_ref = fbl::internal::MakeRefPtrNoAdopt(dev);
+ return devhost_device_remove(std::move(dev_ref));
}
__EXPORT zx_status_t device_rebind(zx_device_t* dev) {
- ApiAutoLock lock;
- fbl::RefPtr<zx_device_t> dev_ref(dev);
- return devhost_device_rebind(dev_ref);
+ ApiAutoLock lock;
+ fbl::RefPtr<zx_device_t> dev_ref(dev);
+ return devhost_device_rebind(dev_ref);
}
__EXPORT void device_make_visible(zx_device_t* dev) {
- ApiAutoLock lock;
- fbl::RefPtr<zx_device_t> dev_ref(dev);
- devhost_make_visible(dev_ref);
+ ApiAutoLock lock;
+ fbl::RefPtr<zx_device_t> dev_ref(dev);
+ devhost_make_visible(dev_ref);
}
__EXPORT zx_status_t device_get_profile(zx_device_t* dev, uint32_t priority, const char* name,
zx_handle_t* out_profile) {
- return devhost_get_scheduler_profile(priority, name, out_profile);
+ return devhost_get_scheduler_profile(priority, name, out_profile);
}
-__EXPORT const char* device_get_name(zx_device_t* dev) {
- return dev->name;
-}
+__EXPORT const char* device_get_name(zx_device_t* dev) { return dev->name; }
__EXPORT zx_device_t* device_get_parent(zx_device_t* dev) {
- // The caller should not hold on to this past the lifetime of |dev|.
- return dev->parent.get();
+ // The caller should not hold on to this past the lifetime of |dev|.
+ return dev->parent.get();
}
struct GenericProtocol {
- void* ops;
- void* ctx;
+ void* ops;
+ void* ctx;
};
__EXPORT zx_status_t device_get_protocol(const zx_device_t* dev, uint32_t proto_id, void* out) {
- auto proto = static_cast<GenericProtocol*>(out);
- if (dev->ops->get_protocol) {
- return dev->ops->get_protocol(dev->ctx, proto_id, out);
- }
- if ((proto_id == dev->protocol_id) && (dev->protocol_ops != nullptr)) {
- proto->ops = dev->protocol_ops;
- proto->ctx = dev->ctx;
- return ZX_OK;
- }
- return ZX_ERR_NOT_SUPPORTED;
+ auto proto = static_cast<GenericProtocol*>(out);
+ if (dev->ops->get_protocol) {
+ return dev->ops->get_protocol(dev->ctx, proto_id, out);
+ }
+ if ((proto_id == dev->protocol_id) && (dev->protocol_ops != nullptr)) {
+ proto->ops = dev->protocol_ops;
+ proto->ctx = dev->ctx;
+ return ZX_OK;
+ }
+ return ZX_ERR_NOT_SUPPORTED;
}
__EXPORT void device_state_clr_set(zx_device_t* dev, zx_signals_t clearflag, zx_signals_t setflag) {
- dev->event.signal(clearflag, setflag);
+ dev->event.signal(clearflag, setflag);
}
-__EXPORT zx_off_t device_get_size(zx_device_t* dev) {
- return dev->GetSizeOp();
-}
+__EXPORT zx_off_t device_get_size(zx_device_t* dev) { return dev->GetSizeOp(); }
__EXPORT zx_status_t device_read(zx_device_t* dev, void* buf, size_t count, zx_off_t off,
size_t* actual) {
- return dev->ReadOp(buf, count, off, actual);
+ return dev->ReadOp(buf, count, off, actual);
}
__EXPORT zx_status_t device_write(zx_device_t* dev, const void* buf, size_t count, zx_off_t off,
size_t* actual) {
- return dev->WriteOp(buf, count, off, actual);
+ return dev->WriteOp(buf, count, off, actual);
}
// LibDriver Misc Interfaces
namespace devmgr {
extern zx_handle_t root_resource_handle;
-} // namespace devmgr
+} // namespace devmgr
// Please do not use get_root_resource() in new code. See ZX-1467.
-__EXPORT zx_handle_t get_root_resource() {
- return root_resource_handle;
-}
+__EXPORT zx_handle_t get_root_resource() { return root_resource_handle; }
__EXPORT zx_status_t load_firmware(zx_device_t* dev, const char* path, zx_handle_t* fw,
size_t* size) {
- ApiAutoLock lock;
- fbl::RefPtr<zx_device_t> dev_ref(dev);
- return devhost_load_firmware(dev_ref, path, fw, size);
+ ApiAutoLock lock;
+ fbl::RefPtr<zx_device_t> dev_ref(dev);
+ return devhost_load_firmware(dev_ref, path, fw, size);
}
// Interface Used by DevHost RPC Layer
zx_status_t device_bind(const fbl::RefPtr<zx_device_t>& dev, const char* drv_libname) {
- ApiAutoLock lock;
- return devhost_device_bind(dev, drv_libname);
+ ApiAutoLock lock;
+ return devhost_device_bind(dev, drv_libname);
}
zx_status_t device_unbind(const fbl::RefPtr<zx_device_t>& dev) {
- ApiAutoLock lock;
- return devhost_device_unbind(dev);
+ ApiAutoLock lock;
+ return devhost_device_unbind(dev);
}
zx_status_t device_open(const fbl::RefPtr<zx_device_t>& dev, fbl::RefPtr<zx_device_t>* out,
uint32_t flags) {
- ApiAutoLock lock;
- return devhost_device_open(dev, out, flags);
+ ApiAutoLock lock;
+ return devhost_device_open(dev, out, flags);
}
// This function is intended to consume the reference produced by device_open()
zx_status_t device_close(fbl::RefPtr<zx_device_t> dev, uint32_t flags) {
- ApiAutoLock lock;
- return devhost_device_close(std::move(dev), flags);
+ ApiAutoLock lock;
+ return devhost_device_close(std::move(dev), flags);
}
__EXPORT zx_status_t device_get_metadata(zx_device_t* dev, uint32_t type, void* buf, size_t buflen,
size_t* actual) {
- ApiAutoLock lock;
- auto dev_ref = fbl::WrapRefPtr(dev);
- return devhost_get_metadata(dev_ref, type, buf, buflen, actual);
+ ApiAutoLock lock;
+ auto dev_ref = fbl::WrapRefPtr(dev);
+ return devhost_get_metadata(dev_ref, type, buf, buflen, actual);
}
__EXPORT zx_status_t device_get_metadata_size(zx_device_t* dev, uint32_t type, size_t* out_size) {
- ApiAutoLock lock;
- auto dev_ref = fbl::WrapRefPtr(dev);
- return devhost_get_metadata_size(dev_ref, type, out_size);
+ ApiAutoLock lock;
+ auto dev_ref = fbl::WrapRefPtr(dev);
+ return devhost_get_metadata_size(dev_ref, type, out_size);
}
__EXPORT zx_status_t device_add_metadata(zx_device_t* dev, uint32_t type, const void* data,
size_t length) {
- ApiAutoLock lock;
- auto dev_ref = fbl::WrapRefPtr(dev);
- return devhost_add_metadata(dev_ref, type, data, length);
+ ApiAutoLock lock;
+ auto dev_ref = fbl::WrapRefPtr(dev);
+ return devhost_add_metadata(dev_ref, type, data, length);
}
__EXPORT zx_status_t device_publish_metadata(zx_device_t* dev, const char* path, uint32_t type,
const void* data, size_t length) {
- ApiAutoLock lock;
- auto dev_ref = fbl::WrapRefPtr(dev);
- return devhost_publish_metadata(dev_ref, path, type, data, length);
+ ApiAutoLock lock;
+ auto dev_ref = fbl::WrapRefPtr(dev);
+ return devhost_publish_metadata(dev_ref, path, type, data, length);
}
-__EXPORT zx_status_t device_add_composite(
- zx_device_t* dev, const char* name, const zx_device_prop_t* props, size_t props_count,
- const device_component_t* components, size_t components_count,
- uint32_t coresident_device_index) {
- ApiAutoLock lock;
- auto dev_ref = fbl::WrapRefPtr(dev);
- return devhost_device_add_composite(dev_ref, name, props, props_count, components,
- components_count, coresident_device_index);
+__EXPORT zx_status_t device_add_composite(zx_device_t* dev, const char* name,
+ const zx_device_prop_t* props, size_t props_count,
+ const device_component_t* components,
+ size_t components_count,
+ uint32_t coresident_device_index) {
+ ApiAutoLock lock;
+ auto dev_ref = fbl::WrapRefPtr(dev);
+ return devhost_device_add_composite(dev_ref, name, props, props_count, components,
+ components_count, coresident_device_index);
}
diff --git a/zircon/system/core/devmgr/devhost/composite-device.cc b/zircon/system/core/devmgr/devhost/composite-device.cc
index aab177e..ec288e8 100644
--- a/zircon/system/core/devmgr/devhost/composite-device.cc
+++ b/zircon/system/core/devmgr/devhost/composite-device.cc
@@ -4,10 +4,12 @@
#include "composite-device.h"
-#include <algorithm>
#include <ddk/protocol/composite.h>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
+
+#include <algorithm>
+
#include "devhost.h"
#include "zx-device.h"
@@ -16,115 +18,109 @@
namespace {
class CompositeDeviceInstance {
-public:
- CompositeDeviceInstance(zx_device_t* zxdev, CompositeComponents&& components)
- : zxdev_(zxdev), components_(std::move(components)) { }
+ public:
+ CompositeDeviceInstance(zx_device_t* zxdev, CompositeComponents&& components)
+ : zxdev_(zxdev), components_(std::move(components)) {}
- static zx_status_t Create(fbl::RefPtr<zx_device> zxdev, CompositeComponents&& components,
- std::unique_ptr<CompositeDeviceInstance>* device) {
- // Leak a reference to the zxdev here. It will be cleaned up by the
- // device_remove() in Unbind().
- auto dev = std::make_unique<CompositeDeviceInstance>(zxdev.leak_ref(),
- std::move(components));
- *device = std::move(dev);
- return ZX_OK;
+ static zx_status_t Create(fbl::RefPtr<zx_device> zxdev, CompositeComponents&& components,
+ std::unique_ptr<CompositeDeviceInstance>* device) {
+ // Leak a reference to the zxdev here. It will be cleaned up by the
+ // device_remove() in Unbind().
+ auto dev = std::make_unique<CompositeDeviceInstance>(zxdev.leak_ref(), std::move(components));
+ *device = std::move(dev);
+ return ZX_OK;
+ }
+
+ uint32_t GetComponentCount() { return static_cast<uint32_t>(components_.size()); }
+
+ void GetComponents(zx_device_t** comp_list, size_t comp_count, size_t* comp_actual) {
+ size_t actual = std::min(comp_count, components_.size());
+ for (size_t i = 0; i < actual; ++i) {
+ comp_list[i] = components_[i].get();
}
+ *comp_actual = actual;
+ }
- uint32_t GetComponentCount() {
- return static_cast<uint32_t>(components_.size());
- }
+ void Release() { delete this; }
- void GetComponents(zx_device_t** comp_list, size_t comp_count, size_t* comp_actual) {
- size_t actual = std::min(comp_count, components_.size());
- for (size_t i = 0; i < actual; ++i) {
- comp_list[i] = components_[i].get();
- }
- *comp_actual = actual;
- }
+ void Unbind() {
+ components_.reset();
+ device_remove(zxdev_);
+ }
- void Release() {
- delete this;
- }
+ const CompositeComponents& components() { return components_; }
- void Unbind() {
- components_.reset();
- device_remove(zxdev_);
- }
-
- const CompositeComponents& components() { return components_; }
-private:
- zx_device_t* zxdev_;
- CompositeComponents components_;
+ private:
+ zx_device_t* zxdev_;
+ CompositeComponents components_;
};
// Get the placeholder driver structure for the composite driver
fbl::RefPtr<zx_driver> GetCompositeDriver() {
- static fbl::Mutex lock;
- static fbl::RefPtr<zx_driver> composite TA_GUARDED(lock);
+ static fbl::Mutex lock;
+ static fbl::RefPtr<zx_driver> composite TA_GUARDED(lock);
- fbl::AutoLock guard(&lock);
- if (composite == nullptr) {
- zx_status_t status = zx_driver::Create(&composite);
- if (status != ZX_OK) {
- return nullptr;
- }
- composite->set_name("internal:composite");
- composite->set_libname("<internal:composite>");
+ fbl::AutoLock guard(&lock);
+ if (composite == nullptr) {
+ zx_status_t status = zx_driver::Create(&composite);
+ if (status != ZX_OK) {
+ return nullptr;
}
- return composite;
+ composite->set_name("internal:composite");
+ composite->set_libname("<internal:composite>");
+ }
+ return composite;
}
-} // namespace
+} // namespace
zx_status_t InitializeCompositeDevice(const fbl::RefPtr<zx_device>& dev,
CompositeComponents&& components) {
- static const zx_protocol_device_t composite_device_ops = []() {
- zx_protocol_device_t ops = {};
- ops.unbind = [](void* ctx) { static_cast<CompositeDeviceInstance*>(ctx)->Unbind(); };
- ops.release = [](void* ctx) { static_cast<CompositeDeviceInstance*>(ctx)->Release(); };
- return ops;
- }();
- static composite_protocol_ops_t composite_ops = []() {
- composite_protocol_ops_t ops = {};
- ops.get_component_count = [](void* ctx) {
- return static_cast<CompositeDeviceInstance*>(ctx)->GetComponentCount();
- };
- ops.get_components = [](void* ctx, zx_device_t** comp_list, size_t comp_count,
- size_t* comp_actual) {
- static_cast<CompositeDeviceInstance*>(ctx)->GetComponents(comp_list, comp_count,
- comp_actual);
- };
- return ops;
- }();
+ static const zx_protocol_device_t composite_device_ops = []() {
+ zx_protocol_device_t ops = {};
+ ops.unbind = [](void* ctx) { static_cast<CompositeDeviceInstance*>(ctx)->Unbind(); };
+ ops.release = [](void* ctx) { static_cast<CompositeDeviceInstance*>(ctx)->Release(); };
+ return ops;
+ }();
+ static composite_protocol_ops_t composite_ops = []() {
+ composite_protocol_ops_t ops = {};
+ ops.get_component_count = [](void* ctx) {
+ return static_cast<CompositeDeviceInstance*>(ctx)->GetComponentCount();
+ };
+ ops.get_components = [](void* ctx, zx_device_t** comp_list, size_t comp_count,
+ size_t* comp_actual) {
+ static_cast<CompositeDeviceInstance*>(ctx)->GetComponents(comp_list, comp_count, comp_actual);
+ };
+ return ops;
+ }();
- auto driver = GetCompositeDriver();
- if (driver == nullptr) {
- return ZX_ERR_INTERNAL;
- }
+ auto driver = GetCompositeDriver();
+ if (driver == nullptr) {
+ return ZX_ERR_INTERNAL;
+ }
- auto composite = fbl::MakeRefCounted<CompositeDevice>(dev);
+ auto composite = fbl::MakeRefCounted<CompositeDevice>(dev);
- std::unique_ptr<CompositeDeviceInstance> new_device;
- zx_status_t status = CompositeDeviceInstance::Create(dev, std::move(components),
- &new_device);
- if (status != ZX_OK) {
- return status;
- }
+ std::unique_ptr<CompositeDeviceInstance> new_device;
+ zx_status_t status = CompositeDeviceInstance::Create(dev, std::move(components), &new_device);
+ if (status != ZX_OK) {
+ return status;
+ }
- for (auto& component : new_device->components()) {
- component->set_composite(composite);
- }
+ for (auto& component : new_device->components()) {
+ component->set_composite(composite);
+ }
- dev->protocol_id = ZX_PROTOCOL_COMPOSITE;
- dev->protocol_ops = &composite_ops;
- dev->driver = driver.get();
- dev->ops = &composite_device_ops;
- dev->ctx = new_device.release();
- // Flag that when this is cleaned up, we should run its release hook.
- dev->flags |= DEV_FLAG_ADDED;
- return ZX_OK;
+ dev->protocol_id = ZX_PROTOCOL_COMPOSITE;
+ dev->protocol_ops = &composite_ops;
+ dev->driver = driver.get();
+ dev->ops = &composite_device_ops;
+ dev->ctx = new_device.release();
+ // Flag that when this is cleaned up, we should run its release hook.
+ dev->flags |= DEV_FLAG_ADDED;
+ return ZX_OK;
}
CompositeDevice::~CompositeDevice() = default;
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/composite-device.h b/zircon/system/core/devmgr/devhost/composite-device.h
index 02e614f..c2d402a 100644
--- a/zircon/system/core/devmgr/devhost/composite-device.h
+++ b/zircon/system/core/devmgr/devhost/composite-device.h
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_COMPOSITE_DEVICE_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_COMPOSITE_DEVICE_H_
#include <ddk/driver.h>
#include <fbl/array.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
+
#include "zx-device.h"
namespace devmgr {
@@ -23,12 +25,15 @@
// enables one of them (the first to try) to begin teardown of the composite
// device. This is used for implementing unbind.
class CompositeDevice : public fbl::RefCounted<CompositeDevice> {
-public:
- explicit CompositeDevice(fbl::RefPtr<zx_device> device) : device_(std::move(device)) {}
- ~CompositeDevice();
- fbl::RefPtr<zx_device> Detach() { return std::move(device_); }
-private:
- fbl::RefPtr<zx_device> device_;
+ public:
+ explicit CompositeDevice(fbl::RefPtr<zx_device> device) : device_(std::move(device)) {}
+ ~CompositeDevice();
+ fbl::RefPtr<zx_device> Detach() { return std::move(device_); }
+
+ private:
+ fbl::RefPtr<zx_device> device_;
};
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_COMPOSITE_DEVICE_H_
diff --git a/zircon/system/core/devmgr/devhost/connection-destroyer.cc b/zircon/system/core/devmgr/devhost/connection-destroyer.cc
index 0d15851..258cb71 100644
--- a/zircon/system/core/devmgr/devhost/connection-destroyer.cc
+++ b/zircon/system/core/devmgr/devhost/connection-destroyer.cc
@@ -5,6 +5,7 @@
#include "connection-destroyer.h"
#include <inttypes.h>
+
#include "../shared/log.h"
#include "device-controller-connection.h"
#include "proxy-iostate.h"
@@ -14,42 +15,41 @@
zx_status_t ConnectionDestroyer::QueueProxyConnection(async_dispatcher_t* dispatcher,
ProxyIostate* conn) {
- zx_packet_user_t pkt = {};
- pkt.u64[0] = static_cast<uint64_t>(Type::Proxy);
- pkt.u64[1] = reinterpret_cast<uintptr_t>(conn);
- return receiver_.QueuePacket(dispatcher, &pkt);
+ zx_packet_user_t pkt = {};
+ pkt.u64[0] = static_cast<uint64_t>(Type::Proxy);
+ pkt.u64[1] = reinterpret_cast<uintptr_t>(conn);
+ return receiver_.QueuePacket(dispatcher, &pkt);
}
-zx_status_t ConnectionDestroyer::QueueDeviceControllerConnection(
- async_dispatcher_t* dispatcher, DeviceControllerConnection* conn) {
- zx_packet_user_t pkt = {};
- pkt.u64[0] = static_cast<uint64_t>(Type::DeviceController);
- pkt.u64[1] = reinterpret_cast<uintptr_t>(conn);
- return receiver_.QueuePacket(dispatcher, &pkt);
+zx_status_t ConnectionDestroyer::QueueDeviceControllerConnection(async_dispatcher_t* dispatcher,
+ DeviceControllerConnection* conn) {
+ zx_packet_user_t pkt = {};
+ pkt.u64[0] = static_cast<uint64_t>(Type::DeviceController);
+ pkt.u64[1] = reinterpret_cast<uintptr_t>(conn);
+ return receiver_.QueuePacket(dispatcher, &pkt);
}
void ConnectionDestroyer::Handler(async_dispatcher_t* dispatcher, async::Receiver* receiver,
zx_status_t status, const zx_packet_user_t* data) {
- Type type = static_cast<Type>(data->u64[0]);
- uintptr_t ptr = data->u64[1];
+ Type type = static_cast<Type>(data->u64[0]);
+ uintptr_t ptr = data->u64[1];
- switch (type) {
+ switch (type) {
case Type::DeviceController: {
- auto conn = reinterpret_cast<DeviceControllerConnection*>(ptr);
- log(TRACE, "devhost: destroying devcoord conn '%p'\n", conn);
- delete conn;
- break;
+ auto conn = reinterpret_cast<DeviceControllerConnection*>(ptr);
+ log(TRACE, "devhost: destroying devcoord conn '%p'\n", conn);
+ delete conn;
+ break;
}
case Type::Proxy: {
- auto conn = reinterpret_cast<ProxyIostate*>(ptr);
- log(TRACE, "devhost: destroying proxy conn '%p'\n", conn);
- delete conn;
- break;
+ auto conn = reinterpret_cast<ProxyIostate*>(ptr);
+ log(TRACE, "devhost: destroying proxy conn '%p'\n", conn);
+ delete conn;
+ break;
}
default:
- ZX_ASSERT_MSG(false, "Unknown IosDestructionType %" PRIu64 "\n", data->u64[0]);
- }
+ ZX_ASSERT_MSG(false, "Unknown IosDestructionType %" PRIu64 "\n", data->u64[0]);
+ }
}
-} // namespace devmgr
-
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/connection-destroyer.h b/zircon/system/core/devmgr/devhost/connection-destroyer.h
index 5ae272e3..da2bdb65 100644
--- a/zircon/system/core/devmgr/devhost/connection-destroyer.h
+++ b/zircon/system/core/devmgr/devhost/connection-destroyer.h
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_CONNECTION_DESTROYER_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_CONNECTION_DESTROYER_H_
#include <lib/async/cpp/receiver.h>
#include <zircon/syscalls.h>
@@ -16,35 +17,36 @@
// This allows us to prevent races between canceling waiting on the connection
// channel and executing the connection's handler.
class ConnectionDestroyer {
-public:
- static ConnectionDestroyer* Get() {
- static ConnectionDestroyer destroyer;
- return &destroyer;
- }
+ public:
+ static ConnectionDestroyer* Get() {
+ static ConnectionDestroyer destroyer;
+ return &destroyer;
+ }
- zx_status_t QueueDeviceControllerConnection(async_dispatcher_t* dispatcher,
- DeviceControllerConnection* conn);
- zx_status_t QueueProxyConnection(async_dispatcher_t* dispatcher,
- ProxyIostate* conn);
+ zx_status_t QueueDeviceControllerConnection(async_dispatcher_t* dispatcher,
+ DeviceControllerConnection* conn);
+ zx_status_t QueueProxyConnection(async_dispatcher_t* dispatcher, ProxyIostate* conn);
-private:
- ConnectionDestroyer() = default;
+ private:
+ ConnectionDestroyer() = default;
- ConnectionDestroyer(const ConnectionDestroyer&) = delete;
- ConnectionDestroyer& operator=(const ConnectionDestroyer&) = delete;
+ ConnectionDestroyer(const ConnectionDestroyer&) = delete;
+ ConnectionDestroyer& operator=(const ConnectionDestroyer&) = delete;
- ConnectionDestroyer(ConnectionDestroyer&&) = delete;
- ConnectionDestroyer& operator=(ConnectionDestroyer&&) = delete;
+ ConnectionDestroyer(ConnectionDestroyer&&) = delete;
+ ConnectionDestroyer& operator=(ConnectionDestroyer&&) = delete;
- static void Handler(async_dispatcher_t* dispatcher, async::Receiver* receiver,
- zx_status_t status, const zx_packet_user_t* data);
+ static void Handler(async_dispatcher_t* dispatcher, async::Receiver* receiver, zx_status_t status,
+ const zx_packet_user_t* data);
- enum class Type {
- DeviceController,
- Proxy,
- };
+ enum class Type {
+ DeviceController,
+ Proxy,
+ };
- async::Receiver receiver_{ConnectionDestroyer::Handler};
+ async::Receiver receiver_{ConnectionDestroyer::Handler};
};
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_CONNECTION_DESTROYER_H_
diff --git a/zircon/system/core/devmgr/devhost/core.cc b/zircon/system/core/devmgr/devhost/core.cc
index f26c4e3..1c14d8d 100644
--- a/zircon/system/core/devmgr/devhost/core.cc
+++ b/zircon/system/core/devmgr/devhost/core.cc
@@ -2,30 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "devhost.h"
-
#include <assert.h>
-#include <atomic>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <errno.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <fcntl.h>
-#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <threads.h>
#include <unistd.h>
-#include <utility>
#include <zircon/assert.h>
#include <zircon/listnode.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
+#include <atomic>
+#include <new>
+#include <utility>
+
#include "composite-device.h"
+#include "devhost.h"
namespace devmgr {
@@ -34,9 +34,9 @@
#if TRACE
#define xprintf(fmt...) printf(fmt)
#else
-#define xprintf(fmt...) \
- do { \
- } while (0)
+#define xprintf(fmt...) \
+ do { \
+ } while (0)
#endif
#define TRACE_ADD_REMOVE 0
@@ -44,7 +44,7 @@
namespace internal {
__LOCAL mtx_t devhost_api_lock = MTX_INIT;
__LOCAL std::atomic<thrd_t> devhost_api_lock_owner(0);
-} // namespace internal
+} // namespace internal
static thread_local BindContext* g_bind_context;
static thread_local CreationContext* g_creation_context;
@@ -52,108 +52,93 @@
// The bind and creation contexts is setup before the bind() or
// create() ops are invoked to provide the ability to sanity check the
// required device_add() operations these hooks should be making.
-void devhost_set_bind_context(BindContext* ctx) {
- g_bind_context = ctx;
-}
+void devhost_set_bind_context(BindContext* ctx) { g_bind_context = ctx; }
void devhost_set_creation_context(CreationContext* ctx) {
- ZX_DEBUG_ASSERT(!ctx || ctx->rpc->is_valid());
- g_creation_context = ctx;
+ ZX_DEBUG_ASSERT(!ctx || ctx->rpc->is_valid());
+ g_creation_context = ctx;
}
-static zx_status_t default_open(void* ctx, zx_device_t** out, uint32_t flags) {
- return ZX_OK;
-}
+static zx_status_t default_open(void* ctx, zx_device_t** out, uint32_t flags) { return ZX_OK; }
-static zx_status_t default_close(void* ctx, uint32_t flags) {
- return ZX_OK;
-}
+static zx_status_t default_close(void* ctx, uint32_t flags) { return ZX_OK; }
static void default_unbind(void* ctx) {}
static void default_release(void* ctx) {}
static zx_status_t default_read(void* ctx, void* buf, size_t count, zx_off_t off, size_t* actual) {
- return ZX_ERR_NOT_SUPPORTED;
+ return ZX_ERR_NOT_SUPPORTED;
}
static zx_status_t default_write(void* ctx, const void* buf, size_t count, zx_off_t off,
size_t* actual) {
- return ZX_ERR_NOT_SUPPORTED;
+ return ZX_ERR_NOT_SUPPORTED;
}
-static zx_off_t default_get_size(void* ctx) {
- return 0;
-}
+static zx_off_t default_get_size(void* ctx) { return 0; }
static zx_status_t default_ioctl(void* ctx, uint32_t op, const void* in_buf, size_t in_len,
void* out_buf, size_t out_len, size_t* out_actual) {
- return ZX_ERR_NOT_SUPPORTED;
+ return ZX_ERR_NOT_SUPPORTED;
}
-static zx_status_t default_suspend(void* ctx, uint32_t flags) {
- return ZX_ERR_NOT_SUPPORTED;
-}
+static zx_status_t default_suspend(void* ctx, uint32_t flags) { return ZX_ERR_NOT_SUPPORTED; }
-static zx_status_t default_resume(void* ctx, uint32_t flags) {
- return ZX_ERR_NOT_SUPPORTED;
-}
+static zx_status_t default_resume(void* ctx, uint32_t flags) { return ZX_ERR_NOT_SUPPORTED; }
-static zx_status_t default_rxrpc(void* ctx, zx_handle_t channel) {
- return ZX_ERR_NOT_SUPPORTED;
-}
+static zx_status_t default_rxrpc(void* ctx, zx_handle_t channel) { return ZX_ERR_NOT_SUPPORTED; }
static zx_status_t default_message(void* ctx, fidl_msg_t* msg, fidl_txn_t* txn) {
- fidl_message_header_t* hdr = (fidl_message_header_t*)msg->bytes;
- printf("devhost: Unsupported FIDL operation: 0x%lx\n", hdr->ordinal);
- zx_handle_close_many(msg->handles, msg->num_handles);
- return ZX_ERR_NOT_SUPPORTED;
+ fidl_message_header_t* hdr = (fidl_message_header_t*)msg->bytes;
+ printf("devhost: Unsupported FIDL operation: 0x%lx\n", hdr->ordinal);
+ zx_handle_close_many(msg->handles, msg->num_handles);
+ return ZX_ERR_NOT_SUPPORTED;
}
zx_protocol_device_t device_default_ops = []() {
- zx_protocol_device_t ops = {};
- ops.open = default_open;
- ops.close = default_close;
- ops.unbind = default_unbind;
- ops.release = default_release;
- ops.read = default_read;
- ops.write = default_write;
- ops.get_size = default_get_size;
- ops.ioctl = default_ioctl;
- ops.suspend = default_suspend;
- ops.resume = default_resume;
- ops.rxrpc = default_rxrpc;
- ops.message = default_message;
- return ops;
+ zx_protocol_device_t ops = {};
+ ops.open = default_open;
+ ops.close = default_close;
+ ops.unbind = default_unbind;
+ ops.release = default_release;
+ ops.read = default_read;
+ ops.write = default_write;
+ ops.get_size = default_get_size;
+ ops.ioctl = default_ioctl;
+ ops.suspend = default_suspend;
+ ops.resume = default_resume;
+ ops.rxrpc = default_rxrpc;
+ ops.message = default_message;
+ return ops;
}();
[[noreturn]] static void device_invalid_fatal(void* ctx) {
- printf("devhost: FATAL: zx_device_t used after destruction.\n");
- __builtin_trap();
+ printf("devhost: FATAL: zx_device_t used after destruction.\n");
+ __builtin_trap();
}
static zx_protocol_device_t device_invalid_ops = []() {
- zx_protocol_device_t ops = {};
- ops.open =
- +[](void* ctx, zx_device_t**, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
- ops.close = +[](void* ctx, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
- ops.unbind = +[](void* ctx) { device_invalid_fatal(ctx); };
- ops.release = +[](void* ctx) { device_invalid_fatal(ctx); };
- ops.read = +[](void* ctx, void*, size_t, size_t, size_t*) -> zx_status_t {
- device_invalid_fatal(ctx);
- };
- ops.write = +[](void* ctx, const void*, size_t, size_t, size_t*) -> zx_status_t {
- device_invalid_fatal(ctx);
- };
- ops.get_size = +[](void* ctx) -> zx_off_t { device_invalid_fatal(ctx); };
- ops.ioctl = +[](void* ctx, uint32_t, const void*, size_t, void*, size_t,
- size_t*) -> zx_status_t { device_invalid_fatal(ctx); };
- ops.suspend = +[](void* ctx, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
- ops.resume = +[](void* ctx, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
- ops.rxrpc = +[](void* ctx, zx_handle_t) -> zx_status_t { device_invalid_fatal(ctx); };
- ops.message =
- +[](void* ctx, fidl_msg_t*, fidl_txn_t*) -> zx_status_t { device_invalid_fatal(ctx); };
- return ops;
+ zx_protocol_device_t ops = {};
+ ops.open = +[](void* ctx, zx_device_t**, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
+ ops.close = +[](void* ctx, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
+ ops.unbind = +[](void* ctx) { device_invalid_fatal(ctx); };
+ ops.release = +[](void* ctx) { device_invalid_fatal(ctx); };
+ ops.read =
+ +[](void* ctx, void*, size_t, size_t, size_t*) -> zx_status_t { device_invalid_fatal(ctx); };
+ ops.write = +[](void* ctx, const void*, size_t, size_t, size_t*) -> zx_status_t {
+ device_invalid_fatal(ctx);
+ };
+ ops.get_size = +[](void* ctx) -> zx_off_t { device_invalid_fatal(ctx); };
+ ops.ioctl = +[](void* ctx, uint32_t, const void*, size_t, void*, size_t, size_t*) -> zx_status_t {
+ device_invalid_fatal(ctx);
+ };
+ ops.suspend = +[](void* ctx, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
+ ops.resume = +[](void* ctx, uint32_t) -> zx_status_t { device_invalid_fatal(ctx); };
+ ops.rxrpc = +[](void* ctx, zx_handle_t) -> zx_status_t { device_invalid_fatal(ctx); };
+ ops.message =
+ +[](void* ctx, fidl_msg_t*, fidl_txn_t*) -> zx_status_t { device_invalid_fatal(ctx); };
+ return ops;
}();
// Maximum number of dead devices to hold on the dead device list
@@ -161,52 +146,52 @@
#define DEAD_DEVICE_MAX 7
void devhost_device_destroy(zx_device_t* dev) REQ_DM_LOCK {
- // Wrap the deferred-deletion list in a struct, so we can give it a proper
- // dtor. Otherwise, this causes the binary to crash on exit due to an
- // is_empty assert in fbl::DoublyLinkedList. This was particularly a
- // problem for unit tests.
- struct DeadList {
- ~DeadList() {
- while (!devices.is_empty()) {
- delete devices.pop_front();
- }
- }
- fbl::DoublyLinkedList<zx_device*, zx_device::Node> devices;
- };
-
- static DeadList dead_list;
- static unsigned dead_count = 0;
-
- // ensure any ops will be fatal
- dev->ops = &device_invalid_ops;
-
- dev->magic = 0xdeaddeaddeaddead;
-
- // ensure all owned handles are invalid
- dev->event.reset();
- dev->local_event.reset();
-
- // ensure all pointers are invalid
- dev->ctx = nullptr;
- dev->driver = nullptr;
- dev->parent.reset();
- dev->conn.store(nullptr);
- {
- fbl::AutoLock guard(&dev->proxy_ios_lock);
- dev->proxy_ios = nullptr;
+ // Wrap the deferred-deletion list in a struct, so we can give it a proper
+ // dtor. Otherwise, this causes the binary to crash on exit due to an
+ // is_empty assert in fbl::DoublyLinkedList. This was particularly a
+ // problem for unit tests.
+ struct DeadList {
+ ~DeadList() {
+ while (!devices.is_empty()) {
+ delete devices.pop_front();
+ }
}
+ fbl::DoublyLinkedList<zx_device*, zx_device::Node> devices;
+ };
- // Defer destruction to help catch use-after-free and also
- // so the compiler can't (easily) optimize away the poisoning
- // we do above.
- dead_list.devices.push_back(dev);
+ static DeadList dead_list;
+ static unsigned dead_count = 0;
- if (dead_count == DEAD_DEVICE_MAX) {
- zx_device_t* to_delete = dead_list.devices.pop_front();
- delete to_delete;
- } else {
- dead_count++;
- }
+ // ensure any ops will be fatal
+ dev->ops = &device_invalid_ops;
+
+ dev->magic = 0xdeaddeaddeaddead;
+
+ // ensure all owned handles are invalid
+ dev->event.reset();
+ dev->local_event.reset();
+
+ // ensure all pointers are invalid
+ dev->ctx = nullptr;
+ dev->driver = nullptr;
+ dev->parent.reset();
+ dev->conn.store(nullptr);
+ {
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
+ dev->proxy_ios = nullptr;
+ }
+
+ // Defer destruction to help catch use-after-free and also
+ // so the compiler can't (easily) optimize away the poisoning
+ // we do above.
+ dead_list.devices.push_back(dev);
+
+ if (dead_count == DEAD_DEVICE_MAX) {
+ zx_device_t* to_delete = dead_list.devices.pop_front();
+ delete to_delete;
+ } else {
+ dead_count++;
+ }
}
// defered work list
@@ -214,49 +199,49 @@
int devhost_enumerators = 0;
void devhost_finalize() {
- // Early exit if there's no work
- if (defer_device_list.is_empty()) {
- return;
+ // Early exit if there's no work
+ if (defer_device_list.is_empty()) {
+ return;
+ }
+
+ // Otherwise we snapshot the list
+ auto list = std::move(defer_device_list);
+
+ // We detach all the devices from their parents list-of-children
+ // while under the DM lock to avoid an enumerator starting to mutate
+ // things before we're done detaching them.
+ for (auto& dev : list) {
+ if (dev.parent) {
+ dev.parent->children.erase(dev);
+ }
+ }
+
+ // Then we can get to the actual final teardown where we have
+ // to drop the lock to call the callback
+ zx_device* dev;
+ while ((dev = list.pop_front()) != nullptr) {
+ // invoke release op
+ if (dev->flags & DEV_FLAG_ADDED) {
+ ApiAutoRelock relock;
+ dev->ReleaseOp();
}
- // Otherwise we snapshot the list
- auto list = std::move(defer_device_list);
+ if (dev->parent) {
+ // If the parent wants rebinding when its children are gone,
+ // And the parent is not dead, And this was the last child...
+ if ((dev->parent->flags & DEV_FLAG_WANTS_REBIND) && (!(dev->parent->flags & DEV_FLAG_DEAD)) &&
+ dev->parent->children.is_empty()) {
+ // Clear the wants rebind flag and request the rebind
+ dev->parent->flags &= (~DEV_FLAG_WANTS_REBIND);
+ devhost_device_bind(dev->parent, "");
+ }
- // We detach all the devices from their parents list-of-children
- // while under the DM lock to avoid an enumerator starting to mutate
- // things before we're done detaching them.
- for (auto& dev : list) {
- if (dev.parent) {
- dev.parent->children.erase(dev);
- }
+ dev->parent.reset();
}
- // Then we can get to the actual final teardown where we have
- // to drop the lock to call the callback
- zx_device* dev;
- while ((dev = list.pop_front()) != nullptr) {
- // invoke release op
- if (dev->flags & DEV_FLAG_ADDED) {
- ApiAutoRelock relock;
- dev->ReleaseOp();
- }
-
- if (dev->parent) {
- // If the parent wants rebinding when its children are gone,
- // And the parent is not dead, And this was the last child...
- if ((dev->parent->flags & DEV_FLAG_WANTS_REBIND) &&
- (!(dev->parent->flags & DEV_FLAG_DEAD)) && dev->parent->children.is_empty()) {
- // Clear the wants rebind flag and request the rebind
- dev->parent->flags &= (~DEV_FLAG_WANTS_REBIND);
- devhost_device_bind(dev->parent, "");
- }
-
- dev->parent.reset();
- }
-
- // destroy/deallocate the device
- devhost_device_destroy(dev);
- }
+ // destroy/deallocate the device
+ devhost_device_destroy(dev);
+ }
}
// enum_lock_{acquire,release}() are used whenever we're iterating
@@ -265,335 +250,331 @@
// legal to remove a child. This avoids badness when we have to
// drop the DM lock to call into device ops while enumerating.
-static void enum_lock_acquire() REQ_DM_LOCK {
- devhost_enumerators++;
-}
+static void enum_lock_acquire() REQ_DM_LOCK { devhost_enumerators++; }
static void enum_lock_release() REQ_DM_LOCK {
- if (--devhost_enumerators == 0) {
- devhost_finalize();
- }
+ if (--devhost_enumerators == 0) {
+ devhost_finalize();
+ }
}
zx_status_t devhost_device_create(zx_driver_t* drv, const char* name, void* ctx,
const zx_protocol_device_t* ops,
fbl::RefPtr<zx_device_t>* out) REQ_DM_LOCK {
+ if (!drv) {
+ printf("devhost: device_add could not find driver!\n");
+ return ZX_ERR_INVALID_ARGS;
+ }
- if (!drv) {
- printf("devhost: device_add could not find driver!\n");
- return ZX_ERR_INVALID_ARGS;
- }
+ fbl::RefPtr<zx_device> dev;
+ zx_status_t status = zx_device::Create(&dev);
+ if (status != ZX_OK) {
+ return status;
+ }
- fbl::RefPtr<zx_device> dev;
- zx_status_t status = zx_device::Create(&dev);
- if (status != ZX_OK) {
- return status;
- }
+ dev->ops = ops;
+ dev->driver = drv;
- dev->ops = ops;
- dev->driver = drv;
+ if (name == nullptr) {
+ printf("devhost: dev=%p has null name.\n", dev.get());
+ name = "invalid";
+ dev->magic = 0;
+ }
- if (name == nullptr) {
- printf("devhost: dev=%p has null name.\n", dev.get());
- name = "invalid";
- dev->magic = 0;
- }
+ size_t len = strlen(name);
+ // TODO(teisenbe): I think this is overly aggresive, and could be changed
+ // to |len > ZX_DEVICE_NAME_MAX| and |len = ZX_DEVICE_NAME_MAX|.
+ if (len >= ZX_DEVICE_NAME_MAX) {
+ printf("devhost: dev=%p name too large '%s'\n", dev.get(), name);
+ len = ZX_DEVICE_NAME_MAX - 1;
+ dev->magic = 0;
+ }
- size_t len = strlen(name);
- // TODO(teisenbe): I think this is overly aggresive, and could be changed
- // to |len > ZX_DEVICE_NAME_MAX| and |len = ZX_DEVICE_NAME_MAX|.
- if (len >= ZX_DEVICE_NAME_MAX) {
- printf("devhost: dev=%p name too large '%s'\n", dev.get(), name);
- len = ZX_DEVICE_NAME_MAX - 1;
- dev->magic = 0;
- }
-
- memcpy(dev->name, name, len);
- dev->name[len] = 0;
- // TODO(teisenbe): Why do we default to dev.get() here? Why not just
- // nullptr
- dev->ctx = ctx ? ctx : dev.get();
- *out = std::move(dev);
- return ZX_OK;
+ memcpy(dev->name, name, len);
+ dev->name[len] = 0;
+ // TODO(teisenbe): Why do we default to dev.get() here? Why not just
+ // nullptr
+ dev->ctx = ctx ? ctx : dev.get();
+ *out = std::move(dev);
+ return ZX_OK;
}
static zx_status_t device_validate(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK {
- if (dev == nullptr) {
- printf("INVAL: nullptr!\n");
- return ZX_ERR_INVALID_ARGS;
- }
- if (dev->flags & DEV_FLAG_ADDED) {
- printf("device already added: %p(%s)\n", dev.get(), dev->name);
- return ZX_ERR_BAD_STATE;
- }
- if (dev->magic != DEV_MAGIC) {
- return ZX_ERR_BAD_STATE;
- }
- if (dev->ops == nullptr) {
- printf("device add: %p(%s): nullptr ops\n", dev.get(), dev->name);
- return ZX_ERR_INVALID_ARGS;
- }
- if ((dev->protocol_id == ZX_PROTOCOL_MISC_PARENT) || (dev->protocol_id == ZX_PROTOCOL_ROOT)) {
- // These protocols is only allowed for the special
- // singleton misc or root parent devices.
- return ZX_ERR_INVALID_ARGS;
- }
- // devices which do not declare a primary protocol
- // are implied to be misc devices
- if (dev->protocol_id == 0) {
- dev->protocol_id = ZX_PROTOCOL_MISC;
- }
+ if (dev == nullptr) {
+ printf("INVAL: nullptr!\n");
+ return ZX_ERR_INVALID_ARGS;
+ }
+ if (dev->flags & DEV_FLAG_ADDED) {
+ printf("device already added: %p(%s)\n", dev.get(), dev->name);
+ return ZX_ERR_BAD_STATE;
+ }
+ if (dev->magic != DEV_MAGIC) {
+ return ZX_ERR_BAD_STATE;
+ }
+ if (dev->ops == nullptr) {
+ printf("device add: %p(%s): nullptr ops\n", dev.get(), dev->name);
+ return ZX_ERR_INVALID_ARGS;
+ }
+ if ((dev->protocol_id == ZX_PROTOCOL_MISC_PARENT) || (dev->protocol_id == ZX_PROTOCOL_ROOT)) {
+ // These protocols is only allowed for the special
+ // singleton misc or root parent devices.
+ return ZX_ERR_INVALID_ARGS;
+ }
+ // devices which do not declare a primary protocol
+ // are implied to be misc devices
+ if (dev->protocol_id == 0) {
+ dev->protocol_id = ZX_PROTOCOL_MISC;
+ }
- return ZX_OK;
+ return ZX_OK;
}
zx_status_t devhost_device_add(const fbl::RefPtr<zx_device_t>& dev,
const fbl::RefPtr<zx_device_t>& parent,
const zx_device_prop_t* props, uint32_t prop_count,
const char* proxy_args, zx::channel client_remote) REQ_DM_LOCK {
- auto mark_dead = fbl::MakeAutoCall([&dev]() {
- if (dev) {
- dev->flags |= DEV_FLAG_DEAD | DEV_FLAG_VERY_DEAD;
- }
- });
+ auto mark_dead = fbl::MakeAutoCall([&dev]() {
+ if (dev) {
+ dev->flags |= DEV_FLAG_DEAD | DEV_FLAG_VERY_DEAD;
+ }
+ });
- zx_status_t status;
- if ((status = device_validate(dev)) < 0) {
- return status;
- }
- if (parent == nullptr) {
- printf("device_add: cannot add %p(%s) to nullptr parent\n", dev.get(), dev->name);
- return ZX_ERR_NOT_SUPPORTED;
- }
- if (parent->flags & DEV_FLAG_DEAD) {
- printf("device add: %p: is dead, cannot add child %p\n", parent.get(), dev.get());
- return ZX_ERR_BAD_STATE;
- }
+ zx_status_t status;
+ if ((status = device_validate(dev)) < 0) {
+ return status;
+ }
+ if (parent == nullptr) {
+ printf("device_add: cannot add %p(%s) to nullptr parent\n", dev.get(), dev->name);
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+ if (parent->flags & DEV_FLAG_DEAD) {
+ printf("device add: %p: is dead, cannot add child %p\n", parent.get(), dev.get());
+ return ZX_ERR_BAD_STATE;
+ }
- BindContext* bind_ctx = nullptr;
- CreationContext* creation_ctx = nullptr;
+ BindContext* bind_ctx = nullptr;
+ CreationContext* creation_ctx = nullptr;
- // If the bind or creation ctx (thread locals) are set, we are in
- // a thread that is handling a bind() or create() callback and if
- // that ctx's parent matches the one provided to add we need to do
- // some additional checking...
- if ((g_bind_context != nullptr) && (g_bind_context->parent == parent)) {
- bind_ctx = g_bind_context;
+ // If the bind or creation ctx (thread locals) are set, we are in
+ // a thread that is handling a bind() or create() callback and if
+ // that ctx's parent matches the one provided to add we need to do
+ // some additional checking...
+ if ((g_bind_context != nullptr) && (g_bind_context->parent == parent)) {
+ bind_ctx = g_bind_context;
+ }
+ if ((g_creation_context != nullptr) && (g_creation_context->parent == parent)) {
+ creation_ctx = g_creation_context;
+ // create() must create only one child
+ if (creation_ctx->child != nullptr) {
+ printf("devhost: driver attempted to create multiple proxy devices!\n");
+ return ZX_ERR_BAD_STATE;
}
- if ((g_creation_context != nullptr) && (g_creation_context->parent == parent)) {
- creation_ctx = g_creation_context;
- // create() must create only one child
- if (creation_ctx->child != nullptr) {
- printf("devhost: driver attempted to create multiple proxy devices!\n");
- return ZX_ERR_BAD_STATE;
- }
- }
+ }
#if TRACE_ADD_REMOVE
- printf("devhost: device add: %p(%s) parent=%p(%s)\n", dev.get(), dev->name, parent.get(),
- parent->name);
+ printf("devhost: device add: %p(%s) parent=%p(%s)\n", dev.get(), dev->name, parent.get(),
+ parent->name);
#endif
- // Don't create an event handle if we alredy have one
- if (!dev->event.is_valid() &&
- ((status = zx::eventpair::create(0, &dev->event, &dev->local_event)) < 0)) {
- printf("device add: %p(%s): cannot create event: %d\n", dev.get(), dev->name, status);
- return status;
- }
+ // Don't create an event handle if we alredy have one
+ if (!dev->event.is_valid() &&
+ ((status = zx::eventpair::create(0, &dev->event, &dev->local_event)) < 0)) {
+ printf("device add: %p(%s): cannot create event: %d\n", dev.get(), dev->name, status);
+ return status;
+ }
- dev->flags |= DEV_FLAG_BUSY;
+ dev->flags |= DEV_FLAG_BUSY;
- // proxy devices are created through this handshake process
- if (creation_ctx) {
- if (dev->flags & DEV_FLAG_INVISIBLE) {
- printf("devhost: driver attempted to create invisible device in create()\n");
- return ZX_ERR_INVALID_ARGS;
- }
- dev->flags |= DEV_FLAG_ADDED;
- dev->flags &= (~DEV_FLAG_BUSY);
- dev->rpc = zx::unowned_channel(creation_ctx->rpc);
- creation_ctx->child = dev;
- mark_dead.cancel();
- return ZX_OK;
- }
-
- dev->parent = parent;
-
- // attach to our parent
- parent->children.push_back(dev.get());
-
- if (!(dev->flags & DEV_FLAG_INSTANCE)) {
- // devhost_add always consumes the handle
- status = devhost_add(parent, dev, proxy_args, props, prop_count, std::move(client_remote));
- if (status < 0) {
- printf("devhost: %p(%s): remote add failed %d\n", dev.get(), dev->name, status);
- dev->parent->children.erase(*dev);
- dev->parent.reset();
-
- // since we are under the lock the whole time, we added the node
- // to the tail and then we peeled it back off the tail when we
- // failed, we don't need to interact with the enum lock mechanism
- dev->flags &= (~DEV_FLAG_BUSY);
- return status;
- }
+ // proxy devices are created through this handshake process
+ if (creation_ctx) {
+ if (dev->flags & DEV_FLAG_INVISIBLE) {
+ printf("devhost: driver attempted to create invisible device in create()\n");
+ return ZX_ERR_INVALID_ARGS;
}
dev->flags |= DEV_FLAG_ADDED;
dev->flags &= (~DEV_FLAG_BUSY);
-
- // record this device in the bind context if there is one
- if (bind_ctx && (bind_ctx->child == nullptr)) {
- bind_ctx->child = dev;
- }
+ dev->rpc = zx::unowned_channel(creation_ctx->rpc);
+ creation_ctx->child = dev;
mark_dead.cancel();
return ZX_OK;
+ }
+
+ dev->parent = parent;
+
+ // attach to our parent
+ parent->children.push_back(dev.get());
+
+ if (!(dev->flags & DEV_FLAG_INSTANCE)) {
+ // devhost_add always consumes the handle
+ status = devhost_add(parent, dev, proxy_args, props, prop_count, std::move(client_remote));
+ if (status < 0) {
+ printf("devhost: %p(%s): remote add failed %d\n", dev.get(), dev->name, status);
+ dev->parent->children.erase(*dev);
+ dev->parent.reset();
+
+ // since we are under the lock the whole time, we added the node
+ // to the tail and then we peeled it back off the tail when we
+ // failed, we don't need to interact with the enum lock mechanism
+ dev->flags &= (~DEV_FLAG_BUSY);
+ return status;
+ }
+ }
+ dev->flags |= DEV_FLAG_ADDED;
+ dev->flags &= (~DEV_FLAG_BUSY);
+
+ // record this device in the bind context if there is one
+ if (bind_ctx && (bind_ctx->child == nullptr)) {
+ bind_ctx->child = dev;
+ }
+ mark_dead.cancel();
+ return ZX_OK;
}
#define REMOVAL_BAD_FLAGS (DEV_FLAG_DEAD | DEV_FLAG_BUSY | DEV_FLAG_INSTANCE | DEV_FLAG_MULTI_BIND)
static const char* removal_problem(uint32_t flags) {
- if (flags & DEV_FLAG_DEAD) {
- return "already dead";
- }
- if (flags & DEV_FLAG_BUSY) {
- return "being created";
- }
- if (flags & DEV_FLAG_INSTANCE) {
- return "ephemeral device";
- }
- if (flags & DEV_FLAG_MULTI_BIND) {
- return "multi-bind-able device";
- }
- return "?";
+ if (flags & DEV_FLAG_DEAD) {
+ return "already dead";
+ }
+ if (flags & DEV_FLAG_BUSY) {
+ return "being created";
+ }
+ if (flags & DEV_FLAG_INSTANCE) {
+ return "ephemeral device";
+ }
+ if (flags & DEV_FLAG_MULTI_BIND) {
+ return "multi-bind-able device";
+ }
+ return "?";
}
static void devhost_unbind_children(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK {
#if TRACE_ADD_REMOVE
- printf("devhost_unbind_children: %p(%s)\n", dev.get(), dev->name);
+ printf("devhost_unbind_children: %p(%s)\n", dev.get(), dev->name);
#endif
- enum_lock_acquire();
- for (auto& child : dev->children) {
- if (!(child.flags & DEV_FLAG_DEAD)) {
- // Try to get a reference to the child. This will fail if the last
- // reference to it went away and fbl_recycle() is going to blocked
- // waiting for the DM lock
- auto child_ref =
- fbl::MakeRefPtrUpgradeFromRaw(&child, &::devmgr::internal::devhost_api_lock);
- if (child_ref) {
- devhost_device_unbind(std::move(child_ref));
- }
- }
+ enum_lock_acquire();
+ for (auto& child : dev->children) {
+ if (!(child.flags & DEV_FLAG_DEAD)) {
+ // Try to get a reference to the child. This will fail if the last
+ // reference to it went away and fbl_recycle() is going to blocked
+ // waiting for the DM lock
+ auto child_ref = fbl::MakeRefPtrUpgradeFromRaw(&child, &::devmgr::internal::devhost_api_lock);
+ if (child_ref) {
+ devhost_device_unbind(std::move(child_ref));
+ }
}
+ }
- fbl::RefPtr<CompositeDevice> composite = dev->take_composite();
- if (composite) {
- fbl::RefPtr<zx_device_t> child = composite->Detach();
- if (child && !(child->flags & DEV_FLAG_DEAD)) {
- devhost_device_unbind(std::move(child));
- }
+ fbl::RefPtr<CompositeDevice> composite = dev->take_composite();
+ if (composite) {
+ fbl::RefPtr<zx_device_t> child = composite->Detach();
+ if (child && !(child->flags & DEV_FLAG_DEAD)) {
+ devhost_device_unbind(std::move(child));
}
+ }
- enum_lock_release();
+ enum_lock_release();
}
zx_status_t devhost_device_remove(fbl::RefPtr<zx_device_t> dev) REQ_DM_LOCK {
- if (dev->flags & REMOVAL_BAD_FLAGS) {
- printf("device: %p(%s): cannot be removed (%s)\n", dev.get(), dev->name,
- removal_problem(dev->flags));
- return ZX_ERR_INVALID_ARGS;
- }
+ if (dev->flags & REMOVAL_BAD_FLAGS) {
+ printf("device: %p(%s): cannot be removed (%s)\n", dev.get(), dev->name,
+ removal_problem(dev->flags));
+ return ZX_ERR_INVALID_ARGS;
+ }
#if TRACE_ADD_REMOVE
- printf("device: %p(%s): is being removed\n", dev.get(), dev->name);
+ printf("device: %p(%s): is being removed\n", dev.get(), dev->name);
#endif
- dev->flags |= DEV_FLAG_DEAD;
+ dev->flags |= DEV_FLAG_DEAD;
- devhost_unbind_children(dev);
+ devhost_unbind_children(dev);
- // cause the vfs entry to be unpublished to avoid further open() attempts
- xprintf("device: %p: devhost->devmgr remove rpc\n", dev.get());
- devhost_remove(dev);
+ // cause the vfs entry to be unpublished to avoid further open() attempts
+ xprintf("device: %p: devhost->devmgr remove rpc\n", dev.get());
+ devhost_remove(dev);
- dev->flags |= DEV_FLAG_VERY_DEAD;
- return ZX_OK;
+ dev->flags |= DEV_FLAG_VERY_DEAD;
+ return ZX_OK;
}
zx_status_t devhost_device_rebind(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK {
- // note that we want to be rebound when our children are all gone
- dev->flags |= DEV_FLAG_WANTS_REBIND;
+ // note that we want to be rebound when our children are all gone
+ dev->flags |= DEV_FLAG_WANTS_REBIND;
- // request that any existing children go away
- devhost_unbind_children(dev);
+ // request that any existing children go away
+ devhost_unbind_children(dev);
- return ZX_OK;
+ return ZX_OK;
}
zx_status_t devhost_device_unbind(const fbl::RefPtr<zx_device_t>& dev) REQ_DM_LOCK {
- if (!(dev->flags & DEV_FLAG_UNBOUND)) {
- dev->flags |= DEV_FLAG_UNBOUND;
- // Call dev's unbind op.
- if (dev->ops->unbind) {
+ if (!(dev->flags & DEV_FLAG_UNBOUND)) {
+ dev->flags |= DEV_FLAG_UNBOUND;
+ // Call dev's unbind op.
+ if (dev->ops->unbind) {
#if TRACE_ADD_REMOVE
- printf("call unbind dev: %p(%s)\n", dev.get(), dev->name);
+ printf("call unbind dev: %p(%s)\n", dev.get(), dev->name);
#endif
- ApiAutoRelock relock;
- dev->UnbindOp();
- }
+ ApiAutoRelock relock;
+ dev->UnbindOp();
}
- return ZX_OK;
+ }
+ return ZX_OK;
}
zx_status_t devhost_device_open(const fbl::RefPtr<zx_device_t>& dev, fbl::RefPtr<zx_device_t>* out,
uint32_t flags) REQ_DM_LOCK {
- if (dev->flags & DEV_FLAG_DEAD) {
- printf("device open: %p(%s) is dead!\n", dev.get(), dev->name);
- return ZX_ERR_BAD_STATE;
- }
- fbl::RefPtr<zx_device_t> new_ref(dev);
- zx_status_t r;
- zx_device_t* opened_dev = nullptr;
- {
- ApiAutoRelock relock;
- r = dev->OpenOp(&opened_dev, flags);
- }
- if (r < 0) {
- new_ref.reset();
- } else if (opened_dev != nullptr) {
- // open created a per-instance device for us
- new_ref.reset();
- // Claim the reference from open
- new_ref = fbl::internal::MakeRefPtrNoAdopt(opened_dev);
+ if (dev->flags & DEV_FLAG_DEAD) {
+ printf("device open: %p(%s) is dead!\n", dev.get(), dev->name);
+ return ZX_ERR_BAD_STATE;
+ }
+ fbl::RefPtr<zx_device_t> new_ref(dev);
+ zx_status_t r;
+ zx_device_t* opened_dev = nullptr;
+ {
+ ApiAutoRelock relock;
+ r = dev->OpenOp(&opened_dev, flags);
+ }
+ if (r < 0) {
+ new_ref.reset();
+ } else if (opened_dev != nullptr) {
+ // open created a per-instance device for us
+ new_ref.reset();
+ // Claim the reference from open
+ new_ref = fbl::internal::MakeRefPtrNoAdopt(opened_dev);
- if (!(opened_dev->flags & DEV_FLAG_INSTANCE)) {
- printf("device open: %p(%s) in bad state %x\n", opened_dev, opened_dev->name, flags);
- panic();
- }
+ if (!(opened_dev->flags & DEV_FLAG_INSTANCE)) {
+ printf("device open: %p(%s) in bad state %x\n", opened_dev, opened_dev->name, flags);
+ panic();
}
- *out = std::move(new_ref);
- return r;
+ }
+ *out = std::move(new_ref);
+ return r;
}
zx_status_t devhost_device_close(fbl::RefPtr<zx_device_t> dev, uint32_t flags) REQ_DM_LOCK {
- ApiAutoRelock relock;
- return dev->CloseOp(flags);
+ ApiAutoRelock relock;
+ return dev->CloseOp(flags);
}
zx_status_t devhost_device_suspend(const fbl::RefPtr<zx_device>& dev, uint32_t flags) REQ_DM_LOCK {
- // TODO this should eventually be two-pass using SUSPENDING/SUSPENDED flags
- enum_lock_acquire();
+ // TODO this should eventually be two-pass using SUSPENDING/SUSPENDED flags
+ enum_lock_acquire();
- zx_status_t status = ZX_ERR_NOT_SUPPORTED;
- // then invoke our suspend hook
- if (dev->ops->suspend) {
- ApiAutoRelock relock;
- status = dev->ops->suspend(dev->ctx, flags);
- }
+ zx_status_t status = ZX_ERR_NOT_SUPPORTED;
+ // then invoke our suspend hook
+ if (dev->ops->suspend) {
+ ApiAutoRelock relock;
+ status = dev->ops->suspend(dev->ctx, flags);
+ }
- enum_lock_release();
+ enum_lock_release();
- // default_suspend() returns ZX_ERR_NOT_SUPPORTED
- if ((status != ZX_OK) && (status != ZX_ERR_NOT_SUPPORTED)) {
- return status;
- }
- return ZX_OK;
+ // default_suspend() returns ZX_ERR_NOT_SUPPORTED
+ if ((status != ZX_OK) && (status != ZX_ERR_NOT_SUPPORTED)) {
+ return status;
+ }
+ return ZX_OK;
}
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/devhost.cc b/zircon/system/core/devmgr/devhost/devhost.cc
index 101eaec..d1a973e 100644
--- a/zircon/system/core/devmgr/devhost/devhost.cc
+++ b/zircon/system/core/devmgr/devhost/devhost.cc
@@ -4,34 +4,18 @@
#include "devhost.h"
-#include <dlfcn.h>
-#include <inttypes.h>
-#include <new>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <utility>
-
#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
-
-#include <zircon/dlfcn.h>
-#include <zircon/process.h>
-#include <zircon/processargs.h>
-#include <zircon/status.h>
-#include <zircon/syscalls.h>
-#include <zircon/syscalls/log.h>
-
+#include <dlfcn.h>
#include <fbl/auto_lock.h>
#include <fbl/function.h>
#include <fs/handler.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/device/manager/llcpp/fidl.h>
#include <fuchsia/io/c/fidl.h>
+#include <inttypes.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/receiver.h>
#include <lib/async/cpp/wait.h>
@@ -41,6 +25,20 @@
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <lib/zxio/null.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <zircon/dlfcn.h>
+#include <zircon/process.h>
+#include <zircon/processargs.h>
+#include <zircon/status.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/log.h>
+
+#include <new>
+#include <utility>
#include "../shared/async-loop-owned-rpc-handler.h"
#include "../shared/env.h"
@@ -55,8 +53,8 @@
#include "tracing.h"
zx_status_t zx_driver::Create(fbl::RefPtr<zx_driver>* out_driver) {
- *out_driver = fbl::AdoptRef(new zx_driver());
- return ZX_OK;
+ *out_driver = fbl::AdoptRef(new zx_driver());
+ return ZX_OK;
}
namespace devmgr {
@@ -67,453 +65,444 @@
// Access the devhost's async event loop
async::Loop* DevhostAsyncLoop() {
- static async::Loop loop(&kAsyncLoopConfigAttachToThread);
- return &loop;
+ static async::Loop loop(&kAsyncLoopConfigAttachToThread);
+ return &loop;
}
static zx_status_t SetupRootDevcoordinatorConnection(zx::channel ch) {
- auto conn = std::make_unique<DevhostControllerConnection>();
- if (conn == nullptr) {
- return ZX_ERR_NO_MEMORY;
- }
+ auto conn = std::make_unique<DevhostControllerConnection>();
+ if (conn == nullptr) {
+ return ZX_ERR_NO_MEMORY;
+ }
- conn->set_channel(std::move(ch));
- return DevhostControllerConnection::BeginWait(std::move(conn),
- DevhostAsyncLoop()->dispatcher());
+ conn->set_channel(std::move(ch));
+ return DevhostControllerConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
}
const char* mkdevpath(const fbl::RefPtr<zx_device_t>& dev, char* path, size_t max) {
- if (dev == nullptr) {
- return "";
- }
- if (max < 1) {
- return "<invalid>";
- }
- char* end = path + max;
- char sep = 0;
+ if (dev == nullptr) {
+ return "";
+ }
+ if (max < 1) {
+ return "<invalid>";
+ }
+ char* end = path + max;
+ char sep = 0;
- fbl::RefPtr<zx_device> itr_dev(dev);
- while (itr_dev) {
- *(--end) = sep;
+ fbl::RefPtr<zx_device> itr_dev(dev);
+ while (itr_dev) {
+ *(--end) = sep;
- size_t len = strlen(itr_dev->name);
- if (len > (size_t)(end - path)) {
- break;
- }
- end -= len;
- memcpy(end, itr_dev->name, len);
- sep = '/';
- itr_dev = itr_dev->parent;
+ size_t len = strlen(itr_dev->name);
+ if (len > (size_t)(end - path)) {
+ break;
}
- return end;
+ end -= len;
+ memcpy(end, itr_dev->name, len);
+ sep = '/';
+ itr_dev = itr_dev->parent;
+ }
+ return end;
}
static uint32_t logflagval(char* flag) {
- if (!strcmp(flag, "error")) {
- return DDK_LOG_ERROR;
- }
- if (!strcmp(flag, "warn")) {
- return DDK_LOG_WARN;
- }
- if (!strcmp(flag, "info")) {
- return DDK_LOG_INFO;
- }
- if (!strcmp(flag, "trace")) {
- return DDK_LOG_TRACE;
- }
- if (!strcmp(flag, "spew")) {
- return DDK_LOG_SPEW;
- }
- if (!strcmp(flag, "debug1")) {
- return DDK_LOG_DEBUG1;
- }
- if (!strcmp(flag, "debug2")) {
- return DDK_LOG_DEBUG2;
- }
- if (!strcmp(flag, "debug3")) {
- return DDK_LOG_DEBUG3;
- }
- if (!strcmp(flag, "debug4")) {
- return DDK_LOG_DEBUG4;
- }
- return static_cast<uint32_t>(strtoul(flag, nullptr, 0));
+ if (!strcmp(flag, "error")) {
+ return DDK_LOG_ERROR;
+ }
+ if (!strcmp(flag, "warn")) {
+ return DDK_LOG_WARN;
+ }
+ if (!strcmp(flag, "info")) {
+ return DDK_LOG_INFO;
+ }
+ if (!strcmp(flag, "trace")) {
+ return DDK_LOG_TRACE;
+ }
+ if (!strcmp(flag, "spew")) {
+ return DDK_LOG_SPEW;
+ }
+ if (!strcmp(flag, "debug1")) {
+ return DDK_LOG_DEBUG1;
+ }
+ if (!strcmp(flag, "debug2")) {
+ return DDK_LOG_DEBUG2;
+ }
+ if (!strcmp(flag, "debug3")) {
+ return DDK_LOG_DEBUG3;
+ }
+ if (!strcmp(flag, "debug4")) {
+ return DDK_LOG_DEBUG4;
+ }
+ return static_cast<uint32_t>(strtoul(flag, nullptr, 0));
}
static void logflag(char* flag, uint32_t* flags) {
- if (*flag == '+') {
- *flags |= logflagval(flag + 1);
- } else if (*flag == '-') {
- *flags &= ~logflagval(flag + 1);
- }
+ if (*flag == '+') {
+ *flags |= logflagval(flag + 1);
+ } else if (*flag == '-') {
+ *flags &= ~logflagval(flag + 1);
+ }
}
zx_status_t dh_find_driver(fbl::StringPiece libname, zx::vmo vmo, fbl::RefPtr<zx_driver_t>* out) {
- // check for already-loaded driver first
- for (auto& drv : dh_drivers) {
- if (!libname.compare(drv.libname())) {
- *out = fbl::RefPtr(&drv);
- return drv.status();
- }
+ // check for already-loaded driver first
+ for (auto& drv : dh_drivers) {
+ if (!libname.compare(drv.libname())) {
+ *out = fbl::RefPtr(&drv);
+ return drv.status();
}
+ }
- fbl::RefPtr<zx_driver> new_driver;
- zx_status_t status = zx_driver::Create(&new_driver);
- if (status != ZX_OK) {
- return status;
- }
- new_driver->set_libname(libname);
+ fbl::RefPtr<zx_driver> new_driver;
+ zx_status_t status = zx_driver::Create(&new_driver);
+ if (status != ZX_OK) {
+ return status;
+ }
+ new_driver->set_libname(libname);
- // Let the |dh_drivers| list and our out parameter each have a refcount.
- dh_drivers.push_back(new_driver);
- *out = new_driver;
+ // Let the |dh_drivers| list and our out parameter each have a refcount.
+ dh_drivers.push_back(new_driver);
+ *out = new_driver;
- const char* c_libname = new_driver->libname().c_str();
+ const char* c_libname = new_driver->libname().c_str();
- void* dl = dlopen_vmo(vmo.get(), RTLD_NOW);
- if (dl == nullptr) {
- log(ERROR, "devhost: cannot load '%s': %s\n", c_libname, dlerror());
- new_driver->set_status(ZX_ERR_IO);
- return new_driver->status();
- }
-
- auto dn = static_cast<const zircon_driver_note_t*>(dlsym(dl, "__zircon_driver_note__"));
- if (dn == nullptr) {
- log(ERROR, "devhost: driver '%s' missing __zircon_driver_note__ symbol\n", c_libname);
- new_driver->set_status(ZX_ERR_IO);
- return new_driver->status();
- }
- auto ops = static_cast<const zx_driver_ops_t**>(dlsym(dl, "__zircon_driver_ops__"));
- auto dr = static_cast<zx_driver_rec_t*>(dlsym(dl, "__zircon_driver_rec__"));
- if (dr == nullptr) {
- log(ERROR, "devhost: driver '%s' missing __zircon_driver_rec__ symbol\n", c_libname);
- new_driver->set_status(ZX_ERR_IO);
- return new_driver->status();
- }
- // TODO(kulakowski) Eventually just check __zircon_driver_ops__,
- // when bind programs are standalone.
- if (ops == nullptr) {
- ops = &dr->ops;
- }
- if (!(*ops)) {
- log(ERROR, "devhost: driver '%s' has nullptr ops\n", c_libname);
- new_driver->set_status(ZX_ERR_INVALID_ARGS);
- return new_driver->status();
- }
- if ((*ops)->version != DRIVER_OPS_VERSION) {
- log(ERROR,
- "devhost: driver '%s' has bad driver ops version %" PRIx64 ", expecting %" PRIx64 "\n",
- c_libname, (*ops)->version, DRIVER_OPS_VERSION);
- new_driver->set_status(ZX_ERR_INVALID_ARGS);
- return new_driver->status();
- }
-
- new_driver->set_driver_rec(dr);
- new_driver->set_name(dn->payload.name);
- new_driver->set_ops(*ops);
- dr->driver = new_driver.get();
-
- // check for dprintf log level flags
- char tmp[128];
- snprintf(tmp, sizeof(tmp), "driver.%s.log", new_driver->name());
- char* log = getenv(tmp);
- if (log) {
- while (log) {
- char* sep = strchr(log, ',');
- if (sep) {
- *sep = 0;
- logflag(log, &dr->log_flags);
- *sep = ',';
- log = sep + 1;
- } else {
- logflag(log, &dr->log_flags);
- break;
- }
- }
- log(INFO, "devhost: driver '%s': log flags set to: 0x%x\n", new_driver->name(),
- dr->log_flags);
- }
-
- if (new_driver->has_init_op()) {
- new_driver->set_status(new_driver->InitOp());
- if (new_driver->status() != ZX_OK) {
- log(ERROR, "devhost: driver '%s' failed in init: %d\n", c_libname,
- new_driver->status());
- }
- } else {
- new_driver->set_status(ZX_OK);
- }
-
+ void* dl = dlopen_vmo(vmo.get(), RTLD_NOW);
+ if (dl == nullptr) {
+ log(ERROR, "devhost: cannot load '%s': %s\n", c_libname, dlerror());
+ new_driver->set_status(ZX_ERR_IO);
return new_driver->status();
+ }
+
+ auto dn = static_cast<const zircon_driver_note_t*>(dlsym(dl, "__zircon_driver_note__"));
+ if (dn == nullptr) {
+ log(ERROR, "devhost: driver '%s' missing __zircon_driver_note__ symbol\n", c_libname);
+ new_driver->set_status(ZX_ERR_IO);
+ return new_driver->status();
+ }
+ auto ops = static_cast<const zx_driver_ops_t**>(dlsym(dl, "__zircon_driver_ops__"));
+ auto dr = static_cast<zx_driver_rec_t*>(dlsym(dl, "__zircon_driver_rec__"));
+ if (dr == nullptr) {
+ log(ERROR, "devhost: driver '%s' missing __zircon_driver_rec__ symbol\n", c_libname);
+ new_driver->set_status(ZX_ERR_IO);
+ return new_driver->status();
+ }
+ // TODO(kulakowski) Eventually just check __zircon_driver_ops__,
+ // when bind programs are standalone.
+ if (ops == nullptr) {
+ ops = &dr->ops;
+ }
+ if (!(*ops)) {
+ log(ERROR, "devhost: driver '%s' has nullptr ops\n", c_libname);
+ new_driver->set_status(ZX_ERR_INVALID_ARGS);
+ return new_driver->status();
+ }
+ if ((*ops)->version != DRIVER_OPS_VERSION) {
+ log(ERROR,
+ "devhost: driver '%s' has bad driver ops version %" PRIx64 ", expecting %" PRIx64 "\n",
+ c_libname, (*ops)->version, DRIVER_OPS_VERSION);
+ new_driver->set_status(ZX_ERR_INVALID_ARGS);
+ return new_driver->status();
+ }
+
+ new_driver->set_driver_rec(dr);
+ new_driver->set_name(dn->payload.name);
+ new_driver->set_ops(*ops);
+ dr->driver = new_driver.get();
+
+ // check for dprintf log level flags
+ char tmp[128];
+ snprintf(tmp, sizeof(tmp), "driver.%s.log", new_driver->name());
+ char* log = getenv(tmp);
+ if (log) {
+ while (log) {
+ char* sep = strchr(log, ',');
+ if (sep) {
+ *sep = 0;
+ logflag(log, &dr->log_flags);
+ *sep = ',';
+ log = sep + 1;
+ } else {
+ logflag(log, &dr->log_flags);
+ break;
+ }
+ }
+ log(INFO, "devhost: driver '%s': log flags set to: 0x%x\n", new_driver->name(), dr->log_flags);
+ }
+
+ if (new_driver->has_init_op()) {
+ new_driver->set_status(new_driver->InitOp());
+ if (new_driver->status() != ZX_OK) {
+ log(ERROR, "devhost: driver '%s' failed in init: %d\n", c_libname, new_driver->status());
+ }
+ } else {
+ new_driver->set_status(ZX_OK);
+ }
+
+ return new_driver->status();
}
-void DevhostControllerConnection::CreateDevice(zx::channel rpc,
- ::fidl::StringView driver_path_view,
- ::zx::vmo driver_vmo,
- ::zx::handle parent_proxy,
+void DevhostControllerConnection::CreateDevice(zx::channel rpc, ::fidl::StringView driver_path_view,
+ ::zx::vmo driver_vmo, ::zx::handle parent_proxy,
::fidl::StringView proxy_args,
uint64_t local_device_id,
CreateDeviceCompleter::Sync completer) {
+ fbl::StringPiece driver_path(driver_path_view.data(), driver_path_view.size());
+ // This does not operate under the devhost api lock,
+ // since the newly created device is not visible to
+ // any API surface until a driver is bound to it.
+ // (which can only happen via another message on this thread)
+ log(RPC_IN, "devhost: create device drv='%.*s' args='%.*s'\n",
+ static_cast<int>(driver_path.size()), driver_path.data(), static_cast<int>(proxy_args.size()),
+ proxy_args.data());
- fbl::StringPiece driver_path(driver_path_view.data(), driver_path_view.size());
- // This does not operate under the devhost api lock,
- // since the newly created device is not visible to
- // any API surface until a driver is bound to it.
- // (which can only happen via another message on this thread)
- log(RPC_IN, "devhost: create device drv='%.*s' args='%.*s'\n",
- static_cast<int>(driver_path.size()), driver_path.data(), static_cast<int>(proxy_args.size()),
- proxy_args.data());
+ // named driver -- ask it to create the device
+ fbl::RefPtr<zx_driver_t> drv;
+ zx_status_t r = dh_find_driver(driver_path, std::move(driver_vmo), &drv);
+ if (r != ZX_OK) {
+ log(ERROR, "devhost: driver load failed: %d\n", r);
+ return;
+ }
+ if (!drv->has_create_op()) {
+ log(ERROR, "devhost: driver create() not supported\n");
+ return;
+ }
- // named driver -- ask it to create the device
- fbl::RefPtr<zx_driver_t> drv;
- zx_status_t r = dh_find_driver(driver_path, std::move(driver_vmo), &drv);
- if (r != ZX_OK) {
- log(ERROR, "devhost: driver load failed: %d\n", r);
- return;
- }
- if (!drv->has_create_op()) {
- log(ERROR, "devhost: driver create() not supported\n");
- return;
- }
+ // Create a dummy parent device for use in this call to Create
+ fbl::RefPtr<zx_device> parent;
+ if ((r = zx_device::Create(&parent)) != ZX_OK) {
+ log(ERROR, "devhost: device create() failed: %d\n", r);
+ return;
+ }
+ // magic cookie for device create handshake
+ char dummy_name[sizeof(parent->name)] = "device_create dummy";
+ memcpy(&parent->name, &dummy_name, sizeof(parent->name));
- // Create a dummy parent device for use in this call to Create
- fbl::RefPtr<zx_device> parent;
- if ((r = zx_device::Create(&parent)) != ZX_OK) {
- log(ERROR, "devhost: device create() failed: %d\n", r);
- return;
- }
- // magic cookie for device create handshake
- char dummy_name[sizeof(parent->name)] = "device_create dummy";
- memcpy(&parent->name, &dummy_name, sizeof(parent->name));
+ CreationContext creation_context = {
+ .parent = std::move(parent),
+ .child = nullptr,
+ .rpc = zx::unowned_channel(rpc),
+ };
- CreationContext creation_context = {
- .parent = std::move(parent),
- .child = nullptr,
- .rpc = zx::unowned_channel(rpc),
- };
+ r = drv->CreateOp(&creation_context, creation_context.parent, "proxy", proxy_args.data(),
+ parent_proxy.release());
- r = drv->CreateOp(&creation_context, creation_context.parent, "proxy", proxy_args.data(),
- parent_proxy.release());
+ // Suppress a warning about dummy device being in a bad state. The
+ // message is spurious in this case, since the dummy parent never
+ // actually begins its device lifecycle. This flag is ordinarily
+ // set by device_remove().
+ creation_context.parent->flags |= DEV_FLAG_VERY_DEAD;
- // Suppress a warning about dummy device being in a bad state. The
- // message is spurious in this case, since the dummy parent never
- // actually begins its device lifecycle. This flag is ordinarily
- // set by device_remove().
- creation_context.parent->flags |= DEV_FLAG_VERY_DEAD;
+ if (r != ZX_OK) {
+ log(ERROR, "devhost: driver create() failed: %d\n", r);
+ return;
+ }
- if (r != ZX_OK) {
- log(ERROR, "devhost: driver create() failed: %d\n", r);
- return;
- }
+ auto new_device = std::move(creation_context.child);
+ if (new_device == nullptr) {
+ log(ERROR, "devhost: driver create() failed to create a device!");
+ return;
+ }
- auto new_device = std::move(creation_context.child);
- if (new_device == nullptr) {
- log(ERROR, "devhost: driver create() failed to create a device!");
- return;
- }
+ new_device->set_local_id(local_device_id);
+ std::unique_ptr<DeviceControllerConnection> newconn;
+ r = DeviceControllerConnection::Create(std::move(new_device), std::move(rpc), &newconn);
+ if (r != ZX_OK) {
+ return;
+ }
- new_device->set_local_id(local_device_id);
- std::unique_ptr<DeviceControllerConnection> newconn;
- r = DeviceControllerConnection::Create(std::move(new_device), std::move(rpc), &newconn);
- if (r != ZX_OK) {
- return;
- }
+ // TODO: inform devcoord
- // TODO: inform devcoord
-
- log(RPC_IN, "devhost: creating '%.*s' conn=%p\n", static_cast<int>(driver_path.size()),
- driver_path.data(), newconn.get());
- if ((r = DeviceControllerConnection::BeginWait(
- std::move(newconn), DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
- return;
- }
+ log(RPC_IN, "devhost: creating '%.*s' conn=%p\n", static_cast<int>(driver_path.size()),
+ driver_path.data(), newconn.get());
+ if ((r = DeviceControllerConnection::BeginWait(std::move(newconn),
+ DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
+ return;
+ }
}
-void DevhostControllerConnection::CreateCompositeDevice(zx::channel rpc,
- ::fidl::VectorView<uint64_t> components,
- ::fidl::StringView name,
- uint64_t local_device_id,
- CreateCompositeDeviceCompleter::Sync completer) {
+void DevhostControllerConnection::CreateCompositeDevice(
+ zx::channel rpc, ::fidl::VectorView<uint64_t> components, ::fidl::StringView name,
+ uint64_t local_device_id, CreateCompositeDeviceCompleter::Sync completer) {
+ log(RPC_IN, "devhost: create composite device %.*s'\n", static_cast<int>(name.size()),
+ name.data());
- log(RPC_IN, "devhost: create composite device %.*s'\n", static_cast<int>(name.size()), name.data());
+ // Convert the component IDs into zx_device references
+ CompositeComponents components_list(new fbl::RefPtr<zx_device>[components.count()],
+ components.count());
+ {
+ // Acquire the API lock so that we don't have to worry about concurrent
+ // device removes
+ ApiAutoLock lock;
- // Convert the component IDs into zx_device references
- CompositeComponents components_list(new fbl::RefPtr<zx_device>[components.count()], components.count());
- {
- // Acquire the API lock so that we don't have to worry about concurrent
- // device removes
- ApiAutoLock lock;
-
- for (size_t i = 0; i < components.count(); ++i) {
- uint64_t local_id = components.data()[i];
- fbl::RefPtr<zx_device_t> dev = zx_device::GetDeviceFromLocalId(local_id);
- if (dev == nullptr || (dev->flags & DEV_FLAG_DEAD)) {
- completer.Reply(ZX_ERR_NOT_FOUND);
- return;
- }
- components_list[i] = std::move(dev);
- }
- }
-
- fbl::RefPtr<zx_device_t> dev;
- zx_status_t status = zx_device::Create(&dev);
- if (status != ZX_OK) {
- completer.Reply(status);
+ for (size_t i = 0; i < components.count(); ++i) {
+ uint64_t local_id = components.data()[i];
+ fbl::RefPtr<zx_device_t> dev = zx_device::GetDeviceFromLocalId(local_id);
+ if (dev == nullptr || (dev->flags & DEV_FLAG_DEAD)) {
+ completer.Reply(ZX_ERR_NOT_FOUND);
return;
+ }
+ components_list[i] = std::move(dev);
}
- static_assert(fuchsia_device_manager_DEVICE_NAME_MAX + 1 >= sizeof(dev->name));
- memcpy(dev->name, name.data(), name.size());
- dev->name[name.size()] = 0;
- dev->set_local_id(local_device_id);
+ }
- std::unique_ptr<DeviceControllerConnection> newconn;
- status = DeviceControllerConnection::Create(dev, std::move(rpc), &newconn);
- if (status != ZX_OK) {
- completer.Reply(status);
- return;
- }
+ fbl::RefPtr<zx_device_t> dev;
+ zx_status_t status = zx_device::Create(&dev);
+ if (status != ZX_OK) {
+ completer.Reply(status);
+ return;
+ }
+ static_assert(fuchsia_device_manager_DEVICE_NAME_MAX + 1 >= sizeof(dev->name));
+ memcpy(dev->name, name.data(), name.size());
+ dev->name[name.size()] = 0;
+ dev->set_local_id(local_device_id);
- status = InitializeCompositeDevice(dev, std::move(components_list));
- if (status != ZX_OK) {
- completer.Reply(status);
- return;
- }
+ std::unique_ptr<DeviceControllerConnection> newconn;
+ status = DeviceControllerConnection::Create(dev, std::move(rpc), &newconn);
+ if (status != ZX_OK) {
+ completer.Reply(status);
+ return;
+ }
- log(RPC_IN, "devhost: creating new composite conn=%p\n", newconn.get());
- if ((status = DeviceControllerConnection::BeginWait(
- std::move(newconn), DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
- completer.Reply(status);
- return;
- }
- completer.Reply(ZX_OK);
+ status = InitializeCompositeDevice(dev, std::move(components_list));
+ if (status != ZX_OK) {
+ completer.Reply(status);
+ return;
+ }
+
+ log(RPC_IN, "devhost: creating new composite conn=%p\n", newconn.get());
+ if ((status = DeviceControllerConnection::BeginWait(std::move(newconn),
+ DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
+ completer.Reply(status);
+ return;
+ }
+ completer.Reply(ZX_OK);
}
-void DevhostControllerConnection::CreateDeviceStub(zx::channel rpc,
- uint32_t protocol_id,
+void DevhostControllerConnection::CreateDeviceStub(zx::channel rpc, uint32_t protocol_id,
uint64_t local_device_id,
CreateDeviceStubCompleter::Sync completer) {
+ log(RPC_IN, "devhost: create device stub\n");
- log(RPC_IN, "devhost: create device stub\n");
+ fbl::RefPtr<zx_device_t> dev;
+ zx_status_t r = zx_device::Create(&dev);
+ // TODO: dev->ops and other lifecycle bits
+ // no name means a dummy proxy device
+ if (r != ZX_OK) {
+ return;
+ }
+ strcpy(dev->name, "proxy");
+ dev->protocol_id = protocol_id;
+ dev->ops = &device_default_ops;
+ dev->set_local_id(local_device_id);
- fbl::RefPtr<zx_device_t> dev;
- zx_status_t r = zx_device::Create(&dev);
- // TODO: dev->ops and other lifecycle bits
- // no name means a dummy proxy device
- if (r != ZX_OK) {
- return;
- }
- strcpy(dev->name, "proxy");
- dev->protocol_id = protocol_id;
- dev->ops = &device_default_ops;
- dev->set_local_id(local_device_id);
+ std::unique_ptr<DeviceControllerConnection> newconn;
+ r = DeviceControllerConnection::Create(dev, std::move(rpc), &newconn);
+ if (r != ZX_OK) {
+ return;
+ }
- std::unique_ptr<DeviceControllerConnection> newconn;
- r = DeviceControllerConnection::Create(dev, std::move(rpc), &newconn);
- if (r != ZX_OK) {
- return;
- }
-
- log(RPC_IN, "devhost: creating new stub conn=%p\n", newconn.get());
- if ((r = DeviceControllerConnection::BeginWait(
- std::move(newconn), DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
- return;
- }
+ log(RPC_IN, "devhost: creating new stub conn=%p\n", newconn.get());
+ if ((r = DeviceControllerConnection::BeginWait(std::move(newconn),
+ DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
+ return;
+ }
}
zx_status_t DevhostControllerConnection::HandleRead() {
- zx::unowned_channel conn = channel();
- uint8_t msg[ZX_CHANNEL_MAX_MSG_BYTES];
- zx_handle_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
- uint32_t msize = sizeof(msg);
- uint32_t hcount = fbl::count_of(hin);
- zx_status_t status = conn->read(0, msg, hin, msize, hcount, &msize, &hcount);
- if (status != ZX_OK) {
- return status;
- }
+ zx::unowned_channel conn = channel();
+ uint8_t msg[ZX_CHANNEL_MAX_MSG_BYTES];
+ zx_handle_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
+ uint32_t msize = sizeof(msg);
+ uint32_t hcount = fbl::count_of(hin);
+ zx_status_t status = conn->read(0, msg, hin, msize, hcount, &msize, &hcount);
+ if (status != ZX_OK) {
+ return status;
+ }
- fidl_msg_t fidl_msg = {
- .bytes = msg,
- .handles = hin,
- .num_bytes = msize,
- .num_handles = hcount,
- };
+ fidl_msg_t fidl_msg = {
+ .bytes = msg,
+ .handles = hin,
+ .num_bytes = msize,
+ .num_handles = hcount,
+ };
- if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
- zx_handle_close_many(fidl_msg.handles, fidl_msg.num_handles);
- return ZX_ERR_IO;
- }
+ if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
+ zx_handle_close_many(fidl_msg.handles, fidl_msg.num_handles);
+ return ZX_ERR_IO;
+ }
- auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
- DevmgrFidlTxn txn(std::move(conn), hdr->txid);
- fuchsia::device::manager::DevhostController::Dispatch(this, &fidl_msg, &txn);
- return txn.Status();
+ auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
+ DevmgrFidlTxn txn(std::move(conn), hdr->txid);
+ fuchsia::device::manager::DevhostController::Dispatch(this, &fidl_msg, &txn);
+ return txn.Status();
}
// handles devcoordinator rpc
-void DevhostControllerConnection::HandleRpc(
- fbl::unique_ptr<DevhostControllerConnection> conn, async_dispatcher_t* dispatcher,
- async::WaitBase* wait, zx_status_t status, const zx_packet_signal_t* signal) {
+void DevhostControllerConnection::HandleRpc(fbl::unique_ptr<DevhostControllerConnection> conn,
+ async_dispatcher_t* dispatcher, async::WaitBase* wait,
+ zx_status_t status, const zx_packet_signal_t* signal) {
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: devcoord conn wait error: %d\n", status);
+ return;
+ }
+ if (signal->observed & ZX_CHANNEL_READABLE) {
+ status = conn->HandleRead();
if (status != ZX_OK) {
- log(ERROR, "devhost: devcoord conn wait error: %d\n", status);
- return;
+ log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%s. fatal.\n", conn.get(),
+ zx_status_get_string(status));
+ abort();
}
- if (signal->observed & ZX_CHANNEL_READABLE) {
- status = conn->HandleRead();
- if (status != ZX_OK) {
- log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%s. fatal.\n", conn.get(),
- zx_status_get_string(status));
- abort();
- }
- BeginWait(std::move(conn), dispatcher);
- return;
- }
- if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
- log(ERROR, "devhost: devmgr disconnected! fatal. (conn=%p)\n", conn.get());
- abort();
- }
- log(ERROR, "devhost: no work? %08x\n", signal->observed);
BeginWait(std::move(conn), dispatcher);
+ return;
+ }
+ if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
+ log(ERROR, "devhost: devmgr disconnected! fatal. (conn=%p)\n", conn.get());
+ abort();
+ }
+ log(ERROR, "devhost: no work? %08x\n", signal->observed);
+ BeginWait(std::move(conn), dispatcher);
}
// handles remoteio rpc
void DevfsConnection::HandleRpc(fbl::unique_ptr<DevfsConnection> conn,
async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal) {
- if (status != ZX_OK) {
- log(ERROR, "devhost: devfs conn wait error: %d\n", status);
- return;
- }
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: devfs conn wait error: %d\n", status);
+ return;
+ }
- if (signal->observed & ZX_CHANNEL_READABLE) {
- status = fs::ReadMessage(wait->object(), [&conn](fidl_msg_t* msg, fs::FidlConnection* txn) {
- return devhost_fidl_handler(msg, txn->Txn(), conn.get());
- });
- if (status == ZX_OK) {
- BeginWait(std::move(conn), dispatcher);
- return;
- }
- } else if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
- fs::CloseMessage([&conn](fidl_msg_t* msg, fs::FidlConnection* txn) {
- return devhost_fidl_handler(msg, txn->Txn(), conn.get());
- });
- } else {
- printf("dh_handle_fidl_rpc: invalid signals %x\n", signal->observed);
- abort();
+ if (signal->observed & ZX_CHANNEL_READABLE) {
+ status = fs::ReadMessage(wait->object(), [&conn](fidl_msg_t* msg, fs::FidlConnection* txn) {
+ return devhost_fidl_handler(msg, txn->Txn(), conn.get());
+ });
+ if (status == ZX_OK) {
+ BeginWait(std::move(conn), dispatcher);
+ return;
}
+ } else if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
+ fs::CloseMessage([&conn](fidl_msg_t* msg, fs::FidlConnection* txn) {
+ return devhost_fidl_handler(msg, txn->Txn(), conn.get());
+ });
+ } else {
+ printf("dh_handle_fidl_rpc: invalid signals %x\n", signal->observed);
+ abort();
+ }
- // We arrive here if devhost_fidl_handler was a clean close (ERR_DISPATCHER_DONE),
- // or close-due-to-error (non-ZX_OK), or if the channel was closed
- // out from under us. In all cases, we are done with this connection, so we
- // will destroy it by letting it leave scope.
- log(TRACE, "devhost: destroying devfs conn %p\n", conn.get());
+ // We arrive here if devhost_fidl_handler was a clean close (ERR_DISPATCHER_DONE),
+ // or close-due-to-error (non-ZX_OK), or if the channel was closed
+ // out from under us. In all cases, we are done with this connection, so we
+ // will destroy it by letting it leave scope.
+ log(TRACE, "devhost: destroying devfs conn %p\n", conn.get());
}
static void proxy_ios_destroy(const fbl::RefPtr<zx_device_t>& dev) {
- fbl::AutoLock guard(&dev->proxy_ios_lock);
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
- if (dev->proxy_ios) {
- dev->proxy_ios->CancelLocked(DevhostAsyncLoop()->dispatcher());
- }
+ if (dev->proxy_ios) {
+ dev->proxy_ios->CancelLocked(DevhostAsyncLoop()->dispatcher());
+ }
}
#define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
@@ -521,101 +510,101 @@
static zx::debuglog devhost_log_handle;
static ssize_t devhost_log_write_internal(uint32_t flags, const void* void_data, size_t len) {
- struct Context {
- Context() = default;
+ struct Context {
+ Context() = default;
- uint32_t next = 0;
- zx::unowned_debuglog handle;
- char data[LOGBUF_MAX] = {};
- };
- static thread_local fbl::unique_ptr<Context> ctx;
+ uint32_t next = 0;
+ zx::unowned_debuglog handle;
+ char data[LOGBUF_MAX] = {};
+ };
+ static thread_local fbl::unique_ptr<Context> ctx;
+ if (ctx == nullptr) {
+ ctx = std::make_unique<Context>();
if (ctx == nullptr) {
- ctx = std::make_unique<Context>();
- if (ctx == nullptr) {
- return len;
- }
- ctx->handle = zx::unowned_debuglog(devhost_log_handle);
+ return len;
}
+ ctx->handle = zx::unowned_debuglog(devhost_log_handle);
+ }
- const char* data = static_cast<const char*>(void_data);
- size_t r = len;
+ const char* data = static_cast<const char*>(void_data);
+ size_t r = len;
- auto flush_context = [&]() {
- ctx->handle->write(flags, ctx->data, ctx->next);
- ctx->next = 0;
- };
+ auto flush_context = [&]() {
+ ctx->handle->write(flags, ctx->data, ctx->next);
+ ctx->next = 0;
+ };
- while (len-- > 0) {
- char c = *data++;
- if (c == '\n') {
- if (ctx->next) {
- flush_context();
- }
- continue;
- }
- if (c < ' ') {
- continue;
- }
- ctx->data[ctx->next++] = c;
- if (ctx->next == LOGBUF_MAX) {
- flush_context();
- }
+ while (len-- > 0) {
+ char c = *data++;
+ if (c == '\n') {
+ if (ctx->next) {
+ flush_context();
+ }
+ continue;
}
- return r;
+ if (c < ' ') {
+ continue;
+ }
+ ctx->data[ctx->next++] = c;
+ if (ctx->next == LOGBUF_MAX) {
+ flush_context();
+ }
+ }
+ return r;
}
-} // namespace devmgr
+} // namespace devmgr
__EXPORT void driver_printf(uint32_t flags, const char* fmt, ...) {
- char buffer[512];
- va_list ap;
- va_start(ap, fmt);
- int r = vsnprintf(buffer, sizeof(buffer), fmt, ap);
- va_end(ap);
+ char buffer[512];
+ va_list ap;
+ va_start(ap, fmt);
+ int r = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+ va_end(ap);
- if (r > (int)sizeof(buffer)) {
- r = sizeof(buffer);
- }
+ if (r > (int)sizeof(buffer)) {
+ r = sizeof(buffer);
+ }
- devmgr::devhost_log_write_internal(flags, buffer, r);
+ devmgr::devhost_log_write_internal(flags, buffer, r);
}
namespace devmgr {
static zx_status_t devhost_log_write(zxio_t* io, const void* buffer, size_t capacity,
size_t* out_actual) {
- devhost_log_write_internal(0, buffer, capacity);
- *out_actual = capacity;
- return ZX_OK;
+ devhost_log_write_internal(0, buffer, capacity);
+ *out_actual = capacity;
+ return ZX_OK;
}
static zx_status_t devhost_log_isatty(zxio_t* io, bool* tty) {
- // Claim to be a TTY to get line buffering
- *tty = true;
- return ZX_OK;
+ // Claim to be a TTY to get line buffering
+ *tty = true;
+ return ZX_OK;
}
static constexpr zxio_ops_t devhost_log_ops = []() {
- zxio_ops_t ops = zxio_default_ops;
- ops.write = devhost_log_write;
- ops.isatty = devhost_log_isatty;
- return ops;
+ zxio_ops_t ops = zxio_default_ops;
+ ops.write = devhost_log_write;
+ ops.isatty = devhost_log_isatty;
+ return ops;
}();
static void devhost_io_init() {
- if (zx::debuglog::create(zx::resource(), 0, &devhost_log_handle) < 0) {
- return;
- }
- fdio_t* io = nullptr;
- zxio_storage_t* storage = nullptr;
- if ((io = fdio_zxio_create(&storage)) == nullptr) {
- return;
- }
- zxio_init(&storage->io, &devhost_log_ops);
- close(1);
- fdio_bind_to_fd(io, 1, 0);
- dup2(1, 2);
+ if (zx::debuglog::create(zx::resource(), 0, &devhost_log_handle) < 0) {
+ return;
+ }
+ fdio_t* io = nullptr;
+ zxio_storage_t* storage = nullptr;
+ if ((io = fdio_zxio_create(&storage)) == nullptr) {
+ return;
+ }
+ zxio_init(&storage->io, &devhost_log_ops);
+ close(1);
+ fdio_bind_to_fd(io, 1, 0);
+ dup2(1, 2);
}
// Send message to devcoordinator asking to add child device to
@@ -624,424 +613,422 @@
const fbl::RefPtr<zx_device_t>& child, const char* proxy_args,
const zx_device_prop_t* props, uint32_t prop_count,
zx::channel client_remote) {
- char buffer[512];
- const char* path = mkdevpath(parent, buffer, sizeof(buffer));
- log(RPC_OUT, "devhost[%s] add '%s'\n", path, child->name);
+ char buffer[512];
+ const char* path = mkdevpath(parent, buffer, sizeof(buffer));
+ log(RPC_OUT, "devhost[%s] add '%s'\n", path, child->name);
- bool add_invisible = child->flags & DEV_FLAG_INVISIBLE;
+ bool add_invisible = child->flags & DEV_FLAG_INVISIBLE;
- zx_status_t status;
- zx::channel hrpc, hsend;
- if ((status = zx::channel::create(0, &hrpc, &hsend)) != ZX_OK) {
- return status;
- }
+ zx_status_t status;
+ zx::channel hrpc, hsend;
+ if ((status = zx::channel::create(0, &hrpc, &hsend)) != ZX_OK) {
+ return status;
+ }
- std::unique_ptr<DeviceControllerConnection> conn;
- status = DeviceControllerConnection::Create(child, std::move(hrpc), &conn);
- if (status != ZX_OK) {
- return status;
- }
+ std::unique_ptr<DeviceControllerConnection> conn;
+ status = DeviceControllerConnection::Create(child, std::move(hrpc), &conn);
+ if (status != ZX_OK) {
+ return status;
+ }
- const zx::channel& rpc = *parent->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
- size_t proxy_args_len = proxy_args ? strlen(proxy_args) : 0;
- zx_status_t call_status;
- static_assert(sizeof(zx_device_prop_t) == sizeof(uint64_t));
- uint64_t device_id = 0;
- if (add_invisible) {
- status = fuchsia_device_manager_CoordinatorAddDeviceInvisible(
- rpc.get(), hsend.release(), reinterpret_cast<const uint64_t*>(props), prop_count,
- child->name, strlen(child->name), child->protocol_id, child->driver->libname().data(),
- child->driver->libname().size(), proxy_args, proxy_args_len, client_remote.release(),
- &call_status, &device_id);
- } else {
- status = fuchsia_device_manager_CoordinatorAddDevice(
- rpc.get(), hsend.release(), reinterpret_cast<const uint64_t*>(props), prop_count,
- child->name, strlen(child->name), child->protocol_id, child->driver->libname().data(),
- child->driver->libname().size(), proxy_args, proxy_args_len, client_remote.release(),
- &call_status, &device_id);
- }
- if (status != ZX_OK) {
- log(ERROR, "devhost[%s] add '%s': rpc sending failed: %d\n", path, child->name, status);
- return status;
- } else if (call_status != ZX_OK) {
- log(ERROR, "devhost[%s] add '%s': rpc failed: %d\n", path, child->name, call_status);
- return call_status;
- }
+ const zx::channel& rpc = *parent->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ size_t proxy_args_len = proxy_args ? strlen(proxy_args) : 0;
+ zx_status_t call_status;
+ static_assert(sizeof(zx_device_prop_t) == sizeof(uint64_t));
+ uint64_t device_id = 0;
+ if (add_invisible) {
+ status = fuchsia_device_manager_CoordinatorAddDeviceInvisible(
+ rpc.get(), hsend.release(), reinterpret_cast<const uint64_t*>(props), prop_count,
+ child->name, strlen(child->name), child->protocol_id, child->driver->libname().data(),
+ child->driver->libname().size(), proxy_args, proxy_args_len, client_remote.release(),
+ &call_status, &device_id);
+ } else {
+ status = fuchsia_device_manager_CoordinatorAddDevice(
+ rpc.get(), hsend.release(), reinterpret_cast<const uint64_t*>(props), prop_count,
+ child->name, strlen(child->name), child->protocol_id, child->driver->libname().data(),
+ child->driver->libname().size(), proxy_args, proxy_args_len, client_remote.release(),
+ &call_status, &device_id);
+ }
+ if (status != ZX_OK) {
+ log(ERROR, "devhost[%s] add '%s': rpc sending failed: %d\n", path, child->name, status);
+ return status;
+ } else if (call_status != ZX_OK) {
+ log(ERROR, "devhost[%s] add '%s': rpc failed: %d\n", path, child->name, call_status);
+ return call_status;
+ }
- child->set_local_id(device_id);
+ child->set_local_id(device_id);
- status = DeviceControllerConnection::BeginWait(std::move(conn),
- DevhostAsyncLoop()->dispatcher());
- if (status != ZX_OK) {
- return status;
- }
- return ZX_OK;
+ status = DeviceControllerConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
+ if (status != ZX_OK) {
+ return status;
+ }
+ return ZX_OK;
}
static void log_rpc(const fbl::RefPtr<zx_device_t>& dev, const char* opname) {
- char buffer[512];
- const char* path = mkdevpath(dev, buffer, sizeof(buffer));
- log(RPC_OUT, "devhost[%s] %s'\n", path, opname);
+ char buffer[512];
+ const char* path = mkdevpath(dev, buffer, sizeof(buffer));
+ log(RPC_OUT, "devhost[%s] %s'\n", path, opname);
}
static void log_rpc_result(const char* opname, zx_status_t status, zx_status_t call_status) {
- if (status != ZX_OK) {
- log(ERROR, "devhost: rpc:%s sending failed: %d\n", opname, status);
- } else if (call_status != ZX_OK) {
- log(ERROR, "devhost: rpc:%s failed: %d\n", opname, call_status);
- }
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: rpc:%s sending failed: %d\n", opname, status);
+ } else if (call_status != ZX_OK) {
+ log(ERROR, "devhost: rpc:%s failed: %d\n", opname, call_status);
+ }
}
void devhost_make_visible(const fbl::RefPtr<zx_device_t>& dev) {
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return;
- }
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return;
+ }
- // TODO(teisenbe): Handle failures here...
- log_rpc(dev, "make-visible");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorMakeVisible(rpc.get(), &call_status);
- log_rpc_result("make-visible", status, call_status);
+ // TODO(teisenbe): Handle failures here...
+ log_rpc(dev, "make-visible");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorMakeVisible(rpc.get(), &call_status);
+ log_rpc_result("make-visible", status, call_status);
}
// Send message to devcoordinator informing it that this device
// is being removed. Called under devhost api lock.
zx_status_t devhost_remove(const fbl::RefPtr<zx_device_t>& dev) {
- DeviceControllerConnection* conn = dev->conn.load();
- if (conn == nullptr) {
- log(ERROR, "removing device %p, conn is nullptr\n", dev.get());
- return ZX_ERR_INTERNAL;
- }
+ DeviceControllerConnection* conn = dev->conn.load();
+ if (conn == nullptr) {
+ log(ERROR, "removing device %p, conn is nullptr\n", dev.get());
+ return ZX_ERR_INTERNAL;
+ }
- // This must be done before the RemoveDevice message is sent to
- // devcoordinator, since devcoordinator will close the channel in response.
- // The async loop may see the channel close before it sees the queued
- // shutdown packet, so it needs to check if dev->conn has been nulled to
- // handle that gracefully.
- dev->conn.store(nullptr);
+ // This must be done before the RemoveDevice message is sent to
+ // devcoordinator, since devcoordinator will close the channel in response.
+ // The async loop may see the channel close before it sees the queued
+ // shutdown packet, so it needs to check if dev->conn has been nulled to
+ // handle that gracefully.
+ dev->conn.store(nullptr);
- log(DEVLC, "removing device %p, conn %p\n", dev.get(), conn);
+ log(DEVLC, "removing device %p, conn %p\n", dev.get(), conn);
- const zx::channel& rpc = *dev->rpc;
- ZX_ASSERT(rpc.is_valid());
- // TODO(teisenbe): Handle failures here...
- log_rpc(dev, "remove-device");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorRemoveDevice(rpc.get(), &call_status);
- log_rpc_result("remove-device", status, call_status);
+ const zx::channel& rpc = *dev->rpc;
+ ZX_ASSERT(rpc.is_valid());
+ // TODO(teisenbe): Handle failures here...
+ log_rpc(dev, "remove-device");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorRemoveDevice(rpc.get(), &call_status);
+ log_rpc_result("remove-device", status, call_status);
- // Forget our local ID, to release the reference stored by the local ID map
- dev->set_local_id(0);
+ // Forget our local ID, to release the reference stored by the local ID map
+ dev->set_local_id(0);
- // Forget about our rpc channel since after the port_queue below it may be
- // closed.
- dev->rpc = zx::unowned_channel();
+ // Forget about our rpc channel since after the port_queue below it may be
+ // closed.
+ dev->rpc = zx::unowned_channel();
- // queue an event to destroy the connection
- ConnectionDestroyer::Get()->QueueDeviceControllerConnection(DevhostAsyncLoop()->dispatcher(),
- conn);
+ // queue an event to destroy the connection
+ ConnectionDestroyer::Get()->QueueDeviceControllerConnection(DevhostAsyncLoop()->dispatcher(),
+ conn);
- // shut down our proxy rpc channel if it exists
- proxy_ios_destroy(dev);
+ // shut down our proxy rpc channel if it exists
+ proxy_ios_destroy(dev);
- return ZX_OK;
+ return ZX_OK;
}
zx_status_t devhost_get_topo_path(const fbl::RefPtr<zx_device_t>& dev, char* path, size_t max,
size_t* actual) {
- fbl::RefPtr<zx_device_t> remote_dev = dev;
- if (dev->flags & DEV_FLAG_INSTANCE) {
- // Instances cannot be opened a second time. If dev represents an instance, return the path
- // to its parent, prefixed with an '@'.
- if (max < 1) {
- return ZX_ERR_BUFFER_TOO_SMALL;
- }
- path[0] = '@';
- path++;
- max--;
- remote_dev = dev->parent;
+ fbl::RefPtr<zx_device_t> remote_dev = dev;
+ if (dev->flags & DEV_FLAG_INSTANCE) {
+ // Instances cannot be opened a second time. If dev represents an instance, return the path
+ // to its parent, prefixed with an '@'.
+ if (max < 1) {
+ return ZX_ERR_BUFFER_TOO_SMALL;
}
+ path[0] = '@';
+ path++;
+ max--;
+ remote_dev = dev->parent;
+ }
- const zx::channel& rpc = *remote_dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
+ const zx::channel& rpc = *remote_dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
- log_rpc(remote_dev, "get-topo-path");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorGetTopologicalPath(
- rpc.get(), &call_status, path, max - 1, actual);
- log_rpc_result("get-topo-path", status, call_status);
- if (status != ZX_OK) {
- return status;
- }
- if (call_status != ZX_OK) {
- return status;
- }
+ log_rpc(remote_dev, "get-topo-path");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorGetTopologicalPath(rpc.get(), &call_status,
+ path, max - 1, actual);
+ log_rpc_result("get-topo-path", status, call_status);
+ if (status != ZX_OK) {
+ return status;
+ }
+ if (call_status != ZX_OK) {
+ return status;
+ }
- path[*actual] = 0;
+ path[*actual] = 0;
+ *actual += 1;
+
+ // Account for the prefixed '@' we may have added above.
+ if (dev->flags & DEV_FLAG_INSTANCE) {
*actual += 1;
-
- // Account for the prefixed '@' we may have added above.
- if (dev->flags & DEV_FLAG_INSTANCE) {
- *actual += 1;
- }
- return ZX_OK;
+ }
+ return ZX_OK;
}
zx_status_t devhost_device_bind(const fbl::RefPtr<zx_device_t>& dev, const char* drv_libname) {
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
- log_rpc(dev, "bind-device");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorBindDevice(
- rpc.get(), drv_libname, strlen(drv_libname), &call_status);
- log_rpc_result("bind-device", status, call_status);
- if (status != ZX_OK) {
- return status;
- }
- return call_status;
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ log_rpc(dev, "bind-device");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorBindDevice(
+ rpc.get(), drv_libname, strlen(drv_libname), &call_status);
+ log_rpc_result("bind-device", status, call_status);
+ if (status != ZX_OK) {
+ return status;
+ }
+ return call_status;
}
zx_status_t devhost_load_firmware(const fbl::RefPtr<zx_device_t>& dev, const char* path,
zx_handle_t* vmo, size_t* size) {
- if ((vmo == nullptr) || (size == nullptr)) {
- return ZX_ERR_INVALID_ARGS;
- }
+ if ((vmo == nullptr) || (size == nullptr)) {
+ return ZX_ERR_INVALID_ARGS;
+ }
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
- log_rpc(dev, "load-firmware");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorLoadFirmware(
- rpc.get(), path, strlen(path), &call_status, vmo, size);
- log_rpc_result("load-firmware", status, call_status);
- if (status != ZX_OK) {
- return status;
- }
- if (call_status == ZX_OK && *vmo == ZX_HANDLE_INVALID) {
- return ZX_ERR_INTERNAL;
- }
- return call_status;
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ log_rpc(dev, "load-firmware");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorLoadFirmware(rpc.get(), path, strlen(path),
+ &call_status, vmo, size);
+ log_rpc_result("load-firmware", status, call_status);
+ if (status != ZX_OK) {
+ return status;
+ }
+ if (call_status == ZX_OK && *vmo == ZX_HANDLE_INVALID) {
+ return ZX_ERR_INTERNAL;
+ }
+ return call_status;
}
zx_status_t devhost_get_metadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t type, void* buf,
size_t buflen, size_t* actual) {
- if (!buf) {
- return ZX_ERR_INVALID_ARGS;
- }
+ if (!buf) {
+ return ZX_ERR_INVALID_ARGS;
+ }
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ uint8_t data[fuchsia_device_manager_METADATA_MAX];
+ size_t length = 0;
+ log_rpc(dev, "get-metadata");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorGetMetadata(rpc.get(), type, &call_status,
+ data, sizeof(data), &length);
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: rpc:get-metadata sending failed: %d\n", status);
+ return status;
+ }
+ if (call_status != ZX_OK) {
+ if (call_status != ZX_ERR_NOT_FOUND) {
+ log(ERROR, "devhost: rpc:get-metadata failed: %d\n", call_status);
}
- uint8_t data[fuchsia_device_manager_METADATA_MAX];
- size_t length = 0;
- log_rpc(dev, "get-metadata");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorGetMetadata(
- rpc.get(), type, &call_status, data, sizeof(data), &length);
- if (status != ZX_OK) {
- log(ERROR, "devhost: rpc:get-metadata sending failed: %d\n", status);
- return status;
- }
- if (call_status != ZX_OK) {
- if (call_status != ZX_ERR_NOT_FOUND) {
- log(ERROR, "devhost: rpc:get-metadata failed: %d\n", call_status);
- }
- return call_status;
- }
+ return call_status;
+ }
- memcpy(buf, data, length);
- if (actual != nullptr) {
- *actual = length;
- }
- return ZX_OK;
+ memcpy(buf, data, length);
+ if (actual != nullptr) {
+ *actual = length;
+ }
+ return ZX_OK;
}
zx_status_t devhost_get_metadata_size(const fbl::RefPtr<zx_device_t>& dev, uint32_t type,
size_t* out_length) {
-
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ log_rpc(dev, "get-metadata");
+ zx_status_t call_status;
+ zx_status_t status =
+ fuchsia_device_manager_CoordinatorGetMetadataSize(rpc.get(), type, &call_status, out_length);
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: rpc:get-metadata sending failed: %d\n", status);
+ return status;
+ }
+ if (call_status != ZX_OK) {
+ if (call_status != ZX_ERR_NOT_FOUND) {
+ log(ERROR, "devhost: rpc:get-metadata failed: %d\n", call_status);
}
- log_rpc(dev, "get-metadata");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorGetMetadataSize(
- rpc.get(), type, &call_status, out_length);
- if (status != ZX_OK) {
- log(ERROR, "devhost: rpc:get-metadata sending failed: %d\n", status);
- return status;
- }
- if (call_status != ZX_OK) {
- if (call_status != ZX_ERR_NOT_FOUND) {
- log(ERROR, "devhost: rpc:get-metadata failed: %d\n", call_status);
- }
- return call_status;
- }
- return ZX_OK;
+ return call_status;
+ }
+ return ZX_OK;
}
zx_status_t devhost_add_metadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t type,
const void* data, size_t length) {
- if (!data && length) {
- return ZX_ERR_INVALID_ARGS;
- }
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
- log_rpc(dev, "add-metadata");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorAddMetadata(
- rpc.get(), type, reinterpret_cast<const uint8_t*>(data), length, &call_status);
- log_rpc_result("add-metadata", status, call_status);
- if (status != ZX_OK) {
- return status;
- }
- return call_status;
+ if (!data && length) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ log_rpc(dev, "add-metadata");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorAddMetadata(
+ rpc.get(), type, reinterpret_cast<const uint8_t*>(data), length, &call_status);
+ log_rpc_result("add-metadata", status, call_status);
+ if (status != ZX_OK) {
+ return status;
+ }
+ return call_status;
}
zx_status_t devhost_publish_metadata(const fbl::RefPtr<zx_device_t>& dev, const char* path,
uint32_t type, const void* data, size_t length) {
- if (!path || (!data && length)) {
- return ZX_ERR_INVALID_ARGS;
- }
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
- log_rpc(dev, "publish-metadata");
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorPublishMetadata(
- rpc.get(), path, strlen(path), type, reinterpret_cast<const uint8_t*>(data), length,
- &call_status);
- log_rpc_result("publish-metadata", status, call_status);
- if (status != ZX_OK) {
- return status;
- }
- return call_status;
+ if (!path || (!data && length)) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+ log_rpc(dev, "publish-metadata");
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorPublishMetadata(
+ rpc.get(), path, strlen(path), type, reinterpret_cast<const uint8_t*>(data), length,
+ &call_status);
+ log_rpc_result("publish-metadata", status, call_status);
+ if (status != ZX_OK) {
+ return status;
+ }
+ return call_status;
}
-zx_status_t devhost_device_add_composite(const fbl::RefPtr<zx_device_t>& dev,
- const char* name, const zx_device_prop_t* props,
- size_t props_count, const device_component_t* components,
+zx_status_t devhost_device_add_composite(const fbl::RefPtr<zx_device_t>& dev, const char* name,
+ const zx_device_prop_t* props, size_t props_count,
+ const device_component_t* components,
size_t components_count,
uint32_t coresident_device_index) {
- if ((props == nullptr && props_count > 0) || components == nullptr || name == nullptr) {
+ if ((props == nullptr && props_count > 0) || components == nullptr || name == nullptr) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ if (components_count > fuchsia_device_manager_COMPONENTS_MAX) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return ZX_ERR_IO_REFUSED;
+ }
+
+ // Ideally we could perform the entire serialization with a single
+ // allocation, but for now we allocate this (potentially large) array on
+ // the heap. The array is extra-large because of the use of FIDL array
+ // types instead of vector types, to get around the SimpleLayout
+ // restrictions.
+ std::unique_ptr<fuchsia_device_manager_DeviceComponent[]> fidl_components(
+ new fuchsia_device_manager_DeviceComponent[fuchsia_device_manager_COMPONENTS_MAX]());
+ for (size_t i = 0; i < components_count; ++i) {
+ auto& component = fidl_components[i];
+ component.parts_count = components[i].parts_count;
+ if (component.parts_count > fuchsia_device_manager_DEVICE_COMPONENT_PARTS_MAX) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ for (size_t j = 0; j < component.parts_count; ++j) {
+ auto& part = fidl_components[i].parts[j];
+ part.match_program_count = components[i].parts[j].instruction_count;
+ if (part.match_program_count >
+ fuchsia_device_manager_DEVICE_COMPONENT_PART_INSTRUCTIONS_MAX) {
return ZX_ERR_INVALID_ARGS;
- }
- if (components_count > fuchsia_device_manager_COMPONENTS_MAX) {
- return ZX_ERR_INVALID_ARGS;
- }
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return ZX_ERR_IO_REFUSED;
- }
+ }
- // Ideally we could perform the entire serialization with a single
- // allocation, but for now we allocate this (potentially large) array on
- // the heap. The array is extra-large because of the use of FIDL array
- // types instead of vector types, to get around the SimpleLayout
- // restrictions.
- std::unique_ptr<fuchsia_device_manager_DeviceComponent[]> fidl_components(
- new fuchsia_device_manager_DeviceComponent[fuchsia_device_manager_COMPONENTS_MAX]());
- for (size_t i = 0; i < components_count; ++i) {
- auto& component = fidl_components[i];
- component.parts_count = components[i].parts_count;
- if (component.parts_count > fuchsia_device_manager_DEVICE_COMPONENT_PARTS_MAX) {
- return ZX_ERR_INVALID_ARGS;
- }
- for (size_t j = 0; j < component.parts_count; ++j) {
- auto& part = fidl_components[i].parts[j];
- part.match_program_count = components[i].parts[j].instruction_count;
- if (part.match_program_count >
- fuchsia_device_manager_DEVICE_COMPONENT_PART_INSTRUCTIONS_MAX) {
- return ZX_ERR_INVALID_ARGS;
- }
-
- static_assert(sizeof(components[i].parts[j].match_program[0]) ==
- sizeof(part.match_program[0]));
- memcpy(part.match_program, components[i].parts[j].match_program,
- sizeof(part.match_program[0]) * part.match_program_count);
- }
+ static_assert(sizeof(components[i].parts[j].match_program[0]) ==
+ sizeof(part.match_program[0]));
+ memcpy(part.match_program, components[i].parts[j].match_program,
+ sizeof(part.match_program[0]) * part.match_program_count);
}
+ }
- log_rpc(dev, "create-composite");
- zx_status_t call_status;
- static_assert(sizeof(props[0]) == sizeof(uint64_t));
- zx_status_t status = fuchsia_device_manager_CoordinatorAddCompositeDevice(
- rpc.get(), name, strlen(name), reinterpret_cast<const uint64_t*>(props), props_count,
- fidl_components.get(), static_cast<uint32_t>(components_count),
- coresident_device_index, &call_status);
- log_rpc_result("create-composite", status, call_status);
- if (status != ZX_OK) {
- return status;
- }
- return call_status;
+ log_rpc(dev, "create-composite");
+ zx_status_t call_status;
+ static_assert(sizeof(props[0]) == sizeof(uint64_t));
+ zx_status_t status = fuchsia_device_manager_CoordinatorAddCompositeDevice(
+ rpc.get(), name, strlen(name), reinterpret_cast<const uint64_t*>(props), props_count,
+ fidl_components.get(), static_cast<uint32_t>(components_count), coresident_device_index,
+ &call_status);
+ log_rpc_result("create-composite", status, call_status);
+ if (status != ZX_OK) {
+ return status;
+ }
+ return call_status;
}
zx_handle_t root_resource_handle;
zx_status_t devhost_start_connection(fbl::unique_ptr<DevfsConnection> conn, zx::channel h) {
- conn->set_channel(std::move(h));
- return DevfsConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
+ conn->set_channel(std::move(h));
+ return DevfsConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
}
int device_host_main(int argc, char** argv) {
- devhost_io_init();
+ devhost_io_init();
- log(TRACE, "devhost: main()\n");
+ log(TRACE, "devhost: main()\n");
- zx::channel root_conn_channel(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
- if (!root_conn_channel.is_valid()) {
- log(ERROR, "devhost: rpc handle invalid\n");
- return -1;
- }
+ zx::channel root_conn_channel(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
+ if (!root_conn_channel.is_valid()) {
+ log(ERROR, "devhost: rpc handle invalid\n");
+ return -1;
+ }
- root_resource_handle = zx_take_startup_handle(PA_HND(PA_RESOURCE, 0));
- if (root_resource_handle == ZX_HANDLE_INVALID) {
- log(TRACE, "devhost: no root resource handle!\n");
- }
+ root_resource_handle = zx_take_startup_handle(PA_HND(PA_RESOURCE, 0));
+ if (root_resource_handle == ZX_HANDLE_INVALID) {
+ log(TRACE, "devhost: no root resource handle!\n");
+ }
- zx_status_t r;
+ zx_status_t r;
- if (getenv_bool("driver.tracing.enable", true)) {
- r = devhost_start_trace_provider();
- if (r != ZX_OK) {
- log(INFO, "devhost: error registering as trace provider: %d\n", r);
- // This is not a fatal error.
- }
- }
-
- r = devhost_connect_scheduler_profile_provider();
+ if (getenv_bool("driver.tracing.enable", true)) {
+ r = devhost_start_trace_provider();
if (r != ZX_OK) {
- log(INFO, "devhost: error connecting to profile provider: %d\n", r);
- return -1;
+ log(INFO, "devhost: error registering as trace provider: %d\n", r);
+ // This is not a fatal error.
}
+ }
- if ((r = SetupRootDevcoordinatorConnection(std::move(root_conn_channel))) != ZX_OK) {
- log(ERROR, "devhost: could not watch rpc channel: %d\n", r);
- return -1;
- }
+ r = devhost_connect_scheduler_profile_provider();
+ if (r != ZX_OK) {
+ log(INFO, "devhost: error connecting to profile provider: %d\n", r);
+ return -1;
+ }
- r = DevhostAsyncLoop()->Run(zx::time::infinite(), false /* once */);
- log(ERROR, "devhost: async loop finished: %d\n", r);
+ if ((r = SetupRootDevcoordinatorConnection(std::move(root_conn_channel))) != ZX_OK) {
+ log(ERROR, "devhost: could not watch rpc channel: %d\n", r);
+ return -1;
+ }
- return 0;
+ r = DevhostAsyncLoop()->Run(zx::time::infinite(), false /* once */);
+ log(ERROR, "devhost: async loop finished: %d\n", r);
+
+ return 0;
}
-} // namespace devmgr
+} // namespace devmgr
__EXPORT int devmgr_device_host_main(int argc, char** argv) {
- return devmgr::device_host_main(argc, argv);
+ return devmgr::device_host_main(argc, argv);
}
diff --git a/zircon/system/core/devmgr/devhost/devhost.h b/zircon/system/core/devmgr/devhost/devhost.h
index 6fb3417..8f8e790 100644
--- a/zircon/system/core/devmgr/devhost/devhost.h
+++ b/zircon/system/core/devmgr/devhost/devhost.h
@@ -2,16 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
-
-#include "../shared/async-loop-owned-rpc-handler.h"
-#include "lock.h"
-#include "zx-device.h"
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_DEVHOST_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_DEVHOST_H_
#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
-
#include <ddktl/fidl.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/ref_counted.h>
@@ -22,33 +18,36 @@
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/wait.h>
#include <lib/zx/channel.h>
+#include <stdint.h>
+#include <threads.h>
#include <zircon/compiler.h>
#include <zircon/fidl.h>
#include <zircon/thread_annotations.h>
#include <zircon/types.h>
-#include <stdint.h>
-#include <threads.h>
+#include "../shared/async-loop-owned-rpc-handler.h"
+#include "lock.h"
+#include "zx-device.h"
namespace devmgr {
namespace fuchsia = ::llcpp::fuchsia;
struct BindContext {
- fbl::RefPtr<zx_device_t> parent;
- fbl::RefPtr<zx_device_t> child;
+ fbl::RefPtr<zx_device_t> parent;
+ fbl::RefPtr<zx_device_t> child;
};
struct CreationContext {
- fbl::RefPtr<zx_device_t> parent;
- fbl::RefPtr<zx_device_t> child;
- zx::unowned_channel rpc;
+ fbl::RefPtr<zx_device_t> parent;
+ fbl::RefPtr<zx_device_t> child;
+ zx::unowned_channel rpc;
};
void devhost_set_bind_context(BindContext* ctx);
void devhost_set_creation_context(CreationContext* ctx);
-} // namespace devmgr
+} // namespace devmgr
// Nothing outside of devmgr/{devmgr,devhost,rpc-device}.c
// should be calling devhost_*() APIs, as this could
@@ -58,69 +57,69 @@
// Note that this must be a struct to match the public opaque declaration.
struct zx_driver : fbl::DoublyLinkedListable<fbl::RefPtr<zx_driver>>, fbl::RefCounted<zx_driver> {
- static zx_status_t Create(fbl::RefPtr<zx_driver>* out_driver);
+ static zx_status_t Create(fbl::RefPtr<zx_driver>* out_driver);
- const char* name() const { return name_; }
+ const char* name() const { return name_; }
- zx_driver_rec_t* driver_rec() const { return driver_rec_; }
+ zx_driver_rec_t* driver_rec() const { return driver_rec_; }
- zx_status_t status() const { return status_; }
+ zx_status_t status() const { return status_; }
- const fbl::String& libname() const { return libname_; }
+ const fbl::String& libname() const { return libname_; }
- void set_name(const char* name) { name_ = name; }
+ void set_name(const char* name) { name_ = name; }
- void set_driver_rec(zx_driver_rec_t* driver_rec) { driver_rec_ = driver_rec; }
+ void set_driver_rec(zx_driver_rec_t* driver_rec) { driver_rec_ = driver_rec; }
- void set_ops(const zx_driver_ops_t* ops) { ops_ = ops; }
+ void set_ops(const zx_driver_ops_t* ops) { ops_ = ops; }
- void set_status(zx_status_t status) { status_ = status; }
+ void set_status(zx_status_t status) { status_ = status; }
- void set_libname(fbl::StringPiece libname) { libname_ = libname; }
+ void set_libname(fbl::StringPiece libname) { libname_ = libname; }
- // Interface to |ops|. These names contain Op in order to not
- // collide with e.g. RefPtr names.
+ // Interface to |ops|. These names contain Op in order to not
+ // collide with e.g. RefPtr names.
- bool has_init_op() const { return ops_->init != nullptr; }
+ bool has_init_op() const { return ops_->init != nullptr; }
- bool has_bind_op() const { return ops_->bind != nullptr; }
+ bool has_bind_op() const { return ops_->bind != nullptr; }
- bool has_create_op() const { return ops_->create != nullptr; }
+ bool has_create_op() const { return ops_->create != nullptr; }
- zx_status_t InitOp() { return ops_->init(&ctx_); }
+ zx_status_t InitOp() { return ops_->init(&ctx_); }
- zx_status_t BindOp(devmgr::BindContext* bind_context,
- const fbl::RefPtr<zx_device_t>& device) const {
- devmgr::devhost_set_bind_context(bind_context);
- auto status = ops_->bind(ctx_, device.get());
- devmgr::devhost_set_bind_context(nullptr);
- return status;
- }
+ zx_status_t BindOp(devmgr::BindContext* bind_context,
+ const fbl::RefPtr<zx_device_t>& device) const {
+ devmgr::devhost_set_bind_context(bind_context);
+ auto status = ops_->bind(ctx_, device.get());
+ devmgr::devhost_set_bind_context(nullptr);
+ return status;
+ }
- zx_status_t CreateOp(devmgr::CreationContext* creation_context,
- const fbl::RefPtr<zx_device_t>& parent, const char* name, const char* args,
- zx_handle_t rpc_channel) const {
- devmgr::devhost_set_creation_context(creation_context);
- auto status = ops_->create(ctx_, parent.get(), name, args, rpc_channel);
- devmgr::devhost_set_creation_context(nullptr);
- return status;
- }
+ zx_status_t CreateOp(devmgr::CreationContext* creation_context,
+ const fbl::RefPtr<zx_device_t>& parent, const char* name, const char* args,
+ zx_handle_t rpc_channel) const {
+ devmgr::devhost_set_creation_context(creation_context);
+ auto status = ops_->create(ctx_, parent.get(), name, args, rpc_channel);
+ devmgr::devhost_set_creation_context(nullptr);
+ return status;
+ }
- void ReleaseOp() const {
- // TODO(kulakowski/teisenbe) Consider poisoning the ops_ table on release.
- ops_->release(ctx_);
- }
+ void ReleaseOp() const {
+ // TODO(kulakowski/teisenbe) Consider poisoning the ops_ table on release.
+ ops_->release(ctx_);
+ }
-private:
- friend fbl::unique_ptr<zx_driver> std::make_unique<zx_driver>();
- zx_driver() = default;
+ private:
+ friend fbl::unique_ptr<zx_driver> std::make_unique<zx_driver>();
+ zx_driver() = default;
- const char* name_ = nullptr;
- zx_driver_rec_t* driver_rec_ = nullptr;
- const zx_driver_ops_t* ops_ = nullptr;
- void* ctx_ = nullptr;
- fbl::String libname_;
- zx_status_t status_ = ZX_OK;
+ const char* name_ = nullptr;
+ zx_driver_rec_t* driver_rec_ = nullptr;
+ const zx_driver_ops_t* ops_ = nullptr;
+ void* ctx_ = nullptr;
+ fbl::String libname_;
+ zx_status_t status_ = ZX_OK;
};
namespace devmgr {
@@ -167,38 +166,43 @@
zx_status_t devhost_publish_metadata(const fbl::RefPtr<zx_device_t>& dev, const char* path,
uint32_t type, const void* data, size_t length) REQ_DM_LOCK;
-zx_status_t devhost_device_add_composite(const fbl::RefPtr<zx_device_t>& dev,
- const char* name, const zx_device_prop_t* props,
- size_t props_count, const device_component_t* components,
+zx_status_t devhost_device_add_composite(const fbl::RefPtr<zx_device_t>& dev, const char* name,
+ const zx_device_prop_t* props, size_t props_count,
+ const device_component_t* components,
size_t components_count,
uint32_t coresident_device_index) REQ_DM_LOCK;
class DevhostControllerConnection : public AsyncLoopOwnedRpcHandler<DevhostControllerConnection>,
public fuchsia::device::manager::DevhostController::Interface {
-public:
- DevhostControllerConnection() = default;
+ public:
+ DevhostControllerConnection() = default;
- static void HandleRpc(fbl::unique_ptr<DevhostControllerConnection> conn,
- async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
- const zx_packet_signal_t* signal);
- zx_status_t HandleRead();
+ static void HandleRpc(fbl::unique_ptr<DevhostControllerConnection> conn,
+ async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
+ const zx_packet_signal_t* signal);
+ zx_status_t HandleRead();
-private:
- void CreateDevice(zx::channel rpc, ::fidl::StringView driver_path, ::zx::vmo driver, ::zx::handle parent_proxy, ::fidl::StringView proxy_args, uint64_t local_device_id, CreateDeviceCompleter::Sync completer) override;
- void CreateCompositeDevice(zx::channel rpc, ::fidl::VectorView<uint64_t> components, ::fidl::StringView name, uint64_t local_device_id, CreateCompositeDeviceCompleter::Sync completer) override;
- void CreateDeviceStub(zx::channel rpc, uint32_t protocol_id, uint64_t local_device_id, CreateDeviceStubCompleter::Sync completer) override;
+ private:
+ void CreateDevice(zx::channel rpc, ::fidl::StringView driver_path, ::zx::vmo driver,
+ ::zx::handle parent_proxy, ::fidl::StringView proxy_args,
+ uint64_t local_device_id, CreateDeviceCompleter::Sync completer) override;
+ void CreateCompositeDevice(zx::channel rpc, ::fidl::VectorView<uint64_t> components,
+ ::fidl::StringView name, uint64_t local_device_id,
+ CreateCompositeDeviceCompleter::Sync completer) override;
+ void CreateDeviceStub(zx::channel rpc, uint32_t protocol_id, uint64_t local_device_id,
+ CreateDeviceStubCompleter::Sync completer) override;
};
struct DevfsConnection : AsyncLoopOwnedRpcHandler<DevfsConnection> {
- DevfsConnection() = default;
+ DevfsConnection() = default;
- static void HandleRpc(fbl::unique_ptr<DevfsConnection> conn, async_dispatcher_t* dispatcher,
- async::WaitBase* wait, zx_status_t status,
- const zx_packet_signal_t* signal);
+ static void HandleRpc(fbl::unique_ptr<DevfsConnection> conn, async_dispatcher_t* dispatcher,
+ async::WaitBase* wait, zx_status_t status,
+ const zx_packet_signal_t* signal);
- fbl::RefPtr<zx_device_t> dev;
- size_t io_off = 0;
- uint32_t flags = 0;
+ fbl::RefPtr<zx_device_t> dev;
+ size_t io_off = 0;
+ uint32_t flags = 0;
};
zx_status_t devhost_fidl_handler(fidl_msg_t* msg, fidl_txn_t* txn, void* cookie);
@@ -234,4 +238,6 @@
// Retrieve the singleton async loop
async::Loop* DevhostAsyncLoop();
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_DEVHOST_H_
diff --git a/zircon/system/core/devmgr/devhost/device-api-test.cc b/zircon/system/core/devmgr/devhost/device-api-test.cc
index a355d36..c0226e1 100644
--- a/zircon/system/core/devmgr/devhost/device-api-test.cc
+++ b/zircon/system/core/devmgr/devhost/device-api-test.cc
@@ -5,22 +5,23 @@
#include <fbl/auto_lock.h>
#include <lib/async-loop/cpp/loop.h>
#include <zxtest/zxtest.h>
+
#include "proxy-iostate.h"
#include "zx-device.h"
namespace {
TEST(DeviceApiTest, OpsNotImplemented) {
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx_protocol_device_t ops = {};
- dev->ops = &ops;
+ zx_protocol_device_t ops = {};
+ dev->ops = &ops;
- EXPECT_EQ(device_get_protocol(dev.get(), 0, nullptr), ZX_ERR_NOT_SUPPORTED);
- EXPECT_EQ(device_get_size(dev.get()), 0);
- EXPECT_EQ(device_read(dev.get(), nullptr, 0, 0, nullptr), ZX_ERR_NOT_SUPPORTED);
- EXPECT_EQ(device_write(dev.get(), nullptr, 0, 0, nullptr), ZX_ERR_NOT_SUPPORTED);
+ EXPECT_EQ(device_get_protocol(dev.get(), 0, nullptr), ZX_ERR_NOT_SUPPORTED);
+ EXPECT_EQ(device_get_size(dev.get()), 0);
+ EXPECT_EQ(device_read(dev.get(), nullptr, 0, 0, nullptr), ZX_ERR_NOT_SUPPORTED);
+ EXPECT_EQ(device_write(dev.get(), nullptr, 0, 0, nullptr), ZX_ERR_NOT_SUPPORTED);
}
uint64_t test_ctx = 0xabcdef;
@@ -59,60 +60,60 @@
}
TEST(DeviceApiTest, GetProtocol) {
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx_protocol_device_t ops = {};
- ops.get_protocol = test_get_protocol;
- dev->ops = &ops;
- dev->ctx = &test_ctx;
+ zx_protocol_device_t ops = {};
+ ops.get_protocol = test_get_protocol;
+ dev->ops = &ops;
+ dev->ctx = &test_ctx;
- uint8_t out = 0;
- ASSERT_OK(device_get_protocol(dev.get(), 42, &out));
- EXPECT_EQ(out, 0xab);
+ uint8_t out = 0;
+ ASSERT_OK(device_get_protocol(dev.get(), 42, &out));
+ EXPECT_EQ(out, 0xab);
}
TEST(DeviceApiTest, GetSize) {
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx_protocol_device_t ops = {};
- ops.get_size = test_get_size;
- dev->ops = &ops;
- dev->ctx = &test_ctx;
+ zx_protocol_device_t ops = {};
+ ops.get_size = test_get_size;
+ dev->ops = &ops;
+ dev->ctx = &test_ctx;
- ASSERT_EQ(device_get_size(dev.get()), 42ul);
+ ASSERT_EQ(device_get_size(dev.get()), 42ul);
}
TEST(DeviceApiTest, Read) {
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx_protocol_device_t ops = {};
- ops.read = test_read;
- dev->ops = &ops;
- dev->ctx = &test_ctx;
+ zx_protocol_device_t ops = {};
+ ops.read = test_read;
+ dev->ops = &ops;
+ dev->ctx = &test_ctx;
- uint8_t buf = 0;
- size_t actual = 0;
- ASSERT_OK(device_read(dev.get(), &buf, 1, 2, &actual));
- EXPECT_EQ(buf, 0xab);
- EXPECT_EQ(actual, 3);
+ uint8_t buf = 0;
+ size_t actual = 0;
+ ASSERT_OK(device_read(dev.get(), &buf, 1, 2, &actual));
+ EXPECT_EQ(buf, 0xab);
+ EXPECT_EQ(actual, 3);
}
TEST(DeviceApiTest, Write) {
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx_protocol_device_t ops = {};
- ops.write = test_write;
- dev->ops = &ops;
- dev->ctx = &test_ctx;
+ zx_protocol_device_t ops = {};
+ ops.write = test_write;
+ dev->ops = &ops;
+ dev->ctx = &test_ctx;
- uint8_t buf = 0xab;
- size_t actual = 0;
- ASSERT_OK(device_write(dev.get(), &buf, 1, 2, &actual));
- EXPECT_EQ(actual, 3);
+ uint8_t buf = 0xab;
+ size_t actual = 0;
+ ASSERT_OK(device_write(dev.get(), &buf, 1, 2, &actual));
+ EXPECT_EQ(actual, 3);
}
-} // namespace
+} // namespace
diff --git a/zircon/system/core/devmgr/devhost/device-controller-connection-test.cc b/zircon/system/core/devmgr/devhost/device-controller-connection-test.cc
index 5c2a61e..8a5caa5 100644
--- a/zircon/system/core/devmgr/devhost/device-controller-connection-test.cc
+++ b/zircon/system/core/devmgr/devhost/device-controller-connection-test.cc
@@ -2,13 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "device-controller-connection.h"
+
#include <fbl/auto_lock.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/zx/vmo.h>
-#include <thread>
#include <zxtest/zxtest.h>
+
+#include <thread>
+
#include "connection-destroyer.h"
-#include "device-controller-connection.h"
#include "zx-device.h"
namespace {
@@ -17,86 +20,85 @@
const fuchsia_io_Directory_ops_t kNoDirectoryOps = {};
TEST(DeviceControllerConnectionTestCase, Creation) {
- async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx::channel device_local, device_remote;
- ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
+ zx::channel device_local, device_remote;
+ ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
- std::unique_ptr<devmgr::DeviceControllerConnection> conn;
+ std::unique_ptr<devmgr::DeviceControllerConnection> conn;
- ASSERT_NULL(dev->conn.load());
- ASSERT_OK(devmgr::DeviceControllerConnection::Create(
- dev, std::move(device_remote), &kNoDeviceOps, &kNoDirectoryOps, &conn));
- ASSERT_NOT_NULL(dev->conn.load());
+ ASSERT_NULL(dev->conn.load());
+ ASSERT_OK(devmgr::DeviceControllerConnection::Create(dev, std::move(device_remote), &kNoDeviceOps,
+ &kNoDirectoryOps, &conn));
+ ASSERT_NOT_NULL(dev->conn.load());
- ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
+ ASSERT_OK(loop.RunUntilIdle());
}
TEST(DeviceControllerConnectionTestCase, PeerClosedDuringReply) {
- async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
+
+ zx::channel device_local, device_remote;
+ ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
+
+ // This is static so we can access it from bind_driver(). The
+ // existing structure of the code makes it difficult to plumb access to it
+ // through to the callback.
+ static struct {
fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ zx::channel local;
+ async_dispatcher_t* dispatcher;
+ } bind_driver_closure;
- zx::channel device_local, device_remote;
- ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
+ bind_driver_closure.dev = dev;
+ bind_driver_closure.local = std::move(device_local);
+ bind_driver_closure.dispatcher = loop.dispatcher();
- // This is static so we can access it from bind_driver(). The
- // existing structure of the code makes it difficult to plumb access to it
- // through to the callback.
- static struct {
- fbl::RefPtr<zx_device> dev;
- zx::channel local;
- async_dispatcher_t* dispatcher;
- } bind_driver_closure;
+ auto bind_driver = [](void* ctx, const char* driver_path_data, size_t driver_path_size,
+ zx_handle_t raw_driver_vmo, fidl_txn_t* txn) {
+ // Pretend that a device closure happened right before we began
+ // processing BindDriver. Close the other half of the channel, so the reply below will fail
+ // from ZX_ERR_PEER_CLOSED.
+ auto conn = bind_driver_closure.dev->conn.exchange(nullptr);
+ devmgr::ConnectionDestroyer::Get()->QueueDeviceControllerConnection(
+ bind_driver_closure.dispatcher, conn);
+ bind_driver_closure.local.reset();
- bind_driver_closure.dev = dev;
- bind_driver_closure.local = std::move(device_local);
- bind_driver_closure.dispatcher = loop.dispatcher();
+ return fuchsia_device_manager_DeviceControllerBindDriver_reply(txn, ZX_OK);
+ };
+ fuchsia_device_manager_DeviceController_ops_t device_ops = {};
+ device_ops.BindDriver = bind_driver;
- auto bind_driver = [](void* ctx, const char* driver_path_data,
- size_t driver_path_size, zx_handle_t raw_driver_vmo,
- fidl_txn_t* txn) {
- // Pretend that a device closure happened right before we began
- // processing BindDriver. Close the other half of the channel, so the reply below will fail
- // from ZX_ERR_PEER_CLOSED.
- auto conn = bind_driver_closure.dev->conn.exchange(nullptr);
- devmgr::ConnectionDestroyer::Get()->QueueDeviceControllerConnection(
- bind_driver_closure.dispatcher, conn);
- bind_driver_closure.local.reset();
+ std::unique_ptr<devmgr::DeviceControllerConnection> conn;
+ ASSERT_OK(devmgr::DeviceControllerConnection::Create(dev, std::move(device_remote), &device_ops,
+ &kNoDirectoryOps, &conn));
- return fuchsia_device_manager_DeviceControllerBindDriver_reply(txn, ZX_OK);
- };
- fuchsia_device_manager_DeviceController_ops_t device_ops = {};
- device_ops.BindDriver = bind_driver;
+ ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
+ ASSERT_OK(loop.RunUntilIdle());
- std::unique_ptr<devmgr::DeviceControllerConnection> conn;
- ASSERT_OK(devmgr::DeviceControllerConnection::Create(
- dev, std::move(device_remote), &device_ops, &kNoDirectoryOps, &conn));
-
- ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
- ASSERT_OK(loop.RunUntilIdle());
-
- // Create a thread to send a BindDriver message. The thread isn't strictly
- // necessary, but is done out of convenience since the FIDL C bindings don't
- // expose non-zx_channel_call client bindings.
- enum {
- INITIAL,
- VMO_CREATE_FAILED,
- WRONG_CALL_STATUS,
- SUCCESS,
- } thread_status = INITIAL;
- std::thread synchronous_call_thread([channel=bind_driver_closure.local.get(),
- &thread_status]() {
+ // Create a thread to send a BindDriver message. The thread isn't strictly
+ // necessary, but is done out of convenience since the FIDL C bindings don't
+ // expose non-zx_channel_call client bindings.
+ enum {
+ INITIAL,
+ VMO_CREATE_FAILED,
+ WRONG_CALL_STATUS,
+ SUCCESS,
+ } thread_status = INITIAL;
+ std::thread synchronous_call_thread(
+ [channel = bind_driver_closure.local.get(), &thread_status]() {
zx::vmo vmo;
zx_status_t status = zx::vmo::create(0, 0, &vmo);
if (status != ZX_OK) {
- thread_status = VMO_CREATE_FAILED;
- return;
+ thread_status = VMO_CREATE_FAILED;
+ return;
}
zx_status_t call_status;
status = fuchsia_device_manager_DeviceControllerBindDriver(channel, "", 0, vmo.release(),
@@ -104,96 +106,94 @@
// zx_channel_call() returns this when the handle is closed during the
// call.
if (status != ZX_ERR_CANCELED) {
- thread_status = WRONG_CALL_STATUS;
- return;
+ thread_status = WRONG_CALL_STATUS;
+ return;
}
thread_status = SUCCESS;
- });
+ });
- ASSERT_OK(loop.Run(zx::time::infinite(), true /* run_once */));
+ ASSERT_OK(loop.Run(zx::time::infinite(), true /* run_once */));
- synchronous_call_thread.join();
- ASSERT_EQ(SUCCESS, thread_status);
- ASSERT_FALSE(bind_driver_closure.local.is_valid());
+ synchronous_call_thread.join();
+ ASSERT_EQ(SUCCESS, thread_status);
+ ASSERT_FALSE(bind_driver_closure.local.is_valid());
}
// Verify we do not abort when an expected PEER_CLOSED comes in.
TEST(DeviceControllerConnectionTestCase, PeerClosed) {
- async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx::channel device_local, device_remote;
- ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
+ zx::channel device_local, device_remote;
+ ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
- std::unique_ptr<devmgr::DeviceControllerConnection> conn;
- ASSERT_OK(devmgr::DeviceControllerConnection::Create(
- dev, std::move(device_remote), &kNoDeviceOps, &kNoDirectoryOps, &conn));
+ std::unique_ptr<devmgr::DeviceControllerConnection> conn;
+ ASSERT_OK(devmgr::DeviceControllerConnection::Create(dev, std::move(device_remote), &kNoDeviceOps,
+ &kNoDirectoryOps, &conn));
- ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
+ ASSERT_OK(loop.RunUntilIdle());
- // Perform the device shutdown protocol, since otherwise the devhost code
- // will assert, since it is unable to handle unexpected connection closures.
- auto dev_conn = dev->conn.exchange(nullptr);
- devmgr::ConnectionDestroyer::Get()->QueueDeviceControllerConnection(loop.dispatcher(),
- dev_conn);
- device_local.reset();
+ // Perform the device shutdown protocol, since otherwise the devhost code
+ // will assert, since it is unable to handle unexpected connection closures.
+ auto dev_conn = dev->conn.exchange(nullptr);
+ devmgr::ConnectionDestroyer::Get()->QueueDeviceControllerConnection(loop.dispatcher(), dev_conn);
+ device_local.reset();
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(loop.RunUntilIdle());
}
TEST(DeviceControllerConnectionTestCase, UnbindHook) {
- async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx::channel device_local, device_remote;
- ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
+ zx::channel device_local, device_remote;
+ ASSERT_OK(zx::channel::create(0, &device_local, &device_remote));
- auto Unbind = [](void* raw_ctx) {
- auto ctx = static_cast<devmgr::DevhostRpcReadContext*>(raw_ctx);
- fbl::RefPtr<zx_device> dev = ctx->conn->dev();
- // Set dev->flags so that we can check that the unbind hook is called in
- // the test.
- dev->flags = DEV_FLAG_DEAD;
- return ZX_OK;
- };
- fuchsia_device_manager_DeviceController_ops_t device_ops = {};
- device_ops.Unbind = Unbind;
+ auto Unbind = [](void* raw_ctx) {
+ auto ctx = static_cast<devmgr::DevhostRpcReadContext*>(raw_ctx);
+ fbl::RefPtr<zx_device> dev = ctx->conn->dev();
+ // Set dev->flags so that we can check that the unbind hook is called in
+ // the test.
+ dev->flags = DEV_FLAG_DEAD;
+ return ZX_OK;
+ };
+ fuchsia_device_manager_DeviceController_ops_t device_ops = {};
+ device_ops.Unbind = Unbind;
- std::unique_ptr<devmgr::DeviceControllerConnection> conn;
- ASSERT_OK(devmgr::DeviceControllerConnection::Create(
- dev, std::move(device_remote), &device_ops, &kNoDirectoryOps, &conn));
+ std::unique_ptr<devmgr::DeviceControllerConnection> conn;
+ ASSERT_OK(devmgr::DeviceControllerConnection::Create(dev, std::move(device_remote), &device_ops,
+ &kNoDirectoryOps, &conn));
- ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(devmgr::DeviceControllerConnection::BeginWait(std::move(conn), loop.dispatcher()));
+ ASSERT_OK(loop.RunUntilIdle());
- // Create a thread to send the Unbind message. The thread isn't strictly
- // necessary, but is done out of convenience since the FIDL C bindings don't
- // expose non-zx_channel_call client bindings.
- enum {
- INITIAL,
- WRITE_FAILED,
- SUCCESS,
- } thread_status = INITIAL;
- std::thread synchronous_call_thread([channel=device_local.get(),
- &thread_status]() {
- zx_status_t status = fuchsia_device_manager_DeviceControllerUnbind(channel);
- if (status != ZX_OK) {
- thread_status = WRITE_FAILED;
- return;
- }
- thread_status = SUCCESS;
- });
+ // Create a thread to send the Unbind message. The thread isn't strictly
+ // necessary, but is done out of convenience since the FIDL C bindings don't
+ // expose non-zx_channel_call client bindings.
+ enum {
+ INITIAL,
+ WRITE_FAILED,
+ SUCCESS,
+ } thread_status = INITIAL;
+ std::thread synchronous_call_thread([channel = device_local.get(), &thread_status]() {
+ zx_status_t status = fuchsia_device_manager_DeviceControllerUnbind(channel);
+ if (status != ZX_OK) {
+ thread_status = WRITE_FAILED;
+ return;
+ }
+ thread_status = SUCCESS;
+ });
- ASSERT_OK(loop.Run(zx::time::infinite(), true /* run_once */));
+ ASSERT_OK(loop.Run(zx::time::infinite(), true /* run_once */));
- synchronous_call_thread.join();
- ASSERT_EQ(SUCCESS, thread_status);
- ASSERT_EQ(dev->flags, DEV_FLAG_DEAD);
+ synchronous_call_thread.join();
+ ASSERT_EQ(SUCCESS, thread_status);
+ ASSERT_EQ(dev->flags, DEV_FLAG_DEAD);
}
-} // namespace
+} // namespace
diff --git a/zircon/system/core/devmgr/devhost/device-controller-connection.cc b/zircon/system/core/devmgr/devhost/device-controller-connection.cc
index 052b599..b7d9f6e 100644
--- a/zircon/system/core/devmgr/devhost/device-controller-connection.cc
+++ b/zircon/system/core/devmgr/devhost/device-controller-connection.cc
@@ -8,6 +8,7 @@
#include <fuchsia/device/c/fidl.h>
#include <lib/zx/vmo.h>
#include <zircon/status.h>
+
#include "../shared/fidl_txn.h"
#include "../shared/log.h"
#include "connection-destroyer.h"
@@ -22,115 +23,114 @@
// Handles outstanding calls to fuchsia.device.manager.DeviceController/BindDriver
// and fuchsia.device.Controller/Bind.
zx_status_t BindReply(const fbl::RefPtr<zx_device_t>& dev, fidl_txn_t* txn, zx_status_t status) {
- zx_status_t bind_driver_status =
- fuchsia_device_manager_DeviceControllerBindDriver_reply(txn, status);
+ zx_status_t bind_driver_status =
+ fuchsia_device_manager_DeviceControllerBindDriver_reply(txn, status);
- zx_status_t bind_status = ZX_OK;
- fs::FidlConnection conn(fidl_txn_t{}, ZX_HANDLE_INVALID, 0);
- if (dev->PopBindConn(&conn)) {
- bind_status = fuchsia_device_ControllerBind_reply(conn.Txn(), status);
- }
+ zx_status_t bind_status = ZX_OK;
+ fs::FidlConnection conn(fidl_txn_t{}, ZX_HANDLE_INVALID, 0);
+ if (dev->PopBindConn(&conn)) {
+ bind_status = fuchsia_device_ControllerBind_reply(conn.Txn(), status);
+ }
- return bind_driver_status != ZX_OK ? bind_driver_status : bind_status;
+ return bind_driver_status != ZX_OK ? bind_driver_status : bind_status;
}
-zx_status_t fidl_BindDriver(void* raw_ctx, const char* driver_path_data,
- size_t driver_path_size, zx_handle_t raw_driver_vmo,
- fidl_txn_t* txn) {
- auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
- const auto& dev = ctx->conn->dev();
- zx::vmo driver_vmo(raw_driver_vmo);
- fbl::StringPiece driver_path(driver_path_data, driver_path_size);
+zx_status_t fidl_BindDriver(void* raw_ctx, const char* driver_path_data, size_t driver_path_size,
+ zx_handle_t raw_driver_vmo, fidl_txn_t* txn) {
+ auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
+ const auto& dev = ctx->conn->dev();
+ zx::vmo driver_vmo(raw_driver_vmo);
+ fbl::StringPiece driver_path(driver_path_data, driver_path_size);
- // TODO: api lock integration
- log(RPC_IN, "devhost[%s] bind driver '%.*s'\n", ctx->path, static_cast<int>(driver_path_size),
- driver_path_data);
- fbl::RefPtr<zx_driver_t> drv;
- if (dev->flags & DEV_FLAG_DEAD) {
- log(ERROR, "devhost[%s] bind to removed device disallowed\n", ctx->path);
- return BindReply(dev, txn, ZX_ERR_IO_NOT_PRESENT);
+ // TODO: api lock integration
+ log(RPC_IN, "devhost[%s] bind driver '%.*s'\n", ctx->path, static_cast<int>(driver_path_size),
+ driver_path_data);
+ fbl::RefPtr<zx_driver_t> drv;
+ if (dev->flags & DEV_FLAG_DEAD) {
+ log(ERROR, "devhost[%s] bind to removed device disallowed\n", ctx->path);
+ return BindReply(dev, txn, ZX_ERR_IO_NOT_PRESENT);
+ }
+
+ zx_status_t r;
+ if ((r = dh_find_driver(driver_path, std::move(driver_vmo), &drv)) < 0) {
+ log(ERROR, "devhost[%s] driver load failed: %d\n", ctx->path, r);
+ return BindReply(dev, txn, r);
+ }
+
+ if (drv->has_bind_op()) {
+ BindContext bind_ctx = {
+ .parent = dev,
+ .child = nullptr,
+ };
+ r = drv->BindOp(&bind_ctx, dev);
+
+ if ((r == ZX_OK) && (bind_ctx.child == nullptr)) {
+ printf("devhost: WARNING: driver '%.*s' did not add device in bind()\n",
+ static_cast<int>(driver_path_size), driver_path_data);
}
-
- zx_status_t r;
- if ((r = dh_find_driver(driver_path, std::move(driver_vmo), &drv)) < 0) {
- log(ERROR, "devhost[%s] driver load failed: %d\n", ctx->path, r);
- return BindReply(dev, txn, r);
+ if (r != ZX_OK) {
+ log(ERROR, "devhost[%s] bind driver '%.*s' failed: %d\n", ctx->path,
+ static_cast<int>(driver_path_size), driver_path_data, r);
}
+ return BindReply(dev, txn, r);
+ }
- if (drv->has_bind_op()) {
- BindContext bind_ctx = {
- .parent = dev,
- .child = nullptr,
- };
- r = drv->BindOp(&bind_ctx, dev);
-
- if ((r == ZX_OK) && (bind_ctx.child == nullptr)) {
- printf("devhost: WARNING: driver '%.*s' did not add device in bind()\n",
- static_cast<int>(driver_path_size), driver_path_data);
- }
- if (r != ZX_OK) {
- log(ERROR, "devhost[%s] bind driver '%.*s' failed: %d\n", ctx->path,
- static_cast<int>(driver_path_size), driver_path_data, r);
- }
- return BindReply(dev, txn, r);
- }
-
- if (!drv->has_create_op()) {
- log(ERROR, "devhost[%s] neither create nor bind are implemented: '%.*s'\n", ctx->path,
- static_cast<int>(driver_path_size), driver_path_data);
- }
- return BindReply(dev, txn, ZX_ERR_NOT_SUPPORTED);
+ if (!drv->has_create_op()) {
+ log(ERROR, "devhost[%s] neither create nor bind are implemented: '%.*s'\n", ctx->path,
+ static_cast<int>(driver_path_size), driver_path_data);
+ }
+ return BindReply(dev, txn, ZX_ERR_NOT_SUPPORTED);
}
zx_status_t fidl_ConnectProxy(void* raw_ctx, zx_handle_t raw_shadow) {
- auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
- zx::channel shadow(raw_shadow);
+ auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
+ zx::channel shadow(raw_shadow);
- log(RPC_SDW, "devhost[%s] connect proxy rpc\n", ctx->path);
- ctx->conn->dev()->ops->rxrpc(ctx->conn->dev()->ctx, ZX_HANDLE_INVALID);
- // Ignore any errors in the creation for now?
- // TODO(teisenbe/kulakowski): Investigate if this is the right thing
- ProxyIostate::Create(ctx->conn->dev(), std::move(shadow), DevhostAsyncLoop()->dispatcher());
- return ZX_OK;
+ log(RPC_SDW, "devhost[%s] connect proxy rpc\n", ctx->path);
+ ctx->conn->dev()->ops->rxrpc(ctx->conn->dev()->ctx, ZX_HANDLE_INVALID);
+ // Ignore any errors in the creation for now?
+ // TODO(teisenbe/kulakowski): Investigate if this is the right thing
+ ProxyIostate::Create(ctx->conn->dev(), std::move(shadow), DevhostAsyncLoop()->dispatcher());
+ return ZX_OK;
}
zx_status_t fidl_Suspend(void* raw_ctx, uint32_t flags, fidl_txn_t* txn) {
- auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
- zx_status_t r;
- {
- ApiAutoLock lock;
- r = devhost_device_suspend(ctx->conn->dev(), flags);
- }
- return fuchsia_device_manager_DeviceControllerSuspend_reply(txn, r);
+ auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
+ zx_status_t r;
+ {
+ ApiAutoLock lock;
+ r = devhost_device_suspend(ctx->conn->dev(), flags);
+ }
+ return fuchsia_device_manager_DeviceControllerSuspend_reply(txn, r);
}
zx_status_t fidl_Unbind(void* raw_ctx) {
- auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
- zx_status_t r;
- {
- ApiAutoLock lock;
- r = devhost_device_unbind(ctx->conn->dev());
- }
- return r;
+ auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
+ zx_status_t r;
+ {
+ ApiAutoLock lock;
+ r = devhost_device_unbind(ctx->conn->dev());
+ }
+ return r;
}
zx_status_t fidl_RemoveDevice(void* raw_ctx) {
- auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
- device_remove(ctx->conn->dev().get());
- return ZX_OK;
+ auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
+ device_remove(ctx->conn->dev().get());
+ return ZX_OK;
}
// Handler for when open() is called on a device
zx_status_t fidl_DirectoryOpen(void* ctx, uint32_t flags, uint32_t mode, const char* path_data,
size_t path_size, zx_handle_t object) {
- zx::channel c(object);
- if (path_size != 1 && path_data[0] != '.') {
- log(ERROR, "devhost: Tried to open path '%.*s'\n", static_cast<int>(path_size), path_data);
- return ZX_OK;
- }
- auto conn = static_cast<DeviceControllerConnection*>(ctx);
- devhost_device_connect(conn->dev(), flags, std::move(c));
+ zx::channel c(object);
+ if (path_size != 1 && path_data[0] != '.') {
+ log(ERROR, "devhost: Tried to open path '%.*s'\n", static_cast<int>(path_size), path_data);
return ZX_OK;
+ }
+ auto conn = static_cast<DeviceControllerConnection*>(ctx);
+ devhost_device_connect(conn->dev(), flags, std::move(c));
+ return ZX_OK;
}
const fuchsia_device_manager_DeviceController_ops_t kDefaultDeviceOps = {
@@ -142,165 +142,159 @@
};
const fuchsia_io_Directory_ops_t kDefaultDirectoryOps = []() {
- fuchsia_io_Directory_ops_t ops;
- ops.Open = fidl_DirectoryOpen;
- return ops;
+ fuchsia_io_Directory_ops_t ops;
+ ops.Open = fidl_DirectoryOpen;
+ return ops;
}();
-zx_status_t dh_null_reply(fidl_txn_t* reply, const fidl_msg_t* msg) {
- return ZX_OK;
-}
+zx_status_t dh_null_reply(fidl_txn_t* reply, const fidl_msg_t* msg) { return ZX_OK; }
-} // namespace
+} // namespace
DeviceControllerConnection::DeviceControllerConnection(
- fbl::RefPtr<zx_device> dev, zx::channel rpc,
- const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
- const fuchsia_io_Directory_ops_t* directory_fidl_ops)
- : dev_(std::move(dev)), device_fidl_ops_(device_fidl_ops),
+ fbl::RefPtr<zx_device> dev, zx::channel rpc,
+ const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
+ const fuchsia_io_Directory_ops_t* directory_fidl_ops)
+ : dev_(std::move(dev)),
+ device_fidl_ops_(device_fidl_ops),
directory_fidl_ops_(directory_fidl_ops) {
-
- dev_->rpc = zx::unowned_channel(rpc);
- dev_->conn.store(this);
- set_channel(std::move(rpc));
+ dev_->rpc = zx::unowned_channel(rpc);
+ dev_->conn.store(this);
+ set_channel(std::move(rpc));
}
DeviceControllerConnection::~DeviceControllerConnection() {
- // Ensure that the device has no dangling references to the resources we're
- // destroying. This is safe because a device only ever has one associated
- // DeviceControllerConnection.
- dev_->conn.store(nullptr);
- dev_->rpc = zx::unowned_channel();
+ // Ensure that the device has no dangling references to the resources we're
+ // destroying. This is safe because a device only ever has one associated
+ // DeviceControllerConnection.
+ dev_->conn.store(nullptr);
+ dev_->rpc = zx::unowned_channel();
+}
+
+zx_status_t DeviceControllerConnection::Create(fbl::RefPtr<zx_device> dev, zx::channel rpc,
+ std::unique_ptr<DeviceControllerConnection>* conn) {
+ return Create(std::move(dev), std::move(rpc), &kDefaultDeviceOps, &kDefaultDirectoryOps, conn);
}
zx_status_t DeviceControllerConnection::Create(
- fbl::RefPtr<zx_device> dev, zx::channel rpc,
- std::unique_ptr<DeviceControllerConnection>* conn) {
- return Create(std::move(dev), std::move(rpc), &kDefaultDeviceOps, &kDefaultDirectoryOps, conn);
+ fbl::RefPtr<zx_device> dev, zx::channel rpc,
+ const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
+ const fuchsia_io_Directory_ops_t* directory_fidl_ops,
+ std::unique_ptr<DeviceControllerConnection>* conn) {
+ *conn = std::make_unique<DeviceControllerConnection>(std::move(dev), std::move(rpc),
+ device_fidl_ops, directory_fidl_ops);
+ if (*conn == nullptr) {
+ return ZX_ERR_NO_MEMORY;
+ }
+ return ZX_OK;
}
-zx_status_t DeviceControllerConnection::Create(
- fbl::RefPtr<zx_device> dev, zx::channel rpc,
- const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
- const fuchsia_io_Directory_ops_t* directory_fidl_ops,
- std::unique_ptr<DeviceControllerConnection>* conn) {
- *conn = std::make_unique<DeviceControllerConnection>(std::move(dev), std::move(rpc),
- device_fidl_ops, directory_fidl_ops);
- if (*conn == nullptr) {
- return ZX_ERR_NO_MEMORY;
- }
- return ZX_OK;
-}
-
-void DeviceControllerConnection::HandleRpc(
- std::unique_ptr<DeviceControllerConnection> conn, async_dispatcher_t* dispatcher,
- async::WaitBase* wait, zx_status_t status, const zx_packet_signal_t* signal) {
- if (status != ZX_OK) {
- log(ERROR, "devhost: devcoord conn wait error: %d\n", status);
+void DeviceControllerConnection::HandleRpc(std::unique_ptr<DeviceControllerConnection> conn,
+ async_dispatcher_t* dispatcher, async::WaitBase* wait,
+ zx_status_t status, const zx_packet_signal_t* signal) {
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: devcoord conn wait error: %d\n", status);
+ return;
+ }
+ if (signal->observed & ZX_CHANNEL_READABLE) {
+ zx_status_t r = conn->HandleRead();
+ if (r != ZX_OK) {
+ if (conn->dev_->conn.load() == nullptr && r == ZX_ERR_INTERNAL) {
+ // Treat this as a PEER_CLOSED below. It can happen if the
+ // devcoordinator sent us a request while we asked the
+ // devcoordinator to remove us. The coordinator then closes the
+ // channel before we can reply, and the FIDL bindings convert
+ // the PEER_CLOSED on zx_channel_write() to a ZX_ERR_INTERNAL. See ZX-4114.
+ __UNUSED auto r = conn.release();
return;
+ }
+ log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%d. fatal.\n", conn.get(), r);
+ abort();
}
- if (signal->observed & ZX_CHANNEL_READABLE) {
- zx_status_t r = conn->HandleRead();
- if (r != ZX_OK) {
- if (conn->dev_->conn.load() == nullptr && r == ZX_ERR_INTERNAL) {
- // Treat this as a PEER_CLOSED below. It can happen if the
- // devcoordinator sent us a request while we asked the
- // devcoordinator to remove us. The coordinator then closes the
- // channel before we can reply, and the FIDL bindings convert
- // the PEER_CLOSED on zx_channel_write() to a ZX_ERR_INTERNAL. See ZX-4114.
- __UNUSED auto r = conn.release();
- return;
- }
- log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%d. fatal.\n", conn.get(), r);
- abort();
- }
- BeginWait(std::move(conn), dispatcher);
- return;
- }
- if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
- // Check if we were expecting this peer close. If not, this could be a
- // serious bug.
- if (conn->dev_->conn.load() == nullptr) {
- // We're in the middle of shutting down, so just stop processing
- // signals and wait for the queued shutdown packet. It has a
- // reference to the connection, which it will use to recover
- // ownership of it.
- __UNUSED auto r = conn.release();
- return;
- }
-
- log(ERROR, "devhost: devmgr disconnected! fatal. (conn=%p)\n", conn.get());
- abort();
- }
- log(ERROR, "devhost: no work? %08x\n", signal->observed);
BeginWait(std::move(conn), dispatcher);
+ return;
+ }
+ if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
+ // Check if we were expecting this peer close. If not, this could be a
+ // serious bug.
+ if (conn->dev_->conn.load() == nullptr) {
+ // We're in the middle of shutting down, so just stop processing
+ // signals and wait for the queued shutdown packet. It has a
+ // reference to the connection, which it will use to recover
+ // ownership of it.
+ __UNUSED auto r = conn.release();
+ return;
+ }
+
+ log(ERROR, "devhost: devmgr disconnected! fatal. (conn=%p)\n", conn.get());
+ abort();
+ }
+ log(ERROR, "devhost: no work? %08x\n", signal->observed);
+ BeginWait(std::move(conn), dispatcher);
}
zx_status_t DeviceControllerConnection::HandleRead() {
- zx::unowned_channel conn = channel();
- uint8_t msg[8192];
- zx_handle_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
- uint32_t msize = sizeof(msg);
- uint32_t hcount = fbl::count_of(hin);
- zx_status_t status = conn->read(0, msg, hin, msize, hcount, &msize, &hcount);
- if (status != ZX_OK) {
- return status;
- }
+ zx::unowned_channel conn = channel();
+ uint8_t msg[8192];
+ zx_handle_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
+ uint32_t msize = sizeof(msg);
+ uint32_t hcount = fbl::count_of(hin);
+ zx_status_t status = conn->read(0, msg, hin, msize, hcount, &msize, &hcount);
+ if (status != ZX_OK) {
+ return status;
+ }
- fidl_msg_t fidl_msg = {
- .bytes = msg,
- .handles = hin,
- .num_bytes = msize,
- .num_handles = hcount,
+ fidl_msg_t fidl_msg = {
+ .bytes = msg,
+ .handles = hin,
+ .num_bytes = msize,
+ .num_handles = hcount,
+ };
+
+ if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
+ zx_handle_close_many(fidl_msg.handles, fidl_msg.num_handles);
+ return ZX_ERR_IO;
+ }
+
+ char buffer[512];
+ const char* path = mkdevpath(dev_, buffer, sizeof(buffer));
+
+ // Double-check that Open (the only message we forward) cannot be mistaken for an
+ // internal dev coordinator RPC message.
+ static_assert(
+ fuchsia_device_manager_DevhostControllerCreateDeviceStubOrdinal !=
+ fuchsia_io_DirectoryOpenOrdinal &&
+ fuchsia_device_manager_DevhostControllerCreateDeviceOrdinal !=
+ fuchsia_io_DirectoryOpenOrdinal &&
+ fuchsia_device_manager_DeviceControllerBindDriverOrdinal != fuchsia_io_DirectoryOpenOrdinal &&
+ fuchsia_device_manager_DeviceControllerConnectProxyOrdinal !=
+ fuchsia_io_DirectoryOpenOrdinal &&
+ fuchsia_device_manager_DeviceControllerSuspendOrdinal != fuchsia_io_DirectoryOpenOrdinal &&
+ fuchsia_device_manager_DeviceControllerRemoveDeviceOrdinal !=
+ fuchsia_io_DirectoryOpenOrdinal);
+
+ auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
+ // Depending on the state of the migration, GenOrdinal and Ordinal may be the
+ // same value. See FIDL-524.
+ uint64_t ordinal = hdr->ordinal;
+ if (ordinal == fuchsia_io_DirectoryOpenOrdinal || ordinal == fuchsia_io_DirectoryOpenGenOrdinal) {
+ log(RPC_RIO, "devhost[%s] FIDL OPEN\n", path);
+
+ fidl_txn_t dh_null_txn = {
+ .reply = dh_null_reply,
};
-
- if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
- zx_handle_close_many(fidl_msg.handles, fidl_msg.num_handles);
- return ZX_ERR_IO;
+ status = fuchsia_io_Directory_dispatch(this, &dh_null_txn, &fidl_msg, directory_fidl_ops_);
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: OPEN failed: %s\n", zx_status_get_string(status));
+ return status;
}
+ return ZX_OK;
+ }
- char buffer[512];
- const char* path = mkdevpath(dev_, buffer, sizeof(buffer));
-
- // Double-check that Open (the only message we forward) cannot be mistaken for an
- // internal dev coordinator RPC message.
- static_assert(
- fuchsia_device_manager_DevhostControllerCreateDeviceStubOrdinal !=
- fuchsia_io_DirectoryOpenOrdinal &&
- fuchsia_device_manager_DevhostControllerCreateDeviceOrdinal !=
- fuchsia_io_DirectoryOpenOrdinal &&
- fuchsia_device_manager_DeviceControllerBindDriverOrdinal !=
- fuchsia_io_DirectoryOpenOrdinal &&
- fuchsia_device_manager_DeviceControllerConnectProxyOrdinal !=
- fuchsia_io_DirectoryOpenOrdinal &&
- fuchsia_device_manager_DeviceControllerSuspendOrdinal !=
- fuchsia_io_DirectoryOpenOrdinal &&
- fuchsia_device_manager_DeviceControllerRemoveDeviceOrdinal !=
- fuchsia_io_DirectoryOpenOrdinal);
-
- auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
- // Depending on the state of the migration, GenOrdinal and Ordinal may be the
- // same value. See FIDL-524.
- uint64_t ordinal = hdr->ordinal;
- if (ordinal == fuchsia_io_DirectoryOpenOrdinal ||
- ordinal == fuchsia_io_DirectoryOpenGenOrdinal) {
- log(RPC_RIO, "devhost[%s] FIDL OPEN\n", path);
-
- fidl_txn_t dh_null_txn = {
- .reply = dh_null_reply,
- };
- status = fuchsia_io_Directory_dispatch(this, &dh_null_txn, &fidl_msg, directory_fidl_ops_);
- if (status != ZX_OK) {
- log(ERROR, "devhost: OPEN failed: %s\n", zx_status_get_string(status));
- return status;
- }
- return ZX_OK;
- }
-
- FidlTxn txn(std::move(conn), hdr->txid);
- DevhostRpcReadContext read_ctx = {path, this};
- return fuchsia_device_manager_DeviceController_dispatch(&read_ctx, txn.fidl_txn(), &fidl_msg,
- device_fidl_ops_);
+ FidlTxn txn(std::move(conn), hdr->txid);
+ DevhostRpcReadContext read_ctx = {path, this};
+ return fuchsia_device_manager_DeviceController_dispatch(&read_ctx, txn.fidl_txn(), &fidl_msg,
+ device_fidl_ops_);
}
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/device-controller-connection.h b/zircon/system/core/devmgr/devhost/device-controller-connection.h
index 69c57e3..72e53ab 100644
--- a/zircon/system/core/devmgr/devhost/device-controller-connection.h
+++ b/zircon/system/core/devmgr/devhost/device-controller-connection.h
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_DEVICE_CONTROLLER_CONNECTION_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_DEVICE_CONTROLLER_CONNECTION_H_
#include <fbl/ref_ptr.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/zx/channel.h>
+
#include "../shared/async-loop-owned-rpc-handler.h"
struct zx_device;
@@ -15,37 +17,39 @@
namespace devmgr {
class DeviceControllerConnection : public AsyncLoopOwnedRpcHandler<DeviceControllerConnection> {
-public:
- DeviceControllerConnection(fbl::RefPtr<zx_device> dev, zx::channel rpc,
- const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
- const fuchsia_io_Directory_ops_t* directory_fidl_ops);
+ public:
+ DeviceControllerConnection(fbl::RefPtr<zx_device> dev, zx::channel rpc,
+ const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
+ const fuchsia_io_Directory_ops_t* directory_fidl_ops);
- static zx_status_t Create(fbl::RefPtr<zx_device> dev, zx::channel rpc,
- std::unique_ptr<DeviceControllerConnection>* conn);
- static zx_status_t Create(fbl::RefPtr<zx_device> dev, zx::channel rpc,
- const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
- const fuchsia_io_Directory_ops_t* directory_fidl_ops,
- std::unique_ptr<DeviceControllerConnection>* conn);
+ static zx_status_t Create(fbl::RefPtr<zx_device> dev, zx::channel rpc,
+ std::unique_ptr<DeviceControllerConnection>* conn);
+ static zx_status_t Create(fbl::RefPtr<zx_device> dev, zx::channel rpc,
+ const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops,
+ const fuchsia_io_Directory_ops_t* directory_fidl_ops,
+ std::unique_ptr<DeviceControllerConnection>* conn);
- ~DeviceControllerConnection();
+ ~DeviceControllerConnection();
- static void HandleRpc(std::unique_ptr<DeviceControllerConnection> conn,
- async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
- const zx_packet_signal_t* signal);
- zx_status_t HandleRead();
+ static void HandleRpc(std::unique_ptr<DeviceControllerConnection> conn,
+ async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
+ const zx_packet_signal_t* signal);
+ zx_status_t HandleRead();
- const fbl::RefPtr<zx_device>& dev() const { return dev_; }
-private:
- const fbl::RefPtr<zx_device> dev_;
+ const fbl::RefPtr<zx_device>& dev() const { return dev_; }
- const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops_;
- const fuchsia_io_Directory_ops_t* directory_fidl_ops_;
+ private:
+ const fbl::RefPtr<zx_device> dev_;
+
+ const fuchsia_device_manager_DeviceController_ops_t* device_fidl_ops_;
+ const fuchsia_io_Directory_ops_t* directory_fidl_ops_;
};
struct DevhostRpcReadContext {
- const char* path;
- DeviceControllerConnection* conn;
+ const char* path;
+ DeviceControllerConnection* conn;
};
-} // namespace devmgr
+} // namespace devmgr
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_DEVICE_CONTROLLER_CONNECTION_H_
diff --git a/zircon/system/core/devmgr/devhost/lock.h b/zircon/system/core/devmgr/devhost/lock.h
index 07813c2..471f6f3 100644
--- a/zircon/system/core/devmgr/devhost/lock.h
+++ b/zircon/system/core/devmgr/devhost/lock.h
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_LOCK_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_LOCK_H_
-#include <atomic>
#include <threads.h>
#include <zircon/thread_annotations.h>
+#include <atomic>
+
namespace devmgr {
// locking and lock debugging
@@ -15,35 +17,37 @@
namespace internal {
extern mtx_t devhost_api_lock;
extern std::atomic<thrd_t> devhost_api_lock_owner;
-} // namespace internal
+} // namespace internal
#define REQ_DM_LOCK TA_REQ(&::devmgr::internal::devhost_api_lock)
#define USE_DM_LOCK TA_GUARDED(&::devmgr::internal::devhost_api_lock)
static inline void DM_LOCK() TA_ACQ(&::devmgr::internal::devhost_api_lock) {
- mtx_lock(&internal::devhost_api_lock);
- internal::devhost_api_lock_owner.store(thrd_current());
+ mtx_lock(&internal::devhost_api_lock);
+ internal::devhost_api_lock_owner.store(thrd_current());
}
static inline void DM_UNLOCK() TA_REL(&::devmgr::internal::devhost_api_lock) {
- internal::devhost_api_lock_owner.store(0);
- mtx_unlock(&internal::devhost_api_lock);
+ internal::devhost_api_lock_owner.store(0);
+ mtx_unlock(&internal::devhost_api_lock);
}
static inline bool DM_LOCK_HELD() {
- return thrd_equal(internal::devhost_api_lock_owner.load(), thrd_current());
+ return thrd_equal(internal::devhost_api_lock_owner.load(), thrd_current());
}
class ApiAutoLock {
-public:
- ApiAutoLock() TA_ACQ(&::devmgr::internal::devhost_api_lock) { DM_LOCK(); }
- ~ApiAutoLock() TA_REL(&::devmgr::internal::devhost_api_lock) { DM_UNLOCK(); }
+ public:
+ ApiAutoLock() TA_ACQ(&::devmgr::internal::devhost_api_lock) { DM_LOCK(); }
+ ~ApiAutoLock() TA_REL(&::devmgr::internal::devhost_api_lock) { DM_UNLOCK(); }
};
class ApiAutoRelock {
-public:
- ApiAutoRelock() TA_REL(&::devmgr::internal::devhost_api_lock) { DM_UNLOCK(); }
- ~ApiAutoRelock() TA_ACQ(&::devmgr::internal::devhost_api_lock) { DM_LOCK(); }
+ public:
+ ApiAutoRelock() TA_REL(&::devmgr::internal::devhost_api_lock) { DM_UNLOCK(); }
+ ~ApiAutoRelock() TA_ACQ(&::devmgr::internal::devhost_api_lock) { DM_LOCK(); }
};
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_LOCK_H_
diff --git a/zircon/system/core/devmgr/devhost/main.cc b/zircon/system/core/devmgr/devhost/main.cc
index 635fce0..7324c63 100644
--- a/zircon/system/core/devmgr/devhost/main.cc
+++ b/zircon/system/core/devmgr/devhost/main.cc
@@ -8,9 +8,7 @@
__BEGIN_CDECLS
-int main(int argc, char** argv) {
- devmgr_device_host_main(argc, argv);
-}
+int main(int argc, char** argv) { devmgr_device_host_main(argc, argv); }
// All drivers have a pure C ABI. But each individual driver might statically
// link in its own copy of some C++ library code. Since no C++ language
@@ -25,9 +23,7 @@
// caught either.
#if __has_feature(address_sanitizer)
#include <sanitizer/asan_interface.h>
-const char* __asan_default_options() {
- return "detect_odr_violation=0";
-}
+const char* __asan_default_options() { return "detect_odr_violation=0"; }
#endif
__END_CDECLS
diff --git a/zircon/system/core/devmgr/devhost/main.h b/zircon/system/core/devmgr/devhost/main.h
index 7e67989..3e00f01 100644
--- a/zircon/system/core/devmgr/devhost/main.h
+++ b/zircon/system/core/devmgr/devhost/main.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_MAIN_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_MAIN_H_
extern "C" int devmgr_device_host_main(int argc, char** argv);
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_MAIN_H_
diff --git a/zircon/system/core/devmgr/devhost/proxy-iostate-test.cc b/zircon/system/core/devmgr/devhost/proxy-iostate-test.cc
index aac672c..d4cb7bd 100644
--- a/zircon/system/core/devmgr/devhost/proxy-iostate-test.cc
+++ b/zircon/system/core/devmgr/devhost/proxy-iostate-test.cc
@@ -2,34 +2,36 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "proxy-iostate.h"
+
#include <fbl/auto_lock.h>
#include <lib/async-loop/cpp/loop.h>
#include <zxtest/zxtest.h>
-#include "proxy-iostate.h"
+
#include "zx-device.h"
namespace {
TEST(ProxyIostateTestCase, Creation) {
- async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx::channel proxy_local, proxy_remote;
- ASSERT_OK(zx::channel::create(0, &proxy_local, &proxy_remote));
+ zx::channel proxy_local, proxy_remote;
+ ASSERT_OK(zx::channel::create(0, &proxy_local, &proxy_remote));
- {
- fbl::AutoLock guard(&dev->proxy_ios_lock);
- ASSERT_NULL(dev->proxy_ios);
- }
- ASSERT_OK(devmgr::ProxyIostate::Create(dev, std::move(proxy_remote), loop.dispatcher()));
- {
- fbl::AutoLock guard(&dev->proxy_ios_lock);
- ASSERT_NOT_NULL(dev->proxy_ios);
- }
+ {
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
+ ASSERT_NULL(dev->proxy_ios);
+ }
+ ASSERT_OK(devmgr::ProxyIostate::Create(dev, std::move(proxy_remote), loop.dispatcher()));
+ {
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
+ ASSERT_NOT_NULL(dev->proxy_ios);
+ }
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(loop.RunUntilIdle());
}
// This test reproduces the bug from ZX-4060, in which we would double-free the
@@ -37,26 +39,26 @@
// gets queued, but before the channel close is processed. If the bug is
// present, and we're running with ASAN, this will crash 100% of the time.
TEST(ProxyIostateTestCase, ChannelCloseThenCancel) {
- async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
- fbl::RefPtr<zx_device> dev;
- ASSERT_OK(zx_device::Create(&dev));
+ fbl::RefPtr<zx_device> dev;
+ ASSERT_OK(zx_device::Create(&dev));
- zx::channel proxy_local, proxy_remote;
- ASSERT_OK(zx::channel::create(0, &proxy_local, &proxy_remote));
+ zx::channel proxy_local, proxy_remote;
+ ASSERT_OK(zx::channel::create(0, &proxy_local, &proxy_remote));
- ASSERT_OK(devmgr::ProxyIostate::Create(dev, std::move(proxy_remote), loop.dispatcher()));
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(devmgr::ProxyIostate::Create(dev, std::move(proxy_remote), loop.dispatcher()));
+ ASSERT_OK(loop.RunUntilIdle());
- proxy_local.reset();
+ proxy_local.reset();
- {
- fbl::AutoLock guard(&dev->proxy_ios_lock);
- dev->proxy_ios->CancelLocked(loop.dispatcher());
- ASSERT_NULL(dev->proxy_ios);
- }
+ {
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
+ dev->proxy_ios->CancelLocked(loop.dispatcher());
+ ASSERT_NULL(dev->proxy_ios);
+ }
- ASSERT_OK(loop.RunUntilIdle());
+ ASSERT_OK(loop.RunUntilIdle());
}
-} // namespace
+} // namespace
diff --git a/zircon/system/core/devmgr/devhost/proxy-iostate.cc b/zircon/system/core/devmgr/devhost/proxy-iostate.cc
index 332c034..d350074 100644
--- a/zircon/system/core/devmgr/devhost/proxy-iostate.cc
+++ b/zircon/system/core/devmgr/devhost/proxy-iostate.cc
@@ -5,6 +5,7 @@
#include "proxy-iostate.h"
#include <fbl/auto_lock.h>
+
#include "../shared/log.h"
#include "connection-destroyer.h"
#include "zx-device.h"
@@ -12,92 +13,91 @@
namespace devmgr {
ProxyIostate::~ProxyIostate() {
- fbl::AutoLock guard(&dev->proxy_ios_lock);
- ZX_ASSERT(dev->proxy_ios != this);
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
+ ZX_ASSERT(dev->proxy_ios != this);
}
// Handling RPC From Proxy Devices to BusDevs
void ProxyIostate::HandleRpc(fbl::unique_ptr<ProxyIostate> conn, async_dispatcher_t* dispatcher,
async::WaitBase* wait, zx_status_t status,
const zx_packet_signal_t* signal) {
- auto handle_destroy = [&conn]() {
- fbl::AutoLock guard(&conn->dev->proxy_ios_lock);
- // If proxy_ios is not |conn|, then it's had a packet queued already to
- // destroy it, so we should let the queued destruction handle things.
- // Otherwise we should destroy it.
- if (conn->dev->proxy_ios == conn.get()) {
- // Mark proxy_ios as disconnected, so that CancelLocked doesn't try to
- // destroy it too
- conn->dev->proxy_ios = nullptr;
- // The actual destruction will happen when |conn| goes out of scope.
- } else {
- __UNUSED auto ptr = conn.release();
- }
- };
- if (status != ZX_OK) {
- return handle_destroy();
+ auto handle_destroy = [&conn]() {
+ fbl::AutoLock guard(&conn->dev->proxy_ios_lock);
+ // If proxy_ios is not |conn|, then it's had a packet queued already to
+ // destroy it, so we should let the queued destruction handle things.
+ // Otherwise we should destroy it.
+ if (conn->dev->proxy_ios == conn.get()) {
+ // Mark proxy_ios as disconnected, so that CancelLocked doesn't try to
+ // destroy it too
+ conn->dev->proxy_ios = nullptr;
+ // The actual destruction will happen when |conn| goes out of scope.
+ } else {
+ __UNUSED auto ptr = conn.release();
}
+ };
+ if (status != ZX_OK) {
+ return handle_destroy();
+ }
- if (conn->dev == nullptr) {
- log(RPC_SDW, "proxy-rpc: stale rpc? (ios=%p)\n", conn.get());
- // Do not re-issue the wait here
- return handle_destroy();
+ if (conn->dev == nullptr) {
+ log(RPC_SDW, "proxy-rpc: stale rpc? (ios=%p)\n", conn.get());
+ // Do not re-issue the wait here
+ return handle_destroy();
+ }
+ if (signal->observed & ZX_CHANNEL_READABLE) {
+ log(RPC_SDW, "proxy-rpc: rpc readable (ios=%p,dev=%p)\n", conn.get(), conn->dev.get());
+ zx_status_t r = conn->dev->ops->rxrpc(conn->dev->ctx, wait->object());
+ if (r != ZX_OK) {
+ log(RPC_SDW, "proxy-rpc: rpc cb error %d (ios=%p,dev=%p)\n", r, conn.get(), conn->dev.get());
+ return handle_destroy();
}
- if (signal->observed & ZX_CHANNEL_READABLE) {
- log(RPC_SDW, "proxy-rpc: rpc readable (ios=%p,dev=%p)\n", conn.get(), conn->dev.get());
- zx_status_t r = conn->dev->ops->rxrpc(conn->dev->ctx, wait->object());
- if (r != ZX_OK) {
- log(RPC_SDW, "proxy-rpc: rpc cb error %d (ios=%p,dev=%p)\n", r, conn.get(),
- conn->dev.get());
- return handle_destroy();
- }
- BeginWait(std::move(conn), dispatcher);
- return;
- }
- if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
- log(RPC_SDW, "proxy-rpc: peer closed (ios=%p,dev=%p)\n", conn.get(), conn->dev.get());
- return handle_destroy();
- }
- log(ERROR, "devhost: no work? %08x\n", signal->observed);
BeginWait(std::move(conn), dispatcher);
+ return;
+ }
+ if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
+ log(RPC_SDW, "proxy-rpc: peer closed (ios=%p,dev=%p)\n", conn.get(), conn->dev.get());
+ return handle_destroy();
+ }
+ log(ERROR, "devhost: no work? %08x\n", signal->observed);
+ BeginWait(std::move(conn), dispatcher);
}
zx_status_t ProxyIostate::Create(const fbl::RefPtr<zx_device_t>& dev, zx::channel rpc,
async_dispatcher_t* dispatcher) {
- // This must be held for the adding of the channel to the port, since the
- // async loop may run immediately after that point.
- fbl::AutoLock guard(&dev->proxy_ios_lock);
+ // This must be held for the adding of the channel to the port, since the
+ // async loop may run immediately after that point.
+ fbl::AutoLock guard(&dev->proxy_ios_lock);
- if (dev->proxy_ios) {
- dev->proxy_ios->CancelLocked(dispatcher);
- }
+ if (dev->proxy_ios) {
+ dev->proxy_ios->CancelLocked(dispatcher);
+ }
- auto ios = std::make_unique<ProxyIostate>(dev);
- if (ios == nullptr) {
- return ZX_ERR_NO_MEMORY;
- }
+ auto ios = std::make_unique<ProxyIostate>(dev);
+ if (ios == nullptr) {
+ return ZX_ERR_NO_MEMORY;
+ }
- ios->set_channel(std::move(rpc));
+ ios->set_channel(std::move(rpc));
- // |ios| is will be owned by the async loop. |dev| holds a reference that will be
- // cleared prior to destruction.
- dev->proxy_ios = ios.get();
+ // |ios| is will be owned by the async loop. |dev| holds a reference that will be
+ // cleared prior to destruction.
+ dev->proxy_ios = ios.get();
- zx_status_t status = BeginWait(std::move(ios), dispatcher);
- if (status != ZX_OK) {
- dev->proxy_ios = nullptr;
- return status;
- }
+ zx_status_t status = BeginWait(std::move(ios), dispatcher);
+ if (status != ZX_OK) {
+ dev->proxy_ios = nullptr;
+ return status;
+ }
- return ZX_OK;
+ return ZX_OK;
}
void ProxyIostate::CancelLocked(async_dispatcher_t* dispatcher) {
- ZX_ASSERT(this->dev->proxy_ios == this);
- this->dev->proxy_ios = nullptr;
- // TODO(teisenbe): We should probably check the return code in case the
- // queue was full
- ConnectionDestroyer::Get()->QueueProxyConnection(dispatcher, this);
+ ZX_ASSERT(this->dev->proxy_ios == this);
+ this->dev->proxy_ios = nullptr;
+ // TODO(teisenbe): We should probably check the return code in case the
+ // queue was full
+ ConnectionDestroyer::Get()->QueueProxyConnection(dispatcher, this);
}
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/proxy-iostate.h b/zircon/system/core/devmgr/devhost/proxy-iostate.h
index 05d0d55..f166f76 100644
--- a/zircon/system/core/devmgr/devhost/proxy-iostate.h
+++ b/zircon/system/core/devmgr/devhost/proxy-iostate.h
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_PROXY_IOSTATE_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_PROXY_IOSTATE_H_
#include <fbl/ref_ptr.h>
#include <fbl/unique_ptr.h>
#include <lib/async/cpp/wait.h>
#include <lib/zx/channel.h>
#include <zircon/thread_annotations.h>
+
#include "../shared/async-loop-owned-rpc-handler.h"
struct zx_device;
@@ -16,28 +18,30 @@
namespace devmgr {
struct ProxyIostate : AsyncLoopOwnedRpcHandler<ProxyIostate> {
- explicit ProxyIostate(fbl::RefPtr<zx_device> device) : dev(std::move(device)) {}
- ~ProxyIostate();
+ explicit ProxyIostate(fbl::RefPtr<zx_device> device) : dev(std::move(device)) {}
+ ~ProxyIostate();
- // Creates a ProxyIostate and points |dev| at it. The ProxyIostate is owned
- // by the async loop, and its destruction may be requested by calling
- // Cancel().
- static zx_status_t Create(const fbl::RefPtr<zx_device>& dev, zx::channel rpc,
- async_dispatcher_t* dispatcher);
+ // Creates a ProxyIostate and points |dev| at it. The ProxyIostate is owned
+ // by the async loop, and its destruction may be requested by calling
+ // Cancel().
+ static zx_status_t Create(const fbl::RefPtr<zx_device>& dev, zx::channel rpc,
+ async_dispatcher_t* dispatcher);
- // Request the destruction of the proxy connection
- // The device for which ProxyIostate is currently attached to should have
- // its proxy_ios_lock held across CancelLocked().
- // We must disable thread safety analysis because the lock is in |this->dev|,
- // and Clang cannot reason about the aliasing involved.
- void CancelLocked(async_dispatcher_t* dispatcher) TA_NO_THREAD_SAFETY_ANALYSIS;
+ // Request the destruction of the proxy connection
+ // The device for which ProxyIostate is currently attached to should have
+ // its proxy_ios_lock held across CancelLocked().
+ // We must disable thread safety analysis because the lock is in |this->dev|,
+ // and Clang cannot reason about the aliasing involved.
+ void CancelLocked(async_dispatcher_t* dispatcher) TA_NO_THREAD_SAFETY_ANALYSIS;
- static void HandleRpc(fbl::unique_ptr<ProxyIostate> conn, async_dispatcher_t* dispatcher,
- async::WaitBase* wait, zx_status_t status,
- const zx_packet_signal_t* signal);
+ static void HandleRpc(fbl::unique_ptr<ProxyIostate> conn, async_dispatcher_t* dispatcher,
+ async::WaitBase* wait, zx_status_t status,
+ const zx_packet_signal_t* signal);
- const fbl::RefPtr<zx_device> dev;
+ const fbl::RefPtr<zx_device> dev;
};
static void proxy_ios_destroy(const fbl::RefPtr<zx_device>& dev);
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_PROXY_IOSTATE_H_
diff --git a/zircon/system/core/devmgr/devhost/rpc-server.cc b/zircon/system/core/devmgr/devhost/rpc-server.cc
index 9ec4e6d..c6c8d44 100644
--- a/zircon/system/core/devmgr/devhost/rpc-server.cc
+++ b/zircon/system/core/devmgr/devhost/rpc-server.cc
@@ -2,42 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "devhost.h"
-#include "zx-device.h"
-
#include <assert.h>
-#include <fcntl.h>
-#include <new>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <threads.h>
-#include <utility>
-
#include <ddk/device.h>
#include <ddk/driver.h>
-#include <lib/sync/completion.h>
-
-#include <zircon/device/ioctl.h>
-#include <zircon/device/vfs.h>
-
-#include <zircon/processargs.h>
-#include <zircon/status.h>
-#include <zircon/syscalls.h>
-#include <zircon/types.h>
-
#include <fbl/auto_lock.h>
+#include <fcntl.h>
#include <fs/connection.h>
#include <fs/handler.h>
#include <fuchsia/device/c/fidl.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
-#include <lib/zircon-internal/debug.h>
#include <lib/fdio/io.h>
#include <lib/fdio/vfs.h>
#include <lib/fidl/coding.h>
+#include <lib/sync/completion.h>
+#include <lib/zircon-internal/debug.h>
#include <lib/zx/channel.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <threads.h>
+#include <zircon/device/ioctl.h>
+#include <zircon/device/vfs.h>
+#include <zircon/processargs.h>
+#include <zircon/status.h>
+#include <zircon/syscalls.h>
+#include <zircon/types.h>
+
+#include <new>
+#include <utility>
+
+#include "devhost.h"
+#include "zx-device.h"
namespace devmgr {
@@ -47,109 +44,108 @@
#define CAN_READ(conn) (conn->flags & ZX_FS_RIGHT_READABLE)
void describe_error(zx::channel h, zx_status_t status) {
- fuchsia_io_NodeOnOpenEvent msg;
- memset(&msg, 0, sizeof(msg));
- msg.hdr.ordinal = fuchsia_io_NodeOnOpenOrdinal;
- msg.s = status;
- h.write(0, &msg, sizeof(msg), nullptr, 0);
+ fuchsia_io_NodeOnOpenEvent msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.hdr.ordinal = fuchsia_io_NodeOnOpenOrdinal;
+ msg.s = status;
+ h.write(0, &msg, sizeof(msg), nullptr, 0);
}
static fidl_union_tag_t device_or_tty(const fbl::RefPtr<zx_device_t>& dev) {
- // only a couple of special cases for now
- const char *libname = dev->driver->libname().c_str();
- if ((strcmp(libname, "/boot/driver/pty.so") == 0) ||
- (strcmp(libname, "/boot/driver/console.so") == 0) ||
- (strcmp(libname, "/boot/driver/virtio.so") == 0)) {
- return fuchsia_io_NodeInfoTag_tty;
- } else {
- return fuchsia_io_NodeInfoTag_device;
- }
+ // only a couple of special cases for now
+ const char* libname = dev->driver->libname().c_str();
+ if ((strcmp(libname, "/boot/driver/pty.so") == 0) ||
+ (strcmp(libname, "/boot/driver/console.so") == 0) ||
+ (strcmp(libname, "/boot/driver/virtio.so") == 0)) {
+ return fuchsia_io_NodeInfoTag_tty;
+ } else {
+ return fuchsia_io_NodeInfoTag_device;
+ }
}
static zx_status_t create_description(const fbl::RefPtr<zx_device_t>& dev, fs::OnOpenMsg* msg,
zx::eventpair* handle) {
- memset(msg, 0, sizeof(*msg));
- msg->primary.hdr.ordinal = fuchsia_io_NodeOnOpenOrdinal;
- msg->extra.tag = device_or_tty(dev);
- msg->primary.s = ZX_OK;
- msg->primary.info = (fuchsia_io_NodeInfo*)FIDL_ALLOC_PRESENT;
- handle->reset();
- zx_handle_t* event = (msg->extra.tag == fuchsia_io_NodeInfoTag_device)
- ? &msg->extra.device.event
- : &msg->extra.tty.event;
- if (dev->event.is_valid()) {
- zx_status_t r;
- if ((r = dev->event.duplicate(ZX_RIGHTS_BASIC, handle)) != ZX_OK) {
- msg->primary.s = r;
- return r;
- }
- *event = FIDL_HANDLE_PRESENT;
- } else {
- *event = FIDL_HANDLE_ABSENT;
+ memset(msg, 0, sizeof(*msg));
+ msg->primary.hdr.ordinal = fuchsia_io_NodeOnOpenOrdinal;
+ msg->extra.tag = device_or_tty(dev);
+ msg->primary.s = ZX_OK;
+ msg->primary.info = (fuchsia_io_NodeInfo*)FIDL_ALLOC_PRESENT;
+ handle->reset();
+ zx_handle_t* event = (msg->extra.tag == fuchsia_io_NodeInfoTag_device) ? &msg->extra.device.event
+ : &msg->extra.tty.event;
+ if (dev->event.is_valid()) {
+ zx_status_t r;
+ if ((r = dev->event.duplicate(ZX_RIGHTS_BASIC, handle)) != ZX_OK) {
+ msg->primary.s = r;
+ return r;
}
+ *event = FIDL_HANDLE_PRESENT;
+ } else {
+ *event = FIDL_HANDLE_ABSENT;
+ }
- return ZX_OK;
+ return ZX_OK;
}
zx_status_t devhost_device_connect(const fbl::RefPtr<zx_device_t>& dev, uint32_t flags,
zx::channel rh) {
- zx_status_t r;
- // detect response directives and discard all other
- // protocol flags
- bool describe = flags & ZX_FS_FLAG_DESCRIBE;
- flags &= (~ZX_FS_FLAG_DESCRIBE);
+ zx_status_t r;
+ // detect response directives and discard all other
+ // protocol flags
+ bool describe = flags & ZX_FS_FLAG_DESCRIBE;
+ flags &= (~ZX_FS_FLAG_DESCRIBE);
- auto newconn = std::make_unique<DevfsConnection>();
- if (!newconn) {
- r = ZX_ERR_NO_MEMORY;
- if (describe) {
- describe_error(std::move(rh), r);
- }
- return r;
- }
-
- newconn->flags = flags;
-
- fbl::RefPtr<zx_device_t> new_dev;
- r = device_open(dev, &new_dev, flags);
- if (r != ZX_OK) {
- fprintf(stderr, "devhost_device_connect(%p:%s) open r=%d\n", dev.get(), dev->name, r);
- goto fail;
- }
- newconn->dev = new_dev;
-
+ auto newconn = std::make_unique<DevfsConnection>();
+ if (!newconn) {
+ r = ZX_ERR_NO_MEMORY;
if (describe) {
- fs::OnOpenMsg info;
- zx::eventpair handle;
- if ((r = create_description(new_dev, &info, &handle)) != ZX_OK) {
- goto fail_open;
- }
- uint32_t hcount = (handle.is_valid()) ? 1 : 0;
- zx_handle_t raw_handles[] = {
- handle.release(),
- };
- r = rh.write(0, &info, sizeof(info), raw_handles, hcount);
- if (r != ZX_OK) {
- goto fail_open;
- }
- }
-
- // If we can't add the new conn and handle to the dispatcher our only option
- // is to give up and tear down. In practice, this should never happen.
- if ((r = devhost_start_connection(std::move(newconn), std::move(rh))) != ZX_OK) {
- fprintf(stderr, "devhost_device_connect: failed to start iostate\n");
- // TODO(teisenbe/kulakowski): Should this be goto fail_open?
- goto fail;
- }
- return ZX_OK;
-
-fail_open:
- device_close(std::move(new_dev), flags);
-fail:
- if (describe) {
- describe_error(std::move(rh), r);
+ describe_error(std::move(rh), r);
}
return r;
+ }
+
+ newconn->flags = flags;
+
+ fbl::RefPtr<zx_device_t> new_dev;
+ r = device_open(dev, &new_dev, flags);
+ if (r != ZX_OK) {
+ fprintf(stderr, "devhost_device_connect(%p:%s) open r=%d\n", dev.get(), dev->name, r);
+ goto fail;
+ }
+ newconn->dev = new_dev;
+
+ if (describe) {
+ fs::OnOpenMsg info;
+ zx::eventpair handle;
+ if ((r = create_description(new_dev, &info, &handle)) != ZX_OK) {
+ goto fail_open;
+ }
+ uint32_t hcount = (handle.is_valid()) ? 1 : 0;
+ zx_handle_t raw_handles[] = {
+ handle.release(),
+ };
+ r = rh.write(0, &info, sizeof(info), raw_handles, hcount);
+ if (r != ZX_OK) {
+ goto fail_open;
+ }
+ }
+
+ // If we can't add the new conn and handle to the dispatcher our only option
+ // is to give up and tear down. In practice, this should never happen.
+ if ((r = devhost_start_connection(std::move(newconn), std::move(rh))) != ZX_OK) {
+ fprintf(stderr, "devhost_device_connect: failed to start iostate\n");
+ // TODO(teisenbe/kulakowski): Should this be goto fail_open?
+ goto fail;
+ }
+ return ZX_OK;
+
+fail_open:
+ device_close(std::move(new_dev), flags);
+fail:
+ if (describe) {
+ describe_error(std::move(rh), r);
+ }
+ return r;
}
#define DO_READ 0
@@ -157,392 +153,391 @@
static ssize_t do_sync_io(const fbl::RefPtr<zx_device_t>& dev, uint32_t opcode, void* buf,
size_t count, zx_off_t off) {
- size_t actual;
- zx_status_t r;
- if (opcode == DO_READ) {
- r = dev->ReadOp(buf, count, off, &actual);
- } else {
- r = dev->WriteOp(buf, count, off, &actual);
- }
- if (r < 0) {
- return r;
- } else {
- return actual;
- }
+ size_t actual;
+ zx_status_t r;
+ if (opcode == DO_READ) {
+ r = dev->ReadOp(buf, count, off, &actual);
+ } else {
+ r = dev->WriteOp(buf, count, off, &actual);
+ }
+ if (r < 0) {
+ return r;
+ } else {
+ return actual;
+ }
}
static zx_status_t fidl_node_clone(void* ctx, uint32_t flags, zx_handle_t object) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- zx::channel c(object);
- flags = conn->flags | (flags & ZX_FS_FLAG_DESCRIBE);
- devhost_device_connect(conn->dev, flags, std::move(c));
- return ZX_OK;
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ zx::channel c(object);
+ flags = conn->flags | (flags & ZX_FS_FLAG_DESCRIBE);
+ devhost_device_connect(conn->dev, flags, std::move(c));
+ return ZX_OK;
}
static zx_status_t fidl_node_close(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- // Call device_close to let the driver execute its close hook. This may
- // be the last reference to the device, causing it to be destroyed.
- device_close(std::move(conn->dev), conn->flags);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ // Call device_close to let the driver execute its close hook. This may
+ // be the last reference to the device, causing it to be destroyed.
+ device_close(std::move(conn->dev), conn->flags);
- fuchsia_io_NodeClose_reply(txn, ZX_OK);
- return ERR_DISPATCHER_DONE;
+ fuchsia_io_NodeClose_reply(txn, ZX_OK);
+ return ERR_DISPATCHER_DONE;
}
static zx_status_t fidl_node_describe(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- const auto& dev = conn->dev;
- fuchsia_io_NodeInfo info;
- memset(&info, 0, sizeof(info));
- info.tag = device_or_tty(dev);
- if (dev->event != ZX_HANDLE_INVALID) {
- zx::eventpair event;
- zx_status_t status = dev->event.duplicate(ZX_RIGHTS_BASIC, &event);
- if (status != ZX_OK) {
- return status;
- }
- zx_handle_t* event_handle = (info.tag == fuchsia_io_NodeInfoTag_device)
- ? &info.device.event
- : &info.tty.event;
- *event_handle = event.release();
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ const auto& dev = conn->dev;
+ fuchsia_io_NodeInfo info;
+ memset(&info, 0, sizeof(info));
+ info.tag = device_or_tty(dev);
+ if (dev->event != ZX_HANDLE_INVALID) {
+ zx::eventpair event;
+ zx_status_t status = dev->event.duplicate(ZX_RIGHTS_BASIC, &event);
+ if (status != ZX_OK) {
+ return status;
}
- return fuchsia_io_NodeDescribe_reply(txn, &info);
+ zx_handle_t* event_handle =
+ (info.tag == fuchsia_io_NodeInfoTag_device) ? &info.device.event : &info.tty.event;
+ *event_handle = event.release();
+ }
+ return fuchsia_io_NodeDescribe_reply(txn, &info);
}
static zx_status_t fidl_directory_open(void* ctx, uint32_t flags, uint32_t mode,
const char* path_data, size_t path_size,
zx_handle_t object) {
- zx_handle_close(object);
- return ZX_ERR_NOT_SUPPORTED;
+ zx_handle_close(object);
+ return ZX_ERR_NOT_SUPPORTED;
}
static zx_status_t fidl_directory_unlink(void* ctx, const char* path_data, size_t path_size,
fidl_txn_t* txn) {
- return fuchsia_io_DirectoryUnlink_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ return fuchsia_io_DirectoryUnlink_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_readdirents(void* ctx, uint64_t max_out, fidl_txn_t* txn) {
- return fuchsia_io_DirectoryReadDirents_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr, 0);
+ return fuchsia_io_DirectoryReadDirents_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr, 0);
}
static zx_status_t fidl_directory_rewind(void* ctx, fidl_txn_t* txn) {
- return fuchsia_io_DirectoryRewind_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ return fuchsia_io_DirectoryRewind_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_gettoken(void* ctx, fidl_txn_t* txn) {
- return fuchsia_io_DirectoryGetToken_reply(txn, ZX_ERR_NOT_SUPPORTED, ZX_HANDLE_INVALID);
+ return fuchsia_io_DirectoryGetToken_reply(txn, ZX_ERR_NOT_SUPPORTED, ZX_HANDLE_INVALID);
}
static zx_status_t fidl_directory_rename(void* ctx, const char* src_data, size_t src_size,
zx_handle_t dst_parent_token, const char* dst_data,
size_t dst_size, fidl_txn_t* txn) {
- zx_handle_close(dst_parent_token);
- return fuchsia_io_DirectoryRename_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ zx_handle_close(dst_parent_token);
+ return fuchsia_io_DirectoryRename_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_link(void* ctx, const char* src_data, size_t src_size,
zx_handle_t dst_parent_token, const char* dst_data,
size_t dst_size, fidl_txn_t* txn) {
- zx_handle_close(dst_parent_token);
- return fuchsia_io_DirectoryLink_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ zx_handle_close(dst_parent_token);
+ return fuchsia_io_DirectoryLink_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_watch(void* ctx, uint32_t mask, uint32_t options,
zx_handle_t raw_watcher, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- auto dev = conn->dev;
- zx::channel watcher(raw_watcher);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ auto dev = conn->dev;
+ zx::channel watcher(raw_watcher);
- const zx::channel& rpc = *dev->rpc;
- if (!rpc.is_valid()) {
- return fuchsia_io_DirectoryWatch_reply(txn, ZX_ERR_INTERNAL);
- }
+ const zx::channel& rpc = *dev->rpc;
+ if (!rpc.is_valid()) {
+ return fuchsia_io_DirectoryWatch_reply(txn, ZX_ERR_INTERNAL);
+ }
- zx_status_t call_status;
- zx_status_t status = fuchsia_device_manager_CoordinatorDirectoryWatch(
- rpc.get(), mask, options, watcher.release(), &call_status);
+ zx_status_t call_status;
+ zx_status_t status = fuchsia_device_manager_CoordinatorDirectoryWatch(
+ rpc.get(), mask, options, watcher.release(), &call_status);
- return fuchsia_io_DirectoryWatch_reply(txn, status != ZX_OK ? status : call_status);
+ return fuchsia_io_DirectoryWatch_reply(txn, status != ZX_OK ? status : call_status);
}
static const fuchsia_io_Directory_ops_t kDirectoryOps = []() {
- fuchsia_io_Directory_ops_t ops;
- ops.Open = fidl_directory_open;
- ops.Unlink = fidl_directory_unlink;
- ops.ReadDirents = fidl_directory_readdirents;
- ops.Rewind = fidl_directory_rewind;
- ops.GetToken = fidl_directory_gettoken;
- ops.Rename = fidl_directory_rename;
- ops.Link = fidl_directory_link;
- ops.Watch = fidl_directory_watch;
- return ops;
+ fuchsia_io_Directory_ops_t ops;
+ ops.Open = fidl_directory_open;
+ ops.Unlink = fidl_directory_unlink;
+ ops.ReadDirents = fidl_directory_readdirents;
+ ops.Rewind = fidl_directory_rewind;
+ ops.GetToken = fidl_directory_gettoken;
+ ops.Rename = fidl_directory_rename;
+ ops.Link = fidl_directory_link;
+ ops.Watch = fidl_directory_watch;
+ return ops;
}();
static zx_status_t fidl_directory_admin_mount(void* ctx, zx_handle_t h, fidl_txn_t* txn) {
- zx_handle_close(h);
- return fuchsia_io_DirectoryAdminMount_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ zx_handle_close(h);
+ return fuchsia_io_DirectoryAdminMount_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_admin_mount_and_create(void* ctx, zx_handle_t h, const char* name,
size_t len, uint32_t flags,
fidl_txn_t* txn) {
- zx_handle_close(h);
- return fuchsia_io_DirectoryAdminMountAndCreate_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ zx_handle_close(h);
+ return fuchsia_io_DirectoryAdminMountAndCreate_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_admin_unmount(void* ctx, fidl_txn_t* txn) {
- return fuchsia_io_DirectoryAdminUnmount_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ return fuchsia_io_DirectoryAdminUnmount_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_directory_admin_unmount_node(void* ctx, fidl_txn_t* txn) {
- return fuchsia_io_DirectoryAdminUnmountNode_reply(txn, ZX_ERR_NOT_SUPPORTED, ZX_HANDLE_INVALID);
+ return fuchsia_io_DirectoryAdminUnmountNode_reply(txn, ZX_ERR_NOT_SUPPORTED, ZX_HANDLE_INVALID);
}
static zx_status_t fidl_directory_admin_query_filesystem(void* ctx, fidl_txn_t* txn) {
- fuchsia_io_FilesystemInfo info;
- memset(&info, 0, sizeof(info));
- const char* devhost_name = "devfs:host";
- strlcpy((char*)info.name, devhost_name, fuchsia_io_MAX_FS_NAME_BUFFER);
- return fuchsia_io_DirectoryAdminQueryFilesystem_reply(txn, ZX_OK, &info);
+ fuchsia_io_FilesystemInfo info;
+ memset(&info, 0, sizeof(info));
+ const char* devhost_name = "devfs:host";
+ strlcpy((char*)info.name, devhost_name, fuchsia_io_MAX_FS_NAME_BUFFER);
+ return fuchsia_io_DirectoryAdminQueryFilesystem_reply(txn, ZX_OK, &info);
}
static zx_status_t fidl_directory_admin_get_device_path(void* ctx, fidl_txn_t* txn) {
- return fuchsia_io_DirectoryAdminGetDevicePath_reply(txn, ZX_ERR_NOT_SUPPORTED, NULL, 0);
+ return fuchsia_io_DirectoryAdminGetDevicePath_reply(txn, ZX_ERR_NOT_SUPPORTED, NULL, 0);
}
static const fuchsia_io_DirectoryAdmin_ops_t kDirectoryAdminOps = []() {
- fuchsia_io_DirectoryAdmin_ops_t ops;
- ops.Mount = fidl_directory_admin_mount;
- ops.MountAndCreate = fidl_directory_admin_mount_and_create;
- ops.Unmount = fidl_directory_admin_unmount;
- ops.UnmountNode = fidl_directory_admin_unmount_node;
- ops.QueryFilesystem = fidl_directory_admin_query_filesystem;
- ops.GetDevicePath = fidl_directory_admin_get_device_path;
- return ops;
+ fuchsia_io_DirectoryAdmin_ops_t ops;
+ ops.Mount = fidl_directory_admin_mount;
+ ops.MountAndCreate = fidl_directory_admin_mount_and_create;
+ ops.Unmount = fidl_directory_admin_unmount;
+ ops.UnmountNode = fidl_directory_admin_unmount_node;
+ ops.QueryFilesystem = fidl_directory_admin_query_filesystem;
+ ops.GetDevicePath = fidl_directory_admin_get_device_path;
+ return ops;
}();
static zx_status_t fidl_file_read(void* ctx, uint64_t count, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- const auto& dev = conn->dev;
- if (!CAN_READ(conn)) {
- return fuchsia_io_FileRead_reply(txn, ZX_ERR_ACCESS_DENIED, nullptr, 0);
- } else if (count > ZXFIDL_MAX_MSG_BYTES) {
- return fuchsia_io_FileRead_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0);
- }
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ const auto& dev = conn->dev;
+ if (!CAN_READ(conn)) {
+ return fuchsia_io_FileRead_reply(txn, ZX_ERR_ACCESS_DENIED, nullptr, 0);
+ } else if (count > ZXFIDL_MAX_MSG_BYTES) {
+ return fuchsia_io_FileRead_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0);
+ }
- uint8_t data[count];
- size_t actual = 0;
- zx_status_t status = ZX_OK;
- ssize_t r = do_sync_io(dev, DO_READ, data, count, conn->io_off);
- if (r >= 0) {
- conn->io_off += r;
- actual = r;
- } else {
- status = static_cast<zx_status_t>(r);
- }
- return fuchsia_io_FileRead_reply(txn, status, data, actual);
+ uint8_t data[count];
+ size_t actual = 0;
+ zx_status_t status = ZX_OK;
+ ssize_t r = do_sync_io(dev, DO_READ, data, count, conn->io_off);
+ if (r >= 0) {
+ conn->io_off += r;
+ actual = r;
+ } else {
+ status = static_cast<zx_status_t>(r);
+ }
+ return fuchsia_io_FileRead_reply(txn, status, data, actual);
}
static zx_status_t fidl_file_readat(void* ctx, uint64_t count, uint64_t offset, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- if (!CAN_READ(conn)) {
- return fuchsia_io_FileReadAt_reply(txn, ZX_ERR_ACCESS_DENIED, nullptr, 0);
- } else if (count > ZXFIDL_MAX_MSG_BYTES) {
- return fuchsia_io_FileReadAt_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0);
- }
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ if (!CAN_READ(conn)) {
+ return fuchsia_io_FileReadAt_reply(txn, ZX_ERR_ACCESS_DENIED, nullptr, 0);
+ } else if (count > ZXFIDL_MAX_MSG_BYTES) {
+ return fuchsia_io_FileReadAt_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0);
+ }
- uint8_t data[count];
- size_t actual = 0;
- zx_status_t status = ZX_OK;
- ssize_t r = do_sync_io(conn->dev, DO_READ, data, count, offset);
- if (r >= 0) {
- actual = r;
- } else {
- status = static_cast<zx_status_t>(r);
- }
- return fuchsia_io_FileReadAt_reply(txn, status, data, actual);
+ uint8_t data[count];
+ size_t actual = 0;
+ zx_status_t status = ZX_OK;
+ ssize_t r = do_sync_io(conn->dev, DO_READ, data, count, offset);
+ if (r >= 0) {
+ actual = r;
+ } else {
+ status = static_cast<zx_status_t>(r);
+ }
+ return fuchsia_io_FileReadAt_reply(txn, status, data, actual);
}
static zx_status_t fidl_file_write(void* ctx, const uint8_t* data, size_t count, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- if (!CAN_WRITE(conn)) {
- return fuchsia_io_FileWrite_reply(txn, ZX_ERR_ACCESS_DENIED, 0);
- }
- size_t actual = 0;
- zx_status_t status = ZX_OK;
- ssize_t r = do_sync_io(conn->dev, DO_WRITE, (uint8_t*)data, count, conn->io_off);
- if (r >= 0) {
- conn->io_off += r;
- actual = r;
- } else {
- status = static_cast<zx_status_t>(r);
- }
- return fuchsia_io_FileWrite_reply(txn, status, actual);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ if (!CAN_WRITE(conn)) {
+ return fuchsia_io_FileWrite_reply(txn, ZX_ERR_ACCESS_DENIED, 0);
+ }
+ size_t actual = 0;
+ zx_status_t status = ZX_OK;
+ ssize_t r = do_sync_io(conn->dev, DO_WRITE, (uint8_t*)data, count, conn->io_off);
+ if (r >= 0) {
+ conn->io_off += r;
+ actual = r;
+ } else {
+ status = static_cast<zx_status_t>(r);
+ }
+ return fuchsia_io_FileWrite_reply(txn, status, actual);
}
static zx_status_t fidl_file_writeat(void* ctx, const uint8_t* data, size_t count, uint64_t offset,
fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- if (!CAN_WRITE(conn)) {
- return fuchsia_io_FileWriteAt_reply(txn, ZX_ERR_ACCESS_DENIED, 0);
- }
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ if (!CAN_WRITE(conn)) {
+ return fuchsia_io_FileWriteAt_reply(txn, ZX_ERR_ACCESS_DENIED, 0);
+ }
- size_t actual = 0;
- zx_status_t status = ZX_OK;
- ssize_t r = do_sync_io(conn->dev, DO_WRITE, (uint8_t*)data, count, offset);
- if (r >= 0) {
- actual = r;
- } else {
- status = static_cast<zx_status_t>(r);
- }
- return fuchsia_io_FileWriteAt_reply(txn, status, actual);
+ size_t actual = 0;
+ zx_status_t status = ZX_OK;
+ ssize_t r = do_sync_io(conn->dev, DO_WRITE, (uint8_t*)data, count, offset);
+ if (r >= 0) {
+ actual = r;
+ } else {
+ status = static_cast<zx_status_t>(r);
+ }
+ return fuchsia_io_FileWriteAt_reply(txn, status, actual);
}
static zx_status_t fidl_file_seek(void* ctx, int64_t offset, fuchsia_io_SeekOrigin start,
fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- auto bad_args = [&]() { return fuchsia_io_FileSeek_reply(txn, ZX_ERR_INVALID_ARGS, 0); };
- size_t end = conn->dev->GetSizeOp();
- size_t n;
- switch (start) {
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ auto bad_args = [&]() { return fuchsia_io_FileSeek_reply(txn, ZX_ERR_INVALID_ARGS, 0); };
+ size_t end = conn->dev->GetSizeOp();
+ size_t n;
+ switch (start) {
case fuchsia_io_SeekOrigin_START:
- if ((offset < 0) || ((size_t)offset > end)) {
- return bad_args();
- }
- n = offset;
- break;
+ if ((offset < 0) || ((size_t)offset > end)) {
+ return bad_args();
+ }
+ n = offset;
+ break;
case fuchsia_io_SeekOrigin_CURRENT:
- // TODO: track seekability with flag, don't update off
- // at all on read/write if not seekable
- n = conn->io_off + offset;
- if (offset < 0) {
- // if negative seek
- if (n > conn->io_off) {
- // wrapped around
- return bad_args();
- }
- } else {
- // positive seek
- if (n < conn->io_off) {
- // wrapped around
- return bad_args();
- }
+ // TODO: track seekability with flag, don't update off
+ // at all on read/write if not seekable
+ n = conn->io_off + offset;
+ if (offset < 0) {
+ // if negative seek
+ if (n > conn->io_off) {
+ // wrapped around
+ return bad_args();
}
- break;
+ } else {
+ // positive seek
+ if (n < conn->io_off) {
+ // wrapped around
+ return bad_args();
+ }
+ }
+ break;
case fuchsia_io_SeekOrigin_END:
- n = end + offset;
- if (offset <= 0) {
- // if negative or exact-end seek
- if (n > end) {
- // wrapped around
- return bad_args();
- }
- } else {
- if (n < end) {
- // wrapped around
- return bad_args();
- }
+ n = end + offset;
+ if (offset <= 0) {
+ // if negative or exact-end seek
+ if (n > end) {
+ // wrapped around
+ return bad_args();
}
- break;
+ } else {
+ if (n < end) {
+ // wrapped around
+ return bad_args();
+ }
+ }
+ break;
default:
- return bad_args();
- }
- if (n > end) {
- // devices may not seek past the end
- return bad_args();
- }
- conn->io_off = n;
- return fuchsia_io_FileSeek_reply(txn, ZX_OK, conn->io_off);
+ return bad_args();
+ }
+ if (n > end) {
+ // devices may not seek past the end
+ return bad_args();
+ }
+ conn->io_off = n;
+ return fuchsia_io_FileSeek_reply(txn, ZX_OK, conn->io_off);
}
static zx_status_t fidl_file_truncate(void* ctx, uint64_t length, fidl_txn_t* txn) {
- return fuchsia_io_FileTruncate_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ return fuchsia_io_FileTruncate_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_file_getflags(void* ctx, fidl_txn_t* txn) {
- return fuchsia_io_FileGetFlags_reply(txn, ZX_ERR_NOT_SUPPORTED, 0);
+ return fuchsia_io_FileGetFlags_reply(txn, ZX_ERR_NOT_SUPPORTED, 0);
}
static zx_status_t fidl_file_setflags(void* ctx, uint32_t flags, fidl_txn_t* txn) {
- return fuchsia_io_FileSetFlags_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ return fuchsia_io_FileSetFlags_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_file_getbuffer(void* ctx, uint32_t flags, fidl_txn_t* txn) {
- return fuchsia_io_FileGetBuffer_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr);
+ return fuchsia_io_FileGetBuffer_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr);
}
static const fuchsia_io_File_ops_t kFileOps = []() {
- fuchsia_io_File_ops_t ops;
- ops.Read = fidl_file_read;
- ops.ReadAt = fidl_file_readat;
- ops.Write = fidl_file_write;
- ops.WriteAt = fidl_file_writeat;
- ops.Seek = fidl_file_seek;
- ops.Truncate = fidl_file_truncate;
- ops.GetFlags = fidl_file_getflags;
- ops.SetFlags = fidl_file_setflags;
- ops.GetBuffer = fidl_file_getbuffer;
- return ops;
+ fuchsia_io_File_ops_t ops;
+ ops.Read = fidl_file_read;
+ ops.ReadAt = fidl_file_readat;
+ ops.Write = fidl_file_write;
+ ops.WriteAt = fidl_file_writeat;
+ ops.Seek = fidl_file_seek;
+ ops.Truncate = fidl_file_truncate;
+ ops.GetFlags = fidl_file_getflags;
+ ops.SetFlags = fidl_file_setflags;
+ ops.GetBuffer = fidl_file_getbuffer;
+ return ops;
}();
static zx_status_t fidl_node_sync(void* ctx, fidl_txn_t* txn) {
- // TODO(ZX-3294): We may want to support sync through the block
- // protocol, but in the interim, it is unsupported.
- return fuchsia_io_NodeSync_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ // TODO(ZX-3294): We may want to support sync through the block
+ // protocol, but in the interim, it is unsupported.
+ return fuchsia_io_NodeSync_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_node_getattr(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- fuchsia_io_NodeAttributes attributes;
- memset(&attributes, 0, sizeof(attributes));
- attributes.mode = V_TYPE_CDEV | V_IRUSR | V_IWUSR;
- attributes.content_size = conn->dev->GetSizeOp();
- attributes.link_count = 1;
- return fuchsia_io_NodeGetAttr_reply(txn, ZX_OK, &attributes);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ fuchsia_io_NodeAttributes attributes;
+ memset(&attributes, 0, sizeof(attributes));
+ attributes.mode = V_TYPE_CDEV | V_IRUSR | V_IWUSR;
+ attributes.content_size = conn->dev->GetSizeOp();
+ attributes.link_count = 1;
+ return fuchsia_io_NodeGetAttr_reply(txn, ZX_OK, &attributes);
}
static zx_status_t fidl_node_setattr(void* ctx, uint32_t flags,
const fuchsia_io_NodeAttributes* attributes, fidl_txn_t* txn) {
- return fuchsia_io_NodeSetAttr_reply(txn, ZX_ERR_NOT_SUPPORTED);
+ return fuchsia_io_NodeSetAttr_reply(txn, ZX_ERR_NOT_SUPPORTED);
}
static zx_status_t fidl_node_ioctl(void* ctx, uint32_t opcode, uint64_t max_out,
const zx_handle_t* handles_data, size_t handles_count,
const uint8_t* in_data, size_t in_count, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- char in_buf[FDIO_IOCTL_MAX_INPUT];
- size_t hsize = handles_count * sizeof(zx_handle_t);
- if ((in_count > FDIO_IOCTL_MAX_INPUT) || (max_out > ZXFIDL_MAX_MSG_BYTES)) {
- zx_handle_close_many(handles_data, handles_count);
- return fuchsia_io_NodeIoctl_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0, nullptr, 0);
- }
- memcpy(in_buf, in_data, in_count);
- memcpy(in_buf, handles_data, hsize);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ char in_buf[FDIO_IOCTL_MAX_INPUT];
+ size_t hsize = handles_count * sizeof(zx_handle_t);
+ if ((in_count > FDIO_IOCTL_MAX_INPUT) || (max_out > ZXFIDL_MAX_MSG_BYTES)) {
+ zx_handle_close_many(handles_data, handles_count);
+ return fuchsia_io_NodeIoctl_reply(txn, ZX_ERR_INVALID_ARGS, nullptr, 0, nullptr, 0);
+ }
+ memcpy(in_buf, in_data, in_count);
+ memcpy(in_buf, handles_data, hsize);
- uint8_t out[max_out];
- zx_handle_t* out_handles = (zx_handle_t*)out;
- size_t out_count = 0;
- ssize_t r = conn->dev->IoctlOp(opcode, in_buf, in_count, out, max_out, &out_count);
- size_t out_hcount = 0;
- if (r >= 0) {
- switch (IOCTL_KIND(opcode)) {
- case IOCTL_KIND_GET_HANDLE:
- out_hcount = 1;
- break;
- case IOCTL_KIND_GET_TWO_HANDLES:
- out_hcount = 2;
- break;
- case IOCTL_KIND_GET_THREE_HANDLES:
- out_hcount = 3;
- break;
- default:
- out_hcount = 0;
- break;
- }
+ uint8_t out[max_out];
+ zx_handle_t* out_handles = (zx_handle_t*)out;
+ size_t out_count = 0;
+ ssize_t r = conn->dev->IoctlOp(opcode, in_buf, in_count, out, max_out, &out_count);
+ size_t out_hcount = 0;
+ if (r >= 0) {
+ switch (IOCTL_KIND(opcode)) {
+ case IOCTL_KIND_GET_HANDLE:
+ out_hcount = 1;
+ break;
+ case IOCTL_KIND_GET_TWO_HANDLES:
+ out_hcount = 2;
+ break;
+ case IOCTL_KIND_GET_THREE_HANDLES:
+ out_hcount = 3;
+ break;
+ default:
+ out_hcount = 0;
+ break;
}
+ }
- auto status = static_cast<zx_status_t>(r);
- return fuchsia_io_NodeIoctl_reply(txn, status, out_handles, out_hcount, out, out_count);
+ auto status = static_cast<zx_status_t>(r);
+ return fuchsia_io_NodeIoctl_reply(txn, status, out_handles, out_hcount, out, out_count);
}
static const fuchsia_io_Node_ops_t kNodeOps = {
@@ -557,108 +552,106 @@
static zx_status_t fidl_DeviceControllerBind(void* ctx, const char* driver_data,
size_t driver_count, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
+ auto conn = static_cast<DevfsConnection*>(ctx);
- char drv_libname[fuchsia_device_MAX_DRIVER_PATH_LEN + 1];
- memcpy(drv_libname, driver_data, driver_count);
- drv_libname[driver_count] = 0;
+ char drv_libname[fuchsia_device_MAX_DRIVER_PATH_LEN + 1];
+ memcpy(drv_libname, driver_data, driver_count);
+ drv_libname[driver_count] = 0;
- if (!strcmp(drv_libname, "/boot/driver/fvm.so")) {
- // TODO(ZX-4198): Workaround for flaky tests involving FVM.
- zx_status_t status = fuchsia_device_ControllerBind_reply(txn, ZX_OK);
- if (status != ZX_OK) {
- return status;
- }
- } else {
- conn->dev->PushBindConn(fs::FidlConnection::CopyTxn(txn));
+ if (!strcmp(drv_libname, "/boot/driver/fvm.so")) {
+ // TODO(ZX-4198): Workaround for flaky tests involving FVM.
+ zx_status_t status = fuchsia_device_ControllerBind_reply(txn, ZX_OK);
+ if (status != ZX_OK) {
+ return status;
}
+ } else {
+ conn->dev->PushBindConn(fs::FidlConnection::CopyTxn(txn));
+ }
- return device_bind(conn->dev, drv_libname);
+ return device_bind(conn->dev, drv_libname);
}
static zx_status_t fidl_DeviceControllerUnbind(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- zx_status_t status = device_unbind(conn->dev);
- return fuchsia_device_ControllerUnbind_reply(txn, status);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ zx_status_t status = device_unbind(conn->dev);
+ return fuchsia_device_ControllerUnbind_reply(txn, status);
}
static zx_status_t fidl_DeviceControllerGetDriverName(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- if (!conn->dev->driver) {
- return fuchsia_device_ControllerGetDriverName_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr, 0);
- }
- const char* name = conn->dev->driver->name();
- if (name == nullptr) {
- name = "unknown";
- }
- return fuchsia_device_ControllerGetDriverName_reply(txn, ZX_OK, name, strlen(name));
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ if (!conn->dev->driver) {
+ return fuchsia_device_ControllerGetDriverName_reply(txn, ZX_ERR_NOT_SUPPORTED, nullptr, 0);
+ }
+ const char* name = conn->dev->driver->name();
+ if (name == nullptr) {
+ name = "unknown";
+ }
+ return fuchsia_device_ControllerGetDriverName_reply(txn, ZX_OK, name, strlen(name));
}
static zx_status_t fidl_DeviceControllerGetDeviceName(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- return fuchsia_device_ControllerGetDeviceName_reply(txn, conn->dev->name,
- strlen(conn->dev->name));
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ return fuchsia_device_ControllerGetDeviceName_reply(txn, conn->dev->name,
+ strlen(conn->dev->name));
}
static zx_status_t fidl_DeviceControllerGetTopologicalPath(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- char buf[fuchsia_device_MAX_DEVICE_PATH_LEN + 1];
- size_t actual;
- zx_status_t status = devhost_get_topo_path(conn->dev, buf, sizeof(buf), &actual);
- if (status != ZX_OK) {
- return fuchsia_device_ControllerGetTopologicalPath_reply(txn, status, nullptr, 0);
- }
- if (actual > 0) {
- // Remove the accounting for the null byte
- actual--;
- }
- return fuchsia_device_ControllerGetTopologicalPath_reply(txn, ZX_OK, buf, actual);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ char buf[fuchsia_device_MAX_DEVICE_PATH_LEN + 1];
+ size_t actual;
+ zx_status_t status = devhost_get_topo_path(conn->dev, buf, sizeof(buf), &actual);
+ if (status != ZX_OK) {
+ return fuchsia_device_ControllerGetTopologicalPath_reply(txn, status, nullptr, 0);
+ }
+ if (actual > 0) {
+ // Remove the accounting for the null byte
+ actual--;
+ }
+ return fuchsia_device_ControllerGetTopologicalPath_reply(txn, ZX_OK, buf, actual);
}
static zx_status_t fidl_DeviceControllerGetEventHandle(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- zx::eventpair event;
- zx_status_t status = conn->dev->event.duplicate(ZX_RIGHTS_BASIC, &event);
- static_assert(fuchsia_device_DEVICE_SIGNAL_READABLE == DEV_STATE_READABLE);
- static_assert(fuchsia_device_DEVICE_SIGNAL_WRITABLE == DEV_STATE_WRITABLE);
- static_assert(fuchsia_device_DEVICE_SIGNAL_ERROR == DEV_STATE_ERROR);
- static_assert(fuchsia_device_DEVICE_SIGNAL_HANGUP == DEV_STATE_HANGUP);
- static_assert(fuchsia_device_DEVICE_SIGNAL_OOB == DEV_STATE_OOB);
- return fuchsia_device_ControllerGetEventHandle_reply(txn, status, event.release());
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ zx::eventpair event;
+ zx_status_t status = conn->dev->event.duplicate(ZX_RIGHTS_BASIC, &event);
+ static_assert(fuchsia_device_DEVICE_SIGNAL_READABLE == DEV_STATE_READABLE);
+ static_assert(fuchsia_device_DEVICE_SIGNAL_WRITABLE == DEV_STATE_WRITABLE);
+ static_assert(fuchsia_device_DEVICE_SIGNAL_ERROR == DEV_STATE_ERROR);
+ static_assert(fuchsia_device_DEVICE_SIGNAL_HANGUP == DEV_STATE_HANGUP);
+ static_assert(fuchsia_device_DEVICE_SIGNAL_OOB == DEV_STATE_OOB);
+ return fuchsia_device_ControllerGetEventHandle_reply(txn, status, event.release());
}
static zx_status_t fidl_DeviceControllerGetDriverLogFlags(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- if (!conn->dev->driver) {
- return fuchsia_device_ControllerGetDriverLogFlags_reply(txn, ZX_ERR_UNAVAILABLE, 0);
- }
- uint32_t flags = conn->dev->driver->driver_rec()->log_flags;
- return fuchsia_device_ControllerGetDriverLogFlags_reply(txn, ZX_OK, flags);
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ if (!conn->dev->driver) {
+ return fuchsia_device_ControllerGetDriverLogFlags_reply(txn, ZX_ERR_UNAVAILABLE, 0);
+ }
+ uint32_t flags = conn->dev->driver->driver_rec()->log_flags;
+ return fuchsia_device_ControllerGetDriverLogFlags_reply(txn, ZX_OK, flags);
}
-static zx_status_t fidl_DeviceControllerSetDriverLogFlags(void* ctx,
- uint32_t clear_flags,
- uint32_t set_flags,
- fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- if (!conn->dev->driver) {
- return fuchsia_device_ControllerSetDriverLogFlags_reply(txn, ZX_ERR_UNAVAILABLE);
- }
- uint32_t flags = conn->dev->driver->driver_rec()->log_flags;
- flags &= ~clear_flags;
- flags |= set_flags;
- conn->dev->driver->driver_rec()->log_flags = flags;
- return fuchsia_device_ControllerSetDriverLogFlags_reply(txn, ZX_OK);
+static zx_status_t fidl_DeviceControllerSetDriverLogFlags(void* ctx, uint32_t clear_flags,
+ uint32_t set_flags, fidl_txn_t* txn) {
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ if (!conn->dev->driver) {
+ return fuchsia_device_ControllerSetDriverLogFlags_reply(txn, ZX_ERR_UNAVAILABLE);
+ }
+ uint32_t flags = conn->dev->driver->driver_rec()->log_flags;
+ flags &= ~clear_flags;
+ flags |= set_flags;
+ conn->dev->driver->driver_rec()->log_flags = flags;
+ return fuchsia_device_ControllerSetDriverLogFlags_reply(txn, ZX_OK);
}
static zx_status_t fidl_DeviceControllerDebugSuspend(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- return fuchsia_device_ControllerDebugSuspend_reply(txn, conn->dev->SuspendOp(0));
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ return fuchsia_device_ControllerDebugSuspend_reply(txn, conn->dev->SuspendOp(0));
}
static zx_status_t fidl_DeviceControllerDebugResume(void* ctx, fidl_txn_t* txn) {
- auto conn = static_cast<DevfsConnection*>(ctx);
- return fuchsia_device_ControllerDebugResume_reply(txn, conn->dev->ResumeOp(0));
+ auto conn = static_cast<DevfsConnection*>(ctx);
+ return fuchsia_device_ControllerDebugResume_reply(txn, conn->dev->ResumeOp(0));
}
static const fuchsia_device_Controller_ops_t kDeviceControllerOps = {
@@ -675,29 +668,29 @@
};
zx_status_t devhost_fidl_handler(fidl_msg_t* msg, fidl_txn_t* txn, void* cookie) {
- zx_status_t status = fuchsia_io_Node_try_dispatch(cookie, txn, msg, &kNodeOps);
- if (status != ZX_ERR_NOT_SUPPORTED) {
- return status;
- }
- status = fuchsia_io_File_try_dispatch(cookie, txn, msg, &kFileOps);
- if (status != ZX_ERR_NOT_SUPPORTED) {
- return status;
- }
- status = fuchsia_io_Directory_try_dispatch(cookie, txn, msg, &kDirectoryOps);
- if (status != ZX_ERR_NOT_SUPPORTED) {
- return status;
- }
- status = fuchsia_io_DirectoryAdmin_try_dispatch(cookie, txn, msg, &kDirectoryAdminOps);
- if (status != ZX_ERR_NOT_SUPPORTED) {
- return status;
- }
- status = fuchsia_device_Controller_try_dispatch(cookie, txn, msg, &kDeviceControllerOps);
- if (status != ZX_ERR_NOT_SUPPORTED) {
- return status;
- }
+ zx_status_t status = fuchsia_io_Node_try_dispatch(cookie, txn, msg, &kNodeOps);
+ if (status != ZX_ERR_NOT_SUPPORTED) {
+ return status;
+ }
+ status = fuchsia_io_File_try_dispatch(cookie, txn, msg, &kFileOps);
+ if (status != ZX_ERR_NOT_SUPPORTED) {
+ return status;
+ }
+ status = fuchsia_io_Directory_try_dispatch(cookie, txn, msg, &kDirectoryOps);
+ if (status != ZX_ERR_NOT_SUPPORTED) {
+ return status;
+ }
+ status = fuchsia_io_DirectoryAdmin_try_dispatch(cookie, txn, msg, &kDirectoryAdminOps);
+ if (status != ZX_ERR_NOT_SUPPORTED) {
+ return status;
+ }
+ status = fuchsia_device_Controller_try_dispatch(cookie, txn, msg, &kDeviceControllerOps);
+ if (status != ZX_ERR_NOT_SUPPORTED) {
+ return status;
+ }
- auto conn = static_cast<DevfsConnection*>(cookie);
- return conn->dev->MessageOp(msg, txn);
+ auto conn = static_cast<DevfsConnection*>(cookie);
+ return conn->dev->MessageOp(msg, txn);
}
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/scheduler_profile.cc b/zircon/system/core/devmgr/devhost/scheduler_profile.cc
index 67f3f41..25fba51 100644
--- a/zircon/system/core/devmgr/devhost/scheduler_profile.cc
+++ b/zircon/system/core/devmgr/devhost/scheduler_profile.cc
@@ -4,46 +4,45 @@
#include "scheduler_profile.h"
-#include <stdio.h>
-#include <string.h>
+#include <fuchsia/scheduler/c/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/zx/channel.h>
#include <lib/zx/profile.h>
-
-#include <fuchsia/scheduler/c/fidl.h>
+#include <stdio.h>
+#include <string.h>
namespace devmgr {
zx_handle_t scheduler_profile_provider;
zx_status_t devhost_connect_scheduler_profile_provider() {
- zx::channel registry_client;
- zx::channel registry_service;
- zx_status_t status = zx::channel::create(0u, ®istry_client, ®istry_service);
- if (status != ZX_OK)
- return status;
+ zx::channel registry_client;
+ zx::channel registry_service;
+ zx_status_t status = zx::channel::create(0u, ®istry_client, ®istry_service);
+ if (status != ZX_OK)
+ return status;
- status = fdio_service_connect("/svc/" fuchsia_scheduler_ProfileProvider_Name,
- registry_service.release());
- if (status != ZX_OK)
- return status;
+ status = fdio_service_connect("/svc/" fuchsia_scheduler_ProfileProvider_Name,
+ registry_service.release());
+ if (status != ZX_OK)
+ return status;
- scheduler_profile_provider = registry_client.release();
- return ZX_OK;
+ scheduler_profile_provider = registry_client.release();
+ return ZX_OK;
}
zx_status_t devhost_get_scheduler_profile(uint32_t priority, const char* name,
zx_handle_t* profile) {
- zx_status_t fidl_status = ZX_ERR_INTERNAL;
- zx_status_t status = fuchsia_scheduler_ProfileProviderGetProfile(
- scheduler_profile_provider, priority, name, strlen(name), &fidl_status, profile);
- if (status != ZX_OK) {
- return status;
- }
- if (fidl_status != ZX_OK) {
- return fidl_status;
- }
- return ZX_OK;
+ zx_status_t fidl_status = ZX_ERR_INTERNAL;
+ zx_status_t status = fuchsia_scheduler_ProfileProviderGetProfile(
+ scheduler_profile_provider, priority, name, strlen(name), &fidl_status, profile);
+ if (status != ZX_OK) {
+ return status;
+ }
+ if (fidl_status != ZX_OK) {
+ return fidl_status;
+ }
+ return ZX_OK;
}
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/scheduler_profile.h b/zircon/system/core/devmgr/devhost/scheduler_profile.h
index 26cb61f..c522a76 100644
--- a/zircon/system/core/devmgr/devhost/scheduler_profile.h
+++ b/zircon/system/core/devmgr/devhost/scheduler_profile.h
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_SCHEDULER_PROFILE_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_SCHEDULER_PROFILE_H_
#include <zircon/types.h>
@@ -12,4 +13,6 @@
zx_status_t devhost_get_scheduler_profile(uint32_t priority, const char* name,
zx_handle_t* profile);
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_SCHEDULER_PROFILE_H_
diff --git a/zircon/system/core/devmgr/devhost/tracing.cc b/zircon/system/core/devmgr/devhost/tracing.cc
index 0bd605e..638d0ed 100644
--- a/zircon/system/core/devmgr/devhost/tracing.cc
+++ b/zircon/system/core/devmgr/devhost/tracing.cc
@@ -13,38 +13,38 @@
namespace devmgr {
zx_status_t devhost_start_trace_provider() {
- async_loop_t* loop;
- zx_status_t status = async_loop_create(&kAsyncLoopConfigNoAttachToThread, &loop);
- if (status != ZX_OK) {
- log(ERROR, "devhost: error creating async loop: %d\n", status);
- return status;
- }
+ async_loop_t* loop;
+ zx_status_t status = async_loop_create(&kAsyncLoopConfigNoAttachToThread, &loop);
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: error creating async loop: %d\n", status);
+ return status;
+ }
- status = async_loop_start_thread(loop, "devhost-tracer", nullptr);
- if (status != ZX_OK) {
- async_loop_destroy(loop);
- log(ERROR, "devhost: error starting async loop thread: %d\n", status);
- return status;
- }
+ status = async_loop_start_thread(loop, "devhost-tracer", nullptr);
+ if (status != ZX_OK) {
+ async_loop_destroy(loop);
+ log(ERROR, "devhost: error starting async loop thread: %d\n", status);
+ return status;
+ }
- async_dispatcher_t* dispatcher = async_loop_get_dispatcher(loop);
- zx_handle_t to_service;
- status = trace_provider_connect_with_fdio(&to_service);
- if (status != ZX_OK) {
- log(ERROR, "devhost: trace-provider connection failed: %d\n", status);
- return status;
- }
- trace_provider_t* trace_provider = trace_provider_create(to_service, dispatcher);
- if (!trace_provider) {
- async_loop_destroy(loop);
- log(ERROR, "devhost: error registering provider\n");
- return ZX_ERR_INTERNAL;
- }
+ async_dispatcher_t* dispatcher = async_loop_get_dispatcher(loop);
+ zx_handle_t to_service;
+ status = trace_provider_connect_with_fdio(&to_service);
+ if (status != ZX_OK) {
+ log(ERROR, "devhost: trace-provider connection failed: %d\n", status);
+ return status;
+ }
+ trace_provider_t* trace_provider = trace_provider_create(to_service, dispatcher);
+ if (!trace_provider) {
+ async_loop_destroy(loop);
+ log(ERROR, "devhost: error registering provider\n");
+ return ZX_ERR_INTERNAL;
+ }
- // N.B. The registry has begun, but these things are async. TraceManager
- // may not even be running yet (and likely isn't).
- log(SPEW, "devhost: trace provider registry begun\n");
- return ZX_OK;
+ // N.B. The registry has begun, but these things are async. TraceManager
+ // may not even be running yet (and likely isn't).
+ log(SPEW, "devhost: trace provider registry begun\n");
+ return ZX_OK;
}
-} // namespace devmgr
+} // namespace devmgr
diff --git a/zircon/system/core/devmgr/devhost/tracing.h b/zircon/system/core/devmgr/devhost/tracing.h
index 4ecda69..efcf3c2 100644
--- a/zircon/system/core/devmgr/devhost/tracing.h
+++ b/zircon/system/core/devmgr/devhost/tracing.h
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_TRACING_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_TRACING_H_
#include <zircon/types.h>
@@ -13,4 +14,6 @@
// until either us or the manager terminate.
zx_status_t devhost_start_trace_provider();
-} // namespace devmgr
+} // namespace devmgr
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_TRACING_H_
diff --git a/zircon/system/core/devmgr/devhost/zx-device.cc b/zircon/system/core/devmgr/devhost/zx-device.cc
index e4391207..2f6d8e5 100644
--- a/zircon/system/core/devmgr/devhost/zx-device.cc
+++ b/zircon/system/core/devmgr/devhost/zx-device.cc
@@ -7,110 +7,110 @@
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
+
#include "composite-device.h"
#include "devhost.h"
zx_status_t zx_device::Create(fbl::RefPtr<zx_device>* out_dev) {
- *out_dev = fbl::AdoptRef(new zx_device());
- return ZX_OK;
+ *out_dev = fbl::AdoptRef(new zx_device());
+ return ZX_OK;
}
void zx_device::PushBindConn(const fs::FidlConnection& conn) {
- fbl::AutoLock<fbl::Mutex> lock(&bind_conn_lock_);
- bind_conn_.push_back(conn);
+ fbl::AutoLock<fbl::Mutex> lock(&bind_conn_lock_);
+ bind_conn_.push_back(conn);
}
bool zx_device::PopBindConn(fs::FidlConnection* conn) {
- fbl::AutoLock<fbl::Mutex> lock(&bind_conn_lock_);
- if (bind_conn_.is_empty()) {
- return false;
- }
- *conn = bind_conn_[0];
- bind_conn_.erase(0);
- return true;
+ fbl::AutoLock<fbl::Mutex> lock(&bind_conn_lock_);
+ if (bind_conn_.is_empty()) {
+ return false;
+ }
+ *conn = bind_conn_[0];
+ bind_conn_.erase(0);
+ return true;
}
// We must disable thread-safety analysis due to not being able to statically
// guarantee the lock holding invariant. Instead, we acquire the lock if
// it's not already being held by the current thread.
void zx_device::fbl_recycle() TA_NO_THREAD_SAFETY_ANALYSIS {
- bool acq_lock = !devmgr::DM_LOCK_HELD();
+ bool acq_lock = !devmgr::DM_LOCK_HELD();
+ if (acq_lock) {
+ devmgr::DM_LOCK();
+ }
+ auto unlock = fbl::MakeAutoCall([acq_lock]() TA_NO_THREAD_SAFETY_ANALYSIS {
if (acq_lock) {
- devmgr::DM_LOCK();
+ devmgr::DM_UNLOCK();
}
- auto unlock = fbl::MakeAutoCall([acq_lock]() TA_NO_THREAD_SAFETY_ANALYSIS {
- if (acq_lock) {
- devmgr::DM_UNLOCK();
- }
- });
+ });
- if (this->flags & DEV_FLAG_INSTANCE) {
- // these don't get removed, so mark dead state here
- this->flags |= DEV_FLAG_DEAD | DEV_FLAG_VERY_DEAD;
- }
- if (this->flags & DEV_FLAG_BUSY) {
- // this can happen if creation fails
- // the caller to device_add() will free it
- printf("device: %p(%s): ref=0, busy, not releasing\n", this, this->name);
- return;
- }
+ if (this->flags & DEV_FLAG_INSTANCE) {
+ // these don't get removed, so mark dead state here
+ this->flags |= DEV_FLAG_DEAD | DEV_FLAG_VERY_DEAD;
+ }
+ if (this->flags & DEV_FLAG_BUSY) {
+ // this can happen if creation fails
+ // the caller to device_add() will free it
+ printf("device: %p(%s): ref=0, busy, not releasing\n", this, this->name);
+ return;
+ }
#if TRACE_ADD_REMOVE
- printf("device: %p(%s): ref=0. releasing.\n", this, this->name);
+ printf("device: %p(%s): ref=0. releasing.\n", this, this->name);
#endif
- if (!(this->flags & DEV_FLAG_VERY_DEAD)) {
- printf("device: %p(%s): only mostly dead (this is bad)\n", this, this->name);
- }
- if (!this->children.is_empty()) {
- printf("device: %p(%s): still has children! not good.\n", this, this->name);
- }
+ if (!(this->flags & DEV_FLAG_VERY_DEAD)) {
+ printf("device: %p(%s): only mostly dead (this is bad)\n", this, this->name);
+ }
+ if (!this->children.is_empty()) {
+ printf("device: %p(%s): still has children! not good.\n", this, this->name);
+ }
- composite_.reset();
- this->event.reset();
- this->local_event.reset();
+ composite_.reset();
+ this->event.reset();
+ this->local_event.reset();
- // Put on the defered work list for finalization
- devmgr::defer_device_list.push_back(this);
+ // Put on the defered work list for finalization
+ devmgr::defer_device_list.push_back(this);
- // Immediately finalize if there's not an active enumerator
- if (devmgr::devhost_enumerators == 0) {
- devmgr::devhost_finalize();
- }
+ // Immediately finalize if there's not an active enumerator
+ if (devmgr::devhost_enumerators == 0) {
+ devmgr::devhost_finalize();
+ }
}
static fbl::Mutex local_id_map_lock_;
static fbl::WAVLTree<uint64_t, fbl::RefPtr<zx_device>, zx_device::LocalIdKeyTraits,
- zx_device::LocalIdNode> local_id_map_ TA_GUARDED(local_id_map_lock_);
+ zx_device::LocalIdNode>
+ local_id_map_ TA_GUARDED(local_id_map_lock_);
void zx_device::set_local_id(uint64_t id) {
- // If this is the last reference, we want it to go away outside of the lock
- fbl::RefPtr<zx_device> old_entry;
+ // If this is the last reference, we want it to go away outside of the lock
+ fbl::RefPtr<zx_device> old_entry;
- fbl::AutoLock guard(&local_id_map_lock_);
- if (local_id_ != 0) {
- old_entry = local_id_map_.erase(*this);
- ZX_ASSERT(old_entry.get() == this);
- }
+ fbl::AutoLock guard(&local_id_map_lock_);
+ if (local_id_ != 0) {
+ old_entry = local_id_map_.erase(*this);
+ ZX_ASSERT(old_entry.get() == this);
+ }
- local_id_ = id;
- if (id != 0) {
- local_id_map_.insert(fbl::WrapRefPtr(this));
- }
+ local_id_ = id;
+ if (id != 0) {
+ local_id_map_.insert(fbl::WrapRefPtr(this));
+ }
}
fbl::RefPtr<zx_device> zx_device::GetDeviceFromLocalId(uint64_t local_id) {
- fbl::AutoLock guard(&local_id_map_lock_);
- auto itr = local_id_map_.find(local_id);
- if (itr == local_id_map_.end()) {
- return nullptr;
- }
- return fbl::WrapRefPtr(&*itr);
+ fbl::AutoLock guard(&local_id_map_lock_);
+ auto itr = local_id_map_.find(local_id);
+ if (itr == local_id_map_.end()) {
+ return nullptr;
+ }
+ return fbl::WrapRefPtr(&*itr);
}
-fbl::RefPtr<devmgr::CompositeDevice> zx_device::take_composite() {
- return std::move(composite_);
-}
+fbl::RefPtr<devmgr::CompositeDevice> zx_device::take_composite() { return std::move(composite_); }
void zx_device::set_composite(fbl::RefPtr<devmgr::CompositeDevice> composite) {
- composite_ = std::move(composite);
+ composite_ = std::move(composite);
}
diff --git a/zircon/system/core/devmgr/devhost/zx-device.h b/zircon/system/core/devmgr/devhost/zx-device.h
index 0a7e4c39..f26a9f2 100644
--- a/zircon/system/core/devmgr/devhost/zx-device.h
+++ b/zircon/system/core/devmgr/devhost/zx-device.h
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_ZX_DEVICE_H_
+#define ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_ZX_DEVICE_H_
-#include <atomic>
#include <ddk/device.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/intrusive_wavl_tree.h>
@@ -19,184 +19,178 @@
#include <zircon/compiler.h>
#include <zircon/thread_annotations.h>
+#include <atomic>
+
namespace devmgr {
class CompositeDevice;
class DeviceControllerConnection;
struct ProxyIostate;
-} // namespace devmgr
+} // namespace devmgr
#define DEV_MAGIC 'MDEV'
// This needs to be a struct, not a class, to match the public definition
struct zx_device : fbl::RefCountedUpgradeable<zx_device>, fbl::Recyclable<zx_device> {
- ~zx_device() = default;
+ ~zx_device() = default;
- zx_device(const zx_device&) = delete;
- zx_device& operator=(const zx_device&) = delete;
+ zx_device(const zx_device&) = delete;
+ zx_device& operator=(const zx_device&) = delete;
- static zx_status_t Create(fbl::RefPtr<zx_device>* out_dev);
+ static zx_status_t Create(fbl::RefPtr<zx_device>* out_dev);
- zx_status_t OpenOp(zx_device_t** dev_out, uint32_t flags) {
- return Dispatch(ops->open, ZX_OK, dev_out, flags);
+ zx_status_t OpenOp(zx_device_t** dev_out, uint32_t flags) {
+ return Dispatch(ops->open, ZX_OK, dev_out, flags);
+ }
+
+ zx_status_t CloseOp(uint32_t flags) { return Dispatch(ops->close, ZX_OK, flags); }
+
+ void UnbindOp() { Dispatch(ops->unbind); }
+
+ void ReleaseOp() { Dispatch(ops->release); }
+
+ zx_status_t SuspendOp(uint32_t flags) {
+ return Dispatch(ops->suspend, ZX_ERR_NOT_SUPPORTED, flags);
+ }
+
+ zx_status_t ResumeOp(uint32_t flags) {
+ return Dispatch(ops->resume, ZX_ERR_NOT_SUPPORTED, flags);
+ }
+
+ zx_status_t ReadOp(void* buf, size_t count, zx_off_t off, size_t* actual) {
+ return Dispatch(ops->read, ZX_ERR_NOT_SUPPORTED, buf, count, off, actual);
+ }
+
+ zx_status_t WriteOp(const void* buf, size_t count, zx_off_t off, size_t* actual) {
+ return Dispatch(ops->write, ZX_ERR_NOT_SUPPORTED, buf, count, off, actual);
+ }
+
+ zx_off_t GetSizeOp() { return Dispatch(ops->get_size, 0lu); }
+
+ zx_status_t IoctlOp(uint32_t op, const void* in_buf, size_t in_len, void* out_buf, size_t out_len,
+ size_t* out_actual) {
+ return Dispatch(ops->ioctl, ZX_ERR_NOT_SUPPORTED, op, in_buf, in_len, out_buf, out_len,
+ out_actual);
+ }
+
+ zx_status_t MessageOp(fidl_msg_t* msg, fidl_txn_t* txn) {
+ return Dispatch(ops->message, ZX_ERR_NOT_SUPPORTED, msg, txn);
+ }
+
+ void PushBindConn(const fs::FidlConnection& conn);
+ bool PopBindConn(fs::FidlConnection* conn);
+
+ // Check if this devhost has a device with the given ID, and if so returns a
+ // reference to it.
+ static fbl::RefPtr<zx_device> GetDeviceFromLocalId(uint64_t local_id);
+
+ uint64_t local_id() const { return local_id_; }
+ void set_local_id(uint64_t id);
+
+ uintptr_t magic = DEV_MAGIC;
+
+ const zx_protocol_device_t* ops = nullptr;
+
+ // reserved for driver use; will not be touched by devmgr
+ void* ctx = nullptr;
+
+ uint32_t flags = 0;
+
+ zx::eventpair event;
+ zx::eventpair local_event;
+ // The RPC channel is owned by |conn|
+ zx::unowned_channel rpc;
+
+ // most devices implement a single
+ // protocol beyond the base device protocol
+ uint32_t protocol_id = 0;
+ void* protocol_ops = nullptr;
+
+ // driver that has published this device
+ zx_driver_t* driver = nullptr;
+
+ // parent in the device tree
+ fbl::RefPtr<zx_device_t> parent;
+
+ // for the parent's device_list
+ fbl::DoublyLinkedListNodeState<zx_device*> node;
+ struct Node {
+ static fbl::DoublyLinkedListNodeState<zx_device*>& node_state(zx_device& obj) {
+ return obj.node;
}
+ };
- zx_status_t CloseOp(uint32_t flags) {
- return Dispatch(ops->close, ZX_OK, flags);
+ // list of this device's children in the device tree
+ fbl::DoublyLinkedList<zx_device*, Node> children;
+
+ // list node for the defer_device_list
+ fbl::DoublyLinkedListNodeState<zx_device*> defer;
+ struct DeferNode {
+ static fbl::DoublyLinkedListNodeState<zx_device*>& node_state(zx_device& obj) {
+ return obj.defer;
}
+ };
- void UnbindOp() {
- Dispatch(ops->unbind);
+ // This is an atomic so that the connection's async loop can inspect this
+ // value to determine if an expected shutdown is happening. See comments in
+ // devhost_remove().
+ std::atomic<devmgr::DeviceControllerConnection*> conn = nullptr;
+
+ fbl::Mutex proxy_ios_lock;
+ devmgr::ProxyIostate* proxy_ios TA_GUARDED(proxy_ios_lock) = nullptr;
+
+ char name[ZX_DEVICE_NAME_MAX + 1] = {};
+
+ // Trait structures for the local ID map
+ struct LocalIdNode {
+ static fbl::WAVLTreeNodeState<fbl::RefPtr<zx_device>>& node_state(zx_device& obj) {
+ return obj.local_id_node_;
}
+ };
+ struct LocalIdKeyTraits {
+ static uint64_t GetKey(const zx_device& obj) { return obj.local_id_; }
+ static bool LessThan(const uint64_t& key1, const uint64_t& key2) { return key1 < key2; }
+ static bool EqualTo(const uint64_t& key1, const uint64_t& key2) { return key1 == key2; }
+ };
- void ReleaseOp() {
- Dispatch(ops->release);
+ void set_composite(fbl::RefPtr<devmgr::CompositeDevice> composite);
+ fbl::RefPtr<devmgr::CompositeDevice> take_composite();
+
+ private:
+ zx_device() = default;
+
+ friend class fbl::Recyclable<zx_device_t>;
+ void fbl_recycle();
+
+ // Templates that dispatch the protocol operations if they were set.
+ // If they were not set, the second paramater is returned to the caller
+ // (usually ZX_ERR_NOT_SUPPORTED)
+ template <typename RetType, typename... ArgTypes>
+ RetType Dispatch(RetType (*op)(void* ctx, ArgTypes...), RetType fallback, ArgTypes... args) {
+ return op ? (*op)(ctx, args...) : fallback;
+ }
+
+ template <typename... ArgTypes>
+ void Dispatch(void (*op)(void* ctx, ArgTypes...), ArgTypes... args) {
+ if (op) {
+ (*op)(ctx, args...);
}
+ }
- zx_status_t SuspendOp(uint32_t flags) {
- return Dispatch(ops->suspend, ZX_ERR_NOT_SUPPORTED, flags);
- }
+ // If this device is a component of a composite, this points to the
+ // composite control structure.
+ fbl::RefPtr<devmgr::CompositeDevice> composite_;
- zx_status_t ResumeOp(uint32_t flags) {
- return Dispatch(ops->resume, ZX_ERR_NOT_SUPPORTED, flags);
- }
+ fbl::WAVLTreeNodeState<fbl::RefPtr<zx_device>> local_id_node_;
- zx_status_t ReadOp(void* buf, size_t count, zx_off_t off, size_t* actual) {
- return Dispatch(ops->read, ZX_ERR_NOT_SUPPORTED, buf, count, off, actual);
- }
+ // Identifier assigned by devmgr that can be used to assemble composite
+ // devices.
+ uint64_t local_id_ = 0;
- zx_status_t WriteOp(const void* buf, size_t count, zx_off_t off, size_t* actual) {
- return Dispatch(ops->write, ZX_ERR_NOT_SUPPORTED, buf, count, off, actual);
- }
-
- zx_off_t GetSizeOp() {
- return Dispatch(ops->get_size, 0lu);
- }
-
- zx_status_t IoctlOp(uint32_t op, const void* in_buf, size_t in_len, void* out_buf,
- size_t out_len, size_t* out_actual) {
- return Dispatch(ops->ioctl, ZX_ERR_NOT_SUPPORTED, op, in_buf, in_len, out_buf, out_len, out_actual);
- }
-
- zx_status_t MessageOp(fidl_msg_t* msg, fidl_txn_t* txn) {
- return Dispatch(ops->message, ZX_ERR_NOT_SUPPORTED, msg, txn);
- }
-
- void PushBindConn(const fs::FidlConnection& conn);
- bool PopBindConn(fs::FidlConnection* conn);
-
- // Check if this devhost has a device with the given ID, and if so returns a
- // reference to it.
- static fbl::RefPtr<zx_device> GetDeviceFromLocalId(uint64_t local_id);
-
- uint64_t local_id() const { return local_id_; }
- void set_local_id(uint64_t id);
-
- uintptr_t magic = DEV_MAGIC;
-
- const zx_protocol_device_t* ops = nullptr;
-
- // reserved for driver use; will not be touched by devmgr
- void* ctx = nullptr;
-
- uint32_t flags = 0;
-
- zx::eventpair event;
- zx::eventpair local_event;
- // The RPC channel is owned by |conn|
- zx::unowned_channel rpc;
-
- // most devices implement a single
- // protocol beyond the base device protocol
- uint32_t protocol_id = 0;
- void* protocol_ops = nullptr;
-
- // driver that has published this device
- zx_driver_t* driver = nullptr;
-
- // parent in the device tree
- fbl::RefPtr<zx_device_t> parent;
-
- // for the parent's device_list
- fbl::DoublyLinkedListNodeState<zx_device*> node;
- struct Node {
- static fbl::DoublyLinkedListNodeState<zx_device*>& node_state(zx_device& obj) {
- return obj.node;
- }
- };
-
- // list of this device's children in the device tree
- fbl::DoublyLinkedList<zx_device*, Node> children;
-
- // list node for the defer_device_list
- fbl::DoublyLinkedListNodeState<zx_device*> defer;
- struct DeferNode {
- static fbl::DoublyLinkedListNodeState<zx_device*>& node_state(zx_device& obj) {
- return obj.defer;
- }
- };
-
- // This is an atomic so that the connection's async loop can inspect this
- // value to determine if an expected shutdown is happening. See comments in
- // devhost_remove().
- std::atomic<devmgr::DeviceControllerConnection*> conn = nullptr;
-
- fbl::Mutex proxy_ios_lock;
- devmgr::ProxyIostate* proxy_ios TA_GUARDED(proxy_ios_lock) = nullptr;
-
- char name[ZX_DEVICE_NAME_MAX + 1] = {};
-
- // Trait structures for the local ID map
- struct LocalIdNode {
- static fbl::WAVLTreeNodeState<fbl::RefPtr<zx_device>>& node_state(zx_device& obj) {
- return obj.local_id_node_;
- }
- };
- struct LocalIdKeyTraits {
- static uint64_t GetKey(const zx_device& obj) { return obj.local_id_; }
- static bool LessThan(const uint64_t& key1, const uint64_t& key2) { return key1 < key2; }
- static bool EqualTo (const uint64_t& key1, const uint64_t& key2) { return key1 == key2; }
- };
-
- void set_composite(fbl::RefPtr<devmgr::CompositeDevice> composite);
- fbl::RefPtr<devmgr::CompositeDevice> take_composite();
-
-private:
- zx_device() = default;
-
- friend class fbl::Recyclable<zx_device_t>;
- void fbl_recycle();
-
- // Templates that dispatch the protocol operations if they were set.
- // If they were not set, the second paramater is returned to the caller
- // (usually ZX_ERR_NOT_SUPPORTED)
- template <typename RetType, typename... ArgTypes>
- RetType Dispatch(RetType (*op)(void* ctx, ArgTypes...),
- RetType fallback, ArgTypes... args) {
- return op ? (*op)(ctx, args...) : fallback;
- }
-
- template <typename... ArgTypes>
- void Dispatch(void (*op)(void* ctx, ArgTypes...), ArgTypes... args) {
- if (op) {
- (*op)(ctx, args...);
- }
- }
-
- // If this device is a component of a composite, this points to the
- // composite control structure.
- fbl::RefPtr<devmgr::CompositeDevice> composite_;
-
- fbl::WAVLTreeNodeState<fbl::RefPtr<zx_device>> local_id_node_;
-
- // Identifier assigned by devmgr that can be used to assemble composite
- // devices.
- uint64_t local_id_ = 0;
-
- // The connection associated with a fuchsia.device.Controller/Bind.
- fbl::Mutex bind_conn_lock_;
- fbl::Vector<fs::FidlConnection> bind_conn_ TA_GUARDED(bind_conn_lock_);
+ // The connection associated with a fuchsia.device.Controller/Bind.
+ fbl::Mutex bind_conn_lock_;
+ fbl::Vector<fs::FidlConnection> bind_conn_ TA_GUARDED(bind_conn_lock_);
};
// zx_device_t objects must be created or initialized by the driver manager's
@@ -227,3 +221,5 @@
// Note that device_close() is intended to consume a reference (logically, the
// one created by device_open).
zx_status_t device_close(fbl::RefPtr<zx_device_t> dev, uint32_t flags);
+
+#endif // ZIRCON_SYSTEM_CORE_DEVMGR_DEVHOST_ZX_DEVICE_H_