xref: /linux/samples/rust/rust_driver_auxiliary.rs (revision 710ac546883c2cae6e8e7b5dcf7757b8a49d75a1)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Rust auxiliary driver sample (based on a PCI driver for QEMU's `pci-testdev`).
4 //!
5 //! To make this driver probe, QEMU must be run with `-device pci-testdev`.
6 
7 use kernel::{
8     auxiliary, c_str, device::Core, devres::Devres, driver, error::Error, pci, prelude::*,
9     InPlaceModule,
10 };
11 
12 use pin_init::PinInit;
13 
14 const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
15 const AUXILIARY_NAME: &CStr = c_str!("auxiliary");
16 
17 struct AuxiliaryDriver;
18 
19 kernel::auxiliary_device_table!(
20     AUX_TABLE,
21     MODULE_AUX_TABLE,
22     <AuxiliaryDriver as auxiliary::Driver>::IdInfo,
23     [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
24 );
25 
26 impl auxiliary::Driver for AuxiliaryDriver {
27     type IdInfo = ();
28 
29     const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
30 
31     fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
32         dev_info!(
33             adev.as_ref(),
34             "Probing auxiliary driver for auxiliary device with id={}\n",
35             adev.id()
36         );
37 
38         ParentDriver::connect(adev)?;
39 
40         Ok(Self)
41     }
42 }
43 
44 #[pin_data]
45 struct ParentDriver {
46     #[pin]
47     _reg0: Devres<auxiliary::Registration>,
48     #[pin]
49     _reg1: Devres<auxiliary::Registration>,
50 }
51 
52 kernel::pci_device_table!(
53     PCI_TABLE,
54     MODULE_PCI_TABLE,
55     <ParentDriver as pci::Driver>::IdInfo,
56     [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
57 );
58 
59 impl pci::Driver for ParentDriver {
60     type IdInfo = ();
61 
62     const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
63 
64     fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
65         try_pin_init!(Self {
66             _reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME),
67             _reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME),
68         })
69     }
70 }
71 
72 impl ParentDriver {
73     fn connect(adev: &auxiliary::Device) -> Result {
74         let dev = adev.parent();
75         let pdev: &pci::Device = dev.try_into()?;
76 
77         dev_info!(
78             dev,
79             "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
80             adev.id(),
81             pdev.vendor_id(),
82             pdev.device_id()
83         );
84 
85         Ok(())
86     }
87 }
88 
89 #[pin_data]
90 struct SampleModule {
91     #[pin]
92     _pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
93     #[pin]
94     _aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
95 }
96 
97 impl InPlaceModule for SampleModule {
98     fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
99         try_pin_init!(Self {
100             _pci_driver <- driver::Registration::new(MODULE_NAME, module),
101             _aux_driver <- driver::Registration::new(MODULE_NAME, module),
102         })
103     }
104 }
105 
106 module! {
107     type: SampleModule,
108     name: "rust_driver_auxiliary",
109     authors: ["Danilo Krummrich"],
110     description: "Rust auxiliary driver",
111     license: "GPL v2",
112 }
113