proxy wip
Change-Id: Id6ca7ea54e4ad897da11b71df650de53a1364c6f
diff --git a/system/dev/board/astro/astro-display.c b/system/dev/board/astro/astro-display.c
index b9819e7..67baeba 100644
--- a/system/dev/board/astro/astro-display.c
+++ b/system/dev/board/astro/astro-display.c
@@ -91,6 +91,9 @@
},
};
+static const uint32_t display_protocols[] = {
+ ZX_PROTOCOL_CANVAS,
+};
static pbus_dev_t display_dev = {
.name = "display",
@@ -107,6 +110,8 @@
.i2c_channel_count = countof(display_i2c_channels),
.btis = display_btis,
.bti_count = countof(display_btis),
+ .protocols = display_protocols,
+ .protocol_count = countof(display_protocols),
};
zx_status_t aml_display_init(aml_bus_t* bus) {
diff --git a/system/dev/board/hikey960/hikey960.c b/system/dev/board/hikey960/hikey960.c
index 6a7db4b..59c5ca5 100644
--- a/system/dev/board/hikey960/hikey960.c
+++ b/system/dev/board/hikey960/hikey960.c
@@ -79,12 +79,13 @@
if (status != ZX_OK) {
goto fail;
}
- status = pbus_register_protocol(&hikey->pbus, ZX_PROTOCOL_GPIO, &hikey->gpio);
+ status = pbus_register_protocol(&hikey->pbus, ZX_PROTOCOL_GPIO, &hikey->gpio, NULL);
if (status != ZX_OK) {
goto fail;
}
- status = pbus_register_protocol(&hikey->pbus, ZX_PROTOCOL_USB_MODE_SWITCH, &usb_mode_switch);
+ status = pbus_register_protocol(&hikey->pbus, ZX_PROTOCOL_USB_MODE_SWITCH, &usb_mode_switch,
+ NULL);
if (status != ZX_OK) {
goto fail;
}
diff --git a/system/dev/board/imx8mevk/imx8mevk.c b/system/dev/board/imx8mevk/imx8mevk.c
index 416af25..7181445 100644
--- a/system/dev/board/imx8mevk/imx8mevk.c
+++ b/system/dev/board/imx8mevk/imx8mevk.c
@@ -148,7 +148,8 @@
goto fail;
}
- status = pbus_register_protocol(&bus->pbus, ZX_PROTOCOL_USB_MODE_SWITCH, &bus->usb_mode_switch);
+ status = pbus_register_protocol(&bus->pbus, ZX_PROTOCOL_USB_MODE_SWITCH, &bus->usb_mode_switch,
+ NULL);
if (status != ZX_OK) {
goto fail;
}
diff --git a/system/dev/board/vim/vim-display.c b/system/dev/board/vim/vim-display.c
index 8a5a72d..2a56c8b 100644
--- a/system/dev/board/vim/vim-display.c
+++ b/system/dev/board/vim/vim-display.c
@@ -71,6 +71,10 @@
},
};
+static const uint32_t vim_display_protocols[] = {
+ ZX_PROTOCOL_CANVAS,
+};
+
static const pbus_dev_t display_dev = {
.name = "display",
.vid = PDEV_VID_KHADAS,
@@ -84,6 +88,8 @@
.irq_count = countof(vim_display_irqs),
.btis = vim_display_btis,
.bti_count = countof(vim_display_btis),
+ .protocols = vim_display_protocols,
+ .protocol_count = countof(vim_display_protocols),
};
zx_status_t vim_display_init(vim_bus_t* bus) {
diff --git a/system/dev/bus/platform/device-resources.cpp b/system/dev/bus/platform/device-resources.cpp
index 91d166f..0054f6b 100644
--- a/system/dev/bus/platform/device-resources.cpp
+++ b/system/dev/bus/platform/device-resources.cpp
@@ -25,13 +25,17 @@
namespace platform_bus {
zx_status_t DeviceResources::Init(const pbus_dev_t* pdev, uint32_t* next_index) {
+ if (pdev->protocol_count > PROXY_MAX_PROTOCOLS) {
+ return ZX_ERR_INVALID_ARGS;
+ }
if (!CopyResources(pdev->mmio_count, pdev->mmios, &mmios_) ||
!CopyResources(pdev->irq_count, pdev->irqs, &irqs_) ||
!CopyResources(pdev->gpio_count, pdev->gpios, &gpios_) ||
!CopyResources(pdev->i2c_channel_count, pdev->i2c_channels, &i2c_channels_) ||
!CopyResources(pdev->clk_count, pdev->clks, &clks_) ||
!CopyResources(pdev->bti_count, pdev->btis, &btis_) ||
- !CopyResources(pdev->metadata_count, pdev->metadata, &metadata_)) {
+ !CopyResources(pdev->metadata_count, pdev->metadata, &metadata_) ||
+ !CopyResources(pdev->protocol_count, pdev->protocols, &protocols_)) {
return ZX_ERR_NO_MEMORY;
}
diff --git a/system/dev/bus/platform/device-resources.h b/system/dev/bus/platform/device-resources.h
index 215812c..87519ec 100644
--- a/system/dev/bus/platform/device-resources.h
+++ b/system/dev/bus/platform/device-resources.h
@@ -42,6 +42,7 @@
inline const pbus_clk_t& clk(size_t i) const { return clks_[i]; }
inline const pbus_bti_t& bti(size_t i) const { return btis_[i]; }
inline const pbus_metadata_t& metadata(size_t i) const { return metadata_[i]; }
+ inline const uint32_t* protocols() const { return protocols_.begin(); }
// Counts for the above resource lists.
inline size_t mmio_count() const { return mmios_.size(); }
@@ -52,10 +53,11 @@
inline size_t bti_count() const { return btis_.size(); }
inline size_t metadata_count() const { return metadata_.size(); }
inline size_t child_count() const { return children_.size(); }
+ inline size_t protocol_count() const { return protocols_.size(); }
private:
// Index of this DeviceResources instance in PlatformDevice::device_index_.
- uint32_t index_;
+ const uint32_t index_;
// Platform bus resources copied from the pbus_dev_t struct from the board driver.
fbl::Array<pbus_mmio_t> mmios_;
@@ -65,6 +67,7 @@
fbl::Array<pbus_clk_t> clks_;
fbl::Array<pbus_bti_t> btis_;
fbl::Array<pbus_metadata_t> metadata_;
+ fbl::Array<uint32_t> protocols_;
// Resources for children of this device.
fbl::Vector<DeviceResources> children_;
diff --git a/system/dev/bus/platform/platform-bus.cpp b/system/dev/bus/platform/platform-bus.cpp
index 59df0a3..5d446e8 100644
--- a/system/dev/bus/platform/platform-bus.cpp
+++ b/system/dev/bus/platform/platform-bus.cpp
@@ -30,7 +30,8 @@
return zx_bti_create(iommu_handle_.get(), 0, bti_id, out_handle);
}
-zx_status_t PlatformBus::RegisterProtocol(uint32_t proto_id, void* protocol) {
+zx_status_t PlatformBus::RegisterProtocol(uint32_t proto_id, void* protocol,
+ platform_proxy_cb proxy_cb) {
if (!protocol) {
return ZX_ERR_INVALID_ARGS;
}
@@ -89,8 +90,20 @@
break;
}
default:
- // TODO(voydanoff) consider having a registry of arbitrary protocols
- return ZX_ERR_NOT_SUPPORTED;
+ if (proxy_cb == nullptr) {
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+ fbl::AllocChecker ac;
+ fbl::unique_ptr<ProtoProxy> proxy(new (&ac) ProtoProxy(proto_id,
+ static_cast<ddk::AnyProtocol*>(protocol), proxy_cb));
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ fbl::AutoLock lock(&mutex_);
+ proto_proxys_.insert_or_replace(fbl::move(proxy));
+ sync_completion_signal(&proto_completion_);
+ return ZX_OK;
}
fbl::AutoLock lock(&mutex_);
@@ -192,44 +205,44 @@
return ZX_OK;
}
-zx_status_t PlatformBus::DdkGetProtocol(uint32_t proto_id, void* protocol) {
+zx_status_t PlatformBus::DdkGetProtocol(uint32_t proto_id, void* out) {
switch (proto_id) {
case ZX_PROTOCOL_PLATFORM_BUS: {
- auto proto = static_cast<platform_bus_protocol_t*>(protocol);
+ auto proto = static_cast<platform_bus_protocol_t*>(out);
proto->ctx = this;
proto->ops = &pbus_proto_ops_;
return ZX_OK;
}
case ZX_PROTOCOL_USB_MODE_SWITCH:
if (ums_ != nullptr) {
- ums_->GetProto(static_cast<usb_mode_switch_protocol_t*>(protocol));
+ ums_->GetProto(static_cast<usb_mode_switch_protocol_t*>(out));
return ZX_OK;
}
break;
case ZX_PROTOCOL_GPIO:
if (gpio_ != nullptr) {
- gpio_->GetProto(static_cast<gpio_protocol_t*>(protocol));
+ gpio_->GetProto(static_cast<gpio_protocol_t*>(out));
return ZX_OK;
}
break;
case ZX_PROTOCOL_I2C_IMPL:
if (i2c_impl_ != nullptr) {
- i2c_impl_->GetProto(static_cast<i2c_impl_protocol_t*>(protocol));
+ i2c_impl_->GetProto(static_cast<i2c_impl_protocol_t*>(out));
return ZX_OK;
}
break;
case ZX_PROTOCOL_CLK:
if (clk_ != nullptr) {
- clk_->GetProto(static_cast<clk_protocol_t*>(protocol));
+ clk_->GetProto(static_cast<clk_protocol_t*>(out));
return ZX_OK;
}
break;
case ZX_PROTOCOL_IOMMU:
if (iommu_ != nullptr) {
- iommu_->GetProto(static_cast<iommu_protocol_t*>(protocol));
+ iommu_->GetProto(static_cast<iommu_protocol_t*>(out));
} else {
// return default implementation
- auto proto = static_cast<iommu_protocol_t*>(protocol);
+ auto proto = static_cast<iommu_protocol_t*>(out);
proto->ctx = this;
proto->ops = &iommu_proto_ops_;
return ZX_OK;
@@ -237,13 +250,17 @@
break;
case ZX_PROTOCOL_CANVAS:
if (canvas_ != nullptr) {
- canvas_->GetProto(static_cast<canvas_protocol_t*>(protocol));
+ canvas_->GetProto(static_cast<canvas_protocol_t*>(out));
return ZX_OK;
}
break;
default:
- // TODO(voydanoff) consider having a registry of arbitrary protocols
- return ZX_ERR_NOT_SUPPORTED;
+ auto proto_proxy = proto_proxys_.find(proto_id);
+ if (!proto_proxy.IsValid()) {
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+ proto_proxy->GetProtocol(out);
+ return ZX_OK;
}
return ZX_ERR_NOT_SUPPORTED;
diff --git a/system/dev/bus/platform/platform-bus.h b/system/dev/bus/platform/platform-bus.h
index 9fd870c..5f1b487 100644
--- a/system/dev/bus/platform/platform-bus.h
+++ b/system/dev/bus/platform/platform-bus.h
@@ -14,6 +14,7 @@
#include <ddktl/protocol/platform-bus.h>
#include <ddktl/protocol/usb-mode-switch.h>
#include <fbl/array.h>
+#include <fbl/intrusive_wavl_tree.h>
#include <fbl/mutex.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
@@ -31,6 +32,25 @@
namespace platform_bus {
+class ProtoProxy : public fbl::WAVLTreeContainable<fbl::unique_ptr<ProtoProxy>> {
+public:
+ ProtoProxy(uint32_t proto_id, ddk::AnyProtocol* protocol, platform_proxy_cb proxy_cb)
+ : proto_id_(proto_id), protocol_(*protocol), proxy_cb_(proxy_cb) {}
+
+ inline uint32_t GetKey() const { return proto_id_; }
+ inline void GetProtocol(void* out) const { memcpy(out, &protocol_, sizeof(protocol_)); }
+
+ inline zx_status_t Proxy(const void* req_buf, uint32_t req_size, void* rsp_buf,
+ uint32_t rsp_buf_size, uint32_t* out_rsp_actual) {
+ return proxy_cb_(req_buf, req_size, rsp_buf, rsp_buf_size, out_rsp_actual);
+ }
+
+private:
+ const uint32_t proto_id_;
+ ddk::AnyProtocol protocol_;
+ const platform_proxy_cb proxy_cb_;
+};
+
class PlatformBus;
using PlatformBusType = ddk::Device<PlatformBus, ddk::GetProtocolable>;
@@ -47,7 +67,7 @@
// Platform bus protocol implementation.
zx_status_t DeviceAdd(const pbus_dev_t* dev);
zx_status_t ProtocolDeviceAdd(uint32_t proto_id, const pbus_dev_t* dev);
- zx_status_t RegisterProtocol(uint32_t proto_id, void* protocol);
+ zx_status_t RegisterProtocol(uint32_t proto_id, void* protocol, platform_proxy_cb proxy_cb);
const char* GetBoardName();
zx_status_t SetBoardInfo(const pbus_board_info_t* info);
@@ -111,6 +131,9 @@
// Dummy IOMMU.
zx::handle iommu_handle_;
+
+ fbl::WAVLTree<uint32_t, fbl::unique_ptr<ProtoProxy>> proto_proxys_ __TA_GUARDED(mutex_);
+
};
} // namespace platform_bus
diff --git a/system/dev/bus/platform/platform-device.cpp b/system/dev/bus/platform/platform-device.cpp
index 7dfa30b..aff7014 100644
--- a/system/dev/bus/platform/platform-device.cpp
+++ b/system/dev/bus/platform/platform-device.cpp
@@ -193,6 +193,15 @@
}
return status;
}
+ return ZX_OK;
+}
+
+zx_status_t PlatformDevice::RpcGetProtocols(const DeviceResources* dr, uint32_t* out_protocols,
+ uint32_t* out_protocol_count) {
+ auto count = dr->protocol_count();
+ memcpy(out_protocols, dr->protocols(), count * sizeof(*out_protocols));
+ *out_protocol_count = static_cast<uint32_t>(count);
+ return ZX_OK;
}
zx_status_t PlatformDevice::RpcUmsSetMode(const DeviceResources* dr, usb_mode_t mode) {
@@ -423,6 +432,12 @@
resp_len += resp->pdev.metadata_length;
break;
}
+ case PDEV_GET_PROTOCOLS: {
+ auto protos = reinterpret_cast<uint32_t*>(&resp[1]);
+ status = RpcGetProtocols(dr, protos, &resp->protocol_count);
+ resp_len += static_cast<uint32_t>(resp->protocol_count * sizeof(*protos));
+ break;
+ }
default:
zxlogf(ERROR, "platform_dev_rxrpc: unknown op %u\n", req_header->op);
return ZX_ERR_INTERNAL;
diff --git a/system/dev/bus/platform/platform-device.h b/system/dev/bus/platform/platform-device.h
index a28e477..38539db 100644
--- a/system/dev/bus/platform/platform-device.h
+++ b/system/dev/bus/platform/platform-device.h
@@ -68,6 +68,8 @@
zx_status_t RpcDeviceAdd(const DeviceResources* dr, uint32_t index, uint32_t* out_device_id);
zx_status_t RpcGetMetadata(const DeviceResources* dr, uint32_t index, uint32_t* out_type,
uint8_t* buf, uint32_t buf_size, uint32_t* actual);
+ zx_status_t RpcGetProtocols(const DeviceResources* dr, uint32_t* out_protocols,
+ uint32_t* out_protocol_count);
zx_status_t RpcUmsSetMode(const DeviceResources* dr, usb_mode_t mode);
zx_status_t RpcGpioConfig(const DeviceResources* dr, uint32_t index, uint32_t flags);
zx_status_t RpcGpioSetAltFunction(const DeviceResources* dr, uint32_t index, uint64_t function);
diff --git a/system/dev/bus/platform/platform-proxy-device.h b/system/dev/bus/platform/platform-proxy-device.h
index 73d6974..85e3f1b 100644
--- a/system/dev/bus/platform/platform-proxy-device.h
+++ b/system/dev/bus/platform/platform-proxy-device.h
@@ -104,7 +104,7 @@
DISALLOW_COPY_ASSIGN_AND_MOVE(ProxyDevice);
- uint32_t device_id_;
+ const uint32_t device_id_;
fbl::RefPtr<PlatformProxy> proxy_;
fbl::Vector<Mmio> mmios_;
fbl::Vector<Irq> irqs_;
diff --git a/system/dev/bus/platform/platform-proxy-host.cpp b/system/dev/bus/platform/platform-proxy-host.cpp
new file mode 100644
index 0000000..bb6acb0
--- /dev/null
+++ b/system/dev/bus/platform/platform-proxy-host.cpp
@@ -0,0 +1,63 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform-proxy-host.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <threads.h>
+
+#include <ddk/binding.h>
+#include <ddk/debug.h>
+#include <ddk/device.h>
+#include <ddk/driver.h>
+#include <fbl/unique_ptr.h>
+
+#include "platform-proxy.h"
+
+namespace platform_bus {
+
+zx_status_t ProxyHost::Create(uint32_t proto_id, zx_device_t* parent,
+ fbl::RefPtr<PlatformProxy> proxy) {
+ fbl::AllocChecker ac;
+ fbl::unique_ptr<platform_bus::ProxyHost> host(new (&ac)
+ platform_bus::ProxyHost(proto_id, parent, proxy));
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ char name[ZX_DEVICE_NAME_MAX];
+ snprintf(name, sizeof(name), "ProxyHost[%08x]", proto_id);
+
+ zx_device_prop_t props[] = {
+ {BIND_PLATFORM_PROTO, 0, proto_id},
+ };
+
+ auto status = host->DdkAdd(name, 0, props, countof(props));
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ // devmgr is now in charge of the device.
+ __UNUSED auto* dummy = host.release();
+ return ZX_OK;
+}
+
+void ProxyHost::DdkRelease() {
+ delete this;
+}
+
+zx_status_t ProxyHost::SetProtocol(uint32_t proto_id, void* protocol) {
+return -1;
+
+}
+
+zx_status_t ProxyHost::Proxy(uint32_t proto_id, const void* req_buf, uint32_t req_size,
+ void* rsp_buf, uint32_t rsp_buf_size, uint32_t* out_rsp_actual) {
+return -1;
+}
+
+} // namespace platform_bus
diff --git a/system/dev/bus/platform/platform-proxy-host.h b/system/dev/bus/platform/platform-proxy-host.h
new file mode 100644
index 0000000..8209593
--- /dev/null
+++ b/system/dev/bus/platform/platform-proxy-host.h
@@ -0,0 +1,45 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <ddktl/device.h>
+#include <ddktl/protocol/platform-proxy.h>
+#include <fbl/ref_ptr.h>
+#include <fbl/vector.h>
+#include <lib/zx/channel.h>
+#include <lib/zx/handle.h>
+
+#include "platform-proxy.h"
+
+namespace platform_bus {
+
+class ProxyHost;
+using ProxyHostType = ddk::Device<ProxyHost>;
+
+class ProxyHost : public ProxyHostType,
+ public ddk::PlatformProxyProtocol<ProxyHost> {
+public:
+ static zx_status_t Create(uint32_t proto_id, zx_device_t* parent,
+ fbl::RefPtr<PlatformProxy> proxy);
+
+ // Device protocol implementation.
+ void DdkRelease();
+
+ // Platform proxy protocol implementation.
+ zx_status_t SetProtocol(uint32_t proto_id, void* protocol);
+ zx_status_t Proxy(uint32_t proto_id, const void* req_buf, uint32_t req_size, void* rsp_buf,
+ uint32_t rsp_buf_size, uint32_t* out_rsp_actual);
+
+private:
+ explicit ProxyHost(uint32_t proto_id, zx_device_t* parent, fbl::RefPtr<PlatformProxy> proxy)
+ : ProxyHostType(parent), proto_id_(proto_id), proxy_(proxy) {}
+
+ DISALLOW_COPY_ASSIGN_AND_MOVE(ProxyHost);
+
+ uint32_t proto_id_;
+ fbl::RefPtr<PlatformProxy> proxy_;
+};
+
+} // namespace platform_bus
diff --git a/system/dev/bus/platform/platform-proxy.cpp b/system/dev/bus/platform/platform-proxy.cpp
index 00bc008..ada15a3 100644
--- a/system/dev/bus/platform/platform-proxy.cpp
+++ b/system/dev/bus/platform/platform-proxy.cpp
@@ -20,6 +20,7 @@
#include <ddk/protocol/usb-mode-switch.h>
#include "platform-proxy-device.h"
+#include "platform-proxy-host.h"
// The implementation of the platform bus protocol in this file is for use by
// drivers that exist in a proxy devhost and communicate with the platform bus
@@ -78,10 +79,34 @@
return status;
}
+zx_status_t PlatformProxy::LoadProtocols(zx_device_t* parent) {
+ // Get list of extra protocols to proxy.
+ rpc_pdev_req_t req = {};
+ struct {
+ rpc_pdev_rsp_t pdev;
+ uint32_t protocols[PROXY_MAX_PROTOCOLS];
+ } resp = {};
+ req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
+ req.header.op = PDEV_GET_PROTOCOLS;
+
+ auto status = Rpc(ROOT_DEVICE_ID, &req.header, sizeof(req), &resp.pdev.header, sizeof(resp));
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ uint32_t protocol_count = resp.pdev.protocol_count;
+ for (uint32_t i = 0; i < protocol_count; i++) {
+ printf("PROTOCOL %08x\n", resp.protocols[i]);
+ status = ProxyHost::Create(resp.protocols[i], parent, fbl::RefPtr<PlatformProxy>(this));
+ }
+
+ return ZX_OK;
+}
+
zx_status_t PlatformProxy::Create(zx_device_t* parent, zx_handle_t rpc_channel) {
fbl::AllocChecker ac;
- auto proxy = fbl::MakeRefCountedChecked<PlatformProxy>(&ac, rpc_channel);
+ auto proxy = fbl::MakeRefCountedChecked<PlatformProxy>(&ac, parent, rpc_channel);
if (!ac.check()) {
return ZX_ERR_NO_MEMORY;
}
diff --git a/system/dev/bus/platform/platform-proxy.h b/system/dev/bus/platform/platform-proxy.h
index 9b770df..27148f7 100644
--- a/system/dev/bus/platform/platform-proxy.h
+++ b/system/dev/bus/platform/platform-proxy.h
@@ -19,6 +19,8 @@
public:
static zx_status_t Create(zx_device_t* parent, zx_handle_t rpc_channel);
+ zx_status_t LoadProtocols(zx_device_t* parent);
+
zx_status_t Rpc(uint32_t device_id, rpc_req_header_t* req, uint32_t req_length,
rpc_rsp_header_t* resp, uint32_t resp_length,
zx_handle_t* in_handles, uint32_t in_handle_count,
@@ -34,12 +36,13 @@
friend class fbl::RefPtr<PlatformProxy>;
friend class fbl::internal::MakeRefCountedHelper<PlatformProxy>;
- explicit PlatformProxy(zx_handle_t rpc_channel)
- : rpc_channel_(rpc_channel) {}
+ explicit PlatformProxy(zx_device_t* parent, zx_handle_t rpc_channel)
+ : parent_(parent), rpc_channel_(rpc_channel) {}
DISALLOW_COPY_ASSIGN_AND_MOVE(PlatformProxy);
- zx::channel rpc_channel_;
+ zx_device_t* parent_;
+ const zx::channel rpc_channel_;
};
} // namespace platform_bus
diff --git a/system/dev/bus/platform/proxy-protocol.h b/system/dev/bus/platform/proxy-protocol.h
index ad799de..e47fe05 100644
--- a/system/dev/bus/platform/proxy-protocol.h
+++ b/system/dev/bus/platform/proxy-protocol.h
@@ -40,6 +40,7 @@
PDEV_GET_BOARD_INFO,
PDEV_DEVICE_ADD,
PDEV_GET_METADATA,
+ PDEV_GET_PROTOCOLS,
};
typedef struct {
@@ -59,6 +60,7 @@
uint32_t device_id;
uint32_t metadata_type;
uint32_t metadata_length;
+ uint32_t protocol_count;
} rpc_pdev_rsp_t;
// Maximum metadata size that can be returned via PDEV_DEVICE_GET_METADATA.
@@ -70,6 +72,10 @@
uint8_t metadata[PROXY_MAX_METADATA_SIZE];
} rpc_pdev_metadata_rsp_t;
+// Maximum number of protocols that can be returned via PDEV_GET_PROTOCOLS.
+static constexpr size_t PROXY_MAX_PROTOCOLS = ((PROXY_MAX_TRANSFER_SIZE - sizeof(rpc_pdev_rsp_t))
+ / sizeof(uint32_t));
+
// Maximum I2C transfer is I2C_MAX_TRANSFER_SIZE minus size of largest header.
static constexpr uint32_t I2C_MAX_TRANSFER_SIZE = (PROXY_MAX_TRANSFER_SIZE -
(sizeof(rpc_pdev_req_t) > sizeof(rpc_pdev_rsp_t) ?
diff --git a/system/dev/bus/platform/rules.mk b/system/dev/bus/platform/rules.mk
index 0fae0b2..2626d75 100644
--- a/system/dev/bus/platform/rules.mk
+++ b/system/dev/bus/platform/rules.mk
@@ -43,6 +43,7 @@
$(LOCAL_DIR)/platform-proxy.cpp \
$(LOCAL_DIR)/platform-proxy-bind.c \
$(LOCAL_DIR)/platform-proxy-device.cpp \
+ $(LOCAL_DIR)/platform-proxy-host.cpp \
MODULE_STATIC_LIBS := \
system/ulib/ddk \
diff --git a/system/dev/clk/amlogic-clk/aml-clk.cpp b/system/dev/clk/amlogic-clk/aml-clk.cpp
index f34dc24..0816462 100644
--- a/system/dev/clk/amlogic-clk/aml-clk.cpp
+++ b/system/dev/clk/amlogic-clk/aml-clk.cpp
@@ -157,7 +157,7 @@
.ctx = this,
};
- status = pbus_register_protocol(&pbus, ZX_PROTOCOL_CLK, &clk_proto);
+ status = pbus_register_protocol(&pbus, ZX_PROTOCOL_CLK, &clk_proto, NULL);
if (status != ZX_OK) {
zxlogf(ERROR, "meson_clk_bind: pbus_register_protocol failed, st = %d\n", status);
return status;
diff --git a/system/dev/clk/hisi-lib/hisi-clk.c b/system/dev/clk/hisi-lib/hisi-clk.c
index 35c46a9..79baa6b 100644
--- a/system/dev/clk/hisi-lib/hisi-clk.c
+++ b/system/dev/clk/hisi-lib/hisi-clk.c
@@ -224,7 +224,7 @@
hisi_clk->clk.ops = &clk_ops;
hisi_clk->clk.ctx = hisi_clk;
- st = pbus_register_protocol(&pbus, ZX_PROTOCOL_CLK, &hisi_clk->clk);
+ st = pbus_register_protocol(&pbus, ZX_PROTOCOL_CLK, &hisi_clk->clk, NULL);
if (st != ZX_OK) {
zxlogf(ERROR, "hisi_clk_bind: pbus_register_protocol failed, st = %d\n", st);
goto fail;
diff --git a/system/dev/clk/meson-lib/meson_clk.c b/system/dev/clk/meson-lib/meson_clk.c
new file mode 100644
index 0000000..e277e64
--- /dev/null
+++ b/system/dev/clk/meson-lib/meson_clk.c
@@ -0,0 +1,166 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <hw/reg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <threads.h>
+
+#include <zircon/assert.h>
+#include <zircon/threads.h>
+
+#include <ddk/binding.h>
+#include <ddk/debug.h>
+#include <ddk/device.h>
+#include <ddk/protocol/clk.h>
+#include <ddk/protocol/platform-bus.h>
+#include <ddk/protocol/platform-defs.h>
+#include <ddk/protocol/platform-device.h>
+
+#include <dev/clk/meson-lib/meson.h>
+
+typedef struct meson_clk {
+ platform_device_protocol_t pdev;
+ clk_protocol_t clk;
+ zx_device_t* zxdev;
+ io_buffer_t mmio;
+
+ meson_clk_gate_t* gates;
+ size_t gate_count;
+
+ // Serialize access to clocks.
+ mtx_t lock;
+} meson_clk_t;
+
+static zx_status_t meson_clk_toggle(void* ctx, const uint32_t idx,
+ const bool enable) {
+ meson_clk_t* const meson_clk = ctx;
+
+ if (idx >= meson_clk->gate_count) return ZX_ERR_INVALID_ARGS;
+
+ const meson_clk_gate_t* const gate = &meson_clk->gates[idx];
+
+ volatile uint32_t* regs = (volatile uint32_t*)io_buffer_virt(&meson_clk->mmio);
+
+ mtx_lock(&meson_clk->lock);
+
+ uint32_t val = readl(regs + gate->reg);
+
+ if (enable) {
+ val |= (1 << gate->bit);
+ } else {
+ val &= ~(1 << gate->bit);
+ }
+
+ writel(val, regs + gate->reg);
+
+ mtx_unlock(&meson_clk->lock);
+
+ return ZX_OK;
+}
+
+static zx_status_t meson_clk_enable(void* ctx, uint32_t clk) {
+ return meson_clk_toggle(ctx, clk, true);
+}
+
+static zx_status_t meson_clk_disable(void* ctx, uint32_t clk) {
+ return meson_clk_toggle(ctx, clk, false);
+}
+
+clk_protocol_ops_t clk_ops = {
+ .enable = meson_clk_enable,
+ .disable = meson_clk_disable,
+};
+
+static void meson_clk_release(void* ctx) {
+ meson_clk_t* clk = ctx;
+ io_buffer_release(&clk->mmio);
+ mtx_destroy(&clk->lock);
+ free(clk);
+}
+
+
+static zx_protocol_device_t meson_clk_device_proto = {
+ .version = DEVICE_OPS_VERSION,
+ .release = meson_clk_release,
+};
+
+zx_status_t meson_clk_init(const char* name, meson_clk_gate_t* gates,
+ const size_t gate_count, zx_device_t* parent) {
+ zx_status_t st = ZX_ERR_INTERNAL;
+
+ meson_clk_t* meson_clk = calloc(1, sizeof(*meson_clk));
+ if (!meson_clk) {
+ zxlogf(ERROR, "meson_clk_bind: failed to allocate meson_clk, "
+ "st = %d\n", ZX_ERR_NO_MEMORY);
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ meson_clk->gates = gates;
+ meson_clk->gate_count = gate_count;
+
+ int ret = mtx_init(&meson_clk->lock, mtx_plain);
+ if (ret != thrd_success) {
+ st = thrd_status_to_zx_status(ret);
+ zxlogf(ERROR, "meson_clk_bind: failed to initialize mutex, st = %d\n",
+ st);
+ goto fail;
+ }
+
+ st = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_DEV, &meson_clk->pdev);
+ if (st != ZX_OK) {
+ zxlogf(ERROR, "meson_clk_bind: failed to get ZX_PROTOCOL_PLATFORM_DEV, "
+ "st = %d\n", st);
+ goto fail;
+ }
+
+ platform_bus_protocol_t pbus;
+ st = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_BUS, &pbus);
+ if (st != ZX_OK) {
+ zxlogf(ERROR, "meson_clk_bind: failed to get ZX_PROTOCOL_PLATFORM_BUS, "
+ "st = %d\n", st);
+ goto fail;
+ }
+
+ st = pdev_map_mmio_buffer(&meson_clk->pdev, 0,
+ ZX_CACHE_POLICY_UNCACHED_DEVICE,
+ &meson_clk->mmio);
+ if (st != ZX_OK) {
+ zxlogf(ERROR, "meson_clk_bind: failed to map clk mmio, st = %d\n", st);
+ goto fail;
+ }
+
+ device_add_args_t args = {
+ .version = DEVICE_ADD_ARGS_VERSION,
+ .name = name,
+ .ctx = meson_clk,
+ .ops = &meson_clk_device_proto,
+ .flags = DEVICE_ADD_NON_BINDABLE,
+ };
+
+ st = device_add(parent, &args, &meson_clk->zxdev);
+ if (st != ZX_OK) {
+ zxlogf(ERROR, "meson_clk_bind: device_add failed, st = %d\n", st);
+ goto fail;
+ }
+
+ meson_clk->clk.ops = &clk_ops;
+ meson_clk->clk.ctx = meson_clk;
+
+ st = pbus_set_protocol(&pbus, ZX_PROTOCOL_CLK, &meson_clk->clk, NULL);
+ if (st != ZX_OK) {
+ zxlogf(ERROR, "meson_clk_bind: pbus_set_protocol failed, st = %d\n", st);
+ goto fail;
+ }
+
+ return ZX_OK;
+
+fail:
+ meson_clk_release(meson_clk);
+
+ // Make sure we don't accidentally return ZX_OK if the device has failed
+ // to bind for some reason
+ ZX_DEBUG_ASSERT(st != ZX_OK);
+ return st;
+}
\ No newline at end of file
diff --git a/system/dev/display/aml-canvas/aml-canvas.c b/system/dev/display/aml-canvas/aml-canvas.c
index 18c84aa..df00ab3 100644
--- a/system/dev/display/aml-canvas/aml-canvas.c
+++ b/system/dev/display/aml-canvas/aml-canvas.c
@@ -158,12 +158,30 @@
.unbind = aml_canvas_unbind,
};
+static zx_protocol_device_t empty_device_protocol = {
+ .version = DEVICE_OPS_VERSION,
+};
+
static canvas_protocol_ops_t canvas_ops = {
.config = aml_canvas_config,
.free = aml_canvas_free,
};
static zx_status_t aml_canvas_bind(void* ctx, zx_device_t* parent) {
+ platform_proxy_protocol_t proxy;
+ if (device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_PROXY, &proxy) == ZX_OK) {
+printf("bind as proxy\n");
+
+ device_add_args_t args = {
+ .version = DEVICE_ADD_ARGS_VERSION,
+ .name = "aml-canvas-proxy",
+ .ops = &empty_device_protocol,
+ .flags = DEVICE_ADD_NON_BINDABLE,
+ };
+
+ return device_add(parent, &args, NULL);
+ }
+
zx_status_t status = ZX_OK;
aml_canvas_t* canvas = calloc(1, sizeof(aml_canvas_t));
@@ -222,7 +240,7 @@
canvas->canvas.ctx = canvas;
// Set the canvas protocol on the platform bus
- pbus_register_protocol(&pbus, ZX_PROTOCOL_CANVAS, &canvas->canvas);
+ pbus_register_protocol(&pbus, ZX_PROTOCOL_CANVAS, &canvas->canvas, NULL);
return ZX_OK;
fail:
aml_canvas_release(canvas);
@@ -234,9 +252,15 @@
.bind = aml_canvas_bind,
};
-ZIRCON_DRIVER_BEGIN(aml_canvas, aml_canvas_driver_ops, "zircon", "0.1", 4)
- BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV),
+ZIRCON_DRIVER_BEGIN(aml_canvas, aml_canvas_driver_ops, "zircon", "0.1", 7)
+ // platform device binding support
+ BI_GOTO_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV, 0),
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_CANVAS),
+
+ // platform proxy binding support
+ BI_LABEL(0),
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_PROXY),
+ BI_MATCH_IF(EQ, BIND_PLATFORM_PROTO, ZX_PROTOCOL_CANVAS),
ZIRCON_DRIVER_END(aml_canvas)
diff --git a/system/dev/gpio/aml-axg-gpio/aml-axg-gpio.c b/system/dev/gpio/aml-axg-gpio/aml-axg-gpio.c
index 5f5384d..b7a992b 100644
--- a/system/dev/gpio/aml-axg-gpio/aml-axg-gpio.c
+++ b/system/dev/gpio/aml-axg-gpio/aml-axg-gpio.c
@@ -491,7 +491,7 @@
gpio->gpio_interrupt->irq_status = 0;
gpio->gpio.ops = &gpio_ops;
gpio->gpio.ctx = gpio;
- pbus_register_protocol(&pbus, ZX_PROTOCOL_GPIO, &gpio->gpio);
+ pbus_register_protocol(&pbus, ZX_PROTOCOL_GPIO, &gpio->gpio, NULL);
gpio->gpio_interrupt->irq_info = calloc(gpio->gpio_interrupt->irq_count,
sizeof(uint8_t));
if (!gpio->gpio_interrupt->irq_info) {
diff --git a/system/dev/gpio/aml-gxl-gpio/aml-gxl-gpio.c b/system/dev/gpio/aml-gxl-gpio/aml-gxl-gpio.c
index 52ac69a..4b14422 100644
--- a/system/dev/gpio/aml-gxl-gpio/aml-gxl-gpio.c
+++ b/system/dev/gpio/aml-gxl-gpio/aml-gxl-gpio.c
@@ -535,7 +535,7 @@
goto fail;
}
- pbus_register_protocol(&pbus, ZX_PROTOCOL_GPIO, &gpio->gpio);
+ pbus_register_protocol(&pbus, ZX_PROTOCOL_GPIO, &gpio->gpio, NULL);
return ZX_OK;
diff --git a/system/dev/gpio/imx8/imx8-gpio.c b/system/dev/gpio/imx8/imx8-gpio.c
index a3b86b4..79fb441 100644
--- a/system/dev/gpio/imx8/imx8-gpio.c
+++ b/system/dev/gpio/imx8/imx8-gpio.c
@@ -472,7 +472,7 @@
gpio->gpio.ops = &gpio_ops;
gpio->gpio.ctx = gpio;
- pbus_register_protocol(&gpio->pbus, ZX_PROTOCOL_GPIO, &gpio->gpio);
+ pbus_register_protocol(&gpio->pbus, ZX_PROTOCOL_GPIO, &gpio->gpio, NULL);
return ZX_OK;
diff --git a/system/dev/i2c/aml-i2c/aml-i2c.c b/system/dev/i2c/aml-i2c/aml-i2c.c
index a3cfcdc..50d346b 100644
--- a/system/dev/i2c/aml-i2c/aml-i2c.c
+++ b/system/dev/i2c/aml-i2c/aml-i2c.c
@@ -410,7 +410,7 @@
i2c->i2c.ops = &i2c_ops;
i2c->i2c.ctx = i2c;
- pbus_register_protocol(&pbus, ZX_PROTOCOL_I2C_IMPL, &i2c->i2c);
+ pbus_register_protocol(&pbus, ZX_PROTOCOL_I2C_IMPL, &i2c->i2c, NULL);
return ZX_OK;
diff --git a/system/dev/i2c/dw-i2c/dw-i2c.c b/system/dev/i2c/dw-i2c/dw-i2c.c
index 78744d5..c201629 100644
--- a/system/dev/i2c/dw-i2c/dw-i2c.c
+++ b/system/dev/i2c/dw-i2c/dw-i2c.c
@@ -491,7 +491,7 @@
i2c->i2c.ops = &i2c_ops;
i2c->i2c.ctx = i2c;
- pbus_register_protocol(&pbus, ZX_PROTOCOL_I2C_IMPL, &i2c->i2c);
+ pbus_register_protocol(&pbus, ZX_PROTOCOL_I2C_IMPL, &i2c->i2c, NULL);
return ZX_OK;
diff --git a/system/public/zircon/driver/binding.h b/system/public/zircon/driver/binding.h
index b0974b2..8b60e50 100644
--- a/system/public/zircon/driver/binding.h
+++ b/system/public/zircon/driver/binding.h
@@ -94,10 +94,11 @@
#define BIND_USB_SUBCLASS 0x0203
#define BIND_USB_PROTOCOL 0x0204
-// Platform device binding variables at 0x03XX
+// Platform bus binding variables at 0x03XX
#define BIND_PLATFORM_DEV_VID 0x0300
#define BIND_PLATFORM_DEV_PID 0x0301
#define BIND_PLATFORM_DEV_DID 0x0302
+#define BIND_PLATFORM_PROTO 0x0303
// ACPI binding variables at 0x04XX
// The _HID is a 7- or 8-byte string. Because a bind property is 32-bit, use 2
diff --git a/system/ulib/ddk/include/ddk/protocol/platform-bus.h b/system/ulib/ddk/include/ddk/protocol/platform-bus.h
index 35b4316..5285d60 100644
--- a/system/ulib/ddk/include/ddk/protocol/platform-bus.h
+++ b/system/ulib/ddk/include/ddk/protocol/platform-bus.h
@@ -4,6 +4,7 @@
#pragma once
+#include <ddk/protocol/platform-proxy.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
@@ -74,6 +75,10 @@
// platform bus resources.
const pbus_dev_t* children;
uint32_t child_count;
+ // Extra protocols to be provided to this platform device and its children.
+ // These fields are only used for the top level pbus_dev_t,
+ const uint32_t* protocols;
+ uint32_t protocol_count;
};
// Subset of pdev_board_info_t to be set by the board driver.
@@ -85,7 +90,8 @@
typedef struct {
zx_status_t (*device_add)(void* ctx, const pbus_dev_t* dev);
zx_status_t (*protocol_device_add)(void* ctx, uint32_t proto_id, const pbus_dev_t* dev);
- zx_status_t (*register_protocol)(void* ctx, uint32_t proto_id, void* protocol);
+ zx_status_t (*register_protocol)(void* ctx, uint32_t proto_id, void* protocol,
+ platform_proxy_cb proxy_cb);
const char* (*get_board_name)(void* ctx);
zx_status_t (*set_board_info)(void* ctx, const pbus_board_info_t* info);
} platform_bus_protocol_ops_t;
@@ -116,8 +122,9 @@
// Called by protocol implementation drivers to register their protocol
// with the platform bus.
static inline zx_status_t pbus_register_protocol(const platform_bus_protocol_t* pbus,
- uint32_t proto_id, void* protocol) {
- return pbus->ops->register_protocol(pbus->ctx, proto_id, protocol);
+ uint32_t proto_id, void* protocol,
+ platform_proxy_cb proxy_cb) {
+ return pbus->ops->register_protocol(pbus->ctx, proto_id, protocol, proxy_cb);
}
// Returns the board name for the underlying hardware.
diff --git a/system/ulib/ddk/include/ddk/protocol/platform-proxy.h b/system/ulib/ddk/include/ddk/protocol/platform-proxy.h
new file mode 100644
index 0000000..98bacac
--- /dev/null
+++ b/system/ulib/ddk/include/ddk/protocol/platform-proxy.h
@@ -0,0 +1,26 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <zircon/compiler.h>
+#include <zircon/types.h>
+
+__BEGIN_CDECLS;
+
+typedef zx_status_t (*platform_proxy_cb)(const void* req_buf, uint32_t req_size, void* rsp_buf,
+ uint32_t rsp_buf_size, uint32_t* out_rsp_actual);
+
+typedef struct {
+ zx_status_t (*set_protocol)(void* ctx, uint32_t proto_id, void* protocol);
+ zx_status_t (*proxy)(void* ctx, uint32_t proto_id, const void* req_buf, uint32_t req_size,
+ void* rsp_buf, uint32_t rsp_buf_size, uint32_t* out_rsp_actual);
+} platform_proxy_protocol_ops_t;
+
+typedef struct {
+ platform_proxy_protocol_ops_t* ops;
+ void* ctx;
+} platform_proxy_protocol_t;
+
+__END_CDECLS;
diff --git a/system/ulib/ddk/include/ddk/protodefs.h b/system/ulib/ddk/include/ddk/protodefs.h
index a41d313..8942812 100644
--- a/system/ulib/ddk/include/ddk/protodefs.h
+++ b/system/ulib/ddk/include/ddk/protodefs.h
@@ -73,6 +73,7 @@
DDK_PROTOCOL_DEF(TEST_PARENT, 'pTSP', "test-parent", PF_NOPUB)
DDK_PROTOCOL_DEF(PLATFORM_BUS, 'pPBU', "platform-bus", 0)
DDK_PROTOCOL_DEF(PLATFORM_DEV, 'pPDV', "platform-dev", 0)
+DDK_PROTOCOL_DEF(PLATFORM_PROXY, 'pPPR', "platform-proxy", PF_NOPUB)
DDK_PROTOCOL_DEF(I2C_HID, 'pIHD', "i2c-hid", 0)
DDK_PROTOCOL_DEF(SERIAL, 'pSer', "serial", 0)
DDK_PROTOCOL_DEF(SERIAL_IMPL, 'pSri', "serial-impl", 0)
diff --git a/system/ulib/ddktl/include/ddktl/protocol/platform-bus-internal.h b/system/ulib/ddktl/include/ddktl/protocol/platform-bus-internal.h
index 057df2a..e2e457f 100644
--- a/system/ulib/ddktl/include/ddktl/protocol/platform-bus-internal.h
+++ b/system/ulib/ddktl/include/ddktl/protocol/platform-bus-internal.h
@@ -14,7 +14,7 @@
DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_pbus_protocol_device_add, ProtocolDeviceAdd,
zx_status_t (C::*)(uint32_t proto_id, const pbus_dev_t* dev));
DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_pbus_register_protocol, RegisterProtocol,
- zx_status_t (C::*)(uint32_t proto_id, void* protocol));
+ zx_status_t (C::*)(uint32_t proto_id, void* protocol, platform_proxy_cb proxy_cb));
DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_pbus_get_board_name, GetBoardName,
const char* (C::*)());
DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_pbus_set_board_info, SetBoardInfo,
@@ -30,7 +30,7 @@
"ProtocolAdd(uint32_t proto_id, const pbus_dev_t* dev)");
static_assert(internal::has_pbus_register_protocol<D>::value,
"PlatformBusProtocol subclasses must implement "
- "RegisterProtocol(uint32_t proto_id, void* protocol)");
+ "RegisterProtocol(uint32_t proto_id, void* protocol, platform_proxy_cb proxy_cb)");
static_assert(internal::has_pbus_get_board_name<D>::value,
"PlatformBusProtocol subclasses must implement "
"GetBoardName()");
diff --git a/system/ulib/ddktl/include/ddktl/protocol/platform-bus.h b/system/ulib/ddktl/include/ddktl/protocol/platform-bus.h
index 6ab475b..880908c 100644
--- a/system/ulib/ddktl/include/ddktl/protocol/platform-bus.h
+++ b/system/ulib/ddktl/include/ddktl/protocol/platform-bus.h
@@ -36,7 +36,7 @@
//
// zx_status_t DeviceAdd(const pbus_dev_t* dev);
// zx_status_t ProtocolDeviceAdd(uint32_t proto_id, const pbus_dev_t* dev);
-// zx_status_t RegisterProtocol(uint32_t proto_id, void* protocol);
+// zx_status_t RegisterProtocol(uint32_t proto_id, void* protocol, platform_proxy_cb proxy_cb);
// const char* GetBoardName();
// zx_status_t SetBoardInfo(const pbus_board_info_t* info);
// ...
@@ -73,8 +73,9 @@
return static_cast<D*>(ctx)->ProtocolDeviceAdd(proto_id, dev);
}
- static zx_status_t RegisterProtocol(void* ctx, uint32_t proto_id, void* protocol) {
- return static_cast<D*>(ctx)->RegisterProtocol(proto_id, protocol);
+ static zx_status_t RegisterProtocol(void* ctx, uint32_t proto_id, void* protocol,
+ platform_proxy_cb proxy_cb) {
+ return static_cast<D*>(ctx)->RegisterProtocol(proto_id, protocol, proxy_cb);
}
static const char* GetBoardName(void* ctx) {
@@ -100,8 +101,8 @@
return ops_->protocol_device_add(ctx_, proto_id, dev);
}
- zx_status_t RegisterProtocol(uint32_t proto_id, void* protocol) {
- return ops_->register_protocol(ctx_, proto_id, protocol);
+ zx_status_t RegisterProtocol(uint32_t proto_id, void* protocol, platform_proxy_cb proxy_cb) {
+ return ops_->register_protocol(ctx_, proto_id, protocol, proxy_cb);
}
const char* GetBoardName() {
diff --git a/system/ulib/ddktl/include/ddktl/protocol/platform-proxy-internal.h b/system/ulib/ddktl/include/ddktl/protocol/platform-proxy-internal.h
new file mode 100644
index 0000000..9bb53a2
--- /dev/null
+++ b/system/ulib/ddktl/include/ddktl/protocol/platform-proxy-internal.h
@@ -0,0 +1,30 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <fbl/type_support.h>
+
+namespace ddk {
+namespace internal {
+
+DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_platform_proxy_set_protocol, SetProtocol,
+ zx_status_t (C::*)(uint32_t proto_id, void* protocol));
+DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_platform_proxy_proxy, Proxy,
+ zx_status_t (C::*)(uint32_t proto_id, const void* req_buf, uint32_t req_size, void* rsp_buf,
+ uint32_t rsp_buf_size, uint32_t* out_rsp_actual));
+
+template <typename D>
+constexpr void CheckPlatformProxyProtocolSubclass() {
+ static_assert(internal::has_platform_proxy_set_protocol<D>::value,
+ "PlatformProxyProtocol subclasses must implement "
+ "SetProtocol(uint32_t proto_id, void* protocol)");
+ static_assert(internal::has_platform_proxy_proxy<D>::value,
+ "PlatformProxyProtocol subclasses must implement "
+ "Proxy(uint32_t proto_id, const void* req_buf, uint32_t req_size, void* rsp_buf, "
+ "uint32_t rsp_buf_size, uint32_t* out_rsp_actual)");
+ }
+
+} // namespace internal
+} // namespace ddk
diff --git a/system/ulib/ddktl/include/ddktl/protocol/platform-proxy.h b/system/ulib/ddktl/include/ddktl/protocol/platform-proxy.h
new file mode 100644
index 0000000..fcb6fb3
--- /dev/null
+++ b/system/ulib/ddktl/include/ddktl/protocol/platform-proxy.h
@@ -0,0 +1,94 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <ddk/protocol/platform-proxy.h>
+#include <ddktl/device-internal.h>
+#include <zircon/assert.h>
+
+#include "platform-proxy-internal.h"
+
+// DDK platform proxy protocol support.
+//
+// :: Proxies ::
+//
+// ddk::PlatformProxyProtocolProxy is a simple wrappers around platform_proxy_protocol_t. It does
+// not own the pointers passed to it.
+//
+// :: Mixins ::
+//
+// ddk::PlatformProxyProtocol is a mixin class that simplifies writing DDK drivers that
+// implement the platform proxy protocol.
+//
+// :: Examples ::
+//
+// // A driver that implements a ZX_PROTOCOL_PLATFORM_PROXY device.
+// class PlatformProxyDevice;
+// using PlatformProxyDeviceType = ddk::Device<PlatformProxyDevice, /* ddk mixins */>;
+//
+// class PlatformProxyDevice : public PlatformProxyDeviceType,
+// public ddk::PlatformProxyProtocol<PlatformProxyDevice> {
+// public:
+// PlatformProxyDevice(zx_device_t* parent)
+// : PlatformProxyDeviceType("my-platform-proxy", parent) {}
+//
+// zx_status_t SetProtocol(uint32_t proto_id, void* protocol);
+// zx_status_t Proxy(uint32_t proto_id, const void* req_buf, uint32_t req_size, void* rsp_buf,
+// uint32_t rsp_buf_size, uint32_t* out_rsp_actual);
+// ...
+// };
+
+namespace ddk {
+
+template <typename D>
+class PlatformProxyProtocol : public internal::base_protocol {
+public:
+ PlatformProxyProtocol() {
+ internal::CheckPlatformProxyProtocolSubclass<D>();
+ platform_proxy_proto_ops_.set_protocol = SetProtocol;
+ platform_proxy_proto_ops_.proxy = Proxy;
+
+ // Can only inherit from one base_protocol implementation.
+ ZX_ASSERT(ddk_proto_id_ == 0);
+ ddk_proto_id_ = ZX_PROTOCOL_PLATFORM_PROXY;
+ ddk_proto_ops_ = &platform_proxy_proto_ops_;
+ }
+
+protected:
+ platform_proxy_protocol_ops_t platform_proxy_proto_ops_ = {};
+
+private:
+ static zx_status_t SetProtocol(void* ctx, uint32_t proto_id, void* protocol) {
+ return static_cast<D*>(ctx)->SetProtocol(proto_id, protocol);
+ }
+
+ static zx_status_t Proxy(void* ctx, uint32_t proto_id, const void* req_buf, uint32_t req_size,
+ void* rsp_buf, uint32_t rsp_buf_size, uint32_t* out_rsp_actual) {
+ return static_cast<D*>(ctx)->Proxy(proto_id, req_buf, req_size, rsp_buf, rsp_buf_size,
+ out_rsp_actual);
+ }
+};
+
+class PlatformProxyProtocolProxy {
+public:
+ PlatformProxyProtocolProxy(platform_proxy_protocol_t* proto)
+ : ops_(proto->ops), ctx_(proto->ctx) {}
+
+ zx_status_t SetProtocol(uint32_t proto_id, void* protocol) {
+ return ops_->set_protocol(ctx_, proto_id, protocol);
+ }
+
+ zx_status_t Proxy(uint32_t proto_id, const void* req_buf, uint32_t req_size, void* rsp_buf,
+ uint32_t rsp_buf_size, uint32_t* out_rsp_actual) {
+ return ops_->proxy(ctx_, proto_id, req_buf, req_size, rsp_buf, rsp_buf_size,
+ out_rsp_actual);
+ }
+
+private:
+ platform_proxy_protocol_ops_t* ops_;
+ void* ctx_;
+};
+
+} // namespace ddk