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