diff options
Diffstat (limited to 'samples')
-rw-r--r-- | samples/rust/Kconfig | 11 | ||||
-rw-r--r-- | samples/rust/Makefile | 1 | ||||
-rw-r--r-- | samples/rust/rust_driver_usb.rs | 47 | ||||
-rw-r--r-- | samples/rust/rust_misc_device.rs | 39 |
4 files changed, 94 insertions, 4 deletions
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 66360cdf048f..c376eb899b7a 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -105,6 +105,17 @@ config SAMPLE_RUST_DRIVER_PLATFORM If unsure, say N. +config SAMPLE_RUST_DRIVER_USB + tristate "USB Driver" + depends on USB = y && BROKEN + help + This option builds the Rust USB driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_usb. + + If unsure, say N. + config SAMPLE_RUST_DRIVER_FAUX tristate "Faux Driver" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 69ca01497b58..cf8422f8f219 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_SAMPLE_RUST_DEBUGFS_SCOPED) += rust_debugfs_scoped.o obj-$(CONFIG_SAMPLE_RUST_DMA) += rust_dma.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb.rs new file mode 100644 index 000000000000..5c396f421de7 --- /dev/null +++ b/samples/rust/rust_driver_usb.rs @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Collabora Ltd. + +//! Rust USB driver sample. + +use kernel::{device, device::Core, prelude::*, sync::aref::ARef, usb}; + +struct SampleDriver { + _intf: ARef<usb::Interface>, +} + +kernel::usb_device_table!( + USB_TABLE, + MODULE_USB_TABLE, + <SampleDriver as usb::Driver>::IdInfo, + [(usb::DeviceId::from_id(0x1234, 0x5678), ()),] +); + +impl usb::Driver for SampleDriver { + type IdInfo = (); + const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE; + + fn probe( + intf: &usb::Interface<Core>, + _id: &usb::DeviceId, + _info: &Self::IdInfo, + ) -> Result<Pin<KBox<Self>>> { + let dev: &device::Device<Core> = intf.as_ref(); + dev_info!(dev, "Rust USB driver sample probed\n"); + + let drvdata = KBox::new(Self { _intf: intf.into() }, GFP_KERNEL)?; + Ok(drvdata.into()) + } + + fn disconnect(intf: &usb::Interface<Core>, _data: Pin<&Self>) { + let dev: &device::Device<Core> = intf.as_ref(); + dev_info!(dev, "Rust USB driver sample disconnected\n"); + } +} + +kernel::module_usb_driver! { + type: SampleDriver, + name: "rust_driver_usb", + authors: ["Daniel Almeida"], + description: "Rust USB driver sample", + license: "GPL v2", +} diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs index e7ab77448f75..d69bc33dbd99 100644 --- a/samples/rust/rust_misc_device.rs +++ b/samples/rust/rust_misc_device.rs @@ -100,13 +100,13 @@ use core::pin::Pin; use kernel::{ c_str, device::Device, - fs::File, + fs::{File, Kiocb}, ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, + iov::{IovIterDest, IovIterSource}, miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration}, new_mutex, prelude::*, - sync::Mutex, - types::ARef, + sync::{aref::ARef, Mutex}, uaccess::{UserSlice, UserSliceReader, UserSliceWriter}, }; @@ -144,6 +144,7 @@ impl kernel::InPlaceModule for RustMiscDeviceModule { struct Inner { value: i32, + buffer: KVVec<u8>, } #[pin_data(PinnedDrop)] @@ -165,7 +166,10 @@ impl MiscDevice for RustMiscDevice { KBox::try_pin_init( try_pin_init! { RustMiscDevice { - inner <- new_mutex!( Inner{ value: 0_i32 } ), + inner <- new_mutex!(Inner { + value: 0_i32, + buffer: KVVec::new(), + }), dev: dev, } }, @@ -173,6 +177,33 @@ impl MiscDevice for RustMiscDevice { ) } + fn read_iter(mut kiocb: Kiocb<'_, Self::Ptr>, iov: &mut IovIterDest<'_>) -> Result<usize> { + let me = kiocb.file(); + dev_info!(me.dev, "Reading from Rust Misc Device Sample\n"); + + let inner = me.inner.lock(); + // Read the buffer contents, taking the file position into account. + let read = iov.simple_read_from_buffer(kiocb.ki_pos_mut(), &inner.buffer)?; + + Ok(read) + } + + fn write_iter(mut kiocb: Kiocb<'_, Self::Ptr>, iov: &mut IovIterSource<'_>) -> Result<usize> { + let me = kiocb.file(); + dev_info!(me.dev, "Writing to Rust Misc Device Sample\n"); + + let mut inner = me.inner.lock(); + + // Replace buffer contents. + inner.buffer.clear(); + let len = iov.copy_from_iter_vec(&mut inner.buffer, GFP_KERNEL)?; + + // Set position to zero so that future `read` calls will see the new contents. + *kiocb.ki_pos_mut() = 0; + + Ok(len) + } + fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result<isize> { dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n"); |