1// Copyright 2022 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.
45use fidl_fuchsia_hardware_display::ClientCompositionOp;
6use fidl_fuchsia_hardware_display_types::{ClientCompositionOpcode, ConfigResult};
78use futures::channel::mpsc;
9use thiserror::Error;
1011use crate::controller::VsyncEvent;
12use crate::types::{DisplayId, LayerId};
1314/// Library error type.
15#[derive(Error, Debug)]
16pub enum Error {
17/// Error encountered while connecting to a display-coordinator device via devfs.
18#[error("could not find a display-coordinator device")]
19DeviceNotFound,
2021/// No displays were reported by the display driver when expected.
22#[error("device did not enumerate initial displays")]
23NoDisplays,
2425/// A request handling task (such as one that owns a FIDL event stream that can only be
26 /// started once) was already been initiated before.
27#[error("a singleton task was already initiated")]
28AlreadyRequested,
2930/// Error while allocating shared sysmem buffers.
31#[error("sysmem buffer collection allocation failed, or invalid response from sysmem")]
32BuffersNotAllocated,
3334/// Error while establishing a connection to sysmem.
35#[error("error while setting up a sysmem connection")]
36SysmemConnection,
3738/// Ran out of free client-assigned identifiers.
39#[error("ran out of identifiers")]
40IdsExhausted,
4142/// Path to the device is invalid (e.g. containing invalid
43 /// characters).
44#[error("invalid device path")]
45DevicePathInvalid,
4647/// Wrapper for errors from FIDL bindings.
48#[error("FIDL error: {0}")]
49FidlError(#[from] fidl::Error),
5051/// Wrapper for system file I/O errors.
52#[error("OS I/O error: {0}")]
53IoError(#[from] std::io::Error),
5455/// Wrapper for errors from zircon syscalls.
56#[error("zircon error: {0}")]
57ZxError(#[from] zx::Status),
5859/// Wrapper for errors from FIDL device connections.
60#[error("Device connection error: {0}")]
61DeviceConnectionError(anyhow::Error),
6263/// Wrapper for errors from fuchsia-fs.
64#[error("filesystem error: {0}")]
65FsError(#[from] fuchsia_fs::node::OpenError),
6667/// Wrapper for errors from fuchsia-fs watcher creation.
68#[error("failed to create directory watcher: {0}")]
69WatcherCreateError(#[from] fuchsia_fs::directory::WatcherCreateError),
7071/// Wrapper for errors from the fuchsia-fs watcher stream.
72#[error("directory watcher stream produced error: {0}")]
73WatcherStreamError(#[from] fuchsia_fs::directory::WatcherStreamError),
7475/// Error that occurred while notifying vsync event listeners over an in-process async channel.
76#[error("failed to notify vsync: {0}")]
77CouldNotSendVsyncEvent(#[from] mpsc::TrySendError<VsyncEvent>),
7879/// UTF-8 validation error.
80#[error("invalid UTF-8 string")]
81InvalidUtf8(#[from] std::str::Utf8Error),
82}
8384/// Library Result type alias.
85pub type Result<T> = std::result::Result<T, Error>;
8687/// An error generated by `fuchsia.hardware.display.Controller.CheckConfig`.
88#[derive(Debug, Error)]
89pub enum ConfigError {
90/// Failure due to an invalid configuration.
91#[error("invalid configuration - error_code: {error_code:#?}, actions: {actions:#?}")]
92Invalid {
93/// The reason for the failure.
94error_code: ConfigResult,
9596/// Suggested actions that the client can take to resolve the failure.
97actions: Vec<ClientCompositionAction>,
98 },
99100/// Failure due to a FIDL transport error.
101#[error("FIDL channel error")]
102Fidl(#[from] fidl::Error),
103}
104105/// Represents a suggested client composition action generated by the driver.
106#[derive(Debug, Clone)]
107pub struct ClientCompositionAction {
108/// The ID of the display that concerns the action.
109pub display_id: DisplayId,
110111/// The ID of the layer that the action should be taken on.
112pub layer_id: LayerId,
113114/// Description of the action.
115pub opcode: ClientCompositionOpcode,
116}
117118impl ConfigError {
119/// Create an `Invalid` configuration error variant from FIDL output.
120pub fn invalid(error_code: ConfigResult, actions: Vec<ClientCompositionOp>) -> ConfigError {
121 ConfigError::Invalid {
122 error_code,
123 actions: actions.into_iter().map(ClientCompositionAction::from).collect(),
124 }
125 }
126}
127128impl From<ClientCompositionOp> for ClientCompositionAction {
129fn from(src: ClientCompositionOp) -> Self {
130Self {
131 display_id: src.display_id.into(),
132 layer_id: src.layer_id.into(),
133 opcode: src.opcode,
134 }
135 }
136}