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::CurrentTask;
17use starnix_logging::log_warn;
18use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked};
19use starnix_uapi::device_type::DeviceType;
20use starnix_uapi::errors::Errno;
21use starnix_uapi::file_mode::mode;
22use std::sync::Arc;
23
24pub fn hvdcp_opti_init<L>(locked: &mut Locked<L>, current_task: &CurrentTask) -> Result<(), Errno>
25where
26    L: LockEqualOrBefore<FileOpsCore>,
27{
28    let proxy = match connect_to_device_channel("iio") {
29        Ok(chan) => Arc::new(fhvdcpopti::IioSynchronousProxy::new(chan)),
30        Err(e) => {
31            // hvdcp_opti only supported on Sorrel. Let it fail.
32            log_warn!(
33                "Could not connect to hvdcp_opti server {}. This is expected on everything but Sorrel.",
34                e
35            );
36            return Ok(());
37        }
38    };
39
40    let kernel = current_task.kernel();
41    let registry = &kernel.device_registry;
42
43    let qdb_class =
44        registry.objects.class_with_dir("qbg".into(), registry.objects.virtual_bus(), |dir| {
45            dir.entry("qbg_context", ReadWriteBytesFile::new_node(), mode!(IFREG, 0o666));
46        });
47
48    // /dev/qbg
49    registry.register_device(
50        locked,
51        current_task,
52        "qbg".into(),
53        DeviceMetadata::new("qbg".into(), DeviceType::new(484, 0), DeviceMode::Char),
54        qdb_class,
55        create_qbg_device,
56    )?;
57
58    // /dev/qbg_battery
59    registry.register_device(
60        locked,
61        current_task,
62        "qbg_battery".into(),
63        DeviceMetadata::new("qbg_battery".into(), DeviceType::new(485, 0), DeviceMode::Char),
64        registry.objects.get_or_create_class("qbg_battery".into(), registry.objects.virtual_bus()),
65        create_battery_profile_device,
66    )?;
67
68    // /sys/bus/iio/devices/iio:device
69    // IIO devices should not show up under /sys/class. This makes it show up under /sys/class,
70    // but it's OK.
71    let iio = registry
72        .objects
73        .get_or_create_class("iio".into(), registry.objects.get_or_create_bus("iio".into()));
74    registry.add_numberless_device(locked, "iio:device0".into(), iio.clone(), |device, dir| {
75        build_iio0_directory(device, &proxy, dir)
76    });
77
78    registry.add_numberless_device(locked, "iio:device1".into(), iio, |device, dir| {
79        build_iio1_directory(device, &proxy, dir)
80    });
81
82    // power_supply devices don't show up under any bus. This makes it show up under virtual_bus,
83    // but it's OK.
84    let power_supply =
85        registry.objects.get_or_create_class("power_supply".into(), registry.objects.virtual_bus());
86    // /sys/class/power_supply/usb
87    registry.add_numberless_device(locked, "usb".into(), power_supply.clone(), |device, dir| {
88        build_usb_power_supply_directory(device, &proxy, dir)
89    });
90
91    // /sys/class/power_supply/battery
92    registry.add_numberless_device(
93        locked,
94        "battery".into(),
95        power_supply.clone(),
96        |device, dir| build_battery_power_supply_directory(device, &proxy, dir),
97    );
98
99    // /sys/class/power_supply/bms
100    registry.add_numberless_device(locked, "bms".into(), power_supply, build_device_directory);
101    Ok(())
102}