[LNX007] Linux Device Driver Model: Device-Bus-Driver

Main Content

1. sysfs and kobject

2. device-bus-driver

2.1 bus_type

2.2 class and device_type

2.3 device/driver and sysfs

2.4 device and driver matching

This article is based on the analysis of Linux version 6.6.92

1. sysfs and kobject

sysfs is a virtual file system in the Linux kernel, its main function is to provide a unified interface for user space to access kernel data, allowing users to view and modify information about devices and drivers

sysfs organizes devices and buses connected to the system into a hierarchical file structure, which can be accessed from user space, typically mounted under the /sys directory

$ ls /sys
block  class  devices   fs           kernel  pmic_info  systeminfo
bus    dev    firmware  io_log_data  module  power      vservices

kobject serves as a bridge between device drivers and sysfs:kobject corresponds to a directory in sysfs

  • • parent points to the parent kobject
  • • sd points to kernfs_node, which is the carrier (implementation) of the sysfs file system directory

kset is a collection of kobjects

  • • list is a linked list connecting its own kobjects

[LNX007] Linux Device Driver Model: Device-Bus-Driver

kobject_create_and_add() function creates and initializes a kobject {} object, then calls kobject_add() to add it to the system

kobject_add() function is quite complex, the main logic is as follows

  • • Set the name and parent of the kobject
  • • If a kset is specified, add it to the end of the kset’s list
  • • Then create directories and attribute files

[LNX007] Linux Device Driver Model: Device-Bus-Driver

kset_create_and_add() is used to create and initialize a kset {} object, then calls kset_register() to add it to the system

kset_register() function does two things

  • • Calls kobject_add_internal() to add kset::kobj to the system
  • • Then sends a uevent to the system

[LNX007] Linux Device Driver Model: Device-Bus-Driver

2. device-bus-driver

During initialization, the buses_init() and devices_init() functions create the bus/class/dev/devices directories under the “/sys” directory

[LNX007] Linux Device Driver Model: Device-Bus-Driver

2.1 bus_type

The system uses the bus_type {} data structure to represent a bus, for example, platform_bus is defined as follows

struct bus_type platform_bus_type = {
    .name        = "platform",
    .dev_groups    = platform_dev_groups,
    .match        = platform_match,
    .uevent        = platform_uevent,
    .probe        = platform_probe,
    .remove        = platform_remove,
    .shutdown    = platform_shutdown,
    .dma_configure    = platform_dma_configure,
    .dma_cleanup    = platform_dma_cleanup,
    .pm        = &platform_dev_pm_ops,
};

More information is in the subsys_private {} data structure, where a subsys_private {} object is allocated in the bus_register() function

  • bus points to the bus_type {} object
  • • subsys is a kset {} object, which will create a directory /sys/bus/busX
  • device_kset and driver_kset are used to manage the kobjects of devices and drivers on the bus
    • • The kobjects of devices and drivers are added to device_kset and driver_kset respectively
  • klist_devices and klist_drivers linked lists are used to connect devices and drivers on the bus
  • • The interfaces linked list connects subsys_interface {} objects, notifying the corresponding bus_type {} object when devices are added and removed

[LNX007] Linux Device Driver Model: Device-Bus-Driver

The bus_register() function adds a bus_type {} object to the system

  • • Allocates a subsys_private {} object
  • • Creates the “/sys/bus/busX” directory

[LNX007] Linux Device Driver Model: Device-Bus-Driver

For example, the contents under the “/sys/bus/platform” directory

$ ls /sys/bus/platform/
devices  drivers  drivers_autoprobe  drivers_probe  uevent

2.2 class and device_type

class provides device category information for user space, used to organize devices under “/sys/class” for easier management

device_type is the category information of the device model, mainly used to provide common kernel callbacks, kobject/sysfs attribute groups, uevent handling, etc., for the same kernel device type. It is more related to kernel implementation/behavior.

The class {} object is also bound to a subsys_private {} object

  • • The interfaces linked list connects class_interface {} objects, used to notify devices when adding and removing
  • • The klist_devices linked list connects all devices of the current class

[LNX007] Linux Device Driver Model: Device-Bus-Driver

class_register() function registers a class, creating a directory cls->name under /sys/class

If class_groups is specified, attribute files will be created under /sys/class/cls->name/

[LNX007] Linux Device Driver Model: Device-Bus-Driver

For example, when a character device calls the device_get_devnode() function to get the node name

  • • It first tries to use the devnode in device_type to get the node name
  • • If not supported, it tries to use the function callback pointed to by devnode in class to get the node name
  • • Finally, it uses dev_name() as the node name

[LNX007] Linux Device Driver Model: Device-Bus-Driver

2.3 device/driver and sysfs

When adding a device {} object, directories and files are created in the sys file directory, below is the creation of the sound card

  • • uevent file
  • • device links to parent
  • • subsystem links to class
  • • A link is also established in the class directory
$ pwd
/sys/class/sound

$ ls -la pcmC0D0p
lrwxrwxrwx 1 root root 0 2025-11-24 20:54 pcmC0D0p -> ../../devices/platform/soc/soc:qcom,msm-audio-apr/soc:qcom,msm-audio-apr:qcom,q6core-audio/soc:qcom,msm-audio-apr:qcom,q6core-audio:sound/sound/card0/pcmC0D0p

$ pwd
/sys/devices/platform/soc/soc:qcom,msm-audio-apr/soc:qcom,msm-audio-apr:qcom,q6core-audio/soc:qcom,msm-audio-apr:qcom,q6core-audio:sound/sound/card0

$ ls -la pcmC0D0p
total 0
drwxr-xr-x   3 root root 0 2025-11-24 21:52 .
drwxr-xr-x 121 root root 0 2025-11-24 21:51 ..-?????????   ? ?    ?    ?                ? dev
lrwxrwxrwx   1 root root 0 2025-11-24 21:52 device -> ../../card0
-?????????   ? ?    ?    ?                ? pcm_class
drwxr-xr-x   2 root root 0 2025-11-24 21:52 power
lrwxrwxrwx   1 root root 0 2025-11-24 21:52 subsystem -> ../../../../../../../../../class/sound
-?????????   ? ?    ?    ?                ? uevent

The function calls are as follows

[LNX007] Linux Device Driver Model: Device-Bus-Driver

Additionally, there are defined attributes, for example, the three attributes defined by v4l2

static DEVICE_ATTR_RO(index);
static DEVICE_ATTR_RW(dev_debug);
static DEVICE_ATTR_RO(name);

static struct attribute *video_device_attrs[] = {
    &dev_attr_name.attr,
    &dev_attr_dev_debug.attr,
    &dev_attr_index.attr,
    NULL,
};
ATTRIBUTE_GROUPS(video_device);

static struct class video_class = {
    .name = VIDEO_NAME,
    .dev_groups = video_device_groups,
};

In the directory corresponding to the device, three corresponding files will be created

$ pwd
/sys/devices/platform/cam_sync/video4linux/video1

$ ls -la
total 0
drwxr-xr-x 3 root root 0 2025-11-24 21:17 .
drwxr-xr-x 3 root root 0 2025-11-24 21:17 ..-????????? ? ?    ?    ?                ? dev
-????????? ? ?    ?    ?                ? dev_debug
lrwxrwxrwx 1 root root 0 2025-11-24 21:17 device -> ../../../cam_sync
-????????? ? ?    ?    ?                ? index
-????????? ? ?    ?    ?                ? name
drwxr-xr-x 2 root root 0 2025-11-24 21:17 power
lrwxrwxrwx 1 root root 0 2025-11-24 21:17 subsystem -> ../../../../../class/video4linux
-????????? ? ?    ?    ?                ? uevent

$ pwd
/sys/devices/platform/cam_sync/video4linux

$ ls -la /sys/bus/platform/devices/ | grep cam_sy
lrwxrwxrwx 1 root root 0 2025-11-24 21:56 cam_sync -> ../../../devices/platform/cam_sync

[LNX007] Linux Device Driver Model: Device-Bus-Driver

Finally, the files and directories created by the driver in sysfs

$ pwd
/sys/devices/platform/snd-soc-dummy

$ ls -la
total 0
drwxr-xr-x  3 root root 0 2025-11-25 00:25 .
drwxr-xr-x 23 root root 0 1972-07-19 02:27 ..lrwxrwxrwx  1 root root 0 2025-11-25 00:26 driver -> ../../../bus/platform/drivers/snd-soc-dummy
-?????????  ? ?    ?    ?                ? driver_override
-?????????  ? ?    ?    ?                ? modalias
drwxr-xr-x  2 root root 0 2025-11-25 00:26 power
lrwxrwxrwx  1 root root 0 2025-11-25 00:26 subsystem -> ../../../bus/platform
-?????????  ? ?    ?    ?                ? uevent

$ ls -la ../../../bus/platform/drivers/snd-soc-dummy
total 0
drwxr-xr-x   2 root root 0 2025-11-25 00:26 .
drwxr-xr-x 310 root root 0 2025-11-25 00:26 ..-?????????   ? ?    ?    ?                ? bind
lrwxrwxrwx   1 root root 0 2025-11-25 00:26 snd-soc-dummy -> ../../../../devices/platform/snd-soc-dummy
-?????????   ? ?    ?    ?                ? uevent
-?????????   ? ?    ?    ?                ? unbind

[LNX007] Linux Device Driver Model: Device-Bus-Driver

2.4 device and driver matching

device {} objects are bound to a device_private {} object, similarly, device_driver {} objects are also bound to a device_private {} object

In device_private, the klist_children linked list connects all child devices

In driver_private, the klist_devices linked list connects all matched devices

[LNX007] Linux Device Driver Model: Device-Bus-Driver

device_register() function is used to add a device to the system: first calls device_initialize() to initialize, then calls device_add() to add the device

device_add() function will call bus_probe_device() to match with the driver

[LNX007] Linux Device Driver Model: Device-Bus-Driver

bus_probe_device() function

  • • If dev->driver is not null, add the device to the driver’s klist_devices linked list
  • Then traverse the bus’s klist_drivers linked list, trying to match the device and driver

[LNX007] Linux Device Driver Model: Device-Bus-Driver

driver_register() is used to add a driver {} object

  • • Adds itself to the bus’s klist_drivers linked list
  • Traverses the bus’s klist_devices linked list, trying to match

[LNX007] Linux Device Driver Model: Device-Bus-Driver

If the device and driver match successfully, the probe function is called

This is a simplification and does not consider asynchronous behavior; refer to the source code for more details

[LNX007] Linux Device Driver Model: Device-Bus-Driver

Leave a Comment