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

Can't use ioctl with media_device_info, result is always ENOTTY #1386

Closed
patrickelectric opened this issue Feb 9, 2021 · 5 comments
Closed

Comments

@patrickelectric
Copy link

I have lost some time already trying to figure out how to use ioctl with nix, but until now I couldn't get it work.
Is there any documentation with examples that could help ?
From what I read this could is correct and should work.

use nix;
use std::os::unix::io::AsRawFd;
// https://www.kernel.org/doc/html/latest/userspace-api/media/mediactl/media-ioc-device-info.html#description
#[repr(C)]
pub struct MediaDeviceInfo {
    driver_name: [char; 16],      // ASCII
    device_name: [char; 32],      // UTF-8
    serial_number: [char; 40],    // ASCII
    bus_info: [char; 32],         // ASCII
    media_version: u32,           // Media API version, formatted with the KERNEL_VERSION() macro.
    hardware_device_version: u32, // Hardware device revision in a driver-specific format.
    driver_version: u32, //	Media device driver version, formatted with the KERNEL_VERSION() macro. Together with the driver field this identifies a particular driver.
    reserved: [u32; 31], // Reserved for future extensions. Drivers and applications must set this array to zero.
}
// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/media.h#L372
nix::ioctl_readwrite!(media_ioc_device_info, b'|', 0x00, MediaDeviceInfo);

fn main() {
    let video_device = std::fs::File::open("/dev/video0").unwrap();
    let video_device_pointer = video_device.as_raw_fd();
    let mut media_device_info: MediaDeviceInfo = unsafe { std::mem::zeroed() };

    let result = unsafe { media_ioc_device_info(video_device_pointer, &mut media_device_info) };

    println!("device_name: {:#?}", media_device_info.device_name);
    println!("result: {:#?}", result);
}
@asomers
Copy link
Member

asomers commented Feb 13, 2021

Have you looked at the tests in Nix's test/sys/test_ioctl.rs directory?

@asomers
Copy link
Member

asomers commented Feb 13, 2021

ENOTTY usually indicates that you either got the ioctl number wrong, or you're trying to use it on the wrong kind of file descriptor. If you run your program with strace, it will attempt to decode the ioctl number. If you see MEDIA_IOC_DEVICE_INFO in strace's output then you know you defined it correctly.

@7b4software
Copy link

I don't know if is related but when implement usbapi crate I noticed that I could now use standard macros in nix and implemented ioctl_readwrite_ptr and ioctl_read_ptr. Full code here https://gitlab.com/mike7b4/usbapi-rs/-/blob/master/src/os/linux/usbfs.rs

snippets:

#[macro_export]
macro_rules! ioctl_read_ptr {
    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
        $(#[$attr])*
        /// # Safety
        /// ioctl call need unsafe calls to C
        pub unsafe fn $name(fd: nix::libc::c_int,
                            data: *const $ty)
                            -> nix::Result<nix::libc::c_int> {
            convert_ioctl_res!(nix::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as nix::sys::ioctl::ioctl_num_type, data))
        }
    )
}

#[macro_export]
macro_rules! ioctl_readwrite_ptr {
    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
        $(#[$attr])*
            /// # Safety
            /// ioctl call need unsafe calls to C
            pub unsafe fn $name(fd: nix::libc::c_int,
                                data: *mut $ty)
                                -> nix::Result<nix::libc::c_int> {
                                    convert_ioctl_res!(nix::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as nix::sys::ioctl::ioctl_num_type, data))
            }
    )
}

@dcz-purism
Copy link

You're opening the wrong device. Try /dev/media0.

As a side note, you shouldbe using std::ffi::c_char rather than char. The latter is a Unicode code point.

@patrickelectric did you continue working on the code? Media interface would be useful to have.

@asomers
Copy link
Member

asomers commented Apr 2, 2023

I'm going to close the issue, on the assumption that the OP figured his problem out.

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

No branches or pull requests

4 participants