// 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 <string.h>
#include <port/port.h>
#include <fbl/unique_fd.h>
#include <fcntl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/fdio/io.h>
#include <lib/fidl/coding.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>
#include <zircon/device/display-controller.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include "fuchsia/hardware/display/c/fidl.h"
#include "vc.h"

static constexpr const char* kDisplayControllerDir = "/dev/class/display-controller";

static int dc_dir_fd;
static int dc_fd;

// At any point, |dc_ph| will either be waiting on the display controller device directory
// for a display controller instance or it will be waiting on a display controller interface
// for messages.
static port_handler_t dc_ph;

typedef struct display_info {
    uint64_t id;
    uint32_t width;
    uint32_t height;
    uint32_t stride;
    zx_pixel_format_t format;

    uint64_t image_id;
    uint64_t layer_id;

    struct list_node node;
} display_info_t;

static struct list_node display_list = LIST_INITIAL_VALUE(display_list);

static bool displays_bound = false;
// Owned by vc_gfx, only valid when displays_bound is true
static zx_handle_t image_vmo = ZX_HANDLE_INVALID;
static fuchsia_hardware_display_ImageConfig image_config;

// remember whether the virtual console controls the display
bool g_vc_owns_display = false;

static void vc_find_display_controller();

static zx_status_t vc_set_mode(uint8_t mode) {
    fuchsia_hardware_display_ControllerSetVirtconModeRequest request;
    request.hdr.ordinal = fuchsia_hardware_display_ControllerSetVirtconModeOrdinal;
    request.mode = mode;

    return zx_channel_write(dc_ph.handle, 0, &request, sizeof(request), nullptr, 0);
}

void vc_toggle_framebuffer() {
    if (list_is_empty(&display_list)) {
        return;
    }

    zx_status_t status =
        vc_set_mode(!g_vc_owns_display ? fuchsia_hardware_display_VirtconMode_FORCED
                                       : fuchsia_hardware_display_VirtconMode_FALLBACK);
    if (status != ZX_OK) {
        printf("vc: Failed to toggle ownership %d\n", status);
    }
}

static zx_status_t decode_message(void* bytes, uint32_t num_bytes) {
    fidl_message_header_t* header = (fidl_message_header_t*) bytes;

    if (num_bytes < sizeof(fidl_message_header_t)) {
        printf("vc: Unexpected short message (size=%d)\n", num_bytes);
        return ZX_ERR_INTERNAL;
    }
    zx_status_t res;

    const fidl_type_t* table = nullptr;
    if (header->ordinal == fuchsia_hardware_display_ControllerDisplaysChangedOrdinal) {
        table = &fuchsia_hardware_display_ControllerDisplaysChangedEventTable;
    } else if (header->ordinal == fuchsia_hardware_display_ControllerClientOwnershipChangeOrdinal) {
        table = &fuchsia_hardware_display_ControllerClientOwnershipChangeEventTable;
    }
    if (table != nullptr) {
        const char* err;
        if ((res = fidl_decode(table, bytes, num_bytes, nullptr, 0, &err)) != ZX_OK) {
            printf("vc: Error decoding message %d: %s\n", header->ordinal, err);
        }
    } else {
        printf("vc: Error unknown ordinal %d\n", header->ordinal);
        res = ZX_ERR_NOT_SUPPORTED;
    }
    return res;
}

static void
handle_ownership_change(fuchsia_hardware_display_ControllerClientOwnershipChangeEvent* evt) {
    g_vc_owns_display = evt->has_ownership;

    // If we've gained it, repaint
    if (g_vc_owns_display && g_active_vc) {
        vc_full_repaint(g_active_vc);
        vc_render(g_active_vc);
    }
}

static zx_status_t create_layer(uint64_t display_id, uint64_t* layer_id) {
    fuchsia_hardware_display_ControllerCreateLayerRequest create_layer_msg;
    create_layer_msg.hdr.ordinal = fuchsia_hardware_display_ControllerCreateLayerOrdinal;

    fuchsia_hardware_display_ControllerCreateLayerResponse create_layer_rsp;
    zx_channel_call_args_t call_args = {};
    call_args.wr_bytes = &create_layer_msg;
    call_args.rd_bytes = &create_layer_rsp;
    call_args.wr_num_bytes = sizeof(create_layer_msg);
    call_args.rd_num_bytes = sizeof(create_layer_rsp);
    uint32_t actual_bytes, actual_handles;
    zx_status_t status;
    if ((status = zx_channel_call(dc_ph.handle, 0, ZX_TIME_INFINITE, &call_args,
                                  &actual_bytes, &actual_handles)) != ZX_OK) {
        printf("vc: Create layer call failed: %d (%s)\n", status, zx_status_get_string(status));
        return status;
    }
    if (create_layer_rsp.res != ZX_OK) {
        printf("vc: Failed to create layer %d\n", create_layer_rsp.res);
        return create_layer_rsp.res;
    }

    *layer_id = create_layer_rsp.layer_id;
    return ZX_OK;
}



static void destroy_layer(uint64_t layer_id) {
    fuchsia_hardware_display_ControllerDestroyLayerRequest destroy_msg;
    destroy_msg.hdr.ordinal = fuchsia_hardware_display_ControllerDestroyLayerOrdinal;
    destroy_msg.layer_id = layer_id;

    if (zx_channel_write(dc_ph.handle, 0, &destroy_msg, sizeof(destroy_msg), nullptr, 0) != ZX_OK) {
        printf("vc: Failed to destroy layer\n");
    }
}

static void release_image(uint64_t image_id) {
    fuchsia_hardware_display_ControllerReleaseImageRequest release_msg;
    release_msg.hdr.ordinal = fuchsia_hardware_display_ControllerReleaseImageOrdinal;
    release_msg.image_id = image_id;

    if (zx_channel_write(dc_ph.handle, 0, &release_msg, sizeof(release_msg), nullptr, 0)) {
        printf("vc: Failed to release image\n");
    }
}

static zx_status_t handle_display_added(fuchsia_hardware_display_Info* info,
                                        fuchsia_hardware_display_Mode* mode, int32_t pixel_format) {
    fuchsia_hardware_display_ControllerComputeLinearImageStrideRequest stride_msg;
    stride_msg.hdr.ordinal = fuchsia_hardware_display_ControllerComputeLinearImageStrideOrdinal;
    stride_msg.width = mode->horizontal_resolution;
    stride_msg.pixel_format = pixel_format;

    fuchsia_hardware_display_ControllerComputeLinearImageStrideResponse stride_rsp;
    zx_channel_call_args_t stride_call = {};
    stride_call.wr_bytes = &stride_msg;
    stride_call.rd_bytes = &stride_rsp;
    stride_call.wr_num_bytes = sizeof(stride_msg);
    stride_call.rd_num_bytes = sizeof(stride_rsp);
    uint32_t actual_bytes, actual_handles;
    zx_status_t status;
    if ((status = zx_channel_call(dc_ph.handle, 0, ZX_TIME_INFINITE, &stride_call,
                                  &actual_bytes, &actual_handles)) != ZX_OK) {
        printf("vc: Failed to compute fb stride: %d (%s)\n", status,
               zx_status_get_string(status));
        return status;
    }

    if (stride_rsp.stride < mode->horizontal_resolution) {
        printf("vc: Got bad stride\n");
        return ZX_ERR_INVALID_ARGS;
    }

    display_info_t* display_info =
            reinterpret_cast<display_info_t*>(malloc(sizeof(display_info_t)));
    if (!display_info) {
        printf("vc: failed to alloc display info\n");
        return ZX_ERR_NO_MEMORY;
    }

    if ((status = create_layer(info->id, &display_info->layer_id)) != ZX_OK) {
        printf("vc: failed to create display layer\n");
        free(display_info);
        return status;
    }

    display_info->id = info->id;
    display_info->width = mode->horizontal_resolution;
    display_info->height = mode->vertical_resolution;
    display_info->stride = stride_rsp.stride;
    display_info->format = reinterpret_cast<int32_t*>(info->pixel_format.data)[0];
    display_info->image_id = 0;

    list_add_tail(&display_list, &display_info->node);

    return ZX_OK;
}

static void handle_display_removed(uint64_t id) {
    if (list_is_empty(&display_list)) {
        printf("vc: No displays when removing %ld\n", id);
        return;
    }

    bool was_primary = list_peek_head_type(&display_list, display_info_t, node)->id == id;
    display_info_t* info = nullptr;
    display_info_t* temp = nullptr;
    list_for_every_entry_safe(&display_list, info, temp, display_info_t, node) {
        if (info->id == id) {
            destroy_layer(info->layer_id);
            release_image(info->image_id);

            list_delete(&info->node);
            free(info);
        } else if (was_primary) {
            release_image(info->image_id);
            info->image_id = 0;
        }
    }

    if (was_primary) {
        set_log_listener_active(false);
        vc_free_gfx();
        displays_bound = false;
    }
}

static zx_status_t allocate_vmo(uint32_t size, zx_handle_t* vmo_out) {
    fuchsia_hardware_display_ControllerAllocateVmoRequest alloc_msg;
    alloc_msg.hdr.ordinal = fuchsia_hardware_display_ControllerAllocateVmoOrdinal;
    alloc_msg.size = size;

    fuchsia_hardware_display_ControllerAllocateVmoResponse alloc_rsp;
    zx_channel_call_args_t call_args = {};
    call_args.wr_bytes = &alloc_msg;
    call_args.rd_bytes = &alloc_rsp;
    call_args.rd_handles = vmo_out;
    call_args.wr_num_bytes = sizeof(alloc_msg);
    call_args.rd_num_bytes = sizeof(alloc_rsp);
    call_args.rd_num_handles = 1;
    uint32_t actual_bytes, actual_handles;
    zx_status_t status;
    if ((status = zx_channel_call(dc_ph.handle, 0, ZX_TIME_INFINITE, &call_args,
                                  &actual_bytes, &actual_handles)) != ZX_OK) {
        printf("vc: Failed to alloc vmo: %d (%s)\n", status, zx_status_get_string(status));
        return status;
    }
    if (alloc_rsp.res != ZX_OK) {
        printf("vc: Failed to alloc vmo %d\n", alloc_rsp.res);
        return alloc_rsp.res;
    }
    return actual_handles == 1 ? ZX_OK : ZX_ERR_INTERNAL;
}

static zx_status_t import_vmo(zx_handle_t vmo, fuchsia_hardware_display_ImageConfig* config,
                              uint64_t* id) {
    zx_handle_t vmo_dup;
    zx_status_t status;
    if ((status = zx_handle_duplicate(vmo, ZX_RIGHT_SAME_RIGHTS, &vmo_dup)) != ZX_OK) {
        printf("vc: Failed to dup fb handle %d\n", status);
        return status;
    }

    fuchsia_hardware_display_ControllerImportVmoImageRequest import_msg = {};
    import_msg.hdr.ordinal = fuchsia_hardware_display_ControllerImportVmoImageOrdinal;
    import_msg.image_config = *config;
    import_msg.vmo = FIDL_HANDLE_PRESENT;
    import_msg.offset = 0;

    fuchsia_hardware_display_ControllerImportVmoImageResponse import_rsp;
    zx_channel_call_args_t call_args = {};
    call_args.wr_bytes = &import_msg;
    call_args.wr_handles = &vmo_dup;
    call_args.rd_bytes = &import_rsp;
    call_args.wr_num_bytes = sizeof(import_msg);
    call_args.wr_num_handles = 1;
    call_args.rd_num_bytes = sizeof(import_rsp);
    uint32_t actual_bytes, actual_handles;
    if ((status = zx_channel_call(dc_ph.handle, 0, ZX_TIME_INFINITE, &call_args,
                                  &actual_bytes, &actual_handles)) != ZX_OK) {
        printf("vc: Failed to import vmo call %d (%s)\n", status, zx_status_get_string(status));
        return status;
    }

    if (import_rsp.res != ZX_OK) {
        printf("vc: Failed to import vmo %d\n", import_rsp.res);
        return import_rsp.res;
    }

    *id = import_rsp.image_id;
    return ZX_OK;
}

static zx_status_t set_display_layer(uint64_t display_id, uint64_t layer_id) {
    zx_status_t status;
    // Put the layer on the display
    uint8_t fidl_bytes[sizeof(fuchsia_hardware_display_ControllerSetDisplayLayersRequest) +
                       FIDL_ALIGN(sizeof(uint64_t))];
    auto set_display_layer_request =
        reinterpret_cast<fuchsia_hardware_display_ControllerSetDisplayLayersRequest*>(fidl_bytes);

    set_display_layer_request->hdr.ordinal =
        fuchsia_hardware_display_ControllerSetDisplayLayersOrdinal;
    set_display_layer_request->display_id = display_id;
    set_display_layer_request->layer_ids.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);

    uint32_t size;
    if (layer_id) {
        set_display_layer_request->layer_ids.count = 1;
        *reinterpret_cast<uint64_t*>(set_display_layer_request + 1) = layer_id;
        size = sizeof(fidl_bytes);
    } else {
        set_display_layer_request->layer_ids.count = 0;
        size = sizeof(fuchsia_hardware_display_ControllerSetDisplayLayersRequest);
    }
    if ((status = zx_channel_write(dc_ph.handle, 0,
                                   fidl_bytes, size, nullptr, 0)) != ZX_OK) {
        printf("vc: Failed to set display layers %d\n", status);
        return status;
    }

    return ZX_OK;
}

static zx_status_t configure_layer(display_info_t* display, uint64_t layer_id, uint64_t image_id,
                                   fuchsia_hardware_display_ImageConfig* config) {
    zx_status_t status;
    fuchsia_hardware_display_ControllerSetLayerPrimaryConfigRequest layer_cfg_msg;
    layer_cfg_msg.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerPrimaryConfigOrdinal;
    layer_cfg_msg.layer_id = layer_id;
    layer_cfg_msg.image_config = *config;
    if ((status = zx_channel_write(dc_ph.handle, 0, &layer_cfg_msg,
                                   sizeof(layer_cfg_msg), nullptr, 0)) != ZX_OK) {
        printf("vc: Failed to set layer config %d\n", status);
        return status;
    }

    fuchsia_hardware_display_ControllerSetLayerPrimaryPositionRequest layer_pos_msg = {};
    layer_pos_msg.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerPrimaryPositionOrdinal;
    layer_pos_msg.layer_id = layer_id;
    layer_pos_msg.transform = fuchsia_hardware_display_Transform_IDENTITY;
    layer_pos_msg.src_frame.width = config->width;
    layer_pos_msg.src_frame.height = config->height;
    layer_pos_msg.dest_frame.width = display->width;
    layer_pos_msg.dest_frame.height = display->height;
    if ((status = zx_channel_write(dc_ph.handle, 0, &layer_pos_msg,
                                   sizeof(layer_pos_msg), nullptr, 0)) != ZX_OK) {
        printf("vc: Failed to set layer position %d\n", status);
        return status;
    }

    fuchsia_hardware_display_ControllerSetLayerImageRequest set_msg;
    set_msg.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerImageOrdinal;
    set_msg.layer_id = layer_id;
    set_msg.image_id = image_id;
    if ((status = zx_channel_write(dc_ph.handle, 0,
                                   &set_msg, sizeof(set_msg), nullptr, 0)) != ZX_OK) {
        printf("vc: Failed to set image %d\n", status);
        return status;
    }
    return ZX_OK;
}

static zx_status_t apply_configuration() {
    // Validate and then apply the new configuration
    zx_status_t status;
    fuchsia_hardware_display_ControllerCheckConfigRequest check_msg;
    uint8_t check_rsp_bytes[ZX_CHANNEL_MAX_MSG_BYTES];
    auto check_rsp =
        reinterpret_cast<fuchsia_hardware_display_ControllerCheckConfigResponse*>(check_rsp_bytes);
    check_msg.discard = false;
    check_msg.hdr.ordinal = fuchsia_hardware_display_ControllerCheckConfigOrdinal;
    zx_channel_call_args_t call_args = {};
    call_args.wr_bytes = &check_msg;
    call_args.rd_bytes = check_rsp;
    call_args.wr_num_bytes = sizeof(check_msg);
    call_args.rd_num_bytes = sizeof(check_rsp_bytes);
    uint32_t actual_bytes, actual_handles;
    if ((status = zx_channel_call(dc_ph.handle, 0, ZX_TIME_INFINITE, &call_args,
                                  &actual_bytes, &actual_handles)) != ZX_OK) {
        printf("vc: Failed to validate display config: %d (%s)\n", status,
               zx_status_get_string(status));
        return status;
    }

    if (check_rsp->res != fuchsia_hardware_display_ConfigResult_OK) {
        printf("vc: Config not valid %d\n", check_rsp->res);
        return ZX_ERR_INTERNAL;
    }

    fuchsia_hardware_display_ControllerApplyConfigRequest apply_msg;
    apply_msg.hdr.ordinal = fuchsia_hardware_display_ControllerApplyConfigOrdinal;
    if ((status = zx_channel_write(dc_ph.handle, 0,
                                   &apply_msg, sizeof(apply_msg), nullptr, 0)) != ZX_OK) {
        printf("vc: Applying config failed %d\n", status);
        return status;
    }

    return ZX_OK;
}

static zx_status_t rebind_display(bool use_all) {
    // Arbitrarily pick the oldest display as the primary dispay
    display_info* primary = list_peek_head_type(&display_list, display_info, node);
    if (primary == nullptr) {
        printf("vc: No display to bind to\n");
        return ZX_ERR_NO_RESOURCES;
    }

    zx_status_t status;
    if (!displays_bound) {
        uint32_t size = primary->stride * primary->height * ZX_PIXEL_FORMAT_BYTES(primary->format);
        if ((status = allocate_vmo(size, &image_vmo)) != ZX_OK) {
            return ZX_ERR_NO_MEMORY;
        }
        image_config.height = primary->height;
        image_config.width = primary->width;
        image_config.pixel_format = primary->format;
        image_config.type = IMAGE_TYPE_SIMPLE;

        if ((status = vc_init_gfx(image_vmo, primary->width, primary->height,
                                  primary->format, primary->stride)) != ZX_OK) {
            printf("vc: failed to initialize graphics for new display %d\n", status);
            zx_handle_close(image_vmo);
            return status;
        }
    }

    display_info_t* info = nullptr;
    list_for_every_entry(&display_list, info, display_info_t, node) {
        if (!use_all && info != primary) {
            // If we're not showing anything on this display, remove its layer
            if ((status = set_display_layer(info->id, 0)) != ZX_OK) {
                break;
            }
        } else if (info->image_id == 0) {
            // If we want to display something but aren't, configure the display
            if ((status = import_vmo(image_vmo, &image_config, &info->image_id)) != ZX_OK) {
                break;
            }

            if ((status = set_display_layer(info->id, info->layer_id)) != ZX_OK) {
                break;
            }

            if ((status = configure_layer(info, info->layer_id,
                                          info->image_id, &image_config) != ZX_OK)) {
                break;
            }
        }
    }

    if (status == ZX_OK && apply_configuration() == ZX_OK) {
        // Only listen for logs when we have somewhere to print them. Also,
        // use a repeating wait so that we don't add/remove observers for each
        // log message (which is helpful when tracing the addition/removal of
        // observers).
        set_log_listener_active(true);
        vc_show_active();

        printf("vc: Successfully attached to display %ld\n", primary->id);
        displays_bound = true;
        return ZX_OK;
    } else {
        display_info_t* info = nullptr;
        list_for_every_entry(&display_list, info, display_info_t, node) {
            if (info->image_id) {
                release_image(info->image_id);
                info->image_id = 0;
            }
        }

        vc_free_gfx();

        if (use_all) {
            return rebind_display(false);
        } else {
            printf("vc: Failed to bind to displays\n");
            return ZX_ERR_INTERNAL;
        }
    }
}

static zx_status_t
handle_display_changed(fuchsia_hardware_display_ControllerDisplaysChangedEvent* evt) {
    for (unsigned i = 0; i < evt->added.count; i++) {
        fuchsia_hardware_display_Info* info =
            reinterpret_cast<fuchsia_hardware_display_Info*>(evt->added.data) + i;
        fuchsia_hardware_display_Mode* mode =
            reinterpret_cast<fuchsia_hardware_display_Mode*>(info->modes.data);
        int32_t pixel_format = reinterpret_cast<int32_t*>(info->pixel_format.data)[0];
        zx_status_t status = handle_display_added(info, mode, pixel_format);
        if (status != ZX_OK) {
            return status;
        }
    }

    for (unsigned i = 0; i < evt->removed.count; i++) {
        handle_display_removed(reinterpret_cast<int32_t*>(evt->removed.data)[i]);
    }

    return rebind_display(true);
}

static zx_status_t dc_callback_handler(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
    if (signals & ZX_CHANNEL_PEER_CLOSED) {
        printf("vc: Displays lost\n");
        while (!list_is_empty(&display_list)) {
            handle_display_removed(list_peek_head_type(&display_list, display_info_t, node)->id);
        }

        close(dc_fd);
        zx_handle_close(dc_ph.handle);

        vc_find_display_controller();

        return ZX_ERR_STOP;
    }
    ZX_DEBUG_ASSERT(signals & ZX_CHANNEL_READABLE);

    zx_status_t status;
    uint32_t actual_bytes, actual_handles;
    uint8_t fidl_buffer[ZX_CHANNEL_MAX_MSG_BYTES];
    if ((status = zx_channel_read(dc_ph.handle, 0,
                                  fidl_buffer, nullptr, ZX_CHANNEL_MAX_MSG_BYTES, 0,
                                  &actual_bytes, &actual_handles)) != ZX_OK) {
        printf("vc: Error reading display message %d\n", status);
        return ZX_OK;
    }

    if (decode_message(fidl_buffer, actual_bytes) != ZX_OK) {
        return ZX_OK;
    }

    fidl_message_header_t* header = (fidl_message_header_t*) fidl_buffer;
    switch (header->ordinal) {
    case fuchsia_hardware_display_ControllerDisplaysChangedOrdinal: {
        handle_display_changed(
            reinterpret_cast<fuchsia_hardware_display_ControllerDisplaysChangedEvent*>(
                fidl_buffer));
        break;
    }
    case fuchsia_hardware_display_ControllerClientOwnershipChangeOrdinal: {
        auto evt = reinterpret_cast<fuchsia_hardware_display_ControllerClientOwnershipChangeEvent*>(
            fidl_buffer);
        handle_ownership_change(evt);
        break;
    }
    default:
        printf("vc: Unknown display callback message %d\n", header->ordinal);
        break;
    }

    return ZX_OK;
}

static zx_status_t vc_dc_event(uint32_t evt, const char* name) {
    if ((evt != fuchsia_io_WATCH_EVENT_EXISTING) && (evt != fuchsia_io_WATCH_EVENT_ADDED)) {
        return ZX_OK;
    }

    printf("vc: new display device %s/%s/virtcon\n", kDisplayControllerDir, name);

    char buf[64];
    snprintf(buf, 64, "%s/%s/virtcon", kDisplayControllerDir, name);
    fbl::unique_fd fd(open(buf, O_RDWR));
    if (!fd) {
        printf("vc: failed to open display controller device\n");
        return ZX_OK;
    }

    zx::channel dc_channel;
    if (ioctl_display_controller_get_handle(fd.get(), dc_channel.reset_and_get_address())
            != sizeof(zx_handle_t)) {
        printf("vc: failed to get display controller handle\n");
        return ZX_OK;
    }

    zx_handle_close(dc_ph.handle);
    dc_fd = fd.release();
    dc_ph.handle = dc_channel.release();

    zx_status_t status = vc_set_mode(getenv("virtcon.hide-on-boot") == nullptr
                                         ? fuchsia_hardware_display_VirtconMode_FALLBACK
                                         : fuchsia_hardware_display_VirtconMode_INACTIVE);
    if (status != ZX_OK) {
        printf("vc: Failed to set initial ownership %d\n", status);
        vc_find_display_controller();
        return ZX_ERR_STOP;
    }

    dc_ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    dc_ph.func = dc_callback_handler;
    if ((status = port_wait(&port, &dc_ph)) != ZX_OK) {
        printf("vc: Failed to set port waiter %d\n", status);
        vc_find_display_controller();
    }
    return ZX_ERR_STOP;
}

static zx_status_t vc_dc_dir_event_cb(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
    return handle_device_dir_event(ph, signals, vc_dc_event);
}

static void vc_find_display_controller() {
    zx::channel client, server;
    if (zx::channel::create(0, &client, &server) != ZX_OK) {
        printf("vc: Failed to create dc watcher channel\n");
        return;
    }

    fdio_t* fdio = fdio_unsafe_fd_to_io(dc_dir_fd);
    zx_status_t status;
    zx_status_t io_status = fuchsia_io_DirectoryWatch(fdio_unsafe_borrow_channel(fdio),
                                                      fuchsia_io_WATCH_MASK_ALL, 0,
                                                      server.release(),
                                                      &status);
    fdio_unsafe_release(fdio);

    if (io_status != ZX_OK || status != ZX_OK) {
        printf("vc: Failed to watch dc directory\n");
        return;
    }

    dc_ph.handle = client.release();
    dc_ph.waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    dc_ph.func = vc_dc_dir_event_cb;
    if (port_wait(&port, &dc_ph) != ZX_OK) {
        printf("vc: Failed to wait on dc directory\n");
    }
}

bool vc_display_init() {
    fbl::unique_fd fd(open(kDisplayControllerDir, O_DIRECTORY | O_RDONLY));
    if (!fd) {
        return false;
    }
    dc_dir_fd = fd.release();

    vc_find_display_controller();

    return true;
}
