3

これはHow to use nix's ioctl? に関連しています。しかし、それは同じ質問ではありません。

可変サイズのバッファを取得したい。ioctlXバイトを読み取る必要があることを教えてくれる別のものがあります。Cヘッダーは、次のことも教えてくれます:

#define HID_MAX_DESCRIPTOR_SIZE     4096
#define HIDIOCGRDESC        _IOR('H', 0x02, struct hidraw_report_descriptor)

struct hidraw_report_descriptor {
    __u32 size;
    __u8 value[HID_MAX_DESCRIPTOR_SIZE];
};

次のようにマクロを定義します。

ioctl_read_buf!(hid_read_descr, b'H', 0x02, u8);

そして後で呼び出します:

let mut desc_raw = [0u8; 4 + 4096];
let err = unsafe { hid_read_descr(file.as_raw_fd(), &mut desc_raw); };

これを行うdesc_rawと、ゼロでいっぱいになります。size構造体の定義に基づいて、最初の 4 バイトが含まれていると予想していました。

代替手段も機能していないようです

ioctl_read!(hid_read_descr2, b'H', 0x02, [u8; 4+4096]);
// ...
let mut desc_raw = [0xFFu8; 4 + 4096];
let err = unsafe { hid_read_descr2(file.as_raw_fd(), &mut desc_raw); };

どちらの場合も、desc_raw0xFF で初期化を試みましたが、呼び出し後はそのままのようです。

ioctl_read_bufマクロの使い方が間違っていませんか?

4

2 に答える 2

4

Digikataがプログラムを駆動するのに十分なコードを慎重に提供したので...

ioctl_read_bufマクロの使い方が間違っていませんか?

ここでそれを使用することはまったく間違っていると思います。データの配列を読み取るのではなく、特定の型の単一のインスタンスを読み取りたい。それioctl_read!がそのためです。

repr(C)C の定義を模倣する構造体を定義します。これにより、アラインメント、パディング、フィールドの順序などの重要な詳細がすべて、呼び出しているコードと 1 対 1 で一致することが保証されます。

次に、この構造体の初期化されていないインスタンスを構築し、それを新しく定義された関数に渡すことができます。

use libc; // 0.2.66
use nix::ioctl_read; // 0.16.1
use std::{
    fs::OpenOptions,
    mem::MaybeUninit,
    os::unix::{fs::OpenOptionsExt, io::AsRawFd},
};

const HID_MAX_DESCRIPTOR_SIZE: usize = 4096;

#[repr(C)]
pub struct hidraw_report_descriptor {
    size: u32,
    value: [u8; HID_MAX_DESCRIPTOR_SIZE],
}

ioctl_read!(hid_read_sz, b'H', 0x01, libc::c_int);
ioctl_read!(hid_read_descr, b'H', 0x02, hidraw_report_descriptor);

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let file = OpenOptions::new()
        .read(true)
        .write(true)
        .custom_flags(libc::O_NONBLOCK)
        .open("/dev/hidraw0")?;

    unsafe {
        let fd = file.as_raw_fd();

        let mut size = 0;
        hid_read_sz(fd, &mut size)?;
        println!("{}", size);

        let mut desc_raw = MaybeUninit::<hidraw_report_descriptor>::uninit();
        (*desc_raw.as_mut_ptr()).size = size as u32;
        hid_read_descr(file.as_raw_fd(), desc_raw.as_mut_ptr())?;
        let desc_raw = desc_raw.assume_init();
        let data = &desc_raw.value[..desc_raw.size as usize];
        println!("{:02x?}", data);
    }

    Ok(())
}
于 2018-08-18T00:34:46.823 に答える