Skip to main content

DeviceRegistry

Struct DeviceRegistry 

Source
pub struct DeviceRegistry {
    pub objects: KObjectStore,
    /* private fields */
}
Expand description

The registry for devices.

Devices are specified in file systems with major and minor device numbers, together referred to as a DeviceId. When userspace opens one of those files, we look up the DeviceId in the device registry to instantiate a file for that device.

The DeviceRegistry also manages the KObjectStore, which provides metadata for devices via the sysfs file system, typically mounted at /sys.

Fields§

§objects: KObjectStore

The KObjects for registered devices.

Implementations§

Source§

impl DeviceRegistry

Source

pub fn add_device( &self, kernel: &Kernel, name: &FsStr, metadata: DeviceMetadata, class: Class, dev_ops: impl DeviceOps, ) -> Device

Adds a numbered minor device to the DeviceRegistry.

If you are adding a device that exists in other systems, please check the metadata for that device in /sys and make sure you use the same properties when calling this function because these values are visible to userspace.

For example, a typical device will appear in sysfs at a path like:

/sys/devices/{bus}/{class}/{name}

Many common classes have convenient accessors on DeviceRegistry::objects.

To fill out the DeviceMetadata, look at the uevent file:

/sys/devices/{bus}/{class}/{name}/uevent

which has the following format:

  MAJOR={major-number}
  MINOR={minor-number}
  DEVNAME={devname}
  DEVMODE={devmode}

Often, the {name} and the {devname} are the same, but if they are not the same, please take care to use the correct string in the correct field.

If the {major-number} is 10 and the {minor-number} is in the range 52..128, please use Self::add_misc_device instead because these device numbers are dynamically allocated.

If the {major-number} is in the range 234..255, please use Self::add_dyn_device instead because these devices are also dynamically allocated.

If you are unsure which device numbers to use, consult devices.txt:

https://www.kernel.org/doc/Documentation/admin-guide/devices.txt

If you are still unsure, please ask an experienced Starnix contributor rather than make up a device number.

Uses build_device_directory to populate the standard sysfs directory for the device. To populate custom sysfs attributes or specify a parent device, use Self::add_device_with_dir.

Finally, the dev_ops parameter is where you provide the callback for instantiating your device. The returned Device can be removed with Self::remove_device.

Source

pub fn add_device_with_dir( &self, kernel: &Kernel, name: &FsStr, metadata: DeviceMetadata, parent: Option<Device>, subsystem: impl Into<DeviceSubsystem>, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), dev_ops: impl DeviceOps, ) -> Device

Adds a numbered minor device to the DeviceRegistry, with a sysfs directory populated by build_directory beneath parent.

If parent is itself a class device then the device directory is created directly within the parent’s directory, otherwise it is created within a <class> directory under parent. If parent is None then /sys/devices/virtual is used.

Dispatches UEventAction::Add after creating the sysfs and devtmpfs nodes. The returned Device can be removed with Self::remove_device.

See Self::add_device for an explanation of the other parameters.

Source

pub fn add_misc_device( &self, kernel: &Kernel, name: &FsStr, dev_ops: impl DeviceOps, ) -> Result<Device, Errno>

Allocates a dynamic device number in MISC_MAJOR and adds the device to the DeviceRegistry.

MISC devices (major number 10) with minor numbers in the range 52..128 are dynamically assigned. Rather than hardcoding registrations with these device numbers, use this function instead to add the device.

See Self::add_device for an explanation of the parameters.

Source

pub fn add_dyn_device( &self, kernel: &Kernel, name: &FsStr, class: Class, dev_ops: impl DeviceOps, ) -> Result<Device, Errno>

Allocates a dynamic character device number (major 234..255) and adds the device to the DeviceRegistry.

Major device numbers 234..255 are dynamically assigned. Rather than hardcoding registrations with these device numbers, use this function instead to add the device.

Note: We do not currently allocate from this entire range because we have mistakenly hardcoded some device registrations from the dynamic range. Once we fix these registrations to be dynamic, we should expand to using the full dynamic range.

See Self::add_device for an explanation of the parameters.

Source

pub fn add_dyn_device_with_dir( &self, kernel: &Kernel, name: &FsStr, class: Class, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), dev_ops: impl DeviceOps, ) -> Result<Device, Errno>

Allocates a dynamic character device number (major 234..255) and adds the device to the DeviceRegistry, with a sysfs directory populated by build_directory.

See Self::add_device for an explanation of the parameters.

Source

pub fn add_dyn_device_with_devname( &self, kernel: &Kernel, name: &FsStr, devname: &FsStr, class: Class, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), dev_ops: impl DeviceOps, ) -> Result<Device, Errno>

Allocates a dynamic character device number (major 234..255) and adds the device to the DeviceRegistry with a separate sysfs name and /dev devname, and a sysfs directory populated by build_directory.

See Self::add_dyn_device for an explanation of dynamic devices and parameters.

Source

pub fn register_silent_dyn_device( &self, name: &FsStr, dev_ops: impl DeviceOps, ) -> Result<DeviceMetadata, Errno>

Registers a “silent” dynamic device with major numbers 234..255.

Only use for devices that should not be added to the KObjectStore or appear in sysfs. This is a rare occurrence.

See Self::add_dyn_device for an explanation of dynamic devices and parameters.

Source

pub fn add_major_device( &self, kernel: &Kernel, name: &FsStr, metadata: DeviceMetadata, parent: Option<Device>, subsystem: impl Into<DeviceSubsystem>, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), ) -> Device

Adds a numbered device whose major number was previously registered via Self::register_major, with a sysfs directory populated by build_directory.

If you want to add a single minor device with its own DeviceOps, use Self::add_device or Self::add_device_with_dir instead.

The returned Device can be removed with Self::remove_device.

See Self::add_device_with_dir for an explanation of the parameters.

Source

pub fn add_net_device(&self, name: &FsStr) -> Device

Adds a network device to the device registry and dispatches UEventAction::Add.

Network devices do not have a /dev node or device number. Instead, in addition to DEVPATH and SUBSYSTEM=net, their uevent files have the following properties:

INTERFACE={name}
IFINDEX={index}

TODO(https://fxbug.dev/297438880): Populate INTERFACE and IFINDEX in the uevent file and uevent netlink messages. Currently, we only register net devices by name with the standard DEVPATH and SUBSYSTEM=net properties, and stub the address attribute so that reads by userspace are tracked.

The returned Device can be removed with Self::remove_device.

Source

pub fn add_subsystemless_device( &self, name: &FsStr, parent: Option<Device>, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), ) -> Device

Directly adds a device without a bus or class subsystem to the KObjectStore, populated by build_directory, and dispatches UEventAction::Add.

Such devices typically act as structural parents for other devices, e.g. the root of a subsystem’s devices (/sys/devices/system/cpu). If parent is Some, the device directory is created under parent; otherwise it is created directly under /sys/devices/<name>.

The returned Device can be removed with Self::remove_device.

Source

pub fn add_bus_device( &self, name: &FsStr, parent: Option<Device>, bus: Bus, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), ) -> Device

Directly adds a bus device to the KObjectStore, populated by build_directory, and dispatches UEventAction::Add.

If parent is Some, the device directory is created under parent; otherwise it is created directly under /sys/devices/<name>. A symlink is also created under /sys/bus/<bus.name>/devices/<name>.

The returned Device can be removed with Self::remove_device.

Source

pub fn add_numberless_device( &self, name: &FsStr, parent: Option<Device>, class: Class, build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator), ) -> Device

Directly adds a class device without a device number to the KObjectStore, populated by build_directory, and dispatches UEventAction::Add.

This function should be used by class devices that are exposed via sysfs or netlink and do not have a /dev device node (and therefore have no major or minor device number).

If parent is Some and is itself a class device, the device directory is created under <parent>/<name>; otherwise it is created under <parent>/<class.name>/<name> (defaulting parent to /sys/devices/virtual). A symlink is also created under /sys/class/<class.name>/<name>.

The returned Device can be removed with Self::remove_device.

Source

pub fn remove_device(&self, current_task: &CurrentTask, device: Device)

Unregisters device from devtmpfs, sysfs, and the minor device table, recycling any dynamically allocated DeviceId before dispatching UEventAction::Remove.

Any child devices parented under device must be removed before device itself so removal uevents are dispatched in child-before-parent order and intermediate class directories are cleaned up.

Source

pub fn list_major_devices(&self, mode: DeviceMode) -> Vec<(u32, FsString)>

Returns a list of the registered major device numbers for the given DeviceMode and their names.

Source

pub fn list_minor_devices( &self, mode: DeviceMode, range: Range<DeviceId>, ) -> Vec<(DeviceId, FsString)>

Returns a list of the registered minor devices for the given DeviceMode and their names.

Source

pub fn register_major<'a>( &self, name: FsString, mode: DeviceMode, major: u32, dev_ops: impl DeviceOps, ) -> Result<(), Errno>

Register an entire major device number.

If you register an entire major device, use Self::add_major_device and Self::remove_device to manage the sysfs and devtmpfs entries for each minor device rather than registering individual minor devices.

Source

pub fn next_anonymous_dev_id<'a>(&self) -> DeviceId

Allocate an anonymous device identifier.

Source

pub fn register_listener<'a>( &self, listener: impl DeviceListener + 'static, ) -> DeviceListenerKey

Registers a listener for device uevents and returns its DeviceListenerKey.

Source

pub fn unregister_listener<'a>(&self, key: &DeviceListenerKey)

Unregisters a listener previously registered via Self::register_listener.

Source

pub fn dispatch_uevent<'a>(&self, action: UEventAction, device: Device)

Dispatches a uevent with the next monotonic sequence number for device to all registered listeners.

Source

pub fn open_device( &self, current_task: &CurrentTask, node: &NamespaceNode, flags: OpenFlags, devt: DeviceId, mode: DeviceMode, ) -> Result<Box<dyn FileOps>, Errno>

Instantiate a file for the specified device.

The device will be looked up in the device registry by DeviceMode and DeviceId.

Source

pub fn get_device( &self, devt: DeviceId, mode: DeviceMode, ) -> Result<DeviceHandle, Errno>

Trait Implementations§

Source§

impl Default for DeviceRegistry

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsAny for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Source§

fn type_name(&self) -> &'static str

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T, D> Encode<Ambiguous1, D> for T
where D: ResourceDialect,

Source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl<T, D> Encode<Ambiguous2, D> for T
where D: ResourceDialect,

Source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
§

impl<F, N> FidlIntoNative<Box<N>> for F
where F: FidlIntoNative<N>,

§

fn fidl_into_native(self) -> Box<N>

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> InstanceFromServiceTransport<T> for T

§

fn from_service_transport(handle: T) -> T

Converts the given service transport handle of type T to [Self]
Source§

impl<T, U> Into32<U> for T
where U: MultiArchFrom<T>,

Source§

fn into_32(self) -> U

Source§

impl<T, U> Into64<U> for T
where U: MultiArchFrom<T>,

Source§

fn into_64(self) -> U

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoAny for T
where T: 'static + Send + Sync,

Source§

fn into_any(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Cast the given object into a dyn std::any::Any.
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T, U> IntoExt<U> for T
where U: FromExt<T>,

§

fn into_ext(self) -> U

Performs the conversion.
Source§

impl<T, U> IntoFidl<U> for T
where U: FromFidl<T>,

Source§

fn into_fidl(self) -> U

Source§

impl<T, U> MultiArchFrom<T> for U
where U: From<T>,

Source§

fn from_64(value: T) -> U

Source§

fn from_32(value: T) -> U

§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

§

impl<E> RunsTransport<Mpsc> for E

§

impl<E> RunsTransport<Mpsc> for E
where E: RunsTransport<Mpsc>,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T, U> TryIntoExt<U> for T
where U: TryFromExt<T>,

§

type Error = <U as TryFromExt<T>>::Error

§

fn try_into_ext(self) -> Result<U, <T as TryIntoExt<U>>::Error>

Tries to perform the conversion.
§

impl<St> WithTag for St

§

fn tagged<T>(self, tag: T) -> Tagged<T, St> ⓘ

Produce a new stream from this one which yields item tupled with a constant tag