Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function to enumerate devices #208

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

jlHertel
Copy link

Adds a basic DRM Listing functionality.
Please note that, different from libDRM, we don't process the devices to include bus information or anything else. We also don't de-duplicate devices like libDRM does, so duplicates might occur.

This change addresses #207

src/node/mod.rs Outdated
@@ -380,3 +380,21 @@ pub fn dev_path(dev: dev_t, ty: NodeType) -> io::Result<PathBuf> {
),
))
}

/// Returns a Vector with all DRM Nodes we managed to find. There might be duplicates.
pub fn drm_get_devices() -> Result<Vec<DrmNode>, io::Error> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this instead return impl Iterator<Item = io::Result<DrmNode>>?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what would be the best approach here.
We can have IO Errors only by failing to open/read the /dev directory.
For the devices themselves, we will only get errors if they aren't DRM devices, which should be the case for the majority of stuff in /dev.

Would iterator improve anything in regards to the error handling?

Also, sorry if my answers are a bit confusing. I'm quite new to Rust, so I might be missing the big-picture on how to better handle errors/iterators.

Copy link
Contributor

@MarijnS95 MarijnS95 Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have IO Errors only by failing to open/read the /dev directory.

That could be handled with:

io::Result<impl Iterator<Item = io::Result<DrmNode>>>

For the devices themselves, we will only get errors if they aren't DRM devices, which should be the case for the majority of stuff in /dev.

And as just mentioned below, drmGetDevices2() skips errors while opening sub-devices, so we might as well return an iterator over DrmNode directly:

io::Result<impl Iterator<Item = DrmNode>>

For the devices themselves, we will only get errors if they aren't DRM devices, which should be the case for the majority of stuff in /dev.

And as below, on most platforms except FreeBSD we should be reading /dev/dri.

Also, sorry if my answers are a bit confusing. I'm quite new to Rust, so I might be missing the big-picture on how to better handle errors/iterators.

No worries, I think everyone is happy to educate new contributors on Rust as well as describing the "Rust style" used in drm-rs (as much as we're still discovering what that's supposed to be).


Regarding the drm_get_devices() function name (based on drmGetDevices(2)()), I'd drop the drm_ prefix since we're already in the drm crate (i.e. a fully qualified call would look like drm::node::drm_get_devices() which is somewhat superfluous) and then also drop the get_ prefix because of the no get_ prefix convention.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the feedback, it's highly appreciated.
I pushed the changes with everything you suggested. Do you mind to give another look?

src/node/mod.rs Outdated Show resolved Hide resolved
src/node/mod.rs Outdated Show resolved Hide resolved
src/node/mod.rs Outdated Show resolved Hide resolved
src/node/mod.rs Outdated
let mut devices: Vec<DrmNode> = vec![];

fs::read_dir("/dev")?
.for_each(|entry| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about making this a .map().collect() rather than a side-effecting for_each()? If that, use regular control flow with for entry in fs::read_dir(..)? { .. }.

The .collect() can be dropped if using @notgull's suggestion to return an iterator instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't we need to filter the results in some way if we use .map()? Asking as we check all devices and likely a lot of them aren't DRM devices, so we need to skip them. This validation is done right now by calling DrmNode::from_path().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such filtering can be implemented by a .filter_map(), but I'm hesitant to stat() every device on the system to see if it is a DRM device.

Since drmGetDevices2() was requested, I expected this feature to be built after that function. While it does also appear to ignore any error from processing individual devices, this function does open DRM_DIR_NAME which is /dev/dri on every platform except FreeBSD where it is /dev. This way we don't have to stat() devices that we know won't be DRM devices in the first place.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey thanks for the pointers. I somehow completely missed the fact that DRM_DIR_NAME was different in certain platforms. I will update the code to also use /dev/dri for all platforms except FreeBSD.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants