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