1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//! Runs openocd server connected to a device.

use clap::{App, Arg, ArgMatches, SubCommand};
use commands::itmdump;
use config;
use failure::{err_msg, Error};
use itm;
use openocd;
use std::os::unix::process::CommandExt;

const PIPE_NAME: &str = "/tmp/cargo-drone-itmdump";

/// Clap command details.
pub fn command<'a, 'b>() -> App<'a, 'b> {
  SubCommand::with_name("server")
    .arg(
      Arg::with_name("itm")
        .short("i")
        .long("itm")
        .help("Listen to ITM stream"),
    )
    .arg(
      Arg::with_name("PORT")
        .short("p")
        .long("port")
        .help("ITM port to listen"),
    )
    .arg(
      Arg::with_name("debug")
        .short("d")
        .long("debug")
        .help(itmdump::DEBUG_HELP),
    )
    .about("Runs openocd server connected to a device")
}

/// Command runner.
pub fn run(matches: &ArgMatches) -> Result<(), Error> {
  let config = config::read()?;
  if matches.is_present("itm") {
    itm::create_pipe(PIPE_NAME)?;
    spawn_with_itm(PIPE_NAME, &config)?;
    itm::run_loop(
      PIPE_NAME,
      matches
        .value_of("PORT")
        .map(|port| port.parse().unwrap())
        .unwrap_or(0),
      matches.is_present("debug"),
    )?;
  } else {
    openocd::command(&config).exec();
  }
  Ok(())
}

fn spawn_with_itm(name: &str, config: &config::Root) -> Result<(), Error> {
  let mut command = openocd::command(config);
  command
    .arg("-c")
    .arg(format!(
      "tpiu config internal {} uart off {}",
      name,
      config
        .itm
        .as_ref()
        .ok_or_else(|| err_msg("ITM frequency is not configured"))?
        .frequency
    ))
    .arg("-c")
    .arg("itm ports on");
  command.spawn()?;
  Ok(())
}