| // 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."); |
| } |
| } |