linux: use ioctl numbers from linux_raw_sys

This commit is contained in:
Kevin Mehall 2025-03-07 22:43:22 -07:00
parent 0e145f89a6
commit f0a2e8c5a7
2 changed files with 28 additions and 56 deletions

View file

@ -23,6 +23,7 @@ futures-lite = "1.13.0"
[target.'cfg(any(target_os="linux", target_os="android"))'.dependencies]
rustix = { version = "1.0.1", features = ["fs", "event", "net"] }
linux-raw-sys = { version = "0.9.2", features = ["ioctl"] }
[target.'cfg(target_os="windows")'.dependencies]
windows-sys = { version = "0.59.0", features = ["Win32_Devices_Usb", "Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation", "Win32_Devices_Properties", "Win32_Storage_FileSystem", "Win32_Security", "Win32_System_IO", "Win32_System_Registry", "Win32_System_Com"] }

View file

@ -6,6 +6,12 @@
#![allow(dead_code)]
use std::ffi::{c_int, c_uchar, c_uint, c_void};
use linux_raw_sys::ioctl::{
USBDEVFS_CLAIMINTERFACE, USBDEVFS_CLEAR_HALT, USBDEVFS_CONNECT, USBDEVFS_CONTROL,
USBDEVFS_DISCARDURB, USBDEVFS_DISCONNECT, USBDEVFS_DISCONNECT_CLAIM, USBDEVFS_GET_SPEED,
USBDEVFS_IOCTL, USBDEVFS_REAPURBNDELAY, USBDEVFS_RELEASEINTERFACE, USBDEVFS_RESET,
USBDEVFS_SETCONFIGURATION, USBDEVFS_SETINTERFACE, USBDEVFS_SUBMITURB,
};
use rustix::{
fd::AsFd,
io,
@ -14,27 +20,23 @@ use rustix::{
pub fn set_configuration<Fd: AsFd>(fd: Fd, configuration: u8) -> io::Result<()> {
unsafe {
let ctl = ioctl::Setter::<{ ioctl::opcode::read::<c_uint>(b'U', 5) }, c_uint>::new(
configuration.into(),
);
let ctl =
ioctl::Setter::<{ USBDEVFS_SETCONFIGURATION as _ }, c_uint>::new(configuration.into());
ioctl::ioctl(fd, ctl)
}
}
pub fn claim_interface<Fd: AsFd>(fd: Fd, interface: u8) -> io::Result<()> {
unsafe {
let ctl = ioctl::Setter::<{ ioctl::opcode::read::<c_uint>(b'U', 15) }, c_uint>::new(
interface.into(),
);
let ctl = ioctl::Setter::<{ USBDEVFS_CLAIMINTERFACE as _ }, c_uint>::new(interface.into());
ioctl::ioctl(fd, ctl)
}
}
pub fn release_interface<Fd: AsFd>(fd: Fd, interface: u8) -> io::Result<()> {
unsafe {
let ctl = ioctl::Setter::<{ ioctl::opcode::read::<c_uint>(b'U', 16) }, c_uint>::new(
interface.into(),
);
let ctl =
ioctl::Setter::<{ USBDEVFS_RELEASEINTERFACE as _ }, c_uint>::new(interface.into());
ioctl::ioctl(fd, ctl)
}
}
@ -57,7 +59,7 @@ pub fn detach_and_claim_interface<Fd: AsFd>(fd: Fd, interface: u8) -> io::Result
dc.driver[0..6].copy_from_slice(b"usbfs\0");
let ctl = ioctl::Setter::<{ opcodes::USBDEVFS_DISCONNECT_CLAIM }, DetachAndClaim>::new(dc);
let ctl = ioctl::Setter::<{ USBDEVFS_DISCONNECT_CLAIM as _ }, DetachAndClaim>::new(dc);
ioctl::ioctl(&fd, ctl)
}
@ -70,39 +72,15 @@ struct UsbFsIoctl {
data: *mut c_void,
}
/// Opcodes used in ioctl with the usb device fs.
///
/// Taken from https://github.com/torvalds/linux/blob/e9680017b2dc8686a908ea1b51941a91b6da9f1d/include/uapi/linux/usbdevice_fs.h#L187
// We repeat the USBDEVFS_ prefix to help keep the same names as what linux uses.
// This makes the code more searchable.
// TODO: Move the rest of the opcodes into here.
#[allow(non_camel_case_types)]
mod opcodes {
use rustix::ioctl::Opcode;
use super::*;
pub const USBDEVFS_IOCTL: Opcode = ioctl::opcode::read_write::<UsbFsIoctl>(b'U', 18);
pub const USBDEVFS_DISCONNECT_CLAIM: Opcode = ioctl::opcode::read::<DetachAndClaim>(b'U', 27);
/// These opcodes are nested inside a [`USBDEVFS_IOCTL`] operation.
pub mod nested {
use super::*;
pub const USBDEVFS_DISCONNECT: Opcode = ioctl::opcode::none(b'U', 22);
pub const USBDEVFS_CONNECT: Opcode = ioctl::opcode::none(b'U', 23);
}
}
pub fn detach_kernel_driver<Fd: AsFd>(fd: Fd, interface: u8) -> io::Result<()> {
let command = UsbFsIoctl {
interface: interface.into(),
// NOTE: Cast needed since on android this type is i32 vs u32 on linux
ioctl_code: opcodes::nested::USBDEVFS_DISCONNECT as _,
ioctl_code: USBDEVFS_DISCONNECT as _,
data: std::ptr::null_mut(),
};
unsafe {
let ctl = ioctl::Setter::<{ opcodes::USBDEVFS_IOCTL }, UsbFsIoctl>::new(command);
let ctl = ioctl::Setter::<{ USBDEVFS_IOCTL as _ }, UsbFsIoctl>::new(command);
ioctl::ioctl(fd, ctl)
}
}
@ -110,11 +88,11 @@ pub fn detach_kernel_driver<Fd: AsFd>(fd: Fd, interface: u8) -> io::Result<()> {
pub fn attach_kernel_driver<Fd: AsFd>(fd: Fd, interface: u8) -> io::Result<()> {
let command = UsbFsIoctl {
interface: interface.into(),
ioctl_code: opcodes::nested::USBDEVFS_CONNECT as _,
ioctl_code: USBDEVFS_CONNECT as _,
data: std::ptr::null_mut(),
};
unsafe {
let ctl = ioctl::Setter::<{ opcodes::USBDEVFS_IOCTL }, UsbFsIoctl>::new(command);
let ctl = ioctl::Setter::<{ USBDEVFS_IOCTL as _ }, UsbFsIoctl>::new(command);
ioctl::ioctl(fd, ctl)
}
}
@ -128,12 +106,10 @@ struct SetAltSetting {
pub fn set_interface<Fd: AsFd>(fd: Fd, interface: u8, alt_setting: u8) -> io::Result<()> {
unsafe {
let ctl =
ioctl::Setter::<{ ioctl::opcode::read::<SetAltSetting>(b'U', 4) }, SetAltSetting>::new(
SetAltSetting {
ioctl::Setter::<{ USBDEVFS_SETINTERFACE as _ }, SetAltSetting>::new(SetAltSetting {
interface: interface.into(),
alt_setting: alt_setting.into(),
},
);
});
ioctl::ioctl(fd, ctl)
}
}
@ -176,28 +152,28 @@ unsafe impl<const OPCODE: Opcode, Input> Ioctl for PassPtr<OPCODE, Input> {
pub unsafe fn submit_urb<Fd: AsFd>(fd: Fd, urb: *mut Urb) -> io::Result<()> {
unsafe {
let ctl = PassPtr::<{ ioctl::opcode::read::<Urb>(b'U', 10) }, Urb>::new(urb);
let ctl = PassPtr::<{ USBDEVFS_SUBMITURB as _ }, Urb>::new(urb);
ioctl::ioctl(fd, ctl)
}
}
pub fn reap_urb_ndelay<Fd: AsFd>(fd: Fd) -> io::Result<*mut Urb> {
unsafe {
let ctl = ioctl::Getter::<{ ioctl::opcode::write::<*mut Urb>(b'U', 13) }, *mut Urb>::new();
let ctl = ioctl::Getter::<{ USBDEVFS_REAPURBNDELAY as _ }, *mut Urb>::new();
ioctl::ioctl(fd, ctl)
}
}
pub unsafe fn discard_urb<Fd: AsFd>(fd: Fd, urb: *mut Urb) -> io::Result<()> {
unsafe {
let ctl = PassPtr::<{ ioctl::opcode::none(b'U', 11) }, Urb>::new(urb);
let ctl = PassPtr::<{ USBDEVFS_DISCARDURB as _ }, Urb>::new(urb);
ioctl::ioctl(fd, ctl)
}
}
pub fn reset<Fd: AsFd>(fd: Fd) -> io::Result<()> {
unsafe {
let ctl = ioctl::NoArg::<{ ioctl::opcode::none(b'U', 20) }>::new();
let ctl = ioctl::NoArg::<{ USBDEVFS_RESET as _ }>::new();
ioctl::ioctl(fd, ctl)
}
}
@ -274,26 +250,21 @@ pub struct CtrlTransfer {
pub fn control<Fd: AsFd>(fd: Fd, transfer: CtrlTransfer) -> io::Result<usize> {
unsafe {
let ctl =
Transfer::<{ ioctl::opcode::read_write::<CtrlTransfer>(b'U', 0) }, CtrlTransfer>::new(
transfer,
);
let ctl = Transfer::<{ USBDEVFS_CONTROL as _ }, CtrlTransfer>::new(transfer);
ioctl::ioctl(fd, ctl)
}
}
pub fn clear_halt<Fd: AsFd>(fd: Fd, endpoint: u8) -> io::Result<()> {
unsafe {
let ctl = ioctl::Setter::<{ ioctl::opcode::read::<c_uint>(b'U', 21) }, c_uint>::new(
endpoint.into(),
);
let ctl = ioctl::Setter::<{ USBDEVFS_CLEAR_HALT as _ }, c_uint>::new(endpoint.into());
ioctl::ioctl(fd, ctl)
}
}
pub fn get_speed<Fd: AsFd>(fd: Fd) -> io::Result<usize> {
unsafe {
let ctl = Transfer::<{ ioctl::opcode::none(b'U', 31) }, ()>::new(());
let ctl = Transfer::<{ USBDEVFS_GET_SPEED as _ }, ()>::new(());
ioctl::ioctl(fd, ctl)
}
}