From d49490ce6ade74c52c8a716ecf35906c033127e6 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 1 Feb 2025 20:38:53 -0700 Subject: [PATCH 1/4] Update Rustix to 1.0 --- Cargo.toml | 2 +- src/platform/linux_usbfs/events.rs | 5 +- src/platform/linux_usbfs/usbfs.rs | 108 +++++++++++++++-------------- 3 files changed, 60 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 72f3d90..1d57c47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ env_logger = "0.10.0" futures-lite = "1.13.0" [target.'cfg(any(target_os="linux", target_os="android"))'.dependencies] -rustix = { version = "0.38.17", features = ["fs", "event", "net"] } +rustix = { version = "1.0.1", features = ["fs", "event", "net"] } libc = "0.2.155" [target.'cfg(target_os="windows")'.dependencies] diff --git a/src/platform/linux_usbfs/events.rs b/src/platform/linux_usbfs/events.rs index ef9d1b0..cfdd453 100644 --- a/src/platform/linux_usbfs/events.rs +++ b/src/platform/linux_usbfs/events.rs @@ -14,6 +14,7 @@ use crate::Error; use once_cell::sync::OnceCell; use rustix::{ + buffer::spare_capacity, event::epoll::{self, EventData, EventFlags}, fd::{AsFd, BorrowedFd, OwnedFd}, io::retry_on_intr, @@ -87,9 +88,9 @@ pub(super) fn unregister_fd(fd: BorrowedFd) { fn event_loop() { let epoll_fd = EPOLL_FD.get().unwrap(); - let mut event_list = epoll::EventVec::with_capacity(4); + let mut event_list = Vec::with_capacity(4); loop { - retry_on_intr(|| epoll::wait(epoll_fd, &mut event_list, -1)).unwrap(); + retry_on_intr(|| epoll::wait(epoll_fd, spare_capacity(&mut event_list), None)).unwrap(); for event in &event_list { match Tag::from_event_data(event.data) { Tag::Device(id) => Device::handle_usb_epoll(id), diff --git a/src/platform/linux_usbfs/usbfs.rs b/src/platform/linux_usbfs/usbfs.rs index 20485d5..19a693c 100644 --- a/src/platform/linux_usbfs/usbfs.rs +++ b/src/platform/linux_usbfs/usbfs.rs @@ -4,37 +4,37 @@ //! [usbfs]: https://www.kernel.org/doc/html/latest/driver-api/usb/usb.html#the-usb-character-device-nodes //! [uapi]: https://github.com/torvalds/linux/blob/master/tools/include/uapi/linux/usbdevice_fs.h #![allow(dead_code)] -use std::{ - ffi::{c_int, c_uchar, c_uint, c_void}, - marker::PhantomData, -}; +use std::ffi::{c_int, c_uchar, c_uint, c_void}; use rustix::{ fd::AsFd, io, - ioctl::{self, CompileTimeOpcode, Ioctl, IoctlOutput}, + ioctl::{self, Ioctl, IoctlOutput, Opcode}, }; pub fn set_configuration(fd: Fd, configuration: u8) -> io::Result<()> { unsafe { - let ctl = - ioctl::Setter::, c_uint>::new(configuration.into()); + let ctl = ioctl::Setter::<{ ioctl::opcode::read::(b'U', 5) }, c_uint>::new( + configuration.into(), + ); ioctl::ioctl(fd, ctl) } } pub fn claim_interface(fd: Fd, interface: u8) -> io::Result<()> { unsafe { - let ctl = - ioctl::Setter::, c_uint>::new(interface.into()); + let ctl = ioctl::Setter::<{ ioctl::opcode::read::(b'U', 15) }, c_uint>::new( + interface.into(), + ); ioctl::ioctl(fd, ctl) } } pub fn release_interface(fd: Fd, interface: u8) -> io::Result<()> { unsafe { - let ctl = - ioctl::Setter::, c_uint>::new(interface.into()); + let ctl = ioctl::Setter::<{ ioctl::opcode::read::(b'U', 16) }, c_uint>::new( + interface.into(), + ); ioctl::ioctl(fd, ctl) } } @@ -57,7 +57,7 @@ pub fn detach_and_claim_interface(fd: Fd, interface: u8) -> io::Result dc.driver[0..6].copy_from_slice(b"usbfs\0"); - let ctl = ioctl::Setter::::new(dc); + let ctl = ioctl::Setter::<{ opcodes::USBDEVFS_DISCONNECT_CLAIM }, DetachAndClaim>::new(dc); ioctl::ioctl(&fd, ctl) } @@ -78,17 +78,19 @@ struct UsbFsIoctl { // TODO: Move the rest of the opcodes into here. #[allow(non_camel_case_types)] mod opcodes { + use rustix::ioctl::Opcode; + use super::*; - pub type USBDEVFS_IOCTL = ioctl::ReadWriteOpcode; - pub type USBDEVFS_DISCONNECT_CLAIM = ioctl::ReadOpcode; + pub const USBDEVFS_IOCTL: Opcode = ioctl::opcode::read_write::(b'U', 18); + pub const USBDEVFS_DISCONNECT_CLAIM: Opcode = ioctl::opcode::read::(b'U', 27); /// These opcodes are nested inside a [`USBDEVFS_IOCTL`] operation. pub mod nested { use super::*; - pub type USBDEVFS_DISCONNECT = ioctl::NoneOpcode; - pub type USBDEVFS_CONNECT = ioctl::NoneOpcode; + pub const USBDEVFS_DISCONNECT: Opcode = ioctl::opcode::none(b'U', 22); + pub const USBDEVFS_CONNECT: Opcode = ioctl::opcode::none(b'U', 23); } } @@ -96,11 +98,11 @@ pub fn detach_kernel_driver(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::OPCODE.raw() as _, + ioctl_code: opcodes::nested::USBDEVFS_DISCONNECT as _, data: std::ptr::null_mut(), }; unsafe { - let ctl = ioctl::Setter::::new(command); + let ctl = ioctl::Setter::<{ opcodes::USBDEVFS_IOCTL }, UsbFsIoctl>::new(command); ioctl::ioctl(fd, ctl) } } @@ -108,11 +110,11 @@ pub fn detach_kernel_driver(fd: Fd, interface: u8) -> io::Result<()> { pub fn attach_kernel_driver(fd: Fd, interface: u8) -> io::Result<()> { let command = UsbFsIoctl { interface: interface.into(), - ioctl_code: opcodes::nested::USBDEVFS_CONNECT::OPCODE.raw() as _, + ioctl_code: opcodes::nested::USBDEVFS_CONNECT as _, data: std::ptr::null_mut(), }; unsafe { - let ctl = ioctl::Setter::::new(command); + let ctl = ioctl::Setter::<{ opcodes::USBDEVFS_IOCTL }, UsbFsIoctl>::new(command); ioctl::ioctl(fd, ctl) } } @@ -125,22 +127,22 @@ struct SetAltSetting { pub fn set_interface(fd: Fd, interface: u8, alt_setting: u8) -> io::Result<()> { unsafe { - let ctl = ioctl::Setter::, SetAltSetting>::new( - SetAltSetting { - interface: interface.into(), - alt_setting: alt_setting.into(), - }, - ); + let ctl = + ioctl::Setter::<{ ioctl::opcode::read::(b'U', 4) }, SetAltSetting>::new( + SetAltSetting { + interface: interface.into(), + alt_setting: alt_setting.into(), + }, + ); ioctl::ioctl(fd, ctl) } } -pub struct PassPtr { +pub struct PassPtr { input: *mut Input, - _opcode: PhantomData, } -impl PassPtr { +impl PassPtr { /// Create a new pointer setter-style `ioctl` object. /// /// # Safety @@ -150,18 +152,18 @@ impl PassPtr { /// get. #[inline] pub unsafe fn new(input: *mut Input) -> Self { - Self { - input, - _opcode: PhantomData, - } + Self { input } } } -unsafe impl Ioctl for PassPtr { +unsafe impl Ioctl for PassPtr { type Output = (); const IS_MUTATING: bool = false; - const OPCODE: rustix::ioctl::Opcode = Opcode::OPCODE; + + fn opcode(&self) -> ioctl::Opcode { + OPCODE + } fn as_ptr(&mut self) -> *mut c_void { self.input as *mut c_void @@ -174,28 +176,28 @@ unsafe impl Ioctl for PassPtr { pub unsafe fn submit_urb(fd: Fd, urb: *mut Urb) -> io::Result<()> { unsafe { - let ctl = PassPtr::, Urb>::new(urb); + let ctl = PassPtr::<{ ioctl::opcode::read::(b'U', 10) }, Urb>::new(urb); ioctl::ioctl(fd, ctl) } } pub fn reap_urb_ndelay(fd: Fd) -> io::Result<*mut Urb> { unsafe { - let ctl = ioctl::Getter::, *mut Urb>::new(); + let ctl = ioctl::Getter::<{ ioctl::opcode::write::<*mut Urb>(b'U', 13) }, *mut Urb>::new(); ioctl::ioctl(fd, ctl) } } pub unsafe fn discard_urb(fd: Fd, urb: *mut Urb) -> io::Result<()> { unsafe { - let ctl = PassPtr::, Urb>::new(urb); + let ctl = PassPtr::<{ ioctl::opcode::none(b'U', 11) }, Urb>::new(urb); ioctl::ioctl(fd, ctl) } } pub fn reset(fd: Fd) -> io::Result<()> { unsafe { - let ctl = ioctl::NoArg::>::new(); + let ctl = ioctl::NoArg::<{ ioctl::opcode::none(b'U', 20) }>::new(); ioctl::ioctl(fd, ctl) } } @@ -229,26 +231,25 @@ pub struct Urb { // + variable size array of iso_packet_desc } -pub struct Transfer { +pub struct Transfer { input: Input, - _opcode: PhantomData, } -impl Transfer { +impl Transfer { #[inline] pub unsafe fn new(input: Input) -> Self { - Self { - input, - _opcode: PhantomData, - } + Self { input } } } -unsafe impl Ioctl for Transfer { +unsafe impl Ioctl for Transfer { type Output = usize; const IS_MUTATING: bool = true; - const OPCODE: rustix::ioctl::Opcode = Opcode::OPCODE; + + fn opcode(&self) -> ioctl::Opcode { + OPCODE + } fn as_ptr(&mut self) -> *mut c_void { &mut self.input as *mut Input as *mut c_void @@ -274,22 +275,25 @@ pub struct CtrlTransfer { pub fn control(fd: Fd, transfer: CtrlTransfer) -> io::Result { unsafe { let ctl = - Transfer::, CtrlTransfer>::new(transfer); + Transfer::<{ ioctl::opcode::read_write::(b'U', 0) }, CtrlTransfer>::new( + transfer, + ); ioctl::ioctl(fd, ctl) } } pub fn clear_halt(fd: Fd, endpoint: u8) -> io::Result<()> { unsafe { - let ctl = - ioctl::Setter::, c_uint>::new(endpoint.into()); + let ctl = ioctl::Setter::<{ ioctl::opcode::read::(b'U', 21) }, c_uint>::new( + endpoint.into(), + ); ioctl::ioctl(fd, ctl) } } pub fn get_speed(fd: Fd) -> io::Result { unsafe { - let ctl = Transfer::, ()>::new(()); + let ctl = Transfer::<{ ioctl::opcode::none(b'U', 31) }, ()>::new(()); ioctl::ioctl(fd, ctl) } } From 53a3fe41fcade9519337de5f9d0600fd5dfecab5 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Wed, 26 Feb 2025 21:15:02 -0700 Subject: [PATCH 2/4] linux: Use MaybeUninit buffer for epoll --- src/platform/linux_usbfs/events.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/platform/linux_usbfs/events.rs b/src/platform/linux_usbfs/events.rs index cfdd453..a74e438 100644 --- a/src/platform/linux_usbfs/events.rs +++ b/src/platform/linux_usbfs/events.rs @@ -14,14 +14,14 @@ use crate::Error; use once_cell::sync::OnceCell; use rustix::{ - buffer::spare_capacity, event::epoll::{self, EventData, EventFlags}, fd::{AsFd, BorrowedFd, OwnedFd}, - io::retry_on_intr, + io::Errno, }; use slab::Slab; use std::{ io, + mem::MaybeUninit, sync::{Arc, Mutex}, task::Waker, thread, @@ -88,10 +88,14 @@ pub(super) fn unregister_fd(fd: BorrowedFd) { fn event_loop() { let epoll_fd = EPOLL_FD.get().unwrap(); - let mut event_list = Vec::with_capacity(4); + let mut event_buf = [MaybeUninit::::uninit(); 4]; loop { - retry_on_intr(|| epoll::wait(epoll_fd, spare_capacity(&mut event_list), None)).unwrap(); - for event in &event_list { + let events = match epoll::wait(epoll_fd, &mut event_buf, None) { + Ok((events, _)) => events, + Err(Errno::INTR) => &mut [], + Err(e) => panic!("epoll::wait failed: {e}"), + }; + for event in events { match Tag::from_event_data(event.data) { Tag::Device(id) => Device::handle_usb_epoll(id), Tag::Waker(id) => { From 0e145f89a698a6743be3459b72ca87b91f96a971 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 1 Feb 2025 19:42:37 -0700 Subject: [PATCH 3/4] Switch to rustix for netlink bind/recvfrom --- Cargo.toml | 1 - src/platform/linux_usbfs/hotplug.rs | 78 +++++++++-------------------- 2 files changed, 24 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1d57c47..b0afabd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ futures-lite = "1.13.0" [target.'cfg(any(target_os="linux", target_os="android"))'.dependencies] rustix = { version = "1.0.1", features = ["fs", "event", "net"] } -libc = "0.2.155" [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"] } diff --git a/src/platform/linux_usbfs/hotplug.rs b/src/platform/linux_usbfs/hotplug.rs index a2d4814..28ddc04 100644 --- a/src/platform/linux_usbfs/hotplug.rs +++ b/src/platform/linux_usbfs/hotplug.rs @@ -1,16 +1,14 @@ -use libc::{sockaddr, sockaddr_nl, socklen_t, AF_NETLINK, MSG_DONTWAIT}; use log::{error, trace, warn}; use rustix::{ - fd::{AsFd, AsRawFd, OwnedFd}, - net::{netlink, socket_with, AddressFamily, SocketFlags, SocketType}, -}; -use std::{ - io::ErrorKind, - mem, - os::{raw::c_void, unix::prelude::BorrowedFd}, - path::Path, - task::Poll, + fd::{AsFd, OwnedFd}, + io::Errno, + net::{ + bind, + netlink::{self, SocketAddrNetlink}, + recvfrom, socket_with, AddressFamily, RecvFlags, SocketFlags, SocketType, + }, }; +use std::{mem::MaybeUninit, os::unix::prelude::BorrowedFd, path::Path, task::Poll}; use crate::{hotplug::HotplugEvent, Error}; @@ -31,23 +29,7 @@ impl LinuxHotplugWatch { SocketFlags::CLOEXEC, Some(netlink::KOBJECT_UEVENT), )?; - - unsafe { - // rustix doesn't support netlink yet (pending https://github.com/bytecodealliance/rustix/pull/1004) - // so use libc for now. - let mut addr: sockaddr_nl = mem::zeroed(); - addr.nl_family = AF_NETLINK as u16; - addr.nl_groups = UDEV_MULTICAST_GROUP; - let r = libc::bind( - fd.as_raw_fd(), - &addr as *const sockaddr_nl as *const sockaddr, - mem::size_of_val(&addr) as socklen_t, - ); - if r != 0 { - return Err(Error::last_os_error()); - } - } - + bind(&fd, &SocketAddrNetlink::new(0, UDEV_MULTICAST_GROUP))?; Ok(LinuxHotplugWatch { fd: Async::new(fd)?, }) @@ -67,40 +49,28 @@ impl LinuxHotplugWatch { } fn try_receive_event(fd: BorrowedFd) -> Option { - let mut buf = [0; 8192]; + let mut buf = [MaybeUninit::uninit(); 8192]; - let received = unsafe { - let mut addr: sockaddr_nl = mem::zeroed(); - let mut addrlen: socklen_t = mem::size_of_val(&addr) as socklen_t; - let r = libc::recvfrom( - fd.as_raw_fd(), - buf.as_mut_ptr() as *mut c_void, - buf.len(), - MSG_DONTWAIT, - &mut addr as *mut sockaddr_nl as *mut sockaddr, - &mut addrlen, - ); - if r >= 0 { - Ok((r as usize, addr.nl_groups)) - } else { - Err(Error::last_os_error()) + let (data, src) = match recvfrom(fd, &mut buf, RecvFlags::DONTWAIT) { + Ok(((buf, _), _, src)) => (buf, src), + Err(Errno::AGAIN | Errno::INTR) => return None, + Err(e) => { + error!("udev netlink socket recvfrom failed with {e}"); + return None; } }; - match received { - // udev messages will normally be sent to a multicast group, which only - // root can send to. Reject unicast messages that may be from anywhere. - Ok((size, groups)) if groups == UDEV_MULTICAST_GROUP => parse_packet(&buf[..size]), - Ok((_, src)) => { + // udev messages will normally be sent to a multicast group, which only + // root can send to. Reject unicast messages that may be from anywhere. + match src.map(SocketAddrNetlink::try_from).transpose() { + Ok(Some(nl)) if nl.groups() == UDEV_MULTICAST_GROUP => {} + src => { warn!("udev netlink socket received message from {src:?}"); - None - } - Err(e) if e.kind() == ErrorKind::WouldBlock => None, - Err(e) => { - error!("udev netlink socket recvfrom failed with {e}"); - None + return None; } } + + parse_packet(data) } fn parse_packet(buf: &[u8]) -> Option { From f0a2e8c5a71ff701e7b980b361ab9396886ee351 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Fri, 7 Mar 2025 22:43:22 -0700 Subject: [PATCH 4/4] linux: use ioctl numbers from linux_raw_sys --- Cargo.toml | 1 + src/platform/linux_usbfs/usbfs.rs | 83 ++++++++++--------------------- 2 files changed, 28 insertions(+), 56 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b0afabd..67a0576 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/src/platform/linux_usbfs/usbfs.rs b/src/platform/linux_usbfs/usbfs.rs index 19a693c..e0e6ea1 100644 --- a/src/platform/linux_usbfs/usbfs.rs +++ b/src/platform/linux_usbfs/usbfs.rs @@ -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: Fd, configuration: u8) -> io::Result<()> { unsafe { - let ctl = ioctl::Setter::<{ ioctl::opcode::read::(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: Fd, interface: u8) -> io::Result<()> { unsafe { - let ctl = ioctl::Setter::<{ ioctl::opcode::read::(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: Fd, interface: u8) -> io::Result<()> { unsafe { - let ctl = ioctl::Setter::<{ ioctl::opcode::read::(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: 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::(b'U', 18); - pub const USBDEVFS_DISCONNECT_CLAIM: Opcode = ioctl::opcode::read::(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: 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: Fd, interface: u8) -> io::Result<()> { pub fn attach_kernel_driver(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: Fd, interface: u8, alt_setting: u8) -> io::Result<()> { unsafe { let ctl = - ioctl::Setter::<{ ioctl::opcode::read::(b'U', 4) }, SetAltSetting>::new( - SetAltSetting { - interface: interface.into(), - alt_setting: alt_setting.into(), - }, - ); + 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 Ioctl for PassPtr { pub unsafe fn submit_urb(fd: Fd, urb: *mut Urb) -> io::Result<()> { unsafe { - let ctl = PassPtr::<{ ioctl::opcode::read::(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: 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: 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: 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: Fd, transfer: CtrlTransfer) -> io::Result { unsafe { - let ctl = - Transfer::<{ ioctl::opcode::read_write::(b'U', 0) }, CtrlTransfer>::new( - transfer, - ); + let ctl = Transfer::<{ USBDEVFS_CONTROL as _ }, CtrlTransfer>::new(transfer); ioctl::ioctl(fd, ctl) } } pub fn clear_halt(fd: Fd, endpoint: u8) -> io::Result<()> { unsafe { - let ctl = ioctl::Setter::<{ ioctl::opcode::read::(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: Fd) -> io::Result { unsafe { - let ctl = Transfer::<{ ioctl::opcode::none(b'U', 31) }, ()>::new(()); + let ctl = Transfer::<{ USBDEVFS_GET_SPEED as _ }, ()>::new(()); ioctl::ioctl(fd, ctl) } }