blob: d472ca7726755d0330bf2a914fd429acbf32e93a [file] [log] [blame]
// Copyright 2022 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.
use crate::framebuffer::{DetectResult, DisplayInfo, Framebuffer};
use anyhow::Error;
use fidl::endpoints;
use fidl_fuchsia_hardware_display::{
CoordinatorEvent, CoordinatorMarker, CoordinatorSynchronousProxy, Info,
ProviderSynchronousProxy,
};
use fuchsia_zircon as zx;
use serde_json::json;
const DEVICE_PATH: &'static str = "/dev/class/display-coordinator/000";
fn convert_info(info: &Info) -> DisplayInfo {
DisplayInfo {
id: format!("[mfgr: '{}', model: '{}']", info.manufacturer_name, info.monitor_name),
width: info.modes[0].horizontal_resolution,
height: info.modes[0].vertical_resolution,
}
}
fn read_info() -> Result<DetectResult, Error> {
// Connect to the display coordinator.
let provider = {
let (client_end, server_end) = zx::Channel::create();
fuchsia_component::client::connect_channel_to_protocol_at_path(server_end, DEVICE_PATH)?;
ProviderSynchronousProxy::new(client_end)
};
let coordinator = {
let (dc_client, dc_server) = endpoints::create_endpoints::<CoordinatorMarker>();
provider.open_coordinator_for_primary(dc_server, zx::Time::INFINITE)?;
CoordinatorSynchronousProxy::new(dc_client.into_channel())
};
// Wait for the 'OnDisplaysChanged' event.
let displays = loop {
match coordinator.wait_for_event(zx::Time::INFINITE)? {
CoordinatorEvent::OnDisplaysChanged { added, .. } => break added,
_ => {}
}
};
Ok(DetectResult {
displays: displays.iter().map(convert_info).collect(),
details: json!(format!("{:#?}", displays)),
..Default::default()
})
}
fn read_info_from_display_coordinator() -> DetectResult {
read_info().unwrap_or_else(DetectResult::from_error)
}
pub struct ZirconFramebuffer;
impl Framebuffer for ZirconFramebuffer {
fn detect_displays(&self) -> DetectResult {
read_info_from_display_coordinator()
}
}