| // Copyright 2024 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Provide debugd APIs. This module should only contain straight translations |
| // for the org.chromium.debugd interface. Higher level business logic should |
| // remain in the various command modules. |
| |
| use bitflags::bitflags; |
| use dbus::{ |
| arg::{OwnedFd, PropMap}, |
| blocking::Connection, |
| }; |
| use log::error; |
| use system_api::client::OrgChromiumDebugd; |
| |
| use crate::util::DEFAULT_DBUS_TIMEOUT; |
| |
| const BUS_NAME: &str = "org.chromium.debugd"; |
| const SERVICE_PATH: &str = "/org/chromium/debugd"; |
| |
| pub struct Debugd { |
| connection: dbus::blocking::Connection, |
| } |
| |
| // These bitflag values must match those in org.chromium.debugd.xml. |
| bitflags! { |
| pub struct DRMTraceCategories: u32 { |
| const CORE = 0x001; |
| const DRIVER = 0x002; |
| const KMS = 0x004; |
| const PRIME = 0x008; |
| const ATOMIC = 0x010; |
| const VBL = 0x020; |
| const STATE = 0x040; |
| const LEASE = 0x080; |
| const DP = 0x100; |
| const DRMRES = 0x200; |
| } |
| } |
| |
| // These enum values must match those in org.chromium.debugd.xml. |
| pub enum DRMTraceSize { |
| Default = 0, |
| Debug = 1, |
| } |
| |
| // These enum values must match those in org.chromium.debugd.xml. |
| pub enum DRMTraceSnapshotType { |
| Trace = 0, |
| Modetest = 1, |
| } |
| |
| // These enum values must match those in org.chromium.debugd.xml. |
| pub enum FirmwareDumpType { |
| All = 0, |
| Wifi = 1, |
| } |
| |
| impl Debugd { |
| pub fn new() -> Result<Debugd, dbus::Error> { |
| match Connection::new_system() { |
| Ok(connection) => Ok(Debugd { connection }), |
| Err(err) => { |
| // Include output in syslog. |
| error!("ERROR: Failed to get D-Bus connection: {}", err); |
| Err(err) |
| } |
| } |
| } |
| |
| pub fn call_dmesg(&self, options: PropMap) -> Result<String, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .call_dmesg(options) |
| } |
| |
| pub fn drmtrace_annotate_log(&self, log: String) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .drmtrace_annotate_log(&log) |
| .map(|_| self) |
| } |
| |
| pub fn drmtrace_snapshot( |
| &self, |
| snapshot_type: DRMTraceSnapshotType, |
| ) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .drmtrace_snapshot(snapshot_type as u32) |
| .map(|_| self) |
| } |
| |
| pub fn drmtrace_set_size(&self, size: DRMTraceSize) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .drmtrace_set_size(size as u32) |
| .map(|_| self) |
| } |
| |
| pub fn drmtrace_set_categories( |
| &self, |
| categories: DRMTraceCategories, |
| ) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .drmtrace_set_categories(categories.bits()) |
| .map(|_| self) |
| } |
| |
| pub fn get_u2f_flags(&self) -> Result<String, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .get_u2f_flags() |
| } |
| |
| pub fn set_u2f_flags(&self, flags: &str) -> Result<String, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .set_u2f_flags(flags) |
| } |
| |
| pub fn upload_crashes(&self) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .upload_crashes() |
| .map(|_| self) |
| } |
| |
| pub fn enable_dev_coredump_upload(&self) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .enable_dev_coredump_upload() |
| .map(|_| self) |
| } |
| |
| pub fn disable_dev_coredump_upload(&self) -> Result<&Debugd, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .disable_dev_coredump_upload() |
| .map(|_| self) |
| } |
| |
| pub fn update_and_verify_fwon_usb_start( |
| &self, |
| outfd: OwnedFd, |
| image_file: &str, |
| ro_db_dir: &str, |
| ) -> Result<String, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .update_and_verify_fwon_usb_start(outfd, image_file, ro_db_dir) |
| } |
| |
| pub fn update_and_verify_fwon_usb_stop(&self, handle: &str) -> Result<(), dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .update_and_verify_fwon_usb_stop(handle) |
| } |
| |
| pub fn packet_capture_start( |
| &self, |
| statfd: OwnedFd, |
| outfd: OwnedFd, |
| options: PropMap, |
| ) -> Result<String, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .packet_capture_start(statfd, outfd, options) |
| } |
| |
| pub fn packet_capture_stop(&self, handle: &str) -> Result<(), dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .packet_capture_stop(handle) |
| } |
| |
| pub fn generate_firmware_dump( |
| &self, |
| fwdump_type: FirmwareDumpType, |
| ) -> Result<bool, dbus::Error> { |
| self.connection |
| .with_proxy(BUS_NAME, SERVICE_PATH, DEFAULT_DBUS_TIMEOUT) |
| .generate_firmware_dump(fwdump_type as u32) |
| } |
| } |