• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium OS 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 //!  `sound_card_init` is an user space binary to perform sound card initialization during boot time.
5 //!
6 //!
7 //!  # Arguments
8 //!
9 //!  * `sound_card_id` - The sound card name, ex: sofcmlmax98390d.
10 //!
11 //!  Given the `sound_card_id`, this binary parses the CONF_DIR/<sound_card_id>.yaml to perform per sound card initialization.
12 //!  The upstart job of `sound_card_init` is started by the udev event specified in /lib/udev/rules.d/99-sound_card_init.rules.
13 #![deny(missing_docs)]
14 use std::env;
15 use std::error;
16 use std::fmt;
17 use std::process;
18 use std::string::String;
19 
20 use getopts::Options;
21 use remain::sorted;
22 use sys_util::{error, info, syslog};
23 
24 use amp::AmpBuilder;
25 use dsm::utils::run_time;
26 
27 type Result<T> = std::result::Result<T, Error>;
28 
29 #[derive(Default)]
30 struct Args {
31     pub sound_card_id: String,
32     pub conf: String,
33 }
34 
35 #[sorted]
36 #[derive(Debug)]
37 enum Error {
38     MissingOption(String),
39     ParseArgsFailed(getopts::Fail),
40 }
41 
42 impl error::Error for Error {}
43 
44 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result45     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46         use Error::*;
47         match self {
48             MissingOption(option) => write!(f, "missing required option: {}", option),
49             ParseArgsFailed(e) => write!(f, "parse_args failed: {}", e),
50         }
51     }
52 }
53 
print_usage(opts: &Options)54 fn print_usage(opts: &Options) {
55     let brief = "Usage: sound_card_init [options]".to_owned();
56     print!("{}", opts.usage(&brief));
57 }
58 
parse_args() -> Result<Args>59 fn parse_args() -> Result<Args> {
60     let mut opts = Options::new();
61     opts.optopt("", "id", "sound card id", "ID");
62     opts.optopt(
63         "",
64         "conf",
65         "the config file name. It should be $(cros_config /audio/main sound-card-init-conf)",
66         "CONFIG_NAME",
67     );
68     opts.optflag("h", "help", "print help menu");
69     let matches = opts
70         .parse(&env::args().collect::<Vec<_>>()[1..])
71         .map_err(|e| {
72             print_usage(&opts);
73             Error::ParseArgsFailed(e)
74         })?;
75 
76     if matches.opt_present("h") {
77         print_usage(&opts);
78         process::exit(0);
79     }
80 
81     let sound_card_id = matches
82         .opt_str("id")
83         .ok_or_else(|| Error::MissingOption("id".to_owned()))
84         .map_err(|e| {
85             print_usage(&opts);
86             e
87         })?;
88 
89     let conf = matches
90         .opt_str("conf")
91         .ok_or_else(|| Error::MissingOption("conf".to_owned()))
92         .map_err(|e| {
93             print_usage(&opts);
94             e
95         })?;
96 
97     Ok(Args {
98         sound_card_id,
99         conf,
100     })
101 }
102 
103 /// Parses the CONF_DIR/${args.conf}.yaml and starts the boot time calibration.
sound_card_init(args: &Args) -> std::result::Result<(), Box<dyn error::Error>>104 fn sound_card_init(args: &Args) -> std::result::Result<(), Box<dyn error::Error>> {
105     info!("sound_card_id: {}, conf:{}", args.sound_card_id, args.conf);
106     AmpBuilder::new(&args.sound_card_id, &args.conf)
107         .build()?
108         .boot_time_calibration()?;
109 
110     Ok(())
111 }
112 
main()113 fn main() {
114     syslog::init().expect("failed to initialize syslog");
115     let args = match parse_args() {
116         Ok(args) => args,
117         Err(e) => {
118             error!("failed to parse arguments: {}", e);
119             return;
120         }
121     };
122 
123     match sound_card_init(&args) {
124         Ok(_) => info!("sound_card_init finished successfully."),
125         Err(e) => error!("sound_card_init: {}", e),
126     }
127 
128     if let Err(e) = run_time::now_to_file(&args.sound_card_id) {
129         error!("failed to create sound_card_init run time file: {}", e);
130     }
131 }
132