blob: 8420150c4d0862aef2446e5cfe72b8b965e4e2ac [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use bind_debugger::debugger;
use bind_debugger::instruction::{DeviceProperty, RawInstruction};
use fidl_fuchsia_device_manager::BindDebuggerMarker;
use fuchsia_async as fasync;
use fuchsia_component::client::connect_to_service;
use fuchsia_zircon as zx;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
struct Opt {
/// The path of the driver to debug, e.g. "/system/driver/usb_video.so"
driver_path: String,
/// The path of the device to debug, relative to the /dev directory.
/// E.g. "sys/pci/00:1f.6" or "class/usb-device/000"
device_path: String,
/// Print out the device properties.
#[structopt(short = "p", long = "print-properties")]
print_properties: bool,
/// Print out the bind program instructions.
#[structopt(short = "i", long = "print-instructions")]
print_instructions: bool,
}
#[fasync::run_singlethreaded]
async fn main() {
let opt = Opt::from_iter(std::env::args());
let service = match connect_to_service::<BindDebuggerMarker>() {
Ok(service) => service,
Err(_) => {
eprintln!("Failed to connect to BindDebugger service.");
std::process::exit(1);
}
};
let bind_program = match service.get_bind_program(&opt.driver_path).await {
Err(fidl_err) => {
eprintln!("FIDL call to get bind program failed: {}", fidl_err);
std::process::exit(1);
}
Ok(Err(zx_err)) => {
eprintln!(
"FIDL call to get bind program returned an error: {}",
zx::Status::from_raw(zx_err)
);
std::process::exit(1);
}
Ok(Ok(program)) => program,
};
let device_properties = match service.get_device_properties(&opt.device_path).await {
Err(fidl_err) => {
eprintln!("FIDL call to get device properties failed: {}", fidl_err);
std::process::exit(1);
}
Ok(Err(zx_err)) => {
eprintln!(
"FIDL call to get device properties returned an error: {}",
zx::Status::from_raw(zx_err)
);
std::process::exit(1);
}
Ok(Ok(props)) => props,
};
let raw_instructions = bind_program
.into_iter()
.map(|instruction| RawInstruction([instruction.op, instruction.arg, instruction.debug]))
.collect::<Vec<RawInstruction<[u32; 3]>>>();
let device_properties =
device_properties.into_iter().map(DeviceProperty::from).collect::<Vec<DeviceProperty>>();
if opt.print_instructions {
println!("Bind program:");
for instruction in &raw_instructions {
println!("{}", instruction);
}
println!();
}
if opt.print_properties {
println!("Device properties:");
for property in &device_properties {
println!("{}", property);
}
println!();
}
let binds = match debugger::debug(&raw_instructions, &device_properties) {
Ok(binds) => binds,
Err(err) => {
eprintln!("{}", err);
std::process::exit(1);
}
};
if binds {
println!("Driver binds to the device.");
} else {
println!("Driver doesn't bind to the device.");
}
}