How to use nix's ioctl?
There is some example usage in rust-spidev. I will try to apply that to your code.
TUNSETIFF
is defined as:
#define TUNSETIFF _IOW('T', 202, int)
That would be this in Rust using nix:
const TUN_IOC_MAGIC: u8 = 'T' as u8;
const TUN_IOC_SET_IFF: u8 = 202;
ioctl!(write tun_set_iff with TUN_IOC_MAGIC, TUN_IOC_SET_IFF; u32);
The above macro will define the function, which you can call like this:
let err = unsafe { tun_set_iff(fd, ifr) }; // assuming ifr is an u32
How to use ioctl + nix macros to get a variable size buffer
Now that Digikata has thoughtfully provided enough code to drive the program...
Am I using the
ioctl_read_buf
macro incorrectly?
I'd say that using it at all is incorrect here. You don't want to read an array of data, you want to read a single instance of a specific type. That's what ioctl_read!
is for.
We define a repr(C)
struct that mimics the C definition. This ensures that important details like alignment, padding, field ordering, etc., all match one-to-one with the code we are calling.
We can then construct an uninitialized instance of this struct and pass it to the newly-defined function.
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(())
}
How to call ioctl in Rust? And interface the Linux tun driver
You can find ioctl
in nix
, which contains convenience wrapper of *nix functionalities.
How can I call ioctl for interface list, or other ioctl stuff, on Free Pascal?
Does BaseUnix.FpIOCtl
meet your use case? Have a look at the BaseUnix documentation. I found an example of using it here (reposted below).
program testrpi;
{$mode objfpc}{$H+}
uses
baseUnix,
classes,
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
sysutils;
const
I2C_SLAVE = 1795;
var
buf : packed array [0..1] of char;
c : char;
devPath : string = '/dev/i2c-1';
handle : Cint;
iDevAddr : Cint = $04;
begin
try
handle := fpopen(devPath,O_RDWR);
fpIOCtl(handle, I2C_SLAVE, pointer(iDevAddr));
except
writeln('Error initalizing i2c');
halt;
end;
while true do begin
write('Enter digit 1-9:');
readln(c);
if (not(c in ['1'..'9'])) then begin
writeln('oops - try again');
continue;
end;
buf[0] := chr(ord(c) - ord('0'));
try
fpwrite(handle, buf, 1);
except
writeln('Error writing');
halt;
end; //try
buf[0] := #99;
sleep(10);
try
fpread(handle, buf, 1);
except
writeln('Error reading');
halt;
end; //try
writeln('buf=', ord(buf[0]));
end; //while
fpclose(handle);
end.
How are ioctl() and/or fcntl() used for writing a non-blocking socket?
You use one or the other to set O_NONBLOCK
. Surely you already discovered that?
What happens to the invocation of system call when a process is killed (*nix)?
What happens in operating system kernel (Linux 2+/FreeBSD7+/OSX) when
a process is being killed (SIGKILL) while it is executing a system
call?
A process executes a system call in the context of kernel mode. At this time if kernel receives any interrupt(signal comes under software interrupt), it would check out for the priority of that particular interrupt. Software interrupt has least priority among all type of interrupt and hence it would continue to execute until it finished the critical path execution. At this point kernel would store its context and would determine the reason and priority of interrupt and service the interrupt(which is in this case is to terminate/kill the program).
However these concepts are bit complicated and may vary on different system. You may want to refer the great book "The Design Of UNIX Operating System" By Maurice J Bach which describes these concepts and the implementation in detailed way.
In particular: does every single system call know how to clean-up
itself when process termination is imminent?
Yes, As system calls gets executed in the context of kernel mode on behalf of a process.
So they always do have the logic to clean-up while process has started to abort/terminate. If user mode program terminates due to unexpected reason,kernel ensures that it clean up all the resources of that particular process. This is the great thing about kernel.
inappropriate ioctl for device
Most likely it means that the open didn't fail.
When Perl opens a file, it checks whether or not the file is a TTY (so that it can answer the -T $fh
filetest operator) by issuing the TCGETS
ioctl against it. If the file is a regular file and not a tty, the ioctl fails and sets errno to ENOTTY
(string value: "Inappropriate ioctl for device"). As ysth says, the most common reason for seeing an unexpected value in $!
is checking it when it's not valid -- that is, anywhere other than immediately after a syscall failed, so testing the result codes of your operations is critically important.
If open
actually did return false for you, and you found ENOTTY
in $!
then I would consider this a small bug (giving a useless value of $!
) but I would also be very curious as to how it happened. Code and/or truss output would be nifty.
Related Topics
Linux Configuration - Ssmtp: Cannot Open Smtp.Gmail.Com:587
How to Store Result of Diff in Linux
How to Execute 'X86_64-Conda_Cos6-Linux-Gnu-Gcc': No Such File or Directory (Pysam Installation)
How to Mmap() a Large File Without Risking The Oom Killer
Sshfs, Linux - How to Mount with Read-Only Access
Get Access to Usb Device on Linux (Libusb-1.0)
How to Copy from Tmux (Copy Mode) Running on a Remote Ssh Connection to Your Local Clipboard
How to Get a Faster Output Pipe Than /Dev/Null
How to Set Errno in Linux Device Driver
Difference Between Starting a Command Using Init.D Script and Service Start
Move Cursor on Middle Button Paste in Sublime Text 3
Why Does 'Ping' Not Timeout in Linux
How to Run .Exe Executable File from Linux Command Line