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}