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::{
|
||||
display_info,
|
||||
drm_scanner::{DrmScanEvent, DrmScanner},
|
||||
edid::EdidInfo,
|
||||
};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
|
||||
|
@ -929,9 +929,17 @@ impl AnvilState<UdevData> {
|
|||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
let (make, model) = EdidInfo::for_connector(&device.drm, connector.handle())
|
||||
.map(|info| (info.manufacturer, info.model))
|
||||
.unwrap_or_else(|| ("Unknown".into(), "Unknown".into()));
|
||||
let display_info = display_info::for_connector(&device.drm, connector.handle());
|
||||
|
||||
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 {
|
||||
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>"]
|
||||
|
||||
[dependencies]
|
||||
edid-rs = "0.1.0"
|
||||
libdisplay-info = { version = "0.1.0", optional = true }
|
||||
drm = { version = "0.12.0" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
generate-hwdata = ["pkg-config"]
|
||||
default = ["display-info"]
|
||||
display-info = ["libdisplay-info"]
|
||||
|
||||
[dev-dependencies.smithay]
|
||||
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
|
||||
|
||||
- `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.
|
||||
- `ConnectorScanner` is responsible for tracking connected/disconnected events.
|
||||
- `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 smithay_drm_extras::{
|
||||
display_info,
|
||||
drm_scanner::{self, DrmScanEvent},
|
||||
edid::EdidInfo,
|
||||
};
|
||||
|
||||
use smithay::{
|
||||
|
@ -135,9 +135,17 @@ impl State {
|
|||
if let Some(device) = self.devices.get_mut(&node) {
|
||||
let name = format!("{}-{}", connector.interface().as_str(), connector.interface_id());
|
||||
|
||||
let (manufacturer, model) = EdidInfo::for_connector(&device.drm, connector.handle())
|
||||
.map(|info| (info.manufacturer, info.model))
|
||||
.unwrap_or_else(|| ("Unknown".into(), "Unknown".into()));
|
||||
let display_info = display_info::for_connector(&device.drm, connector.handle());
|
||||
|
||||
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:");
|
||||
dbg!(name);
|
||||
|
@ -166,7 +174,11 @@ impl State {
|
|||
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 {
|
||||
DrmScanEvent::Connected {
|
||||
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
|
||||
//!
|
||||
//! - [`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
|
||||
//! disconnected events, as well as mapping CRTC to them.
|
||||
//!
|
||||
//! ### 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)]
|
||||
|
||||
#[cfg(feature = "display-info")]
|
||||
pub mod display_info;
|
||||
pub mod drm_scanner;
|
||||
pub mod edid;
|
||||
mod hwdata;
|
||||
|
|
Loading…
Reference in a new issue