kernel/
usb.rs

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