// 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 <dlfcn.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/binding.h>

#include <zircon/dlfcn.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/log.h>

#include <fdio/util.h>
#include <fdio/remoteio.h>

#include "devcoordinator.h"
#include "devhost.h"
#include "log.h"

uint32_t log_flags = LOG_ERROR | LOG_INFO;


#define ios_from_ph(ph) containerof(ph, devhost_iostate_t, ph)

static zx_status_t dh_handle_dc_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt);

static port_t dh_port;

typedef struct devhost_iostate iostate_t;

static iostate_t root_ios = {
    .ph = {
        .waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
        .func = dh_handle_dc_rpc,
    },
};

static list_node_t dh_drivers = LIST_INITIAL_VALUE(dh_drivers);

static const char* mkdevpath(zx_device_t* dev, char* path, size_t max) {
    if (dev == NULL) {
        return "";
    }
    if (max < 1) {
        return "<invalid>";
    }
    char* end = path + max;
    char sep = 0;

    while (dev) {
        *(--end) = sep;

        size_t len = strlen(dev->name);
        if (len > (size_t)(end - path)) {
            break;
        }
        end -= len;
        memcpy(end, dev->name, len);
        sep = '/';
        dev = dev->parent;
    }
    return end;
}

static uint32_t logflagval(char* flag) {
    if (!strcmp(flag, "error")) {
        return DDK_LOG_ERROR;
    }
    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 strtoul(flag, NULL, 0);
}

static void logflag(char* flag, uint32_t* flags) {
    if (*flag == '+') {
        *flags |= logflagval(flag + 1);
    } else if (*flag == '-') {
        *flags &= ~logflagval(flag + 1);
    }
}

static zx_status_t dh_find_driver(const char* libname, zx_handle_t vmo, zx_driver_t** out) {
    // check for already-loaded driver first
    zx_driver_t* drv;
    list_for_every_entry(&dh_drivers, drv, zx_driver_t, node) {
        if (!strcmp(libname, drv->libname)) {
            *out = drv;
            zx_handle_close(vmo);
            return drv->status;
        }
    }

    int len = strlen(libname) + 1;
    drv = calloc(1, sizeof(zx_driver_t) + len);
    if (drv == NULL) {
        zx_handle_close(vmo);
        return ZX_ERR_NO_MEMORY;
    }
    memcpy((void*) (drv + 1), libname, len);
    drv->libname = (const char*) (drv + 1);
    list_add_tail(&dh_drivers, &drv->node);
    *out = drv;

    void* dl = dlopen_vmo(vmo, RTLD_NOW);
    if (dl == NULL) {
        log(ERROR, "devhost: cannot load '%s': %s\n", libname, dlerror());
        drv->status = ZX_ERR_IO;
        goto done;
    }

    const zircon_driver_note_t* dn = dlsym(dl, "__zircon_driver_note__");
    if (dn == NULL) {
        log(ERROR, "devhost: driver '%s' missing __zircon_driver_note__ symbol\n", libname);
        drv->status = ZX_ERR_IO;
        goto done;
    }
    zx_driver_rec_t* dr = dlsym(dl, "__zircon_driver_rec__");
    if (dr == NULL) {
        log(ERROR, "devhost: driver '%s' missing __zircon_driver_rec__ symbol\n", libname);
        drv->status = ZX_ERR_IO;
        goto done;
    }
    if (!dr->ops) {
        log(ERROR, "devhost: driver '%s' has NULL ops\n", libname);
        drv->status = ZX_ERR_INVALID_ARGS;
        goto done;
    }
    if (dr->ops->version != DRIVER_OPS_VERSION) {
        log(ERROR, "devhost: driver '%s' has bad driver ops version %" PRIx64
            ", expecting %" PRIx64 "\n", libname,
            dr->ops->version, DRIVER_OPS_VERSION);
        drv->status = ZX_ERR_INVALID_ARGS;
        goto done;
    }

    drv->name = dn->payload.name;
    drv->ops = dr->ops;
    dr->driver = drv;

    // check for dprintf log level flags
    char tmp[128];
    snprintf(tmp, sizeof(tmp), "driver.%s.log", drv->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", drv->name, dr->log_flags);
    }

    if (drv->ops->init) {
        drv->status = drv->ops->init(&drv->ctx);
        if (drv->status < 0) {
            log(ERROR, "devhost: driver '%s' failed in init: %d\n",
                libname, drv->status);
        }
    } else {
        drv->status = ZX_OK;
    }

done:
    zx_handle_close(vmo);
    return drv->status;
}

static void dh_handle_open(zxrio_msg_t* msg, size_t len,
                           zx_handle_t h, iostate_t* ios) {
    if ((msg->hcount != 1) ||
        (msg->datalen != (len - ZXRIO_HDR_SZ))) {
        zx_handle_close(h);
        log(ERROR, "devhost: malformed OPEN reques\n");
        return;
    }
    msg->handle[0] = h;

    zx_status_t r;
    if ((r = devhost_rio_handler(msg, ios)) < 0) {
        if (r != ERR_DISPATCHER_INDIRECT) {
            log(ERROR, "devhost: OPEN failed: %d\n", r);
        }
    }
}

static zx_status_t dh_handle_rpc_read(zx_handle_t h, iostate_t* ios) {
    dc_msg_t msg;
    zx_handle_t hin[3];
    uint32_t msize = sizeof(msg);
    uint32_t hcount = 3;

    zx_status_t r;
    if ((r = zx_channel_read(h, 0, &msg, hin, msize,
                             hcount, &msize, &hcount)) < 0) {
        return r;
    }

    char buffer[512];
    const char* path = mkdevpath(ios->dev, buffer, sizeof(buffer));

    // handle remoteio open messages only
    if ((msize >= ZXRIO_HDR_SZ) && (ZXRIO_OP(msg.op) == ZXRIO_OPEN)) {
        if (hcount != 1) {
            r = ZX_ERR_INTERNAL;
            goto fail;
        }
        log(RPC_RIO, "devhost[%s] remoteio OPEN\n", path);
        dh_handle_open((void*) &msg, msize, hin[0], ios);
        return ZX_OK;
    }

    const void* data;
    const char* name;
    const char* args;
    if ((r = dc_msg_unpack(&msg, msize, &data, &name, &args)) < 0) {
        goto fail;
    }
    switch (msg.op) {
    case DC_OP_CREATE_DEVICE_STUB:
        log(RPC_IN, "devhost[%s] create device stub drv='%s'\n", path, name);
        if (hcount < 1 || hcount > 2) {
            printf("HCOUNT %d\n", hcount);
            r = ZX_ERR_INVALID_ARGS;
            goto fail;
        }
        iostate_t* newios = calloc(1, sizeof(iostate_t));
        if (newios == NULL) {
            r = ZX_ERR_NO_MEMORY;
            break;
        }

        //TODO: dev->ops and other lifecycle bits
        // no name means a dummy shadow device
        if ((newios->dev = calloc(1, sizeof(zx_device_t))) == NULL) {
            free(newios);
            r = ZX_ERR_NO_MEMORY;
            break;
        }
        zx_device_t* dev = newios->dev;
        memcpy(dev->name, "shadow", 7);
        dev->protocol_id = msg.protocol_id;
        dev->ops = &device_default_ops;
        dev->rpc = hin[0];
        dev->resource = (hcount == 2 ? hin[1] : ZX_HANDLE_INVALID);
        dev->refcount = 1;
        list_initialize(&dev->children);
        list_initialize(&dev->instances);

        newios->ph.handle = hin[0];
        newios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
        newios->ph.func = dh_handle_dc_rpc;
        if ((r = port_wait(&dh_port, &newios->ph)) < 0) {
            free(newios->dev);
            free(newios);
            break;
        }
        log(RPC_IN, "devhost[%s] created '%s' ios=%p\n", path, name, newios);
        return ZX_OK;

    case DC_OP_CREATE_DEVICE: {
        // 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[%s] create device drv='%s' args='%s'\n", path, name, args);

        // hin: rpc, vmo, optional-rsrc
        if (hcount == 2) {
            hin[2] = ZX_HANDLE_INVALID;
        } else if (hcount != 3) {
            r = ZX_ERR_INVALID_ARGS;
            break;
        }
        iostate_t* newios = calloc(1, sizeof(iostate_t));
        if (newios == NULL) {
            r = ZX_ERR_NO_MEMORY;
            break;
        }

        // named driver -- ask it to create the device
        zx_driver_t* drv;
        if ((r = dh_find_driver(name, hin[1], &drv)) < 0) {
            free(newios);
            log(ERROR, "devhost[%s] driver load failed: %d\n", path, r);
            break;
        }
        if (drv->ops->create) {
            // magic cookie for device create handshake
            zx_device_t parent = {
                .name = "device_create dummy",
                .owner = drv,
            };
            device_create_setup(&parent);
            if ((r = drv->ops->create(drv->ctx, &parent, "shadow", args, hin[2])) < 0) {
                log(ERROR, "devhost[%s] driver create() failed: %d\n", path, r);
                device_create_setup(NULL);
                break;
            }
            if ((newios->dev = device_create_setup(NULL)) == NULL) {
                log(ERROR, "devhost[%s] driver create() failed to create a device!", path);
                r = ZX_ERR_BAD_STATE;
                break;
            }
        } else {
            log(ERROR, "devhost[%s] driver create() not supported\n", path);
            r = ZX_ERR_NOT_SUPPORTED;
            break;
        }
        //TODO: inform devcoord

        newios->dev->rpc = hin[0];
        newios->ph.handle = hin[0];
        newios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
        newios->ph.func = dh_handle_dc_rpc;
        if ((r = port_wait(&dh_port, &newios->ph)) < 0) {
            free(newios);
            break;
        }
        log(RPC_IN, "devhost[%s] created '%s' ios=%p\n", path, name, newios);
        return ZX_OK;
    }

    case DC_OP_BIND_DRIVER:
        if (hcount != 1) {
            r = ZX_ERR_INVALID_ARGS;
            break;
        }
        //TODO: api lock integration
        log(RPC_IN, "devhost[%s] bind driver '%s'\n", path, name);
        zx_driver_t* drv;
        if (ios->dev->flags & DEV_FLAG_DEAD) {
            log(ERROR, "devhost[%s] bind to removed device disallowed\n", path);
            r = ZX_ERR_IO_NOT_PRESENT;
        } else if ((r = dh_find_driver(name, hin[0], &drv)) < 0) {
            log(ERROR, "devhost[%s] driver load failed: %d\n", path, r);
        } else {
            void* cookie = NULL;
            if (drv->ops->bind) {
                r = drv->ops->bind(drv->ctx, ios->dev, &cookie);
            } else {
                r = ZX_ERR_NOT_SUPPORTED;
            }
            if (r < 0) {
                log(ERROR, "devhost[%s] bind driver '%s' failed: %d\n", path, name, r);
            } else {
                //TODO: Best behaviour for multibind? maybe retire "owner"?
                //      For now this is extermely rare, so we mostly can ignore
                //      it.
                if (drv->ops->unbind || cookie) {
                    log(INFO, "devhost[%s] driver '%s' unbind=%p, cookie=%p\n",
                        path, name, drv->ops->unbind, cookie);

                    DM_LOCK();
                    if (ios->dev->owner) {
                        log(ERROR, "devhost[%s] driver '%s' device already owned!\n", path, name);
                    } else {
                        ios->dev->owner = drv;
                        ios->dev->owner_cookie = cookie;
                        ios->dev->refcount++;
                    }
                    DM_UNLOCK();
                }
            }
        }
        dc_msg_t reply = {
            .txid = 0,
            .op = DC_OP_STATUS,
            .status = r,
        };
        zx_channel_write(h, 0, &reply, sizeof(reply), NULL, 0);
        return ZX_OK;

    default:
        log(ERROR, "devhost[%s] invalid rpc op %08x\n", path, msg.op);
        r = ZX_ERR_NOT_SUPPORTED;
    }

fail:
    while (hcount > 0) {
        zx_handle_close(hin[--hcount]);
    }
    return r;
}

// handles devcoordinator rpc
static zx_status_t dh_handle_dc_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
    iostate_t* ios = ios_from_ph(ph);

    if (evt != 0) {
        // we send an event to request the destruction
        // of an iostate, to ensure that's the *last*
        // packet about the iostate that we get
        free(ios);
        return ZX_ERR_STOP;
    }
    if (ios->dead) {
        // ports does not let us cancel packets that are
        // alread in the queue, so the dead flag enables us
        // to ignore them
        return ZX_ERR_STOP;
    }
    if (signals & ZX_CHANNEL_READABLE) {
        zx_status_t r = dh_handle_rpc_read(ph->handle, ios);
        if (r != ZX_OK) {
            log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%d. fatal.\n", ios, r);
            exit(0);
        }
        return r;
    }
    if (signals & ZX_CHANNEL_PEER_CLOSED) {
        log(ERROR, "devhost: devmgr disconnected! fatal. (ios=%p)\n", ios);
        exit(0);
    }
    log(ERROR, "devhost: no work? %08x\n", signals);
    return ZX_OK;
}

// handles remoteio rpc
static zx_status_t dh_handle_rio_rpc(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
    iostate_t* ios = ios_from_ph(ph);

    zx_status_t r;
    zxrio_msg_t msg;
    if (signals & ZX_CHANNEL_READABLE) {
        if ((r = zxrio_handle_rpc(ph->handle, &msg, devhost_rio_handler, ios)) == ZX_OK) {
            return ZX_OK;
        }
    } else if (signals & ZX_CHANNEL_PEER_CLOSED) {
        zxrio_handle_close(devhost_rio_handler, ios);
        r = ZX_ERR_STOP;
    } else {
        printf("dh_handle_rio_rpc: invalid signals %x\n", signals);
        exit(0);
    }

    // We arrive here if handle_rpc 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 (ZX_ERR_STOP).  In all cases, the ios's reference to
    // the device was released, and will no longer be used, so we will free
    // it before returning.
    zx_handle_close(ios->ph.handle);
    free(ios);
    return r;
}

#define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))

static zx_handle_t devhost_log_handle;

static ssize_t _devhost_log_write(uint32_t flags, const void* _data, size_t len) {
    static thread_local struct {
        uint32_t next;
        zx_handle_t handle;
        char data[LOGBUF_MAX];
    }* ctx = NULL;

    if (ctx == NULL) {
        if ((ctx = calloc(1, sizeof(*ctx))) == NULL) {
            return len;
        }
        ctx->handle = devhost_log_handle;
    }

    const char* data = _data;
    size_t r = len;

    while (len-- > 0) {
        char c = *data++;
        if (c == '\n') {
            if (ctx->next) {
flush_ctx:
                zx_log_write(ctx->handle, ctx->next, ctx->data, flags);
                ctx->next = 0;
            }
            continue;
        }
        if (c < ' ') {
            continue;
        }
        ctx->data[ctx->next++] = c;
        if (ctx->next == LOGBUF_MAX) {
            goto flush_ctx;
        }
    }
    return r;
}

__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);

    if (r > (int)sizeof(buffer)) {
        r = sizeof(buffer);
    }

    _devhost_log_write(flags, buffer, r);
}

static ssize_t devhost_log_write(void* cookie, const void* data, size_t len) {
    return _devhost_log_write(0, data, len);
}

static void devhost_io_init(void) {
    if (zx_log_create(0, &devhost_log_handle) < 0) {
        return;
    }
    fdio_t* io;
    if ((io = fdio_output_create(devhost_log_write, NULL)) == NULL) {
        return;
    }
    close(1);
    fdio_bind_to_fd(io, 1, 0);
    dup2(1, 2);
}

// Send message to devcoordinator asking to add child device to
// parent device.  Called under devhost api lock.
zx_status_t devhost_add(zx_device_t* parent, zx_device_t* child,
                        const char* businfo, zx_handle_t resource,
                        const zx_device_prop_t* props, uint32_t prop_count) {
    char buffer[512];
    const char* path = mkdevpath(parent, buffer, sizeof(buffer));
    log(RPC_OUT, "devhost[%s] add '%s'\n", path, child->name);

    const char* libname = child->driver->libname;
    size_t namelen = strlen(libname) + strlen(child->name) + 2;
    char name[namelen];
    snprintf(name, namelen, "%s,%s", libname, child->name);

    zx_status_t r;
    iostate_t* ios = calloc(1, sizeof(*ios));
    if (ios == NULL) {
        r = ZX_ERR_NO_MEMORY;
        goto fail;
    }

    dc_msg_t msg;
    uint32_t msglen;
    if ((r = dc_msg_pack(&msg, &msglen,
                         props, prop_count * sizeof(zx_device_prop_t),
                         name, businfo)) < 0) {
        goto fail;
    }
    msg.op = DC_OP_ADD_DEVICE;
    msg.protocol_id = child->protocol_id;

    // handles: remote endpoint, resource (optional)
    zx_handle_t hrpc, handle[2];
    if ((r = zx_channel_create(0, &hrpc, handle)) < 0) {
        goto fail;
    }
    handle[1] = resource;

    dc_status_t rsp;
    if ((r = dc_msg_rpc(parent->rpc, &msg, msglen,
                        handle, (resource != ZX_HANDLE_INVALID) ? 2 : 1,
                        &rsp, sizeof(rsp))) < 0) {
        log(ERROR, "devhost[%s] add '%s': rpc failed: %d\n", path, child->name, r);
    } else {
        ios->dev = child;
        ios->ph.handle = hrpc;
        ios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
        ios->ph.func = dh_handle_dc_rpc;
        if ((r = port_wait(&dh_port, &ios->ph)) == ZX_OK) {
            child->rpc = hrpc;
            child->ios = ios;
            return ZX_OK;
        }

    }
    zx_handle_close(hrpc);
    free(ios);
    return r;

fail:
    if (resource != ZX_HANDLE_INVALID) {
        zx_handle_close(resource);
    }
    free(ios);
    return r;
}

static zx_status_t devhost_rpc(zx_device_t* dev, uint32_t op,
                               const char* args, const char* opname,
                               dc_status_t* rsp, size_t rsp_len) {
    char buffer[512];
    const char* path = mkdevpath(dev, buffer, sizeof(buffer));
    log(RPC_OUT, "devhost[%s] %s args='%s'\n", path, opname, args ? args : "");
    dc_msg_t msg;
    uint32_t msglen;
    zx_status_t r;
    if ((r = dc_msg_pack(&msg, &msglen, NULL, 0, NULL, args)) < 0) {
        return r;
    }
    msg.op = op;
    msg.protocol_id = 0;
    if ((r = dc_msg_rpc(dev->rpc, &msg, msglen, NULL, 0, rsp, rsp_len)) < 0) {
        log(ERROR, "devhost: rpc:%s failed: %d\n", opname, r);
    }
    return r;
}

// Send message to devcoordinator informing it that this device
// is being removed.  Called under devhost api lock.
zx_status_t devhost_remove(zx_device_t* dev) {
    devhost_iostate_t* ios = dev->ios;
    if (ios == NULL) {
        log(ERROR, "removing device %p, ios is NULL\n", dev);
        return ZX_ERR_INTERNAL;
    }

    log(DEVLC, "removing device %p, ios %p\n", dev, ios);

    // Make this iostate inactive (stop accepting RPCs for it)
    //
    // If the remove is happening on a different thread than
    // the rpc handler, the handler might observe the peer
    // before devhost_simple_rpc() returns.
    ios->dev = NULL;
    ios->dead = true;

    // ensure we get no further events
    //TODO: this does not work yet, ports limitation
    port_cancel(&dh_port, &ios->ph);
    ios->ph.handle = ZX_HANDLE_INVALID;
    dev->ios = NULL;

    dc_status_t rsp;
    devhost_rpc(dev, DC_OP_REMOVE_DEVICE, NULL, "remove-device", &rsp, sizeof(rsp));

    // shut down our rpc channel
    zx_handle_close(dev->rpc);
    dev->rpc = ZX_HANDLE_INVALID;

    // queue an event to destroy the iostate
    port_queue(&dh_port, &ios->ph, 1);

    return ZX_OK;
}

zx_status_t devhost_get_topo_path(zx_device_t* dev, char* path, size_t max, size_t* actual) {
    struct {
        dc_status_t rsp;
        char path[DC_PATH_MAX];
    } reply;
    zx_status_t r;
    if ((r = devhost_rpc(dev, DC_OP_GET_TOPO_PATH, NULL, "get-topo-path",
                         &reply.rsp, sizeof(reply))) < 0) {
        return r;
    }
    reply.path[DC_PATH_MAX - 1] = 0;
    size_t len = strlen(reply.path) + 1;
    if (len > max) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    }

    memcpy(path, reply.path, len);
    *actual = len;
    return ZX_OK;
}

zx_status_t devhost_device_bind(zx_device_t* dev, const char* drv_libname) {
    dc_status_t rsp;
    return devhost_rpc(dev, DC_OP_BIND_DEVICE, drv_libname, "bind-device", &rsp, sizeof(rsp));
}


zx_handle_t root_resource_handle;


zx_status_t devhost_start_iostate(devhost_iostate_t* ios, zx_handle_t h) {
    ios->ph.handle = h;
    ios->ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    ios->ph.func = dh_handle_rio_rpc;
    return port_wait(&dh_port, &ios->ph);
}

__EXPORT int device_host_main(int argc, char** argv) {
    devhost_io_init();

    log(TRACE, "devhost: main()\n");

    root_ios.ph.handle = zx_get_startup_handle(PA_HND(PA_USER0, 0));
    if (root_ios.ph.handle == ZX_HANDLE_INVALID) {
        log(ERROR, "devhost: rpc handle invalid\n");
        return -1;
    }

    root_resource_handle = zx_get_startup_handle(PA_HND(PA_RESOURCE, 0));
    if (root_resource_handle == ZX_HANDLE_INVALID) {
        log(ERROR, "devhost: no root resource handle!\n");
    }

    zx_status_t r;
    if ((r = port_init(&dh_port)) < 0) {
        log(ERROR, "devhost: could not create port: %d\n", r);
        return -1;
    }
    if ((r = port_wait(&dh_port, &root_ios.ph)) < 0) {
        log(ERROR, "devhost: could not watch rpc channel: %d\n", r);
        return -1;
    }

    r = port_dispatch(&dh_port, ZX_TIME_INFINITE, false);
    log(ERROR, "devhost: port dispatch finished: %d\n", r);

    return 0;
}
