mirror of
https://github.com/Smithay/smithay.git
synced 2024-09-28 03:21:14 +02:00
drm-extras: replace edid-rs with libdisplay-info
Some checks are pending
Continuous Integration / format (push) Waiting to run
Continuous Integration / clippy-check (push) Waiting to run
Continuous Integration / check-msrv (push) Blocked by required conditions
Continuous Integration / check-minimal (push) Blocked by required conditions
Continuous Integration / smithay-check-features (push) Waiting to run
Continuous Integration / smithay-tests (push) Blocked by required conditions
Continuous Integration / smallvil-check (push) Blocked by required conditions
Continuous Integration / anvil-check-features (push) Blocked by required conditions
Continuous Integration / WLCS: Bad Buffer Test (push) Blocked by required conditions
Continuous Integration / WLCS: Core tests (push) Blocked by required conditions
Continuous Integration / WLCS: Output tests (push) Blocked by required conditions
Continuous Integration / WLCS: Pointer input tests (push) Blocked by required conditions
Continuous Integration / Documentation on Github Pages (push) Blocked by required conditions
Some checks are pending
Continuous Integration / format (push) Waiting to run
Continuous Integration / clippy-check (push) Waiting to run
Continuous Integration / check-msrv (push) Blocked by required conditions
Continuous Integration / check-minimal (push) Blocked by required conditions
Continuous Integration / smithay-check-features (push) Waiting to run
Continuous Integration / smithay-tests (push) Blocked by required conditions
Continuous Integration / smallvil-check (push) Blocked by required conditions
Continuous Integration / anvil-check-features (push) Blocked by required conditions
Continuous Integration / WLCS: Bad Buffer Test (push) Blocked by required conditions
Continuous Integration / WLCS: Core tests (push) Blocked by required conditions
Continuous Integration / WLCS: Output tests (push) Blocked by required conditions
Continuous Integration / WLCS: Pointer input tests (push) Blocked by required conditions
Continuous Integration / Documentation on Github Pages (push) Blocked by required conditions
This commit is contained in:
parent
13164854de
commit
ba75638167
10 changed files with 74 additions and 2687 deletions
|
@ -88,8 +88,8 @@ use smithay::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use smithay_drm_extras::{
|
use smithay_drm_extras::{
|
||||||
|
display_info,
|
||||||
drm_scanner::{DrmScanEvent, DrmScanner},
|
drm_scanner::{DrmScanEvent, DrmScanner},
|
||||||
edid::EdidInfo,
|
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
|
@ -929,9 +929,17 @@ impl AnvilState<UdevData> {
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
let (make, model) = EdidInfo::for_connector(&device.drm, connector.handle())
|
let display_info = display_info::for_connector(&device.drm, connector.handle());
|
||||||
.map(|info| (info.manufacturer, info.model))
|
|
||||||
.unwrap_or_else(|| ("Unknown".into(), "Unknown".into()));
|
let make = display_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|info| info.make())
|
||||||
|
.unwrap_or_else(|| "Unknown".into());
|
||||||
|
|
||||||
|
let model = display_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|info| info.model())
|
||||||
|
.unwrap_or_else(|| "Unknown".into());
|
||||||
|
|
||||||
if non_desktop {
|
if non_desktop {
|
||||||
info!("Connector {} is non-desktop, setting up for leasing", output_name);
|
info!("Connector {} is non-desktop, setting up for leasing", output_name);
|
||||||
|
|
|
@ -6,15 +6,12 @@ license = "MIT"
|
||||||
authors = ["Bartłomiej Maryńczak <marynczakbartlomiej@gmail.com>"]
|
authors = ["Bartłomiej Maryńczak <marynczakbartlomiej@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
edid-rs = "0.1.0"
|
libdisplay-info = { version = "0.1.0", optional = true }
|
||||||
drm = { version = "0.12.0" }
|
drm = { version = "0.12.0" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["display-info"]
|
||||||
generate-hwdata = ["pkg-config"]
|
display-info = ["libdisplay-info"]
|
||||||
|
|
||||||
[dev-dependencies.smithay]
|
[dev-dependencies.smithay]
|
||||||
path = "../"
|
path = "../"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
pkg-config = { version = "0.3.26", optional = true }
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
This crate contains some extra abstractions and helpers over DRM
|
This crate contains some extra abstractions and helpers over DRM
|
||||||
|
|
||||||
- `edid` module is responsible for extraction of information from DRM connectors (`model` and `manufacturer`)
|
- `display_info` module is responsible for extraction of information from DRM connectors (`model` and `manufacturer`)
|
||||||
- `drm_scanner` module contains helpers for detecting connector connected and disconnected events as well as mapping crtc to them.
|
- `drm_scanner` module contains helpers for detecting connector connected and disconnected events as well as mapping crtc to them.
|
||||||
- `ConnectorScanner` is responsible for tracking connected/disconnected events.
|
- `ConnectorScanner` is responsible for tracking connected/disconnected events.
|
||||||
- `CrtcMapper` trait and `SimpleCrtcMapper` are meant for mapping crtc to connector.
|
- `CrtcMapper` trait and `SimpleCrtcMapper` are meant for mapping crtc to connector.
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
fn main() {
|
|
||||||
#[cfg(feature = "generate-hwdata")]
|
|
||||||
generate_hwdata();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "generate-hwdata")]
|
|
||||||
fn generate_hwdata() {
|
|
||||||
use std::{
|
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
let pkg_path = pkg_config::get_variable("hwdata", "pkgdatadir");
|
|
||||||
// Old versions of hwdata don't have .pc file, so let's guess
|
|
||||||
let pkg_path = pkg_path.as_deref().unwrap_or("/usr/share/hwdata");
|
|
||||||
|
|
||||||
let pnp_ids_path = PathBuf::from(pkg_path).join("pnp.ids");
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"cargo:rerun-if-changed={}",
|
|
||||||
pnp_ids_path.as_os_str().to_string_lossy()
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Ok(file) = fs::read_to_string(pnp_ids_path) {
|
|
||||||
let out_dir = PathBuf::from("src").join("hwdata").join("generated");
|
|
||||||
let dest_path = Path::new(&out_dir).join("pnp_ids.rs");
|
|
||||||
|
|
||||||
let i1 = " ".repeat(4);
|
|
||||||
let i2 = " ".repeat(8);
|
|
||||||
|
|
||||||
let mut output = Vec::new();
|
|
||||||
|
|
||||||
output.push("#[rustfmt::skip]".into());
|
|
||||||
output.push("pub fn pnp_id_to_name(vendor: &[char; 3]) -> Option<&'static str> {".into());
|
|
||||||
output.push(i1.clone() + "match vendor {");
|
|
||||||
|
|
||||||
for line in file.lines() {
|
|
||||||
let mut segment = line.split('\t');
|
|
||||||
|
|
||||||
let mut code = segment.next().unwrap().chars();
|
|
||||||
let n1 = code.next().unwrap();
|
|
||||||
let n2 = code.next().unwrap();
|
|
||||||
let n3 = code.next().unwrap();
|
|
||||||
|
|
||||||
let name = segment.next().unwrap();
|
|
||||||
|
|
||||||
output.push(format!("{i2}['{n1}', '{n2}', '{n3}'] => Some(\"{name}\"),"));
|
|
||||||
}
|
|
||||||
|
|
||||||
output.push(i2 + "_ => None,");
|
|
||||||
|
|
||||||
output.push(i1 + "}");
|
|
||||||
output.push("}".into());
|
|
||||||
|
|
||||||
let output = output.join("\n");
|
|
||||||
|
|
||||||
fs::write(dest_path, output).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,8 @@ use std::{collections::HashMap, path::PathBuf, time::Duration};
|
||||||
|
|
||||||
use ::drm::control::{connector, crtc};
|
use ::drm::control::{connector, crtc};
|
||||||
use smithay_drm_extras::{
|
use smithay_drm_extras::{
|
||||||
|
display_info,
|
||||||
drm_scanner::{self, DrmScanEvent},
|
drm_scanner::{self, DrmScanEvent},
|
||||||
edid::EdidInfo,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
@ -135,9 +135,17 @@ impl State {
|
||||||
if let Some(device) = self.devices.get_mut(&node) {
|
if let Some(device) = self.devices.get_mut(&node) {
|
||||||
let name = format!("{}-{}", connector.interface().as_str(), connector.interface_id());
|
let name = format!("{}-{}", connector.interface().as_str(), connector.interface_id());
|
||||||
|
|
||||||
let (manufacturer, model) = EdidInfo::for_connector(&device.drm, connector.handle())
|
let display_info = display_info::for_connector(&device.drm, connector.handle());
|
||||||
.map(|info| (info.manufacturer, info.model))
|
|
||||||
.unwrap_or_else(|| ("Unknown".into(), "Unknown".into()));
|
let manufacturer = display_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|info| info.make())
|
||||||
|
.unwrap_or_else(|| "Unknown".into());
|
||||||
|
|
||||||
|
let model = display_info
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|info| info.model())
|
||||||
|
.unwrap_or_else(|| "Unknown".into());
|
||||||
|
|
||||||
println!("Connected:");
|
println!("Connected:");
|
||||||
dbg!(name);
|
dbg!(name);
|
||||||
|
@ -166,7 +174,11 @@ impl State {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
for event in device.drm_scanner.scan_connectors(&device.drm) {
|
for event in device
|
||||||
|
.drm_scanner
|
||||||
|
.scan_connectors(&device.drm)
|
||||||
|
.expect("failed to scan connectors")
|
||||||
|
{
|
||||||
match event {
|
match event {
|
||||||
DrmScanEvent::Connected {
|
DrmScanEvent::Connected {
|
||||||
connector,
|
connector,
|
||||||
|
|
37
smithay-drm-extras/src/display_info.rs
Normal file
37
smithay-drm-extras/src/display_info.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//! # EDID - Extended Display Identification Data
|
||||||
|
//!
|
||||||
|
//! This module is meant to help with extraction of EDID data from connectors
|
||||||
|
//!
|
||||||
|
//! ```no_run
|
||||||
|
//! # mod helpers { include!("./docs/doctest_helpers.rs"); };
|
||||||
|
//! # let drm_device: helpers::FakeDevice = todo!();
|
||||||
|
//! # let connector = todo!();
|
||||||
|
//! use smithay_drm_extras::display_info;
|
||||||
|
//!
|
||||||
|
//! let info = display_info::for_connector(&drm_device, connector).unwrap();
|
||||||
|
//!
|
||||||
|
//! println!("Monitor name: {}", info.model());
|
||||||
|
//! println!("Manufacturer name: {}", info.make());
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use drm::control::{connector, Device as ControlDevice};
|
||||||
|
use libdisplay_info::info::Info;
|
||||||
|
|
||||||
|
/// Try to read the [`Info`] from the connector EDID property
|
||||||
|
pub fn for_connector(device: &impl ControlDevice, connector: connector::Handle) -> Option<Info> {
|
||||||
|
let props = device.get_properties(connector).ok()?;
|
||||||
|
|
||||||
|
let (info, value) = props
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(handle, value)| {
|
||||||
|
let info = device.get_property(handle).ok()?;
|
||||||
|
|
||||||
|
Some((info, value))
|
||||||
|
})
|
||||||
|
.find(|(info, _)| info.name().to_str() == Ok("EDID"))?;
|
||||||
|
|
||||||
|
let blob = info.value_type().convert_value(value).as_blob()?;
|
||||||
|
let data = device.get_property_blob(blob).ok()?;
|
||||||
|
|
||||||
|
Info::parse_edid(&data).ok()
|
||||||
|
}
|
|
@ -1,89 +0,0 @@
|
||||||
//! # EDID - Extended Display Identification Data
|
|
||||||
//!
|
|
||||||
//! This module is meant to help with extraction of EDID data from connectors
|
|
||||||
//!
|
|
||||||
//! ```no_run
|
|
||||||
//! # mod helpers { include!("./docs/doctest_helpers.rs"); };
|
|
||||||
//! # let drm_device: helpers::FakeDevice = todo!();
|
|
||||||
//! # let connector = todo!();
|
|
||||||
//! use smithay_drm_extras::edid::EdidInfo;
|
|
||||||
//!
|
|
||||||
//! let info = EdidInfo::for_connector(&drm_device, connector).unwrap();
|
|
||||||
//!
|
|
||||||
//! println!("Monitor name: {}", info.model);
|
|
||||||
//! println!("Manufacturer name: {}", info.manufacturer);
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use drm::control::{connector, Device as ControlDevice, PropertyValueSet};
|
|
||||||
use edid_rs::MonitorDescriptor;
|
|
||||||
|
|
||||||
use super::hwdata;
|
|
||||||
|
|
||||||
/// Information about monitor, acquired from EDID
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct EdidInfo {
|
|
||||||
/// Monitor name
|
|
||||||
pub model: String,
|
|
||||||
/// Name of manufacturer of this monitor
|
|
||||||
pub manufacturer: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EdidInfo {
|
|
||||||
/// Get EDID info from supplied connector
|
|
||||||
pub fn for_connector(device: &impl ControlDevice, connector: connector::Handle) -> Option<EdidInfo> {
|
|
||||||
device
|
|
||||||
.get_properties(connector)
|
|
||||||
.ok()
|
|
||||||
.and_then(|props| get_edid(device, &props))
|
|
||||||
.map(|edid| EdidInfo {
|
|
||||||
model: get_monitor_name(&edid),
|
|
||||||
manufacturer: get_manufacturer_name(&edid),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_edid(device: &impl ControlDevice, props: &PropertyValueSet) -> Option<edid_rs::EDID> {
|
|
||||||
let (info, value) = props
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|(handle, value)| {
|
|
||||||
let info = device.get_property(*handle).ok()?;
|
|
||||||
|
|
||||||
Some((info, value))
|
|
||||||
})
|
|
||||||
.find(|(info, _)| info.name().to_str() == Ok("EDID"))?;
|
|
||||||
|
|
||||||
let blob = info.value_type().convert_value(*value).as_blob()?;
|
|
||||||
let data = device.get_property_blob(blob).ok()?;
|
|
||||||
|
|
||||||
let mut reader = std::io::Cursor::new(data);
|
|
||||||
|
|
||||||
edid_rs::parse(&mut reader).ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_manufacturer_name(edid: &edid_rs::EDID) -> String {
|
|
||||||
let id = edid.product.manufacturer_id;
|
|
||||||
let code = [id.0, id.1, id.2];
|
|
||||||
|
|
||||||
hwdata::pnp_id_to_name(&code)
|
|
||||||
.map(|name| name.to_string())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
code.into_iter()
|
|
||||||
.map(|v| (v as u8).to_string())
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("_")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_monitor_name(edid: &edid_rs::EDID) -> String {
|
|
||||||
edid.descriptors
|
|
||||||
.0
|
|
||||||
.iter()
|
|
||||||
.find_map(|desc| {
|
|
||||||
if let MonitorDescriptor::MonitorName(name) = desc {
|
|
||||||
Some(name.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| edid.product.product_code.to_string())
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +0,0 @@
|
||||||
mod generated {
|
|
||||||
include!("./generated/pnp_ids.rs");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pnp_id_to_name(vendor: &[char; 3]) -> Option<&'static str> {
|
|
||||||
generated::pnp_id_to_name(vendor)
|
|
||||||
}
|
|
|
@ -2,15 +2,15 @@
|
||||||
//!
|
//!
|
||||||
//! This crate contains some extra abstractions and helpers over DRM
|
//! This crate contains some extra abstractions and helpers over DRM
|
||||||
//!
|
//!
|
||||||
//! - [`edid`] is responsible for extraction of information from DRM connectors
|
//! - [`display_info`] is responsible for extraction of information from DRM connectors
|
||||||
//! - [`drm_scanner`] is responsible for detecting connector connected and
|
//! - [`drm_scanner`] is responsible for detecting connector connected and
|
||||||
//! disconnected events, as well as mapping CRTC to them.
|
//! disconnected events, as well as mapping CRTC to them.
|
||||||
//!
|
//!
|
||||||
//! ### Features
|
//! ### Features
|
||||||
//! - `generate-hwdata` - If enabled [hwdata](https://github.com/vcrhonek/hwdata) code will be regenerated using `hwdata` system package
|
//! - `display_info` - If enabled `display_info` functionality is enabled through `libdisplay-info` integration
|
||||||
|
|
||||||
#![warn(missing_docs, missing_debug_implementations)]
|
#![warn(missing_docs, missing_debug_implementations)]
|
||||||
|
|
||||||
|
#[cfg(feature = "display-info")]
|
||||||
|
pub mod display_info;
|
||||||
pub mod drm_scanner;
|
pub mod drm_scanner;
|
||||||
pub mod edid;
|
|
||||||
mod hwdata;
|
|
||||||
|
|
Loading…
Reference in a new issue