1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <fuchsia/device/manager/c/fidl.h>
6 #include <lib/fidl/cpp/builder.h>
7 #include <lib/fidl/cpp/message.h>
8 #include <lib/fidl/cpp/message_part.h>
9 
10 #include "coordinator.h"
11 #include "../shared/log.h"
12 
13 namespace devmgr {
14 
dh_send_remove_device(const Device * dev)15 zx_status_t dh_send_remove_device(const Device* dev) {
16     FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_device_manager_ControllerRemoveDeviceRequest)];
17     fidl::Builder builder(wr_bytes, sizeof(wr_bytes));
18 
19     auto req = builder.New<fuchsia_device_manager_ControllerRemoveDeviceRequest>();
20     ZX_ASSERT(req != nullptr);
21     req->hdr.ordinal = fuchsia_device_manager_ControllerRemoveDeviceOrdinal;
22     // TODO(teisenbe): Allocate and track txids
23     req->hdr.txid = 1;
24 
25     fidl::Message msg(builder.Finalize(), fidl::HandlePart(nullptr, 0));
26     return msg.Write(dev->hrpc.get(), 0);
27 }
28 
dh_send_create_device(Device * dev,Devhost * dh,zx::channel rpc,zx::vmo driver,const char * args,zx::handle rpc_proxy)29 zx_status_t dh_send_create_device(Device* dev, Devhost* dh, zx::channel rpc, zx::vmo driver,
30                                   const char* args, zx::handle rpc_proxy) {
31     size_t driver_path_size = strlen(dev->libname);
32     size_t args_size = strlen(args);
33     uint32_t wr_num_bytes = static_cast<uint32_t>(
34             sizeof(fuchsia_device_manager_ControllerCreateDeviceRequest) +
35             FIDL_ALIGN(driver_path_size) + FIDL_ALIGN(args_size));
36     FIDL_ALIGNDECL char wr_bytes[wr_num_bytes];
37     fidl::Builder builder(wr_bytes, wr_num_bytes);
38 
39     auto req = builder.New<fuchsia_device_manager_ControllerCreateDeviceRequest>();
40     char* driver_path_data = builder.NewArray<char>(static_cast<uint32_t>(driver_path_size));
41     char* args_data = builder.NewArray<char>(static_cast<uint32_t>(args_size));
42     ZX_ASSERT(req != nullptr && driver_path_data != nullptr && args_data != nullptr);
43     req->hdr.ordinal = fuchsia_device_manager_ControllerCreateDeviceOrdinal;
44     // TODO(teisenbe): Allocate and track txids
45     req->hdr.txid = 1;
46 
47     req->rpc = FIDL_HANDLE_PRESENT;
48 
49     req->driver_path.size = driver_path_size;
50     req->driver_path.data = reinterpret_cast<char*>(FIDL_ALLOC_PRESENT);
51     memcpy(driver_path_data, dev->libname, driver_path_size);
52 
53     req->driver = FIDL_HANDLE_PRESENT;
54     req->parent_proxy = rpc_proxy.is_valid() ? FIDL_HANDLE_PRESENT : FIDL_HANDLE_ABSENT;
55 
56     req->proxy_args.size = args_size;
57     req->proxy_args.data = reinterpret_cast<char*>(FIDL_ALLOC_PRESENT);
58     memcpy(args_data, args, args_size);
59 
60     zx_handle_t handles[3] = { rpc.release(), driver.release() };
61     uint32_t num_handles = 2;
62 
63     if (rpc_proxy.is_valid()) {
64         handles[num_handles++] = rpc_proxy.release();
65     }
66 
67     fidl::Message msg(builder.Finalize(), fidl::HandlePart(handles, num_handles, num_handles));
68     return msg.Write(dh->hrpc(), 0);
69 }
70 
dh_send_create_device_stub(Devhost * dh,zx::channel rpc,uint32_t protocol_id)71 zx_status_t dh_send_create_device_stub(Devhost* dh, zx::channel rpc, uint32_t protocol_id) {
72     FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_device_manager_ControllerCreateDeviceStubRequest)];
73     fidl::Builder builder(wr_bytes, sizeof(wr_bytes));
74 
75     auto req = builder.New<fuchsia_device_manager_ControllerCreateDeviceStubRequest>();
76     ZX_ASSERT(req != nullptr);
77     req->hdr.ordinal = fuchsia_device_manager_ControllerCreateDeviceStubOrdinal;
78     // TODO(teisenbe): Allocate and track txids
79     req->hdr.txid = 1;
80 
81     req->rpc = FIDL_HANDLE_PRESENT;
82     req->protocol_id  = protocol_id;
83 
84     zx_handle_t handles[] = { rpc.release() };
85     fidl::Message msg(builder.Finalize(),
86                       fidl::HandlePart(handles, fbl::count_of(handles), fbl::count_of(handles)));
87     return msg.Write(dh->hrpc(), 0);
88 }
89 
dh_send_bind_driver(Device * dev,const char * libname,zx::vmo driver)90 zx_status_t dh_send_bind_driver(Device* dev, const char* libname, zx::vmo driver) {
91     size_t libname_size = strlen(libname);
92     uint32_t wr_num_bytes = static_cast<uint32_t>(
93             sizeof(fuchsia_device_manager_ControllerBindDriverRequest) + FIDL_ALIGN(libname_size));
94     FIDL_ALIGNDECL char wr_bytes[wr_num_bytes];
95     fidl::Builder builder(wr_bytes, wr_num_bytes);
96 
97     auto req = builder.New<fuchsia_device_manager_ControllerBindDriverRequest>();
98     char* libname_data = builder.NewArray<char>(static_cast<uint32_t>(libname_size));
99     ZX_ASSERT(req != nullptr && libname_data != nullptr);
100     req->hdr.ordinal = fuchsia_device_manager_ControllerBindDriverOrdinal;
101     // TODO(teisenbe): Allocate and track txids
102     req->hdr.txid = 1;
103 
104     req->driver_path.size = libname_size;
105     req->driver_path.data = reinterpret_cast<char*>(FIDL_ALLOC_PRESENT);
106     memcpy(libname_data, libname, libname_size);
107 
108     req->driver = FIDL_HANDLE_PRESENT;
109 
110     zx_handle_t handles[] = { driver.release() };
111     fidl::Message msg(builder.Finalize(),
112                       fidl::HandlePart(handles, fbl::count_of(handles), fbl::count_of(handles)));
113     return msg.Write(dev->hrpc.get(), 0);
114 }
115 
dh_send_connect_proxy(const Device * dev,zx::channel proxy)116 zx_status_t dh_send_connect_proxy(const Device* dev, zx::channel proxy) {
117     FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_device_manager_ControllerConnectProxyRequest)];
118     fidl::Builder builder(wr_bytes, sizeof(wr_bytes));
119 
120     auto req = builder.New<fuchsia_device_manager_ControllerConnectProxyRequest>();
121     ZX_ASSERT(req != nullptr);
122     req->hdr.ordinal = fuchsia_device_manager_ControllerConnectProxyOrdinal;
123     // TODO(teisenbe): Allocate and track txids
124     req->hdr.txid = 1;
125 
126     req->shadow = FIDL_HANDLE_PRESENT;
127 
128     zx_handle_t handles[] = { proxy.release() };
129     fidl::Message msg(builder.Finalize(),
130                       fidl::HandlePart(handles, fbl::count_of(handles), fbl::count_of(handles)));
131     return msg.Write(dev->hrpc.get(), 0);
132 }
133 
dh_send_suspend(const Device * dev,uint32_t flags)134 zx_status_t dh_send_suspend(const Device* dev, uint32_t flags) {
135     FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_device_manager_ControllerSuspendRequest)];
136     fidl::Builder builder(wr_bytes, sizeof(wr_bytes));
137 
138     auto req = builder.New<fuchsia_device_manager_ControllerSuspendRequest>();
139     ZX_ASSERT(req != nullptr);
140     req->hdr.ordinal = fuchsia_device_manager_ControllerSuspendOrdinal;
141     // TODO(teisenbe): Allocate and track txids
142     req->hdr.txid = 1;
143     req->flags = flags;
144 
145     fidl::Message msg(builder.Finalize(), fidl::HandlePart(nullptr, 0));
146     return msg.Write(dev->hrpc.get(), 0);
147 }
148 
149 
150 } // namespace devmgr
151