$ // SPDX-License-Identifier: GPL-2.0\n// Sample Rust PCIe driver for Linux 6.10, targeting Rust 1.85\n// Demonstrates core driver lifecycle: probe, -weight: 500;">remove, and error handling\nuse kernel::{\n prelude::*,\n device::Device,\n pci::{PciDevice, PciDriver, PciId},\n sync::Mutex,\n error::KernelError,\n str::CStr,\n};\n\n// Define driver private data stored in struct device::DriverData\nstruct MyPcieDriverData {\n bar0: Mutex<*mut u8>, // BAR0 mapped address, wrapped in Mutex for sync\n dev: Device,\n}\n\n// Implement PciDriver trait for our driver\nstruct MyPcieDriver;\nimpl PciDriver for MyPcieDriver {\n type Data = MyPcieDriverData;\n\n // Probe function: called when device matches our ID table\n fn probe(\n pdev: &PciDevice,\n _id: &PciId,\n ) -> Result {\n pr_info!(\"my_pcie: Probing device {:?}\\n\", pdev);\n\n // Enable device: standard PCIe -weight: 500;">enable, returns error if failed\n pdev.-weight: 500;">enable().map_err(|e| {\n pr_err!(\"my_pcie: Failed to -weight: 500;">enable PCIe device: {:?}\\n\", e);\n KernelError::EINVAL\n })?;\n\n // Request BAR0 region, ensure no conflicts\n let bar0_res = pdev.request_region(0, \"my_pcie_bar0\").map_err(|e| {\n pr_err!(\"my_pcie: Failed to request BAR0: {:?}\\n\", e);\n KernelError::EBUSY\n })?;\n\n // Map BAR0 to kernel virtual address\n let bar0_addr = pdev.ioremap(bar0_res).map_err(|e| {\n pr_err!(\"my_pcie: Failed to ioremap BAR0: {:?}\\n\", e);\n KernelError::ENOMEM\n }? as *mut u8;\n\n // Check device revision ID for compatibility\n let rev = pdev.revision().map_err(|e| {\n pr_err!(\"my_pcie: Failed to read revision ID: {:?}\\n\", e);\n KernelError::EIO\n })?;\n\n if rev < 0x02 {\n pr_err!(\"my_pcie: Unsupported revision ID: 0x{:x}\\n\", rev);\n return Err(KernelError::ENODEV);\n }\n\n // Initialize driver private data\n let data = MyPcieDriverData {\n bar0: Mutex::new(bar0_addr),\n dev: pdev.dev().clone(),\n };\n\n pr_info!(\"my_pcie: Probe succeeded for {:?}\\n\", pdev);\n Ok(data)\n }\n\n // Remove function: called when device is unplugged or driver unloaded\n fn -weight: 500;">remove(data: &mut Self::Data) -> Result {\n pr_info!(\"my_pcie: Removing device\\n\");\n\n // Unmap BAR0: get lock, then unmap\n let bar0_addr = *data.bar0.lock();\n if !bar0_addr.is_null() {\n // SAFETY: bar0_addr was mapped via ioremap in probe\n unsafe { pdev.iounmap(bar0_addr) };\n }\n\n pr_info!(\"my_pcie: Remove completed\\n\");\n Ok(())\n }\n}\n\n// Register PCIe ID table: match any device with vendor 0x1234, device 0x5678\nconst ID_TABLE: [PciId; 2] = [\n PciId::new(0x1234, 0x5678, None),\n PciId::null(), // Terminator\n];\n\n// Register driver with kernel PCI subsystem\nkernel::pci_driver! {\n type: MyPcieDriver,\n name: \"my_pcie\",\n id_table: &ID_TABLE,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust PCIe driver for Linux 6.10, targeting Rust 1.85\n// Demonstrates core driver lifecycle: probe, -weight: 500;">remove, and error handling\nuse kernel::{\n prelude::*,\n device::Device,\n pci::{PciDevice, PciDriver, PciId},\n sync::Mutex,\n error::KernelError,\n str::CStr,\n};\n\n// Define driver private data stored in struct device::DriverData\nstruct MyPcieDriverData {\n bar0: Mutex<*mut u8>, // BAR0 mapped address, wrapped in Mutex for sync\n dev: Device,\n}\n\n// Implement PciDriver trait for our driver\nstruct MyPcieDriver;\nimpl PciDriver for MyPcieDriver {\n type Data = MyPcieDriverData;\n\n // Probe function: called when device matches our ID table\n fn probe(\n pdev: &PciDevice,\n _id: &PciId,\n ) -> Result {\n pr_info!(\"my_pcie: Probing device {:?}\\n\", pdev);\n\n // Enable device: standard PCIe -weight: 500;">enable, returns error if failed\n pdev.-weight: 500;">enable().map_err(|e| {\n pr_err!(\"my_pcie: Failed to -weight: 500;">enable PCIe device: {:?}\\n\", e);\n KernelError::EINVAL\n })?;\n\n // Request BAR0 region, ensure no conflicts\n let bar0_res = pdev.request_region(0, \"my_pcie_bar0\").map_err(|e| {\n pr_err!(\"my_pcie: Failed to request BAR0: {:?}\\n\", e);\n KernelError::EBUSY\n })?;\n\n // Map BAR0 to kernel virtual address\n let bar0_addr = pdev.ioremap(bar0_res).map_err(|e| {\n pr_err!(\"my_pcie: Failed to ioremap BAR0: {:?}\\n\", e);\n KernelError::ENOMEM\n }? as *mut u8;\n\n // Check device revision ID for compatibility\n let rev = pdev.revision().map_err(|e| {\n pr_err!(\"my_pcie: Failed to read revision ID: {:?}\\n\", e);\n KernelError::EIO\n })?;\n\n if rev < 0x02 {\n pr_err!(\"my_pcie: Unsupported revision ID: 0x{:x}\\n\", rev);\n return Err(KernelError::ENODEV);\n }\n\n // Initialize driver private data\n let data = MyPcieDriverData {\n bar0: Mutex::new(bar0_addr),\n dev: pdev.dev().clone(),\n };\n\n pr_info!(\"my_pcie: Probe succeeded for {:?}\\n\", pdev);\n Ok(data)\n }\n\n // Remove function: called when device is unplugged or driver unloaded\n fn -weight: 500;">remove(data: &mut Self::Data) -> Result {\n pr_info!(\"my_pcie: Removing device\\n\");\n\n // Unmap BAR0: get lock, then unmap\n let bar0_addr = *data.bar0.lock();\n if !bar0_addr.is_null() {\n // SAFETY: bar0_addr was mapped via ioremap in probe\n unsafe { pdev.iounmap(bar0_addr) };\n }\n\n pr_info!(\"my_pcie: Remove completed\\n\");\n Ok(())\n }\n}\n\n// Register PCIe ID table: match any device with vendor 0x1234, device 0x5678\nconst ID_TABLE: [PciId; 2] = [\n PciId::new(0x1234, 0x5678, None),\n PciId::null(), // Terminator\n];\n\n// Register driver with kernel PCI subsystem\nkernel::pci_driver! {\n type: MyPcieDriver,\n name: \"my_pcie\",\n id_table: &ID_TABLE,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust PCIe driver for Linux 6.10, targeting Rust 1.85\n// Demonstrates core driver lifecycle: probe, -weight: 500;">remove, and error handling\nuse kernel::{\n prelude::*,\n device::Device,\n pci::{PciDevice, PciDriver, PciId},\n sync::Mutex,\n error::KernelError,\n str::CStr,\n};\n\n// Define driver private data stored in struct device::DriverData\nstruct MyPcieDriverData {\n bar0: Mutex<*mut u8>, // BAR0 mapped address, wrapped in Mutex for sync\n dev: Device,\n}\n\n// Implement PciDriver trait for our driver\nstruct MyPcieDriver;\nimpl PciDriver for MyPcieDriver {\n type Data = MyPcieDriverData;\n\n // Probe function: called when device matches our ID table\n fn probe(\n pdev: &PciDevice,\n _id: &PciId,\n ) -> Result {\n pr_info!(\"my_pcie: Probing device {:?}\\n\", pdev);\n\n // Enable device: standard PCIe -weight: 500;">enable, returns error if failed\n pdev.-weight: 500;">enable().map_err(|e| {\n pr_err!(\"my_pcie: Failed to -weight: 500;">enable PCIe device: {:?}\\n\", e);\n KernelError::EINVAL\n })?;\n\n // Request BAR0 region, ensure no conflicts\n let bar0_res = pdev.request_region(0, \"my_pcie_bar0\").map_err(|e| {\n pr_err!(\"my_pcie: Failed to request BAR0: {:?}\\n\", e);\n KernelError::EBUSY\n })?;\n\n // Map BAR0 to kernel virtual address\n let bar0_addr = pdev.ioremap(bar0_res).map_err(|e| {\n pr_err!(\"my_pcie: Failed to ioremap BAR0: {:?}\\n\", e);\n KernelError::ENOMEM\n }? as *mut u8;\n\n // Check device revision ID for compatibility\n let rev = pdev.revision().map_err(|e| {\n pr_err!(\"my_pcie: Failed to read revision ID: {:?}\\n\", e);\n KernelError::EIO\n })?;\n\n if rev < 0x02 {\n pr_err!(\"my_pcie: Unsupported revision ID: 0x{:x}\\n\", rev);\n return Err(KernelError::ENODEV);\n }\n\n // Initialize driver private data\n let data = MyPcieDriverData {\n bar0: Mutex::new(bar0_addr),\n dev: pdev.dev().clone(),\n };\n\n pr_info!(\"my_pcie: Probe succeeded for {:?}\\n\", pdev);\n Ok(data)\n }\n\n // Remove function: called when device is unplugged or driver unloaded\n fn -weight: 500;">remove(data: &mut Self::Data) -> Result {\n pr_info!(\"my_pcie: Removing device\\n\");\n\n // Unmap BAR0: get lock, then unmap\n let bar0_addr = *data.bar0.lock();\n if !bar0_addr.is_null() {\n // SAFETY: bar0_addr was mapped via ioremap in probe\n unsafe { pdev.iounmap(bar0_addr) };\n }\n\n pr_info!(\"my_pcie: Remove completed\\n\");\n Ok(())\n }\n}\n\n// Register PCIe ID table: match any device with vendor 0x1234, device 0x5678\nconst ID_TABLE: [PciId; 2] = [\n PciId::new(0x1234, 0x5678, None),\n PciId::null(), // Terminator\n];\n\n// Register driver with kernel PCI subsystem\nkernel::pci_driver! {\n type: MyPcieDriver,\n name: \"my_pcie\",\n id_table: &ID_TABLE,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust USB 3.2 driver for Linux 6.10, Rust 1.85\n// Demonstrates URB (USB Request Block) handling, async I/O, and error recovery\nuse kernel::{\n prelude::*,\n usb::{UsbDevice, UsbDriver, UsbId, Urb, UrbFlags, PipeDirection},\n sync::Completion,\n error::KernelError,\n time::Duration,\n};\n\n// Driver private data for USB device\nstruct MyUsbDriverData {\n udev: UsbDevice,\n in_urb: Option,\n out_urb: Option,\n completion: Completion,\n}\n\n// USB driver implementation\nstruct MyUsbDriver;\nimpl UsbDriver for MyUsbDriver {\n type Data = MyUsbDriverData;\n\n // Probe function for USB device\n fn probe(udev: &UsbDevice, id: &UsbId) -> Result {\n pr_info!(\"my_usb: Probing USB device {:?} (vendor 0x{:x}, product 0x{:x})\\n\",\n udev, id.vendor_id(), id.product_id());\n\n // Check device speed: require USB 3.2 SuperSpeed\n if udev.speed() != kernel::usb::Speed::SuperSpeedPlus {\n pr_err!(\"my_usb: Unsupported USB speed: {:?}\\n\", udev.speed());\n return Err(KernelError::ENODEV);\n }\n\n // Allocate IN URB for bulk transfers\n let in_urb = Urb::new(udev, PipeDirection::In, 0x81, 4096).map_err(|e| {\n pr_err!(\"my_usb: Failed to allocate IN URB: {:?}\\n\", e);\n KernelError::ENOMEM\n })?;\n\n // Allocate OUT URB for bulk transfers\n let out_urb = Urb::new(udev, PipeDirection::Out, 0x02, 4096).map_err(|e| {\n pr_err!(\"my_usb: Failed to allocate OUT URB: {:?}\\n\", e);\n KernelError::ENOMEM\n })?;\n\n // Initialize completion for async URB callbacks\n let completion = Completion::new();\n\n // Register URB completion callback\n in_urb.set_completion_callback(|urb| {\n let data = urb.context::().unwrap();\n pr_info!(\"my_usb: IN URB completed with -weight: 500;">status {:?}\\n\", urb.-weight: 500;">status());\n data.completion.complete();\n });\n\n let data = MyUsbDriverData {\n udev: udev.clone(),\n in_urb: Some(in_urb),\n out_urb: Some(out_urb),\n completion,\n };\n\n // Submit initial IN URB to -weight: 500;">start listening\n if let Some(ref urb) = data.in_urb {\n urb.submit().map_err(|e| {\n pr_err!(\"my_usb: Failed to submit IN URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n pr_info!(\"my_usb: Probe succeeded for {:?}\\n\", udev);\n Ok(data)\n }\n\n // Disconnect function: called when USB device is unplugged\n fn disconnect(data: &mut Self::Data) -> Result {\n pr_info!(\"my_usb: Disconnecting USB device\\n\");\n\n // Cancel all pending URBs\n if let Some(ref urb) = data.in_urb {\n urb.cancel().map_err(|e| {\n pr_err!(\"my_usb: Failed to cancel IN URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n if let Some(ref urb) = data.out_urb {\n urb.cancel().map_err(|e| {\n pr_err!(\"my_usb: Failed to cancel OUT URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n // Wait for completion to ensure no pending callbacks\n data.completion.wait(Duration::from_secs(5)).map_err(|_| {\n pr_err!(\"my_usb: Timeout waiting for URB completion\\n\");\n KernelError::ETIMEDOUT\n })?;\n\n pr_info!(\"my_usb: Disconnect completed\\n\");\n Ok(())\n }\n}\n\n// USB ID table: match vendor 0xabcd, product 0x1234\nconst USB_ID_TABLE: [UsbId; 2] = [\n UsbId::new(0xabcd, 0x1234, None),\n UsbId::null(),\n];\n\n// Register USB driver with kernel\nkernel::usb_driver! {\n type: MyUsbDriver,\n name: \"my_usb\",\n id_table: &USB_ID_TABLE,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust USB 3.2 driver for Linux 6.10, Rust 1.85\n// Demonstrates URB (USB Request Block) handling, async I/O, and error recovery\nuse kernel::{\n prelude::*,\n usb::{UsbDevice, UsbDriver, UsbId, Urb, UrbFlags, PipeDirection},\n sync::Completion,\n error::KernelError,\n time::Duration,\n};\n\n// Driver private data for USB device\nstruct MyUsbDriverData {\n udev: UsbDevice,\n in_urb: Option,\n out_urb: Option,\n completion: Completion,\n}\n\n// USB driver implementation\nstruct MyUsbDriver;\nimpl UsbDriver for MyUsbDriver {\n type Data = MyUsbDriverData;\n\n // Probe function for USB device\n fn probe(udev: &UsbDevice, id: &UsbId) -> Result {\n pr_info!(\"my_usb: Probing USB device {:?} (vendor 0x{:x}, product 0x{:x})\\n\",\n udev, id.vendor_id(), id.product_id());\n\n // Check device speed: require USB 3.2 SuperSpeed\n if udev.speed() != kernel::usb::Speed::SuperSpeedPlus {\n pr_err!(\"my_usb: Unsupported USB speed: {:?}\\n\", udev.speed());\n return Err(KernelError::ENODEV);\n }\n\n // Allocate IN URB for bulk transfers\n let in_urb = Urb::new(udev, PipeDirection::In, 0x81, 4096).map_err(|e| {\n pr_err!(\"my_usb: Failed to allocate IN URB: {:?}\\n\", e);\n KernelError::ENOMEM\n })?;\n\n // Allocate OUT URB for bulk transfers\n let out_urb = Urb::new(udev, PipeDirection::Out, 0x02, 4096).map_err(|e| {\n pr_err!(\"my_usb: Failed to allocate OUT URB: {:?}\\n\", e);\n KernelError::ENOMEM\n })?;\n\n // Initialize completion for async URB callbacks\n let completion = Completion::new();\n\n // Register URB completion callback\n in_urb.set_completion_callback(|urb| {\n let data = urb.context::().unwrap();\n pr_info!(\"my_usb: IN URB completed with -weight: 500;">status {:?}\\n\", urb.-weight: 500;">status());\n data.completion.complete();\n });\n\n let data = MyUsbDriverData {\n udev: udev.clone(),\n in_urb: Some(in_urb),\n out_urb: Some(out_urb),\n completion,\n };\n\n // Submit initial IN URB to -weight: 500;">start listening\n if let Some(ref urb) = data.in_urb {\n urb.submit().map_err(|e| {\n pr_err!(\"my_usb: Failed to submit IN URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n pr_info!(\"my_usb: Probe succeeded for {:?}\\n\", udev);\n Ok(data)\n }\n\n // Disconnect function: called when USB device is unplugged\n fn disconnect(data: &mut Self::Data) -> Result {\n pr_info!(\"my_usb: Disconnecting USB device\\n\");\n\n // Cancel all pending URBs\n if let Some(ref urb) = data.in_urb {\n urb.cancel().map_err(|e| {\n pr_err!(\"my_usb: Failed to cancel IN URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n if let Some(ref urb) = data.out_urb {\n urb.cancel().map_err(|e| {\n pr_err!(\"my_usb: Failed to cancel OUT URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n // Wait for completion to ensure no pending callbacks\n data.completion.wait(Duration::from_secs(5)).map_err(|_| {\n pr_err!(\"my_usb: Timeout waiting for URB completion\\n\");\n KernelError::ETIMEDOUT\n })?;\n\n pr_info!(\"my_usb: Disconnect completed\\n\");\n Ok(())\n }\n}\n\n// USB ID table: match vendor 0xabcd, product 0x1234\nconst USB_ID_TABLE: [UsbId; 2] = [\n UsbId::new(0xabcd, 0x1234, None),\n UsbId::null(),\n];\n\n// Register USB driver with kernel\nkernel::usb_driver! {\n type: MyUsbDriver,\n name: \"my_usb\",\n id_table: &USB_ID_TABLE,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust USB 3.2 driver for Linux 6.10, Rust 1.85\n// Demonstrates URB (USB Request Block) handling, async I/O, and error recovery\nuse kernel::{\n prelude::*,\n usb::{UsbDevice, UsbDriver, UsbId, Urb, UrbFlags, PipeDirection},\n sync::Completion,\n error::KernelError,\n time::Duration,\n};\n\n// Driver private data for USB device\nstruct MyUsbDriverData {\n udev: UsbDevice,\n in_urb: Option,\n out_urb: Option,\n completion: Completion,\n}\n\n// USB driver implementation\nstruct MyUsbDriver;\nimpl UsbDriver for MyUsbDriver {\n type Data = MyUsbDriverData;\n\n // Probe function for USB device\n fn probe(udev: &UsbDevice, id: &UsbId) -> Result {\n pr_info!(\"my_usb: Probing USB device {:?} (vendor 0x{:x}, product 0x{:x})\\n\",\n udev, id.vendor_id(), id.product_id());\n\n // Check device speed: require USB 3.2 SuperSpeed\n if udev.speed() != kernel::usb::Speed::SuperSpeedPlus {\n pr_err!(\"my_usb: Unsupported USB speed: {:?}\\n\", udev.speed());\n return Err(KernelError::ENODEV);\n }\n\n // Allocate IN URB for bulk transfers\n let in_urb = Urb::new(udev, PipeDirection::In, 0x81, 4096).map_err(|e| {\n pr_err!(\"my_usb: Failed to allocate IN URB: {:?}\\n\", e);\n KernelError::ENOMEM\n })?;\n\n // Allocate OUT URB for bulk transfers\n let out_urb = Urb::new(udev, PipeDirection::Out, 0x02, 4096).map_err(|e| {\n pr_err!(\"my_usb: Failed to allocate OUT URB: {:?}\\n\", e);\n KernelError::ENOMEM\n })?;\n\n // Initialize completion for async URB callbacks\n let completion = Completion::new();\n\n // Register URB completion callback\n in_urb.set_completion_callback(|urb| {\n let data = urb.context::().unwrap();\n pr_info!(\"my_usb: IN URB completed with -weight: 500;">status {:?}\\n\", urb.-weight: 500;">status());\n data.completion.complete();\n });\n\n let data = MyUsbDriverData {\n udev: udev.clone(),\n in_urb: Some(in_urb),\n out_urb: Some(out_urb),\n completion,\n };\n\n // Submit initial IN URB to -weight: 500;">start listening\n if let Some(ref urb) = data.in_urb {\n urb.submit().map_err(|e| {\n pr_err!(\"my_usb: Failed to submit IN URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n pr_info!(\"my_usb: Probe succeeded for {:?}\\n\", udev);\n Ok(data)\n }\n\n // Disconnect function: called when USB device is unplugged\n fn disconnect(data: &mut Self::Data) -> Result {\n pr_info!(\"my_usb: Disconnecting USB device\\n\");\n\n // Cancel all pending URBs\n if let Some(ref urb) = data.in_urb {\n urb.cancel().map_err(|e| {\n pr_err!(\"my_usb: Failed to cancel IN URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n if let Some(ref urb) = data.out_urb {\n urb.cancel().map_err(|e| {\n pr_err!(\"my_usb: Failed to cancel OUT URB: {:?}\\n\", e);\n KernelError::EIO\n })?;\n }\n\n // Wait for completion to ensure no pending callbacks\n data.completion.wait(Duration::from_secs(5)).map_err(|_| {\n pr_err!(\"my_usb: Timeout waiting for URB completion\\n\");\n KernelError::ETIMEDOUT\n })?;\n\n pr_info!(\"my_usb: Disconnect completed\\n\");\n Ok(())\n }\n}\n\n// USB ID table: match vendor 0xabcd, product 0x1234\nconst USB_ID_TABLE: [UsbId; 2] = [\n UsbId::new(0xabcd, 0x1234, None),\n UsbId::null(),\n];\n\n// Register USB driver with kernel\nkernel::usb_driver! {\n type: MyUsbDriver,\n name: \"my_usb\",\n id_table: &USB_ID_TABLE,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust character device driver for Linux 6.10, Rust 1.85\n// Demonstrates ioctl handling, user-kernel copy, spinlock synchronization\nuse kernel::{\n prelude::*,\n cdev::{Cdev, CdevRegistration},\n file::{File, FileOperations},\n ioctl::{IoctlCommand, IoctlHandler},\n sync::Spinlock,\n user_ptr::{UserSlice, UserSliceMut},\n error::KernelError,\n};\n\n// Define ioctl command: 0xED is a free magic number for example\nconst IOCTL_GET_VERSION: u32 = kernel::ioctl!(_IOR('E', 0xD0, 4));\nconst IOCTL_SET_CONFIG: u32 = kernel::ioctl!(_IOW('E', 0xD1, 16));\n\n// Driver private data: protected by spinlock for SMP safety\nstruct MyCharDriverData {\n version: u32,\n config: Spinlock<[u8; 16]>,\n}\n\n// Implement FileOperations for our char device\nstruct MyCharFile;\nimpl FileOperations for MyCharFile {\n type Data = &'static MyCharDriverData;\n\n fn open(data: &'static MyCharDriverData, _file: &File) -> Result {\n pr_info!(\"my_char: Opening char device\\n\");\n Ok(data)\n }\n\n fn ioctl(\n data: &MyCharDriverData,\n _file: &File,\n cmd: IoctlCommand,\n ) -> Result {\n match cmd.cmd() {\n IOCTL_GET_VERSION => {\n pr_info!(\"my_char: Handling IOCTL_GET_VERSION\\n\");\n let mut user_buf = UserSliceMut::new(cmd.arg() as *mut u8, 4);\n user_buf.write(&data.version.to_ne_bytes()).map_err(|e| {\n pr_err!(\"my_char: Failed to copy version to user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n Ok(0)\n }\n IOCTL_SET_CONFIG => {\n pr_info!(\"my_char: Handling IOCTL_SET_CONFIG\\n\");\n let mut user_buf = UserSlice::new(cmd.arg() as *const u8, 16);\n let mut new_config = [0u8; 16];\n user_buf.read(&mut new_config).map_err(|e| {\n pr_err!(\"my_char: Failed to copy config from user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n\n // Update config with spinlock protection\n let mut config = data.config.lock();\n *config = new_config;\n Ok(0)\n }\n _ => {\n pr_err!(\"my_char: Unknown ioctl command 0x{:x}\\n\", cmd.cmd());\n Err(KernelError::ENOTTY)\n }\n }\n }\n\n fn read(\n data: &MyCharDriverData,\n _file: &File,\n buf: &mut UserSliceMut,\n _offset: u64,\n ) -> Result {\n pr_info!(\"my_char: Handling read\\n\");\n let config = data.config.lock();\n let len = buf.len().min(config.len());\n buf.write(&config[..len]).map_err(|e| {\n pr_err!(\"my_char: Failed to read config to user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n Ok(len)\n }\n}\n\n// Static driver data: initialized at module load\nstatic DRIVER_DATA: MyCharDriverData = MyCharDriverData {\n version: 0x0100, // Version 1.0\n config: Spinlock::new([0u8; 16]),\n};\n\n// Register character device\nkernel::cdev_register! {\n name: \"my_char\",\n major: 0, // Dynamic major number\n minor: 0,\n count: 1,\n file_ops: MyCharFile,\n data: &DRIVER_DATA,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust character device driver for Linux 6.10, Rust 1.85\n// Demonstrates ioctl handling, user-kernel copy, spinlock synchronization\nuse kernel::{\n prelude::*,\n cdev::{Cdev, CdevRegistration},\n file::{File, FileOperations},\n ioctl::{IoctlCommand, IoctlHandler},\n sync::Spinlock,\n user_ptr::{UserSlice, UserSliceMut},\n error::KernelError,\n};\n\n// Define ioctl command: 0xED is a free magic number for example\nconst IOCTL_GET_VERSION: u32 = kernel::ioctl!(_IOR('E', 0xD0, 4));\nconst IOCTL_SET_CONFIG: u32 = kernel::ioctl!(_IOW('E', 0xD1, 16));\n\n// Driver private data: protected by spinlock for SMP safety\nstruct MyCharDriverData {\n version: u32,\n config: Spinlock<[u8; 16]>,\n}\n\n// Implement FileOperations for our char device\nstruct MyCharFile;\nimpl FileOperations for MyCharFile {\n type Data = &'static MyCharDriverData;\n\n fn open(data: &'static MyCharDriverData, _file: &File) -> Result {\n pr_info!(\"my_char: Opening char device\\n\");\n Ok(data)\n }\n\n fn ioctl(\n data: &MyCharDriverData,\n _file: &File,\n cmd: IoctlCommand,\n ) -> Result {\n match cmd.cmd() {\n IOCTL_GET_VERSION => {\n pr_info!(\"my_char: Handling IOCTL_GET_VERSION\\n\");\n let mut user_buf = UserSliceMut::new(cmd.arg() as *mut u8, 4);\n user_buf.write(&data.version.to_ne_bytes()).map_err(|e| {\n pr_err!(\"my_char: Failed to copy version to user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n Ok(0)\n }\n IOCTL_SET_CONFIG => {\n pr_info!(\"my_char: Handling IOCTL_SET_CONFIG\\n\");\n let mut user_buf = UserSlice::new(cmd.arg() as *const u8, 16);\n let mut new_config = [0u8; 16];\n user_buf.read(&mut new_config).map_err(|e| {\n pr_err!(\"my_char: Failed to copy config from user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n\n // Update config with spinlock protection\n let mut config = data.config.lock();\n *config = new_config;\n Ok(0)\n }\n _ => {\n pr_err!(\"my_char: Unknown ioctl command 0x{:x}\\n\", cmd.cmd());\n Err(KernelError::ENOTTY)\n }\n }\n }\n\n fn read(\n data: &MyCharDriverData,\n _file: &File,\n buf: &mut UserSliceMut,\n _offset: u64,\n ) -> Result {\n pr_info!(\"my_char: Handling read\\n\");\n let config = data.config.lock();\n let len = buf.len().min(config.len());\n buf.write(&config[..len]).map_err(|e| {\n pr_err!(\"my_char: Failed to read config to user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n Ok(len)\n }\n}\n\n// Static driver data: initialized at module load\nstatic DRIVER_DATA: MyCharDriverData = MyCharDriverData {\n version: 0x0100, // Version 1.0\n config: Spinlock::new([0u8; 16]),\n};\n\n// Register character device\nkernel::cdev_register! {\n name: \"my_char\",\n major: 0, // Dynamic major number\n minor: 0,\n count: 1,\n file_ops: MyCharFile,\n data: &DRIVER_DATA,\n}\n
// SPDX-License-Identifier: GPL-2.0\n// Sample Rust character device driver for Linux 6.10, Rust 1.85\n// Demonstrates ioctl handling, user-kernel copy, spinlock synchronization\nuse kernel::{\n prelude::*,\n cdev::{Cdev, CdevRegistration},\n file::{File, FileOperations},\n ioctl::{IoctlCommand, IoctlHandler},\n sync::Spinlock,\n user_ptr::{UserSlice, UserSliceMut},\n error::KernelError,\n};\n\n// Define ioctl command: 0xED is a free magic number for example\nconst IOCTL_GET_VERSION: u32 = kernel::ioctl!(_IOR('E', 0xD0, 4));\nconst IOCTL_SET_CONFIG: u32 = kernel::ioctl!(_IOW('E', 0xD1, 16));\n\n// Driver private data: protected by spinlock for SMP safety\nstruct MyCharDriverData {\n version: u32,\n config: Spinlock<[u8; 16]>,\n}\n\n// Implement FileOperations for our char device\nstruct MyCharFile;\nimpl FileOperations for MyCharFile {\n type Data = &'static MyCharDriverData;\n\n fn open(data: &'static MyCharDriverData, _file: &File) -> Result {\n pr_info!(\"my_char: Opening char device\\n\");\n Ok(data)\n }\n\n fn ioctl(\n data: &MyCharDriverData,\n _file: &File,\n cmd: IoctlCommand,\n ) -> Result {\n match cmd.cmd() {\n IOCTL_GET_VERSION => {\n pr_info!(\"my_char: Handling IOCTL_GET_VERSION\\n\");\n let mut user_buf = UserSliceMut::new(cmd.arg() as *mut u8, 4);\n user_buf.write(&data.version.to_ne_bytes()).map_err(|e| {\n pr_err!(\"my_char: Failed to copy version to user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n Ok(0)\n }\n IOCTL_SET_CONFIG => {\n pr_info!(\"my_char: Handling IOCTL_SET_CONFIG\\n\");\n let mut user_buf = UserSlice::new(cmd.arg() as *const u8, 16);\n let mut new_config = [0u8; 16];\n user_buf.read(&mut new_config).map_err(|e| {\n pr_err!(\"my_char: Failed to copy config from user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n\n // Update config with spinlock protection\n let mut config = data.config.lock();\n *config = new_config;\n Ok(0)\n }\n _ => {\n pr_err!(\"my_char: Unknown ioctl command 0x{:x}\\n\", cmd.cmd());\n Err(KernelError::ENOTTY)\n }\n }\n }\n\n fn read(\n data: &MyCharDriverData,\n _file: &File,\n buf: &mut UserSliceMut,\n _offset: u64,\n ) -> Result {\n pr_info!(\"my_char: Handling read\\n\");\n let config = data.config.lock();\n let len = buf.len().min(config.len());\n buf.write(&config[..len]).map_err(|e| {\n pr_err!(\"my_char: Failed to read config to user: {:?}\\n\", e);\n KernelError::EFAULT\n })?;\n Ok(len)\n }\n}\n\n// Static driver data: initialized at module load\nstatic DRIVER_DATA: MyCharDriverData = MyCharDriverData {\n version: 0x0100, // Version 1.0\n config: Spinlock::new([0u8; 16]),\n};\n\n// Register character device\nkernel::cdev_register! {\n name: \"my_char\",\n major: 0, // Dynamic major number\n minor: 0,\n count: 1,\n file_ops: MyCharFile,\n data: &DRIVER_DATA,\n}\n
// Before: violates FFI rules\nlet mut bar0 = 0x1234u32;\npdev.ffi_call(&mut bar0); // Clippy warns here\n\n// After: correct FFI usage\nlet mut bar0 = 0x1234u32;\npdev.ffi_call(&mut bar0 as *mut u32); // No warning\n
// Before: violates FFI rules\nlet mut bar0 = 0x1234u32;\npdev.ffi_call(&mut bar0); // Clippy warns here\n\n// After: correct FFI usage\nlet mut bar0 = 0x1234u32;\npdev.ffi_call(&mut bar0 as *mut u32); // No warning\n
// Before: violates FFI rules\nlet mut bar0 = 0x1234u32;\npdev.ffi_call(&mut bar0); // Clippy warns here\n\n// After: correct FFI usage\nlet mut bar0 = 0x1234u32;\npdev.ffi_call(&mut bar0 as *mut u32); // No warning\n
// Type-safe DMA buffer using const generics (Rust 1.85+)\nuse kernel::dma::DmaBuffer;\n\n// Allocate 4KB DMA buffer for RX\nlet rx_buf: DmaBuffer<4096> = DmaBuffer::alloc(pdev).map_err(|e| {\n pr_err!(\"Failed to alloc RX buffer: {:?}\\n\", e);\n KernelError::ENOMEM\n})?;\n\n// Function only accepts 4KB buffers, compile error if passed smaller\nfn process_rx(buf: &DmaBuffer) where N >= 4096 {\n // Safe: N is at least 4096\n let data = buf.as_slice();\n}\n
// Type-safe DMA buffer using const generics (Rust 1.85+)\nuse kernel::dma::DmaBuffer;\n\n// Allocate 4KB DMA buffer for RX\nlet rx_buf: DmaBuffer<4096> = DmaBuffer::alloc(pdev).map_err(|e| {\n pr_err!(\"Failed to alloc RX buffer: {:?}\\n\", e);\n KernelError::ENOMEM\n})?;\n\n// Function only accepts 4KB buffers, compile error if passed smaller\nfn process_rx(buf: &DmaBuffer) where N >= 4096 {\n // Safe: N is at least 4096\n let data = buf.as_slice();\n}\n
// Type-safe DMA buffer using const generics (Rust 1.85+)\nuse kernel::dma::DmaBuffer;\n\n// Allocate 4KB DMA buffer for RX\nlet rx_buf: DmaBuffer<4096> = DmaBuffer::alloc(pdev).map_err(|e| {\n pr_err!(\"Failed to alloc RX buffer: {:?}\\n\", e);\n KernelError::ENOMEM\n})?;\n\n// Function only accepts 4KB buffers, compile error if passed smaller\nfn process_rx(buf: &DmaBuffer) where N >= 4096 {\n // Safe: N is at least 4096\n let data = buf.as_slice();\n}\n
// KUnit test for PCIe driver probe error handling\n#[kernel::test]\nfn test_probe_invalid_bar() {\n let mock_pdev = kernel::test::mock_pci_device! {\n vendor: 0x1234,\n device: 0x5678,\n bar0: None, // Invalid BAR0\n };\n\n let result = MyPcieDriver::probe(&mock_pdev, &PciId::new(0x1234, 0x5678, None));\n assert!(result.is_err());\n assert_eq!(result.unwrap_err(), KernelError::EBUSY);\n}\n
// KUnit test for PCIe driver probe error handling\n#[kernel::test]\nfn test_probe_invalid_bar() {\n let mock_pdev = kernel::test::mock_pci_device! {\n vendor: 0x1234,\n device: 0x5678,\n bar0: None, // Invalid BAR0\n };\n\n let result = MyPcieDriver::probe(&mock_pdev, &PciId::new(0x1234, 0x5678, None));\n assert!(result.is_err());\n assert_eq!(result.unwrap_err(), KernelError::EBUSY);\n}\n
// KUnit test for PCIe driver probe error handling\n#[kernel::test]\nfn test_probe_invalid_bar() {\n let mock_pdev = kernel::test::mock_pci_device! {\n vendor: 0x1234,\n device: 0x5678,\n bar0: None, // Invalid BAR0\n };\n\n let result = MyPcieDriver::probe(&mock_pdev, &PciId::new(0x1234, 0x5678, None));\n assert!(result.is_err());\n assert_eq!(result.unwrap_err(), KernelError::EBUSY);\n}\n - ⭐ rust-lang/rust — 112,424 stars, 14,840 forks - Zed 1.0 (1525 points)
- Copy Fail – CVE-2026-31431 (577 points)
- Cursor Camp (626 points)
- OpenTrafficMap (153 points)
- HERMES.md in commit messages causes requests to route to extra usage billing (982 points)