1*e7e2296bSDaniel Almeida // SPDX-License-Identifier: GPL-2.0 2*e7e2296bSDaniel Almeida // SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd. 3*e7e2296bSDaniel Almeida 4*e7e2296bSDaniel Almeida //! Abstractions for the USB bus. 5*e7e2296bSDaniel Almeida //! 6*e7e2296bSDaniel Almeida //! C header: [`include/linux/usb.h`](srctree/include/linux/usb.h) 7*e7e2296bSDaniel Almeida 8*e7e2296bSDaniel Almeida use crate::{ 9*e7e2296bSDaniel Almeida bindings, device, 10*e7e2296bSDaniel Almeida device_id::{RawDeviceId, RawDeviceIdIndex}, 11*e7e2296bSDaniel Almeida driver, 12*e7e2296bSDaniel Almeida error::{from_result, to_result, Result}, 13*e7e2296bSDaniel Almeida prelude::*, 14*e7e2296bSDaniel Almeida str::CStr, 15*e7e2296bSDaniel Almeida types::{AlwaysRefCounted, Opaque}, 16*e7e2296bSDaniel Almeida ThisModule, 17*e7e2296bSDaniel Almeida }; 18*e7e2296bSDaniel Almeida use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; 19*e7e2296bSDaniel Almeida 20*e7e2296bSDaniel Almeida /// An adapter for the registration of USB drivers. 21*e7e2296bSDaniel Almeida pub struct Adapter<T: Driver>(T); 22*e7e2296bSDaniel Almeida 23*e7e2296bSDaniel Almeida // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 24*e7e2296bSDaniel Almeida // a preceding call to `register` has been successful. 25*e7e2296bSDaniel Almeida unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 26*e7e2296bSDaniel Almeida type RegType = bindings::usb_driver; 27*e7e2296bSDaniel Almeida 28*e7e2296bSDaniel Almeida unsafe fn register( 29*e7e2296bSDaniel Almeida udrv: &Opaque<Self::RegType>, 30*e7e2296bSDaniel Almeida name: &'static CStr, 31*e7e2296bSDaniel Almeida module: &'static ThisModule, 32*e7e2296bSDaniel Almeida ) -> Result { 33*e7e2296bSDaniel Almeida // SAFETY: It's safe to set the fields of `struct usb_driver` on initialization. 34*e7e2296bSDaniel Almeida unsafe { 35*e7e2296bSDaniel Almeida (*udrv.get()).name = name.as_char_ptr(); 36*e7e2296bSDaniel Almeida (*udrv.get()).probe = Some(Self::probe_callback); 37*e7e2296bSDaniel Almeida (*udrv.get()).disconnect = Some(Self::disconnect_callback); 38*e7e2296bSDaniel Almeida (*udrv.get()).id_table = T::ID_TABLE.as_ptr(); 39*e7e2296bSDaniel Almeida } 40*e7e2296bSDaniel Almeida 41*e7e2296bSDaniel Almeida // SAFETY: `udrv` is guaranteed to be a valid `RegType`. 42*e7e2296bSDaniel Almeida to_result(unsafe { 43*e7e2296bSDaniel Almeida bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr()) 44*e7e2296bSDaniel Almeida }) 45*e7e2296bSDaniel Almeida } 46*e7e2296bSDaniel Almeida 47*e7e2296bSDaniel Almeida unsafe fn unregister(udrv: &Opaque<Self::RegType>) { 48*e7e2296bSDaniel Almeida // SAFETY: `udrv` is guaranteed to be a valid `RegType`. 49*e7e2296bSDaniel Almeida unsafe { bindings::usb_deregister(udrv.get()) }; 50*e7e2296bSDaniel Almeida } 51*e7e2296bSDaniel Almeida } 52*e7e2296bSDaniel Almeida 53*e7e2296bSDaniel Almeida impl<T: Driver + 'static> Adapter<T> { 54*e7e2296bSDaniel Almeida extern "C" fn probe_callback( 55*e7e2296bSDaniel Almeida intf: *mut bindings::usb_interface, 56*e7e2296bSDaniel Almeida id: *const bindings::usb_device_id, 57*e7e2296bSDaniel Almeida ) -> kernel::ffi::c_int { 58*e7e2296bSDaniel Almeida // SAFETY: The USB core only ever calls the probe callback with a valid pointer to a 59*e7e2296bSDaniel Almeida // `struct usb_interface` and `struct usb_device_id`. 60*e7e2296bSDaniel Almeida // 61*e7e2296bSDaniel Almeida // INVARIANT: `intf` is valid for the duration of `probe_callback()`. 62*e7e2296bSDaniel Almeida let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal>>() }; 63*e7e2296bSDaniel Almeida 64*e7e2296bSDaniel Almeida from_result(|| { 65*e7e2296bSDaniel Almeida // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct usb_device_id` and 66*e7e2296bSDaniel Almeida // does not add additional invariants, so it's safe to transmute. 67*e7e2296bSDaniel Almeida let id = unsafe { &*id.cast::<DeviceId>() }; 68*e7e2296bSDaniel Almeida 69*e7e2296bSDaniel Almeida let info = T::ID_TABLE.info(id.index()); 70*e7e2296bSDaniel Almeida let data = T::probe(intf, id, info)?; 71*e7e2296bSDaniel Almeida 72*e7e2296bSDaniel Almeida let dev: &device::Device<device::CoreInternal> = intf.as_ref(); 73*e7e2296bSDaniel Almeida dev.set_drvdata(data); 74*e7e2296bSDaniel Almeida Ok(0) 75*e7e2296bSDaniel Almeida }) 76*e7e2296bSDaniel Almeida } 77*e7e2296bSDaniel Almeida 78*e7e2296bSDaniel Almeida extern "C" fn disconnect_callback(intf: *mut bindings::usb_interface) { 79*e7e2296bSDaniel Almeida // SAFETY: The USB core only ever calls the disconnect callback with a valid pointer to a 80*e7e2296bSDaniel Almeida // `struct usb_interface`. 81*e7e2296bSDaniel Almeida // 82*e7e2296bSDaniel Almeida // INVARIANT: `intf` is valid for the duration of `disconnect_callback()`. 83*e7e2296bSDaniel Almeida let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal>>() }; 84*e7e2296bSDaniel Almeida 85*e7e2296bSDaniel Almeida let dev: &device::Device<device::CoreInternal> = intf.as_ref(); 86*e7e2296bSDaniel Almeida 87*e7e2296bSDaniel Almeida // SAFETY: `disconnect_callback` is only ever called after a successful call to 88*e7e2296bSDaniel Almeida // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 89*e7e2296bSDaniel Almeida // and stored a `Pin<KBox<T>>`. 90*e7e2296bSDaniel Almeida let data = unsafe { dev.drvdata_obtain::<Pin<KBox<T>>>() }; 91*e7e2296bSDaniel Almeida 92*e7e2296bSDaniel Almeida T::disconnect(intf, data.as_ref()); 93*e7e2296bSDaniel Almeida } 94*e7e2296bSDaniel Almeida } 95*e7e2296bSDaniel Almeida 96*e7e2296bSDaniel Almeida /// Abstraction for the USB device ID structure, i.e. [`struct usb_device_id`]. 97*e7e2296bSDaniel Almeida /// 98*e7e2296bSDaniel Almeida /// [`struct usb_device_id`]: https://docs.kernel.org/driver-api/basics.html#c.usb_device_id 99*e7e2296bSDaniel Almeida #[repr(transparent)] 100*e7e2296bSDaniel Almeida #[derive(Clone, Copy)] 101*e7e2296bSDaniel Almeida pub struct DeviceId(bindings::usb_device_id); 102*e7e2296bSDaniel Almeida 103*e7e2296bSDaniel Almeida impl DeviceId { 104*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE` macro. 105*e7e2296bSDaniel Almeida pub const fn from_id(vendor: u16, product: u16) -> Self { 106*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 107*e7e2296bSDaniel Almeida match_flags: bindings::USB_DEVICE_ID_MATCH_DEVICE as u16, 108*e7e2296bSDaniel Almeida idVendor: vendor, 109*e7e2296bSDaniel Almeida idProduct: product, 110*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 111*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 112*e7e2296bSDaniel Almeida }) 113*e7e2296bSDaniel Almeida } 114*e7e2296bSDaniel Almeida 115*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE_VER` macro. 116*e7e2296bSDaniel Almeida pub const fn from_device_ver(vendor: u16, product: u16, bcd_lo: u16, bcd_hi: u16) -> Self { 117*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 118*e7e2296bSDaniel Almeida match_flags: bindings::USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION as u16, 119*e7e2296bSDaniel Almeida idVendor: vendor, 120*e7e2296bSDaniel Almeida idProduct: product, 121*e7e2296bSDaniel Almeida bcdDevice_lo: bcd_lo, 122*e7e2296bSDaniel Almeida bcdDevice_hi: bcd_hi, 123*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 124*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 125*e7e2296bSDaniel Almeida }) 126*e7e2296bSDaniel Almeida } 127*e7e2296bSDaniel Almeida 128*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE_INFO` macro. 129*e7e2296bSDaniel Almeida pub const fn from_device_info(class: u8, subclass: u8, protocol: u8) -> Self { 130*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 131*e7e2296bSDaniel Almeida match_flags: bindings::USB_DEVICE_ID_MATCH_DEV_INFO as u16, 132*e7e2296bSDaniel Almeida bDeviceClass: class, 133*e7e2296bSDaniel Almeida bDeviceSubClass: subclass, 134*e7e2296bSDaniel Almeida bDeviceProtocol: protocol, 135*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 136*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 137*e7e2296bSDaniel Almeida }) 138*e7e2296bSDaniel Almeida } 139*e7e2296bSDaniel Almeida 140*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_INTERFACE_INFO` macro. 141*e7e2296bSDaniel Almeida pub const fn from_interface_info(class: u8, subclass: u8, protocol: u8) -> Self { 142*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 143*e7e2296bSDaniel Almeida match_flags: bindings::USB_DEVICE_ID_MATCH_INT_INFO as u16, 144*e7e2296bSDaniel Almeida bInterfaceClass: class, 145*e7e2296bSDaniel Almeida bInterfaceSubClass: subclass, 146*e7e2296bSDaniel Almeida bInterfaceProtocol: protocol, 147*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 148*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 149*e7e2296bSDaniel Almeida }) 150*e7e2296bSDaniel Almeida } 151*e7e2296bSDaniel Almeida 152*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE_INTERFACE_CLASS` macro. 153*e7e2296bSDaniel Almeida pub const fn from_device_interface_class(vendor: u16, product: u16, class: u8) -> Self { 154*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 155*e7e2296bSDaniel Almeida match_flags: (bindings::USB_DEVICE_ID_MATCH_DEVICE 156*e7e2296bSDaniel Almeida | bindings::USB_DEVICE_ID_MATCH_INT_CLASS) as u16, 157*e7e2296bSDaniel Almeida idVendor: vendor, 158*e7e2296bSDaniel Almeida idProduct: product, 159*e7e2296bSDaniel Almeida bInterfaceClass: class, 160*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 161*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 162*e7e2296bSDaniel Almeida }) 163*e7e2296bSDaniel Almeida } 164*e7e2296bSDaniel Almeida 165*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE_INTERFACE_PROTOCOL` macro. 166*e7e2296bSDaniel Almeida pub const fn from_device_interface_protocol(vendor: u16, product: u16, protocol: u8) -> Self { 167*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 168*e7e2296bSDaniel Almeida match_flags: (bindings::USB_DEVICE_ID_MATCH_DEVICE 169*e7e2296bSDaniel Almeida | bindings::USB_DEVICE_ID_MATCH_INT_PROTOCOL) as u16, 170*e7e2296bSDaniel Almeida idVendor: vendor, 171*e7e2296bSDaniel Almeida idProduct: product, 172*e7e2296bSDaniel Almeida bInterfaceProtocol: protocol, 173*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 174*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 175*e7e2296bSDaniel Almeida }) 176*e7e2296bSDaniel Almeida } 177*e7e2296bSDaniel Almeida 178*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE_INTERFACE_NUMBER` macro. 179*e7e2296bSDaniel Almeida pub const fn from_device_interface_number(vendor: u16, product: u16, number: u8) -> Self { 180*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 181*e7e2296bSDaniel Almeida match_flags: (bindings::USB_DEVICE_ID_MATCH_DEVICE 182*e7e2296bSDaniel Almeida | bindings::USB_DEVICE_ID_MATCH_INT_NUMBER) as u16, 183*e7e2296bSDaniel Almeida idVendor: vendor, 184*e7e2296bSDaniel Almeida idProduct: product, 185*e7e2296bSDaniel Almeida bInterfaceNumber: number, 186*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 187*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 188*e7e2296bSDaniel Almeida }) 189*e7e2296bSDaniel Almeida } 190*e7e2296bSDaniel Almeida 191*e7e2296bSDaniel Almeida /// Equivalent to C's `USB_DEVICE_AND_INTERFACE_INFO` macro. 192*e7e2296bSDaniel Almeida pub const fn from_device_and_interface_info( 193*e7e2296bSDaniel Almeida vendor: u16, 194*e7e2296bSDaniel Almeida product: u16, 195*e7e2296bSDaniel Almeida class: u8, 196*e7e2296bSDaniel Almeida subclass: u8, 197*e7e2296bSDaniel Almeida protocol: u8, 198*e7e2296bSDaniel Almeida ) -> Self { 199*e7e2296bSDaniel Almeida Self(bindings::usb_device_id { 200*e7e2296bSDaniel Almeida match_flags: (bindings::USB_DEVICE_ID_MATCH_INT_INFO 201*e7e2296bSDaniel Almeida | bindings::USB_DEVICE_ID_MATCH_DEVICE) as u16, 202*e7e2296bSDaniel Almeida idVendor: vendor, 203*e7e2296bSDaniel Almeida idProduct: product, 204*e7e2296bSDaniel Almeida bInterfaceClass: class, 205*e7e2296bSDaniel Almeida bInterfaceSubClass: subclass, 206*e7e2296bSDaniel Almeida bInterfaceProtocol: protocol, 207*e7e2296bSDaniel Almeida // SAFETY: It is safe to use all zeroes for the other fields of `usb_device_id`. 208*e7e2296bSDaniel Almeida ..unsafe { MaybeUninit::zeroed().assume_init() } 209*e7e2296bSDaniel Almeida }) 210*e7e2296bSDaniel Almeida } 211*e7e2296bSDaniel Almeida } 212*e7e2296bSDaniel Almeida 213*e7e2296bSDaniel Almeida // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `usb_device_id` and does not add 214*e7e2296bSDaniel Almeida // additional invariants, so it's safe to transmute to `RawType`. 215*e7e2296bSDaniel Almeida unsafe impl RawDeviceId for DeviceId { 216*e7e2296bSDaniel Almeida type RawType = bindings::usb_device_id; 217*e7e2296bSDaniel Almeida } 218*e7e2296bSDaniel Almeida 219*e7e2296bSDaniel Almeida // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_info` field. 220*e7e2296bSDaniel Almeida unsafe impl RawDeviceIdIndex for DeviceId { 221*e7e2296bSDaniel Almeida const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::usb_device_id, driver_info); 222*e7e2296bSDaniel Almeida 223*e7e2296bSDaniel Almeida fn index(&self) -> usize { 224*e7e2296bSDaniel Almeida self.0.driver_info 225*e7e2296bSDaniel Almeida } 226*e7e2296bSDaniel Almeida } 227*e7e2296bSDaniel Almeida 228*e7e2296bSDaniel Almeida /// [`IdTable`](kernel::device_id::IdTable) type for USB. 229*e7e2296bSDaniel Almeida pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 230*e7e2296bSDaniel Almeida 231*e7e2296bSDaniel Almeida /// Create a USB `IdTable` with its alias for modpost. 232*e7e2296bSDaniel Almeida #[macro_export] 233*e7e2296bSDaniel Almeida macro_rules! usb_device_table { 234*e7e2296bSDaniel Almeida ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 235*e7e2296bSDaniel Almeida const $table_name: $crate::device_id::IdArray< 236*e7e2296bSDaniel Almeida $crate::usb::DeviceId, 237*e7e2296bSDaniel Almeida $id_info_type, 238*e7e2296bSDaniel Almeida { $table_data.len() }, 239*e7e2296bSDaniel Almeida > = $crate::device_id::IdArray::new($table_data); 240*e7e2296bSDaniel Almeida 241*e7e2296bSDaniel Almeida $crate::module_device_table!("usb", $module_table_name, $table_name); 242*e7e2296bSDaniel Almeida }; 243*e7e2296bSDaniel Almeida } 244*e7e2296bSDaniel Almeida 245*e7e2296bSDaniel Almeida /// The USB driver trait. 246*e7e2296bSDaniel Almeida /// 247*e7e2296bSDaniel Almeida /// # Examples 248*e7e2296bSDaniel Almeida /// 249*e7e2296bSDaniel Almeida ///``` 250*e7e2296bSDaniel Almeida /// # use kernel::{bindings, device::Core, usb}; 251*e7e2296bSDaniel Almeida /// use kernel::prelude::*; 252*e7e2296bSDaniel Almeida /// 253*e7e2296bSDaniel Almeida /// struct MyDriver; 254*e7e2296bSDaniel Almeida /// 255*e7e2296bSDaniel Almeida /// kernel::usb_device_table!( 256*e7e2296bSDaniel Almeida /// USB_TABLE, 257*e7e2296bSDaniel Almeida /// MODULE_USB_TABLE, 258*e7e2296bSDaniel Almeida /// <MyDriver as usb::Driver>::IdInfo, 259*e7e2296bSDaniel Almeida /// [ 260*e7e2296bSDaniel Almeida /// (usb::DeviceId::from_id(0x1234, 0x5678), ()), 261*e7e2296bSDaniel Almeida /// (usb::DeviceId::from_id(0xabcd, 0xef01), ()), 262*e7e2296bSDaniel Almeida /// ] 263*e7e2296bSDaniel Almeida /// ); 264*e7e2296bSDaniel Almeida /// 265*e7e2296bSDaniel Almeida /// impl usb::Driver for MyDriver { 266*e7e2296bSDaniel Almeida /// type IdInfo = (); 267*e7e2296bSDaniel Almeida /// const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE; 268*e7e2296bSDaniel Almeida /// 269*e7e2296bSDaniel Almeida /// fn probe( 270*e7e2296bSDaniel Almeida /// _interface: &usb::Interface<Core>, 271*e7e2296bSDaniel Almeida /// _id: &usb::DeviceId, 272*e7e2296bSDaniel Almeida /// _info: &Self::IdInfo, 273*e7e2296bSDaniel Almeida /// ) -> Result<Pin<KBox<Self>>> { 274*e7e2296bSDaniel Almeida /// Err(ENODEV) 275*e7e2296bSDaniel Almeida /// } 276*e7e2296bSDaniel Almeida /// 277*e7e2296bSDaniel Almeida /// fn disconnect(_interface: &usb::Interface<Core>, _data: Pin<&Self>) {} 278*e7e2296bSDaniel Almeida /// } 279*e7e2296bSDaniel Almeida ///``` 280*e7e2296bSDaniel Almeida pub trait Driver { 281*e7e2296bSDaniel Almeida /// The type holding information about each one of the device ids supported by the driver. 282*e7e2296bSDaniel Almeida type IdInfo: 'static; 283*e7e2296bSDaniel Almeida 284*e7e2296bSDaniel Almeida /// The table of device ids supported by the driver. 285*e7e2296bSDaniel Almeida const ID_TABLE: IdTable<Self::IdInfo>; 286*e7e2296bSDaniel Almeida 287*e7e2296bSDaniel Almeida /// USB driver probe. 288*e7e2296bSDaniel Almeida /// 289*e7e2296bSDaniel Almeida /// Called when a new USB interface is bound to this driver. 290*e7e2296bSDaniel Almeida /// Implementers should attempt to initialize the interface here. 291*e7e2296bSDaniel Almeida fn probe( 292*e7e2296bSDaniel Almeida interface: &Interface<device::Core>, 293*e7e2296bSDaniel Almeida id: &DeviceId, 294*e7e2296bSDaniel Almeida id_info: &Self::IdInfo, 295*e7e2296bSDaniel Almeida ) -> Result<Pin<KBox<Self>>>; 296*e7e2296bSDaniel Almeida 297*e7e2296bSDaniel Almeida /// USB driver disconnect. 298*e7e2296bSDaniel Almeida /// 299*e7e2296bSDaniel Almeida /// Called when the USB interface is about to be unbound from this driver. 300*e7e2296bSDaniel Almeida fn disconnect(interface: &Interface<device::Core>, data: Pin<&Self>); 301*e7e2296bSDaniel Almeida } 302*e7e2296bSDaniel Almeida 303*e7e2296bSDaniel Almeida /// A USB interface. 304*e7e2296bSDaniel Almeida /// 305*e7e2296bSDaniel Almeida /// This structure represents the Rust abstraction for a C [`struct usb_interface`]. 306*e7e2296bSDaniel Almeida /// The implementation abstracts the usage of a C [`struct usb_interface`] passed 307*e7e2296bSDaniel Almeida /// in from the C side. 308*e7e2296bSDaniel Almeida /// 309*e7e2296bSDaniel Almeida /// # Invariants 310*e7e2296bSDaniel Almeida /// 311*e7e2296bSDaniel Almeida /// An [`Interface`] instance represents a valid [`struct usb_interface`] created 312*e7e2296bSDaniel Almeida /// by the C portion of the kernel. 313*e7e2296bSDaniel Almeida /// 314*e7e2296bSDaniel Almeida /// [`struct usb_interface`]: https://www.kernel.org/doc/html/latest/driver-api/usb/usb.html#c.usb_interface 315*e7e2296bSDaniel Almeida #[repr(transparent)] 316*e7e2296bSDaniel Almeida pub struct Interface<Ctx: device::DeviceContext = device::Normal>( 317*e7e2296bSDaniel Almeida Opaque<bindings::usb_interface>, 318*e7e2296bSDaniel Almeida PhantomData<Ctx>, 319*e7e2296bSDaniel Almeida ); 320*e7e2296bSDaniel Almeida 321*e7e2296bSDaniel Almeida impl<Ctx: device::DeviceContext> Interface<Ctx> { 322*e7e2296bSDaniel Almeida fn as_raw(&self) -> *mut bindings::usb_interface { 323*e7e2296bSDaniel Almeida self.0.get() 324*e7e2296bSDaniel Almeida } 325*e7e2296bSDaniel Almeida } 326*e7e2296bSDaniel Almeida 327*e7e2296bSDaniel Almeida // SAFETY: `Interface` is a transparent wrapper of a type that doesn't depend on 328*e7e2296bSDaniel Almeida // `Interface`'s generic argument. 329*e7e2296bSDaniel Almeida kernel::impl_device_context_deref!(unsafe { Interface }); 330*e7e2296bSDaniel Almeida kernel::impl_device_context_into_aref!(Interface); 331*e7e2296bSDaniel Almeida 332*e7e2296bSDaniel Almeida impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Interface<Ctx> { 333*e7e2296bSDaniel Almeida fn as_ref(&self) -> &device::Device<Ctx> { 334*e7e2296bSDaniel Almeida // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid 335*e7e2296bSDaniel Almeida // `struct usb_interface`. 336*e7e2296bSDaniel Almeida let dev = unsafe { &raw mut ((*self.as_raw()).dev) }; 337*e7e2296bSDaniel Almeida 338*e7e2296bSDaniel Almeida // SAFETY: `dev` points to a valid `struct device`. 339*e7e2296bSDaniel Almeida unsafe { device::Device::from_raw(dev) } 340*e7e2296bSDaniel Almeida } 341*e7e2296bSDaniel Almeida } 342*e7e2296bSDaniel Almeida 343*e7e2296bSDaniel Almeida impl<Ctx: device::DeviceContext> AsRef<Device<Ctx>> for Interface<Ctx> { 344*e7e2296bSDaniel Almeida fn as_ref(&self) -> &Device<Ctx> { 345*e7e2296bSDaniel Almeida // SAFETY: `self.as_raw()` is valid by the type invariants. For a valid interface, 346*e7e2296bSDaniel Almeida // the helper should always return a valid USB device pointer. 347*e7e2296bSDaniel Almeida let usb_dev = unsafe { bindings::interface_to_usbdev(self.as_raw()) }; 348*e7e2296bSDaniel Almeida 349*e7e2296bSDaniel Almeida // SAFETY: The helper returns a valid interface pointer that shares the 350*e7e2296bSDaniel Almeida // same `DeviceContext`. 351*e7e2296bSDaniel Almeida unsafe { &*(usb_dev.cast()) } 352*e7e2296bSDaniel Almeida } 353*e7e2296bSDaniel Almeida } 354*e7e2296bSDaniel Almeida 355*e7e2296bSDaniel Almeida // SAFETY: Instances of `Interface` are always reference-counted. 356*e7e2296bSDaniel Almeida unsafe impl AlwaysRefCounted for Interface { 357*e7e2296bSDaniel Almeida fn inc_ref(&self) { 358*e7e2296bSDaniel Almeida // SAFETY: The invariants of `Interface` guarantee that `self.as_raw()` 359*e7e2296bSDaniel Almeida // returns a valid `struct usb_interface` pointer, for which we will 360*e7e2296bSDaniel Almeida // acquire a new refcount. 361*e7e2296bSDaniel Almeida unsafe { bindings::usb_get_intf(self.as_raw()) }; 362*e7e2296bSDaniel Almeida } 363*e7e2296bSDaniel Almeida 364*e7e2296bSDaniel Almeida unsafe fn dec_ref(obj: NonNull<Self>) { 365*e7e2296bSDaniel Almeida // SAFETY: The safety requirements guarantee that the refcount is non-zero. 366*e7e2296bSDaniel Almeida unsafe { bindings::usb_put_intf(obj.cast().as_ptr()) } 367*e7e2296bSDaniel Almeida } 368*e7e2296bSDaniel Almeida } 369*e7e2296bSDaniel Almeida 370*e7e2296bSDaniel Almeida // SAFETY: A `Interface` is always reference-counted and can be released from any thread. 371*e7e2296bSDaniel Almeida unsafe impl Send for Interface {} 372*e7e2296bSDaniel Almeida 373*e7e2296bSDaniel Almeida // SAFETY: It is safe to send a &Interface to another thread because we do not 374*e7e2296bSDaniel Almeida // allow any mutation through a shared reference. 375*e7e2296bSDaniel Almeida unsafe impl Sync for Interface {} 376*e7e2296bSDaniel Almeida 377*e7e2296bSDaniel Almeida /// A USB device. 378*e7e2296bSDaniel Almeida /// 379*e7e2296bSDaniel Almeida /// This structure represents the Rust abstraction for a C [`struct usb_device`]. 380*e7e2296bSDaniel Almeida /// The implementation abstracts the usage of a C [`struct usb_device`] passed in 381*e7e2296bSDaniel Almeida /// from the C side. 382*e7e2296bSDaniel Almeida /// 383*e7e2296bSDaniel Almeida /// # Invariants 384*e7e2296bSDaniel Almeida /// 385*e7e2296bSDaniel Almeida /// A [`Device`] instance represents a valid [`struct usb_device`] created by the C portion of the 386*e7e2296bSDaniel Almeida /// kernel. 387*e7e2296bSDaniel Almeida /// 388*e7e2296bSDaniel Almeida /// [`struct usb_device`]: https://www.kernel.org/doc/html/latest/driver-api/usb/usb.html#c.usb_device 389*e7e2296bSDaniel Almeida #[repr(transparent)] 390*e7e2296bSDaniel Almeida pub struct Device<Ctx: device::DeviceContext = device::Normal>( 391*e7e2296bSDaniel Almeida Opaque<bindings::usb_device>, 392*e7e2296bSDaniel Almeida PhantomData<Ctx>, 393*e7e2296bSDaniel Almeida ); 394*e7e2296bSDaniel Almeida 395*e7e2296bSDaniel Almeida impl<Ctx: device::DeviceContext> Device<Ctx> { 396*e7e2296bSDaniel Almeida fn as_raw(&self) -> *mut bindings::usb_device { 397*e7e2296bSDaniel Almeida self.0.get() 398*e7e2296bSDaniel Almeida } 399*e7e2296bSDaniel Almeida } 400*e7e2296bSDaniel Almeida 401*e7e2296bSDaniel Almeida // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic 402*e7e2296bSDaniel Almeida // argument. 403*e7e2296bSDaniel Almeida kernel::impl_device_context_deref!(unsafe { Device }); 404*e7e2296bSDaniel Almeida kernel::impl_device_context_into_aref!(Device); 405*e7e2296bSDaniel Almeida 406*e7e2296bSDaniel Almeida // SAFETY: Instances of `Device` are always reference-counted. 407*e7e2296bSDaniel Almeida unsafe impl AlwaysRefCounted for Device { 408*e7e2296bSDaniel Almeida fn inc_ref(&self) { 409*e7e2296bSDaniel Almeida // SAFETY: The invariants of `Device` guarantee that `self.as_raw()` 410*e7e2296bSDaniel Almeida // returns a valid `struct usb_device` pointer, for which we will 411*e7e2296bSDaniel Almeida // acquire a new refcount. 412*e7e2296bSDaniel Almeida unsafe { bindings::usb_get_dev(self.as_raw()) }; 413*e7e2296bSDaniel Almeida } 414*e7e2296bSDaniel Almeida 415*e7e2296bSDaniel Almeida unsafe fn dec_ref(obj: NonNull<Self>) { 416*e7e2296bSDaniel Almeida // SAFETY: The safety requirements guarantee that the refcount is non-zero. 417*e7e2296bSDaniel Almeida unsafe { bindings::usb_put_dev(obj.cast().as_ptr()) } 418*e7e2296bSDaniel Almeida } 419*e7e2296bSDaniel Almeida } 420*e7e2296bSDaniel Almeida 421*e7e2296bSDaniel Almeida impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> { 422*e7e2296bSDaniel Almeida fn as_ref(&self) -> &device::Device<Ctx> { 423*e7e2296bSDaniel Almeida // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid 424*e7e2296bSDaniel Almeida // `struct usb_device`. 425*e7e2296bSDaniel Almeida let dev = unsafe { &raw mut ((*self.as_raw()).dev) }; 426*e7e2296bSDaniel Almeida 427*e7e2296bSDaniel Almeida // SAFETY: `dev` points to a valid `struct device`. 428*e7e2296bSDaniel Almeida unsafe { device::Device::from_raw(dev) } 429*e7e2296bSDaniel Almeida } 430*e7e2296bSDaniel Almeida } 431*e7e2296bSDaniel Almeida 432*e7e2296bSDaniel Almeida // SAFETY: A `Device` is always reference-counted and can be released from any thread. 433*e7e2296bSDaniel Almeida unsafe impl Send for Device {} 434*e7e2296bSDaniel Almeida 435*e7e2296bSDaniel Almeida // SAFETY: It is safe to send a &Device to another thread because we do not 436*e7e2296bSDaniel Almeida // allow any mutation through a shared reference. 437*e7e2296bSDaniel Almeida unsafe impl Sync for Device {} 438*e7e2296bSDaniel Almeida 439*e7e2296bSDaniel Almeida /// Declares a kernel module that exposes a single USB driver. 440*e7e2296bSDaniel Almeida /// 441*e7e2296bSDaniel Almeida /// # Examples 442*e7e2296bSDaniel Almeida /// 443*e7e2296bSDaniel Almeida /// ```ignore 444*e7e2296bSDaniel Almeida /// module_usb_driver! { 445*e7e2296bSDaniel Almeida /// type: MyDriver, 446*e7e2296bSDaniel Almeida /// name: "Module name", 447*e7e2296bSDaniel Almeida /// author: ["Author name"], 448*e7e2296bSDaniel Almeida /// description: "Description", 449*e7e2296bSDaniel Almeida /// license: "GPL v2", 450*e7e2296bSDaniel Almeida /// } 451*e7e2296bSDaniel Almeida /// ``` 452*e7e2296bSDaniel Almeida #[macro_export] 453*e7e2296bSDaniel Almeida macro_rules! module_usb_driver { 454*e7e2296bSDaniel Almeida ($($f:tt)*) => { 455*e7e2296bSDaniel Almeida $crate::module_driver!(<T>, $crate::usb::Adapter<T>, { $($f)* }); 456*e7e2296bSDaniel Almeida } 457*e7e2296bSDaniel Almeida } 458