diff --git a/zircon/system/core/devmgr/devcoordinator/coordinator.cpp b/zircon/system/core/devmgr/devcoordinator/coordinator.cpp index ebc7a9bc42711a9afb95c41604d785887b8c7fd8..24ddf1861c854dc77fd7681675a15c26ab1acbc0 100644 --- a/zircon/system/core/devmgr/devcoordinator/coordinator.cpp +++ b/zircon/system/core/devmgr/devcoordinator/coordinator.cpp @@ -1183,6 +1183,15 @@ static zx_status_t fidl_PublishMetadata(void* ctx, const char* device_path_data, return fuchsia_device_manager_CoordinatorPublishMetadata_reply(txn, status); } +static zx_status_t fidl_AddCompositeDevice( + void* ctx, const char* name_data, size_t name_size, const uint64_t* props, + size_t props_count, const fuchsia_device_manager_DeviceComponent components[16], + uint32_t components_count, uint32_t coresident_device_index, fidl_txn_t* txn) { + + //auto dev = static_cast<Device*>(ctx); + return fuchsia_device_manager_CoordinatorAddCompositeDevice_reply(txn, ZX_ERR_NOT_SUPPORTED); +} + static zx_status_t fidl_DmCommand(void* ctx, zx_handle_t raw_log_socket, const char* command_data, size_t command_size, fidl_txn_t* txn) { zx::socket log_socket(raw_log_socket); @@ -1299,6 +1308,8 @@ static fuchsia_device_manager_Coordinator_ops_t fidl_ops = { .GetMetadataSize = fidl_GetMetadataSize, .AddMetadata = fidl_AddMetadata, .PublishMetadata = fidl_PublishMetadata, + .AddCompositeDevice = fidl_AddCompositeDevice, + .DmCommand = fidl_DmCommand, .DmOpenVirtcon = fidl_DmOpenVirtcon, .DmMexec = fidl_DmMexec, diff --git a/zircon/system/core/devmgr/devhost/api.cpp b/zircon/system/core/devmgr/devhost/api.cpp index 3d2a2915c5f7b84b1bf1a39581259b8e3e688dff..ad882b83769020d9befa96cf72537b79476d3b73 100644 --- a/zircon/system/core/devmgr/devhost/api.cpp +++ b/zircon/system/core/devmgr/devhost/api.cpp @@ -263,6 +263,8 @@ __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) { - // TODO(ZX-2648): Implement - return ZX_ERR_NOT_SUPPORTED; + 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/devhost.cpp b/zircon/system/core/devmgr/devhost/devhost.cpp index bf8773a32f0825ff26e05fb1a5d5f3f173d35a11..48dbaf260082f31bcd810cb136d376c049783bb1 100644 --- a/zircon/system/core/devmgr/devhost/devhost.cpp +++ b/zircon/system/core/devmgr/devhost/devhost.cpp @@ -1185,6 +1185,64 @@ zx_status_t devhost_publish_metadata(const fbl::RefPtr<zx_device_t>& dev, const 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, + size_t components_count, + uint32_t coresident_device_index) { + 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; + } + + 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; +} + zx_handle_t root_resource_handle; zx_status_t devhost_start_connection(fbl::unique_ptr<DevfsConnection> conn, zx::channel h) { diff --git a/zircon/system/core/devmgr/devhost/devhost.h b/zircon/system/core/devmgr/devhost/devhost.h index ff08a9e9eb02b2363ef51cbfd9dc63835a5c9b1c..751c4d1449621c7cbb02cf33169496fec1a3e28e 100644 --- a/zircon/system/core/devmgr/devhost/devhost.h +++ b/zircon/system/core/devmgr/devhost/devhost.h @@ -163,6 +163,12 @@ zx_status_t devhost_add_metadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t t 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, + size_t components_count, + uint32_t coresident_device_index) REQ_DM_LOCK; + // shared between devhost.c and rpc-device.c struct DevcoordinatorConnection : AsyncLoopOwnedRpcHandler<DevcoordinatorConnection> { DevcoordinatorConnection() = default; diff --git a/zircon/system/fidl/fuchsia-device-manager/coordinator.fidl b/zircon/system/fidl/fuchsia-device-manager/coordinator.fidl index 3ff3f97479a6a14aaab7d195fc7c8be59913e632..e7823ef59b5bb5cc1d4073d5d4b9d37c2465ba9b 100644 --- a/zircon/system/fidl/fuchsia-device-manager/coordinator.fidl +++ b/zircon/system/fidl/fuchsia-device-manager/coordinator.fidl @@ -14,6 +14,9 @@ using zx; // we can make this reflect the actual structure. using DeviceProperty = uint64; +// Same as above, but for bind zx_bind_inst_t. +using BindInstruction = uint64; + /// This definition must match ZX_DEVICE_NAME_MAX and is checked by a static assert. const uint32 DEVICE_NAME_MAX = 31; @@ -33,6 +36,33 @@ const uint32 COMMAND_MAX = 1024; /// Maximum number of properties that can be attached to a device const uint32 PROPERTIES_MAX = 256; +/// Maximum number of components that a composite device can have +const uint32 COMPONENTS_MAX = 8; + +/// Maximum number of parts that a composite device component can have +const uint32 DEVICE_COMPONENT_PARTS_MAX = 16; + +/// Maximum instructions in a match program +const uint32 DEVICE_COMPONENT_PART_INSTRUCTIONS_MAX = 32; + +/// A part of a description of a DeviceComponent +struct DeviceComponentPart { + // This is an awful hack around the LLCPP bindings not being ready yet. + // Since we're using the C ones for now, we can only embed these structures as + // arrays instead of vectors. + uint32 match_program_count; + array<BindInstruction>:DEVICE_COMPONENT_PART_INSTRUCTIONS_MAX match_program; +}; + +/// A piece of a composite device +struct DeviceComponent { + // This is an awful hack around the LLCPP bindings not being ready yet. + // Since we're using the C ones for now, we can only embed these structures as + // arrays instead of vectors. + uint32 parts_count; + array<DeviceComponentPart>:DEVICE_COMPONENT_PARTS_MAX parts; +}; + // All functions in these interfaces have the most-significant-byte set to 0x01 to allow // multiplexing these interfaces and parts of the fuchsia.io interfaces. // TODO(ZX-2922): I believe this shouldn't be necessary anymore. @@ -148,6 +178,16 @@ protocol Coordinator { PublishMetadata(string:DEVICE_PATH_MAX device_path, uint32 key, vector<uint8>:METADATA_MAX? data) -> (zx.status status); + /// Adds the given composite device. This causes the devcoordinator to try to match the + /// components against the existing device tree, and to monitor all new device additions + /// in order to find the components as they are created. + // The treatment of |components| is an awful hack around the LLCPP bindings not being ready + // yet. Since we're using the C ones for now, we can only embed these structures as arrays + // instead of vectors. + AddCompositeDevice(string:DEVICE_NAME_MAX name, vector<DeviceProperty>:PROPERTIES_MAX props, + array<DeviceComponent>:COMPONENTS_MAX components, uint32 components_count, + uint32 coresident_device_index) -> (zx.status status); + /// Special commands for implementing the dmctl device. // TODO(teisenbe): We should revisit how these are carried over.