Skip to main content

starnix_modules_hvdcp_opti/
device.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::iio_file::{
6    build_battery_power_supply_directory, build_iio0_directory, build_iio1_directory,
7    build_usb_power_supply_directory,
8};
9use super::qbg_battery_file::create_battery_profile_device;
10use super::qbg_file::create_qbg_device;
11use super::utils::{ReadWriteBytesFile, connect_to_device_channel};
12use fidl_fuchsia_hardware_qcom_hvdcpopti as fhvdcpopti;
13use starnix_core::device::DeviceMode;
14use starnix_core::device::kobject::DeviceMetadata;
15use starnix_core::fs::sysfs::build_device_directory;
16use starnix_core::task::Kernel;
17use starnix_logging::log_warn;
18
19use starnix_uapi::device_id::DeviceId;
20use starnix_uapi::errors::Errno;
21use starnix_uapi::file_mode::mode;
22use std::sync::Arc;
23
24pub fn hvdcp_opti_init(kernel: &Kernel) -> Result<(), Errno> {
25    let proxy = match connect_to_device_channel("iio") {
26        Ok(chan) => Arc::new(fhvdcpopti::IioSynchronousProxy::new(chan)),
27        Err(e) => {
28            // hvdcp_opti only supported on Sorrel. Let it fail.
29            log_warn!(
30                "Could not connect to hvdcp_opti server {}. This is expected on everything but Sorrel.",
31                e
32            );
33            return Ok(());
34        }
35    };
36
37    let registry = &kernel.device_registry;
38
39    let qdb_class =
40        registry.objects.class_with_dir("qbg".into(), registry.objects.virtual_bus(), |dir| {
41            dir.entry("qbg_context", ReadWriteBytesFile::new_node(), mode!(IFREG, 0o666));
42        });
43
44    // /dev/qbg
45    registry.register_device(
46        kernel,
47        "qbg".into(),
48        DeviceMetadata::new("qbg".into(), DeviceId::new(484, 0), DeviceMode::Char),
49        qdb_class,
50        create_qbg_device,
51    )?;
52
53    // /dev/qbg_battery
54    registry.register_device(
55        kernel,
56        "qbg_battery".into(),
57        DeviceMetadata::new("qbg_battery".into(), DeviceId::new(485, 0), DeviceMode::Char),
58        registry.objects.get_or_create_class("qbg_battery".into(), registry.objects.virtual_bus()),
59        create_battery_profile_device,
60    )?;
61
62    // /sys/bus/iio/devices/iio:device
63    // IIO devices should not show up under /sys/class. This makes it show up under /sys/class,
64    // but it's OK.
65    let iio = registry
66        .objects
67        .get_or_create_class("iio".into(), registry.objects.get_or_create_bus("iio".into()));
68    registry.add_numberless_device("iio:device0".into(), iio.clone(), |device, dir| {
69        build_iio0_directory(device, &proxy, dir)
70    });
71
72    registry.add_numberless_device("iio:device1".into(), iio, |device, dir| {
73        build_iio1_directory(device, &proxy, dir)
74    });
75
76    // power_supply devices don't show up under any bus. This makes it show up under virtual_bus,
77    // but it's OK.
78    let power_supply =
79        registry.objects.get_or_create_class("power_supply".into(), registry.objects.virtual_bus());
80    // /sys/class/power_supply/usb
81    registry.add_numberless_device("usb".into(), power_supply.clone(), |device, dir| {
82        build_usb_power_supply_directory(device, &proxy, dir)
83    });
84
85    // /sys/class/power_supply/battery
86    registry.add_numberless_device("battery".into(), power_supply.clone(), |device, dir| {
87        build_battery_power_supply_directory(device, &proxy, dir)
88    });
89
90    // /sys/class/power_supply/bms
91    registry.add_numberless_device("bms".into(), power_supply, build_device_directory);
92    Ok(())
93}