diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:00:07 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:00:07 +0000 |
commit | 7fe2412222a5198f9e169ce0effa8318320fe3ad (patch) | |
tree | a7ce485be0cac8f35324dc264f433104555c8424 | |
parent | 4f97d6740411fb53a4fb5f6e1af03e1f1b28c1ba (diff) | |
parent | 8d2c5b2edb9023b91d79709f2900ee1b643a3127 (diff) | |
download | adhd-aml_tz2_305400100.tar.gz |
Snap for 8426163 from 8d2c5b2edb9023b91d79709f2900ee1b643a3127 to mainline-tzdata2-releaseandroid-mainline-12.0.0_r112aml_tz2_305400500aml_tz2_305400300aml_tz2_305400100aml_tz2_304500300aml_tz2_303900110aml_tz2_303900102aml_tz2_303800002aml_tz2_303800001aml_tz2_303200001android12-mainline-tzdata2-releaseaml_tz2_305400100
Change-Id: I127ce133361317d9ebfb8ef2a903afdd64a6feeb
475 files changed, 13587 insertions, 25455 deletions
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index e8af785b..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,65 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -name: "CodeQL" - -on: - push: - branches: [main] - pull_request: - # The branches below must be a subset of the branches above - branches: [main] - schedule: - - cron: '0 11 * * 1' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - # Override automatic language detection by changing the below list - # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] - language: ['cpp'] - # Learn more... - # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 - - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - - # Command-line programs to run using the OS shell. - # https://git.io/JvXDl - - - name: Install cras deps - working-directory: ./cras - run: sudo ./install_deps.sh - - - name: Build - working-directory: ./cras - run: | - ./git_prepare.sh - ./configure - make - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/Android.bp b/Android.bp deleted file mode 100644 index 4cb9810f..00000000 --- a/Android.bp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (C) 2021 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - default_applicable_licenses: ["external_adhd_license"], -} - -// Added automatically by a large-scale-change that took the approach of -// 'apply every license found to every target'. While this makes sure we respect -// every license restriction, it may not be entirely correct. -// -// e.g. GPL in an MIT project might only apply to the contrib/ directory. -// -// Please consider splitting the single license below into multiple licenses, -// taking care not to lose any license_kind information, and overriding the -// default license using the 'licenses: [...]' property on targets as needed. -// -// For unused files, consider creating a 'fileGroup' with "//visibility:private" -// to attach the license to, and including a comment whether the files may be -// used in the current project. -// -// large-scale-change included anything that looked like it might be a license -// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc. -// -// Please consider removing redundant or irrelevant files from 'license_text:'. -// See: http://go/android-license-faq -license { - name: "external_adhd_license", - visibility: [":__subpackages__"], - license_kinds: [ - "SPDX-license-identifier-BSD", - "SPDX-license-identifier-LGPL", - ], - license_text: [ - "LICENSE.SUPERFASTHASH", - "LICENSE.UTLIST", - "LICENSE.WEBKIT", - "NOTICE", - ], -} diff --git a/METADATA b/METADATA deleted file mode 100644 index 6d8601bb..00000000 --- a/METADATA +++ /dev/null @@ -1,3 +0,0 @@ -third_party { - license_type: RESTRICTED -} @@ -15,11 +15,11 @@ cras_install: cras-scripts: $(ECHO) "Installing cras scripts" - $(INSTALL) --mode 755 -d $(DESTDIR)/usr/bin/ + $(INSTALL) --mode 755 -d $(DESTDIR)usr/bin/ $(INSTALL) --mode 755 -D $(ADHD_DIR)/scripts/audio_diagnostics \ - $(DESTDIR)/usr/bin/ + $(DESTDIR)usr/bin/ $(INSTALL) --mode 755 -D $(ADHD_DIR)/scripts/asoc_dapm_graph \ - $(DESTDIR)/usr/bin/ + $(DESTDIR)usr/bin/ cras_init_upstart: $(ADHD_DIR)/init/cras.conf $(ECHO) "Installing upstart file" @@ -52,7 +52,7 @@ cras_init: cras_init_upstart cras_init_scripts endif -$(DESTDIR)/etc/cras/device_blocklist: $(ADHD_DIR)/cras-config/device_blocklist +$(DESTDIR)/etc/cras/device_blacklist: $(ADHD_DIR)/cras-config/device_blacklist $(ECHO) "Installing '$<' to '$@'" $(INSTALL) --mode 644 -D $< $@ @@ -83,7 +83,7 @@ install: $(DESTDIR)/lib/firmware/$(BOARD)_alsa.fw endif -install: $(DESTDIR)/etc/cras/device_blocklist \ +install: $(DESTDIR)/etc/cras/device_blacklist \ cras-scripts \ cras_install \ cras_init diff --git a/OWNERS.fuzz b/OWNERS.fuzz deleted file mode 100644 index 8c7567ff..00000000 --- a/OWNERS.fuzz +++ /dev/null @@ -1,5 +0,0 @@ -cychiang@chromium.org -dgreid@chromium.org -enshuo@chromium.org -paulhsia@chromium.org -chromeos-audio-bugs@google.com diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg index e85e5dc2..c0e6ae9e 100644 --- a/PRESUBMIT.cfg +++ b/PRESUBMIT.cfg @@ -1,7 +1,6 @@ [Hook Overrides] tab_check: false clang_format_check: true -cargo_clippy_check: true # On by default, but required for options below. cros_license_check: true @@ -11,9 +10,3 @@ cros_license_check: true cros_license_check: --exclude_regex=HiFi\.conf$ clang_format_check: cras/ -cargo_clippy_check: - --project=audio_streams - --project=cras/client/cras-sys - --project=cras/client/cras_tests - --project=cras/client/libcras - --project=cras/src/server/rust diff --git a/alsa-module-config/alsa-cid.conf b/alsa-module-config/alsa-cid.conf new file mode 100644 index 00000000..92544684 --- /dev/null +++ b/alsa-module-config/alsa-cid.conf @@ -0,0 +1 @@ +options snd_hda_intel model=cid patch=,cid_alsa.fw diff --git a/alsa-module-config/alsa-falco.conf b/alsa-module-config/alsa-falco.conf new file mode 100644 index 00000000..2a5fcda3 --- /dev/null +++ b/alsa-module-config/alsa-falco.conf @@ -0,0 +1 @@ +options snd_hda_intel model=falco patch=,falco_alsa.fw diff --git a/alsa-module-config/alsa-jecht.conf b/alsa-module-config/alsa-jecht.conf new file mode 100644 index 00000000..550a387f --- /dev/null +++ b/alsa-module-config/alsa-jecht.conf @@ -0,0 +1 @@ +options snd_hda_intel model=jecht patch=,jecht_alsa.fw diff --git a/alsa-module-config/alsa-leon.conf b/alsa-module-config/alsa-leon.conf new file mode 100644 index 00000000..d3a6af37 --- /dev/null +++ b/alsa-module-config/alsa-leon.conf @@ -0,0 +1 @@ +options snd_hda_intel model=leon patch=,leon_alsa.fw diff --git a/alsa-module-config/alsa-mccloud.conf b/alsa-module-config/alsa-mccloud.conf new file mode 100644 index 00000000..f06a52ad --- /dev/null +++ b/alsa-module-config/alsa-mccloud.conf @@ -0,0 +1 @@ +options snd_hda_intel model=mccloud patch=,mccloud_alsa.fw diff --git a/alsa-module-config/alsa-monroe.conf b/alsa-module-config/alsa-monroe.conf new file mode 100644 index 00000000..620f8db3 --- /dev/null +++ b/alsa-module-config/alsa-monroe.conf @@ -0,0 +1 @@ +options snd_hda_intel model=monroe patch=,monroe_alsa.fw diff --git a/alsa-module-config/alsa-peppy.conf b/alsa-module-config/alsa-peppy.conf new file mode 100644 index 00000000..482df733 --- /dev/null +++ b/alsa-module-config/alsa-peppy.conf @@ -0,0 +1 @@ +options snd_hda_intel model=peppy patch=,peppy_alsa.fw diff --git a/alsa-module-config/alsa-rikku.conf b/alsa-module-config/alsa-rikku.conf new file mode 100644 index 00000000..36dec7f2 --- /dev/null +++ b/alsa-module-config/alsa-rikku.conf @@ -0,0 +1 @@ +options snd_hda_intel model=rikku patch=,rikku_alsa.fw diff --git a/alsa-module-config/alsa-stout.conf b/alsa-module-config/alsa-stout.conf new file mode 100644 index 00000000..b1170341 --- /dev/null +++ b/alsa-module-config/alsa-stout.conf @@ -0,0 +1,2 @@ +# Tell patch_realtek that it is running on a stout. +options snd_hda_intel model=stout patch=stout_alsa.fw diff --git a/alsa-module-config/alsa-stout32.conf b/alsa-module-config/alsa-stout32.conf new file mode 100644 index 00000000..847501d1 --- /dev/null +++ b/alsa-module-config/alsa-stout32.conf @@ -0,0 +1,2 @@ +# Tell patch_realtek that it is running on a stout. +options snd_hda_intel model=stout patch=stout32_alsa.fw diff --git a/alsa-module-config/alsa-tidus.conf b/alsa-module-config/alsa-tidus.conf new file mode 100644 index 00000000..868d61e2 --- /dev/null +++ b/alsa-module-config/alsa-tidus.conf @@ -0,0 +1 @@ +options snd_hda_intel model=tidus patch=,tidus_alsa.fw diff --git a/alsa-module-config/alsa-tricky.conf b/alsa-module-config/alsa-tricky.conf new file mode 100644 index 00000000..ba28ce58 --- /dev/null +++ b/alsa-module-config/alsa-tricky.conf @@ -0,0 +1 @@ +options snd_hda_intel model=tricky patch=,tricky_alsa.fw diff --git a/alsa-module-config/alsa-wolf.conf b/alsa-module-config/alsa-wolf.conf new file mode 100644 index 00000000..c7f4f0fc --- /dev/null +++ b/alsa-module-config/alsa-wolf.conf @@ -0,0 +1 @@ +options snd_hda_intel model=wolf patch=,wolf_alsa.fw diff --git a/alsa-module-config/alsa-zako.conf b/alsa-module-config/alsa-zako.conf new file mode 100644 index 00000000..fcd6372a --- /dev/null +++ b/alsa-module-config/alsa-zako.conf @@ -0,0 +1 @@ +options snd_hda_intel model=zako patch=,zako_alsa.fw diff --git a/alsa-module-config/cid_alsa.fw b/alsa-module-config/cid_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/cid_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/falco_alsa.fw b/alsa-module-config/falco_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/falco_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/jecht_alsa.fw b/alsa-module-config/jecht_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/jecht_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/leon_alsa.fw b/alsa-module-config/leon_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/leon_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/mccloud_alsa.fw b/alsa-module-config/mccloud_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/mccloud_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/monroe_alsa.fw b/alsa-module-config/monroe_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/monroe_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/peppy_alsa.fw b/alsa-module-config/peppy_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/peppy_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/rikku_alsa.fw b/alsa-module-config/rikku_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/rikku_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/stout32_alsa.fw b/alsa-module-config/stout32_alsa.fw new file mode 100644 index 00000000..2ba7aa2a --- /dev/null +++ b/alsa-module-config/stout32_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0269 0x17aa21fe 0 + +[model] +stout + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/stout_alsa.fw b/alsa-module-config/stout_alsa.fw new file mode 100644 index 00000000..2ba7aa2a --- /dev/null +++ b/alsa-module-config/stout_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0269 0x17aa21fe 0 + +[model] +stout + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/tidus_alsa.fw b/alsa-module-config/tidus_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/tidus_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/tricky_alsa.fw b/alsa-module-config/tricky_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/tricky_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/wolf_alsa.fw b/alsa-module-config/wolf_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/wolf_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/alsa-module-config/zako_alsa.fw b/alsa-module-config/zako_alsa.fw new file mode 100644 index 00000000..40ac817e --- /dev/null +++ b/alsa-module-config/zako_alsa.fw @@ -0,0 +1,9 @@ +[codec] +0x10ec0283 0x10ec0283 0 + +[model] +alc283-dac-wcaps + +[hint] +auto_mute = no +auto_mic = no diff --git a/audio_streams/.gitignore b/audio_streams/.gitignore deleted file mode 100644 index fa8d85ac..00000000 --- a/audio_streams/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Cargo.lock -target diff --git a/audio_streams/Android.bp b/audio_streams/Android.bp index 2909b544..cbb67437 100644 --- a/audio_streams/Android.bp +++ b/audio_streams/Android.bp @@ -1,61 +1,18 @@ -// This file is generated by cargo2android.py --run --device --test --global_defaults=crosvm_defaults --dependencies. +// This file is generated by cargo2android.py, added defaults. -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "external_adhd_license" - // to get the below license kinds: - // SPDX-license-identifier-BSD - default_applicable_licenses: ["external_adhd_license"], -} - -rust_defaults { - name: "audio_streams_defaults", +rust_test_host { + name: "audio_streams_tests_audio_streams", defaults: ["crosvm_defaults"], crate_name: "audio_streams", srcs: ["src/audio_streams.rs"], + relative_install_path: "audio_streams_tests", test_suites: ["general-tests"], auto_gen_config: true, - edition: "2018", - rustlibs: [ - "libsync_rust", - "libsys_util", - ], } -rust_test_host { - name: "audio_streams_host_test_src_audio_streams", - defaults: ["audio_streams_defaults"], -} - -rust_test { - name: "audio_streams_device_test_src_audio_streams", - defaults: ["audio_streams_defaults"], -} - -rust_library { +rust_library_host_rlib { name: "libaudio_streams", defaults: ["crosvm_defaults"], - host_supported: true, crate_name: "audio_streams", srcs: ["src/audio_streams.rs"], - edition: "2018", - rustlibs: [ - "libsync_rust", - "libsys_util", - ], } - -// dependent_library ["feature_list"] -// ../../crosvm/assertions/src/lib.rs -// ../../crosvm/data_model/src/lib.rs -// ../../crosvm/sync/src/lib.rs -// ../../crosvm/sys_util/poll_token_derive/poll_token_derive.rs -// ../../crosvm/sys_util/src/lib.rs -// ../../crosvm/syscall_defines/src/lib.rs -// ../../crosvm/tempfile/src/lib.rs -// libc-0.2.76 "default,std" -// proc-macro2-1.0.19 "default,proc-macro" -// quote-1.0.7 "default,proc-macro" -// syn-1.0.39 "clone-impls,default,derive,parsing,printing,proc-macro,quote" -// unicode-xid-0.2.1 "default" diff --git a/audio_streams/Cargo.toml b/audio_streams/Cargo.toml index dd169c7f..54e6af63 100644 --- a/audio_streams/Cargo.toml +++ b/audio_streams/Cargo.toml @@ -8,5 +8,3 @@ edition = "2018" path = "src/audio_streams.rs" [dependencies] -sync = { path = "../../crosvm/sync" } # provided by ebuild -sys_util = { path = "../../crosvm/sys_util" } # provided by ebuild diff --git a/audio_streams/README.md b/audio_streams/README.md index d3a02e8f..b62c2946 100644 --- a/audio_streams/README.md +++ b/audio_streams/README.md @@ -2,5 +2,5 @@ The `audio_streams` crate provides a basic interface for playing audio. This will be used to enable playback to various audio subsystems such as -Alsa and cras. To start, an empty playback example `NoopStreamSource` +Alsa and cras. To start, an empty playback example `DummyStreamSource` is provided. diff --git a/audio_streams/src/audio_streams.rs b/audio_streams/src/audio_streams.rs index e5fc83cb..672034b7 100644 --- a/audio_streams/src/audio_streams.rs +++ b/audio_streams/src/audio_streams.rs @@ -13,158 +13,67 @@ //! the samples written to it are committed to the `PlaybackBufferStream` it came from. //! //! ``` -//! use audio_streams::{BoxError, SampleFormat, StreamSource, NoopStreamSource}; +//! use audio_streams::{StreamSource, DummyStreamSource}; //! use std::io::Write; //! //! const buffer_size: usize = 120; //! const num_channels: usize = 2; +//! const frame_size: usize = num_channels * 2; // 16-bit samples are two bytes. //! -//! # fn main() -> std::result::Result<(), BoxError> { -//! let mut stream_source = NoopStreamSource::new(); -//! let sample_format = SampleFormat::S16LE; -//! let frame_size = num_channels * sample_format.sample_bytes(); +//! # fn main() -> std::result::Result<(), Box<std::error::Error>> { +//! let mut stream_source = DummyStreamSource::new(); //! //! let (_, mut stream) = stream_source -//! .new_playback_stream(num_channels, sample_format, 48000, buffer_size)?; +//! .new_playback_stream(num_channels, 48000, buffer_size)?; //! // Play 10 buffers of DC. -//! let mut buf = Vec::new(); -//! buf.resize(buffer_size * frame_size, 0xa5u8); -//! for _ in 0..10 { +//! let pb_bufs = [[0xa5u8; buffer_size * frame_size]; 10]; +//! for pb_buf in &pb_bufs { //! let mut stream_buffer = stream.next_playback_buffer()?; -//! assert_eq!(stream_buffer.write(&buf)?, buffer_size * frame_size); +//! assert_eq!(stream_buffer.write(pb_buf)?, buffer_size * frame_size); //! } //! # Ok (()) //! # } //! ``` -use std::cmp::min; use std::error; use std::fmt::{self, Display}; use std::io::{self, Write}; use std::os::unix::io::RawFd; use std::result::Result; -use std::str::FromStr; use std::time::{Duration, Instant}; -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum SampleFormat { - U8, - S16LE, - S24LE, - S32LE, -} - -impl SampleFormat { - pub fn sample_bytes(self) -> usize { - use SampleFormat::*; - match self { - U8 => 1, - S16LE => 2, - S24LE => 4, // Not a typo, S24_LE samples are stored in 4 byte chunks. - S32LE => 4, - } - } -} - -impl Display for SampleFormat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use SampleFormat::*; - match self { - U8 => write!(f, "Unsigned 8 bit"), - S16LE => write!(f, "Signed 16 bit Little Endian"), - S24LE => write!(f, "Signed 24 bit Little Endian"), - S32LE => write!(f, "Signed 32 bit Little Endian"), - } - } -} - -/// Valid directions of an audio stream. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum StreamDirection { - Playback, - Capture, -} - -/// Valid effects for an audio stream. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum StreamEffect { - NoEffect, - EchoCancellation, -} - pub mod capture; -pub mod shm_streams; - -impl Default for StreamEffect { - fn default() -> Self { - StreamEffect::NoEffect - } -} - -/// Errors that can pass across threads. -pub type BoxError = Box<dyn error::Error + Send + Sync>; - -/// Errors that are possible from a `StreamEffect`. -#[derive(Debug)] -pub enum StreamEffectError { - InvalidEffect, -} - -impl error::Error for StreamEffectError {} - -impl Display for StreamEffectError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - StreamEffectError::InvalidEffect => write!(f, "Must be in [EchoCancellation, aec]"), - } - } -} - -impl FromStr for StreamEffect { - type Err = StreamEffectError; - fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { - match s { - "EchoCancellation" | "aec" => Ok(StreamEffect::EchoCancellation), - _ => Err(StreamEffectError::InvalidEffect), - } - } -} /// `StreamSource` creates streams for playback or capture of audio. pub trait StreamSource: Send { /// Returns a stream control and buffer generator object. These are separate as the buffer /// generator might want to be passed to the audio stream. - #[allow(clippy::type_complexity)] fn new_playback_stream( &mut self, num_channels: usize, - format: SampleFormat, - frame_rate: u32, + frame_rate: usize, buffer_size: usize, - ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError>; + ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>>; /// Returns a stream control and buffer generator object. These are separate as the buffer /// generator might want to be passed to the audio stream. - /// Default implementation returns `NoopStreamControl` and `NoopCaptureStream`. - #[allow(clippy::type_complexity)] + /// Default implementation returns `DummyStreamControl` and `DummyCaptureStream`. fn new_capture_stream( &mut self, num_channels: usize, - format: SampleFormat, - frame_rate: u32, + frame_rate: usize, buffer_size: usize, ) -> Result< ( Box<dyn StreamControl>, Box<dyn capture::CaptureBufferStream>, ), - BoxError, + Box<dyn error::Error>, > { Ok(( - Box::new(NoopStreamControl::new()), - Box::new(capture::NoopCaptureStream::new( + Box::new(DummyStreamControl::new()), + Box::new(capture::DummyCaptureStream::new( num_channels, - format, frame_rate, buffer_size, )), @@ -180,7 +89,7 @@ pub trait StreamSource: Send { /// `PlaybackBufferStream` provides `PlaybackBuffer`s to fill with audio samples for playback. pub trait PlaybackBufferStream: Send { - fn next_playback_buffer(&mut self) -> Result<PlaybackBuffer, BoxError>; + fn next_playback_buffer<'a>(&'a mut self) -> Result<PlaybackBuffer<'a>, Box<dyn error::Error>>; } /// `StreamControl` provides a way to set the volume and mute states of a stream. `StreamControl` @@ -263,10 +172,7 @@ impl<'a> PlaybackBuffer<'a> { /// Writes up to `size` bytes directly to this buffer inside of the given callback function. pub fn copy_cb<F: FnOnce(&mut [u8])>(&mut self, size: usize, cb: F) { // only write complete frames. - let len = min( - size / self.buffer.frame_size * self.buffer.frame_size, - self.buffer.buffer.len() - self.buffer.offset, - ); + let len = size / self.buffer.frame_size * self.buffer.frame_size; cb(&mut self.buffer.buffer[self.buffer.offset..(self.buffer.offset + len)]); self.buffer.offset += len; } @@ -295,55 +201,51 @@ impl<'a> Drop for PlaybackBuffer<'a> { } /// Stream that accepts playback samples but drops them. -pub struct NoopStream { +pub struct DummyStream { buffer: Vec<u8>, frame_size: usize, interval: Duration, next_frame: Duration, start_time: Option<Instant>, - buffer_drop: NoopBufferDrop, + buffer_drop: DummyBufferDrop, } -/// NoopStream data that is needed from the buffer complete callback. -struct NoopBufferDrop { +/// DummyStream data that is needed from the buffer complete callback. +struct DummyBufferDrop { which_buffer: bool, } -impl BufferDrop for NoopBufferDrop { +impl BufferDrop for DummyBufferDrop { fn trigger(&mut self, _nwritten: usize) { // When a buffer completes, switch to the other one. self.which_buffer ^= true; } } -impl NoopStream { - pub fn new( - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - ) -> Self { - let frame_size = format.sample_bytes() * num_channels; +impl DummyStream { + // TODO(allow other formats) + pub fn new(num_channels: usize, frame_rate: usize, buffer_size: usize) -> Self { + const S16LE_SIZE: usize = 2; + let frame_size = S16LE_SIZE * num_channels; let interval = Duration::from_millis(buffer_size as u64 * 1000 / frame_rate as u64); - NoopStream { + DummyStream { buffer: vec![0; buffer_size * frame_size], frame_size, interval, next_frame: interval, start_time: None, - buffer_drop: NoopBufferDrop { + buffer_drop: DummyBufferDrop { which_buffer: false, }, } } } -impl PlaybackBufferStream for NoopStream { - fn next_playback_buffer(&mut self) -> Result<PlaybackBuffer, BoxError> { +impl PlaybackBufferStream for DummyStream { + fn next_playback_buffer<'a>(&'a mut self) -> Result<PlaybackBuffer<'a>, Box<dyn error::Error>> { if let Some(start_time) = self.start_time { - let elapsed = start_time.elapsed(); - if elapsed < self.next_frame { - std::thread::sleep(self.next_frame - elapsed); + if start_time.elapsed() < self.next_frame { + std::thread::sleep(self.next_frame - start_time.elapsed()); } self.next_frame += self.interval; } else { @@ -358,45 +260,39 @@ impl PlaybackBufferStream for NoopStream { } } -/// No-op control for `NoopStream`s. +/// No-op control for `DummyStream`s. #[derive(Default)] -pub struct NoopStreamControl; +pub struct DummyStreamControl; -impl NoopStreamControl { +impl DummyStreamControl { pub fn new() -> Self { - NoopStreamControl {} + DummyStreamControl {} } } -impl StreamControl for NoopStreamControl {} +impl StreamControl for DummyStreamControl {} -/// Source of `NoopStream` and `NoopStreamControl` objects. +/// Source of `DummyStream` and `DummyStreamControl` objects. #[derive(Default)] -pub struct NoopStreamSource; +pub struct DummyStreamSource; -impl NoopStreamSource { +impl DummyStreamSource { pub fn new() -> Self { - NoopStreamSource {} + DummyStreamSource {} } } -impl StreamSource for NoopStreamSource { - #[allow(clippy::type_complexity)] +impl StreamSource for DummyStreamSource { fn new_playback_stream( &mut self, num_channels: usize, - format: SampleFormat, - frame_rate: u32, + frame_rate: usize, buffer_size: usize, - ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> { + ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>> + { Ok(( - Box::new(NoopStreamControl::new()), - Box::new(NoopStream::new( - num_channels, - format, - frame_rate, - buffer_size, - )), + Box::new(DummyStreamControl::new()), + Box::new(DummyStream::new(num_channels, frame_rate, buffer_size)), )) } } @@ -409,7 +305,7 @@ mod tests { fn invalid_buffer_length() { // Playback buffers can't be created with a size that isn't divisible by the frame size. let mut pb_buf = [0xa5u8; 480 * 2 * 2 + 1]; - let mut buffer_drop = NoopBufferDrop { + let mut buffer_drop = DummyBufferDrop { which_buffer: false, }; assert!(PlaybackBuffer::new(2, &mut pb_buf, &mut buffer_drop).is_err()); @@ -430,17 +326,15 @@ mod tests { const FRAME_SIZE: usize = 4; let mut buf = [0u8; 480 * FRAME_SIZE]; let mut pb_buf = PlaybackBuffer::new(FRAME_SIZE, &mut buf, &mut test_drop).unwrap(); - pb_buf.write_all(&[0xa5u8; 480 * FRAME_SIZE]).unwrap(); + pb_buf.write(&[0xa5u8; 480 * FRAME_SIZE]).unwrap(); } assert_eq!(test_drop.frame_count, 480); } #[test] fn sixteen_bit_stereo() { - let mut server = NoopStreamSource::new(); - let (_, mut stream) = server - .new_playback_stream(2, SampleFormat::S16LE, 48000, 480) - .unwrap(); + let mut server = DummyStreamSource::new(); + let (_, mut stream) = server.new_playback_stream(2, 48000, 480).unwrap(); let mut stream_buffer = stream.next_playback_buffer().unwrap(); assert_eq!(stream_buffer.frame_capacity(), 480); let pb_buf = [0xa5u8; 480 * 2 * 2]; @@ -449,10 +343,8 @@ mod tests { #[test] fn consumption_rate() { - let mut server = NoopStreamSource::new(); - let (_, mut stream) = server - .new_playback_stream(2, SampleFormat::S16LE, 48000, 480) - .unwrap(); + let mut server = DummyStreamSource::new(); + let (_, mut stream) = server.new_playback_stream(2, 48000, 480).unwrap(); let start = Instant::now(); { let mut stream_buffer = stream.next_playback_buffer().unwrap(); diff --git a/audio_streams/src/capture.rs b/audio_streams/src/capture.rs index 6a32cf1a..0e58dc8a 100644 --- a/audio_streams/src/capture.rs +++ b/audio_streams/src/capture.rs @@ -2,43 +2,40 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! ``` -//! use audio_streams::{BoxError, SampleFormat, StreamSource, NoopStreamSource}; +//! use audio_streams::{StreamSource, DummyStreamSource}; //! use std::io::Read; //! //! const buffer_size: usize = 120; //! const num_channels: usize = 2; +//! const frame_size: usize = num_channels * 2; // 16-bit samples are two bytes. //! -//! # fn main() -> std::result::Result<(),BoxError> { -//! let mut stream_source = NoopStreamSource::new(); -//! let sample_format = SampleFormat::S16LE; -//! let frame_size = num_channels * sample_format.sample_bytes(); +//! # fn main() -> std::result::Result<(), Box<std::error::Error>> { +//! let mut stream_source = DummyStreamSource::new(); //! //! let (_, mut stream) = stream_source -//! .new_capture_stream(num_channels, sample_format, 48000, buffer_size)?; +//! .new_capture_stream(num_channels, 48000, buffer_size)?; //! // Capture 10 buffers of zeros. -//! let mut buf = Vec::new(); -//! buf.resize(buffer_size * frame_size, 0xa5u8); -//! for _ in 0..10 { +//! let mut cp_bufs = [[0xa5u8; buffer_size * frame_size]; 10]; +//! for cp_buf in &mut cp_bufs { //! let mut stream_buffer = stream.next_capture_buffer()?; -//! assert_eq!(stream_buffer.read(&mut buf)?, buffer_size * frame_size); +//! assert_eq!(stream_buffer.read(cp_buf)?, buffer_size * frame_size); //! } //! # Ok (()) //! # } //! ``` use std::{ - cmp::min, error, fmt::{self, Display}, io::{self, Read, Write}, time::{Duration, Instant}, }; -use super::{AudioBuffer, BoxError, BufferDrop, NoopBufferDrop, SampleFormat}; +use super::{AudioBuffer, BufferDrop, DummyBufferDrop}; /// `CaptureBufferStream` provides `CaptureBuffer`s to read with audio samples from capture. pub trait CaptureBufferStream: Send { - fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, BoxError>; + fn next_capture_buffer<'a>(&'a mut self) -> Result<CaptureBuffer<'a>, Box<dyn error::Error>>; } /// `CaptureBuffer` contains a block of audio samples got from capture stream. It provides @@ -97,10 +94,7 @@ impl<'a> CaptureBuffer<'a> { /// Reads up to `size` bytes directly from this buffer inside of the given callback function. pub fn copy_cb<F: FnOnce(&[u8])>(&mut self, size: usize, cb: F) { - let len = min( - size / self.buffer.frame_size * self.buffer.frame_size, - self.buffer.buffer.len() - self.buffer.offset, - ); + let len = size / self.buffer.frame_size * self.buffer.frame_size; cb(&self.buffer.buffer[self.buffer.offset..(self.buffer.offset + len)]); self.buffer.offset += len; } @@ -123,43 +117,39 @@ impl<'a> Drop for CaptureBuffer<'a> { } /// Stream that provides null capture samples. -pub struct NoopCaptureStream { +pub struct DummyCaptureStream { buffer: Vec<u8>, frame_size: usize, interval: Duration, next_frame: Duration, start_time: Option<Instant>, - buffer_drop: NoopBufferDrop, + buffer_drop: DummyBufferDrop, } -impl NoopCaptureStream { - pub fn new( - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - ) -> Self { - let frame_size = format.sample_bytes() * num_channels; +impl DummyCaptureStream { + // TODO(allow other formats) + pub fn new(num_channels: usize, frame_rate: usize, buffer_size: usize) -> Self { + const S16LE_SIZE: usize = 2; + let frame_size = S16LE_SIZE * num_channels; let interval = Duration::from_millis(buffer_size as u64 * 1000 / frame_rate as u64); - NoopCaptureStream { + DummyCaptureStream { buffer: vec![0; buffer_size * frame_size], frame_size, interval, next_frame: interval, start_time: None, - buffer_drop: NoopBufferDrop { + buffer_drop: DummyBufferDrop { which_buffer: false, }, } } } -impl CaptureBufferStream for NoopCaptureStream { - fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, BoxError> { +impl CaptureBufferStream for DummyCaptureStream { + fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, Box<dyn error::Error>> { if let Some(start_time) = self.start_time { - let elapsed = start_time.elapsed(); - if elapsed < self.next_frame { - std::thread::sleep(self.next_frame - elapsed); + if start_time.elapsed() < self.next_frame { + std::thread::sleep(self.next_frame - start_time.elapsed()); } self.next_frame += self.interval; } else { @@ -183,7 +173,7 @@ mod tests { fn invalid_buffer_length() { // Capture buffers can't be created with a size that isn't divisible by the frame size. let mut cp_buf = [0xa5u8; 480 * 2 * 2 + 1]; - let mut buffer_drop = NoopBufferDrop { + let mut buffer_drop = DummyBufferDrop { which_buffer: false, }; assert!(CaptureBuffer::new(2, &mut cp_buf, &mut buffer_drop).is_err()); @@ -213,10 +203,8 @@ mod tests { #[test] fn sixteen_bit_stereo() { - let mut server = NoopStreamSource::new(); - let (_, mut stream) = server - .new_capture_stream(2, SampleFormat::S16LE, 48000, 480) - .unwrap(); + let mut server = DummyStreamSource::new(); + let (_, mut stream) = server.new_capture_stream(2, 48000, 480).unwrap(); let mut stream_buffer = stream.next_capture_buffer().unwrap(); assert_eq!(stream_buffer.frame_capacity(), 480); let mut pb_buf = [0xa5u8; 480 * 2 * 2]; @@ -225,17 +213,15 @@ mod tests { #[test] fn consumption_rate() { - let mut server = NoopStreamSource::new(); - let (_, mut stream) = server - .new_capture_stream(2, SampleFormat::S16LE, 48000, 480) - .unwrap(); + let mut server = DummyStreamSource::new(); + let (_, mut stream) = server.new_capture_stream(2, 48000, 480).unwrap(); let start = Instant::now(); { let mut stream_buffer = stream.next_capture_buffer().unwrap(); let mut cp_buf = [0xa5u8; 480 * 2 * 2]; assert_eq!(stream_buffer.read(&mut cp_buf).unwrap(), 480 * 2 * 2); - for buf in cp_buf.iter() { - assert_eq!(*buf, 0, "Read samples should all be zeros."); + for i in 0..cp_buf.len() { + assert_eq!(cp_buf[i], 0, "Read samples should all be zeros."); } } // The second call should block until the first buffer is consumed. @@ -247,4 +233,5 @@ mod tests { elapsed.subsec_millis() ); } + } diff --git a/audio_streams/src/shm_streams.rs b/audio_streams/src/shm_streams.rs deleted file mode 100644 index b11626fd..00000000 --- a/audio_streams/src/shm_streams.rs +++ /dev/null @@ -1,568 +0,0 @@ -// Copyright 2019 The Chromium OS 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 std::error; -use std::fmt; -use std::os::unix::io::RawFd; -use std::sync::Arc; -use std::time::{Duration, Instant}; - -use sync::{Condvar, Mutex}; -use sys_util::SharedMemory; - -use crate::{BoxError, SampleFormat, StreamDirection, StreamEffect}; - -type GenericResult<T> = std::result::Result<T, BoxError>; - -/// `BufferSet` is used as a callback mechanism for `ServerRequest` objects. -/// It is meant to be implemented by the audio stream, allowing arbitrary code -/// to be run after a buffer offset and length is set. -pub trait BufferSet { - /// Called when the client sets a buffer offset and length. - /// - /// `offset` is the offset within shared memory of the buffer and `frames` - /// indicates the number of audio frames that can be read from or written to - /// the buffer. - fn callback(&mut self, offset: usize, frames: usize) -> GenericResult<()>; - - /// Called when the client ignores a request from the server. - fn ignore(&mut self) -> GenericResult<()>; -} - -#[derive(Debug)] -pub enum Error { - TooManyFrames(usize, usize), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::TooManyFrames(provided, requested) => write!( - f, - "Provided number of frames {} exceeds requested number of frames {}", - provided, requested - ), - } - } -} - -/// `ServerRequest` represents an active request from the server for the client -/// to provide a buffer in shared memory to playback from or capture to. -pub struct ServerRequest<'a> { - requested_frames: usize, - buffer_set: &'a mut dyn BufferSet, -} - -impl<'a> ServerRequest<'a> { - /// Create a new ServerRequest object - /// - /// Create a ServerRequest object representing a request from the server - /// for a buffer `requested_frames` in size. - /// - /// When the client responds to this request by calling - /// [`set_buffer_offset_and_frames`](ServerRequest::set_buffer_offset_and_frames), - /// BufferSet::callback will be called on `buffer_set`. - /// - /// # Arguments - /// * `requested_frames` - The requested buffer size in frames. - /// * `buffer_set` - The object implementing the callback for when a buffer is provided. - pub fn new<D: BufferSet>(requested_frames: usize, buffer_set: &'a mut D) -> Self { - Self { - requested_frames, - buffer_set, - } - } - - /// Get the number of frames of audio data requested by the server. - /// - /// The returned value should never be greater than the `buffer_size` - /// given in [`new_stream`](ShmStreamSource::new_stream). - pub fn requested_frames(&self) -> usize { - self.requested_frames - } - - /// Sets the buffer offset and length for the requested buffer. - /// - /// Sets the buffer offset and length of the buffer that fulfills this - /// server request to `offset` and `length`, respectively. This means that - /// `length` bytes of audio samples may be read from/written to that - /// location in `client_shm` for a playback/capture stream, respectively. - /// This function may only be called once for a `ServerRequest`, at which - /// point the ServerRequest is dropped and no further calls are possible. - /// - /// # Arguments - /// - /// * `offset` - The value to use as the new buffer offset for the next buffer. - /// * `frames` - The length of the next buffer in frames. - /// - /// # Errors - /// - /// * If `frames` is greater than `requested_frames`. - pub fn set_buffer_offset_and_frames(self, offset: usize, frames: usize) -> GenericResult<()> { - if frames > self.requested_frames { - return Err(Box::new(Error::TooManyFrames( - frames, - self.requested_frames, - ))); - } - - self.buffer_set.callback(offset, frames) - } - - /// Ignore this request - /// - /// If the client does not intend to respond to this ServerRequest with a - /// buffer, they should call this function. The stream will be notified that - /// the request has been ignored and will handle it properly. - pub fn ignore_request(self) -> GenericResult<()> { - self.buffer_set.ignore() - } -} - -/// `ShmStream` allows a client to interact with an active CRAS stream. -pub trait ShmStream: Send { - /// Get the size of a frame of audio data for this stream. - fn frame_size(&self) -> usize; - - /// Get the number of channels of audio data for this stream. - fn num_channels(&self) -> usize; - - /// Get the frame rate of audio data for this stream. - fn frame_rate(&self) -> u32; - - /// Waits until the next server message indicating action is required. - /// - /// For playback streams, this will be `AUDIO_MESSAGE_REQUEST_DATA`, meaning - /// that we must set the buffer offset to the next location where playback - /// data can be found. - /// For capture streams, this will be `AUDIO_MESSAGE_DATA_READY`, meaning - /// that we must set the buffer offset to the next location where captured - /// data can be written to. - /// Will return early if `timeout` elapses before a message is received. - /// - /// # Arguments - /// - /// * `timeout` - The amount of time to wait until a message is received. - /// - /// # Return value - /// - /// Returns `Some(request)` where `request` is an object that implements the - /// [`ServerRequest`](ServerRequest) trait and which can be used to get the - /// number of bytes requested for playback streams or that have already been - /// written to shm for capture streams. - /// - /// If the timeout occurs before a message is received, returns `None`. - /// - /// # Errors - /// - /// * If an invalid message type is received for the stream. - fn wait_for_next_action_with_timeout( - &mut self, - timeout: Duration, - ) -> GenericResult<Option<ServerRequest>>; -} - -/// `ShmStreamSource` creates streams for playback or capture of audio. -pub trait ShmStreamSource: Send { - /// Creates a new [`ShmStream`](ShmStream) - /// - /// Creates a new `ShmStream` object, which allows: - /// * Waiting until the server has communicated that data is ready or - /// requested that we make more data available. - /// * Setting the location and length of buffers for reading/writing audio data. - /// - /// # Arguments - /// - /// * `direction` - The direction of the stream, either `Playback` or `Capture`. - /// * `num_channels` - The number of audio channels for the stream. - /// * `format` - The audio format to use for audio samples. - /// * `frame_rate` - The stream's frame rate in Hz. - /// * `buffer_size` - The maximum size of an audio buffer. This will be the - /// size used for transfers of audio data between client - /// and server. - /// * `effects` - Audio effects to use for the stream, such as echo-cancellation. - /// * `client_shm` - The shared memory area that will contain samples. - /// * `buffer_offsets` - The two initial values to use as buffer offsets - /// for streams. This way, the server will not write - /// audio data to an arbitrary offset in `client_shm` - /// if the client fails to update offsets in time. - /// - /// # Errors - /// - /// * If sending the connect stream message to the server fails. - #[allow(clippy::too_many_arguments)] - fn new_stream( - &mut self, - direction: StreamDirection, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - effects: &[StreamEffect], - client_shm: &SharedMemory, - buffer_offsets: [u64; 2], - ) -> GenericResult<Box<dyn ShmStream>>; - - /// Get a list of file descriptors used by the implementation. - /// - /// Returns any open file descriptors needed by the implementation. - /// This list helps users of the ShmStreamSource enter Linux jails without - /// closing needed file descriptors. - fn keep_fds(&self) -> Vec<RawFd> { - Vec::new() - } -} - -/// Class that implements ShmStream trait but does nothing with the samples -pub struct NullShmStream { - num_channels: usize, - frame_rate: u32, - buffer_size: usize, - frame_size: usize, - interval: Duration, - next_frame: Duration, - start_time: Instant, -} - -impl NullShmStream { - /// Attempt to create a new NullShmStream with the given number of channels, - /// format, frame_rate, and buffer_size. - pub fn new( - buffer_size: usize, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - ) -> Self { - let interval = Duration::from_millis(buffer_size as u64 * 1000 / frame_rate as u64); - Self { - num_channels, - frame_rate, - buffer_size, - frame_size: format.sample_bytes() * num_channels, - interval, - next_frame: interval, - start_time: Instant::now(), - } - } -} - -impl BufferSet for NullShmStream { - fn callback(&mut self, _offset: usize, _frames: usize) -> GenericResult<()> { - Ok(()) - } - - fn ignore(&mut self) -> GenericResult<()> { - Ok(()) - } -} - -impl ShmStream for NullShmStream { - fn frame_size(&self) -> usize { - self.frame_size - } - - fn num_channels(&self) -> usize { - self.num_channels - } - - fn frame_rate(&self) -> u32 { - self.frame_rate - } - - fn wait_for_next_action_with_timeout( - &mut self, - timeout: Duration, - ) -> GenericResult<Option<ServerRequest>> { - let elapsed = self.start_time.elapsed(); - if elapsed < self.next_frame { - if timeout < self.next_frame - elapsed { - std::thread::sleep(timeout); - return Ok(None); - } else { - std::thread::sleep(self.next_frame - elapsed); - } - } - self.next_frame += self.interval; - Ok(Some(ServerRequest::new(self.buffer_size, self))) - } -} - -/// Source of `NullShmStream` objects. -#[derive(Default)] -pub struct NullShmStreamSource; - -impl NullShmStreamSource { - pub fn new() -> Self { - Self::default() - } -} - -impl ShmStreamSource for NullShmStreamSource { - fn new_stream( - &mut self, - _direction: StreamDirection, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - _effects: &[StreamEffect], - _client_shm: &SharedMemory, - _buffer_offsets: [u64; 2], - ) -> GenericResult<Box<dyn ShmStream>> { - let new_stream = NullShmStream::new(buffer_size, num_channels, format, frame_rate); - Ok(Box::new(new_stream)) - } -} - -#[derive(Clone)] -pub struct MockShmStream { - num_channels: usize, - frame_rate: u32, - request_size: usize, - frame_size: usize, - request_notifier: Arc<(Mutex<bool>, Condvar)>, -} - -impl MockShmStream { - /// Attempt to create a new MockShmStream with the given number of - /// channels, frame_rate, format, and buffer_size. - pub fn new( - num_channels: usize, - frame_rate: u32, - format: SampleFormat, - buffer_size: usize, - ) -> Self { - Self { - num_channels, - frame_rate, - request_size: buffer_size, - frame_size: format.sample_bytes() * num_channels, - request_notifier: Arc::new((Mutex::new(false), Condvar::new())), - } - } - - /// Call to request data from the stream, causing it to return from - /// `wait_for_next_action_with_timeout`. Will block until - /// `set_buffer_offset_and_frames` is called on the ServerRequest returned - /// from `wait_for_next_action_with_timeout`, or until `timeout` elapses. - /// Returns true if a response was successfully received. - pub fn trigger_callback_with_timeout(&mut self, timeout: Duration) -> bool { - let &(ref lock, ref cvar) = &*self.request_notifier; - let mut requested = lock.lock(); - *requested = true; - cvar.notify_one(); - let start_time = Instant::now(); - while *requested { - requested = cvar.wait_timeout(requested, timeout).0; - if start_time.elapsed() > timeout { - // We failed to get a callback in time, mark this as false. - *requested = false; - return false; - } - } - - true - } - - fn notify_request(&mut self) { - let &(ref lock, ref cvar) = &*self.request_notifier; - let mut requested = lock.lock(); - *requested = false; - cvar.notify_one(); - } -} - -impl BufferSet for MockShmStream { - fn callback(&mut self, _offset: usize, _frames: usize) -> GenericResult<()> { - self.notify_request(); - Ok(()) - } - - fn ignore(&mut self) -> GenericResult<()> { - self.notify_request(); - Ok(()) - } -} - -impl ShmStream for MockShmStream { - fn frame_size(&self) -> usize { - self.frame_size - } - - fn num_channels(&self) -> usize { - self.num_channels - } - - fn frame_rate(&self) -> u32 { - self.frame_rate - } - - fn wait_for_next_action_with_timeout( - &mut self, - timeout: Duration, - ) -> GenericResult<Option<ServerRequest>> { - { - let start_time = Instant::now(); - let &(ref lock, ref cvar) = &*self.request_notifier; - let mut requested = lock.lock(); - while !*requested { - requested = cvar.wait_timeout(requested, timeout).0; - if start_time.elapsed() > timeout { - return Ok(None); - } - } - } - - Ok(Some(ServerRequest::new(self.request_size, self))) - } -} - -/// Source of `MockShmStream` objects. -#[derive(Clone, Default)] -pub struct MockShmStreamSource { - last_stream: Arc<(Mutex<Option<MockShmStream>>, Condvar)>, -} - -impl MockShmStreamSource { - pub fn new() -> Self { - Default::default() - } - - /// Get the last stream that has been created from this source. If no stream - /// has been created, block until one has. - pub fn get_last_stream(&self) -> MockShmStream { - let &(ref last_stream, ref cvar) = &*self.last_stream; - let mut stream = last_stream.lock(); - loop { - match &*stream { - None => stream = cvar.wait(stream), - Some(ref s) => return s.clone(), - }; - } - } -} - -impl ShmStreamSource for MockShmStreamSource { - fn new_stream( - &mut self, - _direction: StreamDirection, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - _effects: &[StreamEffect], - _client_shm: &SharedMemory, - _buffer_offsets: [u64; 2], - ) -> GenericResult<Box<dyn ShmStream>> { - let &(ref last_stream, ref cvar) = &*self.last_stream; - let mut stream = last_stream.lock(); - - let new_stream = MockShmStream::new(num_channels, frame_rate, format, buffer_size); - *stream = Some(new_stream.clone()); - cvar.notify_one(); - Ok(Box::new(new_stream)) - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - - #[test] - fn mock_trigger_callback() { - let stream_source = MockShmStreamSource::new(); - let mut thread_stream_source = stream_source.clone(); - - let buffer_size = 480; - let num_channels = 2; - let format = SampleFormat::S24LE; - let shm = SharedMemory::anon().expect("Failed to create shm"); - - let handle = std::thread::spawn(move || { - let mut stream = thread_stream_source - .new_stream( - StreamDirection::Playback, - num_channels, - format, - 44100, - buffer_size, - &[], - &shm, - [400, 8000], - ) - .expect("Failed to create stream"); - - let request = stream - .wait_for_next_action_with_timeout(Duration::from_secs(5)) - .expect("Failed to wait for next action"); - match request { - Some(r) => { - let requested = r.requested_frames(); - r.set_buffer_offset_and_frames(872, requested) - .expect("Failed to set buffer offset and frames"); - requested - } - None => 0, - } - }); - - let mut stream = stream_source.get_last_stream(); - assert!(stream.trigger_callback_with_timeout(Duration::from_secs(1))); - - let requested_frames = handle.join().expect("Failed to join thread"); - assert_eq!(requested_frames, buffer_size); - } - - #[test] - fn null_consumption_rate() { - let frame_rate = 44100; - let buffer_size = 480; - let interval = Duration::from_millis(buffer_size as u64 * 1000 / frame_rate as u64); - - let shm = SharedMemory::anon().expect("Failed to create shm"); - - let start = Instant::now(); - - let mut stream_source = NullShmStreamSource::new(); - let mut stream = stream_source - .new_stream( - StreamDirection::Playback, - 2, - SampleFormat::S24LE, - frame_rate, - buffer_size, - &[], - &shm, - [400, 8000], - ) - .expect("Failed to create stream"); - - let timeout = Duration::from_secs(5); - let request = stream - .wait_for_next_action_with_timeout(timeout) - .expect("Failed to wait for first request") - .expect("First request should not have timed out"); - request - .set_buffer_offset_and_frames(276, 480) - .expect("Failed to set buffer offset and length"); - - // The second call should block until the first buffer is consumed. - let _request = stream - .wait_for_next_action_with_timeout(timeout) - .expect("Failed to wait for second request"); - let elapsed = start.elapsed(); - assert!( - elapsed > interval, - "wait_for_next_action_with_timeout didn't block long enough: {:?}", - elapsed - ); - - assert!( - elapsed < timeout, - "wait_for_next_action_with_timeout blocked for too long: {:?}", - elapsed - ); - } -} diff --git a/cras-config/bolt/HDA Intel PCH b/cras-config/bolt/HDA Intel PCH new file mode 100644 index 00000000..b3865e6e --- /dev/null +++ b/cras-config/bolt/HDA Intel PCH @@ -0,0 +1,107 @@ +[Default] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -100 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -300 + db_at_90 = -300 + db_at_89 = -300 + db_at_88 = -300 + db_at_87 = -400 + db_at_86 = -400 + db_at_85 = -400 + db_at_84 = -400 + db_at_83 = -500 + db_at_82 = -500 + db_at_81 = -500 + db_at_80 = -500 + db_at_79 = -600 + db_at_78 = -600 + db_at_77 = -600 + db_at_76 = -600 + db_at_75 = -700 + db_at_74 = -700 + db_at_73 = -700 + db_at_72 = -700 + db_at_71 = -800 + db_at_70 = -800 + db_at_69 = -800 + db_at_68 = -800 + db_at_67 = -900 + db_at_66 = -900 + db_at_65 = -900 + db_at_64 = -900 + db_at_63 = -900 + db_at_62 = -900 + db_at_61 = -900 + db_at_60 = -1000 + db_at_59 = -1000 + db_at_58 = -1000 + db_at_57 = -1000 + db_at_56 = -1100 + db_at_55 = -1100 + db_at_54 = -1100 + db_at_53 = -1100 + db_at_52 = -1200 + db_at_51 = -1200 + db_at_50 = -1200 + db_at_49 = -1200 + db_at_48 = -1300 + db_at_47 = -1300 + db_at_46 = -1300 + db_at_45 = -1300 + db_at_44 = -1400 + db_at_43 = -1400 + db_at_42 = -1400 + db_at_41 = -1400 + db_at_40 = -1500 + db_at_39 = -1600 + db_at_38 = -1600 + db_at_37 = -1700 + db_at_36 = -1700 + db_at_35 = -1800 + db_at_34 = -1900 + db_at_33 = -2000 + db_at_32 = -2100 + db_at_31 = -2200 + db_at_30 = -2300 + db_at_29 = -2400 + db_at_28 = -2500 + db_at_27 = -2600 + db_at_26 = -2700 + db_at_25 = -2800 + db_at_24 = -2900 + db_at_23 = -3000 + db_at_22 = -3100 + db_at_21 = -3200 + db_at_20 = -3300 + db_at_19 = -3400 + db_at_18 = -3500 + db_at_17 = -3600 + db_at_16 = -3700 + db_at_15 = -3800 + db_at_14 = -3900 + db_at_13 = -4000 + db_at_12 = -4100 + db_at_11 = -4200 + db_at_10 = -4300 + db_at_9 = -4400 + db_at_8 = -4500 + db_at_7 = -4600 + db_at_6 = -4800 + db_at_5 = -5000 + db_at_4 = -5200 + db_at_3 = -5400 + db_at_2 = -5600 + db_at_1 = -5800 + db_at_0 = -6000 +[Front Headphone Jack] + volume_curve = simple_step + volume_step = 75 + max_volume = -900 diff --git a/cras-config/cid/HDA Intel PCH b/cras-config/cid/HDA Intel PCH new file mode 100644 index 00000000..e0adc3e9 --- /dev/null +++ b/cras-config/cid/HDA Intel PCH @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -75 + db_at_98 = -75 + db_at_97 = -75 + db_at_96 = -75 + db_at_95 = -75 + db_at_94 = -150 + db_at_93 = -150 + db_at_92 = -150 + db_at_91 = -150 + db_at_90 = -225 + db_at_89 = -225 + db_at_88 = -225 + db_at_87 = -225 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -375 + db_at_81 = -375 + db_at_80 = -450 + db_at_79 = -450 + db_at_78 = -450 + db_at_77 = -450 + db_at_76 = -525 + db_at_75 = -525 + db_at_74 = -600 + db_at_73 = -600 + db_at_72 = -600 + db_at_71 = -600 + db_at_70 = -675 + db_at_69 = -675 + db_at_68 = -675 + db_at_67 = -675 + db_at_66 = -750 + db_at_65 = -750 + db_at_64 = -825 + db_at_63 = -825 + db_at_62 = -825 + db_at_61 = -825 + db_at_60 = -900 + db_at_59 = -900 + db_at_58 = -900 + db_at_57 = -900 + db_at_56 = -975 + db_at_55 = -975 + db_at_54 = -1050 + db_at_53 = -1050 + db_at_52 = -1050 + db_at_51 = -1050 + db_at_50 = -1125 + db_at_49 = -1125 + db_at_48 = -1200 + db_at_47 = -1200 + db_at_46 = -1200 + db_at_45 = -1200 + db_at_44 = -1275 + db_at_43 = -1275 + db_at_42 = -1275 + db_at_41 = -1275 + db_at_40 = -1350 + db_at_39 = -1425 + db_at_38 = -1425 + db_at_37 = -1500 + db_at_36 = -1500 + db_at_35 = -1575 + db_at_34 = -1650 + db_at_33 = -1650 + db_at_32 = -1725 + db_at_31 = -1800 + db_at_30 = -1800 + db_at_29 = -1800 + db_at_28 = -1875 + db_at_27 = -2025 + db_at_26 = -2100 + db_at_25 = -2100 + db_at_24 = -2175 + db_at_23 = -2250 + db_at_22 = -2400 + db_at_21 = -2475 + db_at_20 = -2550 + db_at_19 = -2625 + db_at_18 = -2700 + db_at_17 = -2850 + db_at_16 = -2925 + db_at_15 = -3000 + db_at_14 = -3075 + db_at_13 = -3225 + db_at_12 = -3300 + db_at_11 = -3375 + db_at_10 = -3450 + db_at_9 = -3600 + db_at_8 = -3675 + db_at_7 = -3750 + db_at_6 = -3825 + db_at_5 = -3900 + db_at_4 = -4050 + db_at_3 = -4050 + db_at_2 = -4275 + db_at_1 = -4500 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 50 + max_volume = 0 diff --git a/cras-config/daisy/DAISY-I2S b/cras-config/daisy/DAISY-I2S new file mode 100755 index 00000000..949658d6 --- /dev/null +++ b/cras-config/daisy/DAISY-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -900 + db_at_99 = -900 + db_at_98 = -900 + db_at_97 = -950 + db_at_96 = -950 + db_at_95 = -950 + db_at_94 = -1000 + db_at_93 = -1000 + db_at_92 = -1000 + db_at_91 = -1050 + db_at_90 = -1050 + db_at_89 = -1050 + db_at_88 = -1100 + db_at_87 = -1100 + db_at_86 = -1100 + db_at_85 = -1150 + db_at_84 = -1150 + db_at_83 = -1150 + db_at_82 = -1200 + db_at_81 = -1200 + db_at_80 = -1200 + db_at_79 = -1250 + db_at_78 = -1250 + db_at_77 = -1250 + db_at_76 = -1300 + db_at_75 = -1300 + db_at_74 = -1300 + db_at_73 = -1350 + db_at_72 = -1350 + db_at_71 = -1350 + db_at_70 = -1425 + db_at_69 = -1425 + db_at_68 = -1425 + db_at_67 = -1500 + db_at_66 = -1500 + db_at_65 = -1500 + db_at_64 = -1575 + db_at_63 = -1575 + db_at_62 = -1575 + db_at_61 = -1650 + db_at_60 = -1650 + db_at_59 = -1650 + db_at_58 = -1725 + db_at_57 = -1725 + db_at_56 = -1725 + db_at_55 = -1800 + db_at_54 = -1800 + db_at_53 = -1800 + db_at_52 = -1900 + db_at_51 = -1900 + db_at_50 = -1900 + db_at_49 = -2000 + db_at_48 = -2000 + db_at_47 = -2000 + db_at_46 = -2100 + db_at_45 = -2100 + db_at_44 = -2100 + db_at_43 = -2200 + db_at_42 = -2200 + db_at_41 = -2200 + db_at_40 = -2350 + db_at_39 = -2350 + db_at_38 = -2350 + db_at_37 = -2500 + db_at_36 = -2500 + db_at_35 = -2500 + db_at_34 = -2650 + db_at_33 = -2650 + db_at_32 = -2650 + db_at_31 = -2725 + db_at_30 = -2725 + db_at_29 = -2800 + db_at_28 = -3000 + db_at_27 = -3000 + db_at_26 = -3000 + db_at_25 = -3200 + db_at_24 = -3200 + db_at_23 = -3200 + db_at_22 = -3200 + db_at_21 = -3600 + db_at_20 = -3600 + db_at_19 = -4000 + db_at_18 = -4000 + db_at_17 = -4000 + db_at_16 = -4000 + db_at_15 = -4400 + db_at_14 = -4400 + db_at_13 = -4400 + db_at_12 = -4400 + db_at_11 = -4800 + db_at_10 = -4800 + db_at_9 = -4800 + db_at_8 = -4800 + db_at_7 = -5000 + db_at_6 = -5000 + db_at_5 = -5200 + db_at_4 = -5200 + db_at_3 = -5200 + db_at_2 = -5200 + db_at_1 = -5600 + db_at_0 = -6000 +[Headphone] + volume_curve = simple_step ; Headphones allowed full range, 0.5dB per step, 50dB total range. + volume_step = 50 + max_volume = -200 diff --git a/cras-config/daisy/DAISY-I2S-98090 b/cras-config/daisy/DAISY-I2S-98090 new file mode 100755 index 00000000..f6420238 --- /dev/null +++ b/cras-config/daisy/DAISY-I2S-98090 @@ -0,0 +1,206 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -500 + db_at_98 = -500 + db_at_97 = -500 + db_at_96 = -600 + db_at_95 = -600 + db_at_94 = -600 + db_at_93 = -600 + db_at_92 = -700 + db_at_91 = -700 + db_at_90 = -700 + db_at_89 = -700 + db_at_88 = -800 + db_at_87 = -800 + db_at_86 = -800 + db_at_85 = -800 + db_at_84 = -900 + db_at_83 = -900 + db_at_82 = -900 + db_at_81 = -900 + db_at_80 = -1000 + db_at_79 = -1000 + db_at_78 = -1000 + db_at_77 = -1000 + db_at_76 = -1100 + db_at_75 = -1100 + db_at_74 = -1100 + db_at_73 = -1100 + db_at_72 = -1200 + db_at_71 = -1200 + db_at_70 = -1200 + db_at_69 = -1200 + db_at_68 = -1300 + db_at_67 = -1300 + db_at_66 = -1300 + db_at_65 = -1300 + db_at_64 = -1400 + db_at_63 = -1400 + db_at_62 = -1400 + db_at_61 = -1400 + db_at_60 = -1500 + db_at_59 = -1500 + db_at_58 = -1500 + db_at_57 = -1500 + db_at_56 = -1600 + db_at_55 = -1600 + db_at_54 = -1600 + db_at_53 = -1600 + db_at_52 = -1700 + db_at_51 = -1700 + db_at_50 = -1700 + db_at_49 = -1700 + db_at_48 = -1800 + db_at_47 = -1800 + db_at_46 = -1800 + db_at_45 = -1800 + db_at_44 = -1900 + db_at_43 = -1900 + db_at_42 = -1900 + db_at_41 = -1900 + db_at_40 = -2100 + db_at_39 = -2100 + db_at_38 = -2100 + db_at_37 = -2100 + db_at_36 = -2300 + db_at_35 = -2300 + db_at_34 = -2300 + db_at_33 = -2300 + db_at_32 = -2500 + db_at_31 = -2500 + db_at_30 = -2500 + db_at_29 = -2500 + db_at_28 = -2700 + db_at_27 = -2700 + db_at_26 = -2700 + db_at_25 = -2700 + db_at_24 = -2900 + db_at_23 = -2900 + db_at_22 = -2900 + db_at_21 = -2900 + db_at_20 = -3300 + db_at_19 = -3300 + db_at_18 = -3300 + db_at_17 = -3300 + db_at_16 = -3600 + db_at_15 = -3600 + db_at_14 = -3600 + db_at_13 = -3600 + db_at_12 = -4300 + db_at_11 = -4300 + db_at_10 = -4300 + db_at_9 = -4300 + db_at_8 = -4900 + db_at_7 = -4900 + db_at_6 = -4900 + db_at_5 = -4900 + db_at_4 = -5500 + db_at_3 = -5500 + db_at_2 = -5500 + db_at_1 = -5500 + db_at_0 = -6500 +[Headphone] + volume_curve = explicit + db_at_100 = -1000 + db_at_99 = -1000 + db_at_98 = -1000 + db_at_97 = -1000 + db_at_96 = -1200 + db_at_95 = -1200 + db_at_94 = -1200 + db_at_93 = -1200 + db_at_92 = -1400 + db_at_91 = -1400 + db_at_90 = -1400 + db_at_89 = -1400 + db_at_88 = -1600 + db_at_87 = -1600 + db_at_86 = -1600 + db_at_85 = -1600 + db_at_84 = -1800 + db_at_83 = -1800 + db_at_82 = -1800 + db_at_81 = -1800 + db_at_80 = -2000 + db_at_79 = -2000 + db_at_78 = -2000 + db_at_77 = -2000 + db_at_76 = -2200 + db_at_75 = -2200 + db_at_74 = -2200 + db_at_73 = -2200 + db_at_72 = -2300 + db_at_71 = -2300 + db_at_70 = -2300 + db_at_69 = -2300 + db_at_68 = -2500 + db_at_67 = -2500 + db_at_66 = -2500 + db_at_65 = -2500 + db_at_64 = -2700 + db_at_63 = -2700 + db_at_62 = -2700 + db_at_61 = -2700 + db_at_60 = -2900 + db_at_59 = -2900 + db_at_58 = -2900 + db_at_57 = -2900 + db_at_56 = -3100 + db_at_55 = -3100 + db_at_54 = -3100 + db_at_53 = -3100 + db_at_52 = -3300 + db_at_51 = -3300 + db_at_50 = -3300 + db_at_49 = -3300 + db_at_48 = -3500 + db_at_47 = -3500 + db_at_46 = -3500 + db_at_45 = -3500 + db_at_44 = -3700 + db_at_43 = -3700 + db_at_42 = -3700 + db_at_41 = -3700 + db_at_40 = -4000 + db_at_39 = -4000 + db_at_38 = -4000 + db_at_37 = -4000 + db_at_36 = -4300 + db_at_35 = -4300 + db_at_34 = -4300 + db_at_33 = -4300 + db_at_32 = -4600 + db_at_31 = -4600 + db_at_30 = -4600 + db_at_29 = -4600 + db_at_28 = -4900 + db_at_27 = -4900 + db_at_26 = -4900 + db_at_25 = -4900 + db_at_24 = -5200 + db_at_23 = -5200 + db_at_22 = -5200 + db_at_21 = -5200 + db_at_20 = -5500 + db_at_19 = -5500 + db_at_18 = -5500 + db_at_17 = -5500 + db_at_16 = -5800 + db_at_15 = -5800 + db_at_14 = -5800 + db_at_13 = -5800 + db_at_12 = -6200 + db_at_11 = -6200 + db_at_10 = -6200 + db_at_9 = -6200 + db_at_8 = -6600 + db_at_7 = -6600 + db_at_6 = -6600 + db_at_5 = -6600 + db_at_4 = -7000 + db_at_3 = -7000 + db_at_2 = -7000 + db_at_1 = -7000 + db_at_0 = -7400 diff --git a/cras-config/daisy/dsp.ini b/cras-config/daisy/dsp.ini new file mode 100644 index 00000000..e675d558 --- /dev/null +++ b/cras-config/daisy/dsp.ini @@ -0,0 +1,46 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[eq2] +library=builtin +label=eq2 +input_0={src:0} +input_1={src:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=150 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=150 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=1051 ; freq +input_14=2 ; Q +input_15=-3 ; gain +input_16=6 ; peaking +input_17=1051 ; freq +input_18=2 ; Q +input_19=-3 ; gain +input_20=6 ; peaking +input_21=4146 ; freq +input_22=3 ; Q +input_23=-3 ; gain +input_24=6 ; peaking +input_25=4146 ; freq +input_26=3 ; Q +input_27=-3 ; gain diff --git a/cras-config/daisy_skate/dsp.ini b/cras-config/daisy_skate/dsp.ini new file mode 100644 index 00000000..7c94fc0d --- /dev/null +++ b/cras-config/daisy_skate/dsp.ini @@ -0,0 +1,111 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-24 ; threshold +input_8=30 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=2 ; boost +input_13=200 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=30 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=2 ; boost +input_21=2000 ; f +input_22=1 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=2 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=200 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=200 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=350 ; freq +input_14=1 ; Q +input_15=3 ; gain +input_16=6 ; peaking +input_17=350 ; freq +input_18=1 ; Q +input_19=3 ; gain +input_20=6 ; peaking +input_21=1000 ; freq +input_22=1 ; Q +input_23=-8 ; gain +input_24=6 ; peaking +input_25=1000 ; freq +input_26=1 ; Q +input_27=-8 ; gain +input_28=6 ; peaking +input_29=5000 ; freq +input_30=1 ; Q +input_31=3 ; gain +input_32=6 ; peaking +input_33=5000 ; freq +input_34=1 ; Q +input_35=3 ; gain +input_36=6 ; peaking +input_37=8000 ; freq +input_38=1 ; Q +input_39=3 ; gain +input_40=6 ; peaking +input_41=8000 ; freq +input_42=1 ; Q +input_43=3 ; gain +input_44=6 ; peaking +input_45=10000 ; freq +input_46=1 ; Q +input_47=3 ; gain +input_48=6 ; peaking +input_49=10000 ; freq +input_50=1 ; Q +input_51=3 ; gain +input_52=6 ; peaking +input_53=2000 ; freq +input_54=1 ; Q +input_55=-2 ; gain +input_56=6 ; peaking +input_57=2000 ; freq +input_58=1 ; Q +input_59=-2 ; gain diff --git a/cras-config/daisy_spring/DAISY-I2S b/cras-config/daisy_spring/DAISY-I2S new file mode 100755 index 00000000..ae9801a4 --- /dev/null +++ b/cras-config/daisy_spring/DAISY-I2S @@ -0,0 +1,206 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -100 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -300 + db_at_90 = -300 + db_at_89 = -300 + db_at_88 = -300 + db_at_87 = -400 + db_at_86 = -400 + db_at_85 = -400 + db_at_84 = -400 + db_at_83 = -500 + db_at_82 = -500 + db_at_81 = -500 + db_at_80 = -500 + db_at_79 = -600 + db_at_78 = -600 + db_at_77 = -600 + db_at_76 = -600 + db_at_75 = -700 + db_at_74 = -700 + db_at_73 = -700 + db_at_72 = -700 + db_at_71 = -800 + db_at_70 = -800 + db_at_69 = -800 + db_at_68 = -800 + db_at_67 = -1000 + db_at_66 = -1000 + db_at_65 = -1000 + db_at_64 = -1000 + db_at_63 = -1000 + db_at_62 = -1000 + db_at_61 = -1000 + db_at_60 = -1000 + db_at_59 = -1200 + db_at_58 = -1200 + db_at_57 = -1200 + db_at_56 = -1200 + db_at_55 = -1200 + db_at_54 = -1200 + db_at_53 = -1200 + db_at_52 = -1400 + db_at_51 = -1400 + db_at_50 = -1400 + db_at_49 = -1400 + db_at_48 = -1400 + db_at_47 = -1400 + db_at_46 = -1400 + db_at_45 = -1400 + db_at_44 = -1600 + db_at_43 = -1600 + db_at_42 = -1600 + db_at_41 = -1600 + db_at_40 = -1600 + db_at_39 = -1600 + db_at_38 = -1600 + db_at_37 = -1600 + db_at_36 = -1800 + db_at_35 = -1800 + db_at_34 = -1800 + db_at_33 = -2000 + db_at_32 = -2000 + db_at_31 = -2200 + db_at_30 = -2200 + db_at_29 = -2500 + db_at_28 = -2500 + db_at_27 = -2500 + db_at_26 = -2500 + db_at_25 = -2800 + db_at_24 = -2800 + db_at_23 = -2800 + db_at_22 = -3100 + db_at_21 = -3100 + db_at_20 = -3100 + db_at_19 = -3400 + db_at_18 = -3400 + db_at_17 = -3400 + db_at_16 = -3400 + db_at_15 = -3700 + db_at_14 = -3700 + db_at_13 = -4000 + db_at_12 = -4000 + db_at_11 = -4300 + db_at_10 = -4300 + db_at_9 = -4600 + db_at_8 = -4600 + db_at_7 = -4600 + db_at_6 = -5000 + db_at_5 = -5000 + db_at_4 = -5400 + db_at_3 = -5400 + db_at_2 = -5800 + db_at_1 = -5800 + db_at_0 = -6200 +[Headphone] + volume_curve = explicit + db_at_100 = -300 + db_at_99 = -300 + db_at_98 = -300 + db_at_97 = -300 + db_at_96 = -400 + db_at_95 = -400 + db_at_94 = -400 + db_at_93 = -400 + db_at_92 = -600 + db_at_91 = -600 + db_at_90 = -600 + db_at_89 = -600 + db_at_88 = -700 + db_at_87 = -700 + db_at_86 = -700 + db_at_85 = -700 + db_at_84 = -800 + db_at_83 = -800 + db_at_82 = -800 + db_at_81 = -800 + db_at_80 = -1000 + db_at_79 = -1000 + db_at_78 = -1000 + db_at_77 = -1000 + db_at_76 = -1200 + db_at_75 = -1200 + db_at_74 = -1200 + db_at_73 = -1200 + db_at_72 = -1400 + db_at_71 = -1400 + db_at_70 = -1400 + db_at_69 = -1400 + db_at_68 = -1600 + db_at_67 = -1600 + db_at_66 = -1600 + db_at_65 = -1600 + db_at_64 = -1800 + db_at_63 = -1800 + db_at_62 = -1800 + db_at_61 = -1800 + db_at_60 = -2000 + db_at_59 = -2000 + db_at_58 = -2000 + db_at_57 = -2000 + db_at_56 = -2200 + db_at_55 = -2200 + db_at_54 = -2200 + db_at_53 = -2200 + db_at_52 = -2500 + db_at_51 = -2500 + db_at_50 = -2500 + db_at_49 = -2500 + db_at_48 = -2800 + db_at_47 = -2800 + db_at_46 = -2800 + db_at_45 = -2800 + db_at_44 = -3100 + db_at_43 = -3100 + db_at_42 = -3100 + db_at_41 = -3100 + db_at_40 = -3400 + db_at_39 = -3400 + db_at_38 = -3400 + db_at_37 = -3400 + db_at_36 = -3700 + db_at_35 = -3700 + db_at_34 = -3700 + db_at_33 = -3700 + db_at_32 = -4000 + db_at_31 = -4000 + db_at_30 = -4000 + db_at_29 = -4000 + db_at_28 = -4300 + db_at_27 = -4300 + db_at_26 = -4300 + db_at_25 = -4300 + db_at_24 = -4700 + db_at_23 = -4700 + db_at_22 = -4700 + db_at_21 = -4700 + db_at_20 = -5100 + db_at_19 = -5100 + db_at_18 = -5100 + db_at_17 = -5100 + db_at_16 = -5500 + db_at_15 = -5500 + db_at_14 = -5500 + db_at_13 = -5500 + db_at_12 = -5900 + db_at_11 = -5900 + db_at_10 = -5900 + db_at_9 = -5900 + db_at_8 = -6300 + db_at_7 = -6300 + db_at_6 = -6300 + db_at_5 = -6300 + db_at_4 = -6700 + db_at_3 = -6700 + db_at_2 = -6700 + db_at_1 = -6700 + db_at_0 = -6700 diff --git a/cras-config/daisy_spring/dsp.ini b/cras-config/daisy_spring/dsp.ini new file mode 100644 index 00000000..19ba9453 --- /dev/null +++ b/cras-config/daisy_spring/dsp.ini @@ -0,0 +1,95 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=0 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-30 ; threshold +input_8=12 ; knee +input_9=10.384 ; ratio +input_10=0.02 ; attack +input_11=1 ; release +input_12=0 ; boost +input_13=600 ; f +input_14=1 ; enable +input_15=-32 ; threshold +input_16=21 ; knee +input_17=12 ; ratio +input_18=0.02 ; attack +input_19=0.2 ; release +input_20=1 ; boost +input_21=2000 ; f +input_22=1 ; enable +input_23=-24 ; threshold +input_24=21 ; knee +input_25=6.329 ; ratio +input_26=0.02 ; attack +input_27=0.2 ; release +input_28=-1 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=6 ; peaking +input_5=380 ; freq +input_6=3 ; Q +input_7=-10 ; gain +input_8=6 ; peaking +input_9=450 ; freq +input_10=3 ; Q +input_11=-12 ; gain +input_12=6 ; peaking +input_13=720 ; freq +input_14=3 ; Q +input_15=-12 ; gain +input_16=6 ; peaking +input_17=721 ; freq +input_18=3 ; Q +input_19=-12 ; gain +input_20=6 ; peaking +input_21=1705 ; freq +input_22=3 ; Q +input_23=-8 ; gain +input_24=6 ; peaking +input_25=1800 ; freq +input_26=8 ; Q +input_27=-10.2 ; gain +input_28=6 ; peaking +input_29=580 ; freq +input_30=6 ; Q +input_31=-8 ; gain +input_32=6 ; peaking +input_33=580 ; freq +input_34=6 ; Q +input_35=-8 ; gain +input_36=2 ; highpass +input_37=218 ; freq +input_38=0.7 ; Q +input_39=2 ; gain +input_40=2 ; highpass +input_41=250 ; freq +input_42=0.7 ; Q +input_43=0.6578 ; gain diff --git a/cras-config/device_blocklist b/cras-config/device_blacklist index 19a9b033..19a9b033 100644 --- a/cras-config/device_blocklist +++ b/cras-config/device_blacklist diff --git a/cras-config/falco/HDA Intel PCH b/cras-config/falco/HDA Intel PCH new file mode 100644 index 00000000..e0adc3e9 --- /dev/null +++ b/cras-config/falco/HDA Intel PCH @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -75 + db_at_98 = -75 + db_at_97 = -75 + db_at_96 = -75 + db_at_95 = -75 + db_at_94 = -150 + db_at_93 = -150 + db_at_92 = -150 + db_at_91 = -150 + db_at_90 = -225 + db_at_89 = -225 + db_at_88 = -225 + db_at_87 = -225 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -375 + db_at_81 = -375 + db_at_80 = -450 + db_at_79 = -450 + db_at_78 = -450 + db_at_77 = -450 + db_at_76 = -525 + db_at_75 = -525 + db_at_74 = -600 + db_at_73 = -600 + db_at_72 = -600 + db_at_71 = -600 + db_at_70 = -675 + db_at_69 = -675 + db_at_68 = -675 + db_at_67 = -675 + db_at_66 = -750 + db_at_65 = -750 + db_at_64 = -825 + db_at_63 = -825 + db_at_62 = -825 + db_at_61 = -825 + db_at_60 = -900 + db_at_59 = -900 + db_at_58 = -900 + db_at_57 = -900 + db_at_56 = -975 + db_at_55 = -975 + db_at_54 = -1050 + db_at_53 = -1050 + db_at_52 = -1050 + db_at_51 = -1050 + db_at_50 = -1125 + db_at_49 = -1125 + db_at_48 = -1200 + db_at_47 = -1200 + db_at_46 = -1200 + db_at_45 = -1200 + db_at_44 = -1275 + db_at_43 = -1275 + db_at_42 = -1275 + db_at_41 = -1275 + db_at_40 = -1350 + db_at_39 = -1425 + db_at_38 = -1425 + db_at_37 = -1500 + db_at_36 = -1500 + db_at_35 = -1575 + db_at_34 = -1650 + db_at_33 = -1650 + db_at_32 = -1725 + db_at_31 = -1800 + db_at_30 = -1800 + db_at_29 = -1800 + db_at_28 = -1875 + db_at_27 = -2025 + db_at_26 = -2100 + db_at_25 = -2100 + db_at_24 = -2175 + db_at_23 = -2250 + db_at_22 = -2400 + db_at_21 = -2475 + db_at_20 = -2550 + db_at_19 = -2625 + db_at_18 = -2700 + db_at_17 = -2850 + db_at_16 = -2925 + db_at_15 = -3000 + db_at_14 = -3075 + db_at_13 = -3225 + db_at_12 = -3300 + db_at_11 = -3375 + db_at_10 = -3450 + db_at_9 = -3600 + db_at_8 = -3675 + db_at_7 = -3750 + db_at_6 = -3825 + db_at_5 = -3900 + db_at_4 = -4050 + db_at_3 = -4050 + db_at_2 = -4275 + db_at_1 = -4500 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 50 + max_volume = 0 diff --git a/cras-config/falco/dsp.ini b/cras-config/falco/dsp.ini new file mode 100644 index 00000000..a2b11097 --- /dev/null +++ b/cras-config/falco/dsp.ini @@ -0,0 +1,111 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=0 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-24 ; threshold +input_8=30 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=2 ; boost +input_13=200 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=30 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=2 ; boost +input_21=2000 ; f +input_22=1 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=2 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=200 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=200 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=350 ; freq +input_14=1 ; Q +input_15=3 ; gain +input_16=6 ; peaking +input_17=350 ; freq +input_18=1 ; Q +input_19=3 ; gain +input_20=6 ; peaking +input_21=1000 ; freq +input_22=1 ; Q +input_23=-8 ; gain +input_24=6 ; peaking +input_25=1000 ; freq +input_26=1 ; Q +input_27=-8 ; gain +input_28=6 ; peaking +input_29=5000 ; freq +input_30=1 ; Q +input_31=3 ; gain +input_32=6 ; peaking +input_33=5000 ; freq +input_34=1 ; Q +input_35=3 ; gain +input_36=6 ; peaking +input_37=8000 ; freq +input_38=1 ; Q +input_39=3 ; gain +input_40=6 ; peaking +input_41=8000 ; freq +input_42=1 ; Q +input_43=3 ; gain +input_44=6 ; peaking +input_45=10000 ; freq +input_46=1 ; Q +input_47=3 ; gain +input_48=6 ; peaking +input_49=10000 ; freq +input_50=1 ; Q +input_51=3 ; gain +input_52=6 ; peaking +input_53=2000 ; freq +input_54=1 ; Q +input_55=-2 ; gain +input_56=6 ; peaking +input_57=2000 ; freq +input_58=1 ; Q +input_59=-2 ; gain diff --git a/cras-config/leon/HDA Intel PCH b/cras-config/leon/HDA Intel PCH new file mode 100644 index 00000000..e0adc3e9 --- /dev/null +++ b/cras-config/leon/HDA Intel PCH @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -75 + db_at_98 = -75 + db_at_97 = -75 + db_at_96 = -75 + db_at_95 = -75 + db_at_94 = -150 + db_at_93 = -150 + db_at_92 = -150 + db_at_91 = -150 + db_at_90 = -225 + db_at_89 = -225 + db_at_88 = -225 + db_at_87 = -225 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -375 + db_at_81 = -375 + db_at_80 = -450 + db_at_79 = -450 + db_at_78 = -450 + db_at_77 = -450 + db_at_76 = -525 + db_at_75 = -525 + db_at_74 = -600 + db_at_73 = -600 + db_at_72 = -600 + db_at_71 = -600 + db_at_70 = -675 + db_at_69 = -675 + db_at_68 = -675 + db_at_67 = -675 + db_at_66 = -750 + db_at_65 = -750 + db_at_64 = -825 + db_at_63 = -825 + db_at_62 = -825 + db_at_61 = -825 + db_at_60 = -900 + db_at_59 = -900 + db_at_58 = -900 + db_at_57 = -900 + db_at_56 = -975 + db_at_55 = -975 + db_at_54 = -1050 + db_at_53 = -1050 + db_at_52 = -1050 + db_at_51 = -1050 + db_at_50 = -1125 + db_at_49 = -1125 + db_at_48 = -1200 + db_at_47 = -1200 + db_at_46 = -1200 + db_at_45 = -1200 + db_at_44 = -1275 + db_at_43 = -1275 + db_at_42 = -1275 + db_at_41 = -1275 + db_at_40 = -1350 + db_at_39 = -1425 + db_at_38 = -1425 + db_at_37 = -1500 + db_at_36 = -1500 + db_at_35 = -1575 + db_at_34 = -1650 + db_at_33 = -1650 + db_at_32 = -1725 + db_at_31 = -1800 + db_at_30 = -1800 + db_at_29 = -1800 + db_at_28 = -1875 + db_at_27 = -2025 + db_at_26 = -2100 + db_at_25 = -2100 + db_at_24 = -2175 + db_at_23 = -2250 + db_at_22 = -2400 + db_at_21 = -2475 + db_at_20 = -2550 + db_at_19 = -2625 + db_at_18 = -2700 + db_at_17 = -2850 + db_at_16 = -2925 + db_at_15 = -3000 + db_at_14 = -3075 + db_at_13 = -3225 + db_at_12 = -3300 + db_at_11 = -3375 + db_at_10 = -3450 + db_at_9 = -3600 + db_at_8 = -3675 + db_at_7 = -3750 + db_at_6 = -3825 + db_at_5 = -3900 + db_at_4 = -4050 + db_at_3 = -4050 + db_at_2 = -4275 + db_at_1 = -4500 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 50 + max_volume = 0 diff --git a/cras-config/leon/dsp.ini b/cras-config/leon/dsp.ini new file mode 100644 index 00000000..14476470 --- /dev/null +++ b/cras-config/leon/dsp.ini @@ -0,0 +1,79 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=0 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-20 ; threshold +input_8=25 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=4 ; boost +input_13=579 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=31 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=-3 ; boost +input_21=2164 ; f +input_22=1 ; enable +input_23=-25 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=4 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=231 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=218 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=728 ; freq +input_14=1.5264 ; Q +input_15=-7.8 ; gain +input_16=6 ; peaking +input_17=728 ; freq +input_18=1.6351 ; Q +input_19=-8.8 ; gain +input_20=2 ; highpass +input_21=164 ; freq +input_22=3.3685 ; Q +input_23=0 ; gain +input_24=2 ; highpass +input_25=164 ; freq +input_26=3.3685 ; Q +input_27=0 ; gain diff --git a/cras-config/link/HDA Intel PCH b/cras-config/link/HDA Intel PCH new file mode 100644 index 00000000..5344a083 --- /dev/null +++ b/cras-config/link/HDA Intel PCH @@ -0,0 +1,107 @@ +[Default] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -100 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -300 + db_at_90 = -300 + db_at_89 = -300 + db_at_88 = -300 + db_at_87 = -400 + db_at_86 = -400 + db_at_85 = -400 + db_at_84 = -400 + db_at_83 = -500 + db_at_82 = -500 + db_at_81 = -500 + db_at_80 = -500 + db_at_79 = -600 + db_at_78 = -600 + db_at_77 = -600 + db_at_76 = -600 + db_at_75 = -700 + db_at_74 = -700 + db_at_73 = -700 + db_at_72 = -700 + db_at_71 = -800 + db_at_70 = -800 + db_at_69 = -800 + db_at_68 = -800 + db_at_67 = -900 + db_at_66 = -900 + db_at_65 = -900 + db_at_64 = -900 + db_at_63 = -900 + db_at_62 = -900 + db_at_61 = -900 + db_at_60 = -1000 + db_at_59 = -1000 + db_at_58 = -1000 + db_at_57 = -1000 + db_at_56 = -1100 + db_at_55 = -1100 + db_at_54 = -1100 + db_at_53 = -1100 + db_at_52 = -1200 + db_at_51 = -1200 + db_at_50 = -1200 + db_at_49 = -1200 + db_at_48 = -1300 + db_at_47 = -1300 + db_at_46 = -1300 + db_at_45 = -1300 + db_at_44 = -1400 + db_at_43 = -1400 + db_at_42 = -1400 + db_at_41 = -1400 + db_at_40 = -1500 + db_at_39 = -1600 + db_at_38 = -1600 + db_at_37 = -1700 + db_at_36 = -1700 + db_at_35 = -1800 + db_at_34 = -1900 + db_at_33 = -2000 + db_at_32 = -2100 + db_at_31 = -2200 + db_at_30 = -2300 + db_at_29 = -2400 + db_at_28 = -2500 + db_at_27 = -2600 + db_at_26 = -2700 + db_at_25 = -2800 + db_at_24 = -2900 + db_at_23 = -3000 + db_at_22 = -3100 + db_at_21 = -3200 + db_at_20 = -3300 + db_at_19 = -3400 + db_at_18 = -3500 + db_at_17 = -3600 + db_at_16 = -3700 + db_at_15 = -3800 + db_at_14 = -3900 + db_at_13 = -4000 + db_at_12 = -4100 + db_at_11 = -4200 + db_at_10 = -4300 + db_at_9 = -4400 + db_at_8 = -4500 + db_at_7 = -4600 + db_at_6 = -4800 + db_at_5 = -5000 + db_at_4 = -5200 + db_at_3 = -5400 + db_at_2 = -5600 + db_at_1 = -5800 + db_at_0 = -6000 +[Headphone Jack] + volume_curve = simple_step + volume_step = 75 + max_volume = -900 diff --git a/cras-config/peppy/HDA Intel PCH b/cras-config/peppy/HDA Intel PCH new file mode 100644 index 00000000..e0adc3e9 --- /dev/null +++ b/cras-config/peppy/HDA Intel PCH @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -75 + db_at_98 = -75 + db_at_97 = -75 + db_at_96 = -75 + db_at_95 = -75 + db_at_94 = -150 + db_at_93 = -150 + db_at_92 = -150 + db_at_91 = -150 + db_at_90 = -225 + db_at_89 = -225 + db_at_88 = -225 + db_at_87 = -225 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -375 + db_at_81 = -375 + db_at_80 = -450 + db_at_79 = -450 + db_at_78 = -450 + db_at_77 = -450 + db_at_76 = -525 + db_at_75 = -525 + db_at_74 = -600 + db_at_73 = -600 + db_at_72 = -600 + db_at_71 = -600 + db_at_70 = -675 + db_at_69 = -675 + db_at_68 = -675 + db_at_67 = -675 + db_at_66 = -750 + db_at_65 = -750 + db_at_64 = -825 + db_at_63 = -825 + db_at_62 = -825 + db_at_61 = -825 + db_at_60 = -900 + db_at_59 = -900 + db_at_58 = -900 + db_at_57 = -900 + db_at_56 = -975 + db_at_55 = -975 + db_at_54 = -1050 + db_at_53 = -1050 + db_at_52 = -1050 + db_at_51 = -1050 + db_at_50 = -1125 + db_at_49 = -1125 + db_at_48 = -1200 + db_at_47 = -1200 + db_at_46 = -1200 + db_at_45 = -1200 + db_at_44 = -1275 + db_at_43 = -1275 + db_at_42 = -1275 + db_at_41 = -1275 + db_at_40 = -1350 + db_at_39 = -1425 + db_at_38 = -1425 + db_at_37 = -1500 + db_at_36 = -1500 + db_at_35 = -1575 + db_at_34 = -1650 + db_at_33 = -1650 + db_at_32 = -1725 + db_at_31 = -1800 + db_at_30 = -1800 + db_at_29 = -1800 + db_at_28 = -1875 + db_at_27 = -2025 + db_at_26 = -2100 + db_at_25 = -2100 + db_at_24 = -2175 + db_at_23 = -2250 + db_at_22 = -2400 + db_at_21 = -2475 + db_at_20 = -2550 + db_at_19 = -2625 + db_at_18 = -2700 + db_at_17 = -2850 + db_at_16 = -2925 + db_at_15 = -3000 + db_at_14 = -3075 + db_at_13 = -3225 + db_at_12 = -3300 + db_at_11 = -3375 + db_at_10 = -3450 + db_at_9 = -3600 + db_at_8 = -3675 + db_at_7 = -3750 + db_at_6 = -3825 + db_at_5 = -3900 + db_at_4 = -4050 + db_at_3 = -4050 + db_at_2 = -4275 + db_at_1 = -4500 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 50 + max_volume = 0 diff --git a/cras-config/peppy/dsp.ini b/cras-config/peppy/dsp.ini new file mode 100644 index 00000000..e229b199 --- /dev/null +++ b/cras-config/peppy/dsp.ini @@ -0,0 +1,119 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=0 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-30 ; threshold +input_8=24 ; knee +input_9=6.032 ; ratio +input_10=0.02 ; attack +input_11=0.25 ; release +input_12=2 ; boost +input_13=326 ; f +input_14=1 ; enable +input_15=-27 ; threshold +input_16=23 ; knee +input_17=5.634 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=2 ; boost +input_21=1842 ; f +input_22=1 ; enable +input_23=-40 ; threshold +input_24=37 ; knee +input_25=5.67 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=3 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=6 ; peaking +input_5=248 ; freq +input_6=4.8668 ; Q +input_7=-7.8 ; gain +input_8=6 ; peaking +input_9=688 ; freq +input_10=2.6911 ; Q +input_11=-3.9 ; gain +input_12=6 ; peaking +input_13=410 ; freq +input_14=8.5 ; Q +input_15=-7.3 ; gain +input_16=6 ; peaking +input_17=817 ; freq +input_18=4.1703 ; Q +input_19=-15 ; gain +input_20=6 ; peaking +input_21=5112 ; freq +input_22=3.957 ; Q +input_23=-4.4 ; gain +input_24=6 ; peaking +input_25=4827 ; freq +input_26=3.3685 ; Q +input_27=-6.3 ; gain +input_28=6 ; peaking +input_29=819 ; freq +input_30=2.2529 ; Q +input_31=-14.1 ; gain +input_32=6 ; peaking +input_33=4065 ; freq +input_34=2.5388 ; Q +input_35=3 ; gain +input_36=6 ; peaking +input_37=4065 ; freq +input_38=5.9436 ; Q +input_39=3 ; gain +input_40=6 ; peaking +input_41=2292 ; freq +input_42=2.6 ; Q +input_43=1.5 ; gain +input_44=6 ; peaking +input_45=2292 ; freq +input_46=2.6911 ; Q +input_47=1.5 ; gain +input_48=5 ; highshelf +input_49=8960 ; freq +input_50=2.1187 ; Q +input_51=2.6 ; gain +input_52=2 ; highpass +input_53=293 ; freq +input_54=1.0465 ; Q +input_55=0 ; gain +input_56=2 ; highpass +input_57=343 ; freq +input_58=1.4222 ; Q +input_59=0 ; gain +input_60=5 ; highshelf +input_61=8960 ; freq +input_62=1 ; Q +input_63=2.6 ; gain +input_64=0 ; none +input_65=0 ; freq +input_66=0 ; Q +input_67=0 ; gain diff --git a/cras-config/stout/HDA Intel PCH b/cras-config/stout/HDA Intel PCH new file mode 100644 index 00000000..884c0060 --- /dev/null +++ b/cras-config/stout/HDA Intel PCH @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -75 + db_at_98 = -75 + db_at_97 = -75 + db_at_96 = -150 + db_at_95 = -150 + db_at_94 = -150 + db_at_93 = -225 + db_at_92 = -225 + db_at_91 = -300 + db_at_90 = -300 + db_at_89 = -300 + db_at_88 = -375 + db_at_87 = -375 + db_at_86 = -375 + db_at_85 = -450 + db_at_84 = -450 + db_at_83 = -450 + db_at_82 = -525 + db_at_81 = -525 + db_at_80 = -600 + db_at_79 = -600 + db_at_78 = -675 + db_at_77 = -675 + db_at_76 = -750 + db_at_75 = -750 + db_at_74 = -750 + db_at_73 = -825 + db_at_72 = -825 + db_at_71 = -825 + db_at_70 = -900 + db_at_69 = -900 + db_at_68 = -975 + db_at_67 = -975 + db_at_66 = -1050 + db_at_65 = -1050 + db_at_64 = -1125 + db_at_63 = -1125 + db_at_62 = -1125 + db_at_61 = -1200 + db_at_60 = -1200 + db_at_59 = -1200 + db_at_58 = -1275 + db_at_57 = -1275 + db_at_56 = -1350 + db_at_55 = -1350 + db_at_54 = -1425 + db_at_53 = -1425 + db_at_52 = -1500 + db_at_51 = -1500 + db_at_50 = -1500 + db_at_49 = -1500 + db_at_48 = -1575 + db_at_47 = -1575 + db_at_46 = -1650 + db_at_45 = -1650 + db_at_44 = -1725 + db_at_43 = -1725 + db_at_42 = -1800 + db_at_41 = -1800 + db_at_40 = -1875 + db_at_39 = -1875 + db_at_38 = -1950 + db_at_37 = -2025 + db_at_36 = -2100 + db_at_35 = -2175 + db_at_34 = -2250 + db_at_33 = -2250 + db_at_32 = -2325 + db_at_31 = -2400 + db_at_30 = -2475 + db_at_29 = -2475 + db_at_28 = -2625 + db_at_27 = -2700 + db_at_26 = -2850 + db_at_25 = -2850 + db_at_24 = -3000 + db_at_23 = -3075 + db_at_22 = -3225 + db_at_21 = -3375 + db_at_20 = -3450 + db_at_19 = -3600 + db_at_18 = -3750 + db_at_17 = -3825 + db_at_16 = -3975 + db_at_15 = -4125 + db_at_14 = -4200 + db_at_13 = -4350 + db_at_12 = -4500 + db_at_11 = -4575 + db_at_10 = -4725 + db_at_9 = -4875 + db_at_8 = -4950 + db_at_7 = -5100 + db_at_6 = -5250 + db_at_5 = -5325 + db_at_4 = -5475 + db_at_3 = -5550 + db_at_2 = -5850 + db_at_1 = -6150 + db_at_0 = -6525 +[Headphone] + volume_curve = simple_step + volume_step = 65 + max_volume = 0 diff --git a/cras-config/veryon_jerry-kernelnext b/cras-config/veryon_jerry-kernelnext new file mode 120000 index 00000000..0462d3a7 --- /dev/null +++ b/cras-config/veryon_jerry-kernelnext @@ -0,0 +1 @@ +veyron_jerry
\ No newline at end of file diff --git a/cras-config/veyron_jaq/ROCKCHIP-I2S b/cras-config/veyron_jaq/ROCKCHIP-I2S new file mode 100644 index 00000000..2b946ca9 --- /dev/null +++ b/cras-config/veyron_jaq/ROCKCHIP-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -100 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -200 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -200 + db_at_90 = -200 + db_at_89 = -200 + db_at_88 = -300 + db_at_87 = -300 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -300 + db_at_81 = -400 + db_at_80 = -400 + db_at_79 = -400 + db_at_78 = -400 + db_at_77 = -400 + db_at_76 = -400 + db_at_75 = -400 + db_at_74 = -500 + db_at_73 = -500 + db_at_72 = -500 + db_at_71 = -500 + db_at_70 = -500 + db_at_69 = -500 + db_at_68 = -500 + db_at_67 = -500 + db_at_66 = -600 + db_at_65 = -600 + db_at_64 = -600 + db_at_63 = -600 + db_at_62 = -600 + db_at_61 = -600 + db_at_60 = -600 + db_at_59 = -700 + db_at_58 = -700 + db_at_57 = -700 + db_at_56 = -700 + db_at_55 = -700 + db_at_54 = -800 + db_at_53 = -800 + db_at_52 = -800 + db_at_51 = -900 + db_at_50 = -900 + db_at_49 = -900 + db_at_48 = -900 + db_at_47 = -1000 + db_at_46 = -1000 + db_at_45 = -1000 + db_at_44 = -1100 + db_at_43 = -1100 + db_at_42 = -1100 + db_at_41 = -1200 + db_at_40 = -1200 + db_at_39 = -1200 + db_at_38 = -1200 + db_at_37 = -1300 + db_at_36 = -1300 + db_at_35 = -1300 + db_at_34 = -1400 + db_at_33 = -1400 + db_at_32 = -1400 + db_at_31 = -1500 + db_at_30 = -1500 + db_at_29 = -1500 + db_at_28 = -1500 + db_at_27 = -1600 + db_at_26 = -1600 + db_at_25 = -1600 + db_at_24 = -1700 + db_at_23 = -1700 + db_at_22 = -1700 + db_at_21 = -1800 + db_at_20 = -1800 + db_at_19 = -1800 + db_at_18 = -1900 + db_at_17 = -1900 + db_at_16 = -1900 + db_at_15 = -1900 + db_at_14 = -2000 + db_at_13 = -2000 + db_at_12 = -2000 + db_at_11 = -2100 + db_at_10 = -2100 + db_at_9 = -2100 + db_at_8 = -2200 + db_at_7 = -2200 + db_at_6 = -2200 + db_at_5 = -2200 + db_at_4 = -2300 + db_at_3 = -2300 + db_at_2 = -2300 + db_at_1 = -2400 + db_at_0 = -2400 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_jaq/VEYRON-I2S b/cras-config/veyron_jaq/VEYRON-I2S new file mode 100644 index 00000000..2b946ca9 --- /dev/null +++ b/cras-config/veyron_jaq/VEYRON-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -100 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -200 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -200 + db_at_90 = -200 + db_at_89 = -200 + db_at_88 = -300 + db_at_87 = -300 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -300 + db_at_81 = -400 + db_at_80 = -400 + db_at_79 = -400 + db_at_78 = -400 + db_at_77 = -400 + db_at_76 = -400 + db_at_75 = -400 + db_at_74 = -500 + db_at_73 = -500 + db_at_72 = -500 + db_at_71 = -500 + db_at_70 = -500 + db_at_69 = -500 + db_at_68 = -500 + db_at_67 = -500 + db_at_66 = -600 + db_at_65 = -600 + db_at_64 = -600 + db_at_63 = -600 + db_at_62 = -600 + db_at_61 = -600 + db_at_60 = -600 + db_at_59 = -700 + db_at_58 = -700 + db_at_57 = -700 + db_at_56 = -700 + db_at_55 = -700 + db_at_54 = -800 + db_at_53 = -800 + db_at_52 = -800 + db_at_51 = -900 + db_at_50 = -900 + db_at_49 = -900 + db_at_48 = -900 + db_at_47 = -1000 + db_at_46 = -1000 + db_at_45 = -1000 + db_at_44 = -1100 + db_at_43 = -1100 + db_at_42 = -1100 + db_at_41 = -1200 + db_at_40 = -1200 + db_at_39 = -1200 + db_at_38 = -1200 + db_at_37 = -1300 + db_at_36 = -1300 + db_at_35 = -1300 + db_at_34 = -1400 + db_at_33 = -1400 + db_at_32 = -1400 + db_at_31 = -1500 + db_at_30 = -1500 + db_at_29 = -1500 + db_at_28 = -1500 + db_at_27 = -1600 + db_at_26 = -1600 + db_at_25 = -1600 + db_at_24 = -1700 + db_at_23 = -1700 + db_at_22 = -1700 + db_at_21 = -1800 + db_at_20 = -1800 + db_at_19 = -1800 + db_at_18 = -1900 + db_at_17 = -1900 + db_at_16 = -1900 + db_at_15 = -1900 + db_at_14 = -2000 + db_at_13 = -2000 + db_at_12 = -2000 + db_at_11 = -2100 + db_at_10 = -2100 + db_at_9 = -2100 + db_at_8 = -2200 + db_at_7 = -2200 + db_at_6 = -2200 + db_at_5 = -2200 + db_at_4 = -2300 + db_at_3 = -2300 + db_at_2 = -2300 + db_at_1 = -2400 + db_at_0 = -2400 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_jaq/dsp.ini b/cras-config/veyron_jaq/dsp.ini new file mode 100644 index 00000000..8f7c6282 --- /dev/null +++ b/cras-config/veyron_jaq/dsp.ini @@ -0,0 +1,119 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-24 ; threshold +input_8=30 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=0 ; boost +input_13=200 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=30 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=0 ; boost +input_21=2000 ; f +input_22=1 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=250 ; freq +input_6=3 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=250 ; freq +input_10=3 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=400 ; freq +input_14=1 ; Q +input_15=3 ; gain +input_16=6 ; peaking +input_17=400 ; freq +input_18=1 ; Q +input_19=3 ; gain +input_20=6 ; peaking +input_21=630 ; freq +input_22=1 ; Q +input_23=1 ; gain +input_24=6 ; peaking +input_25=630 ; freq +input_26=1 ; Q +input_27=1 ; gain +input_28=6 ; peaking +input_29=1500 ; freq +input_30=1 ; Q +input_31=-2 ; gain +input_32=6 ; peaking +input_33=1500 ; freq +input_34=1 ; Q +input_35=-2 ; gain +input_36=6 ; peaking +input_37=2200 ; freq +input_38=1 ; Q +input_39=1 ; gain +input_40=6 ; peaking +input_41=2200 ; freq +input_42=1 ; Q +input_43=1 ; gain +input_44=6 ; peaking +input_45=3300 ; freq +input_46=0.7 ; Q +input_47=-6 ; gain +input_48=6 ; peaking +input_49=3300 ; freq +input_50=0.7 ; Q +input_51=-6 ; gain +input_52=6 ; peaking +input_53=6000 ; freq +input_54=1 ; Q +input_55=-3 ; gain +input_56=6 ; peaking +input_57=6000 ; freq +input_58=1 ; Q +input_59=-3 ; gain +input_60=5 ; highshelf +input_61=12000 ; freq +input_62=1 ; Q +input_63=1.5 ; gain +input_64=5 ; highshelf +input_65=12000 ; freq +input_66=1 ; Q +input_67=1.5 ; gain diff --git a/cras-config/veyron_jerry/ROCKCHIP-I2S b/cras-config/veyron_jerry/ROCKCHIP-I2S new file mode 100644 index 00000000..d59988f6 --- /dev/null +++ b/cras-config/veyron_jerry/ROCKCHIP-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -520 + db_at_98 = -520 + db_at_97 = -540 + db_at_96 = -540 + db_at_95 = -560 + db_at_94 = -580 + db_at_93 = -580 + db_at_92 = -600 + db_at_91 = -620 + db_at_90 = -620 + db_at_89 = -640 + db_at_88 = -640 + db_at_87 = -660 + db_at_86 = -680 + db_at_85 = -680 + db_at_84 = -700 + db_at_83 = -720 + db_at_82 = -740 + db_at_81 = -760 + db_at_80 = -780 + db_at_79 = -800 + db_at_78 = -820 + db_at_77 = -840 + db_at_76 = -860 + db_at_75 = -880 + db_at_74 = -880 + db_at_73 = -880 + db_at_72 = -900 + db_at_71 = -920 + db_at_70 = -940 + db_at_69 = -980 + db_at_68 = -1000 + db_at_67 = -1020 + db_at_66 = -1040 + db_at_65 = -1080 + db_at_64 = -1100 + db_at_63 = -1120 + db_at_62 = -1140 + db_at_61 = -1180 + db_at_60 = -1200 + db_at_59 = -1220 + db_at_58 = -1240 + db_at_57 = -1280 + db_at_56 = -1300 + db_at_55 = -1320 + db_at_54 = -1340 + db_at_53 = -1380 + db_at_52 = -1400 + db_at_51 = -1460 + db_at_50 = -1540 + db_at_49 = -1600 + db_at_48 = -1660 + db_at_47 = -1720 + db_at_46 = -1800 + db_at_45 = -1860 + db_at_44 = -1920 + db_at_43 = -1980 + db_at_42 = -2060 + db_at_41 = -2120 + db_at_40 = -2180 + db_at_39 = -2240 + db_at_38 = -2320 + db_at_37 = -2380 + db_at_36 = -2440 + db_at_35 = -2520 + db_at_34 = -2580 + db_at_33 = -2640 + db_at_32 = -2700 + db_at_31 = -2780 + db_at_30 = -2840 + db_at_29 = -2900 + db_at_28 = -2960 + db_at_27 = -3040 + db_at_26 = -3100 + db_at_25 = -3160 + db_at_24 = -3240 + db_at_23 = -3300 + db_at_22 = -3360 + db_at_21 = -3420 + db_at_20 = -3500 + db_at_19 = -3560 + db_at_18 = -3620 + db_at_17 = -3680 + db_at_16 = -3760 + db_at_15 = -3820 + db_at_14 = -3880 + db_at_13 = -3940 + db_at_12 = -4020 + db_at_11 = -4080 + db_at_10 = -4140 + db_at_9 = -4220 + db_at_8 = -4280 + db_at_7 = -4340 + db_at_6 = -4400 + db_at_5 = -4480 + db_at_4 = -4540 + db_at_3 = -4600 + db_at_2 = -4660 + db_at_1 = -4740 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_jerry/VEYRON-I2S b/cras-config/veyron_jerry/VEYRON-I2S new file mode 100644 index 00000000..d59988f6 --- /dev/null +++ b/cras-config/veyron_jerry/VEYRON-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -520 + db_at_98 = -520 + db_at_97 = -540 + db_at_96 = -540 + db_at_95 = -560 + db_at_94 = -580 + db_at_93 = -580 + db_at_92 = -600 + db_at_91 = -620 + db_at_90 = -620 + db_at_89 = -640 + db_at_88 = -640 + db_at_87 = -660 + db_at_86 = -680 + db_at_85 = -680 + db_at_84 = -700 + db_at_83 = -720 + db_at_82 = -740 + db_at_81 = -760 + db_at_80 = -780 + db_at_79 = -800 + db_at_78 = -820 + db_at_77 = -840 + db_at_76 = -860 + db_at_75 = -880 + db_at_74 = -880 + db_at_73 = -880 + db_at_72 = -900 + db_at_71 = -920 + db_at_70 = -940 + db_at_69 = -980 + db_at_68 = -1000 + db_at_67 = -1020 + db_at_66 = -1040 + db_at_65 = -1080 + db_at_64 = -1100 + db_at_63 = -1120 + db_at_62 = -1140 + db_at_61 = -1180 + db_at_60 = -1200 + db_at_59 = -1220 + db_at_58 = -1240 + db_at_57 = -1280 + db_at_56 = -1300 + db_at_55 = -1320 + db_at_54 = -1340 + db_at_53 = -1380 + db_at_52 = -1400 + db_at_51 = -1460 + db_at_50 = -1540 + db_at_49 = -1600 + db_at_48 = -1660 + db_at_47 = -1720 + db_at_46 = -1800 + db_at_45 = -1860 + db_at_44 = -1920 + db_at_43 = -1980 + db_at_42 = -2060 + db_at_41 = -2120 + db_at_40 = -2180 + db_at_39 = -2240 + db_at_38 = -2320 + db_at_37 = -2380 + db_at_36 = -2440 + db_at_35 = -2520 + db_at_34 = -2580 + db_at_33 = -2640 + db_at_32 = -2700 + db_at_31 = -2780 + db_at_30 = -2840 + db_at_29 = -2900 + db_at_28 = -2960 + db_at_27 = -3040 + db_at_26 = -3100 + db_at_25 = -3160 + db_at_24 = -3240 + db_at_23 = -3300 + db_at_22 = -3360 + db_at_21 = -3420 + db_at_20 = -3500 + db_at_19 = -3560 + db_at_18 = -3620 + db_at_17 = -3680 + db_at_16 = -3760 + db_at_15 = -3820 + db_at_14 = -3880 + db_at_13 = -3940 + db_at_12 = -4020 + db_at_11 = -4080 + db_at_10 = -4140 + db_at_9 = -4220 + db_at_8 = -4280 + db_at_7 = -4340 + db_at_6 = -4400 + db_at_5 = -4480 + db_at_4 = -4540 + db_at_3 = -4600 + db_at_2 = -4660 + db_at_1 = -4740 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_jerry/dsp.ini b/cras-config/veyron_jerry/dsp.ini new file mode 100644 index 00000000..4973a551 --- /dev/null +++ b/cras-config/veyron_jerry/dsp.ini @@ -0,0 +1,79 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-30 ; threshold +input_8=25 ; knee +input_9=4 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=0 ; boost +input_13=200 ; f +input_14=1 ; enable +input_15=-30 ; threshold +input_16=25 ; knee +input_17=4 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=0 ; boost +input_21=2000 ; f +input_22=1 ; enable +input_23=-30 ; threshold +input_24=25 ; knee +input_25=4 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=500 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=500 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=350 ; freq +input_14=4 ; Q +input_15=-6 ; gain +input_16=6 ; peaking +input_17=350 ; freq +input_18=4 ; Q +input_19=-6 ; gain +input_20=6 ; peaking +input_21=750 ; freq +input_22=4 ; Q +input_23=-6 ; gain +input_24=6 ; peaking +input_25=750 ; freq +input_26=4 ; Q +input_27=-6 ; gain diff --git a/cras-config/veyron_mighty/ROCKCHIP-I2S b/cras-config/veyron_mighty/ROCKCHIP-I2S new file mode 100644 index 00000000..2b946ca9 --- /dev/null +++ b/cras-config/veyron_mighty/ROCKCHIP-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -100 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -200 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -200 + db_at_90 = -200 + db_at_89 = -200 + db_at_88 = -300 + db_at_87 = -300 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -300 + db_at_81 = -400 + db_at_80 = -400 + db_at_79 = -400 + db_at_78 = -400 + db_at_77 = -400 + db_at_76 = -400 + db_at_75 = -400 + db_at_74 = -500 + db_at_73 = -500 + db_at_72 = -500 + db_at_71 = -500 + db_at_70 = -500 + db_at_69 = -500 + db_at_68 = -500 + db_at_67 = -500 + db_at_66 = -600 + db_at_65 = -600 + db_at_64 = -600 + db_at_63 = -600 + db_at_62 = -600 + db_at_61 = -600 + db_at_60 = -600 + db_at_59 = -700 + db_at_58 = -700 + db_at_57 = -700 + db_at_56 = -700 + db_at_55 = -700 + db_at_54 = -800 + db_at_53 = -800 + db_at_52 = -800 + db_at_51 = -900 + db_at_50 = -900 + db_at_49 = -900 + db_at_48 = -900 + db_at_47 = -1000 + db_at_46 = -1000 + db_at_45 = -1000 + db_at_44 = -1100 + db_at_43 = -1100 + db_at_42 = -1100 + db_at_41 = -1200 + db_at_40 = -1200 + db_at_39 = -1200 + db_at_38 = -1200 + db_at_37 = -1300 + db_at_36 = -1300 + db_at_35 = -1300 + db_at_34 = -1400 + db_at_33 = -1400 + db_at_32 = -1400 + db_at_31 = -1500 + db_at_30 = -1500 + db_at_29 = -1500 + db_at_28 = -1500 + db_at_27 = -1600 + db_at_26 = -1600 + db_at_25 = -1600 + db_at_24 = -1700 + db_at_23 = -1700 + db_at_22 = -1700 + db_at_21 = -1800 + db_at_20 = -1800 + db_at_19 = -1800 + db_at_18 = -1900 + db_at_17 = -1900 + db_at_16 = -1900 + db_at_15 = -1900 + db_at_14 = -2000 + db_at_13 = -2000 + db_at_12 = -2000 + db_at_11 = -2100 + db_at_10 = -2100 + db_at_9 = -2100 + db_at_8 = -2200 + db_at_7 = -2200 + db_at_6 = -2200 + db_at_5 = -2200 + db_at_4 = -2300 + db_at_3 = -2300 + db_at_2 = -2300 + db_at_1 = -2400 + db_at_0 = -2400 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_mighty/VEYRON-I2S b/cras-config/veyron_mighty/VEYRON-I2S new file mode 100644 index 00000000..2b946ca9 --- /dev/null +++ b/cras-config/veyron_mighty/VEYRON-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -100 + db_at_99 = -100 + db_at_98 = -100 + db_at_97 = -100 + db_at_96 = -200 + db_at_95 = -200 + db_at_94 = -200 + db_at_93 = -200 + db_at_92 = -200 + db_at_91 = -200 + db_at_90 = -200 + db_at_89 = -200 + db_at_88 = -300 + db_at_87 = -300 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -300 + db_at_81 = -400 + db_at_80 = -400 + db_at_79 = -400 + db_at_78 = -400 + db_at_77 = -400 + db_at_76 = -400 + db_at_75 = -400 + db_at_74 = -500 + db_at_73 = -500 + db_at_72 = -500 + db_at_71 = -500 + db_at_70 = -500 + db_at_69 = -500 + db_at_68 = -500 + db_at_67 = -500 + db_at_66 = -600 + db_at_65 = -600 + db_at_64 = -600 + db_at_63 = -600 + db_at_62 = -600 + db_at_61 = -600 + db_at_60 = -600 + db_at_59 = -700 + db_at_58 = -700 + db_at_57 = -700 + db_at_56 = -700 + db_at_55 = -700 + db_at_54 = -800 + db_at_53 = -800 + db_at_52 = -800 + db_at_51 = -900 + db_at_50 = -900 + db_at_49 = -900 + db_at_48 = -900 + db_at_47 = -1000 + db_at_46 = -1000 + db_at_45 = -1000 + db_at_44 = -1100 + db_at_43 = -1100 + db_at_42 = -1100 + db_at_41 = -1200 + db_at_40 = -1200 + db_at_39 = -1200 + db_at_38 = -1200 + db_at_37 = -1300 + db_at_36 = -1300 + db_at_35 = -1300 + db_at_34 = -1400 + db_at_33 = -1400 + db_at_32 = -1400 + db_at_31 = -1500 + db_at_30 = -1500 + db_at_29 = -1500 + db_at_28 = -1500 + db_at_27 = -1600 + db_at_26 = -1600 + db_at_25 = -1600 + db_at_24 = -1700 + db_at_23 = -1700 + db_at_22 = -1700 + db_at_21 = -1800 + db_at_20 = -1800 + db_at_19 = -1800 + db_at_18 = -1900 + db_at_17 = -1900 + db_at_16 = -1900 + db_at_15 = -1900 + db_at_14 = -2000 + db_at_13 = -2000 + db_at_12 = -2000 + db_at_11 = -2100 + db_at_10 = -2100 + db_at_9 = -2100 + db_at_8 = -2200 + db_at_7 = -2200 + db_at_6 = -2200 + db_at_5 = -2200 + db_at_4 = -2300 + db_at_3 = -2300 + db_at_2 = -2300 + db_at_1 = -2400 + db_at_0 = -2400 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_mighty/dsp.ini b/cras-config/veyron_mighty/dsp.ini new file mode 100644 index 00000000..94c7ad23 --- /dev/null +++ b/cras-config/veyron_mighty/dsp.ini @@ -0,0 +1,119 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-24 ; threshold +input_8=30 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=0 ; boost +input_13=200 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=30 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=0 ; boost +input_21=2000 ; f +input_22=1 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=250 ; freq +input_6=3 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=300 ; freq +input_10=3 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=500 ; freq +input_14=1 ; Q +input_15=4.5 ; gain +input_16=6 ; peaking +input_17=500 ; freq +input_18=1 ; Q +input_19=4.5 ; gain +input_20=6 ; peaking +input_21=800 ; freq +input_22=3 ; Q +input_23=-8 ; gain +input_24=6 ; peaking +input_25=800 ; freq +input_26=3 ; Q +input_27=-8 ; gain +input_28=6 ; peaking +input_29=1000 ; freq +input_30=1 ; Q +input_31=-2 ; gain +input_32=6 ; peaking +input_33=1000 ; freq +input_34=1 ; Q +input_35=-2 ; gain +input_36=6 ; peaking +input_37=2600 ; freq +input_38=1 ; Q +input_39=-2 ; gain +input_40=6 ; peaking +input_41=2600 ; freq +input_42=1 ; Q +input_43=-2 ; gain +input_44=6 ; peaking +input_45=3500 ; freq +input_46=2.5 ; Q +input_47=-8 ; gain +input_48=6 ; peaking +input_49=3500 ; freq +input_50=2.5 ; Q +input_51=-8 ; gain +input_52=6 ; peaking +input_53=6000 ; freq +input_54=1 ; Q +input_55=-2 ; gain +input_56=6 ; peaking +input_57=6000 ; freq +input_58=1 ; Q +input_59=-2 ; gain +input_60=5 ; highshelf +input_61=8000 ; freq +input_62=1 ; Q +input_63=1.5 ; gain +input_64=5 ; highshelf +input_65=8000 ; freq +input_66=1 ; Q +input_67=1.5 ; gain diff --git a/cras-config/veyron_minnie-kernelnext b/cras-config/veyron_minnie-kernelnext new file mode 120000 index 00000000..5fea6bb7 --- /dev/null +++ b/cras-config/veyron_minnie-kernelnext @@ -0,0 +1 @@ +veyron_minnie
\ No newline at end of file diff --git a/cras-config/veyron_minnie/ROCKCHIP-I2S b/cras-config/veyron_minnie/ROCKCHIP-I2S new file mode 100644 index 00000000..297ac51d --- /dev/null +++ b/cras-config/veyron_minnie/ROCKCHIP-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -500 + db_at_98 = -500 + db_at_97 = -600 + db_at_96 = -600 + db_at_95 = -600 + db_at_94 = -600 + db_at_93 = -700 + db_at_92 = -700 + db_at_91 = -700 + db_at_90 = -700 + db_at_89 = -800 + db_at_88 = -800 + db_at_87 = -800 + db_at_86 = -800 + db_at_85 = -900 + db_at_84 = -900 + db_at_83 = -900 + db_at_82 = -900 + db_at_81 = -1000 + db_at_80 = -1000 + db_at_79 = -1000 + db_at_78 = -1000 + db_at_77 = -1100 + db_at_76 = -1100 + db_at_75 = -1100 + db_at_74 = -1100 + db_at_73 = -1200 + db_at_72 = -1200 + db_at_71 = -1200 + db_at_70 = -1200 + db_at_69 = -1300 + db_at_68 = -1300 + db_at_67 = -1300 + db_at_66 = -1300 + db_at_65 = -1400 + db_at_64 = -1400 + db_at_63 = -1400 + db_at_62 = -1400 + db_at_61 = -1500 + db_at_60 = -1500 + db_at_59 = -1500 + db_at_58 = -1500 + db_at_57 = -1600 + db_at_56 = -1600 + db_at_55 = -1600 + db_at_54 = -1600 + db_at_53 = -1700 + db_at_52 = -1700 + db_at_51 = -1700 + db_at_50 = -1700 + db_at_49 = -1800 + db_at_48 = -1800 + db_at_47 = -1800 + db_at_46 = -1800 + db_at_45 = -1900 + db_at_44 = -1900 + db_at_43 = -1900 + db_at_42 = -1900 + db_at_41 = -2000 + db_at_40 = -2000 + db_at_39 = -2000 + db_at_38 = -2100 + db_at_37 = -2100 + db_at_36 = -2200 + db_at_35 = -2200 + db_at_34 = -2300 + db_at_33 = -2300 + db_at_32 = -2400 + db_at_31 = -2400 + db_at_30 = -2500 + db_at_29 = -2500 + db_at_28 = -2600 + db_at_27 = -2600 + db_at_26 = -2700 + db_at_25 = -2700 + db_at_24 = -2800 + db_at_23 = -2900 + db_at_22 = -2900 + db_at_21 = -3000 + db_at_20 = -3100 + db_at_19 = -3200 + db_at_18 = -3200 + db_at_17 = -3300 + db_at_16 = -3400 + db_at_15 = -3500 + db_at_14 = -3500 + db_at_13 = -3600 + db_at_12 = -3700 + db_at_11 = -3800 + db_at_10 = -3800 + db_at_9 = -3900 + db_at_8 = -4000 + db_at_7 = -4100 + db_at_6 = -4100 + db_at_5 = -4200 + db_at_4 = -4300 + db_at_3 = -4400 + db_at_2 = -4400 + db_at_1 = -4500 + db_at_0 = -4600 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_minnie/VEYRON-I2S b/cras-config/veyron_minnie/VEYRON-I2S new file mode 100644 index 00000000..297ac51d --- /dev/null +++ b/cras-config/veyron_minnie/VEYRON-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -500 + db_at_98 = -500 + db_at_97 = -600 + db_at_96 = -600 + db_at_95 = -600 + db_at_94 = -600 + db_at_93 = -700 + db_at_92 = -700 + db_at_91 = -700 + db_at_90 = -700 + db_at_89 = -800 + db_at_88 = -800 + db_at_87 = -800 + db_at_86 = -800 + db_at_85 = -900 + db_at_84 = -900 + db_at_83 = -900 + db_at_82 = -900 + db_at_81 = -1000 + db_at_80 = -1000 + db_at_79 = -1000 + db_at_78 = -1000 + db_at_77 = -1100 + db_at_76 = -1100 + db_at_75 = -1100 + db_at_74 = -1100 + db_at_73 = -1200 + db_at_72 = -1200 + db_at_71 = -1200 + db_at_70 = -1200 + db_at_69 = -1300 + db_at_68 = -1300 + db_at_67 = -1300 + db_at_66 = -1300 + db_at_65 = -1400 + db_at_64 = -1400 + db_at_63 = -1400 + db_at_62 = -1400 + db_at_61 = -1500 + db_at_60 = -1500 + db_at_59 = -1500 + db_at_58 = -1500 + db_at_57 = -1600 + db_at_56 = -1600 + db_at_55 = -1600 + db_at_54 = -1600 + db_at_53 = -1700 + db_at_52 = -1700 + db_at_51 = -1700 + db_at_50 = -1700 + db_at_49 = -1800 + db_at_48 = -1800 + db_at_47 = -1800 + db_at_46 = -1800 + db_at_45 = -1900 + db_at_44 = -1900 + db_at_43 = -1900 + db_at_42 = -1900 + db_at_41 = -2000 + db_at_40 = -2000 + db_at_39 = -2000 + db_at_38 = -2100 + db_at_37 = -2100 + db_at_36 = -2200 + db_at_35 = -2200 + db_at_34 = -2300 + db_at_33 = -2300 + db_at_32 = -2400 + db_at_31 = -2400 + db_at_30 = -2500 + db_at_29 = -2500 + db_at_28 = -2600 + db_at_27 = -2600 + db_at_26 = -2700 + db_at_25 = -2700 + db_at_24 = -2800 + db_at_23 = -2900 + db_at_22 = -2900 + db_at_21 = -3000 + db_at_20 = -3100 + db_at_19 = -3200 + db_at_18 = -3200 + db_at_17 = -3300 + db_at_16 = -3400 + db_at_15 = -3500 + db_at_14 = -3500 + db_at_13 = -3600 + db_at_12 = -3700 + db_at_11 = -3800 + db_at_10 = -3800 + db_at_9 = -3900 + db_at_8 = -4000 + db_at_7 = -4100 + db_at_6 = -4100 + db_at_5 = -4200 + db_at_4 = -4300 + db_at_3 = -4400 + db_at_2 = -4400 + db_at_1 = -4500 + db_at_0 = -4600 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_minnie/dsp.ini b/cras-config/veyron_minnie/dsp.ini new file mode 100644 index 00000000..148b098f --- /dev/null +++ b/cras-config/veyron_minnie/dsp.ini @@ -0,0 +1,79 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=0 ; enable +input_7=-24 ; threshold +input_8=30 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=0 ; boost +input_13=100 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=24 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.5 ; release +input_20=1 ; boost +input_21=2000 ; f +input_22=0 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=200 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=200 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=700 ; freq +input_14=3 ; Q +input_15=-12 ; gain +input_16=6 ; peaking +input_17=700 ; freq +input_18=3 ; Q +input_19=-12 ; gain +input_20=6 ; peaking +input_21=930 ; freq +input_22=3 ; Q +input_23=-12 ; gain +input_24=6 ; peaking +input_25=980 ; freq +input_26=3 ; Q +input_27=-12 ; gain diff --git a/cras-config/veyron_speedy/ROCKCHIP-I2S b/cras-config/veyron_speedy/ROCKCHIP-I2S new file mode 100644 index 00000000..297ac51d --- /dev/null +++ b/cras-config/veyron_speedy/ROCKCHIP-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -500 + db_at_98 = -500 + db_at_97 = -600 + db_at_96 = -600 + db_at_95 = -600 + db_at_94 = -600 + db_at_93 = -700 + db_at_92 = -700 + db_at_91 = -700 + db_at_90 = -700 + db_at_89 = -800 + db_at_88 = -800 + db_at_87 = -800 + db_at_86 = -800 + db_at_85 = -900 + db_at_84 = -900 + db_at_83 = -900 + db_at_82 = -900 + db_at_81 = -1000 + db_at_80 = -1000 + db_at_79 = -1000 + db_at_78 = -1000 + db_at_77 = -1100 + db_at_76 = -1100 + db_at_75 = -1100 + db_at_74 = -1100 + db_at_73 = -1200 + db_at_72 = -1200 + db_at_71 = -1200 + db_at_70 = -1200 + db_at_69 = -1300 + db_at_68 = -1300 + db_at_67 = -1300 + db_at_66 = -1300 + db_at_65 = -1400 + db_at_64 = -1400 + db_at_63 = -1400 + db_at_62 = -1400 + db_at_61 = -1500 + db_at_60 = -1500 + db_at_59 = -1500 + db_at_58 = -1500 + db_at_57 = -1600 + db_at_56 = -1600 + db_at_55 = -1600 + db_at_54 = -1600 + db_at_53 = -1700 + db_at_52 = -1700 + db_at_51 = -1700 + db_at_50 = -1700 + db_at_49 = -1800 + db_at_48 = -1800 + db_at_47 = -1800 + db_at_46 = -1800 + db_at_45 = -1900 + db_at_44 = -1900 + db_at_43 = -1900 + db_at_42 = -1900 + db_at_41 = -2000 + db_at_40 = -2000 + db_at_39 = -2000 + db_at_38 = -2100 + db_at_37 = -2100 + db_at_36 = -2200 + db_at_35 = -2200 + db_at_34 = -2300 + db_at_33 = -2300 + db_at_32 = -2400 + db_at_31 = -2400 + db_at_30 = -2500 + db_at_29 = -2500 + db_at_28 = -2600 + db_at_27 = -2600 + db_at_26 = -2700 + db_at_25 = -2700 + db_at_24 = -2800 + db_at_23 = -2900 + db_at_22 = -2900 + db_at_21 = -3000 + db_at_20 = -3100 + db_at_19 = -3200 + db_at_18 = -3200 + db_at_17 = -3300 + db_at_16 = -3400 + db_at_15 = -3500 + db_at_14 = -3500 + db_at_13 = -3600 + db_at_12 = -3700 + db_at_11 = -3800 + db_at_10 = -3800 + db_at_9 = -3900 + db_at_8 = -4000 + db_at_7 = -4100 + db_at_6 = -4100 + db_at_5 = -4200 + db_at_4 = -4300 + db_at_3 = -4400 + db_at_2 = -4400 + db_at_1 = -4500 + db_at_0 = -4600 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_speedy/VEYRON-I2S b/cras-config/veyron_speedy/VEYRON-I2S new file mode 100644 index 00000000..297ac51d --- /dev/null +++ b/cras-config/veyron_speedy/VEYRON-I2S @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = -500 + db_at_99 = -500 + db_at_98 = -500 + db_at_97 = -600 + db_at_96 = -600 + db_at_95 = -600 + db_at_94 = -600 + db_at_93 = -700 + db_at_92 = -700 + db_at_91 = -700 + db_at_90 = -700 + db_at_89 = -800 + db_at_88 = -800 + db_at_87 = -800 + db_at_86 = -800 + db_at_85 = -900 + db_at_84 = -900 + db_at_83 = -900 + db_at_82 = -900 + db_at_81 = -1000 + db_at_80 = -1000 + db_at_79 = -1000 + db_at_78 = -1000 + db_at_77 = -1100 + db_at_76 = -1100 + db_at_75 = -1100 + db_at_74 = -1100 + db_at_73 = -1200 + db_at_72 = -1200 + db_at_71 = -1200 + db_at_70 = -1200 + db_at_69 = -1300 + db_at_68 = -1300 + db_at_67 = -1300 + db_at_66 = -1300 + db_at_65 = -1400 + db_at_64 = -1400 + db_at_63 = -1400 + db_at_62 = -1400 + db_at_61 = -1500 + db_at_60 = -1500 + db_at_59 = -1500 + db_at_58 = -1500 + db_at_57 = -1600 + db_at_56 = -1600 + db_at_55 = -1600 + db_at_54 = -1600 + db_at_53 = -1700 + db_at_52 = -1700 + db_at_51 = -1700 + db_at_50 = -1700 + db_at_49 = -1800 + db_at_48 = -1800 + db_at_47 = -1800 + db_at_46 = -1800 + db_at_45 = -1900 + db_at_44 = -1900 + db_at_43 = -1900 + db_at_42 = -1900 + db_at_41 = -2000 + db_at_40 = -2000 + db_at_39 = -2000 + db_at_38 = -2100 + db_at_37 = -2100 + db_at_36 = -2200 + db_at_35 = -2200 + db_at_34 = -2300 + db_at_33 = -2300 + db_at_32 = -2400 + db_at_31 = -2400 + db_at_30 = -2500 + db_at_29 = -2500 + db_at_28 = -2600 + db_at_27 = -2600 + db_at_26 = -2700 + db_at_25 = -2700 + db_at_24 = -2800 + db_at_23 = -2900 + db_at_22 = -2900 + db_at_21 = -3000 + db_at_20 = -3100 + db_at_19 = -3200 + db_at_18 = -3200 + db_at_17 = -3300 + db_at_16 = -3400 + db_at_15 = -3500 + db_at_14 = -3500 + db_at_13 = -3600 + db_at_12 = -3700 + db_at_11 = -3800 + db_at_10 = -3800 + db_at_9 = -3900 + db_at_8 = -4000 + db_at_7 = -4100 + db_at_6 = -4100 + db_at_5 = -4200 + db_at_4 = -4300 + db_at_3 = -4400 + db_at_2 = -4400 + db_at_1 = -4500 + db_at_0 = -4600 +[Headphone] + volume_curve = simple_step + volume_step = 70 + max_volume = 0 diff --git a/cras-config/veyron_speedy/dsp.ini b/cras-config/veyron_speedy/dsp.ini new file mode 100644 index 00000000..f95096d4 --- /dev/null +++ b/cras-config/veyron_speedy/dsp.ini @@ -0,0 +1,79 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=0 ; enable +input_7=-24 ; threshold +input_8=30 ; knee +input_9=12 ; ratio +input_10=0.003 ; attack +input_11=0.25 ; release +input_12=-6 ; boost +input_13=50 ; f +input_14=1 ; enable +input_15=-24 ; threshold +input_16=30 ; knee +input_17=12 ; ratio +input_18=0.003 ; attack +input_19=0.25 ; release +input_20=-4.5 ; boost +input_21=2000 ; f +input_22=0 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=300 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=300 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=600 ; freq +input_14=4 ; Q +input_15=-6 ; gain +input_16=6 ; peaking +input_17=600 ; freq +input_18=4 ; Q +input_19=-6 ; gain +input_20=6 ; peaking +input_21=800 ; freq +input_22=4 ; Q +input_23=-6 ; gain +input_24=6 ; peaking +input_25=800 ; freq +input_26=4 ; Q +input_27=-6 ; gain diff --git a/cras-config/whirlwind/dsp.ini b/cras-config/whirlwind/dsp.ini new file mode 100644 index 00000000..9b1badd6 --- /dev/null +++ b/cras-config/whirlwind/dsp.ini @@ -0,0 +1,95 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=1 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-35 ; threshold +input_8=24 ; knee +input_9=8 ; ratio +input_10=0.003 ; attack +input_11=0.3 ; release +input_12=0 ; boost +input_13=450 ; f +input_14=1 ; enable +input_15=-16 ; threshold +input_16=10 ; knee +input_17=6 ; ratio +input_18=0.003 ; attack +input_19=0.3 ; release +input_20=0 ; boost +input_21=1500 ; f +input_22=1 ; enable +input_23=0 ; threshold +input_24=0 ; knee +input_25=1 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=150 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=150 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=350 ; freq +input_14=5 ; Q +input_15=-6 ; gain +input_16=6 ; peaking +input_17=350 ; freq +input_18=5 ; Q +input_19=-6 ; gain +input_20=6 ; peaking +input_21=700 ; freq +input_22=2 ; Q +input_23=-3 ; gain +input_24=6 ; peaking +input_25=700 ; freq +input_26=2 ; Q +input_27=-3 ; gain +input_28=6 ; peaking +input_29=3300 ; freq +input_30=3 ; Q +input_31=-4 ; gain +input_32=6 ; peaking +input_33=3300 ; freq +input_34=3 ; Q +input_35=-4 ; gain +input_36=5 ; highshelf +input_37=2000 ; freq +input_38=1 ; Q +input_39=2 ; gain +input_40=5 ; highshelf +input_41=2000 ; freq +input_42=1 ; Q +input_43=2 ; gain diff --git a/cras-config/wolf/HDA Intel PCH b/cras-config/wolf/HDA Intel PCH new file mode 100644 index 00000000..e0adc3e9 --- /dev/null +++ b/cras-config/wolf/HDA Intel PCH @@ -0,0 +1,107 @@ +[Speaker] + volume_curve = explicit + db_at_100 = 0 + db_at_99 = -75 + db_at_98 = -75 + db_at_97 = -75 + db_at_96 = -75 + db_at_95 = -75 + db_at_94 = -150 + db_at_93 = -150 + db_at_92 = -150 + db_at_91 = -150 + db_at_90 = -225 + db_at_89 = -225 + db_at_88 = -225 + db_at_87 = -225 + db_at_86 = -300 + db_at_85 = -300 + db_at_84 = -300 + db_at_83 = -300 + db_at_82 = -375 + db_at_81 = -375 + db_at_80 = -450 + db_at_79 = -450 + db_at_78 = -450 + db_at_77 = -450 + db_at_76 = -525 + db_at_75 = -525 + db_at_74 = -600 + db_at_73 = -600 + db_at_72 = -600 + db_at_71 = -600 + db_at_70 = -675 + db_at_69 = -675 + db_at_68 = -675 + db_at_67 = -675 + db_at_66 = -750 + db_at_65 = -750 + db_at_64 = -825 + db_at_63 = -825 + db_at_62 = -825 + db_at_61 = -825 + db_at_60 = -900 + db_at_59 = -900 + db_at_58 = -900 + db_at_57 = -900 + db_at_56 = -975 + db_at_55 = -975 + db_at_54 = -1050 + db_at_53 = -1050 + db_at_52 = -1050 + db_at_51 = -1050 + db_at_50 = -1125 + db_at_49 = -1125 + db_at_48 = -1200 + db_at_47 = -1200 + db_at_46 = -1200 + db_at_45 = -1200 + db_at_44 = -1275 + db_at_43 = -1275 + db_at_42 = -1275 + db_at_41 = -1275 + db_at_40 = -1350 + db_at_39 = -1425 + db_at_38 = -1425 + db_at_37 = -1500 + db_at_36 = -1500 + db_at_35 = -1575 + db_at_34 = -1650 + db_at_33 = -1650 + db_at_32 = -1725 + db_at_31 = -1800 + db_at_30 = -1800 + db_at_29 = -1800 + db_at_28 = -1875 + db_at_27 = -2025 + db_at_26 = -2100 + db_at_25 = -2100 + db_at_24 = -2175 + db_at_23 = -2250 + db_at_22 = -2400 + db_at_21 = -2475 + db_at_20 = -2550 + db_at_19 = -2625 + db_at_18 = -2700 + db_at_17 = -2850 + db_at_16 = -2925 + db_at_15 = -3000 + db_at_14 = -3075 + db_at_13 = -3225 + db_at_12 = -3300 + db_at_11 = -3375 + db_at_10 = -3450 + db_at_9 = -3600 + db_at_8 = -3675 + db_at_7 = -3750 + db_at_6 = -3825 + db_at_5 = -3900 + db_at_4 = -4050 + db_at_3 = -4050 + db_at_2 = -4275 + db_at_1 = -4500 + db_at_0 = -4800 +[Headphone] + volume_curve = simple_step + volume_step = 50 + max_volume = 0 diff --git a/cras-config/wolf/dsp.ini b/cras-config/wolf/dsp.ini new file mode 100644 index 00000000..6afaf612 --- /dev/null +++ b/cras-config/wolf/dsp.ini @@ -0,0 +1,103 @@ +[output_source] +library=builtin +label=source +purpose=playback +disable=(not (equal? dsp_name "speaker_eq")) +output_0={src:0} +output_1={src:1} + +[output_sink] +library=builtin +label=sink +purpose=playback +input_0={dst:0} +input_1={dst:1} + +[drc] +library=builtin +label=drc +input_0={src:0} +input_1={src:1} +output_2={intermediate:0} +output_3={intermediate:1} +input_4=0 ; emphasis_disabled +input_5=0 ; f +input_6=1 ; enable +input_7=-16 ; threshold +input_8=11 ; knee +input_9=4.476 ; ratio +input_10=0.003 ; attack +input_11=0.427 ; release +input_12=3 ; boost +input_13=2292 ; f +input_14=1 ; enable +input_15=-17 ; threshold +input_16=13 ; knee +input_17=3.78 ; ratio +input_18=0.003 ; attack +input_19=0.421 ; release +input_20=4 ; boost +input_21=3000 ; f +input_22=0 ; enable +input_23=-24 ; threshold +input_24=30 ; knee +input_25=12 ; ratio +input_26=0.003 ; attack +input_27=0.25 ; release +input_28=0 ; boost + +[eq2] +library=builtin +label=eq2 +input_0={intermediate:0} +input_1={intermediate:1} +output_2={dst:0} +output_3={dst:1} +input_4=2 ; highpass +input_5=200 ; freq +input_6=0 ; Q +input_7=0 ; gain +input_8=2 ; highpass +input_9=200 ; freq +input_10=0 ; Q +input_11=0 ; gain +input_12=6 ; peaking +input_13=794 ; freq +input_14=2 ; Q +input_15=-6.6 ; gain +input_16=6 ; peaking +input_17=794 ; freq +input_18=2 ; Q +input_19=-6.6 ; gain +input_20=6 ; peaking +input_21=1491 ; freq +input_22=3.8537 ; Q +input_23=-4.6 ; gain +input_24=6 ; peaking +input_25=1491 ; freq +input_26=3.8537 ; Q +input_27=-4.6 ; gain +input_28=6 ; peaking +input_29=399 ; freq +input_30=5.2495 ; Q +input_31=-5.1 ; gain +input_32=6 ; peaking +input_33=399 ; freq +input_34=5.2495 ; Q +input_35=-5.1 ; gain +input_36=6 ; peaking +input_37=2645 ; freq +input_38=1 ; Q +input_39=-1.7 ; gain +input_40=6 ; peaking +input_41=2645 ; freq +input_42=1 ; Q +input_43=-1.7 ; gain +input_44=6 ; peaking +input_45=2966 ; freq +input_46=5.5184 ; Q +input_47=4.1 ; gain +input_48=6 ; peaking +input_49=2966 ; freq +input_50=5.5184 ; Q +input_51=4.1 ; gain diff --git a/cras/Makefile.am b/cras/Makefile.am index 6c89bdcb..6ecfbaec 100644 --- a/cras/Makefile.am +++ b/cras/Makefile.am @@ -5,10 +5,3 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = src pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libcras.pc - -compile_commands.json: - which bear || (echo "Please install 'bear' first." && exit 1) - bear make check -j$(nproc) - -clean-local: - rm -f compile_commands.json diff --git a/cras/README.md b/cras/README index e0ef0ec5..bb7004a9 100644 --- a/cras/README.md +++ b/cras/README @@ -1,88 +1,59 @@ CRAS = ChromeOS Audio Server -=== - -# Directories -- [src/server](src/server) - the source for the sound server -- [src/libcras](src/libcras) - client library for interacting with cras -- [src/common](src/common) - files common to both the server and library -- [src/tests](src/tests) - tests for cras and libcras -- [src/fuzz](src/fuzz) - source code and build scripts for coverage-guided - fuzzers for CRAS - -# Building from source: -``` -# Generate install-sh -./git_prepare.sh - -# Configure -CC=clang \ -CXX=clang++ \ -CXXFLAGS="-g -O2 -std=gnu++11 -Wall" \ -CFLAGS="-g -O2 -Wall" \ -./configure --disable-alsa-plugin - -# Compile -make -j$(nproc) -# Compile with unit tests -make -j$(nproc) check +Directories +src/server - the source for the sound server +src/libcras - client library for interacting with cras +src/common - files common to both the server and library +src/tests - tests for cras and libcras -# Install binaries to /usr/bin +Building from source: +./git_prepare.sh +./configure +make sudo make install -``` - -## Code complete for for editors -You need to install [bear] first and generate [compile commands] for -[language server plugins in editors] by -``` -make clean && make compile_commands.json -``` -Then you'll get `compile_commands.json` for editor. -Import the JSON file to your editor and you'll get useful code complete -features for CRAS and its unit tests. - -# Configuration: -## Device Blocklisting: +--------------------- +Configuration: +--------------------- -Blocklist of certain USB output device(s) is possible by modifying the config -file `/etc/cras/device_blocklist`. +Device Blacklisting: +-------------------- +Blacklist of certain USB output device(s) is possible by modifying the config +file /etc/cras/device_blacklist. The format of this file is as follows: -``` + [USB_Outputs] <vendor_id>_<product_id>_<checksum>_<device_index> = 1 -``` + Where vendor_id and product id are the USB identifiers for the card to -blocklist. The checksum is the output of "cksum" command applied to the +blacklist. The checksum is the output of "cksum" command applied to the sysfs "descriptors" file of the device. The device index specifies the -index of the output device in the card to blocklist. This is a bool +index of the output device in the card to blacklist. This is a bool parameter, so '= 1' enables the option. -Example, blocklisting the non-functional output device reported by the C-Media +Example, blacklisting the non-functional output device reported by the C-Media based CAD-u1 mic: -``` + [USB_Outputs] 0d8c_0008_00000000_0 = 1 -``` - -## Card Configuration: +Card Configuration: +------------------- There can be a config file for each sound alsa card on the system. This file -lives in `/etc/cras/`. The file should be named with the card name returned by +lives in /etc/cras/. The file should be named with the card name returned by ALSA, the string in the second set of '[]' in the aplay -l output. The ini file has the following format. -``` [<output-node-name>] ; Name of the mixer control for this output. <config-option> = <config-value> -``` + output-node-name can be speficied in a few ways to link with the real node: -- UCM device name - The name string following the SectionDevice label in UCM + UCM device name - The name string following the SectionDevice label in UCM config, i.e. HiFi.conf -- Jack name - Name of the mixer control for mixer jack, or the gpio jack name + Jack name - Name of the mixer control for mixer jack, or the gpio jack name listed by 'evtest' command. -- Mixer control name - e.g. "Headphone" or "Speaker", listed by + Mixer control name - e.g. "Headphone" or "Speaker", listed by 'amixer scontrols' command. Note that an output node matches to the output-node-name label in card config by @@ -91,12 +62,12 @@ search the config file for the UCM device name. When not found, jack name will be used for searching, and lastly the mixer output control name. config-option can be the following: -- volume_curve - The type of volume curve, "simple_step" or "explicit". -- Options valid and mandatory when volume_curve = simple_step: - - max_volume - The maximum volume for this output specified in dBFS * 100. - - volume_step - Number of dB per volume 'tick' specified in dBFS * 100. -- Options valid and mandatory when volume_curve = explicit: - - dB_at_N - The value in dB*100 that should be used for the volume at step + volume_curve - The type of volume curve, "simple_step" or "explicit". + Options valid and mandatory when volume_curve = simple_step: + max_volume - The maximum volume for this output specified in dBFS * 100. + volume_step - Number of dB per volume 'tick' specified in dBFS * 100. + Options valid and mandatory when volume_curve = explicit: + dB_at_N - The value in dB*100 that should be used for the volume at step "N". There must be one of these for each setting from N=0 to 100 inclusive. @@ -107,7 +78,6 @@ step size of 0.75dBFS and the Speaker to have the curve specified by the steps given, which is a 1dBFS per step curve from max = +0.5dBFS to min = -99.5dBFS (volume step 10 is -89.5dBFS). -``` [Headphone] volume_curve = simple_step volume_step = 75 @@ -215,8 +185,3 @@ given, which is a 1dBFS per step curve from max = +0.5dBFS to min = -99.5dBFS dB_at_98 = -150 dB_at_99 = -50 dB_at_100 = 50 -``` - -[bear]: https://github.com/rizsotto/Bear -[compile commands]: https://clang.llvm.org/extra/clangd/Installation.html#compile-commands-json -[language server plugins in editors]: https://clang.llvm.org/extra/clangd/Installation.html#editor-plugins diff --git a/cras/README.dbus-api b/cras/README.dbus-api index f347358e..cac2f031 100644 --- a/cras/README.dbus-api +++ b/cras/README.dbus-api @@ -30,12 +30,19 @@ Methods void SetOutputVolume(int32 volume) Sets the system output mute from user action. + void SetInputGain(int32 gain) + + Sets the capture gain of the system. Gain is specified + in dBFS * 100. For example 5dB of gain would be + specified with an argument of 500, while -10 would be + specified with -1000, and 11.5 maps to 1150. + void SetInputNodeGain(uint64 node_id, int32 gain) - Sets the capture gain of the node. gain is a 0-100 - integer which linearly maps [0, 50] to range [-40dB, 0dB] - and [50, 100] to [0dB, 20dB], - Default gain value is 50, which is 0dB. + Sets the capture gain of the node. Gain is specified + in dBFS * 100. For example 5dB of gain would be + specified with an argument of 500, while -10 would be + specified with -1000, and 11.5 maps to 1150. void SetInputMute(boolean mute_on) @@ -105,6 +112,9 @@ Methods void SetOutputVolume(int32 volume) uint64 PluggedTime The time that this device was plugged in. This value is in microseconds. + string MicPositions + The string formed by floating numbers + describing the position of mic array. unit64 NodeVolume The node volume indexed from 0 to 100. unit64 NodeCaptureGain @@ -151,9 +161,9 @@ Methods void SetOutputVolume(int32 volume) int32 IsAudioOutputActive() Returns 1 if there are currently any active output streams, - excluding 'fake' streams that are not actually outputting any + excluding 'dummy' streams that are not actually outputting any audio. Returns 0 if there are no active streams, or all active - streams are 'fake' streams. + streams are 'dummy' streams. void SetGlobalOutputChannelRemix(int32 num_channels, array:double coefficient) diff --git a/cras/client/cras-sys/.gitignore b/cras/client/cras-sys/.gitignore index fa8d85ac..5245cb55 100644 --- a/cras/client/cras-sys/.gitignore +++ b/cras/client/cras-sys/.gitignore @@ -1,2 +1,2 @@ -Cargo.lock -target +target/ +lib_gen.rs diff --git a/cras/client/cras-sys/Android.bp b/cras/client/cras-sys/Android.bp index d6482b2e..2a90f8f9 100644 --- a/cras/client/cras-sys/Android.bp +++ b/cras/client/cras-sys/Android.bp @@ -1,62 +1,26 @@ -// This file is generated by cargo2android.py --run --device --test --global_defaults=crosvm_defaults --dependencies. +// This file is generated by cargo2android.py, added defaults. -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "external_adhd_license" - // to get the below license kinds: - // SPDX-license-identifier-BSD - default_applicable_licenses: ["external_adhd_license"], -} - -rust_defaults { - name: "cras-sys_defaults", +rust_test_host { + name: "cras-sys_tests_cras_sys", defaults: ["crosvm_defaults"], crate_name: "cras_sys", srcs: ["src/lib.rs"], + relative_install_path: "cras-sys_tests", test_suites: ["general-tests"], auto_gen_config: true, edition: "2015", - rustlibs: [ - "libaudio_streams", + rlibs: [ "libdata_model", ], } -rust_test_host { - name: "cras-sys_host_test_src_lib", - defaults: ["cras-sys_defaults"], -} - -rust_test { - name: "cras-sys_device_test_src_lib", - defaults: ["cras-sys_defaults"], -} - -rust_library { +rust_library_host_rlib { name: "libcras_sys", defaults: ["crosvm_defaults"], - host_supported: true, crate_name: "cras_sys", srcs: ["src/lib.rs"], edition: "2015", - rustlibs: [ - "libaudio_streams", + rlibs: [ "libdata_model", ], } - -// dependent_library ["feature_list"] -// ../../../../crosvm/assertions/src/lib.rs -// ../../../../crosvm/data_model/src/lib.rs -// ../../../../crosvm/sync/src/lib.rs -// ../../../../crosvm/sys_util/poll_token_derive/poll_token_derive.rs -// ../../../../crosvm/sys_util/src/lib.rs -// ../../../../crosvm/syscall_defines/src/lib.rs -// ../../../../crosvm/tempfile/src/lib.rs -// ../../../audio_streams/src/audio_streams.rs -// libc-0.2.76 "default,std" -// proc-macro2-1.0.19 "default,proc-macro" -// quote-1.0.7 "default,proc-macro" -// syn-1.0.39 "clone-impls,default,derive,parsing,printing,proc-macro,quote" -// unicode-xid-0.2.1 "default" diff --git a/cras/client/cras-sys/Cargo.toml b/cras/client/cras-sys/Cargo.toml index 1ac1857a..f71e5408 100644 --- a/cras/client/cras-sys/Cargo.toml +++ b/cras/client/cras-sys/Cargo.toml @@ -4,5 +4,4 @@ version = "0.1.0" authors = ["The Chromium OS Authors"] [dependencies] -audio_streams = { path = "../../../audio_streams" } # provided by ebuild -data_model = { path = "../../../../crosvm/data_model" } # provided by ebuild +data_model = { path = "../../../../../platform/crosvm/data_model" } # provided by ebuild diff --git a/cras/client/cras-sys/generator/src/main.rs b/cras/client/cras-sys/generator/src/main.rs index e562691d..7b47f025 100644 --- a/cras/client/cras-sys/generator/src/main.rs +++ b/cras/client/cras-sys/generator/src/main.rs @@ -36,7 +36,6 @@ fn copy_headers(src_dir: &Path, dst_dir: &Path) -> Result<(), String> { "cras_shm.h", "cras_types.h", "cras_util.h", - "packet_status_logger.h", ]; for header in &header_files { @@ -111,10 +110,8 @@ fn gen() -> String { .whitelist_type("CRAS_.*") .whitelist_var("CRAS_.*") .whitelist_type("audio_message") - .whitelist_var("MAX_DEBUG_.*") .rustified_enum("CRAS_.*") .rustified_enum("_snd_pcm_.*") - .bitfield_enum("CRAS_STREAM_EFFECT") .generate() .expect(format!("Unable to generate {} code", name).as_str()); @@ -134,11 +131,7 @@ fn write_output(output_path: &Path, output: String) -> std::io::Result<()> { * cras_shm.h * cras_types.h * cras_util.h - * packet_status_logger.h */ - -#![allow(clippy::unreadable_literal)] -#![allow(clippy::cognitive_complexity)] "; let mut output_file = File::create(output_path)?; diff --git a/cras/client/cras-sys/src/gen.rs b/cras/client/cras-sys/src/gen.rs index 6fb4cdf8..59d146a6 100644 --- a/cras/client/cras-sys/src/gen.rs +++ b/cras/client/cras-sys/src/gen.rs @@ -10,11 +10,7 @@ * cras_shm.h * cras_types.h * cras_util.h - * packet_status_logger.h */ - -#![allow(clippy::unreadable_literal)] -#![allow(clippy::cognitive_complexity)] /* automatically generated by rust-bindgen */ pub const CRAS_IODEV_NAME_BUFFER_SIZE: u32 = 64; @@ -27,15 +23,13 @@ pub const CRAS_MAX_IONODES: u32 = 20; pub const CRAS_MAX_ATTACHED_CLIENTS: u32 = 20; pub const CRAS_MAX_AUDIO_THREAD_SNAPSHOTS: u32 = 10; pub const CRAS_MAX_HOTWORD_MODEL_NAME_SIZE: u32 = 12; -pub const MAX_DEBUG_DEVS: u32 = 4; -pub const MAX_DEBUG_STREAMS: u32 = 8; pub const CRAS_BT_EVENT_LOG_SIZE: u32 = 1024; pub const CRAS_SERVER_STATE_VERSION: u32 = 2; -pub const CRAS_PROTO_VER: u32 = 7; +pub const CRAS_PROTO_VER: u32 = 5; pub const CRAS_SERV_MAX_MSG_SIZE: u32 = 256; pub const CRAS_CLIENT_MAX_MSG_SIZE: u32 = 256; -pub const CRAS_MAX_HOTWORD_MODELS: u32 = 243; -pub const CRAS_MAX_REMIX_CHANNELS: u32 = 8; +pub const CRAS_MAX_HOTWORD_MODELS: u32 = 244; +pub const CRAS_MAX_REMIX_CHANNELS: u32 = 32; pub const CRAS_MAX_TEST_DATA_LEN: u32 = 224; pub const CRAS_AEC_DUMP_FILE_NAME_LEN: u32 = 128; pub const CRAS_NUM_SHM_BUFFERS: u32 = 2; @@ -54,7 +48,7 @@ pub struct cras_iodev_info { pub idx: u32, pub name: [::std::os::raw::c_char; 64usize], pub stable_id: u32, - pub max_supported_channels: u32, + pub stable_id_new: u32, } #[test] fn bindgen_test_layout_cras_iodev_info() { @@ -99,15 +93,13 @@ fn bindgen_test_layout_cras_iodev_info() { ) ); assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_iodev_info>())).max_supported_channels as *const _ as usize - }, + unsafe { &(*(::std::ptr::null::<cras_iodev_info>())).stable_id_new as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(cras_iodev_info), "::", - stringify!(max_supported_channels) + stringify!(stable_id_new) ) ); } @@ -121,10 +113,11 @@ pub struct cras_ionode_info { pub plugged_time: cras_ionode_info__bindgen_ty_1, pub volume: u32, pub capture_gain: i32, - pub ui_gain_scaler: f32, pub left_right_swapped: i32, pub type_enum: u32, pub stable_id: u32, + pub stable_id_new: u32, + pub mic_positions: [::std::os::raw::c_char; 128usize], pub type_: [::std::os::raw::c_char; 32usize], pub name: [::std::os::raw::c_char; 64usize], pub active_hotword_model: [::std::os::raw::c_char; 16usize], @@ -176,7 +169,7 @@ fn bindgen_test_layout_cras_ionode_info__bindgen_ty_1() { fn bindgen_test_layout_cras_ionode_info() { assert_eq!( ::std::mem::size_of::<cras_ionode_info>(), - 168usize, + 296usize, concat!("Size of: ", stringify!(cras_ionode_info)) ); assert_eq!( @@ -255,60 +248,70 @@ fn bindgen_test_layout_cras_ionode_info() { ) ); assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).ui_gain_scaler as *const _ as usize }, + unsafe { + &(*(::std::ptr::null::<cras_ionode_info>())).left_right_swapped as *const _ as usize + }, 40usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), "::", - stringify!(ui_gain_scaler) + stringify!(left_right_swapped) ) ); assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_ionode_info>())).left_right_swapped as *const _ as usize - }, + unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).type_enum as *const _ as usize }, 44usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), "::", - stringify!(left_right_swapped) + stringify!(type_enum) ) ); assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).type_enum as *const _ as usize }, + unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).stable_id as *const _ as usize }, 48usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), "::", - stringify!(type_enum) + stringify!(stable_id) ) ); assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).stable_id as *const _ as usize }, + unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).stable_id_new as *const _ as usize }, 52usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), "::", - stringify!(stable_id) + stringify!(stable_id_new) ) ); assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).type_ as *const _ as usize }, + unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).mic_positions as *const _ as usize }, 56usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), "::", + stringify!(mic_positions) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).type_ as *const _ as usize }, + 184usize, + concat!( + "Offset of field: ", + stringify!(cras_ionode_info), + "::", stringify!(type_) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).name as *const _ as usize }, - 88usize, + 216usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), @@ -320,7 +323,7 @@ fn bindgen_test_layout_cras_ionode_info() { unsafe { &(*(::std::ptr::null::<cras_ionode_info>())).active_hotword_model as *const _ as usize }, - 152usize, + 280usize, concat!( "Offset of field: ", stringify!(cras_ionode_info), @@ -613,78 +616,6 @@ fn bindgen_test_layout_cras_audio_format_packed() { ) ); } -#[repr(C)] -#[derive(Copy, Clone)] -pub struct packet_status_logger { - pub data: [u8; 64usize], - pub size: ::std::os::raw::c_int, - pub wp: ::std::os::raw::c_int, - pub num_wraps: ::std::os::raw::c_int, - pub ts: timespec, -} -#[test] -fn bindgen_test_layout_packet_status_logger() { - assert_eq!( - ::std::mem::size_of::<packet_status_logger>(), - 96usize, - concat!("Size of: ", stringify!(packet_status_logger)) - ); - assert_eq!( - ::std::mem::align_of::<packet_status_logger>(), - 8usize, - concat!("Alignment of ", stringify!(packet_status_logger)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<packet_status_logger>())).data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(packet_status_logger), - "::", - stringify!(data) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<packet_status_logger>())).size as *const _ as usize }, - 64usize, - concat!( - "Offset of field: ", - stringify!(packet_status_logger), - "::", - stringify!(size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<packet_status_logger>())).wp as *const _ as usize }, - 68usize, - concat!( - "Offset of field: ", - stringify!(packet_status_logger), - "::", - stringify!(wp) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<packet_status_logger>())).num_wraps as *const _ as usize }, - 72usize, - concat!( - "Offset of field: ", - stringify!(packet_status_logger), - "::", - stringify!(num_wraps) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<packet_status_logger>())).ts as *const _ as usize }, - 80usize, - concat!( - "Offset of field: ", - stringify!(packet_status_logger), - "::", - stringify!(ts) - ) - ); -} #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct cras_timespec { @@ -742,18 +673,6 @@ pub enum CRAS_TEST_IODEV_CMD { } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum CRAS_CONNECTION_TYPE { - CRAS_CONTROL = 0, - CRAS_PLAYBACK = 1, - CRAS_CAPTURE = 2, - CRAS_VMS_LEGACY = 3, - CRAS_VMS_UNIFIED = 4, - CRAS_PLUGIN_PLAYBACK = 5, - CRAS_PLUGIN_UNIFIED = 6, - CRAS_NUM_CONN_TYPE = 7, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum CRAS_STREAM_DIRECTION { CRAS_STREAM_OUTPUT = 0, CRAS_STREAM_INPUT = 1, @@ -798,53 +717,15 @@ pub enum CRAS_CLIENT_TYPE { CRAS_CLIENT_TYPE_CHROME = 4, CRAS_CLIENT_TYPE_ARC = 5, CRAS_CLIENT_TYPE_CROSVM = 6, - CRAS_CLIENT_TYPE_SERVER_STREAM = 7, - CRAS_CLIENT_TYPE_LACROS = 8, - CRAS_CLIENT_TYPE_PLUGIN = 9, - CRAS_CLIENT_TYPE_ARCVM = 10, - CRAS_NUM_CLIENT_TYPE = 11, -} -impl CRAS_STREAM_EFFECT { - pub const APM_ECHO_CANCELLATION: CRAS_STREAM_EFFECT = CRAS_STREAM_EFFECT(1); -} -impl CRAS_STREAM_EFFECT { - pub const APM_NOISE_SUPRESSION: CRAS_STREAM_EFFECT = CRAS_STREAM_EFFECT(2); -} -impl CRAS_STREAM_EFFECT { - pub const APM_GAIN_CONTROL: CRAS_STREAM_EFFECT = CRAS_STREAM_EFFECT(4); -} -impl CRAS_STREAM_EFFECT { - pub const APM_VOICE_DETECTION: CRAS_STREAM_EFFECT = CRAS_STREAM_EFFECT(8); -} -impl ::std::ops::BitOr<CRAS_STREAM_EFFECT> for CRAS_STREAM_EFFECT { - type Output = Self; - #[inline] - fn bitor(self, other: Self) -> Self { - CRAS_STREAM_EFFECT(self.0 | other.0) - } -} -impl ::std::ops::BitOrAssign for CRAS_STREAM_EFFECT { - #[inline] - fn bitor_assign(&mut self, rhs: CRAS_STREAM_EFFECT) { - self.0 |= rhs.0; - } -} -impl ::std::ops::BitAnd<CRAS_STREAM_EFFECT> for CRAS_STREAM_EFFECT { - type Output = Self; - #[inline] - fn bitand(self, other: Self) -> Self { - CRAS_STREAM_EFFECT(self.0 & other.0) - } -} -impl ::std::ops::BitAndAssign for CRAS_STREAM_EFFECT { - #[inline] - fn bitand_assign(&mut self, rhs: CRAS_STREAM_EFFECT) { - self.0 &= rhs.0; - } } -#[repr(C)] +#[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct CRAS_STREAM_EFFECT(pub u32); +pub enum CRAS_STREAM_EFFECT { + APM_ECHO_CANCELLATION = 1, + APM_NOISE_SUPRESSION = 2, + APM_GAIN_CONTROL = 4, + APM_VOICE_DETECTION = 8, +} #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct cras_attached_client_info { @@ -919,25 +800,19 @@ pub enum CRAS_BT_LOG_EVENTS { BT_A2DP_START = 6, BT_A2DP_SUSPENDED = 7, BT_CODEC_SELECTION = 8, - BT_DEV_CONNECTED = 9, - BT_DEV_DISCONNECTED = 10, - BT_DEV_CONN_WATCH_CB = 11, - BT_DEV_SUSPEND_CB = 12, - BT_HFP_NEW_CONNECTION = 13, - BT_HFP_REQUEST_DISCONNECT = 14, - BT_HFP_SUPPORTED_FEATURES = 15, - BT_HFP_HF_INDICATOR = 16, - BT_HFP_SET_SPEAKER_GAIN = 17, - BT_HFP_UPDATE_SPEAKER_GAIN = 18, - BT_HSP_NEW_CONNECTION = 19, - BT_HSP_REQUEST_DISCONNECT = 20, - BT_NEW_AUDIO_PROFILE_AFTER_CONNECT = 21, - BT_RESET = 22, - BT_SCO_CONNECT = 23, - BT_TRANSPORT_ACQUIRE = 24, - BT_TRANSPORT_RELEASE = 25, - BT_TRANSPORT_SET_VOLUME = 26, - BT_TRANSPORT_UPDATE_VOLUME = 27, + BT_DEV_CONNECTED_CHANGE = 9, + BT_DEV_CONN_WATCH_CB = 10, + BT_DEV_SUSPEND_CB = 11, + BT_HFP_NEW_CONNECTION = 12, + BT_HFP_REQUEST_DISCONNECT = 13, + BT_HFP_SUPPORTED_FEATURES = 14, + BT_HSP_NEW_CONNECTION = 15, + BT_HSP_REQUEST_DISCONNECT = 16, + BT_NEW_AUDIO_PROFILE_AFTER_CONNECT = 17, + BT_RESET = 18, + BT_SCO_CONNECT = 19, + BT_TRANSPORT_ACQUIRE = 20, + BT_TRANSPORT_RELEASE = 21, } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] @@ -1014,8 +889,7 @@ fn bindgen_test_layout_audio_thread_event() { #[repr(C, packed)] #[derive(Copy, Clone)] pub struct audio_thread_event_log { - pub write_pos: u64, - pub sync_write_pos: u64, + pub write_pos: u32, pub len: u32, pub log: [audio_thread_event; 6144usize], } @@ -1023,7 +897,7 @@ pub struct audio_thread_event_log { fn bindgen_test_layout_audio_thread_event_log() { assert_eq!( ::std::mem::size_of::<audio_thread_event_log>(), - 122900usize, + 122888usize, concat!("Size of: ", stringify!(audio_thread_event_log)) ); assert_eq!( @@ -1044,20 +918,8 @@ fn bindgen_test_layout_audio_thread_event_log() { ) ); assert_eq!( - unsafe { - &(*(::std::ptr::null::<audio_thread_event_log>())).sync_write_pos as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(audio_thread_event_log), - "::", - stringify!(sync_write_pos) - ) - ); - assert_eq!( unsafe { &(*(::std::ptr::null::<audio_thread_event_log>())).len as *const _ as usize }, - 16usize, + 4usize, concat!( "Offset of field: ", stringify!(audio_thread_event_log), @@ -1067,7 +929,7 @@ fn bindgen_test_layout_audio_thread_event_log() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<audio_thread_event_log>())).log as *const _ as usize }, - 20usize, + 8usize, concat!( "Offset of field: ", stringify!(audio_thread_event_log), @@ -1093,15 +955,13 @@ pub struct audio_dev_debug_info { pub highest_hw_level: u32, pub runtime_sec: u32, pub runtime_nsec: u32, - pub longest_wake_sec: u32, - pub longest_wake_nsec: u32, pub software_gain_scaler: f64, } #[test] fn bindgen_test_layout_audio_dev_debug_info() { assert_eq!( ::std::mem::size_of::<audio_dev_debug_info>(), - 133usize, + 125usize, concat!("Size of: ", stringify!(audio_dev_debug_info)) ); assert_eq!( @@ -1274,34 +1134,10 @@ fn bindgen_test_layout_audio_dev_debug_info() { ); assert_eq!( unsafe { - &(*(::std::ptr::null::<audio_dev_debug_info>())).longest_wake_sec as *const _ as usize - }, - 117usize, - concat!( - "Offset of field: ", - stringify!(audio_dev_debug_info), - "::", - stringify!(longest_wake_sec) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<audio_dev_debug_info>())).longest_wake_nsec as *const _ as usize - }, - 121usize, - concat!( - "Offset of field: ", - stringify!(audio_dev_debug_info), - "::", - stringify!(longest_wake_nsec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<audio_dev_debug_info>())).software_gain_scaler as *const _ as usize }, - 125usize, + 117usize, concat!( "Offset of field: ", stringify!(audio_dev_debug_info), @@ -1609,7 +1445,7 @@ pub struct audio_debug_info { fn bindgen_test_layout_audio_debug_info() { assert_eq!( ::std::mem::size_of::<audio_debug_info>(), - 124264usize, + 124220usize, concat!("Size of: ", stringify!(audio_debug_info)) ); assert_eq!( @@ -1649,7 +1485,7 @@ fn bindgen_test_layout_audio_debug_info() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<audio_debug_info>())).streams as *const _ as usize }, - 540usize, + 508usize, concat!( "Offset of field: ", stringify!(audio_debug_info), @@ -1659,7 +1495,7 @@ fn bindgen_test_layout_audio_debug_info() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<audio_debug_info>())).log as *const _ as usize }, - 1364usize, + 1332usize, concat!( "Offset of field: ", stringify!(audio_debug_info), @@ -1670,156 +1506,6 @@ fn bindgen_test_layout_audio_debug_info() { } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] -pub struct main_thread_event { - pub tag_sec: u32, - pub nsec: u32, - pub data1: u32, - pub data2: u32, - pub data3: u32, -} -#[test] -fn bindgen_test_layout_main_thread_event() { - assert_eq!( - ::std::mem::size_of::<main_thread_event>(), - 20usize, - concat!("Size of: ", stringify!(main_thread_event)) - ); - assert_eq!( - ::std::mem::align_of::<main_thread_event>(), - 1usize, - concat!("Alignment of ", stringify!(main_thread_event)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event>())).tag_sec as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event), - "::", - stringify!(tag_sec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event>())).nsec as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event), - "::", - stringify!(nsec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event>())).data1 as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event), - "::", - stringify!(data1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event>())).data2 as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event), - "::", - stringify!(data2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event>())).data3 as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event), - "::", - stringify!(data3) - ) - ); -} -#[repr(C, packed)] -#[derive(Copy, Clone)] -pub struct main_thread_event_log { - pub write_pos: u32, - pub len: u32, - pub log: [main_thread_event; 1024usize], -} -#[test] -fn bindgen_test_layout_main_thread_event_log() { - assert_eq!( - ::std::mem::size_of::<main_thread_event_log>(), - 20488usize, - concat!("Size of: ", stringify!(main_thread_event_log)) - ); - assert_eq!( - ::std::mem::align_of::<main_thread_event_log>(), - 1usize, - concat!("Alignment of ", stringify!(main_thread_event_log)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event_log>())).write_pos as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event_log), - "::", - stringify!(write_pos) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event_log>())).len as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event_log), - "::", - stringify!(len) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_event_log>())).log as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(main_thread_event_log), - "::", - stringify!(log) - ) - ); -} -#[repr(C, packed)] -#[derive(Copy, Clone)] -pub struct main_thread_debug_info { - pub main_log: main_thread_event_log, -} -#[test] -fn bindgen_test_layout_main_thread_debug_info() { - assert_eq!( - ::std::mem::size_of::<main_thread_debug_info>(), - 20488usize, - concat!("Size of: ", stringify!(main_thread_debug_info)) - ); - assert_eq!( - ::std::mem::align_of::<main_thread_debug_info>(), - 1usize, - concat!("Alignment of ", stringify!(main_thread_debug_info)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<main_thread_debug_info>())).main_log as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(main_thread_debug_info), - "::", - stringify!(main_log) - ) - ); -} -#[repr(C, packed)] -#[derive(Debug, Copy, Clone)] pub struct cras_bt_event { pub tag_sec: u32, pub nsec: u32, @@ -1933,13 +1619,12 @@ fn bindgen_test_layout_cras_bt_event_log() { #[derive(Copy, Clone)] pub struct cras_bt_debug_info { pub bt_log: cras_bt_event_log, - pub wbs_logger: packet_status_logger, } #[test] fn bindgen_test_layout_cras_bt_debug_info() { assert_eq!( ::std::mem::size_of::<cras_bt_debug_info>(), - 16488usize, + 16392usize, concat!("Size of: ", stringify!(cras_bt_debug_info)) ); assert_eq!( @@ -1957,29 +1642,15 @@ fn bindgen_test_layout_cras_bt_debug_info() { stringify!(bt_log) ) ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_bt_debug_info>())).wbs_logger as *const _ as usize }, - 16392usize, - concat!( - "Offset of field: ", - stringify!(cras_bt_debug_info), - "::", - stringify!(wbs_logger) - ) - ); } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum CRAS_AUDIO_THREAD_EVENT_TYPE { - AUDIO_THREAD_EVENT_A2DP_OVERRUN = 0, - AUDIO_THREAD_EVENT_A2DP_THROTTLE = 1, - AUDIO_THREAD_EVENT_BUSYLOOP = 2, - AUDIO_THREAD_EVENT_DEBUG = 3, - AUDIO_THREAD_EVENT_SEVERE_UNDERRUN = 4, - AUDIO_THREAD_EVENT_UNDERRUN = 5, - AUDIO_THREAD_EVENT_DROP_SAMPLES = 6, - AUDIO_THREAD_EVENT_DEV_OVERRUN = 7, - AUDIO_THREAD_EVENT_TYPE_COUNT = 8, + AUDIO_THREAD_EVENT_BUSYLOOP = 0, + AUDIO_THREAD_EVENT_DEBUG = 1, + AUDIO_THREAD_EVENT_SEVERE_UNDERRUN = 2, + AUDIO_THREAD_EVENT_UNDERRUN = 3, + AUDIO_THREAD_EVENT_TYPE_COUNT = 4, } #[repr(C, packed)] #[derive(Copy, Clone)] @@ -1992,7 +1663,7 @@ pub struct cras_audio_thread_snapshot { fn bindgen_test_layout_cras_audio_thread_snapshot() { assert_eq!( ::std::mem::size_of::<cras_audio_thread_snapshot>(), - 124284usize, + 124240usize, concat!("Size of: ", stringify!(cras_audio_thread_snapshot)) ); assert_eq!( @@ -2048,7 +1719,7 @@ pub struct cras_audio_thread_snapshot_buffer { fn bindgen_test_layout_cras_audio_thread_snapshot_buffer() { assert_eq!( ::std::mem::size_of::<cras_audio_thread_snapshot_buffer>(), - 1242844usize, + 1242404usize, concat!("Size of: ", stringify!(cras_audio_thread_snapshot_buffer)) ); assert_eq!( @@ -2076,7 +1747,7 @@ fn bindgen_test_layout_cras_audio_thread_snapshot_buffer() { unsafe { &(*(::std::ptr::null::<cras_audio_thread_snapshot_buffer>())).pos as *const _ as usize }, - 1242840usize, + 1242400usize, concat!( "Offset of field: ", stringify!(cras_audio_thread_snapshot_buffer), @@ -2097,8 +1768,11 @@ pub struct cras_server_state { pub mute_locked: i32, pub suspended: i32, pub capture_gain: i32, + pub capture_gain_target: i32, pub capture_mute: i32, pub capture_mute_locked: i32, + pub min_capture_gain: i32, + pub max_capture_gain: i32, pub num_streams_attached: u32, pub num_output_devs: u32, pub num_input_devs: u32, @@ -2121,17 +1795,12 @@ pub struct cras_server_state { pub snapshot_buffer: cras_audio_thread_snapshot_buffer, pub bt_debug_info: cras_bt_debug_info, pub bt_wbs_enabled: i32, - pub deprioritize_bt_wbs_mic: i32, - pub main_thread_debug_info: main_thread_debug_info, - pub num_input_streams_with_permission: [u32; 11usize], - pub noise_cancellation_enabled: i32, - pub hotword_pause_at_suspend: i32, } #[test] fn bindgen_test_layout_cras_server_state() { assert_eq!( ::std::mem::size_of::<cras_server_state>(), - 1414344usize, + 1398352usize, concat!("Size of: ", stringify!(cras_server_state)) ); assert_eq!( @@ -2234,12 +1903,24 @@ fn bindgen_test_layout_cras_server_state() { ) ); assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_server_state>())).capture_mute as *const _ as usize }, + unsafe { + &(*(::std::ptr::null::<cras_server_state>())).capture_gain_target as *const _ as usize + }, 36usize, concat!( "Offset of field: ", stringify!(cras_server_state), "::", + stringify!(capture_gain_target) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<cras_server_state>())).capture_mute as *const _ as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(cras_server_state), + "::", stringify!(capture_mute) ) ); @@ -2247,7 +1928,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).capture_mute_locked as *const _ as usize }, - 40usize, + 44usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2257,9 +1938,33 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { + &(*(::std::ptr::null::<cras_server_state>())).min_capture_gain as *const _ as usize + }, + 48usize, + concat!( + "Offset of field: ", + stringify!(cras_server_state), + "::", + stringify!(min_capture_gain) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_server_state>())).max_capture_gain as *const _ as usize + }, + 52usize, + concat!( + "Offset of field: ", + stringify!(cras_server_state), + "::", + stringify!(max_capture_gain) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_streams_attached as *const _ as usize }, - 44usize, + 56usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2271,7 +1976,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_output_devs as *const _ as usize }, - 48usize, + 60usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2283,7 +1988,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_input_devs as *const _ as usize }, - 52usize, + 64usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2293,7 +1998,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).output_devs as *const _ as usize }, - 56usize, + 68usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2303,7 +2008,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).input_devs as *const _ as usize }, - 1576usize, + 1588usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2315,7 +2020,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_output_nodes as *const _ as usize }, - 3096usize, + 3108usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2327,7 +2032,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_input_nodes as *const _ as usize }, - 3100usize, + 3112usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2337,7 +2042,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).output_nodes as *const _ as usize }, - 3104usize, + 3116usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2347,7 +2052,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).input_nodes as *const _ as usize }, - 6464usize, + 9036usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2359,7 +2064,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_attached_clients as *const _ as usize }, - 9824usize, + 14956usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2369,7 +2074,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).client_info as *const _ as usize }, - 9828usize, + 14960usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2379,7 +2084,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).update_count as *const _ as usize }, - 10148usize, + 15280usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2391,7 +2096,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).num_active_streams as *const _ as usize }, - 10152usize, + 15284usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2404,7 +2109,7 @@ fn bindgen_test_layout_cras_server_state() { &(*(::std::ptr::null::<cras_server_state>())).last_active_stream_time as *const _ as usize }, - 10168usize, + 15300usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2416,7 +2121,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).audio_debug_info as *const _ as usize }, - 10184usize, + 15316usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2429,7 +2134,7 @@ fn bindgen_test_layout_cras_server_state() { &(*(::std::ptr::null::<cras_server_state>())).default_output_buffer_size as *const _ as usize }, - 134448usize, + 139536usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2441,7 +2146,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).non_empty_status as *const _ as usize }, - 134452usize, + 139540usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2451,7 +2156,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).aec_supported as *const _ as usize }, - 134456usize, + 139544usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2461,7 +2166,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).aec_group_id as *const _ as usize }, - 134460usize, + 139548usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2473,7 +2178,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).snapshot_buffer as *const _ as usize }, - 134464usize, + 139552usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2483,7 +2188,7 @@ fn bindgen_test_layout_cras_server_state() { ); assert_eq!( unsafe { &(*(::std::ptr::null::<cras_server_state>())).bt_debug_info as *const _ as usize }, - 1377308usize, + 1381956usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2495,7 +2200,7 @@ fn bindgen_test_layout_cras_server_state() { unsafe { &(*(::std::ptr::null::<cras_server_state>())).bt_wbs_enabled as *const _ as usize }, - 1393796usize, + 1398348usize, concat!( "Offset of field: ", stringify!(cras_server_state), @@ -2503,71 +2208,6 @@ fn bindgen_test_layout_cras_server_state() { stringify!(bt_wbs_enabled) ) ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_server_state>())).deprioritize_bt_wbs_mic as *const _ - as usize - }, - 1393800usize, - concat!( - "Offset of field: ", - stringify!(cras_server_state), - "::", - stringify!(deprioritize_bt_wbs_mic) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_server_state>())).main_thread_debug_info as *const _ - as usize - }, - 1393804usize, - concat!( - "Offset of field: ", - stringify!(cras_server_state), - "::", - stringify!(main_thread_debug_info) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_server_state>())).num_input_streams_with_permission - as *const _ as usize - }, - 1414292usize, - concat!( - "Offset of field: ", - stringify!(cras_server_state), - "::", - stringify!(num_input_streams_with_permission) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_server_state>())).noise_cancellation_enabled as *const _ - as usize - }, - 1414336usize, - concat!( - "Offset of field: ", - stringify!(cras_server_state), - "::", - stringify!(noise_cancellation_enabled) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_server_state>())).hotword_pause_at_suspend as *const _ - as usize - }, - 1414340usize, - concat!( - "Offset of field: ", - stringify!(cras_server_state), - "::", - stringify!(hotword_pause_at_suspend) - ) - ); } pub const cras_notify_device_action_CRAS_DEVICE_ACTION_ADD: cras_notify_device_action = 0; pub const cras_notify_device_action_CRAS_DEVICE_ACTION_REMOVE: cras_notify_device_action = 1; @@ -2683,14 +2323,9 @@ pub enum CRAS_NODE_TYPE { CRAS_NODE_TYPE_HOTWORD = 6, CRAS_NODE_TYPE_POST_MIX_PRE_DSP = 7, CRAS_NODE_TYPE_POST_DSP = 8, - CRAS_NODE_TYPE_BLUETOOTH_NB_MIC = 9, - CRAS_NODE_TYPE_USB = 10, - CRAS_NODE_TYPE_BLUETOOTH = 11, - CRAS_NODE_TYPE_FALLBACK_NORMAL = 12, - CRAS_NODE_TYPE_FALLBACK_ABNORMAL = 13, - CRAS_NODE_TYPE_UNKNOWN = 14, - CRAS_NODE_TYPE_ECHO_REFERENCE = 15, - CRAS_NODE_TYPE_ALSA_LOOPBACK = 16, + CRAS_NODE_TYPE_USB = 9, + CRAS_NODE_TYPE_BLUETOOTH = 10, + CRAS_NODE_TYPE_UNKNOWN = 11, } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -2734,8 +2369,6 @@ pub enum CRAS_SERVER_MESSAGE_ID { CRAS_SERVER_RELOAD_AEC_CONFIG = 27, CRAS_SERVER_DUMP_BT = 28, CRAS_SERVER_SET_BT_WBS_ENABLED = 29, - CRAS_SERVER_GET_ATLOG_FD = 30, - CRAS_SERVER_DUMP_MAIN = 31, } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -2754,7 +2387,6 @@ pub enum CRAS_CLIENT_MESSAGE_ID { CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED = 11, CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED = 12, CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED = 13, - CRAS_CLIENT_ATLOG_FD_READY = 14, } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] @@ -2849,14 +2481,13 @@ pub struct cras_connect_message { pub dev_idx: u32, pub effects: u64, pub client_type: CRAS_CLIENT_TYPE, - pub client_shm_size: u64, - pub buffer_offsets: [u64; 2usize], + pub client_shm_size: u32, } #[test] fn bindgen_test_layout_cras_connect_message() { assert_eq!( ::std::mem::size_of::<cras_connect_message>(), - 99usize, + 79usize, concat!("Size of: ", stringify!(cras_connect_message)) ); assert_eq!( @@ -3006,16 +2637,158 @@ fn bindgen_test_layout_cras_connect_message() { stringify!(client_shm_size) ) ); +} +#[repr(C, packed)] +#[derive(Debug, Copy, Clone)] +pub struct cras_connect_message_old { + pub header: cras_server_message, + pub proto_version: u32, + pub direction: CRAS_STREAM_DIRECTION, + pub stream_id: cras_stream_id_t, + pub stream_type: CRAS_STREAM_TYPE, + pub buffer_frames: u32, + pub cb_threshold: u32, + pub flags: u32, + pub format: cras_audio_format_packed, + pub dev_idx: u32, + pub effects: u64, +} +#[test] +fn bindgen_test_layout_cras_connect_message_old() { + assert_eq!( + ::std::mem::size_of::<cras_connect_message_old>(), + 71usize, + concat!("Size of: ", stringify!(cras_connect_message_old)) + ); + assert_eq!( + ::std::mem::align_of::<cras_connect_message_old>(), + 1usize, + concat!("Alignment of ", stringify!(cras_connect_message_old)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<cras_connect_message_old>())).header as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(header) + ) + ); assert_eq!( unsafe { - &(*(::std::ptr::null::<cras_connect_message>())).buffer_offsets as *const _ as usize + &(*(::std::ptr::null::<cras_connect_message_old>())).proto_version as *const _ as usize }, - 83usize, + 8usize, concat!( "Offset of field: ", - stringify!(cras_connect_message), + stringify!(cras_connect_message_old), + "::", + stringify!(proto_version) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).direction as *const _ as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(direction) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).stream_id as *const _ as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(stream_id) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).stream_type as *const _ as usize + }, + 20usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(stream_type) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).buffer_frames as *const _ as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(buffer_frames) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).cb_threshold as *const _ as usize + }, + 28usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(cb_threshold) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<cras_connect_message_old>())).flags as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(flags) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<cras_connect_message_old>())).format as *const _ as usize }, + 36usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), "::", - stringify!(buffer_offsets) + stringify!(format) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).dev_idx as *const _ as usize + }, + 59usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(dev_idx) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_connect_message_old>())).effects as *const _ as usize + }, + 63usize, + concat!( + "Offset of field: ", + stringify!(cras_connect_message_old), + "::", + stringify!(effects) ) ); } @@ -3161,6 +2934,49 @@ fn bindgen_test_layout_cras_set_system_volume() { } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] +pub struct cras_set_system_capture_gain { + pub header: cras_server_message, + pub gain: i32, +} +#[test] +fn bindgen_test_layout_cras_set_system_capture_gain() { + assert_eq!( + ::std::mem::size_of::<cras_set_system_capture_gain>(), + 12usize, + concat!("Size of: ", stringify!(cras_set_system_capture_gain)) + ); + assert_eq!( + ::std::mem::align_of::<cras_set_system_capture_gain>(), + 1usize, + concat!("Alignment of ", stringify!(cras_set_system_capture_gain)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_set_system_capture_gain>())).header as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(cras_set_system_capture_gain), + "::", + stringify!(header) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<cras_set_system_capture_gain>())).gain as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(cras_set_system_capture_gain), + "::", + stringify!(gain) + ) + ); +} +#[repr(C, packed)] +#[derive(Debug, Copy, Clone)] pub struct cras_set_system_mute { pub header: cras_server_message, pub mute: i32, @@ -3495,62 +3311,6 @@ fn bindgen_test_layout_cras_dump_audio_thread() { } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] -pub struct cras_get_atlog_fd { - pub header: cras_server_message, -} -#[test] -fn bindgen_test_layout_cras_get_atlog_fd() { - assert_eq!( - ::std::mem::size_of::<cras_get_atlog_fd>(), - 8usize, - concat!("Size of: ", stringify!(cras_get_atlog_fd)) - ); - assert_eq!( - ::std::mem::align_of::<cras_get_atlog_fd>(), - 1usize, - concat!("Alignment of ", stringify!(cras_get_atlog_fd)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_get_atlog_fd>())).header as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cras_get_atlog_fd), - "::", - stringify!(header) - ) - ); -} -#[repr(C, packed)] -#[derive(Debug, Copy, Clone)] -pub struct cras_dump_main { - pub header: cras_server_message, -} -#[test] -fn bindgen_test_layout_cras_dump_main() { - assert_eq!( - ::std::mem::size_of::<cras_dump_main>(), - 8usize, - concat!("Size of: ", stringify!(cras_dump_main)) - ); - assert_eq!( - ::std::mem::align_of::<cras_dump_main>(), - 1usize, - concat!("Alignment of ", stringify!(cras_dump_main)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<cras_dump_main>())).header as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cras_dump_main), - "::", - stringify!(header) - ) - ); -} -#[repr(C, packed)] -#[derive(Debug, Copy, Clone)] pub struct cras_dump_bt { pub header: cras_server_message, } @@ -3717,17 +3477,17 @@ fn bindgen_test_layout_cras_test_dev_command() { ); } #[repr(C, packed)] -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub struct cras_config_global_remix { pub header: cras_server_message, pub num_channels: ::std::os::raw::c_uint, - pub coefficient: [f32; 64usize], + pub coefficient: [f32; 32usize], } #[test] fn bindgen_test_layout_cras_config_global_remix() { assert_eq!( ::std::mem::size_of::<cras_config_global_remix>(), - 268usize, + 140usize, concat!("Size of: ", stringify!(cras_config_global_remix)) ); assert_eq!( @@ -4169,7 +3929,7 @@ fn bindgen_test_layout_cras_client_stream_connected() { ) ); } -#[repr(C, packed)] +#[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cras_client_audio_debug_info_ready { pub header: cras_client_message, @@ -4203,37 +3963,7 @@ fn bindgen_test_layout_cras_client_audio_debug_info_ready() { ) ); } -#[repr(C, packed)] -#[derive(Debug, Copy, Clone)] -pub struct cras_client_atlog_fd_ready { - pub header: cras_client_message, -} -#[test] -fn bindgen_test_layout_cras_client_atlog_fd_ready() { - assert_eq!( - ::std::mem::size_of::<cras_client_atlog_fd_ready>(), - 8usize, - concat!("Size of: ", stringify!(cras_client_atlog_fd_ready)) - ); - assert_eq!( - ::std::mem::align_of::<cras_client_atlog_fd_ready>(), - 1usize, - concat!("Alignment of ", stringify!(cras_client_atlog_fd_ready)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<cras_client_atlog_fd_ready>())).header as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(cras_client_atlog_fd_ready), - "::", - stringify!(header) - ) - ); -} -#[repr(C, packed)] +#[repr(C)] #[derive(Copy, Clone)] pub struct cras_client_get_hotword_models_ready { pub header: cras_client_message, @@ -4252,7 +3982,7 @@ fn bindgen_test_layout_cras_client_get_hotword_models_ready() { ); assert_eq!( ::std::mem::align_of::<cras_client_get_hotword_models_ready>(), - 1usize, + 4usize, concat!( "Alignment of ", stringify!(cras_client_get_hotword_models_ready) @@ -4727,13 +4457,13 @@ pub struct cras_audio_shm_header { pub callback_pending: i32, pub num_overruns: u32, pub ts: cras_timespec, - pub buffer_offset: [u64; 2usize], + pub buffer_offset: [u32; 2usize], } #[test] fn bindgen_test_layout_cras_audio_shm_header() { assert_eq!( ::std::mem::size_of::<cras_audio_shm_header>(), - 88usize, + 80usize, concat!("Size of: ", stringify!(cras_audio_shm_header)) ); assert_eq!( diff --git a/cras/client/cras-sys/src/lib.rs b/cras/client/cras-sys/src/lib.rs index 2b3d21e0..4056162f 100644 --- a/cras/client/cras-sys/src/lib.rs +++ b/cras/client/cras-sys/src/lib.rs @@ -1,168 +1,49 @@ // Copyright 2019 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -extern crate audio_streams; extern crate data_model; -use std::cmp::min; -use std::convert::{TryFrom, TryInto}; -use std::error; -use std::fmt; -use std::iter::FromIterator; -use std::os::raw::c_char; -use std::str::FromStr; -use std::time::Duration; - #[allow(dead_code)] #[allow(non_upper_case_globals)] #[allow(non_camel_case_types)] #[allow(non_snake_case)] pub mod gen; use gen::{ - _snd_pcm_format, audio_dev_debug_info, audio_message, audio_stream_debug_info, - cras_audio_format_packed, cras_iodev_info, cras_ionode_info, cras_ionode_info__bindgen_ty_1, - cras_timespec, snd_pcm_format_t, CRAS_AUDIO_MESSAGE_ID, CRAS_CHANNEL, CRAS_CLIENT_TYPE, - CRAS_NODE_TYPE, CRAS_STREAM_DIRECTION, CRAS_STREAM_EFFECT, CRAS_STREAM_TYPE, + _snd_pcm_format, audio_message, cras_audio_format_packed, CRAS_AUDIO_MESSAGE_ID, CRAS_CHANNEL, }; -use audio_streams::{SampleFormat, StreamDirection, StreamEffect}; - unsafe impl data_model::DataInit for gen::audio_message {} -unsafe impl data_model::DataInit for gen::audio_debug_info {} -unsafe impl data_model::DataInit for gen::audio_dev_debug_info {} -unsafe impl data_model::DataInit for gen::audio_stream_debug_info {} unsafe impl data_model::DataInit for gen::cras_client_connected {} unsafe impl data_model::DataInit for gen::cras_client_stream_connected {} unsafe impl data_model::DataInit for gen::cras_connect_message {} unsafe impl data_model::DataInit for gen::cras_disconnect_stream_message {} -unsafe impl data_model::DataInit for gen::cras_dump_audio_thread {} -unsafe impl data_model::DataInit for gen::cras_iodev_info {} -unsafe impl data_model::DataInit for gen::cras_ionode_info {} unsafe impl data_model::DataInit for gen::cras_server_state {} -unsafe impl data_model::DataInit for gen::cras_set_system_mute {} -unsafe impl data_model::DataInit for gen::cras_set_system_volume {} - -/// An enumeration of errors that can occur when converting the packed C -/// structs into Rust-style structs. -#[derive(Debug)] -pub enum Error { - InvalidChannel(i8), - InvalidClientType(u32), - InvalidClientTypeStr, - InvalidStreamType(u32), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - InvalidChannel(c) => write!( - f, - "Channel value {} is not within valid range [0, {})", - c, - CRAS_CHANNEL::CRAS_CH_MAX as u32 - ), - InvalidClientType(t) => write!( - f, - "Client type {} is not within valid range [0, {})", - t, - CRAS_CLIENT_TYPE::CRAS_CLIENT_TYPE_SERVER_STREAM as u32 + 1 - ), - InvalidClientTypeStr => write!(f, "Invalid client type string"), - InvalidStreamType(t) => write!( - f, - "Stream type {} is not within valid range [0, {})", - t, - CRAS_STREAM_TYPE::CRAS_STREAM_NUM_TYPES as u32 - ), - } - } -} impl cras_audio_format_packed { /// Initializes `cras_audio_format_packed` from input parameters. - /// Field `channel_layout` will be assigned with default channel layout defined in - /// `Self::default_channel_layout`. /// /// # Arguments /// * `format` - Format in used. /// * `rate` - Rate in used. /// * `num_channels` - Number of channels in used. - /// * `direction` - Stream direction enumeration. /// /// # Returns /// Structure `cras_audio_format_packed` - pub fn new( - format: _snd_pcm_format, - rate: u32, - num_channels: usize, - direction: CRAS_STREAM_DIRECTION, - ) -> Self { - Self { + pub fn new(format: _snd_pcm_format, rate: usize, num_channels: usize) -> Self { + let mut audio_format = Self { format: format as i32, - frame_rate: rate, + frame_rate: rate as u32, num_channels: num_channels as u32, - channel_layout: Self::default_channel_layout(num_channels, direction), - } - } - - /// Generates default channel layout by given number of channels and stream direction. - /// ``` - /// use cras_sys::gen::{ - /// _snd_pcm_format, - /// cras_audio_format_packed, - /// CRAS_STREAM_DIRECTION::* - /// }; - /// let test_one = | num_channels, direction, expected_results | { - /// let default_channel_fmt = cras_audio_format_packed::new( - /// _snd_pcm_format::SND_PCM_FORMAT_S16, - /// 48000, - /// num_channels, - /// direction - /// ); - /// assert_eq!(default_channel_fmt.channel_layout, expected_results); - /// }; - /// test_one(2, CRAS_STREAM_OUTPUT, [0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1]); - /// test_one(4, CRAS_STREAM_OUTPUT, [0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1]); - /// test_one(6, CRAS_STREAM_OUTPUT, [0, 1, 4, 5, 2, 3, -1, -1, -1, -1, -1]); - /// test_one(2, CRAS_STREAM_INPUT, [0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1]); - /// test_one(4, CRAS_STREAM_INPUT, [0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1]); - /// test_one(6, CRAS_STREAM_INPUT, [0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1]); - /// ``` - fn default_channel_layout( - num_channels: usize, - direction: CRAS_STREAM_DIRECTION, - ) -> [i8; CRAS_CHANNEL::CRAS_CH_MAX as usize] { - use {CRAS_CHANNEL::*, CRAS_STREAM_DIRECTION::*}; - - let mut channel_layout = [-1; CRAS_CH_MAX as usize]; - match (num_channels, direction) { - (6, CRAS_STREAM_OUTPUT) => { - [ - CRAS_CH_FL, - CRAS_CH_FR, - CRAS_CH_FC, - CRAS_CH_LFE, - CRAS_CH_RL, - CRAS_CH_RR, - ] - .iter() - .enumerate() - .for_each(|(idx, &channel)| channel_layout[channel as usize] = idx as i8); - } - _ => { - for (i, channel) in channel_layout - .iter_mut() - .enumerate() - .take(min(num_channels, CRAS_CH_MAX as usize)) - { - *channel = i as i8; - } + channel_layout: [-1; CRAS_CHANNEL::CRAS_CH_MAX as usize], + }; + for i in 0..CRAS_CHANNEL::CRAS_CH_MAX as usize { + if i < num_channels { + audio_format.channel_layout[i] = i as i8; + } else { + break; } } - channel_layout + audio_format } } @@ -175,483 +56,3 @@ impl Default for audio_message { } } } - -impl Default for cras_iodev_info { - fn default() -> Self { - Self { - idx: 0, - name: [0; 64usize], - stable_id: 0, - max_supported_channels: 0, - } - } -} - -#[derive(Debug)] -pub struct CrasIodevInfo { - pub index: u32, - pub name: String, -} - -fn cstring_to_string(cstring: &[c_char]) -> String { - let null_idx = match cstring.iter().enumerate().find(|(_, &c)| c == 0) { - Some((i, _)) => i, - None => return "".to_owned(), - }; - - let ptr = cstring.as_ptr() as *const u8; - let slice = unsafe { core::slice::from_raw_parts(ptr, null_idx) }; - String::from_utf8_lossy(slice).to_string() -} - -impl From<cras_iodev_info> for CrasIodevInfo { - fn from(info: cras_iodev_info) -> Self { - Self { - index: info.idx, - name: cstring_to_string(&info.name), - } - } -} - -impl Default for cras_ionode_info { - fn default() -> Self { - Self { - iodev_idx: 0, - ionode_idx: 0, - plugged: 0, - active: 0, - plugged_time: cras_ionode_info__bindgen_ty_1 { - tv_sec: 0, - tv_usec: 0, - }, - volume: 0, - ui_gain_scaler: 0.0, - capture_gain: 0, - left_right_swapped: 0, - type_enum: 0, - stable_id: 0, - type_: [0; 32usize], - name: [0; 64usize], - active_hotword_model: [0; 16usize], - } - } -} - -impl From<u32> for CRAS_NODE_TYPE { - fn from(node_type: u32) -> CRAS_NODE_TYPE { - use CRAS_NODE_TYPE::*; - match node_type { - 0 => CRAS_NODE_TYPE_INTERNAL_SPEAKER, - 1 => CRAS_NODE_TYPE_HEADPHONE, - 2 => CRAS_NODE_TYPE_HDMI, - 3 => CRAS_NODE_TYPE_HAPTIC, - 4 => CRAS_NODE_TYPE_LINEOUT, - 5 => CRAS_NODE_TYPE_MIC, - 6 => CRAS_NODE_TYPE_HOTWORD, - 7 => CRAS_NODE_TYPE_POST_MIX_PRE_DSP, - 8 => CRAS_NODE_TYPE_POST_DSP, - 9 => CRAS_NODE_TYPE_USB, - 10 => CRAS_NODE_TYPE_BLUETOOTH, - _ => CRAS_NODE_TYPE_UNKNOWN, - } - } -} - -#[derive(Debug)] -pub struct CrasIonodeInfo { - pub name: String, - pub iodev_index: u32, - pub ionode_index: u32, - pub stable_id: u32, - pub plugged: bool, - pub active: bool, - pub node_type: CRAS_NODE_TYPE, - pub type_name: String, - pub volume: u32, - pub capture_gain: i32, - pub plugged_time: cras_timespec, -} - -impl From<cras_ionode_info> for CrasIonodeInfo { - fn from(info: cras_ionode_info) -> Self { - Self { - name: cstring_to_string(&info.name), - iodev_index: info.iodev_idx, - ionode_index: info.ionode_idx, - stable_id: info.stable_id, - plugged: info.plugged != 0, - active: info.active != 0, - node_type: CRAS_NODE_TYPE::from(info.type_enum), - type_name: cstring_to_string(&info.type_), - volume: info.volume, - capture_gain: info.capture_gain, - plugged_time: cras_timespec { - tv_sec: info.plugged_time.tv_sec, - tv_nsec: info.plugged_time.tv_usec * 1000, - }, - } - } -} - -impl From<u32> for CRAS_STREAM_DIRECTION { - fn from(node_type: u32) -> CRAS_STREAM_DIRECTION { - use CRAS_STREAM_DIRECTION::*; - match node_type { - 0 => CRAS_STREAM_OUTPUT, - 1 => CRAS_STREAM_INPUT, - 2 => CRAS_STREAM_UNDEFINED, - 3 => CRAS_STREAM_POST_MIX_PRE_DSP, - _ => CRAS_STREAM_UNDEFINED, - } - } -} - -impl Default for audio_dev_debug_info { - fn default() -> Self { - Self { - dev_name: [0; 64], - buffer_size: 0, - min_buffer_level: 0, - min_cb_level: 0, - max_cb_level: 0, - frame_rate: 0, - num_channels: 0, - est_rate_ratio: 0.0, - direction: 0, - num_underruns: 0, - num_severe_underruns: 0, - highest_hw_level: 0, - runtime_sec: 0, - runtime_nsec: 0, - longest_wake_sec: 0, - longest_wake_nsec: 0, - software_gain_scaler: 0.0, - } - } -} - -/// A rust-style representation of the server's packed audio_dev_debug_info -/// struct. -#[derive(Debug)] -pub struct AudioDevDebugInfo { - pub dev_name: String, - pub buffer_size: u32, - pub min_buffer_level: u32, - pub min_cb_level: u32, - pub max_cb_level: u32, - pub frame_rate: u32, - pub num_channels: u32, - pub est_rate_ratio: f64, - pub direction: CRAS_STREAM_DIRECTION, - pub num_underruns: u32, - pub num_severe_underruns: u32, - pub highest_hw_level: u32, - pub runtime: Duration, - pub longest_wake: Duration, - pub software_gain_scaler: f64, -} - -impl From<audio_dev_debug_info> for AudioDevDebugInfo { - fn from(info: audio_dev_debug_info) -> Self { - Self { - dev_name: cstring_to_string(&info.dev_name), - buffer_size: info.buffer_size, - min_buffer_level: info.min_buffer_level, - min_cb_level: info.min_cb_level, - max_cb_level: info.max_cb_level, - frame_rate: info.frame_rate, - num_channels: info.num_channels, - est_rate_ratio: info.est_rate_ratio, - direction: CRAS_STREAM_DIRECTION::from(u32::from(info.direction)), - num_underruns: info.num_underruns, - num_severe_underruns: info.num_severe_underruns, - highest_hw_level: info.highest_hw_level, - runtime: Duration::new(info.runtime_sec.into(), info.runtime_nsec), - longest_wake: Duration::new(info.longest_wake_sec.into(), info.longest_wake_nsec), - software_gain_scaler: info.software_gain_scaler, - } - } -} - -impl fmt::Display for AudioDevDebugInfo { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "Device: {}", self.dev_name)?; - writeln!(f, " Direction: {:?}", self.direction)?; - writeln!(f, " Buffer size: {}", self.buffer_size)?; - writeln!(f, " Minimum buffer level: {}", self.min_buffer_level)?; - writeln!(f, " Minimum callback level: {}", self.min_cb_level)?; - writeln!(f, " Max callback level: {}", self.max_cb_level)?; - writeln!(f, " Frame rate: {}", self.frame_rate)?; - writeln!(f, " Number of channels: {}", self.num_channels)?; - writeln!(f, " Estimated rate ratio: {:.2}", self.est_rate_ratio)?; - writeln!(f, " Underrun count: {}", self.num_underruns)?; - writeln!(f, " Severe underrun count: {}", self.num_severe_underruns)?; - writeln!(f, " Highest hardware level: {}", self.highest_hw_level)?; - writeln!(f, " Runtime: {:?}", self.runtime)?; - writeln!(f, " Longest wake: {:?}", self.longest_wake)?; - writeln!(f, " Software gain scaler: {}", self.software_gain_scaler)?; - Ok(()) - } -} - -impl TryFrom<u32> for CRAS_STREAM_TYPE { - type Error = Error; - fn try_from(stream_type: u32) -> Result<Self, Self::Error> { - use CRAS_STREAM_TYPE::*; - match stream_type { - 0 => Ok(CRAS_STREAM_TYPE_DEFAULT), - 1 => Ok(CRAS_STREAM_TYPE_MULTIMEDIA), - 2 => Ok(CRAS_STREAM_TYPE_VOICE_COMMUNICATION), - 3 => Ok(CRAS_STREAM_TYPE_SPEECH_RECOGNITION), - 4 => Ok(CRAS_STREAM_TYPE_PRO_AUDIO), - 5 => Ok(CRAS_STREAM_TYPE_ACCESSIBILITY), - _ => Err(Error::InvalidStreamType(stream_type)), - } - } -} - -impl TryFrom<u32> for CRAS_CLIENT_TYPE { - type Error = Error; - fn try_from(client_type: u32) -> Result<Self, Self::Error> { - use CRAS_CLIENT_TYPE::*; - match client_type { - 0 => Ok(CRAS_CLIENT_TYPE_UNKNOWN), - 1 => Ok(CRAS_CLIENT_TYPE_LEGACY), - 2 => Ok(CRAS_CLIENT_TYPE_TEST), - 3 => Ok(CRAS_CLIENT_TYPE_PCM), - 4 => Ok(CRAS_CLIENT_TYPE_CHROME), - 5 => Ok(CRAS_CLIENT_TYPE_ARC), - 6 => Ok(CRAS_CLIENT_TYPE_CROSVM), - 7 => Ok(CRAS_CLIENT_TYPE_SERVER_STREAM), - 8 => Ok(CRAS_CLIENT_TYPE_LACROS), - _ => Err(Error::InvalidClientType(client_type)), - } - } -} - -impl FromStr for CRAS_CLIENT_TYPE { - type Err = Error; - fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { - use CRAS_CLIENT_TYPE::*; - match s { - "crosvm" => Ok(CRAS_CLIENT_TYPE_CROSVM), - "arcvm" => Ok(CRAS_CLIENT_TYPE_ARCVM), - _ => Err(Error::InvalidClientTypeStr), - } - } -} - -impl Default for audio_stream_debug_info { - fn default() -> Self { - Self { - stream_id: 0, - dev_idx: 0, - direction: 0, - stream_type: 0, - client_type: 0, - buffer_frames: 0, - cb_threshold: 0, - effects: 0, - flags: 0, - frame_rate: 0, - num_channels: 0, - longest_fetch_sec: 0, - longest_fetch_nsec: 0, - num_missed_cb: 0, - num_overruns: 0, - is_pinned: 0, - pinned_dev_idx: 0, - runtime_sec: 0, - runtime_nsec: 0, - stream_volume: 0.0, - channel_layout: [0; 11], - } - } -} - -impl TryFrom<i8> for CRAS_CHANNEL { - type Error = Error; - fn try_from(channel: i8) -> Result<Self, Self::Error> { - use CRAS_CHANNEL::*; - match channel { - 0 => Ok(CRAS_CH_FL), - 1 => Ok(CRAS_CH_FR), - 2 => Ok(CRAS_CH_RL), - 3 => Ok(CRAS_CH_RR), - 4 => Ok(CRAS_CH_FC), - 5 => Ok(CRAS_CH_LFE), - 6 => Ok(CRAS_CH_SL), - 7 => Ok(CRAS_CH_SR), - 8 => Ok(CRAS_CH_RC), - 9 => Ok(CRAS_CH_FLC), - 10 => Ok(CRAS_CH_FRC), - _ => Err(Error::InvalidChannel(channel)), - } - } -} - -/// A rust-style representation of the server's packed audio_stream_debug_info -/// struct. -#[derive(Debug)] -pub struct AudioStreamDebugInfo { - pub stream_id: u64, - pub dev_idx: u32, - pub direction: CRAS_STREAM_DIRECTION, - pub stream_type: CRAS_STREAM_TYPE, - pub client_type: CRAS_CLIENT_TYPE, - pub buffer_frames: u32, - pub cb_threshold: u32, - pub effects: u64, - pub flags: u32, - pub frame_rate: u32, - pub num_channels: u32, - pub longest_fetch: Duration, - pub num_missed_cb: u32, - pub num_overruns: u32, - pub is_pinned: bool, - pub pinned_dev_idx: u32, - pub runtime: Duration, - pub stream_volume: f64, - pub channel_layout: Vec<CRAS_CHANNEL>, -} - -impl TryFrom<audio_stream_debug_info> for AudioStreamDebugInfo { - type Error = Error; - fn try_from(info: audio_stream_debug_info) -> Result<Self, Self::Error> { - let channel_layout = info - .channel_layout - .iter() - .cloned() - .take_while(|&c| c != -1) - .map(TryInto::try_into) - .collect::<Result<Vec<_>, _>>()?; - Ok(Self { - stream_id: info.stream_id, - dev_idx: info.dev_idx, - direction: info.direction.into(), - stream_type: info.stream_type.try_into()?, - client_type: info.client_type.try_into()?, - buffer_frames: info.buffer_frames, - cb_threshold: info.cb_threshold, - effects: info.effects, - flags: info.flags, - frame_rate: info.frame_rate, - num_channels: info.num_channels, - longest_fetch: Duration::new(info.longest_fetch_sec.into(), info.longest_fetch_nsec), - num_missed_cb: info.num_missed_cb, - num_overruns: info.num_overruns, - is_pinned: info.is_pinned != 0, - pinned_dev_idx: info.pinned_dev_idx, - runtime: Duration::new(info.runtime_sec.into(), info.runtime_nsec), - stream_volume: info.stream_volume, - channel_layout, - }) - } -} - -impl fmt::Display for AudioStreamDebugInfo { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!( - f, - "Stream: {}, Device index: {}", - self.stream_id, self.dev_idx - )?; - writeln!(f, " Direction: {:?}", self.direction)?; - writeln!(f, " Stream type: {:?}", self.stream_type)?; - writeln!(f, " Client type: {:?}", self.client_type)?; - writeln!(f, " Buffer frames: {}", self.buffer_frames)?; - writeln!(f, " Callback threshold: {}", self.cb_threshold)?; - writeln!(f, " Effects: {:#x}", self.effects)?; - writeln!(f, " Frame rate: {}", self.frame_rate)?; - writeln!(f, " Number of channels: {}", self.num_channels)?; - writeln!(f, " Longest fetch: {:?}", self.longest_fetch)?; - writeln!(f, " Overrun count: {}", self.num_overruns)?; - writeln!(f, " Pinned: {}", self.is_pinned)?; - writeln!(f, " Pinned device index: {}", self.pinned_dev_idx)?; - writeln!(f, " Missed callbacks: {}", self.num_missed_cb)?; - match self.direction { - CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT => { - writeln!(f, " Volume: {:.2}", self.stream_volume)? - } - CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT => { - writeln!(f, " Gain: {:.2}", self.stream_volume)? - } - _ => (), - }; - writeln!(f, " Runtime: {:?}", self.runtime)?; - write!(f, " Channel map:")?; - for channel in &self.channel_layout { - write!(f, " {:?}", channel)?; - } - writeln!(f)?; - Ok(()) - } -} - -/// A rust-style representation of the server's audio debug info. -pub struct AudioDebugInfo { - pub devices: Vec<AudioDevDebugInfo>, - pub streams: Vec<AudioStreamDebugInfo>, -} - -impl AudioDebugInfo { - pub fn new(devices: Vec<AudioDevDebugInfo>, streams: Vec<AudioStreamDebugInfo>) -> Self { - Self { devices, streams } - } -} - -impl Into<u64> for CRAS_STREAM_EFFECT { - fn into(self) -> u64 { - u64::from(self.0) - } -} - -impl CRAS_STREAM_EFFECT { - pub fn empty() -> Self { - CRAS_STREAM_EFFECT(0) - } -} - -impl From<StreamDirection> for CRAS_STREAM_DIRECTION { - /// Convert an audio_streams StreamDirection into the corresponding CRAS_STREAM_DIRECTION. - fn from(direction: StreamDirection) -> Self { - match direction { - StreamDirection::Playback => CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT, - StreamDirection::Capture => CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT, - } - } -} - -impl From<StreamEffect> for CRAS_STREAM_EFFECT { - /// Convert an audio_streams StreamEffect into the corresponding CRAS_STREAM_EFFECT. - fn from(effect: StreamEffect) -> Self { - match effect { - StreamEffect::NoEffect => CRAS_STREAM_EFFECT::empty(), - StreamEffect::EchoCancellation => CRAS_STREAM_EFFECT::APM_ECHO_CANCELLATION, - } - } -} - -impl<'a> FromIterator<&'a StreamEffect> for CRAS_STREAM_EFFECT { - fn from_iter<I>(iter: I) -> Self - where - I: IntoIterator<Item = &'a StreamEffect>, - { - iter.into_iter().fold( - CRAS_STREAM_EFFECT::empty(), - |cras_effect, &stream_effect| cras_effect | stream_effect.into(), - ) - } -} - -/// Convert an audio_streams SampleFormat into the corresponding pcm_format. -impl From<SampleFormat> for snd_pcm_format_t { - fn from(format: SampleFormat) -> Self { - match format { - SampleFormat::U8 => snd_pcm_format_t::SND_PCM_FORMAT_U8, - SampleFormat::S16LE => snd_pcm_format_t::SND_PCM_FORMAT_S16_LE, - SampleFormat::S24LE => snd_pcm_format_t::SND_PCM_FORMAT_S24_LE, - SampleFormat::S32LE => snd_pcm_format_t::SND_PCM_FORMAT_S32_LE, - } - } -} diff --git a/cras/client/cras_tests/Cargo.toml b/cras/client/cras_tests/Cargo.toml index 108fe6c4..94453ddf 100644 --- a/cras/client/cras_tests/Cargo.toml +++ b/cras/client/cras_tests/Cargo.toml @@ -7,11 +7,5 @@ edition = "2018" [dependencies] audio_streams = { path = "../../../audio_streams" } # provided by ebuild getopts = "0.2.18" -hound = "3.4.0" libcras = { path = "../libcras" } # provided by ebuild -sys_util = { path = "../../../../crosvm/sys_util" } # provided by ebuild - -[profile.release] -lto = true -panic = 'abort' -overflow-checks = true +sys_util = { path = "../../../../../platform/crosvm/sys_util" } # provided by ebuild diff --git a/cras/client/cras_tests/src/arguments.rs b/cras/client/cras_tests/src/arguments.rs deleted file mode 100644 index 59e9ec26..00000000 --- a/cras/client/cras_tests/src/arguments.rs +++ /dev/null @@ -1,462 +0,0 @@ -// Copyright 2019 The Chromium OS 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 std::error; -use std::fmt; -use std::path::PathBuf; - -use audio_streams::SampleFormat; -use getopts::{self, Matches, Options}; - -#[derive(Debug)] -pub enum Error { - GetOpts(getopts::Fail), - InvalidArgument(String, String, String), - InvalidFiletype(String), - MissingArgument(String), - MissingCommand, - MissingFilename, - UnknownCommand(String), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - GetOpts(e) => write!(f, "Getopts Error: {}", e), - InvalidArgument(flag, value, error_msg) => { - write!(f, "Invalid {} argument '{}': {}", flag, value, error_msg) - } - InvalidFiletype(extension) => write!( - f, - "Invalid file extension '{}'. Supported types are 'wav' and 'raw'", - extension - ), - MissingArgument(subcommand) => write!(f, "Missing argument for {}", subcommand), - MissingCommand => write!(f, "A command must be provided"), - MissingFilename => write!(f, "A file name must be provided"), - UnknownCommand(s) => write!(f, "Unknown command '{}'", s), - } - } -} - -type Result<T> = std::result::Result<T, Error>; - -/// The different types of commands that can be given to cras_tests. -/// Any options for those commands are passed as parameters to the enum values. -#[derive(Debug, PartialEq)] -pub enum Command { - Capture(AudioOptions), - Playback(AudioOptions), - Control(ControlCommand), -} - -impl Command { - pub fn parse<T: AsRef<str>>(args: &[T]) -> Result<Option<Self>> { - let program_name = args.get(0).map(|s| s.as_ref()).unwrap_or("cras_tests"); - let remaining_args = args.get(2..).unwrap_or(&[]); - match args.get(1).map(|s| s.as_ref()) { - None => { - show_usage(program_name); - Err(Error::MissingCommand) - } - Some("help") => { - show_usage(program_name); - Ok(None) - } - Some("capture") => Ok( - AudioOptions::parse(program_name, "capture", remaining_args)?.map(Command::Capture), - ), - Some("playback") => Ok( - AudioOptions::parse(program_name, "playback", remaining_args)? - .map(Command::Playback), - ), - Some("control") => { - Ok(ControlCommand::parse(program_name, remaining_args)?.map(Command::Control)) - } - Some(s) => { - show_usage(program_name); - Err(Error::UnknownCommand(s.to_string())) - } - } - } -} - -#[derive(Debug, PartialEq)] -pub enum FileType { - Raw, - Wav, -} - -impl fmt::Display for FileType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - FileType::Raw => write!(f, "raw data"), - FileType::Wav => write!(f, "WAVE"), - } - } -} - -fn show_usage(program_name: &str) { - eprintln!("Usage: {} [command] <command args>", program_name); - eprintln!("\nCommands:\n"); - eprintln!("capture - Capture to a file from CRAS"); - eprintln!("playback - Playback to CRAS from a file"); - eprintln!("control - Get and set server settings"); - eprintln!("\nhelp - Print help message"); -} - -fn show_audio_command_usage(program_name: &str, command: &str, opts: &Options) { - let brief = format!("Usage: {} {} [options] [filename]", program_name, command); - eprint!("{}", opts.usage(&brief)); -} - -/// The possible command line options that can be passed to the 'playback' and -/// 'capture' commands. Optional values will be `Some(_)` only if a value was -/// explicitly provided by the user. -/// -/// This struct will be passed to `playback()` and `capture()`. -#[derive(Debug, PartialEq)] -pub enum LoopbackType { - PreDsp, - PostDsp, -} - -#[derive(Debug, PartialEq)] -pub struct AudioOptions { - pub file_name: PathBuf, - pub loopback_type: Option<LoopbackType>, - pub file_type: FileType, - pub buffer_size: Option<usize>, - pub num_channels: Option<usize>, - pub format: Option<SampleFormat>, - pub frame_rate: Option<u32>, -} - -fn get_u32_param(matches: &Matches, option_name: &str) -> Result<Option<u32>> { - matches.opt_get::<u32>(option_name).map_err(|e| { - let argument = matches.opt_str(option_name).unwrap_or_default(); - Error::InvalidArgument(option_name.to_string(), argument, e.to_string()) - }) -} - -fn get_usize_param(matches: &Matches, option_name: &str) -> Result<Option<usize>> { - matches.opt_get::<usize>(option_name).map_err(|e| { - let argument = matches.opt_str(option_name).unwrap_or_default(); - Error::InvalidArgument(option_name.to_string(), argument, e.to_string()) - }) -} - -impl AudioOptions { - fn parse<T: AsRef<str>>( - program_name: &str, - command_name: &str, - args: &[T], - ) -> Result<Option<Self>> { - let mut opts = Options::new(); - opts.optopt("b", "buffer_size", "Buffer size in frames", "SIZE") - .optopt("c", "channels", "Number of channels", "NUM") - .optopt( - "f", - "format", - "Sample format (U8, S16_LE, S24_LE, or S32_LE)", - "FORMAT", - ) - .optopt("r", "rate", "Audio frame rate (Hz)", "RATE") - .optflag("h", "help", "Print help message"); - - if command_name == "capture" { - opts.optopt( - "", - "loopback", - "Capture from loopback device ('pre_dsp' or 'post_dsp')", - "DEVICE", - ); - } - - let args = args.iter().map(|s| s.as_ref()); - let matches = match opts.parse(args) { - Ok(m) => m, - Err(e) => { - show_audio_command_usage(program_name, command_name, &opts); - return Err(Error::GetOpts(e)); - } - }; - if matches.opt_present("h") { - show_audio_command_usage(program_name, command_name, &opts); - return Ok(None); - } - - let loopback_type = if matches.opt_defined("loopback") { - match matches.opt_str("loopback").as_deref() { - Some("pre_dsp") => Some(LoopbackType::PreDsp), - Some("post_dsp") => Some(LoopbackType::PostDsp), - Some(s) => { - return Err(Error::InvalidArgument( - "loopback".to_string(), - s.to_string(), - "Loopback type must be 'pre_dsp' or 'post_dsp'".to_string(), - )) - } - None => None, - } - } else { - None - }; - - let file_name = match matches.free.get(0) { - None => { - show_audio_command_usage(program_name, command_name, &opts); - return Err(Error::MissingFilename); - } - Some(file_name) => PathBuf::from(file_name), - }; - - let extension = file_name - .extension() - .map(|s| s.to_string_lossy().into_owned()); - let file_type = match extension.as_deref() { - Some("wav") | Some("wave") => FileType::Wav, - Some("raw") | None => FileType::Raw, - Some(extension) => return Err(Error::InvalidFiletype(extension.to_string())), - }; - - let buffer_size = get_usize_param(&matches, "buffer_size")?; - let num_channels = get_usize_param(&matches, "channels")?; - let frame_rate = get_u32_param(&matches, "rate")?; - let format = match matches.opt_str("format").as_deref() { - Some("U8") => Some(SampleFormat::U8), - Some("S16_LE") => Some(SampleFormat::S16LE), - Some("S24_LE") => Some(SampleFormat::S24LE), - Some("S32_LE") => Some(SampleFormat::S32LE), - Some(s) => { - show_audio_command_usage(program_name, command_name, &opts); - return Err(Error::InvalidArgument( - "format".to_string(), - s.to_string(), - "Format must be 'U8', 'S16_LE', 'S24_LE', or 'S32_LE'".to_string(), - )); - } - None => None, - }; - - Ok(Some(AudioOptions { - loopback_type, - file_name, - file_type, - buffer_size, - num_channels, - format, - frame_rate, - })) - } -} - -fn show_control_command_usage(program_name: &str) { - eprintln!("Usage: {} control [command] <command args>", program_name); - eprintln!(""); - eprintln!("Commands:"); - let commands = [ - ("help", "", "Print help message"), - ("", "", ""), - ("get_volume", "", "Get the system volume (0 - 100)"), - ( - "set_volume", - "VOLUME", - "Set the system volume to VOLUME (0 - 100)", - ), - ("get_mute", "", "Get the system mute state (true or false)"), - ( - "set_mute", - "MUTE", - "Set the system mute state to MUTE (true or false)", - ), - ("", "", ""), - ("list_output_devices", "", "Print list of output devices"), - ("list_input_devices", "", "Print list of input devices"), - ("list_output_nodes", "", "Print list of output nodes"), - ("list_input_nodes", "", "Print list of input nodes"), - ( - "dump_audio_debug_info", - "", - "Print stream info, device info, and audio thread log.", - ), - ]; - for command in &commands { - let command_string = format!("{} {}", command.0, command.1); - eprintln!("\t{: <23} {}", command_string, command.2); - } -} - -#[derive(Debug, PartialEq)] -pub enum ControlCommand { - GetSystemVolume, - SetSystemVolume(u32), - GetSystemMute, - SetSystemMute(bool), - ListOutputDevices, - ListInputDevices, - ListOutputNodes, - ListInputNodes, - DumpAudioDebugInfo, -} - -impl ControlCommand { - fn parse<T: AsRef<str>>(program_name: &str, args: &[T]) -> Result<Option<Self>> { - let mut args = args.iter().map(|s| s.as_ref()); - match args.next() { - Some("help") => { - show_control_command_usage(program_name); - Ok(None) - } - Some("get_volume") => Ok(Some(ControlCommand::GetSystemVolume)), - Some("set_volume") => { - let volume_str = args - .next() - .ok_or_else(|| Error::MissingArgument("set_volume".to_string()))?; - - let volume = volume_str.parse::<u32>().map_err(|e| { - Error::InvalidArgument( - "set_volume".to_string(), - volume_str.to_string(), - e.to_string(), - ) - })?; - - Ok(Some(ControlCommand::SetSystemVolume(volume))) - } - Some("get_mute") => Ok(Some(ControlCommand::GetSystemMute)), - Some("set_mute") => { - let mute_str = args - .next() - .ok_or_else(|| Error::MissingArgument("set_mute".to_string()))?; - - let mute = mute_str.parse::<bool>().map_err(|e| { - Error::InvalidArgument( - "set_mute".to_string(), - mute_str.to_string(), - e.to_string(), - ) - })?; - Ok(Some(ControlCommand::SetSystemMute(mute))) - } - Some("list_output_devices") => Ok(Some(ControlCommand::ListOutputDevices)), - Some("list_input_devices") => Ok(Some(ControlCommand::ListInputDevices)), - Some("list_output_nodes") => Ok(Some(ControlCommand::ListOutputNodes)), - Some("list_input_nodes") => Ok(Some(ControlCommand::ListInputNodes)), - Some("dump_audio_debug_info") => Ok(Some(ControlCommand::DumpAudioDebugInfo)), - Some(s) => { - show_control_command_usage(program_name); - Err(Error::UnknownCommand(s.to_string())) - } - None => { - show_control_command_usage(program_name); - Err(Error::MissingCommand) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_command() { - let command = Command::parse(&["cras_tests", "playback", "output.wav"]) - .unwrap() - .unwrap(); - assert_eq!( - command, - Command::Playback(AudioOptions { - file_name: PathBuf::from("output.wav"), - loopback_type: None, - file_type: FileType::Wav, - frame_rate: None, - num_channels: None, - format: None, - buffer_size: None, - }) - ); - let command = Command::parse(&["cras_tests", "capture", "input.raw"]) - .unwrap() - .unwrap(); - assert_eq!( - command, - Command::Capture(AudioOptions { - file_name: PathBuf::from("input.raw"), - loopback_type: None, - file_type: FileType::Raw, - frame_rate: None, - num_channels: None, - format: None, - buffer_size: None, - }) - ); - - let command = Command::parse(&[ - "cras_tests", - "playback", - "-r", - "44100", - "output.wave", - "-c", - "2", - ]) - .unwrap() - .unwrap(); - assert_eq!( - command, - Command::Playback(AudioOptions { - file_name: PathBuf::from("output.wave"), - loopback_type: None, - file_type: FileType::Wav, - frame_rate: Some(44100), - num_channels: Some(2), - format: None, - buffer_size: None, - }) - ); - - let command = - Command::parse(&["cras_tests", "playback", "-r", "44100", "output", "-c", "2"]) - .unwrap() - .unwrap(); - assert_eq!( - command, - Command::Playback(AudioOptions { - file_name: PathBuf::from("output"), - loopback_type: None, - file_type: FileType::Raw, - frame_rate: Some(44100), - num_channels: Some(2), - format: None, - buffer_size: None, - }) - ); - - assert!(Command::parse(&["cras_tests"]).is_err()); - assert!(Command::parse(&["cras_tests", "capture"]).is_err()); - assert!(Command::parse(&["cras_tests", "capture", "input.mp3"]).is_err()); - assert!(Command::parse(&["cras_tests", "capture", "input.ogg"]).is_err()); - assert!(Command::parse(&["cras_tests", "capture", "input.flac"]).is_err()); - assert!(Command::parse(&["cras_tests", "playback"]).is_err()); - assert!(Command::parse(&["cras_tests", "loopback"]).is_err()); - assert!(Command::parse(&["cras_tests", "loopback", "file.ogg"]).is_err()); - assert!(Command::parse(&["cras_tests", "filename.wav"]).is_err()); - assert!(Command::parse(&["cras_tests", "filename.wav", "capture"]).is_err()); - assert!(Command::parse(&["cras_tests", "help"]).is_ok()); - assert!(Command::parse(&[ - "cras_tests", - "-c", - "2", - "playback", - "output.wav", - "-r", - "44100" - ]) - .is_err()); - } -} diff --git a/cras/client/cras_tests/src/audio.rs b/cras/client/cras_tests/src/audio.rs deleted file mode 100644 index 23018fd7..00000000 --- a/cras/client/cras_tests/src/audio.rs +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright 2019 The Chromium OS 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 std::error; -use std::fmt; -use std::fs::File; -use std::io::{self, BufReader, BufWriter, Read, Write}; -use std::os::raw::c_int; -use std::path::Path; -use std::sync::atomic::{AtomicBool, Ordering}; - -use audio_streams::{SampleFormat, StreamSource}; -use hound::{WavReader, WavSpec, WavWriter}; -use libcras::{BoxError, CrasClient, CrasNodeType}; -use sys_util::{register_signal_handler, set_rt_prio_limit, set_rt_round_robin}; - -use crate::arguments::{AudioOptions, FileType, LoopbackType}; - -#[derive(Debug)] -pub enum Error { - CreateStream(BoxError), - FetchStream(BoxError), - FloatingPointSamples, - InvalidWavFile(hound::Error), - Io(io::Error), - Libcras(libcras::Error), - NoLoopbackNode(CrasNodeType), - OpenFile(hound::Error), - SampleBits(u16), - SysUtil(sys_util::Error), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - CreateStream(e) => write!(f, "Failed to create stream: {}", e), - FetchStream(e) => write!(f, "Failed to fetch buffer from stream: {}", e), - FloatingPointSamples => write!(f, "Floating point audio samples are not supported"), - InvalidWavFile(e) => write!(f, "Could not open file as WAV file: {}", e), - Io(e) => write!(f, "IO Error: {}", e), - Libcras(e) => write!(f, "Libcras Error: {}", e), - NoLoopbackNode(typ) => write!(f, "No loopback node found with type {:?}", typ), - OpenFile(e) => write!(f, "Could not open WAV file for writing: {}", e), - SampleBits(bits) => write!( - f, - "Sample size {} is not supported, only 8, 16, 24, and 32 bit samples are supported", - bits - ), - SysUtil(e) => write!(f, "SysUtil Error: {}", e), - } - } -} - -type Result<T> = std::result::Result<T, Error>; - -static INTERRUPTED: AtomicBool = AtomicBool::new(false); - -extern "C" fn sigint_handler(_: c_int) { - // Check if we've already received one SIGINT. If we have, the program may - // be misbehaving and not terminating, so to be safe we'll forcefully exit. - if INTERRUPTED.load(Ordering::Acquire) { - std::process::exit(1); - } - INTERRUPTED.store(true, Ordering::Release); -} - -fn add_sigint_handler() -> Result<()> { - const SIGINT: c_int = 2; - let result = unsafe { register_signal_handler(SIGINT, sigint_handler) }; - result.map_err(Error::SysUtil) -} - -fn set_priority_to_realtime() { - const AUDIO_THREAD_RTPRIO: u16 = 10; - if set_rt_prio_limit(AUDIO_THREAD_RTPRIO as u64).is_err() - || set_rt_round_robin(AUDIO_THREAD_RTPRIO as i32).is_err() - { - println!("Attempt to use real-time priority failed, running with default scheduler."); - } -} - -fn channel_string(num_channels: usize) -> String { - match num_channels { - 1 => "Mono".to_string(), - 2 => "Stereo".to_string(), - _ => format!("{} Channels", num_channels), - } -} - -struct WavSource { - wav_reader: WavReader<BufReader<File>>, - format: SampleFormat, - num_channels: usize, - frame_rate: u32, -} - -impl WavSource { - fn try_new(opts: &AudioOptions) -> Result<Self> { - let wav_reader = WavReader::open(&opts.file_name).map_err(Error::InvalidWavFile)?; - let spec = wav_reader.spec(); - if spec.sample_format == hound::SampleFormat::Float { - return Err(Error::FloatingPointSamples); - } - - let format = match spec.bits_per_sample { - 8 => SampleFormat::U8, - 16 => SampleFormat::S16LE, - 24 => SampleFormat::S24LE, - 32 => SampleFormat::S32LE, - s => return Err(Error::SampleBits(s)), - }; - if opts.format.is_some() && Some(format) != opts.format { - eprintln!("Warning: format changed to {:?}", format); - } - - let num_channels = spec.channels as usize; - if opts.num_channels.is_some() && Some(num_channels) != opts.num_channels { - eprintln!("Warning: number of channels changed to {}", num_channels); - } - - let frame_rate = spec.sample_rate; - if opts.frame_rate.is_some() && Some(frame_rate) != opts.frame_rate { - eprintln!("Warning: frame rate changed to {}", frame_rate); - } - - Ok(Self { - wav_reader, - format, - num_channels, - frame_rate, - }) - } - - fn format(&self) -> SampleFormat { - self.format - } - - fn num_channels(&self) -> usize { - self.num_channels - } - - fn frame_rate(&self) -> u32 { - self.frame_rate - } -} - -impl Read for WavSource { - fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> { - let frame_size = self.format.sample_bytes() * self.num_channels; - let read_len = buf.len() - buf.len() % frame_size; - let num_samples = read_len / self.format.sample_bytes(); - let samples = self.wav_reader.samples::<i32>(); - let mut read = 0; - for s in samples.take(num_samples) { - match s { - Ok(sample) => { - let result = match self.format { - SampleFormat::U8 => buf.write_all(&((sample + 128) as u8).to_le_bytes()), - SampleFormat::S16LE => buf.write_all(&(sample as i16).to_le_bytes()), - SampleFormat::S24LE | SampleFormat::S32LE => { - buf.write_all(&sample.to_le_bytes()) - } - }; - - match result { - Ok(()) => read += self.format.sample_bytes(), - Err(_) => return Ok(read), - }; - } - Err(_) => return Ok(read), - }; - } - Ok(read) - } -} - -pub fn playback(opts: AudioOptions) -> Result<()> { - let num_channels; - let frame_rate; - let format; - let mut sample_source: Box<dyn Read> = match opts.file_type { - FileType::Wav => { - let wav_source = WavSource::try_new(&opts)?; - num_channels = wav_source.num_channels(); - frame_rate = wav_source.frame_rate(); - format = wav_source.format(); - Box::new(wav_source) - } - FileType::Raw => { - num_channels = opts.num_channels.unwrap_or(2); - frame_rate = opts.frame_rate.unwrap_or(48000); - format = opts.format.unwrap_or(SampleFormat::S16LE); - Box::new(BufReader::new( - File::open(&opts.file_name).map_err(Error::Io)?, - )) - } - }; - - println!( - "Playing {} '{}' : {}, Rate {} Hz, {}", - opts.file_type, - opts.file_name.display(), - format, - frame_rate, - channel_string(num_channels) - ); - - let mut cras_client = CrasClient::new().map_err(Error::Libcras)?; - let (_control, mut stream) = cras_client - .new_playback_stream( - num_channels, - format, - frame_rate, - opts.buffer_size.unwrap_or(256), - ) - .map_err(Error::CreateStream)?; - set_priority_to_realtime(); - - add_sigint_handler()?; - while !INTERRUPTED.load(Ordering::Acquire) { - let mut buffer = stream.next_playback_buffer().map_err(Error::FetchStream)?; - - let frame_size = num_channels * format.sample_bytes(); - let frames = buffer.frame_capacity(); - - let mut chunk = (&mut sample_source).take((frames * frame_size) as u64); - let transferred = io::copy(&mut chunk, &mut buffer).map_err(Error::Io)?; - if transferred == 0 { - break; - } - } - // Stream and client should gracefully be closed out of this scope - - Ok(()) -} - -struct WavSink { - wav_writer: WavWriter<BufWriter<File>>, - format: SampleFormat, -} - -impl WavSink { - fn try_new<P: AsRef<Path>>( - path: P, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - ) -> Result<Self> { - let spec = WavSpec { - channels: num_channels as u16, - sample_rate: frame_rate, - bits_per_sample: (format.sample_bytes() * 8) as u16, - sample_format: hound::SampleFormat::Int, - }; - let wav_writer = WavWriter::create(path, spec).map_err(Error::OpenFile)?; - Ok(Self { wav_writer, format }) - } -} - -impl Write for WavSink { - fn write(&mut self, samples: &[u8]) -> io::Result<usize> { - let sample_bytes = self.format.sample_bytes(); - if samples.len() % sample_bytes != 0 { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!( - "u8 samples vector of length {} cannot be interpreted as {:?} samples", - samples.len(), - self.format - ), - )); - } - let num_samples = samples.len() / sample_bytes; - match self.format { - SampleFormat::U8 => { - for sample in samples { - self.wav_writer.write_sample(*sample as i8).map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!("Failed to write sample: {}", e), - ) - })?; - } - } - SampleFormat::S16LE => { - // hound offers an optimized i16 writer, so special case here. - let mut writer = self.wav_writer.get_i16_writer(num_samples as u32); - for i in 0..num_samples { - let sample = i16::from_le_bytes([ - samples[sample_bytes * i], - samples[sample_bytes * i + 1], - ]); - writer.write_sample(sample); - } - // I16Writer buffers internally and must be explicitly flushed to write - // samples to the backing writer. Flush is not called automatically - // on drop. - // The flush method only writes data from the i16_writer to the underlying - // WavWriter, it does not actually guarantee a flush to disk. - writer.flush().map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!("Failed to flush SampleWriter: {}", e), - ) - })?; - } - SampleFormat::S24LE | SampleFormat::S32LE => { - for i in 0..num_samples { - let mut sample = i32::from_le_bytes([ - samples[sample_bytes * i], - samples[sample_bytes * i + 1], - samples[sample_bytes * i + 2], - samples[sample_bytes * i + 3], - ]); - - // Upsample to 32 bit since CRAS doesn't support S24_3LE. - // Our wav encoder/decoder, hound, does have support for - // S24_LE, but it hasn't released a new version since the - // support was added. If getting that support is an issue, - // push upstream to cut a new a release. - if self.format == SampleFormat::S24LE { - sample <<= 8; - } - - self.wav_writer.write_sample(sample).map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!("Failed to write sample: {}", e), - ) - })?; - } - } - } - - Ok(samples.len()) - } - - fn flush(&mut self) -> io::Result<()> { - self.wav_writer.flush().map_err(|e| { - io::Error::new( - io::ErrorKind::Other, - format!("Failed to flush WavWriter: {}", e), - ) - }) - } -} - -pub fn capture(opts: AudioOptions) -> Result<()> { - let num_channels = opts.num_channels.unwrap_or(2); - let format = opts.format.unwrap_or(SampleFormat::S16LE); - let frame_rate = opts.frame_rate.unwrap_or(48000); - let buffer_size = opts.buffer_size.unwrap_or(256); - - let mut sample_sink: Box<dyn Write> = match opts.file_type { - FileType::Raw => Box::new(BufWriter::new( - File::create(&opts.file_name).map_err(Error::Io)?, - )), - FileType::Wav => Box::new(WavSink::try_new( - &opts.file_name, - num_channels, - format, - frame_rate, - )?), - }; - - println!( - "Recording {} '{}' : {}, Rate {} Hz, {}", - opts.file_type, - opts.file_name.display(), - format, - frame_rate, - channel_string(num_channels) - ); - - let mut cras_client = CrasClient::new().map_err(Error::Libcras)?; - cras_client.enable_cras_capture(); - let (_control, mut stream) = match opts.loopback_type { - Some(loopback_type) => { - let node_type = match loopback_type { - LoopbackType::PreDsp => CrasNodeType::CRAS_NODE_TYPE_POST_MIX_PRE_DSP, - LoopbackType::PostDsp => CrasNodeType::CRAS_NODE_TYPE_POST_DSP, - }; - - let loopback_node = cras_client - .input_nodes() - .find(|node| node.node_type == node_type) - .ok_or(Error::NoLoopbackNode(node_type))?; - - cras_client - .new_pinned_capture_stream( - loopback_node.iodev_index, - num_channels, - format, - frame_rate, - buffer_size, - ) - .map_err(Error::CreateStream)? - } - None => cras_client - .new_capture_stream(num_channels, format, frame_rate, buffer_size) - .map_err(Error::CreateStream)?, - }; - set_priority_to_realtime(); - add_sigint_handler()?; - while !INTERRUPTED.load(Ordering::Acquire) { - let mut buf = stream.next_capture_buffer().map_err(Error::FetchStream)?; - io::copy(&mut buf, &mut sample_sink).map_err(Error::Io)?; - } - Ok(()) -} diff --git a/cras/client/cras_tests/src/audio_options.rs b/cras/client/cras_tests/src/audio_options.rs new file mode 100644 index 00000000..d71aac5b --- /dev/null +++ b/cras/client/cras_tests/src/audio_options.rs @@ -0,0 +1,194 @@ +// Copyright 2019 The Chromium OS 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 std::fmt; +use std::io; +use std::path::PathBuf; + +use getopts::Options; + +type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; + +#[derive(Debug, PartialEq)] +pub enum Subcommand { + Capture, + Playback, +} + +impl fmt::Display for Subcommand { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Subcommand::Capture => write!(f, "capture"), + Subcommand::Playback => write!(f, "playback"), + } + } +} + +fn show_usage<T: AsRef<str>>(program_name: T) { + println!( + "Usage: {} [subcommand] <subcommand args>", + program_name.as_ref() + ); + println!("\nSubcommands:\n"); + println!("capture - Capture to a file from CRAS"); + println!("playback - Playback to CRAS from a file"); + println!("\nhelp - Print help message"); +} + +fn show_subcommand_usage<T: AsRef<str>>(program_name: T, subcommand: &Subcommand, opts: &Options) { + let brief = format!( + "Usage: {} {} [options] [filename]", + program_name.as_ref(), + subcommand + ); + print!("{}", opts.usage(&brief)); +} + +pub struct AudioOptions { + pub subcommand: Subcommand, + pub file_name: PathBuf, + pub buffer_size: Option<usize>, + pub num_channels: Option<usize>, + pub frame_rate: Option<usize>, +} + +impl AudioOptions { + pub fn parse_from_args<T: AsRef<str>>(args: &[T]) -> Result<Option<Self>> { + let mut opts = Options::new(); + opts.optopt("b", "buffer_size", "Buffer size in frames", "SIZE") + .optopt("c", "", "Number of channels", "NUM") + .optopt("r", "rate", "Audio frame rate (Hz)", "RATE") + .optflag("h", "help", "Print help message"); + + let mut args = args.into_iter().map(|s| s.as_ref()); + + let program_name = args.next().ok_or_else(|| { + Box::new(io::Error::new( + std::io::ErrorKind::InvalidInput, + "Program name must be specified", + )) + })?; + + let subcommand = match args.next() { + None => { + println!("Must specify a subcommand."); + show_usage(program_name); + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "No subcommand", + ))); + } + Some("help") => { + show_usage(&program_name); + return Ok(None); + } + Some("capture") => Subcommand::Capture, + Some("playback") => Subcommand::Playback, + Some(s) => { + println!("Subcommand \"{}\" does not exist.", s); + show_usage(&program_name); + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Subcommand does not exist", + ))); + } + }; + + let matches = match opts.parse(args) { + Ok(m) => m, + Err(e) => { + show_subcommand_usage(&program_name, &subcommand, &opts); + return Err(Box::new(e)); + } + }; + if matches.opt_present("h") { + show_subcommand_usage(&program_name, &subcommand, &opts); + return Ok(None); + } + let file_name = match matches.free.get(0) { + None => { + println!("Must provide file name."); + show_subcommand_usage(&program_name, &subcommand, &opts); + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Must provide file name.", + ))); + } + Some(file_name) => PathBuf::from(file_name), + }; + let buffer_size = matches.opt_get::<usize>("b")?; + let num_channels = matches.opt_get::<usize>("c")?; + let frame_rate = matches.opt_get::<usize>("r")?; + + Ok(Some(AudioOptions { + subcommand, + file_name, + buffer_size, + num_channels, + frame_rate, + })) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::ffi::OsString; + + #[test] + fn parse_from_args() { + let opts = AudioOptions::parse_from_args(&["cras_tests", "playback", "output.wav"]) + .unwrap() + .unwrap(); + assert_eq!(opts.subcommand, Subcommand::Playback); + assert_eq!(opts.file_name, OsString::from("output.wav")); + assert_eq!(opts.frame_rate, None); + assert_eq!(opts.num_channels, None); + assert_eq!(opts.buffer_size, None); + + let opts = AudioOptions::parse_from_args(&["cras_tests", "capture", "input.flac"]) + .unwrap() + .unwrap(); + assert_eq!(opts.subcommand, Subcommand::Capture); + assert_eq!(opts.file_name, OsString::from("input.flac")); + assert_eq!(opts.frame_rate, None); + assert_eq!(opts.num_channels, None); + assert_eq!(opts.buffer_size, None); + + let opts = AudioOptions::parse_from_args(&[ + "cras_tests", + "playback", + "-r", + "44100", + "output.wav", + "-c", + "2", + ]) + .unwrap() + .unwrap(); + assert_eq!(opts.subcommand, Subcommand::Playback); + assert_eq!(opts.file_name, OsString::from("output.wav")); + assert_eq!(opts.frame_rate, Some(44100)); + assert_eq!(opts.num_channels, Some(2)); + assert_eq!(opts.buffer_size, None); + + assert!(AudioOptions::parse_from_args(&["cras_tests"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "capture"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "playback"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "loopback"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "loopback", "file.ogg"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "filename.wav"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "filename.wav", "capture"]).is_err()); + assert!(AudioOptions::parse_from_args(&["cras_tests", "help"]).is_ok()); + assert!(AudioOptions::parse_from_args(&[ + "cras_tests", + "-c", + "2", + "playback", + "output.wav", + "-r", + "44100" + ]) + .is_err()); + } +} diff --git a/cras/client/cras_tests/src/control.rs b/cras/client/cras_tests/src/control.rs deleted file mode 100644 index 3a98ec98..00000000 --- a/cras/client/cras_tests/src/control.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2019 The Chromium OS 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 std::error; -use std::fmt; - -use libcras::{AudioDebugInfo, CrasClient, CrasIonodeInfo}; - -use crate::arguments::ControlCommand; - -/// An enumeration of errors that can occur when running `ControlCommand` using -/// the `control()` function. -#[derive(Debug)] -pub enum Error { - Libcras(libcras::Error), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - Libcras(e) => write!(f, "Libcras Error: {}", e), - } - } -} - -type Result<T> = std::result::Result<T, Error>; - -fn print_nodes(nodes: impl Iterator<Item = CrasIonodeInfo>) { - println!( - "{: <13}{: <7}{: <6}{: <10}{: <13}{: <20} {: <10}", - "Stable ID", "ID", "Vol", "Plugged", "Time", "Type", "Name" - ); - for node in nodes { - let id = format!("{}:{}", node.iodev_index, node.ionode_index); - let stable_id = format!("({:08x})", node.stable_id); - let plugged_time = node.plugged_time.tv_sec; - let active = if node.active { "*" } else { " " }; - println!( - "{: <13}{: <7}{: <6}{: <10}{: <13}{: <20}{}{: <10}", - stable_id, - id, - node.volume, - node.plugged, - plugged_time, - node.type_name, - active, - node.name - ); - } -} - -fn print_audio_debug_info(info: &AudioDebugInfo) { - println!("Audio Debug Stats:"); - println!("-------------devices------------"); - for device in &info.devices { - println!("{}", device); - println!(); - } - - println!("-------------stream_dump------------"); - for stream in &info.streams { - println!("{}", stream); - println!(); - } -} - -/// Connect to CRAS and run the given `ControlCommand`. -pub fn control(command: ControlCommand) -> Result<()> { - use ControlCommand::*; - let mut cras_client = CrasClient::new().map_err(Error::Libcras)?; - match command { - GetSystemVolume => println!("{}", cras_client.get_system_volume()), - SetSystemVolume(volume) => { - cras_client - .set_system_volume(volume) - .map_err(Error::Libcras)?; - } - GetSystemMute => println!("{}", cras_client.get_system_mute()), - SetSystemMute(mute) => { - cras_client.set_system_mute(mute).map_err(Error::Libcras)?; - } - ListOutputDevices => { - println!("{: <5}{: <10}", "ID", "Name"); - for dev in cras_client.output_devices() { - println!("{: <5}{: <10}", dev.index, dev.name); - } - } - ListInputDevices => { - println!("{: <5}{: <10}", "ID", "Name"); - for dev in cras_client.input_devices() { - println!("{: <5}{: <10}", dev.index, dev.name); - } - } - ListOutputNodes => print_nodes(cras_client.output_nodes()), - ListInputNodes => print_nodes(cras_client.input_nodes()), - DumpAudioDebugInfo => { - let debug_info = cras_client.get_audio_debug_info().map_err(Error::Libcras)?; - print_audio_debug_info(&debug_info); - } - }; - Ok(()) -} diff --git a/cras/client/cras_tests/src/main.rs b/cras/client/cras_tests/src/main.rs index 50ffd090..97094042 100644 --- a/cras/client/cras_tests/src/main.rs +++ b/cras/client/cras_tests/src/main.rs @@ -2,57 +2,130 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -mod arguments; -mod audio; -mod control; - -use std::error; -use std::fmt; - -use crate::arguments::Command; -use crate::audio::{capture, playback}; -use crate::control::control; - -#[derive(Debug)] -pub enum Error { - Audio(audio::Error), - ParseArgs(arguments::Error), - Control(control::Error), +mod audio_options; + +use std::fs::File; +use std::io::{self, BufRead, BufReader, Write}; +use std::thread::spawn; +use sys_util::{set_rt_prio_limit, set_rt_round_robin}; +type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; + +use audio_streams::StreamSource; +use libcras::CrasClient; + +use crate::audio_options::{AudioOptions, Subcommand}; + +fn set_priority_to_realtime() { + const AUDIO_THREAD_RTPRIO: u16 = 10; + if set_rt_prio_limit(AUDIO_THREAD_RTPRIO as u64).is_err() + || set_rt_round_robin(AUDIO_THREAD_RTPRIO as i32).is_err() + { + println!("Attempt to use real-time priority failed, running with default scheduler."); + } } -impl error::Error for Error {} +fn channel_string(num_channels: usize) -> String { + match num_channels { + 1 => "Mono".to_string(), + 2 => "Stereo".to_string(), + _ => format!("{} Channels", num_channels), + } +} + +fn playback(opts: AudioOptions) -> Result<()> { + let file = File::open(&opts.file_name).expect("failed to open file"); + let mut buffered_file = BufReader::new(file); + + let num_channels = opts.num_channels.unwrap_or(2); + let frame_rate = opts.frame_rate.unwrap_or(48000); + + println!( + "Playing raw data '{}' : Signed 16 bit Little Endian, Rate {} Hz, {}", + opts.file_name.display(), + frame_rate, + channel_string(num_channels) + ); + + let mut cras_client = CrasClient::new()?; + let (_control, mut stream) = cras_client.new_playback_stream( + num_channels, + frame_rate, + opts.buffer_size.unwrap_or(256), + )?; + let thread = spawn(move || { + set_priority_to_realtime(); + loop { + let local_buffer = buffered_file + .fill_buf() + .expect("failed to read from input file"); + + // Reached EOF + if local_buffer.len() == 0 { + break; + } + + // Gets writable buffer from stream + let mut buffer = stream + .next_playback_buffer() + .expect("failed to get next playback buffer"); -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - Audio(e) => e.fmt(f), - ParseArgs(e) => write!(f, "Failed to parse arguments: {}", e), - Control(e) => e.fmt(f), + // Writes data to stream buffer + let write_frames = buffer + .write(&local_buffer) + .expect("failed to write output data to buffer"); + + // Mark the file data as written + buffered_file.consume(write_frames); } - } + }); + thread.join().expect("Failed to join playback thread"); + // Stream and client should gracefully be closed out of this scope + + Ok(()) } -type Result<T> = std::result::Result<T, Error>; +fn capture(opts: AudioOptions) -> Result<()> { + let num_channels = opts.num_channels.unwrap_or(2); + let frame_rate = opts.frame_rate.unwrap_or(48000); + + println!( + "Recording raw data '{}' : Signed 16 bit Little Endian, Rate {} Hz, {}", + opts.file_name.display(), + frame_rate, + channel_string(num_channels) + ); + + let mut cras_client = CrasClient::new()?; + cras_client.enable_cras_capture(); + let (_control, mut stream) = cras_client.new_capture_stream( + num_channels, + frame_rate, + opts.buffer_size.unwrap_or(256), + )?; + let mut file = File::create(&opts.file_name).unwrap(); + loop { + let _frames = match stream.next_capture_buffer() { + Err(e) => { + return Err(e.into()); + } + Ok(mut buf) => { + let written = io::copy(&mut buf, &mut file)?; + written + } + }; + } +} -fn run() -> Result<()> { +fn main() -> Result<()> { let args: Vec<String> = std::env::args().collect(); - let command = match Command::parse(&args).map_err(Error::ParseArgs)? { + let opts = match AudioOptions::parse_from_args(&args)? { None => return Ok(()), Some(v) => v, }; - match command { - Command::Capture(audio_opts) => capture(audio_opts).map_err(Error::Audio), - Command::Control(command) => control(command).map_err(Error::Control), - Command::Playback(audio_opts) => playback(audio_opts).map_err(Error::Audio), - } -} - -fn main() { - // Use run() instead of returning a Result from main() so that we can print - // errors using Display instead of Debug. - if let Err(e) = run() { - eprintln!("{}", e); - } + match opts.subcommand { + Subcommand::Capture => capture(opts)?, + Subcommand::Playback => playback(opts)?, + }; + Ok(()) } diff --git a/cras/client/libcras/.gitignore b/cras/client/libcras/.gitignore index fa8d85ac..41cebfd4 100644 --- a/cras/client/libcras/.gitignore +++ b/cras/client/libcras/.gitignore @@ -1,2 +1,3 @@ -Cargo.lock -target +target/ +.rustfmt.toml +.*.rustfmt.toml diff --git a/cras/client/libcras/Android.bp b/cras/client/libcras/Android.bp index aecb27a2..33c4ddb1 100644 --- a/cras/client/libcras/Android.bp +++ b/cras/client/libcras/Android.bp @@ -1,23 +1,15 @@ -// This file is generated by cargo2android.py --run --device --test --global_defaults=crosvm_defaults --dependencies. +// This file is generated by cargo2android.py, added defaults. -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "external_adhd_license" - // to get the below license kinds: - // SPDX-license-identifier-BSD - default_applicable_licenses: ["external_adhd_license"], -} - -rust_defaults { - name: "libcras_defaults", +rust_test_host { + name: "libcras_tests_libcras", defaults: ["crosvm_defaults"], + deny_warnings: false, crate_name: "libcras", srcs: ["src/libcras.rs"], + relative_install_path: "libcras_tests", test_suites: ["general-tests"], auto_gen_config: true, - edition: "2018", - rustlibs: [ + rlibs: [ "libaudio_streams", "libcras_sys", "libdata_model", @@ -26,24 +18,13 @@ rust_defaults { ], } -rust_test_host { - name: "libcras_host_test_src_libcras", - defaults: ["libcras_defaults"], -} - -rust_test { - name: "libcras_device_test_src_libcras", - defaults: ["libcras_defaults"], -} - -rust_library { +rust_library_host_rlib { name: "liblibcras", defaults: ["crosvm_defaults"], - host_supported: true, + deny_warnings: false, crate_name: "libcras", srcs: ["src/libcras.rs"], - edition: "2018", - rustlibs: [ + rlibs: [ "libaudio_streams", "libcras_sys", "libdata_model", @@ -51,19 +32,3 @@ rust_library { "libsys_util", ], } - -// dependent_library ["feature_list"] -// ../../../../crosvm/assertions/src/lib.rs -// ../../../../crosvm/data_model/src/lib.rs -// ../../../../crosvm/sync/src/lib.rs -// ../../../../crosvm/sys_util/poll_token_derive/poll_token_derive.rs -// ../../../../crosvm/sys_util/src/lib.rs -// ../../../../crosvm/syscall_defines/src/lib.rs -// ../../../../crosvm/tempfile/src/lib.rs -// ../../../audio_streams/src/audio_streams.rs -// ../cras-sys/src/lib.rs -// libc-0.2.76 "default,std" -// proc-macro2-1.0.19 "default,proc-macro" -// quote-1.0.7 "default,proc-macro" -// syn-1.0.39 "clone-impls,default,derive,parsing,printing,proc-macro,quote" -// unicode-xid-0.2.1 "default" diff --git a/cras/client/libcras/Cargo.toml b/cras/client/libcras/Cargo.toml index b52a2612..cc2a3e13 100644 --- a/cras/client/libcras/Cargo.toml +++ b/cras/client/libcras/Cargo.toml @@ -11,5 +11,5 @@ path = "src/libcras.rs" audio_streams = { path = "../../../audio_streams" } # provided by ebuild libc = "*" cras-sys = { path = "../cras-sys" } # provided by ebuild -data_model = { path = "../../../../crosvm/data_model" } # provided by ebuild -sys_util = { path = "../../../../crosvm/sys_util" } # provided by ebuild +data_model = { path = "../../../../../platform/crosvm/data_model" } # provided by ebuild +sys_util = { path = "../../../../../platform/crosvm/sys_util" } # provided by ebuild diff --git a/cras/client/libcras/src/cras_client_message.rs b/cras/client/libcras/src/cras_client_message.rs index c1c5ec5c..0921c5f2 100644 --- a/cras/client/libcras/src/cras_client_message.rs +++ b/cras/client/libcras/src/cras_client_message.rs @@ -16,7 +16,7 @@ use crate::cras_shm::*; use crate::cras_stream; #[derive(Debug)] -pub enum Error { +enum ErrorType { IoError(io::Error), SysUtilError(sys_util::Error), CrasStreamError(cras_stream::Error), @@ -29,21 +29,32 @@ pub enum Error { MessageFromSliceError, } +#[derive(Debug)] +pub struct Error { + error_type: ErrorType, +} + +impl Error { + fn new(error_type: ErrorType) -> Error { + Error { error_type } + } +} + impl error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::IoError(ref err) => err.fmt(f), - Error::SysUtilError(ref err) => err.fmt(f), - Error::MessageTypeError => write!(f, "Message type error"), - Error::CrasStreamError(ref err) => err.fmt(f), - Error::ArrayTryFromSliceError(ref err) => err.fmt(f), - Error::MessageNumFdError => write!(f, "Message the number of fds is not matched"), - Error::MessageTruncated => write!(f, "Read truncated message"), - Error::MessageIdError => write!(f, "No such id"), - Error::MessageFromSliceError => write!(f, "Message from slice error"), - Error::InvalidSize => write!(f, "Invalid data size"), + match self.error_type { + ErrorType::IoError(ref err) => err.fmt(f), + ErrorType::SysUtilError(ref err) => err.fmt(f), + ErrorType::MessageTypeError => write!(f, "Message type error"), + ErrorType::CrasStreamError(ref err) => err.fmt(f), + ErrorType::ArrayTryFromSliceError(ref err) => err.fmt(f), + ErrorType::MessageNumFdError => write!(f, "Message the number of fds is not matched"), + ErrorType::MessageTruncated => write!(f, "Read truncated message"), + ErrorType::MessageIdError => write!(f, "No such id"), + ErrorType::MessageFromSliceError => write!(f, "Message from slice error"), + ErrorType::InvalidSize => write!(f, "Invalid data size"), } } } @@ -52,25 +63,25 @@ type Result<T> = std::result::Result<T, Error>; impl From<io::Error> for Error { fn from(io_err: io::Error) -> Self { - Error::IoError(io_err) + Self::new(ErrorType::IoError(io_err)) } } impl From<sys_util::Error> for Error { fn from(sys_util_err: sys_util::Error) -> Self { - Error::SysUtilError(sys_util_err) + Self::new(ErrorType::SysUtilError(sys_util_err)) } } impl From<cras_stream::Error> for Error { fn from(err: cras_stream::Error) -> Self { - Error::CrasStreamError(err) + Self::new(ErrorType::CrasStreamError(err)) } } impl From<TryFromSliceError> for Error { fn from(err: TryFromSliceError) -> Self { - Error::ArrayTryFromSliceError(err) + Self::new(ErrorType::ArrayTryFromSliceError(err)) } } @@ -80,7 +91,6 @@ pub enum ServerResult { Connected(u32, CrasServerStateShmFd), /// stream_id, header_fd, samples_fd StreamConnected(u32, CrasAudioShmHeaderFd, CrasShmFd), - DebugInfoReady, } impl ServerResult { @@ -112,10 +122,7 @@ impl ServerResult { unsafe { CrasShmFd::new(message.fds[1], cmsg.samples_shm_size as usize) }, )) } - CRAS_CLIENT_MESSAGE_ID::CRAS_CLIENT_AUDIO_DEBUG_INFO_READY => { - Ok(ServerResult::DebugInfoReady) - } - _ => Err(Error::MessageTypeError), + _ => Err(Error::new(ErrorType::MessageTypeError)), } } } @@ -147,7 +154,7 @@ impl CrasClientMessage { let (len, fd_nums) = server_socket.recv_with_fds(&mut message.data, &mut message.fds)?; if len < mem::size_of::<cras_client_message>() { - Err(Error::MessageTruncated) + Err(Error::new(ErrorType::MessageTruncated)) } else { message.len = len; message.check_fd_nums(fd_nums)?; @@ -160,20 +167,16 @@ impl CrasClientMessage { match self.get_id()? { CRAS_CLIENT_CONNECTED => match fd_nums { 1 => Ok(()), - _ => Err(Error::MessageNumFdError), + _ => Err(Error::new(ErrorType::MessageNumFdError)), }, CRAS_CLIENT_STREAM_CONNECTED => match fd_nums { // CRAS should return two shared memory areas the first which has // mem::size_of::<cras_audio_shm_header>() bytes, and the second which has // `samples_shm_size` bytes. 2 => Ok(()), - _ => Err(Error::MessageNumFdError), + _ => Err(Error::new(ErrorType::MessageNumFdError)), }, - CRAS_CLIENT_AUDIO_DEBUG_INFO_READY => match fd_nums { - 0 => Ok(()), - _ => Err(Error::MessageNumFdError), - }, - _ => Err(Error::MessageTypeError), + _ => Err(Error::new(ErrorType::MessageTypeError)), } } @@ -183,18 +186,16 @@ impl CrasClientMessage { match u32::from_le_bytes(self.data[offset..offset + 4].try_into()?) { id if id == (CRAS_CLIENT_CONNECTED as u32) => Ok(CRAS_CLIENT_CONNECTED), id if id == (CRAS_CLIENT_STREAM_CONNECTED as u32) => Ok(CRAS_CLIENT_STREAM_CONNECTED), - id if id == (CRAS_CLIENT_AUDIO_DEBUG_INFO_READY as u32) => { - Ok(CRAS_CLIENT_AUDIO_DEBUG_INFO_READY) - } - _ => Err(Error::MessageIdError), + _ => Err(Error::new(ErrorType::MessageIdError)), } } // Gets a reference to the message content fn get_message<T: DataInit>(&self) -> Result<&T> { if self.len != mem::size_of::<T>() { - return Err(Error::InvalidSize); + return Err(Error::new(ErrorType::InvalidSize)); } - T::from_slice(&self.data[..mem::size_of::<T>()]).ok_or(Error::MessageFromSliceError) + T::from_slice(&self.data[..mem::size_of::<T>()]) + .ok_or_else(|| Error::new(ErrorType::MessageFromSliceError)) } } diff --git a/cras/client/libcras/src/cras_server_socket.rs b/cras/client/libcras/src/cras_server_socket.rs index 4a7d9151..139382a8 100644 --- a/cras/client/libcras/src/cras_server_socket.rs +++ b/cras/client/libcras/src/cras_server_socket.rs @@ -1,31 +1,14 @@ // Copyright 2019 The Chromium OS 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 std::io; use std::os::unix::io::{AsRawFd, RawFd}; -use std::{io, mem}; -use cras_sys::gen::{cras_disconnect_stream_message, cras_server_message, CRAS_SERVER_MESSAGE_ID}; use sys_util::{net::UnixSeqpacket, ScmSocket}; use data_model::DataInit; -/// Server socket type to connect. -pub enum CrasSocketType { - /// A server socket type supports only playback function. - Legacy, - /// A server socket type supports both playback and capture functions. - Unified, -} - -impl CrasSocketType { - fn sock_path(&self) -> &str { - match self { - Self::Legacy => "/run/cras/.cras_socket", - Self::Unified => "/run/cras/.cras_unified", - } - } -} - +const CRAS_SERVER_SOCKET_PATH: &str = "/run/cras/.cras_socket"; /// A socket connecting to the CRAS audio server. pub struct CrasServerSocket { socket: UnixSeqpacket, @@ -33,18 +16,8 @@ pub struct CrasServerSocket { impl CrasServerSocket { pub fn new() -> io::Result<CrasServerSocket> { - Self::with_type(CrasSocketType::Legacy) - } - - /// Creates a `CrasServerSocket` with given `CrasSocketType`. - /// - /// # Errors - /// - /// Returns the `io::Error` generated when connecting to the socket on failure. - pub fn with_type(socket_type: CrasSocketType) -> io::Result<CrasServerSocket> { - Ok(CrasServerSocket { - socket: UnixSeqpacket::connect(socket_type.sock_path())?, - }) + let socket = UnixSeqpacket::connect(CRAS_SERVER_SOCKET_PATH)?; + Ok(CrasServerSocket { socket }) } /// Sends a sized and packed server messge to the server socket. The message @@ -65,13 +38,10 @@ impl CrasServerSocket { ) -> io::Result<usize> { match fds.len() { 0 => self.socket.send(message.as_slice()), - _ => { - let ioslice = io::IoSlice::new(message.as_slice()); - match self.send_with_fds(&[ioslice], fds) { - Ok(len) => Ok(len), - Err(err) => Err(io::Error::new(io::ErrorKind::Other, format!("{}", err))), - } - } + _ => match self.send_with_fds(message.as_slice(), fds) { + Ok(len) => Ok(len), + Err(err) => Err(io::Error::new(io::ErrorKind::Other, format!("{}", err))), + }, } } @@ -81,32 +51,6 @@ impl CrasServerSocket { let new_sock = self.socket.try_clone()?; Ok(CrasServerSocket { socket: new_sock }) } - - /// Send a message to request disconnection of the given stream. - /// - /// Builds a `cras_disconnect_stream_message` containing `stream_id` and - /// sends it to the server. - /// No response is expected. - /// - /// # Arguments - /// - /// * `stream_id` - The id of the stream that should be disconnected. - /// - /// # Errors - /// - /// * If the message was not written to the server socket successfully. - pub fn disconnect_stream(&self, stream_id: u32) -> io::Result<()> { - let msg_header = cras_server_message { - length: mem::size_of::<cras_disconnect_stream_message>() as u32, - id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_DISCONNECT_STREAM, - }; - let server_cmsg = cras_disconnect_stream_message { - header: msg_header, - stream_id, - }; - self.send_server_message_with_fds(&server_cmsg, &[]) - .map(|_| ()) - } } // For using `recv_with_fds` and `send_with_fds`. diff --git a/cras/client/libcras/src/cras_shm.rs b/cras/client/libcras/src/cras_shm.rs index 05533753..55474976 100644 --- a/cras/client/libcras/src/cras_shm.rs +++ b/cras/client/libcras/src/cras_shm.rs @@ -1,26 +1,19 @@ // Copyright 2019 The Chromium OS 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 std::convert::TryFrom; use std::io; use std::mem; use std::os::unix::io::{AsRawFd, RawFd}; use std::ptr; use std::ptr::NonNull; use std::slice; -use std::sync::atomic::{self, Ordering}; -use std::thread; + +use libc; use cras_sys::gen::{ - audio_dev_debug_info, audio_stream_debug_info, cras_audio_shm_header, cras_iodev_info, - cras_ionode_info, cras_server_state, CRAS_MAX_IODEVS, CRAS_MAX_IONODES, CRAS_NUM_SHM_BUFFERS, - CRAS_SERVER_STATE_VERSION, CRAS_SHM_BUFFERS_MASK, MAX_DEBUG_DEVS, MAX_DEBUG_STREAMS, -}; -use cras_sys::{ - AudioDebugInfo, AudioDevDebugInfo, AudioStreamDebugInfo, CrasIodevInfo, CrasIonodeInfo, + cras_audio_shm_header, cras_server_state, CRAS_NUM_SHM_BUFFERS, CRAS_SHM_BUFFERS_MASK, }; -use data_model::{VolatileRef, VolatileSlice}; -use sys_util::warn; +use data_model::VolatileRef; /// A structure wrapping a fd which contains a shared `cras_audio_shm_header`. /// * `shm_fd` - A shared memory fd contains a `cras_audio_shm_header` @@ -52,6 +45,7 @@ impl CrasAudioShmHeaderFd { /// A wrapper for the raw structure `cras_audio_shm_header` with /// size information for the separate audio samples shm area and several /// `VolatileRef` to sub fields for safe access to the header. +#[allow(dead_code)] pub struct CrasAudioHeader<'a> { addr: *mut libc::c_void, /// Size of the buffer for samples in CrasAudioBuffer @@ -62,7 +56,7 @@ pub struct CrasAudioHeader<'a> { write_buf_idx: VolatileRef<'a, u32>, read_offset: [VolatileRef<'a, u32>; CRAS_NUM_SHM_BUFFERS as usize], write_offset: [VolatileRef<'a, u32>; CRAS_NUM_SHM_BUFFERS as usize], - buffer_offset: [VolatileRef<'a, u64>; CRAS_NUM_SHM_BUFFERS as usize], + buffer_offset: [VolatileRef<'a, u32>; CRAS_NUM_SHM_BUFFERS as usize], } // It is safe to send audio buffers between threads as this struct has exclusive ownership of the @@ -232,13 +226,8 @@ impl<'a> CrasAudioHeader<'a> { self.frame_size.load() as usize } - /// Gets the max size in bytes of each shared memory buffer within - /// the samples area. - /// - /// # Returns - /// - /// * `usize` - Value of `used_size` fetched from the shared memory header. - pub fn get_used_size(&self) -> usize { + /// Gets the size in bytes of the shared memory buffer. + fn get_used_size(&self) -> usize { self.used_size.load() as usize } @@ -310,7 +299,7 @@ impl<'a> CrasAudioHeader<'a> { Ok(()) } - /// Sets `read_offset[idx]` to count of written bytes. + /// Sets `read_offset[idx]` of to count of written bytes. /// /// # Arguments /// `idx` - 0 <= `idx` < `CRAS_NUM_SHM_BUFFERS` @@ -345,23 +334,13 @@ impl<'a> CrasAudioHeader<'a> { .load() as usize; let other_end = other_start + self.buffer_len_from_offset(other_start)?; if start < other_end && other_start < end { - // Special case: occasionally we get the same buffer offset twice - // from the intel8x0 kernel driver in crosvm's AC97 device, and we - // don't want to crash in that case. - if start == other_start && end == other_end { - warn!( - "Setting buffer {} to same index/offset as buffer {}, [{}, {})", - idx, other_idx, other_start, other_end - ); - } else { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!( - "Setting buffer {} to [{}, {}) overlaps buffer {} at [{}, {})", - idx, start, end, other_idx, other_start, other_end, - ), - )); - } + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!( + "Setting buffer {} to [{}, {}) overlaps buffer {} at [{}, {})", + idx, start, end, other_idx, other_start, other_end, + ), + )); } Ok(()) } @@ -381,11 +360,11 @@ impl<'a> CrasAudioHeader<'a> { /// * overlaps some other buffer `[other_offset, other_offset + used_size)` /// * is close enough to the end of the samples area that the buffer would /// be shorter than `frame_size`. - pub fn set_buffer_offset(&mut self, idx: usize, offset: usize) -> io::Result<()> { + fn set_buffer_offset(&mut self, idx: usize, offset: usize) -> io::Result<()> { self.check_buffer_offset(idx, offset)?; let buffer_offset = self.buffer_offset.get(idx).ok_or_else(index_out_of_range)?; - buffer_offset.store(offset as u64); + buffer_offset.store(offset as u32); Ok(()) } @@ -520,252 +499,45 @@ unsafe fn cras_mmap( cras_mmap_offset(len, prot, fd, 0) } -/// An unsafe macro for getting a `VolatileSlice` representing an entire array -/// field from a given NonNull pointer. -/// -/// To use this macro safely, we need to -/// - Make sure the pointer address is readable and writeable for its struct. -/// - Make sure all `VolatileSlice`s generated from this macro have exclusive ownership for the same -/// pointer. -/// - Make sure the length of the array field is non-zero. -#[macro_export] -macro_rules! vslice_from_addr { - ($addr:ident, $($field:ident).*) => {{ - let ptr = &mut $addr.as_mut().$($field).* as *mut _ as *mut u8; - let size = std::mem::size_of_val(&$addr.as_mut().$($field).*); - VolatileSlice::from_raw_parts(ptr, size) - }}; -} - /// A structure that points to RO shared memory area - `cras_server_state` /// The structure is created from a shared memory fd which contains the structure. -#[derive(Debug)] -pub struct CrasServerState<'a> { +#[allow(dead_code)] +pub struct CrasServerState { addr: *mut libc::c_void, - volume: VolatileRef<'a, u32>, - mute: VolatileRef<'a, i32>, - num_output_devs: VolatileRef<'a, u32>, - output_devs: VolatileSlice<'a>, - num_input_devs: VolatileRef<'a, u32>, - input_devs: VolatileSlice<'a>, - num_output_nodes: VolatileRef<'a, u32>, - num_input_nodes: VolatileRef<'a, u32>, - output_nodes: VolatileSlice<'a>, - input_nodes: VolatileSlice<'a>, - update_count: VolatileRef<'a, u32>, - debug_info_num_devs: VolatileRef<'a, u32>, - debug_info_devs: VolatileSlice<'a>, - debug_info_num_streams: VolatileRef<'a, u32>, - debug_info_streams: VolatileSlice<'a>, + size: usize, } -// It is safe to send server_state between threads as this struct has exclusive -// ownership of the shared memory area contained in it. -unsafe impl<'a> Send for CrasServerState<'a> {} - -impl<'a> CrasServerState<'a> { - /// Create a CrasServerState - pub fn try_new(state_fd: CrasServerStateShmFd) -> io::Result<Self> { - // Safe because the creator of CrasServerStateShmFd already - // ensured that state_fd contains a cras_server_state. - let mmap_addr = - unsafe { cras_mmap(state_fd.fd.size, libc::PROT_READ, state_fd.fd.as_raw_fd())? }; - - let mut addr = NonNull::new(mmap_addr as *mut cras_server_state).ok_or_else(|| { - io::Error::new(io::ErrorKind::Other, "Failed to create CrasServerState.") - })?; - - // Safe because we know that addr is a non-null pointer to cras_server_state. - let state_version = unsafe { vref_from_addr!(addr, state_version) }; - if state_version.load() != CRAS_SERVER_STATE_VERSION { - return Err(io::Error::new( - io::ErrorKind::Other, - format!( - "CrasServerState version {} does not match expected version {}", - state_version.load(), - CRAS_SERVER_STATE_VERSION - ), - )); - } - - // Safe because we know that mmap_addr (contained in addr) contains a - // cras_server_state, and the mapped area will be exclusively - // owned by this struct. - unsafe { - Ok(CrasServerState { - addr: addr.as_ptr() as *mut libc::c_void, - volume: vref_from_addr!(addr, volume), - mute: vref_from_addr!(addr, mute), - num_output_devs: vref_from_addr!(addr, num_output_devs), - num_input_devs: vref_from_addr!(addr, num_input_devs), - output_devs: vslice_from_addr!(addr, output_devs), - input_devs: vslice_from_addr!(addr, input_devs), - num_output_nodes: vref_from_addr!(addr, num_output_nodes), - num_input_nodes: vref_from_addr!(addr, num_input_nodes), - output_nodes: vslice_from_addr!(addr, output_nodes), - input_nodes: vslice_from_addr!(addr, input_nodes), - update_count: vref_from_addr!(addr, update_count), - debug_info_num_devs: vref_from_addr!(addr, audio_debug_info.num_devs), - debug_info_devs: vslice_from_addr!(addr, audio_debug_info.devs), - debug_info_num_streams: vref_from_addr!(addr, audio_debug_info.num_streams), - debug_info_streams: vslice_from_addr!(addr, audio_debug_info.streams), - }) - } - } - - /// Gets the system volume. - /// - /// Read the current value for system volume from shared memory. - pub fn get_system_volume(&self) -> u32 { - self.volume.load() - } - - /// Gets the system mute. - /// - /// Read the current value for system mute from shared memory. - pub fn get_system_mute(&self) -> bool { - self.mute.load() != 0 - } - - /// Runs a closure safely such that it can be sure that the server state - /// was not updated during the read. - /// This can be used for an "atomic" read of non-atomic data from the - /// state shared memory. - fn synchronized_state_read<F, T>(&self, mut func: F) -> T - where - F: FnMut() -> T, - { - // Waits until the server has completed a state update before returning - // the current update count. - let begin_server_state_read = || -> u32 { - loop { - let update_count = self.update_count.load(); - if update_count % 2 == 0 { - atomic::fence(Ordering::Acquire); - return update_count; - } else { - thread::yield_now(); - } - } - }; - - // Checks that the update count has not changed since the start - // of the server state read. - let end_server_state_read = |count: u32| -> bool { - let result = count == self.update_count.load(); - atomic::fence(Ordering::Release); - result - }; - - // Get the state's update count and run the provided closure. - // If the update count has not changed once the closure is finished, - // return the result, otherwise repeat the process. - loop { - let update_count = begin_server_state_read(); - let result = func(); - if end_server_state_read(update_count) { - return result; - } +impl CrasServerState { + /// An unsafe function for creating `CrasServerState`. To use this function safely, we need to + /// - Make sure that the `shm_fd` must come from the server's message that provides the shared + /// memory region. The Id for the message is `CRAS_CLIENT_MESSAGE_ID::CRAS_CLIENT_CONNECTED`. + #[allow(dead_code)] + pub unsafe fn new(shm_fd: CrasShmFd) -> io::Result<Self> { + let size = mem::size_of::<cras_server_state>(); + if size > shm_fd.size { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid shared memory size.", + )) + } else { + let addr = cras_mmap(size, libc::PROT_READ, shm_fd.as_raw_fd())?; + Ok(CrasServerState { addr, size }) } } - /// Gets a list of output devices - /// - /// Read a list of the currently attached output devices from shared memory. - pub fn output_devices(&self) -> impl Iterator<Item = CrasIodevInfo> { - let mut devs: Vec<cras_iodev_info> = vec![Default::default(); CRAS_MAX_IODEVS as usize]; - let num_devs = self.synchronized_state_read(|| { - self.output_devs.copy_to(&mut devs); - self.num_output_devs.load() - }); - devs.into_iter() - .take(num_devs as usize) - .map(CrasIodevInfo::from) - } - - /// Gets a list of input devices - /// - /// Read a list of the currently attached input devices from shared memory. - pub fn input_devices(&self) -> impl Iterator<Item = CrasIodevInfo> { - let mut devs: Vec<cras_iodev_info> = vec![Default::default(); CRAS_MAX_IODEVS as usize]; - let num_devs = self.synchronized_state_read(|| { - self.input_devs.copy_to(&mut devs); - self.num_input_devs.load() - }); - devs.into_iter() - .take(num_devs as usize) - .map(CrasIodevInfo::from) - } - - /// Gets a list of output nodes - /// - /// Read a list of the currently attached output nodes from shared memory. - pub fn output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> { - let mut nodes: Vec<cras_ionode_info> = vec![Default::default(); CRAS_MAX_IONODES as usize]; - let num_nodes = self.synchronized_state_read(|| { - self.output_nodes.copy_to(&mut nodes); - self.num_output_nodes.load() - }); - nodes - .into_iter() - .take(num_nodes as usize) - .map(CrasIonodeInfo::from) - } - - /// Gets a list of input nodes - /// - /// Read a list of the currently attached input nodes from shared memory. - pub fn input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> { - let mut nodes: Vec<cras_ionode_info> = vec![Default::default(); CRAS_MAX_IONODES as usize]; - let num_nodes = self.synchronized_state_read(|| { - self.input_nodes.copy_to(&mut nodes); - self.num_input_nodes.load() - }); - nodes - .into_iter() - .take(num_nodes as usize) - .map(CrasIonodeInfo::from) - } - - /// Get audio debug info - /// - /// Loads the server's audio_debug_info struct and converts it into an - /// idiomatic rust representation. - /// - /// # Errors - /// * If any of the stream debug information structs are invalid. - pub fn get_audio_debug_info(&self) -> Result<AudioDebugInfo, cras_sys::Error> { - let mut devs: Vec<audio_dev_debug_info> = vec![Default::default(); MAX_DEBUG_DEVS as usize]; - let mut streams: Vec<audio_stream_debug_info> = - vec![Default::default(); MAX_DEBUG_STREAMS as usize]; - let (num_devs, num_streams) = self.synchronized_state_read(|| { - self.debug_info_devs.copy_to(&mut devs); - self.debug_info_streams.copy_to(&mut streams); - ( - self.debug_info_num_devs.load(), - self.debug_info_num_streams.load(), - ) - }); - let dev_info = devs - .into_iter() - .take(num_devs as usize) - .map(AudioDevDebugInfo::from) - .collect(); - let stream_info = streams - .into_iter() - .take(num_streams as usize) - .map(AudioStreamDebugInfo::try_from) - .collect::<Result<Vec<_>, _>>()?; - Ok(AudioDebugInfo::new(dev_info, stream_info)) + // Gets `cras_server_state` reference from the structure. + #[allow(dead_code)] + fn get_ref(&self) -> VolatileRef<cras_server_state> { + unsafe { VolatileRef::new(self.addr as *mut _) } } } -impl<'a> Drop for CrasServerState<'a> { +impl Drop for CrasServerState { /// Call `munmap` for `addr`. fn drop(&mut self) { unsafe { // Safe because all references must be gone by the time drop is called. - libc::munmap(self.addr, mem::size_of::<cras_server_state>()); + libc::munmap(self.addr, self.size); } } } @@ -830,16 +602,6 @@ pub fn create_header_and_buffers<'a>( Ok((header, buffer)) } -/// Creates header from header shared memory fds. Use this function -/// when mapping the samples shm is not necessary, for instance with a -/// client-provided shm stream. -pub fn create_header<'a>( - header_fd: CrasAudioShmHeaderFd, - samples_len: usize, -) -> io::Result<CrasAudioHeader<'a>> { - Ok(CrasAudioHeader::new(header_fd, samples_len)?) -} - /// A structure wrapping a fd which contains a shared memory area and its size. /// * `fd` - The shared memory file descriptor, a `libc::c_int`. /// * `size` - Size of the shared memory area. @@ -888,7 +650,8 @@ impl Drop for CrasShmFd { /// A structure wrapping a fd which contains a shared `cras_server_state`. /// * `shm_fd` - A shared memory fd contains a `cras_server_state` pub struct CrasServerStateShmFd { - fd: CrasShmFd, + #[allow(dead_code)] + shm_fd: CrasShmFd, } impl CrasServerStateShmFd { @@ -907,7 +670,7 @@ impl CrasServerStateShmFd { /// - The shared memory area in the input fd contains a `cras_server_state`. pub unsafe fn new(fd: libc::c_int) -> Self { Self { - fd: CrasShmFd::new(fd, mem::size_of::<cras_server_state>()), + shm_fd: CrasShmFd::new(fd, mem::size_of::<cras_server_state>()), } } } @@ -917,8 +680,6 @@ mod tests { use super::*; use std::fs::File; use std::os::unix::io::IntoRawFd; - use std::sync::{Arc, Mutex}; - use std::thread; use sys_util::{kernel_has_memfd, SharedMemory}; #[test] @@ -1124,16 +885,13 @@ mod tests { header.write_offset[1].store(0); header.buffer_offset[1].store(10); - // Setting buffer_offset to exactly overlap with other buffer is okay - assert!(header.set_buffer_offset(0, 10).is_ok()); - - // Setting buffer_offset to partially overlap other buffer is not okay - assert!(header.set_buffer_offset(0, 9).is_err()); + // Setting buffer_offset to overlap with other buffer is not okay + assert!(header.set_buffer_offset(0, 10).is_err()); header.buffer_offset[0].store(0); header.write_offset[1].store(8); // With samples, it's still an error. - assert!(header.set_buffer_offset(0, 9).is_err()); + assert!(header.set_buffer_offset(0, 10).is_err()); // Setting the offset past the end of the other buffer is okay assert!(header.set_buffer_offset(0, 20).is_ok()); @@ -1148,9 +906,9 @@ mod tests { assert!(header.set_buffer_offset(0, 30).is_err()); // If we try to overlap another buffer with that other buffer at the end, - // it's not okay, unless it's the exact same index. + // it's not okay. assert!(header.set_buffer_offset(1, 25).is_err()); - assert!(header.set_buffer_offset(1, 27).is_ok()); + assert!(header.set_buffer_offset(1, 27).is_err()); assert!(header.set_buffer_offset(1, 28).is_err()); // Setting buffer offset past the end of samples is an error. @@ -1208,101 +966,4 @@ mod tests { let rc = unsafe { cras_mmap(10, libc::PROT_READ, -1) }; assert!(rc.is_err()); } - - #[test] - fn cras_server_state() { - let size = mem::size_of::<cras_server_state>(); - let shm = create_shm(size); - unsafe { - let addr = cras_mmap(size, libc::PROT_WRITE, shm.as_raw_fd()) - .expect("failed to mmap state shm"); - { - let state: &mut cras_server_state = &mut *(addr as *mut cras_server_state); - state.state_version = CRAS_SERVER_STATE_VERSION; - state.volume = 47; - state.mute = 1; - } - libc::munmap(addr, size); - }; - let state_fd = unsafe { CrasServerStateShmFd::new(shm.into_raw_fd()) }; - let state = - CrasServerState::try_new(state_fd).expect("try_new failed for valid server_state fd"); - assert_eq!(state.get_system_volume(), 47); - assert_eq!(state.get_system_mute(), true); - } - - #[test] - fn cras_server_state_old_version() { - let size = mem::size_of::<cras_server_state>(); - let shm = create_shm(size); - unsafe { - let addr = cras_mmap(size, libc::PROT_WRITE, shm.as_raw_fd()) - .expect("failed to mmap state shm"); - { - let state: &mut cras_server_state = &mut *(addr as *mut cras_server_state); - state.state_version = CRAS_SERVER_STATE_VERSION - 1; - state.volume = 29; - state.mute = 0; - } - libc::munmap(addr, size); - }; - let state_fd = unsafe { CrasServerStateShmFd::new(shm.into_raw_fd()) }; - CrasServerState::try_new(state_fd) - .expect_err("try_new succeeded for invalid state version"); - } - - #[test] - fn cras_server_sync_state_read() { - let size = mem::size_of::<cras_server_state>(); - let shm = create_shm(size); - let addr = unsafe { cras_mmap(size, libc::PROT_WRITE, shm.as_raw_fd()).unwrap() }; - let state: &mut cras_server_state = unsafe { &mut *(addr as *mut cras_server_state) }; - state.state_version = CRAS_SERVER_STATE_VERSION; - state.update_count = 14; - state.volume = 12; - - let state_fd = unsafe { CrasServerStateShmFd::new(shm.into_raw_fd()) }; - let state_struct = CrasServerState::try_new(state_fd).unwrap(); - - // Create a lock so that we can block the reader while we change the - // update_count; - let lock = Arc::new(Mutex::new(())); - let thread_lock = lock.clone(); - let reader_thread = { - let _guard = lock.lock().unwrap(); - - // Create reader thread that will get the value of volume. Since we - // hold the lock currently, this will block until we release the lock. - let reader_thread = thread::spawn(move || { - state_struct.synchronized_state_read(|| { - let _guard = thread_lock.lock().unwrap(); - state_struct.volume.load() - }) - }); - - // Update volume and change update count so that the synchronized read - // will not return (odd update count means update in progress). - state.volume = 27; - state.update_count = 15; - - reader_thread - }; - - // The lock has been released, but the reader thread should still not - // terminate, because of the update in progress. - - // Yield thread to give reader_thread a chance to get scheduled. - thread::yield_now(); - { - let _guard = lock.lock().unwrap(); - - // Update volume and change update count to indicate the write has - // finished. - state.volume = 42; - state.update_count = 16; - } - - let read_value = reader_thread.join().unwrap(); - assert_eq!(read_value, 42); - } } diff --git a/cras/client/libcras/src/cras_shm_stream.rs b/cras/client/libcras/src/cras_shm_stream.rs deleted file mode 100644 index f72cc07c..00000000 --- a/cras/client/libcras/src/cras_shm_stream.rs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2019 The Chromium OS 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 std::time::Duration; -use std::{error, fmt}; - -use audio_streams::{ - shm_streams::{BufferSet, ServerRequest, ShmStream}, - BoxError, SampleFormat, StreamDirection, -}; -use cras_sys::gen::CRAS_AUDIO_MESSAGE_ID; -use sys_util::error; - -use crate::audio_socket::{AudioMessage, AudioSocket}; -use crate::cras_server_socket::CrasServerSocket; -use crate::cras_shm::{self, CrasAudioHeader, CrasAudioShmHeaderFd}; - -#[derive(Debug)] -pub enum Error { - MessageTypeError, - CaptureBufferTooSmall, -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::MessageTypeError => write!(f, "Message type error"), - Error::CaptureBufferTooSmall => write!( - f, - "Capture buffer too small, must have size at least 'used_size'." - ), - } - } -} - -/// An object that handles interactions with CRAS for a shm stream. -/// The object implements `ShmStream` and so can be used to wait for -/// `ServerRequest` and `BufferComplete` messages. -pub struct CrasShmStream<'a> { - stream_id: u32, - server_socket: CrasServerSocket, - audio_socket: AudioSocket, - direction: StreamDirection, - header: CrasAudioHeader<'a>, - frame_size: usize, - num_channels: usize, - frame_rate: u32, - // The index of the next buffer within SHM to set the buffer offset for. - next_buffer_idx: usize, -} - -impl<'a> CrasShmStream<'a> { - /// Attempt to creates a CrasShmStream with the given arguments. - /// - /// # Arguments - /// - /// * `stream_id` - The server's ID for the stream. - /// * `server_socket` - The socket that is connected to the server. - /// * `audio_socket` - The socket for audio request and audio available messages. - /// * `direction` - The direction of the stream, `Playback` or `Capture`. - /// * `num_channels` - The number of audio channels for the stream. - /// * `format` - The format to use for the stream's samples. - /// * `header_fd` - The file descriptor for the audio header shm area. - /// * `samples_len` - The size of the audio samples shm area. - /// - /// # Returns - /// - /// `CrasShmStream` - CRAS client stream. - /// - /// # Errors - /// - /// * If `header_fd` could not be successfully mmapped. - #[allow(clippy::too_many_arguments)] - pub fn try_new( - stream_id: u32, - server_socket: CrasServerSocket, - audio_socket: AudioSocket, - direction: StreamDirection, - num_channels: usize, - frame_rate: u32, - format: SampleFormat, - header_fd: CrasAudioShmHeaderFd, - samples_len: usize, - ) -> Result<Self, BoxError> { - let header = cras_shm::create_header(header_fd, samples_len)?; - Ok(Self { - stream_id, - server_socket, - audio_socket, - direction, - header, - frame_size: format.sample_bytes() * num_channels, - num_channels, - frame_rate, - // We have either sent zero or two offsets to the server, so we will - // need to update index 0 next. - next_buffer_idx: 0, - }) - } -} - -impl<'a> Drop for CrasShmStream<'a> { - /// Send the disconnect stream message and log an error if sending fails. - fn drop(&mut self) { - if let Err(e) = self.server_socket.disconnect_stream(self.stream_id) { - error!("CrasShmStream::drop error: {}", e); - } - } -} - -impl<'a> ShmStream for CrasShmStream<'a> { - fn frame_size(&self) -> usize { - self.frame_size - } - - fn num_channels(&self) -> usize { - self.num_channels - } - - fn frame_rate(&self) -> u32 { - self.frame_rate - } - - fn wait_for_next_action_with_timeout( - &mut self, - timeout: Duration, - ) -> Result<Option<ServerRequest>, BoxError> { - let expected_id = match self.direction { - StreamDirection::Playback => CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, - StreamDirection::Capture => CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY, - }; - - match self - .audio_socket - .read_audio_message_with_timeout(Some(timeout))? - { - Some(AudioMessage::Success { id, frames }) if id == expected_id => { - Ok(Some(ServerRequest::new(frames as usize, self))) - } - None => Ok(None), - _ => Err(Box::new(Error::MessageTypeError)), - } - } -} - -impl BufferSet for CrasShmStream<'_> { - fn callback(&mut self, offset: usize, frames: usize) -> Result<(), BoxError> { - self.header - .set_buffer_offset(self.next_buffer_idx, offset)?; - self.next_buffer_idx ^= 1; - let frames = frames as u32; - - match self.direction { - StreamDirection::Playback => { - self.header.commit_written_frames(frames)?; - - // Notify CRAS that we've made playback data available. - self.audio_socket.data_ready(frames)? - } - StreamDirection::Capture => { - let used_size = self.header.get_used_size(); - // Because CRAS doesn't know how long our buffer in shm is, we - // must make sure that there are always at least buffer_size - // frames available so that it doesn't write outside the buffer. - if frames < (used_size / self.frame_size) as u32 { - return Err(Box::new(Error::CaptureBufferTooSmall)); - } - - self.header.commit_read_frames(frames)?; - self.audio_socket.capture_ready(frames)?; - } - } - - Ok(()) - } - - fn ignore(&mut self) -> Result<(), BoxError> { - // We send an empty buffer for an ignored playback request since the - // server will not read from a 0-length buffer. We don't do anything for - // an ignored capture request, since we don't have a way to communicate - // buffer length to the server, and we don't want the server writing - // data to offsets within the SHM area that aren't audio buffers. - if self.direction == StreamDirection::Playback { - self.callback(0, 0)?; - } - - Ok(()) - } -} diff --git a/cras/client/libcras/src/cras_stream.rs b/cras/client/libcras/src/cras_stream.rs index f6004802..bd9520a1 100644 --- a/cras/client/libcras/src/cras_stream.rs +++ b/cras/client/libcras/src/cras_stream.rs @@ -4,13 +4,17 @@ use std::cmp::min; use std::io; use std::marker::PhantomData; +use std::mem; use std::{error, fmt}; use audio_streams::{ capture::{CaptureBuffer, CaptureBufferStream}, - BoxError, BufferDrop, PlaybackBuffer, PlaybackBufferStream, + BufferDrop, PlaybackBuffer, PlaybackBufferStream, +}; +use cras_sys::gen::{ + cras_disconnect_stream_message, cras_server_message, snd_pcm_format_t, CRAS_AUDIO_MESSAGE_ID, + CRAS_SERVER_MESSAGE_ID, CRAS_STREAM_DIRECTION, }; -use cras_sys::gen::{snd_pcm_format_t, CRAS_AUDIO_MESSAGE_ID, CRAS_STREAM_DIRECTION}; use sys_util::error; use crate::audio_socket::{AudioMessage, AudioSocket}; @@ -18,25 +22,38 @@ use crate::cras_server_socket::CrasServerSocket; use crate::cras_shm::*; #[derive(Debug)] -pub enum Error { +pub enum ErrorType { IoError(io::Error), MessageTypeError, + NoShmError, +} + +#[derive(Debug)] +pub struct Error { + error_type: ErrorType, +} + +impl Error { + fn new(error_type: ErrorType) -> Error { + Error { error_type } + } } impl error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::IoError(ref err) => err.fmt(f), - Error::MessageTypeError => write!(f, "Message type error"), + match self.error_type { + ErrorType::IoError(ref err) => err.fmt(f), + ErrorType::MessageTypeError => write!(f, "Message type error"), + ErrorType::NoShmError => write!(f, "Shared memory area is not created"), } } } impl From<io::Error> for Error { fn from(io_err: io::Error) -> Error { - Error::IoError(io_err) + Error::new(ErrorType::IoError(io_err)) } } @@ -44,23 +61,31 @@ impl From<io::Error> for Error { /// interacts with server's audio thread through `AudioSocket`. pub trait CrasStreamData<'a>: Send { // Creates `CrasStreamData` with only `AudioSocket`. - fn new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self; - fn header_mut(&mut self) -> &mut CrasAudioHeader<'a>; + fn new(audio_sock: AudioSocket) -> Self; + fn set_header(&mut self, header: CrasAudioHeader<'a>); + fn header_mut(&mut self) -> &mut Option<CrasAudioHeader<'a>>; fn audio_sock_mut(&mut self) -> &mut AudioSocket; } /// `CrasStreamData` implementation for `PlaybackBufferStream`. pub struct CrasPlaybackData<'a> { audio_sock: AudioSocket, - header: CrasAudioHeader<'a>, + header: Option<CrasAudioHeader<'a>>, } impl<'a> CrasStreamData<'a> for CrasPlaybackData<'a> { - fn new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self { - Self { audio_sock, header } + fn new(audio_sock: AudioSocket) -> Self { + Self { + audio_sock, + header: None, + } + } + + fn set_header(&mut self, header: CrasAudioHeader<'a>) { + self.header = Some(header); } - fn header_mut(&mut self) -> &mut CrasAudioHeader<'a> { + fn header_mut(&mut self) -> &mut Option<CrasAudioHeader<'a>> { &mut self.header } @@ -72,8 +97,10 @@ impl<'a> CrasStreamData<'a> for CrasPlaybackData<'a> { impl<'a> BufferDrop for CrasPlaybackData<'a> { fn trigger(&mut self, nframes: usize) { let log_err = |e| error!("BufferDrop error: {}", e); - if let Err(e) = self.header.commit_written_frames(nframes as u32) { - log_err(e); + if let Some(header) = &mut self.header { + if let Err(e) = header.commit_written_frames(nframes as u32) { + log_err(e); + } } if let Err(e) = self.audio_sock.data_ready(nframes as u32) { log_err(e); @@ -84,15 +111,22 @@ impl<'a> BufferDrop for CrasPlaybackData<'a> { /// `CrasStreamData` implementation for `CaptureBufferStream`. pub struct CrasCaptureData<'a> { audio_sock: AudioSocket, - header: CrasAudioHeader<'a>, + header: Option<CrasAudioHeader<'a>>, } impl<'a> CrasStreamData<'a> for CrasCaptureData<'a> { - fn new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self { - Self { audio_sock, header } + fn new(audio_sock: AudioSocket) -> Self { + Self { + audio_sock, + header: None, + } } - fn header_mut(&mut self) -> &mut CrasAudioHeader<'a> { + fn set_header(&mut self, header: CrasAudioHeader<'a>) { + self.header = Some(header); + } + + fn header_mut(&mut self) -> &mut Option<CrasAudioHeader<'a>> { &mut self.header } @@ -104,8 +138,10 @@ impl<'a> CrasStreamData<'a> for CrasCaptureData<'a> { impl<'a> BufferDrop for CrasCaptureData<'a> { fn trigger(&mut self, nframes: usize) { let log_err = |e| error!("BufferDrop error: {}", e); - if let Err(e) = self.header.commit_read_frames(nframes as u32) { - log_err(e); + if let Some(header) = &mut self.header { + if let Err(e) = header.commit_read_frames(nframes as u32) { + log_err(e); + } } if let Err(e) = self.audio_sock.capture_ready(nframes as u32) { log_err(e); @@ -119,14 +155,14 @@ pub struct CrasStream<'a, T: CrasStreamData<'a> + BufferDrop> { server_socket: CrasServerSocket, block_size: u32, direction: CRAS_STREAM_DIRECTION, - rate: u32, + rate: usize, num_channels: usize, format: snd_pcm_format_t, /// A structure for stream to interact with server audio thread. controls: T, /// The `PhantomData` is used by `controls: T` phantom: PhantomData<CrasAudioHeader<'a>>, - audio_buffer: CrasAudioBuffer, + audio_buffer: Option<CrasAudioBuffer>, } impl<'a, T: CrasStreamData<'a> + BufferDrop> CrasStream<'a, T> { @@ -134,22 +170,17 @@ impl<'a, T: CrasStreamData<'a> + BufferDrop> CrasStream<'a, T> { /// /// # Returns /// `CrasStream` - CRAS client stream. - #[allow(clippy::too_many_arguments)] - pub fn try_new( + pub fn new( stream_id: u32, server_socket: CrasServerSocket, block_size: u32, direction: CRAS_STREAM_DIRECTION, - rate: u32, + rate: usize, num_channels: usize, format: snd_pcm_format_t, audio_sock: AudioSocket, - header_fd: CrasAudioShmHeaderFd, - samples_fd: CrasShmFd, - ) -> Result<Self, Error> { - let (header, audio_buffer) = create_header_and_buffers(header_fd, samples_fd)?; - - Ok(Self { + ) -> Self { + Self { stream_id, server_socket, block_size, @@ -157,29 +188,41 @@ impl<'a, T: CrasStreamData<'a> + BufferDrop> CrasStream<'a, T> { rate, num_channels, format, - controls: T::new(audio_sock, header), + controls: T::new(audio_sock), phantom: PhantomData, - audio_buffer, - }) + audio_buffer: None, + } + } + + /// Receives shared memory fd and initialize stream audio shared memory area + pub fn init_shm( + &mut self, + header_fd: CrasAudioShmHeaderFd, + samples_fd: CrasShmFd, + ) -> Result<(), Error> { + let (header, buffer) = create_header_and_buffers(header_fd, samples_fd)?; + self.controls.set_header(header); + self.audio_buffer = Some(buffer); + Ok(()) } fn wait_request_data(&mut self) -> Result<(), Error> { match self.controls.audio_sock_mut().read_audio_message()? { - AudioMessage::Success { - id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, - .. - } => Ok(()), - _ => Err(Error::MessageTypeError), + AudioMessage::Success { id, .. } => match id { + CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA => Ok(()), + _ => Err(Error::new(ErrorType::MessageTypeError)), + }, + _ => Err(Error::new(ErrorType::MessageTypeError)), } } fn wait_data_ready(&mut self) -> Result<u32, Error> { match self.controls.audio_sock_mut().read_audio_message()? { - AudioMessage::Success { - id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY, - frames, - } => Ok(frames), - _ => Err(Error::MessageTypeError), + AudioMessage::Success { id, frames } => match id { + CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY => Ok(frames), + _ => Err(Error::new(ErrorType::MessageTypeError)), + }, + _ => Err(Error::new(ErrorType::MessageTypeError)), } } } @@ -189,36 +232,57 @@ impl<'a, T: CrasStreamData<'a> + BufferDrop> Drop for CrasStream<'a, T> { /// the return message. /// Logs an error message to stderr if the method fails. fn drop(&mut self) { - if let Err(e) = self.server_socket.disconnect_stream(self.stream_id) { + // Send stream disconnect message + let msg_header = cras_server_message { + length: mem::size_of::<cras_disconnect_stream_message>() as u32, + id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_DISCONNECT_STREAM, + }; + let server_cmsg = cras_disconnect_stream_message { + header: msg_header, + stream_id: self.stream_id, + }; + if let Err(e) = self + .server_socket + .send_server_message_with_fds(&server_cmsg, &[]) + { error!("CrasStream::Drop error: {}", e); } } } impl<'a, T: CrasStreamData<'a> + BufferDrop> PlaybackBufferStream for CrasStream<'a, T> { - fn next_playback_buffer(&mut self) -> Result<PlaybackBuffer, BoxError> { + fn next_playback_buffer(&mut self) -> Result<PlaybackBuffer, Box<dyn error::Error>> { // Wait for request audio message self.wait_request_data()?; - let header = self.controls.header_mut(); - let frame_size = header.get_frame_size(); - let (offset, len) = header.get_write_offset_and_len()?; - let buf = &mut self.audio_buffer.get_buffer()[offset..offset + len]; - + let (frame_size, (offset, len)) = match self.controls.header_mut() { + None => return Err(Error::new(ErrorType::NoShmError).into()), + Some(header) => (header.get_frame_size(), header.get_write_offset_and_len()?), + }; + let buf = match self.audio_buffer.as_mut() { + None => return Err(Error::new(ErrorType::NoShmError).into()), + Some(audio_buffer) => &mut audio_buffer.get_buffer()[offset..offset + len], + }; PlaybackBuffer::new(frame_size, buf, &mut self.controls).map_err(Box::from) } } impl<'a, T: CrasStreamData<'a> + BufferDrop> CaptureBufferStream for CrasStream<'a, T> { - fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, BoxError> { + fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, Box<dyn error::Error>> { // Wait for data ready message let frames = self.wait_data_ready()?; - let header = self.controls.header_mut(); - let frame_size = header.get_frame_size(); - let shm_frames = header.get_readable_frames()?; + let (frame_size, shm_frames, offset) = match self.controls.header_mut() { + None => return Err(Error::new(ErrorType::NoShmError).into()), + Some(header) => ( + header.get_frame_size(), + header.get_readable_frames()?, + header.get_read_buffer_offset()?, + ), + }; let len = min(shm_frames, frames as usize) * frame_size; - let offset = header.get_read_buffer_offset()?; - let buf = &mut self.audio_buffer.get_buffer()[offset..offset + len]; - + let buf = match self.audio_buffer.as_mut() { + None => return Err(Error::new(ErrorType::NoShmError).into()), + Some(audio_buffer) => &mut audio_buffer.get_buffer()[offset..offset + len], + }; CaptureBuffer::new(frame_size, buf, &mut self.controls).map_err(Box::from) } } diff --git a/cras/client/libcras/src/libcras.rs b/cras/client/libcras/src/libcras.rs index 402a4a27..c81e540d 100644 --- a/cras/client/libcras/src/libcras.rs +++ b/cras/client/libcras/src/libcras.rs @@ -23,15 +23,14 @@ //! use std::fs::File; //! use std::io::{Read, Write}; //! use std::thread::{spawn, JoinHandle}; -//! type Result<T> = std::result::Result<T, BoxError>; +//! type Result<T> = std::result::Result<T, Box<std::error::Error>>; //! -//! use libcras::{BoxError, CrasClient, CrasClientType}; -//! use audio_streams::{SampleFormat, StreamSource}; +//! use libcras::{CrasClient, CrasClientType}; +//! use audio_streams::StreamSource; //! //! const BUFFER_SIZE: usize = 256; -//! const FRAME_RATE: u32 = 44100; +//! const FRAME_RATE: usize = 44100; //! const NUM_CHANNELS: usize = 2; -//! const FORMAT: SampleFormat = SampleFormat::S16LE; //! //! # fn main() -> Result<()> { //! # let args: Vec<String> = env::args().collect(); @@ -40,7 +39,7 @@ //! let mut cras_client = CrasClient::new()?; //! cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST); //! let (_control, mut stream) = cras_client -//! .new_playback_stream(NUM_CHANNELS, FORMAT, FRAME_RATE, BUFFER_SIZE)?; +//! .new_playback_stream(NUM_CHANNELS, FRAME_RATE, BUFFER_SIZE)?; //! //! // Plays 1000 * BUFFER_SIZE samples from the given file //! let mut file = File::open(&args[1])?; @@ -76,15 +75,14 @@ //! use std::fs::File; //! use std::io::{Read, Write}; //! use std::thread::{spawn, JoinHandle}; -//! type Result<T> = std::result::Result<T, BoxError>; +//! type Result<T> = std::result::Result<T, Box<std::error::Error>>; //! -//! use libcras::{BoxError, CrasClient, CrasClientType}; -//! use audio_streams::{SampleFormat, StreamSource}; +//! use libcras::{CrasClient, CrasClientType}; +//! use audio_streams::StreamSource; //! //! const BUFFER_SIZE: usize = 256; -//! const FRAME_RATE: u32 = 44100; +//! const FRAME_RATE: usize = 44100; //! const NUM_CHANNELS: usize = 2; -//! const FORMAT: SampleFormat = SampleFormat::S16LE; //! //! # fn main() -> Result<()> { //! # let args: Vec<String> = env::args().collect(); @@ -93,7 +91,7 @@ //! let mut cras_client = CrasClient::new()?; //! cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST); //! let (_control, mut stream) = cras_client -//! .new_capture_stream(NUM_CHANNELS, FORMAT, FRAME_RATE, BUFFER_SIZE)?; +//! .new_capture_stream(NUM_CHANNELS, FRAME_RATE, BUFFER_SIZE)?; //! //! // Capture 1000 * BUFFER_SIZE samples to the given file //! let mut file = File::create(&args[1])?; @@ -124,58 +122,56 @@ use std::os::unix::{ }; use std::{error, fmt}; -pub use audio_streams::BoxError; use audio_streams::{ - capture::{CaptureBufferStream, NoopCaptureStream}, - shm_streams::{NullShmStream, ShmStream, ShmStreamSource}, - BufferDrop, NoopStreamControl, PlaybackBufferStream, SampleFormat, StreamControl, - StreamDirection, StreamEffect, StreamSource, + capture::{CaptureBufferStream, DummyCaptureStream}, + BufferDrop, DummyStreamControl, PlaybackBufferStream, StreamControl, StreamSource, }; +pub use cras_sys::gen::CRAS_CLIENT_TYPE as CrasClientType; use cras_sys::gen::*; -pub use cras_sys::gen::{ - CRAS_CLIENT_TYPE as CrasClientType, CRAS_NODE_TYPE as CrasNodeType, - CRAS_STREAM_EFFECT as CrasStreamEffect, -}; -pub use cras_sys::{AudioDebugInfo, CrasIodevInfo, CrasIonodeInfo, Error as CrasSysError}; -use sys_util::{PollContext, PollToken, SharedMemory}; +use sys_util::{PollContext, PollToken}; mod audio_socket; use crate::audio_socket::AudioSocket; mod cras_server_socket; use crate::cras_server_socket::CrasServerSocket; -pub use crate::cras_server_socket::CrasSocketType; mod cras_shm; -use crate::cras_shm::CrasServerState; -pub mod cras_shm_stream; -use crate::cras_shm_stream::CrasShmStream; mod cras_stream; use crate::cras_stream::{CrasCaptureData, CrasPlaybackData, CrasStream, CrasStreamData}; mod cras_client_message; use crate::cras_client_message::*; #[derive(Debug)] -pub enum Error { +pub enum ErrorType { CrasClientMessageError(cras_client_message::Error), CrasStreamError(cras_stream::Error), - CrasSysError(cras_sys::Error), IoError(io::Error), SysUtilError(sys_util::Error), MessageTypeError, UnexpectedExit, } +#[derive(Debug)] +pub struct Error { + error_type: ErrorType, +} + +impl Error { + fn new(error_type: ErrorType) -> Self { + Self { error_type } + } +} + impl error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::CrasClientMessageError(ref err) => err.fmt(f), - Error::CrasStreamError(ref err) => err.fmt(f), - Error::CrasSysError(ref err) => err.fmt(f), - Error::IoError(ref err) => err.fmt(f), - Error::SysUtilError(ref err) => err.fmt(f), - Error::MessageTypeError => write!(f, "Message type error"), - Error::UnexpectedExit => write!(f, "Unexpected exit"), + match self.error_type { + ErrorType::CrasClientMessageError(ref err) => err.fmt(f), + ErrorType::CrasStreamError(ref err) => err.fmt(f), + ErrorType::IoError(ref err) => err.fmt(f), + ErrorType::SysUtilError(ref err) => err.fmt(f), + ErrorType::MessageTypeError => write!(f, "Message type error"), + ErrorType::UnexpectedExit => write!(f, "Unexpected exit"), } } } @@ -184,40 +180,39 @@ type Result<T> = std::result::Result<T, Error>; impl From<io::Error> for Error { fn from(io_err: io::Error) -> Self { - Error::IoError(io_err) + Self::new(ErrorType::IoError(io_err)) } } impl From<sys_util::Error> for Error { fn from(sys_util_err: sys_util::Error) -> Self { - Error::SysUtilError(sys_util_err) + Self::new(ErrorType::SysUtilError(sys_util_err)) } } impl From<cras_stream::Error> for Error { fn from(err: cras_stream::Error) -> Self { - Error::CrasStreamError(err) + Self::new(ErrorType::CrasStreamError(err)) } } impl From<cras_client_message::Error> for Error { fn from(err: cras_client_message::Error) -> Self { - Error::CrasClientMessageError(err) + Self::new(ErrorType::CrasClientMessageError(err)) } } -/// A CRAS server client, which implements StreamSource and ShmStreamSource. -/// It can create audio streams connecting to CRAS server. -pub struct CrasClient<'a> { +/// A CRAS server client, which implements StreamSource. It can create audio streams connecting +/// to CRAS server. +pub struct CrasClient { server_socket: CrasServerSocket, - server_state: CrasServerState<'a>, client_id: u32, next_stream_id: u32, cras_capture: bool, client_type: CRAS_CLIENT_TYPE, } -impl<'a> CrasClient<'a> { +impl CrasClient { /// Blocks creating a `CrasClient` with registered `client_id` /// /// # Results @@ -229,33 +224,26 @@ impl<'a> CrasClient<'a> { /// Returns error if error occurs while handling server message or message /// type is incorrect pub fn new() -> Result<Self> { - Self::with_type(CrasSocketType::Legacy) - } - - /// Tries to create a `CrasClient` with a given `CrasSocketType`. - /// - /// # Errors - /// - /// Returns error if error occurs while handling server message or message - /// type is incorrect. - pub fn with_type(socket_type: CrasSocketType) -> Result<Self> { // Create a connection to the server. - let mut server_socket = CrasServerSocket::with_type(socket_type)?; - // Gets client ID and server state fd from server - if let ServerResult::Connected(client_id, server_state_fd) = - CrasClient::wait_for_message(&mut server_socket)? - { - Ok(Self { - server_socket, - server_state: CrasServerState::try_new(server_state_fd)?, - client_id, - next_stream_id: 0, - cras_capture: false, - client_type: CRAS_CLIENT_TYPE::CRAS_CLIENT_TYPE_UNKNOWN, - }) - } else { - Err(Error::MessageTypeError) - } + let mut server_socket = CrasServerSocket::new()?; + + // Gets client ID from server + let client_id = { + match CrasClient::wait_for_message(&mut server_socket)? { + ServerResult::Connected(res, _server_state_fd) => res as u32, + _ => { + return Err(Error::new(ErrorType::MessageTypeError)); + } + } + }; + + Ok(Self { + server_socket, + client_id, + next_stream_id: 0, + cras_capture: false, + client_type: CRAS_CLIENT_TYPE::CRAS_CLIENT_TYPE_UNKNOWN, + }) } /// Enables capturing audio through CRAS server. @@ -268,143 +256,31 @@ impl<'a> CrasClient<'a> { self.client_type = client_type; } - /// Sets the system volume to `volume`. - /// - /// Send a message to the server to request setting the system volume - /// to `volume`. No response is returned from the server. - /// - /// # Errors - /// - /// If writing the message to the server socket failed. - pub fn set_system_volume(&mut self, volume: u32) -> Result<()> { - let header = cras_server_message { - length: mem::size_of::<cras_set_system_volume>() as u32, - id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_SET_SYSTEM_VOLUME, - }; - let msg = cras_set_system_volume { header, volume }; - - self.server_socket.send_server_message_with_fds(&msg, &[])?; - Ok(()) - } - - /// Sets the system mute status to `mute`. - /// - /// Send a message to the server to request setting the system mute - /// to `mute`. No response is returned from the server. - /// - /// # Errors - /// - /// If writing the message to the server socket failed. - pub fn set_system_mute(&mut self, mute: bool) -> Result<()> { - let header = cras_server_message { - length: mem::size_of::<cras_set_system_mute>() as u32, - id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_SET_SYSTEM_MUTE, - }; - let msg = cras_set_system_mute { - header, - mute: mute as i32, - }; - - self.server_socket.send_server_message_with_fds(&msg, &[])?; - Ok(()) - } - - /// Gets the system volume. - /// - /// Read the current value for system volume from the server shared memory. - pub fn get_system_volume(&self) -> u32 { - self.server_state.get_system_volume() - } - - /// Gets the system mute. - /// - /// Read the current value for system mute from the server shared memory. - pub fn get_system_mute(&self) -> bool { - self.server_state.get_system_mute() - } - - /// Gets a list of output devices - /// - /// Read a list of the currently attached output devices from the server shared memory. - pub fn output_devices(&self) -> impl Iterator<Item = CrasIodevInfo> { - self.server_state.output_devices() - } - - /// Gets a list of input devices - /// - /// Read a list of the currently attached input devices from the server shared memory. - pub fn input_devices(&self) -> impl Iterator<Item = CrasIodevInfo> { - self.server_state.input_devices() - } - - /// Gets a list of output nodes - /// - /// Read a list of the currently attached output nodes from the server shared memory. - pub fn output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> { - self.server_state.output_nodes() - } - - /// Gets a list of input nodes - /// - /// Read a list of the currently attached input nodes from the server shared memory. - pub fn input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> { - self.server_state.input_nodes() - } - - /// Gets the server's audio debug info. - /// - /// Sends a message to the server requesting an update of audio debug info, - /// waits for the response, and then reads the info from the server state. - /// - /// # Errors - /// - /// * If sending the message to the server failed. - /// * If an unexpected response message is received. - pub fn get_audio_debug_info(&mut self) -> Result<AudioDebugInfo> { - let header = cras_server_message { - length: mem::size_of::<cras_dump_audio_thread>() as u32, - id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_DUMP_AUDIO_THREAD, - }; - let msg = cras_dump_audio_thread { header }; - - self.server_socket.send_server_message_with_fds(&msg, &[])?; - - match CrasClient::wait_for_message(&mut self.server_socket)? { - ServerResult::DebugInfoReady => Ok(self - .server_state - .get_audio_debug_info() - .map_err(Error::CrasSysError)?), - _ => Err(Error::MessageTypeError), - } - } - // Gets next server_stream_id from client and increment stream_id counter. - fn next_server_stream_id(&mut self) -> u32 { + fn next_server_stream_id(&mut self) -> Result<u32> { let res = self.next_stream_id; self.next_stream_id += 1; - self.server_stream_id(res) + self.server_stream_id(&res) } // Gets server_stream_id from given stream_id - fn server_stream_id(&self, stream_id: u32) -> u32 { - (self.client_id << 16) | stream_id + fn server_stream_id(&self, stream_id: &u32) -> Result<u32> { + Ok((self.client_id << 16) | stream_id) } // Creates general stream with given parameters - fn create_stream<'b, T: BufferDrop + CrasStreamData<'b>>( + fn create_stream<'a, T: BufferDrop + CrasStreamData<'a>>( &mut self, - device_index: Option<u32>, block_size: u32, direction: CRAS_STREAM_DIRECTION, - rate: u32, + rate: usize, channel_num: usize, - format: SampleFormat, - ) -> Result<CrasStream<'b, T>> { - let stream_id = self.next_server_stream_id(); + format: snd_pcm_format_t, + ) -> Result<CrasStream<'a, T>> { + let stream_id = self.next_server_stream_id()?; // Prepares server message - let audio_format = - cras_audio_format_packed::new(format.into(), rate, channel_num, direction); + let audio_format = cras_audio_format_packed::new(format, rate, channel_num); let msg_header = cras_server_message { length: mem::size_of::<cras_connect_message>() as u32, id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM, @@ -419,11 +295,10 @@ impl<'a> CrasClient<'a> { cb_threshold: block_size, flags: 0, format: audio_format, - dev_idx: device_index.unwrap_or(CRAS_SPECIAL_DEVICE::NO_DEVICE as u32), + dev_idx: CRAS_SPECIAL_DEVICE::NO_DEVICE as u32, effects: 0, client_type: self.client_type, client_shm_size: 0, - buffer_offsets: [0, 0], }; // Creates AudioSocket pair @@ -435,90 +310,26 @@ impl<'a> CrasClient<'a> { .send_server_message_with_fds(&server_cmsg, &socks)?; let audio_socket = AudioSocket::new(sock1); + let mut stream = CrasStream::new( + stream_id, + self.server_socket.try_clone()?, + block_size, + direction, + rate, + channel_num, + format, + audio_socket, + ); + loop { let result = CrasClient::wait_for_message(&mut self.server_socket)?; if let ServerResult::StreamConnected(_stream_id, header_fd, samples_fd) = result { - return CrasStream::try_new( - stream_id, - self.server_socket.try_clone()?, - block_size, - direction, - rate, - channel_num, - format.into(), - audio_socket, - header_fd, - samples_fd, - ) - .map_err(Error::CrasStreamError); + stream.init_shm(header_fd, samples_fd)?; + break; } } - } - /// Creates a new playback stream pinned to the device at `device_index`. - /// - /// # Arguments - /// - /// * `device_index` - The device to which the stream will be attached. - /// * `num_channels` - The count of audio channels for the stream. - /// * `format` - The format to use for stream audio samples. - /// * `frame_rate` - The sample rate of the stream. - /// * `buffer_size` - The transfer size granularity in frames. - #[allow(clippy::type_complexity)] - pub fn new_pinned_playback_stream( - &mut self, - device_index: u32, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> - { - Ok(( - Box::new(NoopStreamControl::new()), - Box::new(self.create_stream::<CrasPlaybackData>( - Some(device_index), - buffer_size as u32, - CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT, - frame_rate, - num_channels, - format, - )?), - )) - } - - /// Creates a new capture stream pinned to the device at `device_index`. - /// - /// This is useful for, among other things, capturing from a loopback - /// device. - /// - /// # Arguments - /// - /// * `device_index` - The device to which the stream will be attached. - /// * `num_channels` - The count of audio channels for the stream. - /// * `format` - The format to use for stream audio samples. - /// * `frame_rate` - The sample rate of the stream. - /// * `buffer_size` - The transfer size granularity in frames. - #[allow(clippy::type_complexity)] - pub fn new_pinned_capture_stream( - &mut self, - device_index: u32, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError> { - Ok(( - Box::new(NoopStreamControl::new()), - Box::new(self.create_stream::<CrasCaptureData>( - Some(device_index), - buffer_size as u32, - CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT, - frame_rate, - num_channels, - format, - )?), - )) + Ok(stream) } // Blocks handling the first server message received from `socket`. @@ -535,7 +346,7 @@ impl<'a> CrasClient<'a> { let tokens: Vec<Token> = events.iter_readable().map(|e| e.token()).collect(); tokens .get(0) - .ok_or(Error::UnexpectedExit) + .ok_or_else(|| Error::new(ErrorType::UnexpectedExit)) .and_then(|ref token| { match token { Token::ServerMsg => ServerResult::handle_server_message(socket), @@ -543,63 +354,55 @@ impl<'a> CrasClient<'a> { .map_err(Into::into) }) } - - /// Returns any open file descriptors needed by CrasClient. - /// This function is shared between StreamSource and ShmStreamSource. - fn keep_fds(&self) -> Vec<RawFd> { - vec![self.server_socket.as_raw_fd()] - } } -impl<'a> StreamSource for CrasClient<'a> { - #[allow(clippy::type_complexity)] +impl StreamSource for CrasClient { fn new_playback_stream( &mut self, num_channels: usize, - format: SampleFormat, - frame_rate: u32, + frame_rate: usize, buffer_size: usize, - ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> - { + ) -> std::result::Result< + (Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), + Box<dyn error::Error>, + > { Ok(( - Box::new(NoopStreamControl::new()), + Box::new(DummyStreamControl::new()), Box::new(self.create_stream::<CrasPlaybackData>( - None, buffer_size as u32, CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT, frame_rate, num_channels, - format, + _snd_pcm_format::SND_PCM_FORMAT_S16_LE, )?), )) } - #[allow(clippy::type_complexity)] fn new_capture_stream( &mut self, num_channels: usize, - format: SampleFormat, - frame_rate: u32, + frame_rate: usize, buffer_size: usize, - ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError> { + ) -> std::result::Result< + (Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), + Box<dyn error::Error>, + > { if self.cras_capture { Ok(( - Box::new(NoopStreamControl::new()), + Box::new(DummyStreamControl::new()), Box::new(self.create_stream::<CrasCaptureData>( - None, buffer_size as u32, CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT, frame_rate, num_channels, - format, + _snd_pcm_format::SND_PCM_FORMAT_S16_LE, )?), )) } else { Ok(( - Box::new(NoopStreamControl::new()), - Box::new(NoopCaptureStream::new( + Box::new(DummyStreamControl::new()), + Box::new(DummyCaptureStream::new( num_channels, - format, frame_rate, buffer_size, )), @@ -608,92 +411,6 @@ impl<'a> StreamSource for CrasClient<'a> { } fn keep_fds(&self) -> Option<Vec<RawFd>> { - Some(CrasClient::keep_fds(self)) - } -} - -impl<'a> ShmStreamSource for CrasClient<'a> { - fn new_stream( - &mut self, - direction: StreamDirection, - num_channels: usize, - format: SampleFormat, - frame_rate: u32, - buffer_size: usize, - effects: &[StreamEffect], - client_shm: &SharedMemory, - buffer_offsets: [u64; 2], - ) -> std::result::Result<Box<dyn ShmStream>, BoxError> { - if direction == StreamDirection::Capture && !self.cras_capture { - return Ok(Box::new(NullShmStream::new( - buffer_size, - num_channels, - format, - frame_rate, - ))); - } - - let buffer_size = buffer_size as u32; - - // Prepares server message - let stream_id = self.next_server_stream_id(); - let audio_format = cras_audio_format_packed::new( - format.into(), - frame_rate, - num_channels, - direction.into(), - ); - let msg_header = cras_server_message { - length: mem::size_of::<cras_connect_message>() as u32, - id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM, - }; - - let server_cmsg = cras_connect_message { - header: msg_header, - proto_version: CRAS_PROTO_VER, - direction: direction.into(), - stream_id, - stream_type: CRAS_STREAM_TYPE::CRAS_STREAM_TYPE_DEFAULT, - buffer_frames: buffer_size, - cb_threshold: buffer_size, - flags: 0, - format: audio_format, - dev_idx: CRAS_SPECIAL_DEVICE::NO_DEVICE as u32, - effects: effects.iter().collect::<CrasStreamEffect>().into(), - client_type: self.client_type, - client_shm_size: client_shm.size(), - buffer_offsets, - }; - - // Creates AudioSocket pair - let (sock1, sock2) = UnixStream::pair()?; - - // Sends `CRAS_SERVER_CONNECT_STREAM` message - let fds = [sock2.as_raw_fd(), client_shm.as_raw_fd()]; - self.server_socket - .send_server_message_with_fds(&server_cmsg, &fds)?; - - loop { - let result = CrasClient::wait_for_message(&mut self.server_socket)?; - if let ServerResult::StreamConnected(_stream_id, header_fd, _samples_fd) = result { - let audio_socket = AudioSocket::new(sock1); - let stream = CrasShmStream::try_new( - stream_id, - self.server_socket.try_clone()?, - audio_socket, - direction, - num_channels, - frame_rate, - format, - header_fd, - client_shm.size() as usize, - )?; - return Ok(Box::new(stream)); - } - } - } - - fn keep_fds(&self) -> Vec<RawFd> { - CrasClient::keep_fds(self) + Some(vec![self.server_socket.as_raw_fd()]) } } diff --git a/cras/configure.ac b/cras/configure.ac index f39a14a6..f00011c9 100644 --- a/cras/configure.ac +++ b/cras/configure.ac @@ -10,9 +10,6 @@ AC_CANONICAL_HOST AM_INIT_AUTOMAKE([1.10 -Wall no-define]) #AC_CONFIG_HEADERS([config.h]) -# To compile with full logs, use V=1 with make instead. -AM_SILENT_RULES([yes]) - m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AC_PROG_LIBTOOL AC_PROG_CC @@ -26,8 +23,6 @@ AC_CONFIG_FILES([Makefile src/Makefile libcras.pc]) PKG_CHECK_MODULES([LIBSPEEX], [ speexdsp >= 1.2 ]) PKG_CHECK_MODULES([ASOUNDLIB], [ alsa >= 1.1.0 ]) -AC_CHECK_HEADERS([iniparser/iniparser.h]) - AC_ARG_ENABLE([dbus], AS_HELP_STRING([--disable-dbus], [Disable all DBUS uses]), have_dbus=$enableval, have_dbus=yes) AM_CONDITIONAL(HAVE_DBUS, test "$have_dbus" = "yes") if test "$have_dbus" = "yes"; then @@ -53,7 +48,7 @@ AC_SUBST(SELINUX_CFLAGS) AC_SUBST(SELINUX_LIBS) # WEBRTC APM support -AC_ARG_ENABLE([webrtc-apm], AS_HELP_STRING([--enable-webrtc-apm], [Enable webrtc-apm uses]), have_webrtc_apm=$enableval, have_webrtc_apm=no) +AC_ARG_ENABLE([webrtc-apm], AS_HELP_STRING([--disable-webrtc-apm], [Disable webrtc-apm uses]), have_webrtc_apm=$enableval, have_webrtc_apm=yes) AM_CONDITIONAL(HAVE_WEBRTC_APM, test "$have_webrtc_apm" = "yes") if test "$have_webrtc_apm" = "yes"; then PKG_CHECK_MODULES([WEBRTC_APM], [ libwebrtc_apm ]) @@ -63,23 +58,7 @@ else fi AC_SUBST(WEBRTC_APM_LIBS) -# Build fuzzer binaries -AC_ARG_ENABLE([fuzzer], AS_HELP_STRING([--enable-fuzzer], [Enable fuzzer build]), have_fuzzer=$enableval, have_fuzzer=no) -AM_CONDITIONAL(HAVE_FUZZER, test "$have_fuzzer" = "yes") -if test "$have_fuzzer" = "yes"; then - AC_DEFINE(HAVE_FUZZER, 1, [Define to build fuzzers.]) -fi - PKG_CHECK_MODULES([SBC], [ sbc >= 1.0 ]) -AC_CHECK_HEADERS([iniparser/iniparser.h iniparser.h], [FOUND_INIPARSER=1;break]) -test [$FOUND_INIPARSER] || AC_MSG_ERROR([Missing iniparser, please install.]) -AC_SEARCH_LIBS([LADSPA], [ladspa-sdk], [], [ - AC_CHECK_HEADERS([ladspa.h], [], [ - AC_MSG_ERROR([Missing ladspa-sdk, please install.]) - ]) -]) -PKG_CHECK_MODULES([UDEV], [ libudev >= 1.0 ]) -PKG_CHECK_MODULES([GTEST], [ gtest >= 1.0 ]) AC_CHECK_LIB(asound, snd_pcm_ioplug_create,, AC_ERROR([*** libasound has no external plugin SDK]), -ldl) @@ -89,29 +68,12 @@ AC_ARG_ENABLE([alsa-plugin], AS_HELP_STRING([--disable-alsa-plugin], AC_ARG_ENABLE([metrics], AS_HELP_STRING([--enable-metrics], [Enable metrics uses]), have_metrics=$enableval, have_metrics=no) if test "$have_metrics" = "yes"; then AC_DEFINE(HAVE_LIB_METRICS, 1, [Define to use libmetrics]) - METRICS_LIBS=-lmetrics + METRICS_LIBS=-lmetrics-${BASE_VER} else METRICS_LIBS= fi AC_SUBST(METRICS_LIBS) -# Check if the system copy of the cras rust library should be used. If not, make sure cargo and rustc are present to build it. -AC_ARG_WITH([system-cras-rust], - AS_HELP_STRING([--with-system-cras-rust], [Use the system provided cras_rust library]), - with_system_rust=$enableval, - with_system_rust=no) -AM_CONDITIONAL(WITH_SYSTEM_RUST, test "$with_system_rust" = "yes") -if test "$with_system_rust" = "no"; then - AC_CHECK_PROG(CARGO, [cargo], [yes], [no]) - AS_IF(test x$CARGO = xno, - AC_MSG_ERROR([cargo is required to build cras rust lib.]) - ) - AC_CHECK_PROG(RUSTC, [rustc], [yes], [no]) - AS_IF(test x$RUSTC = xno, - AC_MSG_ERROR([rustc is required to build cras rust lib.]) - ) -fi - # Determine ALSA plugin directory. test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix=$prefix diff --git a/cras/install_deps.sh b/cras/install_deps.sh deleted file mode 100755 index 6eac01a6..00000000 --- a/cras/install_deps.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh -apt-get install -y \ - automake \ - build-essential \ - cmake \ - g++ \ - gdb \ - git \ - ladspa-sdk \ - libasound-dev \ - libdbus-1-dev \ - libncurses5-dev \ - libsbc-dev \ - libsndfile-dev \ - libspeexdsp-dev \ - libtool \ - libudev-dev \ - wget \ - zip -cd /tmp -git clone https://github.com/ndevilla/iniparser.git -cd iniparser -make -cp libiniparser.* /usr/local/lib -cp src/dictionary.h src/iniparser.h /usr/local/include -chmod 644 /usr/local/include/dictionary.h /usr/local/include/iniparser.h -chmod 644 /usr/local/lib/libiniparser.a -chmod 755 /usr/local/lib/libiniparser.so.* - -cd /tmp -git clone https://github.com/google/googletest.git -b v1.8.x -cd googletest -mkdir build -cd build -cmake .. -DBUILD_SHARED_LIBS=ON \ - -DINSTALL_GTEST=ON \ - -DCMAKE_INSTALL_PREFIX:PATH=/usr -make -make install - -# Need to build and install alsa so there is a static lib. -mkdir -p /tmp/alsa-build && - cd /tmp/alsa-build && \ - wget ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.1.4.1.tar.bz2 && \ - bzip2 -f -d alsa-lib-* && \ - tar xf alsa-lib-* && \ - cd alsa-lib-* && \ - ./configure --enable-static --disable-shared && \ - make clean && \ - make -j$(nproc) all && \ - make install diff --git a/cras/src/Android.bp b/cras/src/Android.bp index 17b9919a..070e6cae 100644 --- a/cras/src/Android.bp +++ b/cras/src/Android.bp @@ -1,13 +1,3 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "external_adhd_license" - // to get the below license kinds: - // SPDX-license-identifier-BSD - // SPDX-license-identifier-LGPL - default_applicable_licenses: ["external_adhd_license"], -} - cc_library_static { name: "libcras", diff --git a/cras/src/Makefile.am b/cras/src/Makefile.am index 1e89f811..acc62d4a 100644 --- a/cras/src/Makefile.am +++ b/cras/src/Makefile.am @@ -41,12 +41,10 @@ COMMON_CPPFLAGS = -O2 -Wall -Werror -Wno-error=cpp COMMON_SIMD_CPPFLAGS = -O3 -Wall -Werror -Wno-error=cpp bin_PROGRAMS = cras cras_test_client cras_monitor cras_router -noinst_PROGRAMS = if HAVE_DBUS CRAS_DBUS_SOURCES = \ common/cras_sbc_codec.c \ - common/packet_status_logger.c \ server/cras_bt_manager.c \ server/cras_bt_adapter.c \ server/cras_bt_device.c \ @@ -55,7 +53,6 @@ CRAS_DBUS_SOURCES = \ server/cras_bt_player.c \ server/cras_bt_io.c \ server/cras_bt_profile.c \ - server/cras_bt_battery_provider.c \ server/cras_dbus.c \ server/cras_dbus_util.c \ server/cras_dbus_control.c \ @@ -109,7 +106,7 @@ cras_server_SOURCES = \ server/buffer_share.c \ server/config/cras_board_config.c \ server/config/cras_card_config.c \ - server/config/cras_device_blocklist.c \ + server/config/cras_device_blacklist.c \ server/cras_alert.c \ server/cras_alsa_card.c \ server/cras_alsa_helpers.c \ @@ -117,7 +114,6 @@ cras_server_SOURCES = \ server/cras_alsa_jack.c \ server/cras_alsa_mixer.c \ server/cras_alsa_mixer_name.c \ - server/cras_alsa_plugin_io.c \ server/cras_alsa_ucm.c \ server/cras_alsa_ucm_section.c \ server/cras_audio_area.c \ @@ -147,9 +143,7 @@ cras_server_SOURCES = \ server/cras_control_rclient.c \ server/cras_playback_rclient.c \ server/cras_capture_rclient.c \ - server/cras_unified_rclient.c \ server/cras_rstream.c \ - server/cras_rstream_config.c \ server/cras_server_metrics.c \ server/cras_system_state.c \ server/cras_tm.c \ @@ -157,26 +151,22 @@ cras_server_SOURCES = \ server/cras_volume_curve.c \ server/dev_io.c \ server/dev_stream.c \ - server/ewma_power.c \ server/input_data.c \ server/linear_resampler.c \ server/polled_interval_checker.c \ server/server_stream.c \ server/stream_list.c \ server/test_iodev.c \ + server/rate_estimator.c \ server/softvol_curve.c -SERVER_RUST_SRCDIR = $(top_srcdir)/src/server/rust - libcrasserver_la_SOURCES = \ $(cras_server_SOURCES) libcrasserver_la_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/dsp -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/server/config -I$(top_srcdir)/src/plc \ - -I$(SERVER_RUST_SRCDIR)/src/headers \ $(DBUS_CFLAGS) $(SBC_CFLAGS) $(SELINUX_CFLAGS) libcrasserver_la_LIBADD = \ - $(CRAS_RUST) \ libcrasmix.la \ $(CRAS_SSE4_2) \ $(CRAS_AVX) \ @@ -203,7 +193,6 @@ cras_LDADD = \ $(CRAS_AVX) \ $(CRAS_AVX2) \ $(CRAS_FMA) \ - $(CRAS_RUST) \ -lpthread -lasound -lrt -liniparser -ludev -ldl -lm -lspeexdsp \ $(METRICS_LIBS) \ $(SBC_LIBS) \ @@ -283,7 +272,6 @@ include_HEADERS = \ common/cras_types.h \ common/cras_util.h \ common/edid_utils.h \ - common/packet_status_logger.h \ common/utlist.h \ libcras/cras_client.h \ libcras/cras_helpers.h @@ -310,28 +298,6 @@ libasound_module_pcm_cras_la_LIBADD = -lasound libcras.la libasound_module_ctl_cras_la_SOURCES = alsa_plugin/ctl_cras.c libasound_module_ctl_cras_la_LIBADD = -lasound libcras.la -if !WITH_SYSTEM_RUST -RUST_FILES = \ - $(SERVER_RUST_SRCDIR)/Cargo.toml \ - $(SERVER_RUST_SRCDIR)/src/rate_estimator_bindings.rs \ - $(SERVER_RUST_SRCDIR)/src/rate_estimator.rs - -CRAS_RUST_TARGET_DIR = $(top_builddir)/src/server/rust/target -CRAS_RUST = $(CRAS_RUST_TARGET_DIR)/release/libcras_rust.a -$(CRAS_RUST): $(RUST_FILES) - cargo build --release \ - --manifest-path $(SERVER_RUST_SRCDIR)/Cargo.toml \ - --target-dir $(CRAS_RUST_TARGET_DIR) - -clean-local: - cargo clean --release \ - --manifest-path $(SERVER_RUST_SRCDIR)/Cargo.toml \ - --target-dir $(CRAS_RUST_TARGET_DIR) - -else -CRAS_RUST = -lcras_rust -endif - # Inject a dependency between the installation rules of libcras and its modules. # This avoids a race when the modules are relinked before libcras is actually # installed. @@ -343,50 +309,6 @@ hide_install=install $(hide_install)-asound_module_pcm_crasLTLIBRARIES: install-libLTLIBRARIES $(hide_install)-asound_module_ctl_crasLTLIBRARIES: install-libLTLIBRARIES -# ==== Fuzzer section -if HAVE_FUZZER -FUZZERS = \ - cras_rclient_message_fuzzer \ - cras_hfp_slc_fuzzer - -noinst_PROGRAMS += $(FUZZERS) - -FUZZER_CPPFLAGS = $(COMMON_CPPFLAGS) \ - -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/dsp -I$(top_srcdir)/src/server \ - -I$(top_srcdir)/src/server/config -I$(top_srcdir)/src/plc \ - $(DBUS_CFLAGS) $(SBC_CFLAGS) - -FUZZER_LDADD = \ - libcrasmix.la \ - libcrasserver.la \ - $(CRAS_SSE4_2) \ - $(CRAS_AVX) \ - $(CRAS_AVX2) \ - $(CRAS_FMA) \ - $(CRAS_RUST) \ - -lpthread -lasound -lrt -liniparser -ludev -ldl -lm -lspeexdsp \ - $(METRICS_LIBS) \ - $(SBC_LIBS) \ - $(DBUS_LIBS) \ - $(WEBRTC_APM_LIBS) - -cras_rclient_message_fuzzer_SOURCES = \ - fuzz/rclient_message.cc - -cras_rclient_message_fuzzer_CPPFLAGS = $(FUZZER_CPPFLAGS) -cras_rclient_message_fuzzer_LDFLAGS = $(FUZZER_LDFLAGS) -cras_rclient_message_fuzzer_LDADD = $(FUZZER_LDADD) - -cras_hfp_slc_fuzzer_SOURCES = \ - fuzz/cras_hfp_slc.cc - -cras_hfp_slc_fuzzer_CPPFLAGS = $(FUZZER_CPPFLAGS) -cras_hfp_slc_fuzzer_LDFLAGS = $(FUZZER_LDFLAGS) -cras_hfp_slc_fuzzer_LDADD = $(FUZZER_LDADD) -endif - -# ==== Tests section if HAVE_DBUS DBUS_TESTS = \ a2dp_info_unittest \ @@ -427,13 +349,12 @@ TESTS = \ byte_buffer_unittest \ card_config_unittest \ checksum_unittest \ - cras_abi_unittest \ cras_client_unittest \ cras_tm_unittest \ device_monitor_unittest \ dev_io_unittest \ dev_stream_unittest \ - device_blocklist_unittest \ + device_blacklist_unittest \ dsp_core_unittest \ dsp_ini_unittest \ dsp_pipeline_unittest \ @@ -442,7 +363,6 @@ TESTS = \ edid_utils_unittest \ empty_iodev_unittest \ expr_unittest \ - ewma_power_unittest \ file_wait_unittest \ float_buffer_unittest \ fmt_conv_unittest \ @@ -615,7 +535,8 @@ a2dp_info_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/common a2dp_info_unittest_LDADD = -lgtest -lpthread -a2dp_iodev_unittest_SOURCES = tests/a2dp_iodev_unittest.cc +a2dp_iodev_unittest_SOURCES = tests/a2dp_iodev_unittest.cc \ + server/cras_a2dp_iodev.c common/sfh.c a2dp_iodev_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/common $(DBUS_CFLAGS) a2dp_iodev_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) @@ -676,8 +597,7 @@ audio_thread_unittest_SOURCES = tests/audio_thread_unittest.cc \ server/dev_io.c tests/empty_audio_stub.cc tests/metrics_stub.cc \ common/cras_shm.c audio_thread_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ - -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server \ - -I$(SERVER_RUST_SRCDIR)/src/headers + -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server audio_thread_unittest_LDADD = -lgtest -lpthread -lrt audio_thread_monitor_unittest_SOURCES = tests/audio_thread_monitor_unittest.cc @@ -687,8 +607,7 @@ audio_thread_monitor_unittest_LDADD = -lgtest -lpthread -lrt if HAVE_DBUS bt_device_unittest_SOURCES = tests/bt_device_unittest.cc \ - server/cras_bt_device.c \ - tests/metrics_stub.cc common/sfh.c + server/cras_bt_device.c bt_device_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/common $(DBUS_CFLAGS) bt_device_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) @@ -720,13 +639,6 @@ checksum_unittest_SOURCES = tests/checksum_unittest.cc common/cras_checksum.c checksum_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common checksum_unittest_LDADD = -lgtest -lpthread -cras_abi_unittest_SOURCES = tests/cras_abi_unittest.cc \ - common/cras_config.c common/cras_shm.c common/cras_util.c \ - common/cras_file_wait.c common/cras_audio_format.c -cras_abi_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/libcras -cras_abi_unittest_LDADD = -lgtest -lpthread -lrt -lspeexdsp - cras_client_unittest_SOURCES = tests/cras_client_unittest.cc \ common/cras_config.c common/cras_shm.c common/cras_util.c \ common/cras_file_wait.c @@ -756,7 +668,6 @@ dev_io_unittest_CPPFLAGS = \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/server/config \ - -I$(SERVER_RUST_SRCDIR)/src/headers \ $(SELINUX_CFLAGS) dev_io_unittest_LDADD = \ libcrasmix.la \ @@ -773,12 +684,12 @@ dev_stream_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server dev_stream_unittest_LDADD = -lgtest -liniparser -lpthread -lrt -device_blocklist_unittest_SOURCES = tests/device_blocklist_unittest.cc \ - server/config/cras_device_blocklist.c -device_blocklist_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ +device_blacklist_unittest_SOURCES = tests/device_blacklist_unittest.cc \ + server/config/cras_device_blacklist.c +device_blacklist_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/server/config $(CRAS_UT_TMPDIR_CFLAGS) -device_blocklist_unittest_LDADD = -lgtest -liniparser -lpthread +device_blacklist_unittest_LDADD = -lgtest -liniparser -lpthread device_monitor_unittest_SOURCES = tests/device_monitor_unittest.cc device_monitor_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ @@ -863,13 +774,13 @@ hfp_info_unittest_LDADD = -lgtest -lpthread if HAVE_DBUS hfp_iodev_unittest_SOURCES = tests/hfp_iodev_unittest.cc \ - server/cras_hfp_iodev.c + server/cras_hfp_iodev.c common/sfh.c hfp_iodev_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server $(DBUS_CFLAGS) hfp_iodev_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) hfp_alsa_iodev_unittest_SOURCES = tests/hfp_alsa_iodev_unittest.cc \ - server/cras_hfp_alsa_iodev.c + server/cras_hfp_alsa_iodev.c common/sfh.c hfp_alsa_iodev_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server $(DBUS_CFLAGS) hfp_alsa_iodev_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) @@ -881,7 +792,7 @@ hfp_ag_profile_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ hfp_ag_profile_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) hfp_slc_unittest_SOURCES = tests/hfp_slc_unittest.cc \ - server/cras_hfp_slc.c tests/metrics_stub.cc + server/cras_hfp_slc.c hfp_slc_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server $(DBUS_CFLAGS) hfp_slc_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) @@ -893,14 +804,6 @@ buffer_share_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server buffer_share_unittest_LDADD = -lgtest -liniparser -lpthread -ewma_power_unittest_SOURCES = tests/ewma_power_unittest.cc \ - common/cras_audio_format.c server/cras_audio_area.c \ - server/ewma_power.c - -ewma_power_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ - -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server -ewma_power_unittest_LDADD = -lgtest - iodev_list_unittest_SOURCES = tests/iodev_list_unittest.cc \ server/cras_iodev_list.c iodev_list_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ @@ -908,11 +811,11 @@ iodev_list_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ iodev_list_unittest_LDADD = -lgtest -lpthread loopback_iodev_unittest_SOURCES = tests/loopback_iodev_unittest.cc \ - server/cras_loopback_iodev.c common/cras_shm.c common/sfh.c + server/cras_loopback_iodev.c common/sfh.c loopback_iodev_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server -loopback_iodev_unittest_LDADD = -lgtest -lpthread -lrt +loopback_iodev_unittest_LDADD = -lgtest -lpthread input_data_unittest_SOURCES = tests/input_data_unittest.cc \ server/input_data.c @@ -923,8 +826,7 @@ input_data_unittest_LDADD = -lgtest -lpthread iodev_unittest_SOURCES = tests/iodev_unittest.cc \ server/cras_iodev.c common/cras_shm.c iodev_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/server \ - -I$(SERVER_RUST_SRCDIR)/src/headers + -I$(top_srcdir)/src/server iodev_unittest_LDADD = -lgtest -lpthread -lrt mix_unittest_SOURCES = tests/mix_unittest.cc server/cras_mix.c @@ -960,37 +862,31 @@ ramp_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server ramp_unittest_LDADD = -lgtest -lpthread -rate_estimator_unittest_SOURCES = tests/rate_estimator_unittest.cc +rate_estimator_unittest_SOURCES = tests/rate_estimator_unittest.cc server/rate_estimator.c rate_estimator_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/server \ - -I$(SERVER_RUST_SRCDIR)/src/headers -rate_estimator_unittest_LDADD = $(CRAS_RUST) -lgtest -ldl -lpthread + -I$(top_srcdir)/src/server +rate_estimator_unittest_LDADD = -lgtest -lpthread -control_rclient_unittest_SOURCES = tests/control_rclient_unittest.cc \ - server/cras_rstream_config.c +control_rclient_unittest_SOURCES = tests/control_rclient_unittest.cc control_rclient_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/server $(CRAS_UT_TMPDIR_CFLAGS) \ - $(DBUS_CFLAGS) -control_rclient_unittest_LDADD = -lgtest -lpthread $(DBUS_LIBS) + -I$(top_srcdir)/src/server $(CRAS_UT_TMPDIR_CFLAGS) +control_rclient_unittest_LDADD = -lgtest -lpthread -playback_rclient_unittest_SOURCES = tests/playback_rclient_unittest.cc \ - server/cras_rstream_config.c +playback_rclient_unittest_SOURCES = tests/playback_rclient_unittest.cc playback_rclient_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server $(CRAS_UT_TMPDIR_CFLAGS) playback_rclient_unittest_LDADD = -lgtest -lpthread -capture_rclient_unittest_SOURCES = tests/capture_rclient_unittest.cc \ - server/cras_rstream_config.c +capture_rclient_unittest_SOURCES = tests/capture_rclient_unittest.cc capture_rclient_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server $(CRAS_UT_TMPDIR_CFLAGS) capture_rclient_unittest_LDADD = -lgtest -lpthread rstream_unittest_SOURCES = tests/rstream_unittest.cc server/cras_rstream.c \ - common/cras_shm.c tests/metrics_stub.cc \ - server/cras_rstream_config.c $(CRAS_SELINUX_UNITTEST_SOURCES) + common/cras_shm.c $(CRAS_SELINUX_UNITTEST_SOURCES) rstream_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server $(SELINUX_CFLAGS) rstream_unittest_LDADD = $(SELINUX_LIBS) \ @@ -1018,7 +914,7 @@ stream_list_unittest_LDADD = -lgtest -lpthread system_state_unittest_SOURCES = tests/system_state_unittest.cc \ server/cras_system_state.c common/cras_shm.c \ - $(CRAS_SELINUX_UNITTEST_SOURCES) + server/config/cras_board_config.c $(CRAS_SELINUX_UNITTEST_SOURCES) system_state_unittest_CPPFLAGS = $(COMMON_CPPFLAGS) \ -I$(top_srcdir)/src/common -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/server/config $(SELINUX_CFLAGS) @@ -1050,7 +946,6 @@ timing_unittest_CPPFLAGS = \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/server \ -I$(top_srcdir)/src/server/config \ - -I$(SERVER_RUST_SRCDIR)/src/headers \ $(SELINUX_CFLAGS) timing_unittest_LDADD = \ libcrasmix.la \ diff --git a/cras/src/alsa_plugin/ctl_cras.c b/cras/src/alsa_plugin/ctl_cras.c index 76b0c039..822b63ab 100644 --- a/cras/src/alsa_plugin/ctl_cras.c +++ b/cras/src/alsa_plugin/ctl_cras.c @@ -14,6 +14,8 @@ static const size_t MAX_IONODES = 20; /* Max ionodes to print out. */ enum CTL_CRAS_MIXER_CONTROLS { CTL_CRAS_MIXER_PLAYBACK_SWITCH, CTL_CRAS_MIXER_PLAYBACK_VOLUME, + CTL_CRAS_MIXER_CAPTURE_SWITCH, + CTL_CRAS_MIXER_CAPTURE_VOLUME, NUM_CTL_CRAS_MIXER_ELEMS }; @@ -31,6 +33,10 @@ static const struct cras_mixer_control cras_elems[NUM_CTL_CRAS_MIXER_ELEMS] = { SND_CTL_EXT_ACCESS_READWRITE, 1 }, { "Master Playback Volume", SND_CTL_ELEM_TYPE_INTEGER, SND_CTL_EXT_ACCESS_READWRITE, 1 }, + { "Capture Switch", SND_CTL_ELEM_TYPE_BOOLEAN, + SND_CTL_EXT_ACCESS_READWRITE, 1 }, + { "Capture Volume", SND_CTL_ELEM_TYPE_INTEGER, + SND_CTL_EXT_ACCESS_READWRITE, 1 }, }; /* Holds the client and ctl plugin pointers. */ @@ -113,6 +119,46 @@ static int ctl_cras_get_integer_info(snd_ctl_ext_t *ext_ctl, return 0; } +static long capture_index_to_gain(struct cras_client *client, long index) +{ + long min; + long max; + long dB_step; + + min = cras_client_get_system_min_capture_gain(client); + max = cras_client_get_system_max_capture_gain(client); + if (min >= max) + return min; + + dB_step = (max - min) / 100; + + if (index <= 0) + return min; + if (index >= 100) + return max; + return index * dB_step + min; +} + +static long capture_gain_to_index(struct cras_client *client, long gain) +{ + long min; + long max; + long dB_step; + + min = cras_client_get_system_min_capture_gain(client); + max = cras_client_get_system_max_capture_gain(client); + if (min >= max) + return 0; + + dB_step = (max - min) / 100; + + if (gain <= min) + return 0; + if (gain >= max) + return 100; + return (gain - min) / dB_step; +} + static int get_nodes(struct cras_client *client, enum CRAS_STREAM_DIRECTION dir, struct cras_ionode_info *nodes, size_t num_nodes) { @@ -153,6 +199,20 @@ static int ctl_cras_read_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key, break; } break; + case CTL_CRAS_MIXER_CAPTURE_SWITCH: + *value = !cras_client_get_system_capture_muted(cras->client); + break; + case CTL_CRAS_MIXER_CAPTURE_VOLUME: + num_nodes = get_nodes(cras->client, CRAS_STREAM_INPUT, nodes, + MAX_IONODES); + for (i = 0; i < num_nodes; i++) { + if (!nodes[i].active) + continue; + *value = capture_gain_to_index(cras->client, + nodes[i].capture_gain); + break; + } + break; default: return -EINVAL; } @@ -167,6 +227,7 @@ static int ctl_cras_write_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key, struct ctl_cras *cras = (struct ctl_cras *)ext_ctl->private_data; struct cras_ionode_info nodes[MAX_IONODES]; int num_nodes, i; + long gain; switch (key) { case CTL_CRAS_MIXER_PLAYBACK_SWITCH: @@ -185,6 +246,23 @@ static int ctl_cras_write_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key, *value); } break; + case CTL_CRAS_MIXER_CAPTURE_SWITCH: + cras_client_set_system_capture_mute(cras->client, !(*value)); + break; + case CTL_CRAS_MIXER_CAPTURE_VOLUME: + gain = capture_index_to_gain(cras->client, *value); + num_nodes = get_nodes(cras->client, CRAS_STREAM_INPUT, nodes, + MAX_IONODES); + for (i = 0; i < num_nodes; i++) { + if (!nodes[i].active) + continue; + cras_client_set_node_capture_gain( + cras->client, + cras_make_node_id(nodes[i].iodev_idx, + nodes[i].ionode_idx), + gain); + } + break; default: return -EINVAL; } diff --git a/cras/src/alsa_plugin/pcm_cras.c b/cras/src/alsa_plugin/pcm_cras.c index 7bc960bc..715db2cc 100644 --- a/cras/src/alsa_plugin/pcm_cras.c +++ b/cras/src/alsa_plugin/pcm_cras.c @@ -124,7 +124,7 @@ static int pcm_cras_process_cb(struct cras_client *client, struct snd_pcm_cras *pcm_cras; const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t copied_frames; - char empty_byte; + char dummy_byte; size_t chan, frame_bytes, sample_bytes; int rc; uint8_t *samples; @@ -196,7 +196,7 @@ static int pcm_cras_process_cb(struct cras_client *client, copied_frames += frames; } - rc = write(pcm_cras->fd, &empty_byte, 1); /* Wake up polling clients. */ + rc = write(pcm_cras->fd, &dummy_byte, 1); /* Wake up polling clients. */ if (rc < 0 && errno != EWOULDBLOCK && errno != EAGAIN) fprintf(stderr, "%s write failed %d\n", __func__, errno); diff --git a/cras/src/common/bluetooth.h b/cras/src/common/bluetooth.h index 66beadad..155b5e00 100644 --- a/cras/src/common/bluetooth.h +++ b/cras/src/common/bluetooth.h @@ -74,11 +74,3 @@ struct bt_voice { }; #define BT_VOICE_TRANSPARENT 0x0003 - -#define BT_SNDMTU 12 - -#define BT_RCVMTU 13 - -#define BT_PKT_STATUS 16 - -#define BT_SCM_PKT_STATUS 0x03 diff --git a/cras/src/common/cras_audio_format.c b/cras/src/common/cras_audio_format.c index 8bd48656..f504dfc3 100644 --- a/cras/src/common/cras_audio_format.c +++ b/cras/src/common/cras_audio_format.c @@ -62,7 +62,7 @@ int cras_audio_format_set_channel_layout(struct cras_audio_format *format, * channel count set in format. */ for (i = 0; i < CRAS_CH_MAX; i++) - if (layout[i] < -1 || layout[i] >= (int)format->num_channels) + if (layout[i] >= (int)format->num_channels) return -EINVAL; for (i = 0; i < CRAS_CH_MAX; i++) @@ -71,19 +71,6 @@ int cras_audio_format_set_channel_layout(struct cras_audio_format *format, return 0; } -/* Verifies if all channel_layout[i] are in [-1, fmt->num_channels). */ -bool cras_audio_format_valid(const struct cras_audio_format *fmt) -{ - int i; - for (i = 0; i < CRAS_CH_MAX; i++) { - if (fmt->channel_layout[i] < -1 || - fmt->channel_layout[i] >= (int)fmt->num_channels) { - return false; - } - } - return true; -} - /* Destroy an audio format struct created with cras_audio_format_crate. */ void cras_audio_format_destroy(struct cras_audio_format *fmt) { diff --git a/cras/src/common/cras_audio_format.h b/cras/src/common/cras_audio_format.h index f0cc94f4..47bb5c59 100644 --- a/cras/src/common/cras_audio_format.h +++ b/cras/src/common/cras_audio_format.h @@ -10,7 +10,6 @@ extern "C" { #endif -#include <stdbool.h> #include <stdint.h> #include <string.h> @@ -106,16 +105,15 @@ static inline void pack_cras_audio_format(struct cras_audio_format_packed *dest, sizeof(src->channel_layout)); } -static inline struct cras_audio_format -unpack_cras_audio_format(const struct cras_audio_format_packed *src) +static inline void +unpack_cras_audio_format(struct cras_audio_format *dest, + const struct cras_audio_format_packed *src) { - struct cras_audio_format dest; - dest.format = (snd_pcm_format_t)src->format; - dest.frame_rate = src->frame_rate; - dest.num_channels = src->num_channels; - memcpy(dest.channel_layout, src->channel_layout, + dest->format = (snd_pcm_format_t)src->format; + dest->frame_rate = src->frame_rate; + dest->num_channels = src->num_channels; + memcpy(dest->channel_layout, src->channel_layout, sizeof(src->channel_layout)); - return dest; } /* Returns the number of bytes per sample. @@ -145,9 +143,6 @@ struct cras_audio_format *cras_audio_format_create(snd_pcm_format_t format, /* Destroy an audio format struct created with cras_audio_format_crate. */ void cras_audio_format_destroy(struct cras_audio_format *fmt); -/* Returns true if the audio format is valid */ -bool cras_audio_format_valid(const struct cras_audio_format *fmt); - /* Sets the channel layout for given format. * format - The format structure to carry channel layout info * layout - An integer array representing the position of each diff --git a/cras/src/common/cras_config.c b/cras/src/common/cras_config.c index 75fa24e7..335b7849 100644 --- a/cras/src/common/cras_config.c +++ b/cras/src/common/cras_config.c @@ -38,18 +38,6 @@ int cras_fill_socket_path(enum CRAS_CONNECTION_TYPE conn_type, char *sock_path) case CRAS_CAPTURE: sock_file = CRAS_CAPTURE_SOCKET_FILE; break; - case CRAS_VMS_LEGACY: - sock_file = CRAS_VMS_LEGACY_SOCKET_FILE; - break; - case CRAS_VMS_UNIFIED: - sock_file = CRAS_VMS_UNIFIED_SOCKET_FILE; - break; - case CRAS_PLUGIN_PLAYBACK: - sock_file = CRAS_PLUGIN_PLAYBACK_SOCKET_FILE; - break; - case CRAS_PLUGIN_UNIFIED: - sock_file = CRAS_PLUGIN_UNIFIED_SOCKET_FILE; - break; default: return -EINVAL; } diff --git a/cras/src/common/cras_config.h b/cras/src/common/cras_config.h index 1c8e55fa..8b1e6135 100644 --- a/cras/src/common/cras_config.h +++ b/cras/src/common/cras_config.h @@ -9,7 +9,6 @@ #include "cras_types.h" #define CRAS_MIN_BUFFER_TIME_IN_US 1000 /* 1 milliseconds */ -#define CRAS_MAX_BUFFER_TIME_IN_S 10 /* 10 seconds */ #define CRAS_SERVER_RT_THREAD_PRIORITY 12 #define CRAS_CLIENT_RT_THREAD_PRIORITY 10 @@ -17,12 +16,6 @@ #define CRAS_SOCKET_FILE ".cras_socket" #define CRAS_PLAYBACK_SOCKET_FILE ".cras_playback" #define CRAS_CAPTURE_SOCKET_FILE ".cras_capture" -/* Socket file paths for VMs. */ -#define CRAS_VMS_LEGACY_SOCKET_FILE "vms/.cras_socket" -#define CRAS_VMS_UNIFIED_SOCKET_FILE "vms/.cras_unified" -/* Socket file paths for pluginVM. */ -#define CRAS_PLUGIN_PLAYBACK_SOCKET_FILE "vms/plugin/playback/.cras_socket" -#define CRAS_PLUGIN_UNIFIED_SOCKET_FILE "vms/plugin/unified/.cras_socket" /* Maximum socket_path size, which is equals to sizeof(sun_path) in sockaddr_un * structure. diff --git a/cras/src/common/cras_file_wait.c b/cras/src/common/cras_file_wait.c index 190a5e10..9ad94486 100644 --- a/cras/src/common/cras_file_wait.c +++ b/cras/src/common/cras_file_wait.c @@ -190,7 +190,7 @@ int cras_file_wait_dispatch(struct cras_file_wait *file_wait) strcpy(file_wait->watch_dir, file_wait->file_path); watch_dir_len = file_wait->file_path_len; - while (rc == -ENOENT || rc == -EACCES) { + while (rc == -ENOENT) { strcpy(file_wait->watch_path, file_wait->watch_dir); watch_path_len = watch_dir_len; diff --git a/cras/src/common/cras_iodev_info.h b/cras/src/common/cras_iodev_info.h index 85d20f90..5317ddee 100644 --- a/cras/src/common/cras_iodev_info.h +++ b/cras/src/common/cras_iodev_info.h @@ -19,13 +19,11 @@ * idx - iodev index. * name - Name displayed to the user. * stable_id - ID that does not change due to device plug/unplug or reboot. - * max_supported_channels - Max supported channel count of this device. */ struct __attribute__((__packed__)) cras_iodev_info { uint32_t idx; char name[CRAS_IODEV_NAME_BUFFER_SIZE]; uint32_t stable_id; - uint32_t max_supported_channels; }; /* Identifying information about an ionode on an iodev. @@ -36,9 +34,9 @@ struct __attribute__((__packed__)) cras_iodev_info { * active - If this is the node currently being used. * volume - per-node volume (0-100) * capture_gain - per-node capture gain/attenuation (in 100*dBFS) - * ui_gain_scaler - Adjustable gain scaler set by Chrome. * left_right_swapped - Set true if left and right channels are swapped. * stable_id - ID that does not change due to device plug/unplug or reboot. + * mic_positions - Positions of the mic array. * type - Type displayed to the user. * name - Name displayed to the user. * active_hotword_model - name of the currently selected hotword model. @@ -54,10 +52,10 @@ struct __attribute__((__packed__)) cras_ionode_info { } plugged_time; uint32_t volume; int32_t capture_gain; - float ui_gain_scaler; int32_t left_right_swapped; uint32_t type_enum; uint32_t stable_id; + char mic_positions[CRAS_NODE_MIC_POS_BUFFER_SIZE]; char type[CRAS_NODE_TYPE_BUFFER_SIZE]; char name[CRAS_NODE_NAME_BUFFER_SIZE]; char active_hotword_model[CRAS_NODE_HOTWORD_MODEL_BUFFER_SIZE]; diff --git a/cras/src/common/cras_messages.h b/cras/src/common/cras_messages.h index 50cbe7cd..195965bb 100644 --- a/cras/src/common/cras_messages.h +++ b/cras/src/common/cras_messages.h @@ -16,11 +16,11 @@ /* Rev when message format changes. If new messages are added, or message ID * values change. */ -#define CRAS_PROTO_VER 7 +#define CRAS_PROTO_VER 5 #define CRAS_SERV_MAX_MSG_SIZE 256 #define CRAS_CLIENT_MAX_MSG_SIZE 256 #define CRAS_MAX_HOTWORD_MODELS 243 -#define CRAS_MAX_REMIX_CHANNELS 8 +#define CRAS_MAX_REMIX_CHANNELS 32 #define CRAS_MAX_TEST_DATA_LEN 224 #define CRAS_AEC_DUMP_FILE_NAME_LEN 128 @@ -34,7 +34,7 @@ enum CRAS_SERVER_MESSAGE_ID { CRAS_SERVER_SET_SYSTEM_MUTE, CRAS_SERVER_SET_USER_MUTE, CRAS_SERVER_SET_SYSTEM_MUTE_LOCKED, - CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN, /* Deprecated */ + CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN, CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE, CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE_LOCKED, CRAS_SERVER_SET_NODE_ATTR, @@ -58,7 +58,6 @@ enum CRAS_SERVER_MESSAGE_ID { CRAS_SERVER_DUMP_BT, CRAS_SERVER_SET_BT_WBS_ENABLED, CRAS_SERVER_GET_ATLOG_FD, - CRAS_SERVER_DUMP_MAIN, }; enum CRAS_CLIENT_MESSAGE_ID { @@ -114,10 +113,28 @@ struct __attribute__((__packed__)) cras_connect_message { uint32_t dev_idx; /* device to attach stream, 0 if none */ uint64_t effects; /* Bit map of requested effects. */ enum CRAS_CLIENT_TYPE client_type; /* chrome, or arc, etc. */ - uint64_t client_shm_size; /* Size of client-provided samples shm, if any */ - /* Initial values for shm samples buffer offsets. These will be 0 for - * streams that do not use client-provided shm */ - uint64_t buffer_offsets[2]; + uint32_t client_shm_size; /* Size of client-provided samples shm, if any */ +}; + +/* + * Old version of connect message without 'cras_type' and 'client_shm_size' + * defined. + * Used to check against when receiving invalid size of connect message. + * Expected to have proto_version set to 3. + * TODO(yuhsuan): remove when all clients migrate to latest libcras. + */ +struct __attribute__((__packed__)) cras_connect_message_old { + struct cras_server_message header; + uint32_t proto_version; + enum CRAS_STREAM_DIRECTION direction; /* input/output/loopback */ + cras_stream_id_t stream_id; /* unique id for this stream */ + enum CRAS_STREAM_TYPE stream_type; /* media, or call, etc. */ + uint32_t buffer_frames; /* Buffer size in frames. */ + uint32_t cb_threshold; /* callback client when this much is left */ + uint32_t flags; + struct cras_audio_format_packed format; /* rate, channel, sample size */ + uint32_t dev_idx; /* device to attach stream, 0 if none */ + uint64_t effects; /* Bit map of requested effects. */ }; static inline void cras_fill_connect_message( @@ -125,7 +142,8 @@ static inline void cras_fill_connect_message( cras_stream_id_t stream_id, enum CRAS_STREAM_TYPE stream_type, enum CRAS_CLIENT_TYPE client_type, size_t buffer_frames, size_t cb_threshold, uint32_t flags, uint64_t effects, - struct cras_audio_format format, uint32_t dev_idx) + struct cras_audio_format format, uint32_t dev_idx, + uint32_t client_shm_size) { m->proto_version = CRAS_PROTO_VER; m->direction = direction; @@ -138,9 +156,7 @@ static inline void cras_fill_connect_message( pack_cras_audio_format(&m->format, &format); m->dev_idx = dev_idx; m->client_type = client_type; - m->client_shm_size = 0; - m->buffer_offsets[0] = 0; - m->buffer_offsets[1] = 0; + m->client_shm_size = client_shm_size; m->header.id = CRAS_SERVER_CONNECT_STREAM; m->header.length = sizeof(struct cras_connect_message); } @@ -179,6 +195,20 @@ static inline void cras_fill_set_system_volume(struct cras_set_system_volume *m, m->header.length = sizeof(*m); } +/* Sets the capture gain. */ +struct __attribute__((__packed__)) cras_set_system_capture_gain { + struct cras_server_message header; + int32_t gain; +}; +static inline void +cras_fill_set_system_capture_gain(struct cras_set_system_capture_gain *m, + long gain) +{ + m->gain = gain; + m->header.id = CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN; + m->header.length = sizeof(*m); +} + /* Set the system mute state. */ struct __attribute__((__packed__)) cras_set_system_mute { struct cras_server_message header; @@ -331,17 +361,6 @@ static inline void cras_fill_get_atlog_fd(struct cras_get_atlog_fd *m) m->header.length = sizeof(*m); } -/* Dump events in CRAS main thread. */ -struct __attribute__((__packed__)) cras_dump_main { - struct cras_server_message header; -}; - -static inline void cras_fill_dump_main(struct cras_dump_main *m) -{ - m->header.id = CRAS_SERVER_DUMP_MAIN; - m->header.length = sizeof(*m); -} - /* Dump bluetooth events and state changes. */ struct __attribute__((__packed__)) cras_dump_bt { struct cras_server_message header; @@ -415,7 +434,7 @@ static inline void cras_fill_suspend_message(struct cras_server_message *m, struct __attribute__((__packed__)) cras_config_global_remix { struct cras_server_message header; unsigned int num_channels; - float coefficient[CRAS_MAX_REMIX_CHANNELS * CRAS_MAX_REMIX_CHANNELS]; + float coefficient[CRAS_MAX_REMIX_CHANNELS]; }; static inline void @@ -540,8 +559,8 @@ static inline void cras_fill_client_connected(struct cras_client_connected *m, * Reply from server that a stream has been successfully added. * Two file descriptors are added, input shm followed by out shm. * - * |samples_shm_size| is valid for normal streams, not client-provided - * shm streams. + * samples_shm_size is shm_max_size for old clients. + * TODO(fletcherw) remove comment once all clients are on CRAS_PROTO_VER >= 3. */ struct __attribute__((__packed__)) cras_client_stream_connected { struct cras_client_message header; @@ -561,9 +580,6 @@ cras_fill_client_stream_connected(struct cras_client_stream_connected *m, m->err = err; m->stream_id = stream_id; pack_cras_audio_format(&m->format, format); - if (samples_shm_size > UINT32_MAX) { - samples_shm_size = UINT32_MAX; - } m->samples_shm_size = samples_shm_size; m->effects = effects; m->header.id = CRAS_CLIENT_STREAM_CONNECTED; diff --git a/cras/src/common/cras_observer_ops.h b/cras/src/common/cras_observer_ops.h index e73845c9..70dd513c 100644 --- a/cras/src/common/cras_observer_ops.h +++ b/cras/src/common/cras_observer_ops.h @@ -47,19 +47,12 @@ struct cras_observer_ops { void (*num_active_streams_changed)(void *context, enum CRAS_STREAM_DIRECTION dir, uint32_t num_active_streams); - /* Number of input streams with permission changed. */ - void (*num_input_streams_with_permission_changed)( - void *context, - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]); /* Hotword triggered. */ void (*hotword_triggered)(void *context, int64_t tv_sec, int64_t tv_nsec); /* State regarding whether non-empty audio is being played/captured has * changed. */ void (*non_empty_audio_state_changed)(void *context, int non_empty); - /* Bluetooth headset battery level changed. */ - void (*bt_battery_changed)(void *context, const char *address, - uint32_t level); }; #endif /* CRAS_OBSERVER_OPS_H */ diff --git a/cras/src/common/cras_shm.c b/cras/src/common/cras_shm.c index ecb6169c..3e6c2b7e 100644 --- a/cras/src/common/cras_shm.c +++ b/cras/src/common/cras_shm.c @@ -116,31 +116,35 @@ int cras_audio_shm_create(struct cras_shm_info *header_info, * The parameters are cleared, and the owner of cras_audio_shm is now * responsible for closing the fds and unlinking any associated shm * files using cras_audio_shm_destroy. + * + * The source pointers are updated to point to the moved structs so that + * they will be properly cleaned up in the error case. */ ret = cras_shm_info_move(header_info, &shm->header_info); if (ret) goto free_shm; + header_info = &shm->header_info; ret = cras_shm_info_move(samples_info, &shm->samples_info); if (ret) goto free_shm; + samples_info = &shm->samples_info; - shm->header = - mmap(NULL, shm->header_info.length, PROT_READ | PROT_WRITE, - MAP_SHARED, shm->header_info.fd, 0); + shm->header = mmap(NULL, header_info->length, PROT_READ | PROT_WRITE, + MAP_SHARED, header_info->fd, 0); if (shm->header == (struct cras_audio_shm_header *)-1) { - ret = -errno; + ret = errno; syslog(LOG_ERR, "cras_shm: mmap failed to map shm for header."); goto free_shm; } - shm->samples = mmap(NULL, shm->samples_info.length, samples_prot, - MAP_SHARED, shm->samples_info.fd, 0); + shm->samples = mmap(NULL, samples_info->length, samples_prot, + MAP_SHARED, samples_info->fd, 0); if (shm->samples == (uint8_t *)-1) { - ret = -errno; + ret = errno; syslog(LOG_ERR, "cras_shm: mmap failed to map shm for samples."); - goto free_shm; + goto unmap_header; } cras_shm_set_volume_scaler(shm, 1.0); @@ -148,8 +152,10 @@ int cras_audio_shm_create(struct cras_shm_info *header_info, *shm_out = shm; return 0; +unmap_header: + munmap(shm->header, shm->header_info.length); free_shm: - cras_audio_shm_destroy(shm); + free(shm); cleanup_info: cras_shm_info_cleanup(samples_info); cras_shm_info_cleanup(header_info); @@ -161,12 +167,9 @@ void cras_audio_shm_destroy(struct cras_audio_shm *shm) if (!shm) return; - if (shm->samples != NULL && shm->samples != (uint8_t *)-1) - munmap(shm->samples, shm->samples_info.length); + munmap(shm->samples, shm->samples_info.length); cras_shm_info_cleanup(&shm->samples_info); - if (shm->header != NULL && - shm->header != (struct cras_audio_shm_header *)-1) - munmap(shm->header, shm->header_info.length); + munmap(shm->header, shm->header_info.length); cras_shm_info_cleanup(&shm->header_info); free(shm); } @@ -250,7 +253,7 @@ int cras_shm_open_rw(const char *name, size_t size) strerror(-fd)); return fd; } - rc = posix_fallocate(fd, 0, size); + rc = ftruncate(fd, size); if (rc) { rc = -errno; syslog(LOG_ERR, "failed to set size of shm %s: %s\n", name, diff --git a/cras/src/common/cras_shm.h b/cras/src/common/cras_shm.h index 47786c3b..f9c93920 100644 --- a/cras/src/common/cras_shm.h +++ b/cras/src/common/cras_shm.h @@ -59,7 +59,7 @@ struct __attribute__((__packed__)) cras_audio_shm_header { int32_t callback_pending; uint32_t num_overruns; struct cras_timespec ts; - uint64_t buffer_offset[CRAS_NUM_SHM_BUFFERS]; + uint32_t buffer_offset[CRAS_NUM_SHM_BUFFERS]; }; /* Returns the number of bytes needed to hold a cras_audio_shm_header. */ @@ -146,8 +146,6 @@ struct cras_audio_shm { * samples_prot - the mapping protections to use when mapping samples. Allowed * values are PROT_READ or PROT_WRITE. * shm_out - pointer where the created cras_audio_shm will be stored. - * - * Returns 0 on success or a negative error code on failure. */ int cras_audio_shm_create(struct cras_shm_info *header_info, struct cras_shm_info *samples_info, int samples_prot, @@ -564,12 +562,11 @@ static inline void cras_shm_set_used_size(struct cras_audio_shm *shm, uint32_t i; shm->config.used_size = used_size; - if (shm->header) { + if (shm->header) shm->header->config.used_size = used_size; - for (i = 0; i < CRAS_NUM_SHM_BUFFERS; i++) - cras_shm_set_buffer_offset(shm, i, i * used_size); - } + for (i = 0; i < CRAS_NUM_SHM_BUFFERS; i++) + cras_shm_set_buffer_offset(shm, i, i * used_size); } /* Returns the used size of the shm region in bytes. */ @@ -585,7 +582,7 @@ static inline unsigned cras_shm_used_frames(const struct cras_audio_shm *shm) } /* Returns the size of the samples shm region. */ -static inline uint64_t cras_shm_samples_size(const struct cras_audio_shm *shm) +static inline unsigned cras_shm_samples_size(const struct cras_audio_shm *shm) { return shm->samples_info.length; } diff --git a/cras/src/common/cras_types.h b/cras/src/common/cras_types.h index 544ba02c..3dd9413a 100644 --- a/cras/src/common/cras_types.h +++ b/cras/src/common/cras_types.h @@ -15,7 +15,6 @@ #include "cras_audio_format.h" #include "cras_iodev_info.h" -#include "packet_status_logger.h" /* Architecture independent timespec */ struct __attribute__((__packed__)) cras_timespec { @@ -49,10 +48,6 @@ enum CRAS_CONNECTION_TYPE { CRAS_CONTROL, // For legacy client. CRAS_PLAYBACK, // For playback client. CRAS_CAPTURE, // For capture client. - CRAS_VMS_LEGACY, // For legacy client in vms. - CRAS_VMS_UNIFIED, // For unified client in vms. - CRAS_PLUGIN_PLAYBACK, // For playback client in vms/plugin. - CRAS_PLUGIN_UNIFIED, // For unified client in vms/plugin. CRAS_NUM_CONN_TYPE, }; @@ -167,17 +162,8 @@ enum CRAS_CLIENT_TYPE { CRAS_CLIENT_TYPE_ARC, /* ARC++ */ CRAS_CLIENT_TYPE_CROSVM, /* CROSVM */ CRAS_CLIENT_TYPE_SERVER_STREAM, /* Server stream */ - CRAS_CLIENT_TYPE_LACROS, /* LaCrOS */ - CRAS_CLIENT_TYPE_PLUGIN, /* PluginVM */ - CRAS_CLIENT_TYPE_ARCVM, /* ARCVM */ - CRAS_NUM_CLIENT_TYPE, /* numbers of CRAS_CLIENT_TYPE */ }; -static inline bool cras_validate_client_type(enum CRAS_CLIENT_TYPE client_type) -{ - return 0 <= client_type && client_type < CRAS_NUM_CLIENT_TYPE; -} - #define ENUM_STR(x) \ case x: \ return #x; @@ -212,9 +198,6 @@ cras_client_type_str(enum CRAS_CLIENT_TYPE client_type) ENUM_STR(CRAS_CLIENT_TYPE_ARC) ENUM_STR(CRAS_CLIENT_TYPE_CROSVM) ENUM_STR(CRAS_CLIENT_TYPE_SERVER_STREAM) - ENUM_STR(CRAS_CLIENT_TYPE_LACROS) - ENUM_STR(CRAS_CLIENT_TYPE_PLUGIN) - ENUM_STR(CRAS_CLIENT_TYPE_ARCVM) default: return "INVALID_CLIENT_TYPE"; } @@ -267,7 +250,6 @@ static inline uint32_t node_index_of(cras_node_id_t id) #define MAX_DEBUG_STREAMS 8 #define AUDIO_THREAD_EVENT_LOG_SIZE (1024 * 6) #define CRAS_BT_EVENT_LOG_SIZE 1024 -#define MAIN_THREAD_EVENT_LOG_SIZE 1024 /* There are 8 bits of space for events. */ enum AUDIO_THREAD_LOG_EVENTS { @@ -288,8 +270,7 @@ enum AUDIO_THREAD_LOG_EVENTS { AUDIO_THREAD_FETCH_STREAM, AUDIO_THREAD_STREAM_ADDED, AUDIO_THREAD_STREAM_REMOVED, - AUDIO_THREAD_A2DP_FLUSH, - AUDIO_THREAD_A2DP_THROTTLE_TIME, + AUDIO_THREAD_A2DP_ENCODE, AUDIO_THREAD_A2DP_WRITE, AUDIO_THREAD_DEV_STREAM_MIX, AUDIO_THREAD_CAPTURE_POST, @@ -315,48 +296,6 @@ enum AUDIO_THREAD_LOG_EVENTS { AUDIO_THREAD_SEVERE_UNDERRUN, AUDIO_THREAD_CAPTURE_DROP_TIME, AUDIO_THREAD_DEV_DROP_FRAMES, - AUDIO_THREAD_LOOPBACK_PUT, - AUDIO_THREAD_LOOPBACK_GET, - AUDIO_THREAD_LOOPBACK_SAMPLE_HOOK, - AUDIO_THREAD_DEV_OVERRUN, -}; - -/* Important events in main thread. - * MAIN_THREAD_DEV_CLOSE - When an iodev closes at stream removal. - * MAIN_THREAD_DEV_DISABLE - When an iodev is removed from active dev list. - * MAIN_THREAD_DEV_INIT - When an iodev opens when stream attachs. - * MAIN_THREAD_DEV_REOPEN - When an iodev reopens for format change. - * MAIN_THREAD_ADD_ACTIVE_NODE - When an iodev is set as an additional - * active device. - * MAIN_THREAD_SELECT_NODE - When UI selects an iodev as active. - * MAIN_THREAD_NODE_PLUGGED - When a jack of iodev is plugged/unplugged. - * MAIN_THREAD_ADD_TO_DEV_LIST - When iodev is added to list. - * MAIN_THREAD_INPUT_NODE_GAIN - When input node gain changes. - * MAIN_THREAD_OUTPUT_NODE_VOLUME - When output node volume changes. - * MAIN_THREAD_SET_OUTPUT_USER_MUTE - When output mute state is set. - * MAIN_THREAD_RESUME_DEVS - When system resumes and notifies CRAS. - * MAIN_THREAD_SUSPEND_DEVS - When system suspends and notifies CRAS. - * MAIN_THREAD_STREAM_ADDED - When an audio stream is added. - * MAIN_THREAD_STREAM_REMOVED - When an audio stream is removed. - */ -enum MAIN_THREAD_LOG_EVENTS { - /* iodev related */ - MAIN_THREAD_DEV_CLOSE, - MAIN_THREAD_DEV_DISABLE, - MAIN_THREAD_DEV_INIT, - MAIN_THREAD_DEV_REOPEN, - MAIN_THREAD_ADD_ACTIVE_NODE, - MAIN_THREAD_SELECT_NODE, - MAIN_THREAD_NODE_PLUGGED, - MAIN_THREAD_ADD_TO_DEV_LIST, - MAIN_THREAD_INPUT_NODE_GAIN, - MAIN_THREAD_OUTPUT_NODE_VOLUME, - MAIN_THREAD_SET_OUTPUT_USER_MUTE, - MAIN_THREAD_RESUME_DEVS, - MAIN_THREAD_SUSPEND_DEVS, - /* stream related */ - MAIN_THREAD_STREAM_ADDED, - MAIN_THREAD_STREAM_REMOVED, }; /* There are 8 bits of space for events. */ @@ -370,16 +309,12 @@ enum CRAS_BT_LOG_EVENTS { BT_A2DP_START, BT_A2DP_SUSPENDED, BT_CODEC_SELECTION, - BT_DEV_CONNECTED, - BT_DEV_DISCONNECTED, + BT_DEV_CONNECTED_CHANGE, BT_DEV_CONN_WATCH_CB, BT_DEV_SUSPEND_CB, BT_HFP_NEW_CONNECTION, BT_HFP_REQUEST_DISCONNECT, BT_HFP_SUPPORTED_FEATURES, - BT_HFP_HF_INDICATOR, - BT_HFP_SET_SPEAKER_GAIN, - BT_HFP_UPDATE_SPEAKER_GAIN, BT_HSP_NEW_CONNECTION, BT_HSP_REQUEST_DISCONNECT, BT_NEW_AUDIO_PROFILE_AFTER_CONNECT, @@ -387,8 +322,6 @@ enum CRAS_BT_LOG_EVENTS { BT_SCO_CONNECT, BT_TRANSPORT_ACQUIRE, BT_TRANSPORT_RELEASE, - BT_TRANSPORT_SET_VOLUME, - BT_TRANSPORT_UPDATE_VOLUME, }; struct __attribute__((__packed__)) audio_thread_event { @@ -460,24 +393,6 @@ struct __attribute__((__packed__)) audio_debug_info { struct audio_thread_event_log log; }; -struct __attribute__((__packed__)) main_thread_event { - uint32_t tag_sec; - uint32_t nsec; - uint32_t data1; - uint32_t data2; - uint32_t data3; -}; - -struct __attribute__((__packed__)) main_thread_event_log { - uint32_t write_pos; - uint32_t len; - struct main_thread_event log[MAIN_THREAD_EVENT_LOG_SIZE]; -}; - -struct __attribute__((__packed__)) main_thread_debug_info { - struct main_thread_event_log main_log; -}; - struct __attribute__((__packed__)) cras_bt_event { uint32_t tag_sec; uint32_t nsec; @@ -493,7 +408,6 @@ struct __attribute__((__packed__)) cras_bt_event_log { struct __attribute__((__packed__)) cras_bt_debug_info { struct cras_bt_event_log bt_log; - struct packet_status_logger wbs_logger; }; /* @@ -501,14 +415,11 @@ struct __attribute__((__packed__)) cras_bt_debug_info { * or they will be ignored by the handler. */ enum CRAS_AUDIO_THREAD_EVENT_TYPE { - AUDIO_THREAD_EVENT_A2DP_OVERRUN, - AUDIO_THREAD_EVENT_A2DP_THROTTLE, AUDIO_THREAD_EVENT_BUSYLOOP, AUDIO_THREAD_EVENT_DEBUG, AUDIO_THREAD_EVENT_SEVERE_UNDERRUN, AUDIO_THREAD_EVENT_UNDERRUN, AUDIO_THREAD_EVENT_DROP_SAMPLES, - AUDIO_THREAD_EVENT_DEV_OVERRUN, AUDIO_THREAD_EVENT_TYPE_COUNT, }; @@ -540,8 +451,16 @@ struct __attribute__((__packed__)) cras_audio_thread_snapshot_buffer { * mute_locked - 0 = unlocked, 1 = locked. * suspended - 1 = suspended, 0 = resumed. * capture_gain - Capture gain in dBFS * 100. + * capture_gain_target - Target capture gain in dBFS * 100. The actual + * capture gain will be subjected to current + * supported range. When active device/node changes, + * supported range changes accordingly. System state + * should try to re-apply target gain subjected to new + * range. * capture_mute - 0 = unmuted, 1 = muted. * capture_mute_locked - 0 = unlocked, 1 = locked. + * min_capture_gain - Min allowed capture gain in dBFS * 100. + * max_capture_gain - Max allowed capture gain in dBFS * 100. * num_streams_attached - Total number of streams since server started. * num_output_devs - Number of available output devices. * num_input_devs - Number of available input devices. @@ -571,17 +490,6 @@ struct __attribute__((__packed__)) cras_audio_thread_snapshot_buffer { * snapshot_buffer - ring buffer for storing audio thread snapshots. * bt_debug_info - ring buffer for storing bluetooth event logs. * bt_wbs_enabled - Whether or not bluetooth wideband speech is enabled. - * deprioritize_bt_wbs_mic - Whether Bluetooth wideband speech mic - * should be deprioritized for selecting as default audio input. - * main_thread_debug_info - ring buffer for storing main thread event logs. - * num_input_streams_with_permission - An array containing numbers of input - * streams with permission in each client type. - * noise_cancellation_enabled - Whether or not Noise Cancellation is enabled. - * hotword_pause_at_suspend - 1 = Pause hotword detection when the system - * suspends. Hotword detection is resumed after system resumes. - * 0 - Hotword detection is allowed to continue running after system - * suspends, so a detected hotword can wake up the device. - * */ #define CRAS_SERVER_STATE_VERSION 2 struct __attribute__((packed, aligned(4))) cras_server_state { @@ -594,8 +502,11 @@ struct __attribute__((packed, aligned(4))) cras_server_state { int32_t mute_locked; int32_t suspended; int32_t capture_gain; + int32_t capture_gain_target; int32_t capture_mute; int32_t capture_mute_locked; + int32_t min_capture_gain; + int32_t max_capture_gain; uint32_t num_streams_attached; uint32_t num_output_devs; uint32_t num_input_devs; @@ -618,11 +529,6 @@ struct __attribute__((packed, aligned(4))) cras_server_state { struct cras_audio_thread_snapshot_buffer snapshot_buffer; struct cras_bt_debug_info bt_debug_info; int32_t bt_wbs_enabled; - int32_t deprioritize_bt_wbs_mic; - struct main_thread_debug_info main_thread_debug_info; - uint32_t num_input_streams_with_permission[CRAS_NUM_CLIENT_TYPE]; - int32_t noise_cancellation_enabled; - int32_t hotword_pause_at_suspend; }; /* Actions for card add/remove/change. */ @@ -689,16 +595,12 @@ enum CRAS_NODE_TYPE { CRAS_NODE_TYPE_HOTWORD, CRAS_NODE_TYPE_POST_MIX_PRE_DSP, CRAS_NODE_TYPE_POST_DSP, - /* Type for the legacy BT narrow band mic .*/ - CRAS_NODE_TYPE_BLUETOOTH_NB_MIC, /* These value can be used for both output and input nodes. */ CRAS_NODE_TYPE_USB, CRAS_NODE_TYPE_BLUETOOTH, CRAS_NODE_TYPE_FALLBACK_NORMAL, CRAS_NODE_TYPE_FALLBACK_ABNORMAL, CRAS_NODE_TYPE_UNKNOWN, - CRAS_NODE_TYPE_ECHO_REFERENCE, - CRAS_NODE_TYPE_ALSA_LOOPBACK, }; /* Position values to described where a node locates on the system. diff --git a/cras/src/common/cras_util.h b/cras/src/common/cras_util.h index 96985ab2..01034242 100644 --- a/cras/src/common/cras_util.h +++ b/cras/src/common/cras_util.h @@ -187,33 +187,6 @@ static inline uint64_t cras_frames_since_time(const struct timespec *beg, return cras_time_to_frames(&time_since, rate); } -/* Calculates frames until time end. */ -static inline uint64_t cras_frames_until_time(const struct timespec *end, - unsigned int rate) -{ - struct timespec now, time_until; - - clock_gettime(CLOCK_MONOTONIC_RAW, &now); - if (!timespec_after(end, &now)) - return 0; - - subtract_timespecs(end, &now, &time_until); - return cras_time_to_frames(&time_until, rate); -} - -/* Returns true if the difference between a and b is shorter than t. */ -static inline bool timespec_diff_shorter_than(const struct timespec *a, - const struct timespec *b, - const struct timespec *t) -{ - struct timespec diff; - if (timespec_after(a, b)) - subtract_timespecs(a, b, &diff); - else - subtract_timespecs(b, a, &diff); - return timespec_after(t, &diff); -} - /* Poll on the given file descriptors. * * See ppoll(). This implementation changes the value of timeout to the diff --git a/cras/src/common/dumper.c b/cras/src/common/dumper.c index 5da16df8..50789e8e 100644 --- a/cras/src/common/dumper.c +++ b/cras/src/common/dumper.c @@ -108,23 +108,18 @@ struct dumper *mem_dumper_create() struct dumper *dumper = calloc(1, sizeof(struct dumper)); struct mem_data *data = calloc(1, sizeof(struct mem_data)); if (!dumper || !data) - goto error; + return NULL; data->size = 0; data->capacity = 80; data->buf = malloc(data->capacity); - if (!data->buf) - goto error; + if (!data->buf) { + free(data); + return NULL; + } data->buf[0] = '\0'; dumper->data = data; dumper->vprintf = &mem_vprintf; return dumper; - -error: - if (dumper) - free(dumper); - if (data) - free(data); - return NULL; } void mem_dumper_free(struct dumper *dumper) diff --git a/cras/src/common/packet_status_logger.c b/cras/src/common/packet_status_logger.c deleted file mode 100644 index f1be6965..00000000 --- a/cras/src/common/packet_status_logger.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <string.h> -#include <time.h> - -#include "cras_util.h" -#include "packet_status_logger.h" - -void packet_status_logger_init(struct packet_status_logger *logger) -{ - memset(logger->data, 0, PACKET_STATUS_LEN_BYTES); - logger->size = PACKET_STATUS_LEN_BYTES * 8; - logger->wp = 0; - logger->num_wraps = 0; - clock_gettime(CLOCK_MONOTONIC_RAW, &logger->ts); -} - -void packet_status_logger_update(struct packet_status_logger *logger, bool val) -{ - if (val) { - logger->data[logger->wp / 8] |= 1UL << (logger->wp % 8); - } else { - logger->data[logger->wp / 8] &= ~(1UL << (logger->wp % 8)); - } - logger->wp++; - if (logger->wp >= logger->size) { - logger->wp %= logger->size; - logger->num_wraps += 1; - } - if (logger->wp == 0 || (logger->num_wraps == 0 && logger->wp == 1)) - clock_gettime(CLOCK_MONOTONIC_RAW, &logger->ts); -} diff --git a/cras/src/common/packet_status_logger.h b/cras/src/common/packet_status_logger.h deleted file mode 100644 index 3bc90041..00000000 --- a/cras/src/common/packet_status_logger.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef PACKET_STATUS_LOGGER_ -#define PACKET_STATUS_LOGGER_ - -#include <stdint.h> -#include <stdbool.h> - -#define PACKET_STATUS_LEN_BYTES 64 -#define WBS_FRAME_NS 7500000 - -/* Avoid 32, 40, 64 consecutive hex characters so CrOS feedback redact - * tool doesn't trim our dump. */ -#define PACKET_STATUS_LOG_LINE_WRAP 50 - -/* - * Object to log consecutive packets' status. - * Members: - * data - Bytes to store packets' status. - * size - Total number of bits in |data|. - * wp - Position of the next bit to log packet status. - * num_wraps - Number of times the ring buffer has wrapped. - * ts - The timestamp of the last time when the first bit of |data| updated. - */ -struct packet_status_logger { - uint8_t data[PACKET_STATUS_LEN_BYTES]; - int size; - int wp; - int num_wraps; - struct timespec ts; -}; - -/* Initializes the packet status logger. */ -void packet_status_logger_init(struct packet_status_logger *logger); - -/* Updates the next packet status to logger. */ -void packet_status_logger_update(struct packet_status_logger *logger, bool val); - -/* Rewinds logger's time stamp to calculate the beginning. - * If logger's ring buffer hasn't wrapped, simply return logger_ts. - * Otherwise beginning_ts = logger_ts - WBS_FRAME_NS * (size - wp) - */ -static inline void -packet_status_logger_begin_ts(const struct packet_status_logger *logger, - struct timespec *ts) -{ - long nsec = WBS_FRAME_NS * (logger->size - logger->wp); - - *ts = logger->ts; - if (logger->num_wraps == 0) - return; - while (nsec > 1000000000L) { - ts->tv_sec--; - nsec -= 1000000000L; - } - ts->tv_nsec -= nsec; - if (ts->tv_nsec < 0) { - ts->tv_sec--; - ts->tv_nsec += 1000000000L; - } -} - -/* Fast-forwards the logger's time stamp to calculate the end. - * In other words, end_ts = logger_ts + WBS_FRAME_NS * wp - */ -static inline void -packet_status_logger_end_ts(const struct packet_status_logger *logger, - struct timespec *ts) -{ - *ts = logger->ts; - ts->tv_nsec += WBS_FRAME_NS * logger->wp; - while (ts->tv_nsec > 1000000000L) { - ts->tv_sec++; - ts->tv_nsec -= 1000000000L; - } -} - -/* Prints the logger data in hex format */ -static inline void -packet_status_logger_dump_hex(const struct packet_status_logger *logger) -{ - int i = logger->wp / 8; - - /* Print the bits after wp only if buffer has wrapped. */ - if (logger->num_wraps) { - if (logger->wp % 8) - printf("%.2x", - logger->data[i] & (0xff << (logger->wp % 8))); - for (; i < PACKET_STATUS_LEN_BYTES; i++) - printf("%.2x", logger->data[i]); - } - for (i = 0; i < logger->wp / 8; i++) - printf("%.2x", logger->data[i]); - if (logger->wp % 8) - printf("%.2x", logger->data[i] & (~(0xff << (logger->wp % 8)))); - printf("\n"); -} - -/* Prints the logger data in binary format */ -static inline void -packet_status_logger_dump_binary(const struct packet_status_logger *logger) -{ - /* Don't print the bits after wp if buffer hasn't wrapped. */ - int head = logger->num_wraps ? logger->wp : 0; - int len = logger->num_wraps ? logger->size : logger->wp; - int i, j; - - for (i = 0; i < len; ++i) { - j = (head + i) % logger->size; - printf("%d", (logger->data[j / 8] >> (j % 8)) & 1U); - if ((i + 1) % PACKET_STATUS_LOG_LINE_WRAP == 0) - printf("\n"); - } - /* Fill indicator digit 'D' until the last line wraps. */ - if (len % PACKET_STATUS_LOG_LINE_WRAP) { - while (len % PACKET_STATUS_LOG_LINE_WRAP) { - printf("D"); - ++len; - } - printf("\n"); - } -} - -#endif /* PACKET_STATUS_LOGGER_ */ diff --git a/cras/src/common/utlist.h b/cras/src/common/utlist.h index 6c7f1e32..e3ee6304 100644 --- a/cras/src/common/utlist.h +++ b/cras/src/common/utlist.h @@ -194,7 +194,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define DL_DELETE(head, del) \ do { \ - assert((head) != NULL); \ assert((del)->prev != NULL); \ if ((del)->prev == (del)) { \ (head) = NULL; \ diff --git a/cras/src/dsp/drc.c b/cras/src/dsp/drc.c index e6098419..1b2639a0 100644 --- a/cras/src/dsp/drc.c +++ b/cras/src/dsp/drc.c @@ -104,7 +104,7 @@ static void set_default_parameters(struct drc *drc) param[PARAM_RELEASE_ZONE3] = 0.42f; param[PARAM_RELEASE_ZONE4] = 0.98f; - /* This is effectively a main volume on the compressed + /* This is effectively a master volume on the compressed * signal */ param[PARAM_POST_GAIN] = 0; /* dB */ param[PARAM_ENABLED] = 0; diff --git a/cras/src/dsp/drc_kernel.c b/cras/src/dsp/drc_kernel.c index 8c3404fc..c0eb100b 100644 --- a/cras/src/dsp/drc_kernel.c +++ b/cras/src/dsp/drc_kernel.c @@ -257,7 +257,7 @@ void dk_set_parameters(struct drc_kernel *dk, float db_threshold, float db_knee, /* Empirical/perceptual tuning. */ full_range_makeup_gain = powf(full_range_makeup_gain, 0.6f); - dk->main_linear_gain = + dk->master_linear_gain = decibels_to_linear(db_post_gain) * full_range_makeup_gain; /* Attack parameters. */ @@ -566,7 +566,7 @@ static void dk_update_detector_average(struct drc_kernel *dk) #include <arm_neon.h> static void dk_compress_output(struct drc_kernel *dk) { - const float main_linear_gain = dk->main_linear_gain; + const float master_linear_gain = dk->master_linear_gain; const float envelope_rate = dk->envelope_rate; const float scaled_desired_gain = dk->scaled_desired_gain; const float compressor_gain = dk->compressor_gain; @@ -638,7 +638,7 @@ static void dk_compress_output(struct drc_kernel *dk) [A7]"w"(A7), [base]"w"(vdupq_n_f32(scaled_desired_gain)), [r4]"w"(vdupq_n_f32(r*r*r*r)), - [g]"w"(vdupq_n_f32(main_linear_gain)) + [g]"w"(vdupq_n_f32(master_linear_gain)) : /* clobber */ "memory", "cc"); // clang-format on @@ -698,7 +698,7 @@ static void dk_compress_output(struct drc_kernel *dk) [A7]"w"(A7), [one]"w"(vdupq_n_f32(1)), [r4]"w"(vdupq_n_f32(r*r*r*r)), - [g]"w"(vdupq_n_f32(main_linear_gain)) + [g]"w"(vdupq_n_f32(master_linear_gain)) : /* clobber */ "memory", "cc"); // clang-format on @@ -709,7 +709,7 @@ static void dk_compress_output(struct drc_kernel *dk) #include <emmintrin.h> static void dk_compress_output(struct drc_kernel *dk) { - const float main_linear_gain = dk->main_linear_gain; + const float master_linear_gain = dk->master_linear_gain; const float envelope_rate = dk->envelope_rate; const float scaled_desired_gain = dk->scaled_desired_gain; const float compressor_gain = dk->compressor_gain; @@ -789,7 +789,7 @@ static void dk_compress_output(struct drc_kernel *dk) [A7]"x"(A7), [base]"x"(_mm_set1_ps(scaled_desired_gain)), [r4]"x"(_mm_set1_ps(r*r*r*r)), - [g]"x"(_mm_set1_ps(main_linear_gain)) + [g]"x"(_mm_set1_ps(master_linear_gain)) : /* clobber */ "memory", "cc"); // clang-format on @@ -862,7 +862,7 @@ static void dk_compress_output(struct drc_kernel *dk) [A7]"x"(A7), [one]"x"(_mm_set1_ps(1)), [r4]"x"(_mm_set1_ps(r*r*r*r)), - [g]"x"(_mm_set1_ps(main_linear_gain)) + [g]"x"(_mm_set1_ps(master_linear_gain)) : /* clobber */ "memory", "cc"); // clang-format on @@ -872,7 +872,7 @@ static void dk_compress_output(struct drc_kernel *dk) #else static void dk_compress_output(struct drc_kernel *dk) { - const float main_linear_gain = dk->main_linear_gain; + const float master_linear_gain = dk->master_linear_gain; const float envelope_rate = dk->envelope_rate; const float scaled_desired_gain = dk->scaled_desired_gain; const float compressor_gain = dk->compressor_gain; @@ -902,8 +902,8 @@ static void dk_compress_output(struct drc_kernel *dk) float post_warp_compressor_gain = warp_sinf(x[j] + base); - /* Calculate total gain using main gain. */ - float total_gain = main_linear_gain * + /* Calculate total gain using master gain. */ + float total_gain = master_linear_gain * post_warp_compressor_gain; /* Apply final gain. */ @@ -936,8 +936,8 @@ static void dk_compress_output(struct drc_kernel *dk) float post_warp_compressor_gain = warp_sinf(x[j]); - /* Calculate total gain using main gain. */ - float total_gain = main_linear_gain * + /* Calculate total gain using master gain. */ + float total_gain = master_linear_gain * post_warp_compressor_gain; /* Apply final gain. */ diff --git a/cras/src/dsp/drc_kernel.h b/cras/src/dsp/drc_kernel.h index 2ed9956e..1157f225 100644 --- a/cras/src/dsp/drc_kernel.h +++ b/cras/src/dsp/drc_kernel.h @@ -67,7 +67,7 @@ struct drc_kernel { float kA, kB, kC, kD, kE; /* Calculated parameters */ - float main_linear_gain; + float master_linear_gain; float attack_frames; float sat_release_frames_inv_neg; float sat_release_rate_at_neg_two_db; diff --git a/cras/src/fuzz/Dockerfile b/cras/src/fuzz/Dockerfile index caffa995..cf08a6e4 100644 --- a/cras/src/fuzz/Dockerfile +++ b/cras/src/fuzz/Dockerfile @@ -1,13 +1,57 @@ -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Defines a docker image that can build cras fuzzers. # FROM gcr.io/oss-fuzz-base/base-builder -LABEL maintainer="dgreid@chromium.org" -COPY . "${SRC}/adhd" -COPY cras/src/fuzz/build.sh "${SRC}/build.sh" -RUN "${SRC}/adhd/cras/install_deps.sh" -RUN mkdir -p /etc/cras && cp "${SRC}/adhd/cras-config/dsp.ini.sample" /etc/cras +RUN apt-get -y update && \ + apt-get install -y \ + automake \ + build-essential \ + cmake \ + ctags \ + g++ \ + gdb \ + git \ + ladspa-sdk \ + libasound-dev \ + libdbus-1-dev \ + libgtest-dev \ + libncurses5-dev \ + libsbc-dev \ + libsndfile-dev \ + libspeexdsp-dev \ + libtool \ + libudev-dev \ + wget +RUN apt-get clean +RUN cd /tmp && git clone https://github.com/ndevilla/iniparser.git && \ + cd iniparser && \ + make && \ + cp libiniparser.* /usr/local/lib && \ + cp src/dictionary.h src/iniparser.h /usr/local/include && \ + chmod 644 /usr/local/include/dictionary.h /usr/local/include/iniparser.h && \ + chmod 644 /usr/local/lib/libiniparser.a && \ + chmod 755 /usr/local/lib/libiniparser.so.* +RUN cd /usr/src/gtest && \ + cmake . && \ + make && \ + chmod 644 *.a && \ + cp *.a /usr/local/lib + +# Need to build and install alsa so there is a static lib. +RUN mkdir -p /tmp/alsa-build && cd /tmp/alsa-build && \ + wget ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.1.4.1.tar.bz2 && \ + bzip2 -f -d alsa-lib-* && \ + tar xf alsa-lib-* && \ + cd alsa-lib-* && \ + ./configure --enable-static --disable-shared && \ + make clean && \ + make -j$(nproc) all && \ + make install + + +COPY . /src/cras/ +COPY src/fuzz/build.sh /src/ diff --git a/cras/src/fuzz/README.md b/cras/src/fuzz/README.md index 0d235cec..72716023 100644 --- a/cras/src/fuzz/README.md +++ b/cras/src/fuzz/README.md @@ -11,26 +11,22 @@ Detailed instructions are available at: https://github.com/google/oss-fuzz/blob/ ``` sudo adduser $USER docker ``` -### Sync to the latest base-builder -``` -docker pull gcr.io/oss-fuzz-base/base-builder -``` -### Build a container from the adhd directory +### Build a container from the cras directory ``` -docker build -t ossfuzz/cras -f cras/src/fuzz/Dockerfile . +docker build -t ossfuzz/cras -f src/fuzz/Dockerfile . ``` -Add `--no-cache` if you want a complete rebuild. ### Build fuzzers ``` -docker run --cap-add=SYS_PTRACE -ti --rm -v /tmp/fuzzers:/out ossfuzz/cras +docker run --cap-add=SYS_PTRACE -ti --rm -v $(pwd):/src/cras -v /tmp/fuzzers:/out \ + ossfuzz/cras ``` ### Look in /tmp/fuzzers to see the executables. Run them like so: ``` -docker run --cap-add=SYS_PTRACE -ti -v $(pwd)/cras/src/fuzz/corpus:/corpus \ - -v /tmp/fuzzers:/out ossfuzz/cras /out/rclient_message \ +docker run --cap-add=SYS_PTRACE -ti -v $(pwd)/src/fuzz/corpus:/corpus \ + -v /tmp/fuzzers:/out ossfuzz/base-runner /out/rclient_message \ /corpus -runs=100 ``` @@ -38,7 +34,7 @@ docker run --cap-add=SYS_PTRACE -ti -v $(pwd)/cras/src/fuzz/corpus:/corpus \ Go into docker console by ``` -docker run --cap-add=SYS_PTRACE -ti -v $(pwd)/cras/src/fuzz/corpus:/corpus \ - -v /tmp/fuzzers:/out ossfuzz/cras /bin/bash +docker run --cap-add=SYS_PTRACE -ti -v $(pwd)/src/fuzz/corpus:/corpus \ + -v /tmp/fuzzers:/out ossfuzz/base-runner /bin/bash ``` and start debugging. diff --git a/cras/src/fuzz/build.sh b/cras/src/fuzz/build.sh index 44413a7f..ac4ad2fb 100755 --- a/cras/src/fuzz/build.sh +++ b/cras/src/fuzz/build.sh @@ -1,24 +1,22 @@ #!/bin/bash -eux - -# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # -# Builds fuzzers from within a container into ${OUT} directory. -# Expects "${SRC}/adhd" to contain an adhd checkout. +# Builds fuzzers from within a container into /out/ directory. +# Expects /src/cras to contain a cras checkout. -cd "${SRC}/adhd/cras" +mkdir $WORK/cras +cd $SRC/cras ./git_prepare.sh - -FUZZER_LDFLAGS="${FUZZER_LDFLAGS} ${LIB_FUZZING_ENGINE}" -./configure --enable-fuzzer - -# Compile fuzzers +./configure --disable-dbus --disable-webrtc-apm make -j$(nproc) -# Copy fuzzers and dependencies to "${OUT}" directory -cp "${SRC}/adhd/cras/src/cras_rclient_message_fuzzer" "${OUT}/rclient_message" -zip -j "${OUT}/rclient_message_corpus.zip" ./src/fuzz/corpus/* - -cp "${SRC}/adhd/cras/src/cras_hfp_slc_fuzzer" "${OUT}/cras_hfp_slc" -cp "${SRC}/adhd/cras/src/fuzz/cras_hfp_slc.dict" "${OUT}/cras_hfp_slc.dict" +$CXX $CXXFLAGS $FUZZER_LDFLAGS \ + $SRC/cras/src/fuzz/rclient_message.cc -o $OUT/rclient_message \ + -I $SRC/cras/src/server \ + -I $SRC/cras/src/common \ + $SRC/cras/src/.libs/libcrasserver.a \ + -lpthread -lrt -ludev -ldl -lm \ + -lFuzzingEngine \ + -Wl,-Bstatic -liniparser -lasound -lspeexdsp -Wl,-Bdynamic diff --git a/cras/src/fuzz/cras_hfp_slc.cc b/cras/src/fuzz/cras_hfp_slc.cc deleted file mode 100644 index 4a76ea46..00000000 --- a/cras/src/fuzz/cras_hfp_slc.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <assert.h> -#include <fuzzer/FuzzedDataProvider.h> -#include <stddef.h> -#include <stdint.h> - -extern "C" { -#include "cras_bt_device.h" -#include "cras_bt_log.h" -#include "cras_hfp_slc.h" -#include "cras_iodev_list.h" -#include "cras_mix.h" -#include "cras_observer.h" -#include "cras_shm.h" -#include "cras_system_state.h" - -struct cras_bt_event_log* btlog; -} - -int disconnect_cb(struct hfp_slc_handle*) { - return 0; -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider data_provider(data, size); - bool is_hsp = data_provider.ConsumeIntegralInRange(0, 1); - int ag_supported_features = data_provider.ConsumeIntegral<int>(); - std::string command = data_provider.ConsumeRemainingBytesAsString(); - int fd = open("/dev/null", O_RDWR); - - struct cras_bt_device* bt_dev = cras_bt_device_create(NULL, ""); - struct hfp_slc_handle* handle = hfp_slc_create( - fd, is_hsp, ag_supported_features, bt_dev, NULL, &disconnect_cb); - if (!handle) - return 0; - - handle_at_command_for_test(handle, command.c_str()); - - hfp_slc_destroy(handle); - cras_bt_device_remove(bt_dev); - return 0; -} - -extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { - char* shm_name; - if (asprintf(&shm_name, "/cras-%d", getpid()) < 0) - exit(-ENOMEM); - struct cras_server_state* exp_state = - (struct cras_server_state*)calloc(1, sizeof(*exp_state)); - if (!exp_state) - exit(-1); - int rw_shm_fd = open("/dev/null", O_RDWR); - int ro_shm_fd = open("/dev/null", O_RDONLY); - cras_system_state_init("/tmp", shm_name, rw_shm_fd, ro_shm_fd, exp_state, - sizeof(*exp_state)); - free(shm_name); - cras_observer_server_init(); - cras_mix_init(0); - cras_iodev_list_init(); - btlog = cras_bt_event_log_init(); - return 0; -} diff --git a/cras/src/fuzz/cras_hfp_slc.dict b/cras/src/fuzz/cras_hfp_slc.dict deleted file mode 100644 index cfc49895..00000000 --- a/cras/src/fuzz/cras_hfp_slc.dict +++ /dev/null @@ -1,23 +0,0 @@ -"ATA" -"ATD" -"AT+BAC" -"AT+BCS" -"AT+BIA" -"AT+BIEV" -"AT+BIND" -"AT+BLDN" -"AT+BRSF" -"AT+CCWA" -"AT+CHUP" -"AT+CIND" -"AT+CKPD" -"AT+CLCC" -"AT+CLIP" -"AT+CMEE" -"AT+CMER" -"AT+CNUM" -"AT+COPS" -"AT+IPHONEACCEV" -"AT+VG" -"AT+VTS" -"AT+XAPL" diff --git a/cras/src/fuzz/rclient_message.cc b/cras/src/fuzz/rclient_message.cc index eacf9dab..a2a5650a 100644 --- a/cras/src/fuzz/rclient_message.cc +++ b/cras/src/fuzz/rclient_message.cc @@ -4,37 +4,21 @@ */ #include <assert.h> -#include <fuzzer/FuzzedDataProvider.h> #include <stddef.h> #include <stdint.h> extern "C" { -#include "cras_apm_list.h" -#include "cras_bt_log.h" -#include "cras_dsp.h" #include "cras_iodev_list.h" #include "cras_mix.h" #include "cras_observer.h" #include "cras_rclient.h" #include "cras_shm.h" #include "cras_system_state.h" - -struct cras_bt_event_log* btlog; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { cras_rclient* client = cras_rclient_create(0, 0, CRAS_CONTROL); - if (size < 300) { - /* Feeds input data directly if the given bytes is too short. */ - cras_rclient_buffer_from_client(client, data, size, NULL, 0); - } else { - FuzzedDataProvider data_provider(data, size); - int fds[1] = {0}; - int num_fds = data_provider.ConsumeIntegralInRange(0, 1); - std::vector<uint8_t> msg = data_provider.ConsumeRemainingBytes<uint8_t>(); - cras_rclient_buffer_from_client(client, msg.data(), msg.size(), fds, - num_fds); - } + cras_rclient_buffer_from_client(client, data, size, NULL, 0); cras_rclient_destroy(client); return 0; @@ -56,13 +40,7 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { cras_observer_server_init(); cras_mix_init(0); - cras_apm_list_init("/etc/cras"); cras_iodev_list_init(); - /* For cros fuzz, emerge adhd with USE=fuzzer will copy dsp.ini.sample to - * etc/cras. For OSS-Fuzz the Dockerfile will be responsible for copying the - * file. This shouldn't crash CRAS even if the dsp file does not exist. */ - cras_dsp_init("/etc/cras/dsp.ini.sample"); - /* Initializes btlog for CRAS_SERVER_DUMP_BT path with CRAS_DBUS defined. */ - btlog = cras_bt_event_log_init(); + return 0; } diff --git a/cras/src/libcras/cras_client.c b/cras/src/libcras/cras_client.c index 8420db1f..fe54e0e3 100644 --- a/cras/src/libcras/cras_client.c +++ b/cras/src/libcras/cras_client.c @@ -119,8 +119,7 @@ struct thread_state { }; /* Parameters used when setting up a capture or playback stream. See comment - * above cras_client_stream_params_create or libcras_stream_params_set in the - * header for descriptions. */ + * above cras_client_create_stream_params in the header for descriptions. */ struct cras_stream_params { enum CRAS_STREAM_DIRECTION direction; size_t buffer_frames; @@ -134,14 +133,15 @@ struct cras_stream_params { cras_unified_cb_t unified_cb; cras_error_cb_t err_cb; struct cras_audio_format format; - libcras_stream_cb_t stream_cb; + int client_shm_fd; + size_t client_shm_size; }; /* Represents an attached audio stream. * id - Unique stream identifier. * aud_fd - After server connects audio messages come in here. * direction - playback, capture, or loopback (see CRAS_STREAM_DIRECTION). - * flags - Currently only used for CRAS_INPUT_STREAM_FLAG. + * flags - Currently not used. * volume_scaler - Amount to scale the stream by, 0.0 to 1.0. Client could * change this scaler value before stream actually connected, so we need * to cache it until shm is prepared and apply it. @@ -276,92 +276,6 @@ struct cras_hotword_handle { void *user_data; }; -struct cras_stream_cb_data { - cras_stream_id_t stream_id; - enum CRAS_STREAM_DIRECTION direction; - uint8_t *buf; - unsigned int frames; - struct timespec sample_ts; - void *user_arg; -}; - -int stream_cb_get_stream_id(struct cras_stream_cb_data *data, - cras_stream_id_t *id) -{ - *id = data->stream_id; - return 0; -} - -int stream_cb_get_buf(struct cras_stream_cb_data *data, uint8_t **buf) -{ - *buf = data->buf; - return 0; -} - -int stream_cb_get_frames(struct cras_stream_cb_data *data, unsigned int *frames) -{ - *frames = data->frames; - return 0; -} - -int stream_cb_get_latency(struct cras_stream_cb_data *data, - struct timespec *latency) -{ - if (data->direction == CRAS_STREAM_INPUT) - cras_client_calc_capture_latency(&data->sample_ts, latency); - else - cras_client_calc_playback_latency(&data->sample_ts, latency); - return 0; -} - -int stream_cb_get_user_arg(struct cras_stream_cb_data *data, void **user_arg) -{ - *user_arg = data->user_arg; - return 0; -} - -struct libcras_stream_cb_data * -libcras_stream_cb_data_create(cras_stream_id_t stream_id, - enum CRAS_STREAM_DIRECTION direction, - uint8_t *buf, unsigned int frames, - struct timespec sample_ts, void *user_arg) -{ - struct libcras_stream_cb_data *data = - (struct libcras_stream_cb_data *)calloc( - 1, sizeof(struct libcras_stream_cb_data)); - if (!data) { - syslog(LOG_ERR, "cras_client: calloc: %s", strerror(errno)); - return NULL; - } - data->data_ = (struct cras_stream_cb_data *)calloc( - 1, sizeof(struct cras_stream_cb_data)); - if (!data->data_) { - syslog(LOG_ERR, "cras_client: calloc: %s", strerror(errno)); - free(data); - return NULL; - } - data->api_version = CRAS_API_VERSION; - data->get_stream_id = stream_cb_get_stream_id; - data->get_buf = stream_cb_get_buf; - data->get_frames = stream_cb_get_frames; - data->get_latency = stream_cb_get_latency; - data->get_user_arg = stream_cb_get_user_arg; - data->data_->stream_id = stream_id; - data->data_->direction = direction; - data->data_->buf = buf; - data->data_->frames = frames; - data->data_->sample_ts = sample_ts; - data->data_->user_arg = user_arg; - return data; -} - -void libcras_stream_cb_data_destroy(struct libcras_stream_cb_data *data) -{ - if (data) - free(data->data_); - free(data); -} - /* * Local Helpers */ @@ -371,10 +285,6 @@ static int client_thread_rm_stream(struct cras_client *client, static int handle_message_from_server(struct cras_client *client); static int reregister_notifications(struct cras_client *client); -static struct libcras_node_info * -libcras_node_info_create(struct cras_iodev_info *iodev, - struct cras_ionode_info *ionode); - /* * Unlock the server_state_rwlock if lock_rc is 0. * @@ -1176,7 +1086,6 @@ static int handle_capture_data_ready(struct client_stream *stream, uint8_t *captured_frames; struct timespec ts; int rc = 0; - struct libcras_stream_cb_data *data; config = stream->config; /* If this message is for an output stream, log error and drop it. */ @@ -1191,24 +1100,14 @@ static int handle_capture_data_ready(struct client_stream *stream, cras_timespec_to_timespec(&ts, &stream->shm->header->ts); - if (config->stream_cb) { - data = libcras_stream_cb_data_create( - stream->id, stream->direction, captured_frames, - num_frames, ts, config->user_data); - if (!data) - return -errno; - frames = config->stream_cb(data); - libcras_stream_cb_data_destroy(data); - data = NULL; - } else if (config->unified_cb) { + if (config->unified_cb) frames = config->unified_cb(stream->client, stream->id, captured_frames, NULL, num_frames, &ts, NULL, config->user_data); - } else { + else frames = config->aud_cb(stream->client, stream->id, captured_frames, num_frames, &ts, config->user_data); - } if (frames < 0) { send_stream_message(stream, CLIENT_STREAM_EOF); rc = frames; @@ -1255,7 +1154,6 @@ static int handle_playback_request(struct client_stream *stream, struct cras_stream_params *config; struct cras_audio_shm *shm = stream->shm; struct timespec ts; - struct libcras_stream_cb_data *data; config = stream->config; @@ -1273,24 +1171,13 @@ static int handle_playback_request(struct client_stream *stream, cras_timespec_to_timespec(&ts, &shm->header->ts); /* Get samples from the user */ - if (config->stream_cb) { - data = libcras_stream_cb_data_create(stream->id, - stream->direction, buf, - num_frames, ts, - config->user_data); - if (!data) - return -errno; - frames = config->stream_cb(data); - libcras_stream_cb_data_destroy(data); - data = NULL; - } else if (config->unified_cb) { + if (config->unified_cb) frames = config->unified_cb(stream->client, stream->id, NULL, buf, num_frames, NULL, &ts, config->user_data); - } else { + else frames = config->aud_cb(stream->client, stream->id, buf, num_frames, &ts, config->user_data); - } if (frames < 0) { send_stream_message(stream, CLIENT_STREAM_EOF); rc = frames; @@ -1497,6 +1384,7 @@ static int stream_connected(struct client_stream *stream, { int rc, samples_prot; unsigned int i; + struct cras_audio_format mfmt; struct cras_shm_info header_info, samples_info; if (msg->err || num_fds != 2) { @@ -1506,6 +1394,8 @@ static int stream_connected(struct client_stream *stream, goto err_ret; } + unpack_cras_audio_format(&mfmt, &msg->format); + rc = cras_shm_info_init_with_fd(stream_fds[0], cras_shm_header_size(), &header_info); if (rc < 0) @@ -1518,6 +1408,7 @@ static int stream_connected(struct client_stream *stream, goto err_ret; } + samples_prot = 0; if (stream->direction == CRAS_STREAM_OUTPUT) samples_prot = PROT_WRITE; else @@ -1552,6 +1443,8 @@ static int send_connect_message(struct cras_client *client, int rc; struct cras_connect_message serv_msg; int sock[2] = { -1, -1 }; + int fds[2] = { -1, -1 }; + unsigned int num_fds; /* Create a socket pair for the server to notify of audio events. */ rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); @@ -1561,16 +1454,21 @@ static int send_connect_message(struct cras_client *client, goto fail; } - cras_fill_connect_message(&serv_msg, stream->config->direction, - stream->id, stream->config->stream_type, - stream->config->client_type, - stream->config->buffer_frames, - stream->config->cb_threshold, stream->flags, - stream->config->effects, - stream->config->format, dev_idx); + cras_fill_connect_message( + &serv_msg, stream->config->direction, stream->id, + stream->config->stream_type, stream->config->client_type, + stream->config->buffer_frames, stream->config->cb_threshold, + stream->flags, stream->config->effects, stream->config->format, + dev_idx, stream->config->client_shm_size); + fds[0] = sock[1]; + num_fds = 1; + if (stream->config->client_shm_fd >= 0) { + fds[1] = stream->config->client_shm_fd; + num_fds++; + } rc = cras_send_with_fds(client->server_fd, &serv_msg, sizeof(serv_msg), - &sock[1], 1); + fds, num_fds); if (rc != sizeof(serv_msg)) { rc = EIO; syslog(LOG_ERR, @@ -1580,6 +1478,8 @@ static int send_connect_message(struct cras_client *client, stream->aud_fd = sock[0]; close(sock[1]); + if (stream->config->client_shm_fd != -1) + close(stream->config->client_shm_fd); return 0; fail: @@ -1587,6 +1487,8 @@ fail: close(sock[0]); if (sock[1] != -1) close(sock[1]); + if (stream->config->client_shm_fd != -1) + close(stream->config->client_shm_fd); return rc; } @@ -1602,30 +1504,18 @@ static int client_thread_add_stream(struct cras_client *client, cras_stream_id_t new_id; struct client_stream *out; - if ((stream->flags & HOTWORD_STREAM) == HOTWORD_STREAM) { + /* Find the hotword device index. */ + if ((stream->flags & HOTWORD_STREAM) == HOTWORD_STREAM && + dev_idx == NO_DEVICE) { int hotword_idx; hotword_idx = cras_client_get_first_dev_type_idx( client, CRAS_NODE_TYPE_HOTWORD, CRAS_STREAM_INPUT); - - /* Find the hotword device index. */ - if (dev_idx == NO_DEVICE) { - if (hotword_idx < 0) { - syslog(LOG_ERR, - "cras_client: add_stream: No hotword dev"); - return hotword_idx; - } else { - dev_idx = (uint32_t)hotword_idx; - } - } - /* A known Use case for client to pin hotword stream on a not - * hotword device is to use internal mic for Assistant to work - * on board without usable DSP hotwording. We assume there will - * be only one hotword device exists. */ - else if (dev_idx != (uint32_t)hotword_idx) { - /* Unmask the flag to fallback to normal pinned stream - * on specified device. */ - stream->flags &= ~HOTWORD_STREAM; + if (hotword_idx < 0) { + syslog(LOG_ERR, + "cras_client: add_stream: Finding hotword dev"); + return hotword_idx; } + dev_idx = hotword_idx; } /* Find an available stream id. */ @@ -2252,7 +2142,7 @@ int cras_client_create_with_type(struct cras_client **client, rc = fill_socket_file((*client), conn_type); if (rc < 0) { - goto free_server_event_fd; + goto free_error; } rc = cras_file_wait_create((*client)->sock_file, @@ -2285,11 +2175,10 @@ int cras_client_create_with_type(struct cras_client **client, return 0; free_error: - cras_file_wait_destroy((*client)->sock_file_wait); - free((void *)(*client)->sock_file); -free_server_event_fd: if ((*client)->server_event_fd >= 0) close((*client)->server_event_fd); + cras_file_wait_destroy((*client)->sock_file_wait); + free((void *)(*client)->sock_file); free_cond: pthread_cond_destroy(&(*client)->stream_start_cond); free_lock: @@ -2370,8 +2259,9 @@ struct cras_stream_params *cras_client_stream_params_create( params->user_data = user_data; params->aud_cb = aud_cb; params->unified_cb = 0; - params->stream_cb = 0; params->err_cb = err_cb; + params->client_shm_fd = -1; + params->client_shm_size = 0; memcpy(&(params->format), format, sizeof(*format)); return params; } @@ -2422,6 +2312,14 @@ void cras_client_stream_params_disable_vad(struct cras_stream_params *params) params->effects &= ~APM_VOICE_DETECTION; } +void cras_client_stream_params_configure_client_shm( + struct cras_stream_params *params, int client_shm_fd, + size_t client_shm_size) +{ + params->client_shm_fd = client_shm_fd; + params->client_shm_size = client_shm_size; +} + struct cras_stream_params *cras_client_unified_params_create( enum CRAS_STREAM_DIRECTION direction, unsigned int block_size, enum CRAS_STREAM_TYPE stream_type, uint32_t flags, void *user_data, @@ -2444,8 +2342,9 @@ struct cras_stream_params *cras_client_unified_params_create( params->user_data = user_data; params->aud_cb = 0; params->unified_cb = unified_cb; - params->stream_cb = 0; params->err_cb = err_cb; + params->client_shm_fd = -1; + params->client_shm_size = 0; memcpy(&(params->format), format, sizeof(*format)); return params; @@ -2467,8 +2366,7 @@ static inline int cras_client_send_add_stream_command_message( if (client == NULL || config == NULL || stream_id_out == NULL) return -EINVAL; - if (config->stream_cb == NULL && config->aud_cb == NULL && - config->unified_cb == NULL) + if (config->aud_cb == NULL && config->unified_cb == NULL) return -EINVAL; if (config->err_cb == NULL) @@ -2566,6 +2464,17 @@ int cras_client_set_system_volume(struct cras_client *client, size_t volume) return write_message_to_server(client, &msg.header); } +int cras_client_set_system_capture_gain(struct cras_client *client, long gain) +{ + struct cras_set_system_capture_gain msg; + + if (client == NULL) + return -EINVAL; + + cras_fill_set_system_capture_gain(&msg, gain); + return write_message_to_server(client, &msg.header); +} + int cras_client_set_system_mute(struct cras_client *client, int mute) { struct cras_set_system_mute msg; @@ -2720,47 +2629,45 @@ long cras_client_get_system_max_volume(const struct cras_client *client) return max_volume; } -int cras_client_get_default_output_buffer_size(struct cras_client *client) +long cras_client_get_system_min_capture_gain(const struct cras_client *client) { - int default_output_buffer_size; + long min_gain; int lock_rc; lock_rc = server_state_rdlock(client); if (lock_rc) - return -EINVAL; + return 0; - default_output_buffer_size = - client->server_state->default_output_buffer_size; + min_gain = client->server_state->min_capture_gain; server_state_unlock(client, lock_rc); - return default_output_buffer_size; + return min_gain; } -const struct audio_debug_info * -cras_client_get_audio_debug_info(const struct cras_client *client) +long cras_client_get_system_max_capture_gain(const struct cras_client *client) { - const struct audio_debug_info *debug_info; + long max_gain; int lock_rc; lock_rc = server_state_rdlock(client); if (lock_rc) return 0; - debug_info = &client->server_state->audio_debug_info; + max_gain = client->server_state->max_capture_gain; server_state_unlock(client, lock_rc); - return debug_info; + return max_gain; } -const struct main_thread_debug_info * -cras_client_get_main_thread_debug_info(const struct cras_client *client) +const struct audio_debug_info * +cras_client_get_audio_debug_info(const struct cras_client *client) { - const struct main_thread_debug_info *debug_info; + const struct audio_debug_info *debug_info; int lock_rc; lock_rc = server_state_rdlock(client); if (lock_rc) return 0; - debug_info = &client->server_state->main_thread_debug_info; + debug_info = &client->server_state->audio_debug_info; server_state_unlock(client, lock_rc); return debug_info; } @@ -3301,20 +3208,6 @@ int cras_client_read_atlog(struct cras_client *client, uint64_t *read_idx, return len; } -int cras_client_update_main_thread_debug_info( - struct cras_client *client, void (*debug_info_cb)(struct cras_client *)) -{ - struct cras_dump_main msg; - - if (client == NULL) - return -EINVAL; - if (client->debug_info_callback != NULL) - return -EINVAL; - client->debug_info_callback = debug_info_cb; - cras_fill_dump_main(&msg); - return write_message_to_server(client, &msg.header); -} - int cras_client_update_bt_debug_info( struct cras_client *client, void (*debug_info_cb)(struct cras_client *)) { @@ -3347,71 +3240,6 @@ int cras_client_update_audio_thread_snapshots( return write_message_to_server(client, &msg.header); } -int cras_client_get_max_supported_channels(const struct cras_client *client, - cras_node_id_t node_id, - uint32_t *max_channels) -{ - size_t ndevs, nnodes; - struct cras_iodev_info *devs = NULL; - struct cras_ionode_info *nodes = NULL; - int rc = -EINVAL; - unsigned i; - - if (!client) { - rc = -EINVAL; - goto quit; - } - - devs = (struct cras_iodev_info *)malloc(CRAS_MAX_IODEVS * - sizeof(*devs)); - if (!devs) { - rc = -ENOMEM; - goto quit; - } - - nodes = (struct cras_ionode_info *)malloc(CRAS_MAX_IONODES * - sizeof(*nodes)); - if (!nodes) { - rc = -ENOMEM; - goto quit; - } - - ndevs = CRAS_MAX_IODEVS; - nnodes = CRAS_MAX_IONODES; - rc = cras_client_get_output_devices(client, devs, nodes, &ndevs, - &nnodes); - if (rc < 0) - goto quit; - - rc = -ENOENT; - uint32_t iodev_idx; - for (i = 0; i < nnodes; i++) { - if (node_id == cras_make_node_id(nodes[i].iodev_idx, - nodes[i].ionode_idx)) { - iodev_idx = nodes[i].iodev_idx; - rc = 0; - break; - } - } - - if (rc < 0) - goto quit; - - rc = -ENOENT; - for (i = 0; i < ndevs; i++) { - if (iodev_idx == devs[i].idx) { - *max_channels = devs[i].max_supported_channels; - rc = 0; - break; - } - } - -quit: - free(devs); - free(nodes); - return rc; -} - int cras_client_set_node_volume(struct cras_client *client, cras_node_id_t node_id, uint8_t volume) { @@ -3480,10 +3308,10 @@ int cras_client_config_global_remix(struct cras_client *client, { struct cras_config_global_remix *msg; int rc; - size_t nchan = (size_t)num_channels; msg = (struct cras_config_global_remix *)malloc( - sizeof(*msg) + nchan * nchan * sizeof(*coefficient)); + sizeof(*msg) + + num_channels * num_channels * sizeof(*coefficient)); cras_fill_config_global_remix_command(msg, num_channels, coefficient, num_channels * num_channels); rc = write_message_to_server(client, &msg->header); @@ -3933,317 +3761,3 @@ int cras_client_disable_hotword_callback(struct cras_client *client, free(handle); return 0; } - -int get_nodes(struct cras_client *client, enum CRAS_STREAM_DIRECTION direction, - struct libcras_node_info ***nodes, size_t *num) -{ - struct cras_iodev_info iodevs[CRAS_MAX_IODEVS]; - struct cras_ionode_info ionodes[CRAS_MAX_IONODES]; - size_t num_devs = CRAS_MAX_IODEVS, num_nodes = CRAS_MAX_IONODES; - int rc, i, j; - - *num = 0; - if (direction == CRAS_STREAM_INPUT) { - rc = cras_client_get_input_devices(client, iodevs, ionodes, - &num_devs, &num_nodes); - } else { - rc = cras_client_get_output_devices(client, iodevs, ionodes, - &num_devs, &num_nodes); - } - - if (rc < 0) { - syslog(LOG_ERR, "Failed to get devices: %d", rc); - return rc; - } - - *nodes = (struct libcras_node_info **)calloc( - num_nodes, sizeof(struct libcras_node_info *)); - - for (i = 0; i < num_devs; i++) { - for (j = 0; j < num_nodes; j++) { - if (iodevs[i].idx != ionodes[j].iodev_idx) - continue; - (*nodes)[*num] = libcras_node_info_create(&iodevs[i], - &ionodes[j]); - if ((*nodes)[*num] == NULL) { - rc = -errno; - goto clean; - } - (*num)++; - } - } - return 0; -clean: - for (i = 0; i < *num; i++) - libcras_node_info_destroy((*nodes)[i]); - free(*nodes); - *nodes = NULL; - *num = 0; - return rc; -} - -int get_default_output_buffer_size(struct cras_client *client, int *size) -{ - int rc = cras_client_get_default_output_buffer_size(client); - if (rc < 0) - return rc; - *size = rc; - return 0; -} - -int get_aec_group_id(struct cras_client *client, int *id) -{ - int rc = cras_client_get_aec_group_id(client); - if (rc < 0) - return rc; - *id = rc; - return 0; -} - -int get_aec_supported(struct cras_client *client, int *supported) -{ - *supported = cras_client_get_aec_supported(client); - return 0; -} - -int get_system_muted(struct cras_client *client, int *muted) -{ - *muted = cras_client_get_system_muted(client); - return 0; -} - -int get_loopback_dev_idx(struct cras_client *client, int *idx) -{ - int rc = cras_client_get_first_dev_type_idx( - client, CRAS_NODE_TYPE_POST_MIX_PRE_DSP, CRAS_STREAM_INPUT); - if (rc < 0) - return rc; - *idx = rc; - return 0; -} - -struct libcras_client *libcras_client_create() -{ - struct libcras_client *client = (struct libcras_client *)calloc( - 1, sizeof(struct libcras_client)); - if (!client) { - syslog(LOG_ERR, "cras_client: calloc failed"); - return NULL; - } - if (cras_client_create(&client->client_)) { - libcras_client_destroy(client); - return NULL; - } - client->api_version = CRAS_API_VERSION; - client->connect = cras_client_connect; - client->connect_timeout = cras_client_connect_timeout; - client->connected_wait = cras_client_connected_wait; - client->run_thread = cras_client_run_thread; - client->stop = cras_client_stop; - client->add_pinned_stream = cras_client_add_pinned_stream; - client->rm_stream = cras_client_rm_stream; - client->set_stream_volume = cras_client_set_stream_volume; - client->get_nodes = get_nodes; - client->get_default_output_buffer_size = get_default_output_buffer_size; - client->get_aec_group_id = get_aec_group_id; - client->get_aec_supported = get_aec_supported; - client->get_system_muted = get_system_muted; - client->set_system_mute = cras_client_set_system_mute; - client->get_loopback_dev_idx = get_loopback_dev_idx; - return client; -} - -void libcras_client_destroy(struct libcras_client *client) -{ - cras_client_destroy(client->client_); - free(client); -} - -int stream_params_set(struct cras_stream_params *params, - enum CRAS_STREAM_DIRECTION direction, - size_t buffer_frames, size_t cb_threshold, - enum CRAS_STREAM_TYPE stream_type, - enum CRAS_CLIENT_TYPE client_type, uint32_t flags, - void *user_data, libcras_stream_cb_t stream_cb, - cras_error_cb_t err_cb, size_t rate, - snd_pcm_format_t format, size_t num_channels) -{ - params->direction = direction; - params->buffer_frames = buffer_frames; - params->cb_threshold = cb_threshold; - params->stream_type = stream_type; - params->client_type = client_type; - params->flags = flags; - params->user_data = user_data; - params->stream_cb = stream_cb; - params->err_cb = err_cb; - params->format.frame_rate = rate; - params->format.format = format; - params->format.num_channels = num_channels; - return 0; -} - -int stream_params_set_channel_layout(struct cras_stream_params *params, - int length, const int8_t *layout) -{ - if (length != CRAS_CH_MAX) - return -EINVAL; - return cras_audio_format_set_channel_layout(¶ms->format, layout); -} - -struct libcras_stream_params *libcras_stream_params_create() -{ - struct libcras_stream_params *params = - (struct libcras_stream_params *)calloc( - 1, sizeof(struct libcras_stream_params)); - if (!params) { - syslog(LOG_ERR, "cras_client: calloc failed"); - return NULL; - } - params->params_ = (struct cras_stream_params *)calloc( - 1, sizeof(struct cras_stream_params)); - if (params->params_ == NULL) { - syslog(LOG_ERR, "cras_client: calloc failed"); - free(params->params_); - return NULL; - } - params->api_version = CRAS_API_VERSION; - params->set = stream_params_set; - params->set_channel_layout = stream_params_set_channel_layout; - params->enable_aec = cras_client_stream_params_enable_aec; - return params; -} - -void libcras_stream_params_destroy(struct libcras_stream_params *params) -{ - free(params->params_); - free(params); -} - -struct cras_node_info { - uint64_t id; - uint32_t dev_idx; - uint32_t node_idx; - uint32_t max_supported_channels; - bool plugged; - bool active; - char type[CRAS_NODE_TYPE_BUFFER_SIZE]; - char node_name[CRAS_NODE_NAME_BUFFER_SIZE]; - char dev_name[CRAS_IODEV_NAME_BUFFER_SIZE]; -}; - -int cras_node_info_get_id(struct cras_node_info *node, uint64_t *id) -{ - (*id) = node->id; - return 0; -} - -int cras_node_info_get_dev_idx(struct cras_node_info *node, uint32_t *dev_idx) -{ - (*dev_idx) = node->dev_idx; - return 0; -} - -int cras_node_info_get_node_idx(struct cras_node_info *node, uint32_t *node_idx) -{ - (*node_idx) = node->node_idx; - return 0; -} - -int cras_node_info_get_max_supported_channels(struct cras_node_info *node, - uint32_t *max_supported_channels) -{ - (*max_supported_channels) = node->max_supported_channels; - return 0; -} - -int cras_node_info_is_plugged(struct cras_node_info *node, bool *is_plugged) -{ - (*is_plugged) = node->plugged; - return 0; -} - -int cras_node_info_is_active(struct cras_node_info *node, bool *is_active) -{ - (*is_active) = node->active; - return 0; -} - -int cras_node_info_get_type(struct cras_node_info *node, char **type) -{ - (*type) = node->type; - return 0; -} - -int cras_node_info_get_node_name(struct cras_node_info *node, char **node_name) -{ - (*node_name) = node->node_name; - return 0; -} - -int cras_node_info_get_dev_name(struct cras_node_info *node, char **dev_name) -{ - (*dev_name) = node->dev_name; - return 0; -} - -struct libcras_node_info * -libcras_node_info_create(struct cras_iodev_info *iodev, - struct cras_ionode_info *ionode) -{ - struct libcras_node_info *node = (struct libcras_node_info *)calloc( - 1, sizeof(struct libcras_node_info)); - if (!node) { - syslog(LOG_ERR, "cras_client: calloc failed"); - return NULL; - } - node->node_ = (struct cras_node_info *)calloc( - 1, sizeof(struct cras_node_info)); - if (node->node_ == NULL) { - syslog(LOG_ERR, "cras_client: calloc failed"); - free(node); - return NULL; - } - node->api_version = CRAS_API_VERSION; - node->node_->id = - cras_make_node_id(ionode->iodev_idx, ionode->ionode_idx); - node->node_->dev_idx = ionode->iodev_idx; - node->node_->node_idx = ionode->ionode_idx; - node->node_->max_supported_channels = iodev->max_supported_channels; - node->node_->plugged = ionode->plugged; - node->node_->active = ionode->active; - strncpy(node->node_->type, ionode->type, CRAS_NODE_TYPE_BUFFER_SIZE); - node->node_->type[CRAS_NODE_TYPE_BUFFER_SIZE - 1] = '\0'; - strncpy(node->node_->node_name, ionode->name, - CRAS_NODE_NAME_BUFFER_SIZE); - node->node_->node_name[CRAS_NODE_NAME_BUFFER_SIZE - 1] = '\0'; - strncpy(node->node_->dev_name, iodev->name, - CRAS_IODEV_NAME_BUFFER_SIZE); - node->node_->dev_name[CRAS_IODEV_NAME_BUFFER_SIZE - 1] = '\0'; - node->get_id = cras_node_info_get_id; - node->get_dev_idx = cras_node_info_get_dev_idx; - node->get_node_idx = cras_node_info_get_node_idx; - node->get_max_supported_channels = - cras_node_info_get_max_supported_channels; - node->is_plugged = cras_node_info_is_plugged; - node->is_active = cras_node_info_is_active; - node->get_type = cras_node_info_get_type; - node->get_node_name = cras_node_info_get_node_name; - node->get_dev_name = cras_node_info_get_dev_name; - return node; -} - -void libcras_node_info_destroy(struct libcras_node_info *node) -{ - free(node->node_); - free(node); -} - -void libcras_node_info_array_destroy(struct libcras_node_info **nodes, - size_t num) -{ - int i; - for (i = 0; i < num; i++) - libcras_node_info_destroy(nodes[i]); - free(nodes); -} diff --git a/cras/src/libcras/cras_client.h b/cras/src/libcras/cras_client.h index f26a0814..7012e2df 100644 --- a/cras/src/libcras/cras_client.h +++ b/cras/src/libcras/cras_client.h @@ -477,16 +477,6 @@ int cras_client_dump_dsp_info(struct cras_client *client); int cras_client_update_audio_debug_info(struct cras_client *client, void (*cb)(struct cras_client *)); -/* Asks the server to dump current main thread information. - * Args: - * client - The client from cras_client_create. - * cb - A function to call when the data is received. - * Returns: - * 0 on success, -EINVAL if the client isn't valid or isn't running. - */ -int cras_client_update_main_thread_debug_info(struct cras_client *client, - void (*cb)(struct cras_client *)); - /* Asks the server to dump bluetooth debug information. * Args: * client - The client from cras_client_create. @@ -535,19 +525,6 @@ int cras_client_read_atlog(struct cras_client *client, uint64_t *read_idx, int cras_client_update_audio_thread_snapshots(struct cras_client *client, void (*cb)(struct cras_client *)); -/* Gets the max supported channel count of the output device from node_id. - * Args: - * client - The client from cras_client_create. - * node_id - ID of the node. - * max_channels - Out parameter will be filled with the max supported channel - * count. - * Returns: - * 0 on success, or negative error code on failure. - */ -int cras_client_get_max_supported_channels(const struct cras_client *client, - cras_node_id_t node_id, - uint32_t *max_channels); - /* * Stream handling. */ @@ -561,7 +538,7 @@ int cras_client_get_max_supported_channels(const struct cras_client *client, * be called when buffer_frames have been captured). * unused - No longer used. * stream_type - media or talk (currently only support "default"). - * flags - Currently only used for CRAS_INPUT_STREAM_FLAG. + * flags - None currently used. * user_data - Pointer that will be passed to the callback. * aud_cb - Called when audio is needed(playback) or ready(capture). Allowed * return EOF to indicate that the stream should terminate. @@ -596,6 +573,16 @@ void cras_client_stream_params_disable_agc(struct cras_stream_params *params); void cras_client_stream_params_enable_vad(struct cras_stream_params *params); void cras_client_stream_params_disable_vad(struct cras_stream_params *params); +/* Function to setup client-provided shm to be used as the backing shm for the + * samples area in the cras_audio_shm shared with cras. + * Args: + * client_shm_fd - shm fd to use for samples shm area. + * client_shm_size - size of shm area backed by 'client_shm_fd'. + */ +void cras_client_stream_params_configure_client_shm( + struct cras_stream_params *params, int client_shm_fd, + size_t client_shm_size); + /* Setup stream configuration parameters. DEPRECATED. * TODO(crbug.com/972928): remove this * Use cras_client_stream_params_create instead. @@ -705,6 +692,20 @@ int cras_client_set_stream_volume(struct cras_client *client, */ int cras_client_set_system_volume(struct cras_client *client, size_t volume); +/* Sets the capture gain of the system. + * + * Gain is specified in dBFS * 100. For example 5dB of gain would be specified + * with an argument of 500, while -10 would be specified with -1000. + * + * Args: + * client - The client from cras_client_create. + * gain - The gain in dBFS * 100. + * Returns: + * 0 for success, -EPIPE if there is an I/O error talking to the server, or + * -EINVAL if 'client' is invalid. + */ +int cras_client_set_system_capture_gain(struct cras_client *client, long gain); + /* Sets the mute state of the system. * * Args: @@ -780,6 +781,17 @@ int cras_client_set_system_capture_mute_locked(struct cras_client *client, */ size_t cras_client_get_system_volume(const struct cras_client *client); +/* Gets the current system capture gain. + * + * Requires that the connection to the server has been established. + * + * Args: + * client - The client from cras_client_create. + * Returns: + * The current system capture volume in dB * 100. + */ +long cras_client_get_system_capture_gain(const struct cras_client *client); + /* Gets the current system mute state. * * Requires that the connection to the server has been established. @@ -831,13 +843,27 @@ long cras_client_get_system_min_volume(const struct cras_client *client); */ long cras_client_get_system_max_volume(const struct cras_client *client); -/* Gets the default output buffer size. +/* Gets the current minimum system capture gain. + * + * Requires that the connection to the server has been established. + * + * Args: + * client - The client from cras_client_create. + * Returns: + * The minimum capture gain for the current input device in dBFS * 100. + */ +long cras_client_get_system_min_capture_gain(const struct cras_client *client); + +/* Gets the current maximum system capture gain. + * + * Requires that the connection to the server has been established. + * * Args: * client - The client from cras_client_create. * Returns: - * Default output buffer size in frames. A negative error on failure. + * The maximum capture gain for the current input device in dBFS * 100. */ -int cras_client_get_default_output_buffer_size(struct cras_client *client); +long cras_client_get_system_max_capture_gain(const struct cras_client *client); /* Gets audio debug info. * @@ -866,16 +892,6 @@ cras_client_get_audio_debug_info(const struct cras_client *client); const struct cras_bt_debug_info * cras_client_get_bt_debug_info(const struct cras_client *client); -/* Gets main thread debug info. - * Args: - * client - The client from cras_client_create. - * Returns: - * A pointer to the debug info. This info is updated and requested by - * calling cras_client_update_main_thread_debug_info. - */ -const struct main_thread_debug_info * -cras_client_get_main_thread_debug_info(const struct cras_client *client); - /* Gets audio thread snapshot buffer. * * Requires that the connection to the server has been established. @@ -971,8 +987,7 @@ int cras_client_swap_node_left_right(struct cras_client *client, * Args: * client - The client from cras_client_create. * node_id - ID of the node. - * gain - New capture gain for the node, in range (0, 100) which will - * linearly maps to (-4000, 4000) 100*dBFS. + * gain - New capture gain for the node. */ int cras_client_set_node_capture_gain(struct cras_client *client, cras_node_id_t node_id, long gain); @@ -1308,699 +1323,6 @@ int cras_client_set_input_node_gain_changed_callback( int cras_client_set_num_active_streams_changed_callback( struct cras_client *client, cras_client_num_active_streams_changed_callback cb); - -/* - * The functions below prefixed with libcras wrap the original CRAS library - * They provide an interface that maps the pointers to the functions above. - * Please add a new function instead of modifying the existing function. - * Here are some rules about how to add a new function: - * 1. Increase the CRAS_API_VERSION by 1. - * 2. Write a new function in cras_client.c. - * 3. Append the corresponding pointer to the structure. Remeber DO NOT change - * the order of functions in the structs. - * 4. Assign the pointer to the new function in cras_client.c. - * 5. Create the inline function in cras_client.h, which is used by clients. - * Remember to add DISABLE_CFI_ICALL on the inline function. - * 6. Add CHECK_VERSION in the inline function. If the api_version is smaller - * than the supported version, this inline function will return -ENOSYS. - */ - -#define CRAS_API_VERSION 1 -#define CHECK_VERSION(object, version) \ - if (object->api_version < version) { \ - return -ENOSYS; \ - } - -/* - * The inline functions use the indirect function call. Therefore, they are - * incompatible with CFI-icall. - */ -#define DISABLE_CFI_ICALL __attribute__((no_sanitize("cfi-icall"))) - -struct libcras_node_info { - int api_version; - struct cras_node_info *node_; - int (*get_id)(struct cras_node_info *node, uint64_t *id); - int (*get_dev_idx)(struct cras_node_info *node, uint32_t *dev_idx); - int (*get_node_idx)(struct cras_node_info *node, uint32_t *node_idx); - int (*get_max_supported_channels)(struct cras_node_info *node, - uint32_t *max_supported_channels); - int (*is_plugged)(struct cras_node_info *node, bool *plugged); - int (*is_active)(struct cras_node_info *node, bool *active); - int (*get_type)(struct cras_node_info *node, char **name); - int (*get_node_name)(struct cras_node_info *node, char **name); - int (*get_dev_name)(struct cras_node_info *node, char **name); -}; - -struct libcras_client { - int api_version; - struct cras_client *client_; - int (*connect)(struct cras_client *client); - int (*connect_timeout)(struct cras_client *client, - unsigned int timeout_ms); - int (*connected_wait)(struct cras_client *client); - int (*run_thread)(struct cras_client *client); - int (*stop)(struct cras_client *client); - int (*add_pinned_stream)(struct cras_client *client, uint32_t dev_idx, - cras_stream_id_t *stream_id_out, - struct cras_stream_params *config); - int (*rm_stream)(struct cras_client *client, - cras_stream_id_t stream_id); - int (*set_stream_volume)(struct cras_client *client, - cras_stream_id_t stream_id, - float volume_scaler); - int (*get_nodes)(struct cras_client *client, - enum CRAS_STREAM_DIRECTION direction, - struct libcras_node_info ***nodes, size_t *num); - int (*get_default_output_buffer_size)(struct cras_client *client, - int *size); - int (*get_aec_group_id)(struct cras_client *client, int *id); - int (*get_aec_supported)(struct cras_client *client, int *supported); - int (*get_system_muted)(struct cras_client *client, int *muted); - int (*set_system_mute)(struct cras_client *client, int mute); - int (*get_loopback_dev_idx)(struct cras_client *client, int *idx); -}; - -struct cras_stream_cb_data; -struct libcras_stream_cb_data { - int api_version; - struct cras_stream_cb_data *data_; - int (*get_stream_id)(struct cras_stream_cb_data *data, - cras_stream_id_t *id); - int (*get_buf)(struct cras_stream_cb_data *data, uint8_t **buf); - int (*get_frames)(struct cras_stream_cb_data *data, - unsigned int *frames); - int (*get_latency)(struct cras_stream_cb_data *data, - struct timespec *latency); - int (*get_user_arg)(struct cras_stream_cb_data *data, void **user_arg); -}; -typedef int (*libcras_stream_cb_t)(struct libcras_stream_cb_data *data); - -struct libcras_stream_params { - int api_version; - struct cras_stream_params *params_; - int (*set)(struct cras_stream_params *params, - enum CRAS_STREAM_DIRECTION direction, size_t buffer_frames, - size_t cb_threshold, enum CRAS_STREAM_TYPE stream_type, - enum CRAS_CLIENT_TYPE client_type, uint32_t flags, - void *user_data, libcras_stream_cb_t stream_cb, - cras_error_cb_t err_cb, size_t rate, snd_pcm_format_t format, - size_t num_channels); - int (*set_channel_layout)(struct cras_stream_params *params, int length, - const int8_t *layout); - void (*enable_aec)(struct cras_stream_params *params); -}; - -/* - * Creates a new client. - * Returns: - * If success, return a valid libcras_client pointer. Otherwise, return - * NULL. - */ -struct libcras_client *libcras_client_create(); - -/* - * Destroys a client. - * Args: - * client - pointer returned from "libcras_client_create". - */ -void libcras_client_destroy(struct libcras_client *client); - -/* - * Connects a client to the running server. - * Waits forever (until interrupted or connected). - * Args: - * client - pointer returned from "libcras_client_create". - * Returns: - * 0 on success, or a negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_connect(struct libcras_client *client) -{ - return client->connect(client->client_); -} - -/* - * Connects a client to the running server, retries until timeout. - * Args: - * client - pointer returned from "libcras_client_create". - * timeout_ms - timeout in milliseconds or negative to wait forever. - * Returns: - * 0 on success, or a negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_connect_timeout(struct libcras_client *client, - unsigned int timeout_ms) -{ - return client->connect_timeout(client->client_, timeout_ms); -} - -/* - * Wait up to 1 second for the client thread to complete the server connection. - * - * After libcras_client_run_thread() is executed, this function can be - * used to ensure that the connection has been established with the server and - * ensure that any information about the server is up to date. If - * libcras_client_run_thread() has not yet been executed, or - * libcras_client_stop() was executed and thread isn't running, then this - * function returns -EINVAL. - * - * Args: - * client - pointer returned from "libcras_client_create". - * Returns: - * 0 on success, or a negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_connected_wait(struct libcras_client *client) -{ - return client->connected_wait(client->client_); -} - -/* - * Begins running the client control thread. - * - * Required for stream operations and other operations noted below. - * - * Args: - * client - pointer returned from "libcras_client_create". - * Returns: - * 0 on success, or a negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_run_thread(struct libcras_client *client) -{ - return client->run_thread(client->client_); -} - -/* - * Stops running a client. - * This function is executed automatically by cras_client_destroy(). - * Args: - * client - pointer returned from "libcras_client_create". - * Returns: - * 0 on success or if the thread was already stopped, -EINVAL if the client - * isn't valid. - */ -DISABLE_CFI_ICALL -inline int libcras_client_stop(struct libcras_client *client) -{ - return client->stop(client->client_); -} - -/* - * Creates a pinned stream and return the stream id or < 0 on error. - * - * Requires execution of libcras_client_run_thread(), and an active - * connection to the audio server. - * - * Args: - * client - pointer returned from "libcras_client_create". - * dev_idx - Index of the device to attach the newly created stream. - * stream_id_out - On success will be filled with the new stream id. - * Guaranteed to be set before any callbacks are made. - * params - The pointer specifying the parameters for the stream. - * (returned from libcras_stream_params_create) - * Returns: - * 0 on success, negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_add_pinned_stream( - struct libcras_client *client, uint32_t dev_idx, - cras_stream_id_t *stream_id_out, struct libcras_stream_params *params) -{ - return client->add_pinned_stream(client->client_, dev_idx, - stream_id_out, params->params_); -} - -/* - * Removes a currently playing/capturing stream. - * - * Requires execution of libcras_client_run_thread(). - * - * Args: - * client - pointer returned from "libcras_client_create". - * stream_id - ID returned from libcras_client_add_stream to identify - * the stream to remove. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_rm_stream(struct libcras_client *client, - cras_stream_id_t stream_id) -{ - return client->rm_stream(client->client_, stream_id); -} - -/* - * Sets the volume scaling factor for the given stream. - * - * Requires execution of cras_client_run_thread(). - * - * Args: - * client - pointer returned from "libcras_client_create". - * stream_id - ID returned from libcras_client_add_stream. - * volume_scaler - 0.0-1.0 the new value to scale this stream by. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_set_stream_volume(struct libcras_client *client, - cras_stream_id_t stream_id, - float volume_scaler) -{ - return client->set_stream_volume(client->client_, stream_id, - volume_scaler); -} - -/* - * Gets the current list of audio nodes. - * - * Args: - * client - Pointer returned from "libcras_client_create". - * direction - Input or output. - * nodes - Array that will be filled with libcras_node_info pointers. - * num - Pointer to store the size of the array. - * Returns: - * 0 on success negative error code on failure (from errno.h). - * Remember to call libcras_node_info_array_destroy to free the array. - */ -DISABLE_CFI_ICALL -inline int libcras_client_get_nodes(struct libcras_client *client, - enum CRAS_STREAM_DIRECTION direction, - struct libcras_node_info ***nodes, - size_t *num) -{ - return client->get_nodes(client->client_, direction, nodes, num); -} - -/* - * Gets the default output buffer size. - * Args: - * client - Pointer returned from "libcras_client_create". - * size - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_client_get_default_output_buffer_size(struct libcras_client *client, - int *size) -{ - return client->get_default_output_buffer_size(client->client_, size); -} - -/* - * Gets the AEC group ID. - * Args: - * client - Pointer returned from "libcras_client_create". - * id - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_get_aec_group_id(struct libcras_client *client, - int *id) -{ - return client->get_aec_group_id(client->client_, id); -} - -/* - * Gets whether AEC is supported. - * Args: - * client - Pointer returned from "libcras_client_create". - * supported - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_get_aec_supported(struct libcras_client *client, - int *supported) -{ - return client->get_aec_supported(client->client_, supported); -} - -/* - * Gets whether the system is muted. - * Args: - * client - Pointer returned from "libcras_client_create". - * muted - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_get_system_muted(struct libcras_client *client, - int *muted) -{ - return client->get_aec_group_id(client->client_, muted); -} - -/* - * Mutes or unmutes the system. - * Args: - * client - Pointer returned from "libcras_client_create". - * mute - 1 is to mute and 0 is to unmute. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_set_system_mute(struct libcras_client *client, - int mute) -{ - return client->set_system_mute(client->client_, mute); -} - -/* - * Gets the index of the loopback device. - * Args: - * client - Pointer returned from "libcras_client_create". - * idx - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_client_get_loopback_dev_idx(struct libcras_client *client, - int *idx) -{ - return client->get_loopback_dev_idx(client->client_, idx); -} - -/* - * Creates a new struct to save stream params. - * Returns: - * If success, return a valid libcras_stream_params pointer. Otherwise, - * return NULL. - */ -struct libcras_stream_params *libcras_stream_params_create(); - -/* - * Destroys a stream params instance. - * Args: - * params - The pointer returned from libcras_stream_params_create. - */ -void libcras_stream_params_destroy(struct libcras_stream_params *params); - -/* - * Setup stream configuration parameters. - * Args: - * params - The pointer returned from libcras_stream_params_create. - * direction - Playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT). - * buffer_frames - total number of audio frames to buffer (dictates latency). - * cb_threshold - For playback, call back for more data when the buffer - * reaches this level. For capture, this is ignored (Audio callback will - * be called when buffer_frames have been captured). - * stream_type - Media or talk (currently only support "default"). - * client_type - The client type, like Chrome or CrOSVM. - * flags - Currently only used for CRAS_INPUT_STREAM_FLAG. - * user_data - Pointer that will be passed to the callback. - * stream_cb - The audio callback. Called when audio is needed(playback) or - * ready(capture). - * err_cb - Called when there is an error with the stream. - * rate - The sample rate of the audio stream. - * format - The format of the audio stream. - * num_channels - The number of channels of the audio stream. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_stream_params_set( - struct libcras_stream_params *params, - enum CRAS_STREAM_DIRECTION direction, size_t buffer_frames, - size_t cb_threshold, enum CRAS_STREAM_TYPE stream_type, - enum CRAS_CLIENT_TYPE client_type, uint32_t flags, void *user_data, - libcras_stream_cb_t stream_cb, cras_error_cb_t err_cb, size_t rate, - snd_pcm_format_t format, size_t num_channels) -{ - return params->set(params->params_, direction, buffer_frames, - cb_threshold, stream_type, client_type, flags, - user_data, stream_cb, err_cb, rate, format, - num_channels); -} - -/* - * Sets channel layout on given stream parameter. - * Args: - * params - The pointer returned from libcras_stream_params_create. - * length - The length of the array. - * layout - An integer array representing the position of each channel in - * enum CRAS_CHANNEL. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_stream_params_set_channel_layout(struct libcras_stream_params *params, - int length, const int8_t *layout) -{ - return params->set_channel_layout(params->params_, length, layout); -} - -/* - * Enables AEC on given stream parameter. - * Args: - * params - The pointer returned from libcras_stream_params_create. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_stream_params_enable_aec(struct libcras_stream_params *params) -{ - params->enable_aec(params->params_); - return 0; -} - -/* - * Gets stream id from the callback data. - * Args: - * data - The pointer passed to the callback function. - * id - The pointer to save the stream id. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_stream_cb_data_get_stream_id(struct libcras_stream_cb_data *data, - cras_stream_id_t *id) -{ - return data->get_stream_id(data->data_, id); -} - -/* - * Gets stream buf from the callback data. - * Args: - * data - The pointer passed to the callback function. - * buf - The pointer to save the stream buffer. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_stream_cb_data_get_buf(struct libcras_stream_cb_data *data, - uint8_t **buf) -{ - return data->get_buf(data->data_, buf); -} - -/* - * Gets how many frames to read or play from the callback data. - * Args: - * data - The pointer passed to the callback function. - * frames - The pointer to save the number of frames. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_stream_cb_data_get_frames(struct libcras_stream_cb_data *data, - unsigned int *frames) -{ - return data->get_frames(data->data_, frames); -} - -/* - * Gets the latency from the callback data. - * Args: - * data - The pointer passed to the callback function. - * frames - The timespec pointer to save the latency. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_stream_cb_data_get_latency(struct libcras_stream_cb_data *data, - struct timespec *latency) -{ - return data->get_latency(data->data_, latency); -} - -/* - * Gets the user data from the callback data. - * Args: - * data - The pointer passed to the callback function. - * frames - The pointer to save the user data. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_stream_cb_data_get_usr_arg(struct libcras_stream_cb_data *data, - void **user_arg) -{ - return data->get_user_arg(data->data_, user_arg); -} - -/* - * Destroys a node info instance. - * Args: - * node - The libcras_node_info pointer to destroy. - */ -void libcras_node_info_destroy(struct libcras_node_info *node); - -/* - * Destroys a node info array. - * Args: - * nodes - The libcras_node_info pointer array to destroy. - * num - The size of the array. - */ -void libcras_node_info_array_destroy(struct libcras_node_info **nodes, - size_t num); - -/* - * Gets ID from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * id - The pointer to save ID. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_get_id(struct libcras_node_info *node, - uint64_t *id) -{ - return node->get_id(node->node_, id); -} - -/* - * Gets device index from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * dev_idx - The pointer to the device index. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_get_dev_idx(struct libcras_node_info *node, - uint32_t *dev_idx) -{ - return node->get_dev_idx(node->node_, dev_idx); -} - -/* - * Gets node index from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * node_idx - The pointer to save the node index. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_get_node_idx(struct libcras_node_info *node, - uint32_t *node_idx) -{ - return node->get_node_idx(node->node_, node_idx); -} - -/* - * Gets the max supported channels from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * max_supported_channels - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int -libcras_node_info_get_max_supported_channels(struct libcras_node_info *node, - uint32_t *max_supported_channels) -{ - return node->get_max_supported_channels(node->node_, - max_supported_channels); -} - -/* - * Gets whether the node is plugged from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * plugged - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_is_plugged(struct libcras_node_info *node, - bool *plugged) -{ - return node->is_plugged(node->node_, plugged); -} - -/* - * Gets whether the node is active from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * active - The pointer to save the result. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_is_active(struct libcras_node_info *node, - bool *active) -{ - return node->is_active(node->node_, active); -} - -/* - * Gets device type from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * type - The pointer to save the device type. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_get_type(struct libcras_node_info *node, - char **type) -{ - return node->get_type(node->node_, type); -} - -/* - * Gets device name from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * name - The pointer to save the device name. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_get_node_name(struct libcras_node_info *node, - char **name) -{ - return node->get_node_name(node->node_, name); -} - -/* - * Gets node name from the node info pointer. - * Args: - * node - The node info pointer. (Returned from libcras_client_get_nodes) - * name - The pointer to save the node name. - * Returns: - * 0 on success negative error code on failure (from errno.h). - */ -DISABLE_CFI_ICALL -inline int libcras_node_info_get_dev_name(struct libcras_node_info *node, - char **name) -{ - return node->get_dev_name(node->node_, name); -} - #ifdef __cplusplus } #endif diff --git a/cras/src/plc/cras_plc.c b/cras/src/plc/cras_plc.c index 74c3568b..ed42ae97 100644 --- a/cras/src/plc/cras_plc.c +++ b/cras/src/plc/cras_plc.c @@ -22,9 +22,6 @@ #define PLC_SBCRL 36 /* SBC Reconvergence sample Length */ #define PLC_OLAL 16 /* OverLap-Add Length */ -#define PLC_WINDOW_SIZE 5 -#define PLC_PL_THRESHOLD 2 - /* The pre-computed zero input bit stream of mSBC codec, per HFP 1.7 spec. * This mSBC frame will be decoded into all-zero input PCM. */ static const uint8_t msbc_zero_frame[] = { @@ -43,18 +40,6 @@ static const float rcos[PLC_OLAL] = { 0.99148655f, 0.96623611f, 0.92510857f, 0.13049554f, 0.07489143f, 0.03376389f, 0.00851345f }; -/* This structure tracks the packet loss information for last PLC_WINDOW_SIZE - * of packets: - * loss_hist - The packet loss history of receiving packets. 1 means lost. - * ptr - The index of the to be updated packet loss status. - * count - The count of lost packets in the window. - */ -struct packet_window { - uint8_t loss_hist[PLC_WINDOW_SIZE]; - unsigned int ptr; - unsigned int count; -}; - /* The PLC is specifically designed for mSBC. The algorithm searches the * history of receiving samples to find the best match samples and constructs * substitutions for the lost samples. The selection is based on pattern @@ -72,30 +57,23 @@ struct packet_window { * frame. * zero_frame - A buffer used for storing the samples from decoding the * mSBC zero frame packet. - * pl_window - A window monitoring how many packets are bad within the recent - * PLC_WINDOW_SIZE of packets. This is used to determine if we - * want to disable the PLC temporarily. */ struct cras_msbc_plc { int16_t hist[PLC_HL + MSBC_FS + PLC_SBCRL + PLC_OLAL]; unsigned int best_lag; int handled_bad_frames; int16_t zero_frame[MSBC_FS]; - struct packet_window *pl_window; }; struct cras_msbc_plc *cras_msbc_plc_create() { struct cras_msbc_plc *plc = (struct cras_msbc_plc *)calloc(1, sizeof(*plc)); - plc->pl_window = - (struct packet_window *)calloc(1, sizeof(*plc->pl_window)); return plc; } void cras_msbc_plc_destroy(struct cras_msbc_plc *plc) { - free(plc->pl_window); free(plc); } @@ -116,33 +94,14 @@ void overlap_add(int16_t *output, float scaler_d, const int16_t *desc, } } -void update_plc_state(struct packet_window *w, uint8_t is_packet_loss) -{ - uint8_t *curr = &w->loss_hist[w->ptr]; - if (is_packet_loss != *curr) { - w->count += (is_packet_loss - *curr); - *curr = is_packet_loss; - } - w->ptr = (w->ptr + 1) % PLC_WINDOW_SIZE; -} - -int possibly_pause_plc(struct packet_window *w) -{ - /* The packet loss count comes from a time window and we use it as an - * indicator of our confidence of the PLC algorithm. It is known to - * generate poorer and robotic feeling sounds, when the majority of - * samples in the PLC history buffer are from the concealment results. - */ - return w->count >= PLC_PL_THRESHOLD; -} - int cras_msbc_plc_handle_good_frames(struct cras_msbc_plc *state, const uint8_t *input, uint8_t *output) { int16_t *frame_head, *input_samples, *output_samples; if (state->handled_bad_frames == 0) { - /* If there was no packet concealment before this good frame, - * we just simply copy the input to output without reconverge. + /* If there was no packet loss before this good frame, there + * is nothing we need to do to the frame so we'll just pass + * the input to output. */ memmove(output, input, MSBC_FS * MSBC_SAMPLE_SIZE); } else { @@ -170,7 +129,6 @@ int cras_msbc_plc_handle_good_frames(struct cras_msbc_plc *state, (PLC_HL - MSBC_FS) * MSBC_SAMPLE_SIZE); memcpy(&state->hist[PLC_HL - MSBC_FS], output, MSBC_FS * MSBC_SAMPLE_SIZE); - update_plc_state(state->pl_window, 0); return MSBC_CODE_SIZE; } @@ -183,7 +141,7 @@ float cross_correlation(int16_t *x, int16_t *y) x2 += ((float)x[i]) * x[i]; y2 += ((float)y[i]) * y[i]; } - return sum / sqrtf(x2 * y2); + return sum / sqrt(x2 * y2); } int pattern_match(int16_t *hist) @@ -226,60 +184,37 @@ int cras_msbc_plc_handle_bad_frames(struct cras_msbc_plc *state, int16_t *frame_head = &state->hist[PLC_HL]; size_t pcm_decoded = 0; - /* mSBC codec is stateful, the history of signal would contribute to the - * decode result state->zero_frame. - */ codec->decode(codec, msbc_zero_frame, MSBC_PKT_LEN, state->zero_frame, MSBC_FS, &pcm_decoded); - /* The PLC algorithm is more likely to generate bad results that sound - * robotic after severe packet losses happened. Only applying it when - * we are confident. - */ - if (!possibly_pause_plc(state->pl_window)) { - if (state->handled_bad_frames == 0) { - /* Finds the best matching samples and amplitude */ - state->best_lag = pattern_match(state->hist) + PLC_TL; - best_match_hist = &state->hist[state->best_lag]; - scaler = amplitude_match(&state->hist[PLC_HL - MSBC_FS], - best_match_hist); - - /* Constructs the substitution samples */ - overlap_add(frame_head, 1.0, state->zero_frame, scaler, - best_match_hist); - for (int i = PLC_OLAL; i < MSBC_FS; i++) - state->hist[PLC_HL + i] = - f_to_s16(scaler * best_match_hist[i]); - overlap_add(&frame_head[MSBC_FS], scaler, - &best_match_hist[MSBC_FS], 1.0, - &best_match_hist[MSBC_FS]); - - memmove(&frame_head[MSBC_FS + PLC_OLAL], - &best_match_hist[MSBC_FS + PLC_OLAL], - PLC_SBCRL * MSBC_SAMPLE_SIZE); - } else { - memmove(frame_head, &state->hist[state->best_lag], - (MSBC_FS + PLC_SBCRL + PLC_OLAL) * - MSBC_SAMPLE_SIZE); - } - state->handled_bad_frames++; + if (state->handled_bad_frames == 0) { + /* Finds the best matching samples and amplitude */ + state->best_lag = pattern_match(state->hist) + PLC_TL; + best_match_hist = &state->hist[state->best_lag]; + scaler = amplitude_match(&state->hist[PLC_HL - MSBC_FS], + best_match_hist); + + /* Constructs the substitution samples */ + overlap_add(frame_head, 1.0, state->zero_frame, scaler, + best_match_hist); + for (int i = PLC_OLAL; i < MSBC_FS; i++) + state->hist[PLC_HL + i] = + f_to_s16(scaler * best_match_hist[i]); + overlap_add(&frame_head[MSBC_FS], scaler, + &best_match_hist[MSBC_FS], 1.0, + &best_match_hist[MSBC_FS]); + + memmove(&frame_head[MSBC_FS + PLC_OLAL], + &best_match_hist[MSBC_FS + PLC_OLAL], + PLC_SBCRL * MSBC_SAMPLE_SIZE); } else { - /* This is a case similar to receiving a good frame with all - * zeros, we set handled_bad_frames to zero to prevent the - * following good frame from being concealed to reconverge with - * the zero frames we fill in. The concealment result sounds - * more artificial and weird than simply writing zeros and - * following samples. - */ - memmove(frame_head, state->zero_frame, MSBC_CODE_SIZE); - memset(frame_head + MSBC_CODE_SIZE, 0, - (PLC_SBCRL + PLC_OLAL) * MSBC_SAMPLE_SIZE); - state->handled_bad_frames = 0; + memmove(frame_head, &state->hist[state->best_lag], + (MSBC_FS + PLC_SBCRL + PLC_OLAL) * MSBC_SAMPLE_SIZE); } + state->handled_bad_frames++; memcpy(output, frame_head, MSBC_CODE_SIZE); memmove(state->hist, &state->hist[MSBC_FS], (PLC_HL + PLC_SBCRL + PLC_OLAL) * MSBC_SAMPLE_SIZE); - update_plc_state(state->pl_window, 1); return MSBC_CODE_SIZE; } diff --git a/cras/src/plc/cras_plc_test.c b/cras/src/plc/cras_plc_test.c index 4b7a6a77..458f1254 100644 --- a/cras/src/plc/cras_plc_test.c +++ b/cras/src/plc/cras_plc_test.c @@ -4,13 +4,11 @@ */ #include <errno.h> -#include <getopt.h> #include <math.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -31,65 +29,32 @@ static const uint8_t msbc_zero_frame[] = { 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c }; -bool *generate_pl_seq(int input_file_size, float pl_percent) +bool *generate_pl_seq(unsigned pk_count, unsigned loss_count) { - unsigned pk_count, pl_count; - bool *seq; - - pk_count = input_file_size / MSBC_CODE_SIZE; - pl_count = pk_count * (pl_percent / 100.0); - seq = (bool *)calloc(pk_count, sizeof(*seq)); + bool *seq = (bool *)calloc(pk_count, sizeof(*seq)); srand(RND_SEED); - while (pl_count > 0) { + while (loss_count > 0) { bool *missed = &seq[rand() % pk_count]; if (!*missed) { *missed = true; - pl_count--; - } - } - return seq; -} - -/* pl_hex is expected to be consecutive bytes(two chars) in hex format.*/ -bool *parse_pl_hex(int input_file_size, const char *pl_hex) -{ - char tmp[3]; - uint8_t val = 0; - int i, pl_hex_len, seq_len; - bool *seq; - - pl_hex_len = strlen(pl_hex); - seq_len = MAX(1 + input_file_size / MSBC_CODE_SIZE, pl_hex_len * 4); - seq = (bool *)calloc(seq_len, sizeof(*seq)); - - for (i = 0; i < seq_len; i++) { - /* If sequence is longer then the provided pl_hex, leave the - * rest to all zeros. */ - if (i > pl_hex_len * 4) - break; - if (i % 8 == 0) { - memcpy(tmp, pl_hex + i / 4, 2); - tmp[2] = '\0'; - val = strtol(tmp, NULL, 16); + loss_count--; } - seq[i] = val & 1U; - val >>= 1; } - printf("pl_hex string maps to %ld ms, total sequence size %f ms\n", - strlen(pl_hex) * 30, seq_len * 7.5f); return seq; } -void plc_experiment(const char *input_filename, bool *pl_seq, bool with_plc) +void plc_experiment(char *input_filename, float pl_percent, bool with_plc) { char output_filename[255]; int input_fd, output_fd, rc; + struct stat st; + bool *pl_seq; struct cras_audio_codec *msbc_input = cras_msbc_codec_create(); struct cras_audio_codec *msbc_output = cras_msbc_codec_create(); struct cras_msbc_plc *plc = cras_msbc_plc_create(); uint8_t buffer[MSBC_CODE_SIZE], packet_buffer[MSBC_PKT_FRAME_LEN]; size_t encoded, decoded; - unsigned count = 0; + unsigned pk_count, pl_count, count = 0; input_fd = open(input_filename, O_RDONLY); if (input_fd == -1) { @@ -98,9 +63,9 @@ void plc_experiment(const char *input_filename, bool *pl_seq, bool with_plc) } if (with_plc) - sprintf(output_filename, "output_with_plc.raw"); + sprintf(output_filename, "output_%2.2f_plc.raw", pl_percent); else - sprintf(output_filename, "output_with_zero.raw"); + sprintf(output_filename, "output_%2.2f_zero.raw", pl_percent); output_fd = open(output_filename, O_CREAT | O_RDWR | O_TRUNC, 0644); if (output_fd == -1) { @@ -109,6 +74,11 @@ void plc_experiment(const char *input_filename, bool *pl_seq, bool with_plc) return; } + fstat(input_fd, &st); + pk_count = st.st_size / MSBC_CODE_SIZE; + pl_count = pk_count * (pl_percent / 100.0); + pl_seq = generate_pl_seq(pk_count, pl_count); + while (1) { rc = read(input_fd, buffer, MSBC_CODE_SIZE); if (rc < 0) { @@ -147,77 +117,19 @@ void plc_experiment(const char *input_filename, bool *pl_seq, bool with_plc) } } -static void show_usage() -{ - printf("This test only supports reading/writing raw audio with format:\n" - "\t16000 sample rate, mono channel, S16_LE\n"); - printf("--help - Print this usage.\n"); - printf("--input_file - path to an audio file.\n"); - printf("--pattern - Hex string representing consecutive packets'" - "status.\n"); - printf("--random - Percentage of packet loss.\n"); -} - int main(int argc, char **argv) { - int fd; - struct stat st; - float pl_percent; - int pl_percent_set = 0; - int option_character; - int option_index = 0; - const char *input_file = NULL; - const char *pl_hex = NULL; - bool *pl_seq = NULL; - static struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "input", required_argument, NULL, 'i' }, - { "pattern", required_argument, NULL, 'p' }, - { "random", required_argument, NULL, 'r' }, - { NULL, 0, NULL, 0 }, - }; - - while (true) { - option_character = getopt_long(argc, argv, "i:r:p:h", - long_options, &option_index); - if (option_character == -1) - break; - switch (option_character) { - case 'h': - show_usage(); - break; - case 'i': - input_file = optarg; - break; - case 'p': - pl_hex = optarg; - break; - case 'r': - pl_percent = atof(optarg); - pl_percent_set = 1; - break; - default: - break; - } - } - - if ((!pl_percent_set && !pl_hex) || !input_file) { - show_usage(); + if (argc != 3) { + printf("Usage: cras_plc_test input.raw pl_percentage\n" + "This test only supports reading/writing files with " + "format:\n" + "- raw pcm\n" + "- 16000 sample rate\n" + "- mono channel\n" + "- S16_LE sample format\n"); return 1; } - fd = open(input_file, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Cannout open input file %s\n", input_file); - return 1; - } - fstat(fd, &st); - close(fd); - if (pl_percent_set) - pl_seq = generate_pl_seq(st.st_size, pl_percent); - else if (pl_hex) - pl_seq = parse_pl_hex(st.st_size, pl_hex); - - plc_experiment(input_file, pl_seq, true); - plc_experiment(input_file, pl_seq, false); + plc_experiment(argv[1], atof(argv[2]), true); + plc_experiment(argv[1], atof(argv[2]), false); } diff --git a/cras/src/plc/parse_sco.py b/cras/src/plc/parse_sco.py deleted file mode 100755 index c50df159..00000000 --- a/cras/src/plc/parse_sco.py +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -""" -A script to extract raw SCO RX packets from btsnoop. -Use 'btmon -S' to dump SCO traffic from btsnoop file. -Trim the btsnoop output to just the SCO traffic period. -Then execute 'python parse-sco.py <btsnoop-output>' -""" - -import atexit -import binascii -import os -import re -import sys - - -class SCOParser: - """ - Parser for grepping SCO packets - """ - - def __init__(self): - # On old releases, +CIEV: 4,1 indicates the start point of call session - # c 31 0d 0a 9a ..+CIEV: 4,1.. - self.call_start_re = re.compile(r'.*?\+CIEV:\s4,(\d).*?') - - # > SCO Data RX: Handle 257 flags 0x00 dlen 60 #13826 [hci0] 650.388305 - # 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - # 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - # 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - # 00 00 00 00 00 00 00 00 00 00 00 00 - self.sco_rx_re = re.compile(r'.*?SCO\sData\sRX.*?flags\s0x(\d+).*?') - self.sco_f = None - self.output_idx = 0 - self.pk_count = 0 - self.pl_count = 0 - - atexit.register(self._cleanup) - - def _cleanup(self): - if self.sco_f is not None: - print( - "Current file contains %d packets (%d with erroneous status flag)" % - (self.pk_count, self.pl_count)) - self.pk_count = 0 - self.pl_count = 0 - self.sco_f.close() - - def _new_session(self): - if self.sco_f is not None: - close(self.sco_f) - - new_file = "sco_file_%d" % self.output_idx - print("Record to %s" % new_file) - self.sco_f = open(new_file, 'wb') - self.output_idx += 1 - - return self.sco_f - - def parse(self, filename): - if not os.path.exists(filename): - print("%s doesn't exist" % filename) - return - - print("Start parsing %s" % filename) - parse_rx_data = 0 - with open(filename, "r") as f: - for line in f.readlines(): - if parse_rx_data > 0: - self.sco_f.write(binascii.unhexlify(''.join(line[:56].split()))) - parse_rx_data = (parse_rx_data + 1) % 5 - - # Start a new session and output following SCO data to a new file - match = self.call_start_re.search(line) - if match and (1 == int(match.group(1))): - self._new_session() - continue - - match = self.sco_rx_re.search(line) - if match: - if self.sco_f is None: - self._new_session() - - self.pk_count += 1 - - status_flag = int(match.group(1)) - hdr = ['01', str(status_flag) + '1', '3c'] - if status_flag != 0: - self.pl_count += 1 - - self.sco_f.write(binascii.unhexlify(''.join(hdr))) - parse_rx_data = 1 - - -def main(argv): - if len(argv) < 1: - print("parse_sco.py [btsnoop.txt]") - return - - p = SCOParser() - p.parse(argv[0]) - - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/cras/src/server/audio_thread.c b/cras/src/server/audio_thread.c index 48bb0dc2..d7ef8bd6 100644 --- a/cras/src/server/audio_thread.c +++ b/cras/src/server/audio_thread.c @@ -37,13 +37,6 @@ */ #define MAX_CONTINUOUS_ZERO_SLEEP_COUNT 2 -/* - * If the number of continuous zero sleep is equal to this limit, the value - * will be recorded immediately. It can ensure all busyloop will be recorded - * even if the busyloop does not stop. - */ -#define MAX_CONTINUOUS_ZERO_SLEEP_METRIC_LIMIT 1000 - /* Messages that can be sent from the main context to the audio thread. */ enum AUDIO_THREAD_COMMAND { AUDIO_THREAD_ADD_OPEN_DEV, @@ -124,16 +117,16 @@ static struct iodev_callback_list *iodev_callbacks; struct iodev_callback_list { int fd; - int events; - enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger; + int is_write; + int enabled; thread_callback cb; void *cb_data; struct pollfd *pollfd; struct iodev_callback_list *prev, *next; }; -void audio_thread_add_events_callback(int fd, thread_callback cb, void *data, - int events) +static void _audio_thread_add_callback(int fd, thread_callback cb, void *data, + int is_write) { struct iodev_callback_list *iodev_cb; @@ -146,12 +139,22 @@ void audio_thread_add_events_callback(int fd, thread_callback cb, void *data, iodev_cb->fd = fd; iodev_cb->cb = cb; iodev_cb->cb_data = data; - iodev_cb->trigger = TRIGGER_POLL; - iodev_cb->events = events; + iodev_cb->enabled = 1; + iodev_cb->is_write = is_write; DL_APPEND(iodev_callbacks, iodev_cb); } +void audio_thread_add_callback(int fd, thread_callback cb, void *data) +{ + _audio_thread_add_callback(fd, cb, data, 0); +} + +void audio_thread_add_write_callback(int fd, thread_callback cb, void *data) +{ + _audio_thread_add_callback(fd, cb, data, 1); +} + void audio_thread_rm_callback(int fd) { struct iodev_callback_list *iodev_cb; @@ -165,14 +168,13 @@ void audio_thread_rm_callback(int fd) } } -void audio_thread_config_events_callback( - int fd, enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger) +void audio_thread_enable_callback(int fd, int enabled) { struct iodev_callback_list *iodev_cb; DL_FOREACH (iodev_callbacks, iodev_cb) { if (iodev_cb->fd == fd) { - iodev_cb->trigger = trigger; + iodev_cb->enabled = !!enabled; return; } } @@ -443,8 +445,7 @@ static int thread_add_stream(struct audio_thread *thread, { int rc; - rc = dev_io_append_stream(&thread->open_devs[CRAS_STREAM_OUTPUT], - &thread->open_devs[CRAS_STREAM_INPUT], stream, + rc = dev_io_append_stream(&thread->open_devs[stream->direction], stream, iodevs, num_iodevs); if (rc < 0) return rc; @@ -556,11 +557,8 @@ static void append_stream_dump_info(struct audio_debug_info *info, si->runtime_nsec = time_since.tv_nsec; } -/* Handle a message sent from main thread to the audio thread. - * Returns: - * Error code when reading or sending message fails. - */ -static int handle_audio_thread_message(struct audio_thread *thread) +/* Handle a message sent to the playback thread */ +static int handle_playback_thread_message(struct audio_thread *thread) { uint8_t buf[256]; struct audio_thread_msg *msg = (struct audio_thread_msg *)buf; @@ -715,7 +713,7 @@ static int handle_audio_thread_message(struct audio_thread *thread) err = audio_thread_send_response(thread, ret); if (err < 0) return err; - return 0; + return ret; } /* Returns the number of active streams plus the number of active devices. */ @@ -734,7 +732,7 @@ static int fill_next_sleep_interval(struct audio_thread *thread, clock_gettime(CLOCK_MONOTONIC_RAW, &now); add_timespecs(&min_ts, &now); ret = dev_io_next_output_wake(&thread->open_devs[CRAS_STREAM_OUTPUT], - &min_ts); + &min_ts, &now); ret += dev_io_next_input_wake(&thread->open_devs[CRAS_STREAM_INPUT], &min_ts); if (timespec_after(&min_ts, &now)) @@ -744,10 +742,13 @@ static int fill_next_sleep_interval(struct audio_thread *thread, } static struct pollfd *add_pollfd(struct audio_thread *thread, int fd, - int events) + int is_write) { thread->pollfds[thread->num_pollfds].fd = fd; - thread->pollfds[thread->num_pollfds].events = events; + if (is_write) + thread->pollfds[thread->num_pollfds].events = POLLOUT; + else + thread->pollfds[thread->num_pollfds].events = POLLIN; thread->num_pollfds++; if (thread->num_pollfds >= thread->pollfds_size) { thread->pollfds_size *= 2; @@ -795,18 +796,7 @@ static void check_busyloop(struct timespec *wait_ts) busyloop_count++; cras_audio_thread_event_busyloop(); } - if (continuous_zero_sleep_count == - MAX_CONTINUOUS_ZERO_SLEEP_METRIC_LIMIT) - cras_server_metrics_busyloop_length( - continuous_zero_sleep_count); - } else { - if (continuous_zero_sleep_count >= - MAX_CONTINUOUS_ZERO_SLEEP_COUNT && - continuous_zero_sleep_count < - MAX_CONTINUOUS_ZERO_SLEEP_METRIC_LIMIT) - cras_server_metrics_busyloop_length( - continuous_zero_sleep_count); continuous_zero_sleep_count = 0; } } @@ -839,7 +829,6 @@ static void *audio_io_thread(void *arg) while (1) { struct timespec *wait_ts; struct iodev_callback_list *iodev_cb; - int non_empty; wait_ts = NULL; thread->num_pollfds = 1; @@ -849,9 +838,6 @@ static void *audio_io_thread(void *arg) &thread->open_devs[CRAS_STREAM_INPUT], thread->remix_converter); - non_empty = dev_io_check_non_empty_state_transition( - thread->open_devs[CRAS_STREAM_OUTPUT]); - if (fill_next_sleep_interval(thread, &ts)) wait_ts = &ts; @@ -859,12 +845,10 @@ static void *audio_io_thread(void *arg) thread->num_pollfds = 1; DL_FOREACH (iodev_callbacks, iodev_cb) { - if (iodev_cb->trigger != TRIGGER_POLL) { - iodev_cb->pollfd = NULL; + if (!iodev_cb->enabled) continue; - } iodev_cb->pollfd = add_pollfd(thread, iodev_cb->fd, - iodev_cb->events); + iodev_cb->is_write); if (!iodev_cb->pollfd) goto restart_poll_loop; } @@ -875,7 +859,7 @@ static void *audio_io_thread(void *arg) int fd = dev_stream_poll_stream_fd(curr); if (fd < 0) continue; - if (!add_pollfd(thread, fd, POLLIN)) + if (!add_pollfd(thread, fd, 0)) goto restart_poll_loop; } } @@ -884,7 +868,7 @@ static void *audio_io_thread(void *arg) int fd = dev_stream_poll_stream_fd(curr); if (fd < 0) continue; - if (!add_pollfd(thread, fd, POLLIN)) + if (!add_pollfd(thread, fd, 0)) goto restart_poll_loop; } } @@ -892,7 +876,7 @@ static void *audio_io_thread(void *arg) log_busyloop(wait_ts); ATLOG(atlog, AUDIO_THREAD_SLEEP, wait_ts ? wait_ts->tv_sec : 0, - wait_ts ? wait_ts->tv_nsec : 0, non_empty); + wait_ts ? wait_ts->tv_nsec : 0, 0); if (wait_ts) check_busyloop(wait_ts); @@ -902,33 +886,21 @@ static void *audio_io_thread(void *arg) rc = ppoll(thread->pollfds, thread->num_pollfds, wait_ts, NULL); ATLOG(atlog, AUDIO_THREAD_WAKE, rc, 0, 0); - - /* Handle callbacks registered by TRIGGER_WAKEUP */ - DL_FOREACH (iodev_callbacks, iodev_cb) { - if (iodev_cb->trigger == TRIGGER_WAKEUP) { - ATLOG(atlog, AUDIO_THREAD_IODEV_CB, 0, 0, 0); - iodev_cb->cb(iodev_cb->cb_data, 0); - } - } - - /* If there's no pollfd ready to handle. */ if (rc <= 0) continue; if (thread->pollfds[0].revents & POLLIN) { - rc = handle_audio_thread_message(thread); + rc = handle_playback_thread_message(thread); if (rc < 0) syslog(LOG_ERR, "handle message %d", rc); } DL_FOREACH (iodev_callbacks, iodev_cb) { if (iodev_cb->pollfd && - iodev_cb->pollfd->revents & iodev_cb->events) { + iodev_cb->pollfd->revents & (POLLIN | POLLOUT)) { ATLOG(atlog, AUDIO_THREAD_IODEV_CB, - iodev_cb->pollfd->revents, - iodev_cb->events, 0); - iodev_cb->cb(iodev_cb->cb_data, - iodev_cb->pollfd->revents); + iodev_cb->is_write, 0, 0); + iodev_cb->cb(iodev_cb->cb_data); } } } diff --git a/cras/src/server/audio_thread.h b/cras/src/server/audio_thread.h index 34b47863..5e5e9956 100644 --- a/cras/src/server/audio_thread.h +++ b/cras/src/server/audio_thread.h @@ -45,24 +45,11 @@ struct audio_thread { struct cras_fmt_conv *remix_converter; }; -/* - * Enum to specify how a registered event callback be triggered. - * TRIGGER_NONE - Callback will not be triggered. - * TRIGGER_POLL - Triggered by poll given fd and revent. - * TRIGGER_WAKEUP - Triggered everytime when audio thread wakes up. - */ -enum AUDIO_THREAD_EVENTS_CB_TRIGGER { - TRIGGER_NONE, - TRIGGER_POLL, - TRIGGER_WAKEUP, -}; - /* Callback function to be handled in main loop in audio thread. * Args: * data - The data for callback function. - * revent - The returned event from ppoll(). */ -typedef int (*thread_callback)(void *data, int revent); +typedef int (*thread_callback)(void *data); /* Creates an audio thread. * Returns: @@ -96,17 +83,23 @@ int audio_thread_rm_open_dev(struct audio_thread *thread, int audio_thread_is_dev_open(struct audio_thread *thread, struct cras_iodev *dev); -/* Adds a thread_callback to audio thread for requested events. By default - * the callback trigger is set to TRIGGER_POLL. +/* Adds an thread_callback to audio thread. + * Args: + * fd - The file descriptor to be polled for the callback. + * The callback will be called when fd is readable. + * cb - The callback function. + * data - The data for the callback function. + */ +void audio_thread_add_callback(int fd, thread_callback cb, void *data); + +/* Adds an thread_callback to audio thread. * Args: * fd - The file descriptor to be polled for the callback. - * The callback will be called when any of requested events matched. + * The callback will be called when fd is writeable. * cb - The callback function. * data - The data for the callback function. - * events - The requested events to ppoll(). */ -void audio_thread_add_events_callback(int fd, thread_callback cb, void *data, - int events); +void audio_thread_add_write_callback(int fd, thread_callback cb, void *data); /* Removes an thread_callback from audio thread. * Args: @@ -121,13 +114,8 @@ void audio_thread_rm_callback(int fd); */ int audio_thread_rm_callback_sync(struct audio_thread *thread, int fd); -/* Configures the callback associated with fd when it should be triggerred. - * Args: - * fd - The file descriptor associate to the callback. - * trigger - Specifies how the callback should be triggered. - */ -void audio_thread_config_events_callback( - int fd, enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger); +/* Enables or Disabled the callback associated with fd. */ +void audio_thread_enable_callback(int fd, int enabled); /* Starts a thread created with audio_thread_create. * Args: diff --git a/cras/src/server/config/cras_board_config.c b/cras/src/server/config/cras_board_config.c index e36ea3cf..9acdf82c 100644 --- a/cras/src/server/config/cras_board_config.c +++ b/cras/src/server/config/cras_board_config.c @@ -3,95 +3,59 @@ * found in the LICENSE file. */ -#include <errno.h> #include <syslog.h> #include "cras_board_config.h" #include "iniparser_wrapper.h" +/* Allocate 63 chars + 1 for null where declared. */ +static const unsigned int MAX_INI_NAME_LEN = 63; +static const unsigned int MAX_KEY_LEN = 63; static const int32_t DEFAULT_OUTPUT_BUFFER_SIZE = 512; static const int32_t AEC_SUPPORTED_DEFAULT = 0; static const int32_t AEC_GROUP_ID_DEFAULT = -1; -static const int32_t BLUETOOTH_WBS_ENABLED_INI_DEFAULT = 1; -static const int32_t BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_DEFAULT = 0; -static const int32_t HOTWORD_PAUSE_AT_SUSPEND_DEFAULT = 0; #define CONFIG_NAME "board.ini" #define DEFAULT_OUTPUT_BUF_SIZE_INI_KEY "output:default_output_buffer_size" #define AEC_SUPPORTED_INI_KEY "processing:aec_supported" #define AEC_GROUP_ID_INI_KEY "processing:group_id" -#define BLUETOOTH_WBS_ENABLED_INI_KEY "bluetooth:wbs_enabled" -#define BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_KEY "bluetooth:deprioritize_wbs_mic" -#define UCM_IGNORE_SUFFIX_KEY "ucm:ignore_suffix" -#define HOTWORD_PAUSE_AT_SUSPEND "hotword:pause_at_suspend" void cras_board_config_get(const char *config_path, struct cras_board_config *board_config) { - char ini_name[MAX_INI_NAME_LENGTH + 1]; - char ini_key[MAX_INI_KEY_LENGTH + 1]; - const char *ptr; + char ini_name[MAX_INI_NAME_LEN + 1]; + char ini_key[MAX_KEY_LEN + 1]; dictionary *ini; board_config->default_output_buffer_size = DEFAULT_OUTPUT_BUFFER_SIZE; board_config->aec_supported = AEC_SUPPORTED_DEFAULT; board_config->aec_group_id = AEC_GROUP_ID_DEFAULT; - board_config->ucm_ignore_suffix = NULL; - board_config->bt_wbs_enabled = BLUETOOTH_WBS_ENABLED_INI_DEFAULT; - board_config->deprioritize_bt_wbs_mic = - BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_DEFAULT; if (config_path == NULL) return; - snprintf(ini_name, MAX_INI_NAME_LENGTH, "%s/%s", config_path, - CONFIG_NAME); - ini_name[MAX_INI_NAME_LENGTH] = '\0'; + snprintf(ini_name, MAX_INI_NAME_LEN, "%s/%s", config_path, CONFIG_NAME); + ini_name[MAX_INI_NAME_LEN] = '\0'; ini = iniparser_load_wrapper(ini_name); if (ini == NULL) { syslog(LOG_DEBUG, "No ini file %s", ini_name); return; } - snprintf(ini_key, MAX_INI_KEY_LENGTH, DEFAULT_OUTPUT_BUF_SIZE_INI_KEY); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, DEFAULT_OUTPUT_BUF_SIZE_INI_KEY); + ini_key[MAX_KEY_LEN] = 0; board_config->default_output_buffer_size = iniparser_getint(ini, ini_key, DEFAULT_OUTPUT_BUFFER_SIZE); - snprintf(ini_key, MAX_INI_KEY_LENGTH, AEC_SUPPORTED_INI_KEY); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, AEC_SUPPORTED_INI_KEY); + ini_key[MAX_KEY_LEN] = 0; board_config->aec_supported = iniparser_getint(ini, ini_key, AEC_SUPPORTED_DEFAULT); - snprintf(ini_key, MAX_INI_KEY_LENGTH, AEC_GROUP_ID_INI_KEY); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, AEC_GROUP_ID_INI_KEY); + ini_key[MAX_KEY_LEN] = 0; board_config->aec_group_id = iniparser_getint(ini, ini_key, AEC_GROUP_ID_DEFAULT); - snprintf(ini_key, MAX_INI_KEY_LENGTH, BLUETOOTH_WBS_ENABLED_INI_KEY); - ini_key[MAX_INI_KEY_LENGTH] = 0; - board_config->bt_wbs_enabled = iniparser_getint( - ini, ini_key, BLUETOOTH_WBS_ENABLED_INI_DEFAULT); - - snprintf(ini_key, MAX_INI_KEY_LENGTH, - BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_KEY); - ini_key[MAX_INI_KEY_LENGTH] = 0; - board_config->deprioritize_bt_wbs_mic = iniparser_getint( - ini, ini_key, BLUETOOTH_DEPRIORITIZE_WBS_MIC_INI_DEFAULT); - - snprintf(ini_key, MAX_INI_KEY_LENGTH, UCM_IGNORE_SUFFIX_KEY); - ini_key[MAX_INI_KEY_LENGTH] = 0; - ptr = iniparser_getstring(ini, ini_key, ""); - if (ptr) { - board_config->ucm_ignore_suffix = strdup(ptr); - if (!board_config->ucm_ignore_suffix) - syslog(LOG_ERR, "Failed to call strdup: %d", errno); - } - - snprintf(ini_key, MAX_INI_KEY_LENGTH, HOTWORD_PAUSE_AT_SUSPEND); - ini_key[MAX_INI_KEY_LENGTH] = 0; - board_config->hotword_pause_at_suspend = iniparser_getint( - ini, ini_key, HOTWORD_PAUSE_AT_SUSPEND_DEFAULT); - iniparser_freedict(ini); syslog(LOG_DEBUG, "Loaded ini file %s", ini_name); } diff --git a/cras/src/server/config/cras_board_config.h b/cras/src/server/config/cras_board_config.h index d4bd8496..92ef971c 100644 --- a/cras/src/server/config/cras_board_config.h +++ b/cras/src/server/config/cras_board_config.h @@ -12,10 +12,6 @@ struct cras_board_config { int32_t default_output_buffer_size; int32_t aec_supported; int32_t aec_group_id; - int32_t bt_wbs_enabled; - int32_t deprioritize_bt_wbs_mic; - char *ucm_ignore_suffix; - int32_t hotword_pause_at_suspend; }; /* Gets a configuration based on the config file specified. diff --git a/cras/src/server/config/cras_card_config.c b/cras/src/server/config/cras_card_config.c index ae36565d..f19d0855 100644 --- a/cras/src/server/config/cras_card_config.c +++ b/cras/src/server/config/cras_card_config.c @@ -10,6 +10,10 @@ #include "iniparser_wrapper.h" #include "utlist.h" +/* Allocate 63 chars + 1 for null where declared. */ +static const unsigned int MAX_INI_NAME_LEN = 63; +static const unsigned int MAX_KEY_LEN = 63; + struct cras_card_config { dictionary *ini; }; @@ -18,15 +22,15 @@ static struct cras_volume_curve * create_simple_step_curve(const struct cras_card_config *card_config, const char *control_name) { - char ini_key[MAX_INI_KEY_LENGTH + 1]; + char ini_key[MAX_KEY_LEN + 1]; int max_volume; int volume_step; - snprintf(ini_key, MAX_INI_KEY_LENGTH, "%s:max_volume", control_name); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, "%s:max_volume", control_name); + ini_key[MAX_KEY_LEN] = 0; max_volume = iniparser_getint(card_config->ini, ini_key, 0); - snprintf(ini_key, MAX_INI_KEY_LENGTH, "%s:volume_step", control_name); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, "%s:volume_step", control_name); + ini_key[MAX_KEY_LEN] = 0; volume_step = iniparser_getint(card_config->ini, ini_key, 300); syslog(LOG_INFO, "Configure curve found for %s.", control_name); return cras_volume_curve_create_simple_step(max_volume, volume_step); @@ -37,13 +41,12 @@ create_explicit_curve(const struct cras_card_config *card_config, const char *control_name) { unsigned int i; - char ini_key[MAX_INI_KEY_LENGTH + 1]; + char ini_key[MAX_KEY_LEN + 1]; long dB_values[101]; for (i = 0; i < 101; i++) { - snprintf(ini_key, MAX_INI_KEY_LENGTH, "%s:dB_at_%u", - control_name, i); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, "%s:dB_at_%u", control_name, i); + ini_key[MAX_KEY_LEN] = 0; dB_values[i] = iniparser_getint(card_config->ini, ini_key, 0); } syslog(LOG_INFO, "Explicit volume curve found for %s.", control_name); @@ -58,12 +61,11 @@ struct cras_card_config *cras_card_config_create(const char *config_path, const char *card_name) { struct cras_card_config *card_config = NULL; - char ini_name[MAX_INI_NAME_LENGTH + 1]; + char ini_name[MAX_INI_NAME_LEN + 1]; dictionary *ini; - snprintf(ini_name, MAX_INI_NAME_LENGTH, "%s/%s", config_path, - card_name); - ini_name[MAX_INI_NAME_LENGTH] = '\0'; + snprintf(ini_name, MAX_INI_NAME_LEN, "%s/%s", config_path, card_name); + ini_name[MAX_INI_NAME_LEN] = '\0'; ini = iniparser_load_wrapper(ini_name); if (ini == NULL) { syslog(LOG_DEBUG, "No ini file %s", ini_name); @@ -91,14 +93,14 @@ void cras_card_config_destroy(struct cras_card_config *card_config) struct cras_volume_curve *cras_card_config_get_volume_curve_for_control( const struct cras_card_config *card_config, const char *control_name) { - char ini_key[MAX_INI_KEY_LENGTH + 1]; + char ini_key[MAX_KEY_LEN + 1]; const char *curve_type; if (card_config == NULL || control_name == NULL) return NULL; - snprintf(ini_key, MAX_INI_KEY_LENGTH, "%s:volume_curve", control_name); - ini_key[MAX_INI_KEY_LENGTH] = 0; + snprintf(ini_key, MAX_KEY_LEN, "%s:volume_curve", control_name); + ini_key[MAX_KEY_LEN] = 0; curve_type = iniparser_getstring(card_config->ini, ini_key, NULL); if (curve_type && strcmp(curve_type, "simple_step") == 0) diff --git a/cras/src/server/config/cras_device_blacklist.c b/cras/src/server/config/cras_device_blacklist.c new file mode 100644 index 00000000..1d18eb0e --- /dev/null +++ b/cras/src/server/config/cras_device_blacklist.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cras_device_blacklist.h" +#include "iniparser_wrapper.h" +#include "utlist.h" + +/* Allocate 63 chars + 1 for null where declared. */ +static const unsigned int MAX_INI_NAME_LEN = 63; +static const unsigned int MAX_KEY_LEN = 63; + +struct cras_device_blacklist { + dictionary *ini; +}; + +/* + * Exported Interface + */ + +struct cras_device_blacklist * +cras_device_blacklist_create(const char *config_path) +{ + struct cras_device_blacklist *blacklist; + char ini_name[MAX_INI_NAME_LEN + 1]; + + blacklist = calloc(1, sizeof(*blacklist)); + if (!blacklist) + return NULL; + + snprintf(ini_name, MAX_INI_NAME_LEN, "%s/%s", config_path, + "device_blacklist"); + ini_name[MAX_INI_NAME_LEN] = '\0'; + blacklist->ini = iniparser_load_wrapper(ini_name); + + return blacklist; +} + +void cras_device_blacklist_destroy(struct cras_device_blacklist *blacklist) +{ + if (blacklist && blacklist->ini) + iniparser_freedict(blacklist->ini); + free(blacklist); +} + +int cras_device_blacklist_check(struct cras_device_blacklist *blacklist, + unsigned vendor_id, unsigned product_id, + unsigned desc_checksum, unsigned device_index) +{ + char ini_key[MAX_KEY_LEN + 1]; + + if (!blacklist) + return 0; + + snprintf(ini_key, MAX_KEY_LEN, "USB_Outputs:%04x_%04x_%08x_%u", + vendor_id, product_id, desc_checksum, device_index); + ini_key[MAX_KEY_LEN] = 0; + return iniparser_getboolean(blacklist->ini, ini_key, 0); +} diff --git a/cras/src/server/config/cras_device_blocklist.h b/cras/src/server/config/cras_device_blacklist.h index d0f750bd..ac7cfe23 100644 --- a/cras/src/server/config/cras_device_blocklist.h +++ b/cras/src/server/config/cras_device_blacklist.h @@ -8,41 +8,41 @@ * useful for devices that present non-functional alsa devices. For instance * some mics show a phantom playback device. */ -#ifndef CRAS_DEVICE_BLOCKLIST_H_ -#define CRAS_DEVICE_BLOCKLIST_H_ +#ifndef CRAS_DEVICE_BLACKLIST_H_ +#define CRAS_DEVICE_BLACKLIST_H_ #include <stdint.h> #include "cras_types.h" -struct cras_device_blocklist; +struct cras_device_blacklist; -/* Creates a blocklist of devices that should never be added to the system. +/* Creates a blacklist of devices that should never be added to the system. * Args: * config_path - Path containing the config files. * Returns: - * A pointer to the created blocklist on success, NULL on failure. + * A pointer to the created blacklist on success, NULL on failure. */ -struct cras_device_blocklist * -cras_device_blocklist_create(const char *config_path); +struct cras_device_blacklist * +cras_device_blacklist_create(const char *config_path); -/* Destroys a blocklist returned by cras_device_blocklist_create(). +/* Destroys a blacklist returned by cras_device_blacklist_create(). * Args: - * blocklist - Blocklist returned by cras_device_blocklist_create() + * blacklist - Blacklist returned by cras_device_blacklist_create() */ -void cras_device_blocklist_destroy(struct cras_device_blocklist *blocklist); +void cras_device_blacklist_destroy(struct cras_device_blacklist *blacklist); -/* Checks if a playback device on a USB card is blocklisted. +/* Checks if a playback device on a USB card is blacklisted. * Args: - * blocklist - Blocklist returned by cras_device_blocklist_create() + * blacklist - Blacklist returned by cras_device_blacklist_create() * vendor_id - USB vendor ID. * product_id - USB product ID. * device_index - Index of the alsa device in the card. * Returns: - * 1 if the device is blocklisted, 0 otherwise. + * 1 if the device is blacklisted, 0 otherwise. */ -int cras_device_blocklist_check(struct cras_device_blocklist *blocklist, +int cras_device_blacklist_check(struct cras_device_blacklist *blacklist, unsigned vendor_id, unsigned product_id, unsigned desc_checksum, unsigned device_index); -#endif /* CRAS_CARD_DEVICE_BLOCKLIST_H_ */ +#endif /* CRAS_CARD_DEVICE_BLACKLIST_H_ */ diff --git a/cras/src/server/config/cras_device_blocklist.c b/cras/src/server/config/cras_device_blocklist.c deleted file mode 100644 index d418fb80..00000000 --- a/cras/src/server/config/cras_device_blocklist.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "cras_device_blocklist.h" -#include "iniparser_wrapper.h" -#include "utlist.h" - -struct cras_device_blocklist { - dictionary *ini; -}; - -/* - * Exported Interface - */ - -struct cras_device_blocklist * -cras_device_blocklist_create(const char *config_path) -{ - struct cras_device_blocklist *blocklist; - char ini_name[MAX_INI_NAME_LENGTH + 1]; - - blocklist = calloc(1, sizeof(*blocklist)); - if (!blocklist) - return NULL; - - snprintf(ini_name, MAX_INI_NAME_LENGTH, "%s/%s", config_path, - "device_blocklist"); - ini_name[MAX_INI_NAME_LENGTH] = '\0'; - blocklist->ini = iniparser_load_wrapper(ini_name); - - return blocklist; -} - -void cras_device_blocklist_destroy(struct cras_device_blocklist *blocklist) -{ - if (blocklist && blocklist->ini) - iniparser_freedict(blocklist->ini); - free(blocklist); -} - -int cras_device_blocklist_check(struct cras_device_blocklist *blocklist, - unsigned vendor_id, unsigned product_id, - unsigned desc_checksum, unsigned device_index) -{ - char ini_key[MAX_INI_KEY_LENGTH + 1]; - - if (!blocklist) - return 0; - - snprintf(ini_key, MAX_INI_KEY_LENGTH, "USB_Outputs:%04x_%04x_%08x_%u", - vendor_id, product_id, desc_checksum, device_index); - ini_key[MAX_INI_KEY_LENGTH] = 0; - return iniparser_getboolean(blocklist->ini, ini_key, 0); -} diff --git a/cras/src/server/cras.c b/cras/src/server/cras.c index 8d23907a..32953ef3 100644 --- a/cras/src/server/cras.c +++ b/cras/src/server/cras.c @@ -9,7 +9,6 @@ #include <stdio.h> #include <syslog.h> -#include "cras_alsa_plugin_io.h" #include "cras_apm_list.h" #include "cras_config.h" #include "cras_iodev_list.h" @@ -38,7 +37,7 @@ static void set_signals() int main(int argc, char **argv) { int c, option_index; - int log_mask = LOG_WARNING; + int log_mask = LOG_ERR; const char default_dsp_config[] = CRAS_CONFIG_FILE_DIR "/dsp.ini"; const char *dsp_config = default_dsp_config; const char *device_config_dir = CRAS_CONFIG_FILE_DIR; @@ -139,7 +138,6 @@ int main(int argc, char **argv) cras_dsp_init(dsp_config); cras_apm_list_init(device_config_dir); cras_iodev_list_init(); - cras_alsa_plugin_io_init(device_config_dir); /* Start the server. */ return cras_server_run(profile_disable_mask); diff --git a/cras/src/server/cras_a2dp_info.c b/cras/src/server/cras_a2dp_info.c index b2db3848..ffddb252 100644 --- a/cras/src/server/cras_a2dp_info.c +++ b/cras/src/server/cras_a2dp_info.c @@ -104,7 +104,7 @@ int a2dp_queued_frames(const struct a2dp_info *a2dp) return a2dp->samples; } -void a2dp_reset(struct a2dp_info *a2dp) +void a2dp_drain(struct a2dp_info *a2dp) { a2dp->a2dp_buf_used = sizeof(struct rtp_header) + sizeof(struct rtp_payload); @@ -180,7 +180,8 @@ int a2dp_encode(struct a2dp_info *a2dp, const void *pcm_buf, int pcm_buf_size, int a2dp_write(struct a2dp_info *a2dp, int stream_fd, size_t link_mtu) { /* Do avdtp write when the max number of SBC frames is reached. */ - if (a2dp->a2dp_buf_used + a2dp->frame_length > link_mtu) + if (a2dp->a2dp_buf_used + a2dp->frame_length > + link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) return avdtp_write(stream_fd, a2dp); return 0; diff --git a/cras/src/server/cras_a2dp_info.h b/cras/src/server/cras_a2dp_info.h index b33911e8..eaf00d5b 100644 --- a/cras/src/server/cras_a2dp_info.h +++ b/cras/src/server/cras_a2dp_info.h @@ -8,7 +8,7 @@ #include "a2dp-codecs.h" -#define A2DP_BUF_SIZE_BYTES 2048 +#define A2DP_BUF_SIZE_BYTES 1024 /* Represents the codec and encoded state of a2dp iodev. * Members: @@ -60,9 +60,9 @@ int a2dp_block_size(struct a2dp_info *a2dp, int encoded_bytes); int a2dp_queued_frames(const struct a2dp_info *a2dp); /* - * Empty all queued samples in a2dp_info. + * Drains queued samples in a2dp_info. */ -void a2dp_reset(struct a2dp_info *a2dp); +void a2dp_drain(struct a2dp_info *a2dp); /* * Encodes samples using the codec for this a2dp instance, returns the number of diff --git a/cras/src/server/cras_a2dp_iodev.c b/cras/src/server/cras_a2dp_iodev.c index b8a606e4..f6351aba 100644 --- a/cras/src/server/cras_a2dp_iodev.c +++ b/cras/src/server/cras_a2dp_iodev.c @@ -20,24 +20,19 @@ #include "cras_a2dp_info.h" #include "cras_a2dp_iodev.h" #include "cras_audio_area.h" -#include "cras_audio_thread_monitor.h" #include "cras_bt_device.h" #include "cras_iodev.h" #include "cras_util.h" +#include "sfh.h" #include "rtp.h" #include "utlist.h" #define PCM_BUF_MAX_SIZE_FRAMES (4096 * 4) #define PCM_BUF_MAX_SIZE_BYTES (PCM_BUF_MAX_SIZE_FRAMES * 4) -/* Threshold for reasonable a2dp throttle log in audio dump. */ -static const struct timespec throttle_log_threshold = { - 0, 20000000 /* 20ms */ -}; - -/* Threshold for severe a2dp throttle event. */ -static const struct timespec throttle_event_threshold = { - 2, 0 /* 2s */ +/* no_stream target_frames in timespec. */ +static const struct timespec no_stream_target_frames_ts = { + 0, 10 * 1000 * 1000 /* 10 msec. */ }; /* Child of cras_iodev to handle bluetooth A2DP streaming. @@ -48,10 +43,14 @@ static const struct timespec throttle_event_threshold = { * sock_depth_frames - Socket depth in frames of the a2dp socket. * pcm_buf - Buffer to hold pcm samples before encode. * destroyed - Flag to note if this a2dp_io is about to destroy. - * next_flush_time - The time when it is okay for next flush call. - * flush_period - The time period between two a2dp packet writes. - * write_block - How many frames of audio samples are transferred in one - * a2dp packet write. + * bt_written_frames - Accumulated frames written to a2dp socket. Used + * together with the device open timestamp to estimate how many virtual + * buffer is queued there. + * dev_open_time - The last time a2dp_ios is opened. + * drain_complete - Flag to indicate if valid frames have all been drained + * in no stream state. + * filled_zeros_bytes - Number of zero data in bytes that have been filled + * in no stream state. */ struct a2dp_io { struct cras_iodev base; @@ -60,12 +59,13 @@ struct a2dp_io { unsigned sock_depth_frames; struct byte_buffer *pcm_buf; int destroyed; - struct timespec next_flush_time; - struct timespec flush_period; - unsigned int write_block; + uint64_t bt_written_frames; + struct timespec dev_open_time; + bool drain_complete; + int filled_zeros_bytes; }; -static int encode_and_flush(const struct cras_iodev *iodev); +static int flush_data(void *arg); static int update_supported_formats(struct cras_iodev *iodev) { @@ -76,6 +76,7 @@ static int update_supported_formats(struct cras_iodev *iodev) cras_bt_transport_configuration(a2dpio->transport, &a2dp, sizeof(a2dp)); + iodev->format->format = SND_PCM_FORMAT_S16_LE; channel = (a2dp.channel_mode == SBC_CHANNEL_MODE_MONO) ? 1 : 2; if (a2dp.frequency & SBC_SAMPLING_FREQ_48000) @@ -101,167 +102,97 @@ static int update_supported_formats(struct cras_iodev *iodev) iodev->supported_formats = (snd_pcm_format_t *)malloc(2 * sizeof(snd_pcm_format_t)); iodev->supported_formats[0] = SND_PCM_FORMAT_S16_LE; - iodev->supported_formats[1] = (snd_pcm_format_t)0; + iodev->supported_formats[1] = 0; return 0; } -static unsigned int bt_local_queued_frames(const struct cras_iodev *iodev) +/* Calculates the number of virtual buffer in frames. Assuming all written + * buffer is consumed in a constant frame rate at bluetooth device side. + * Args: + * iodev: The a2dp iodev to estimate the queued frames for. + * fr: The amount of frames just transmitted. + */ +static int bt_queued_frames(const struct cras_iodev *iodev, int fr) { + uint64_t consumed; struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; - return a2dp_queued_frames(&a2dpio->a2dp) + - buf_queued(a2dpio->pcm_buf) / - cras_get_format_bytes(iodev->format); + + /* Calculate consumed frames since device has opened */ + a2dpio->bt_written_frames += fr; + consumed = cras_frames_since_time(&a2dpio->dev_open_time, + iodev->format->frame_rate); + + if (a2dpio->bt_written_frames > consumed) + return a2dpio->bt_written_frames - consumed; + else + return 0; } static int frames_queued(const struct cras_iodev *iodev, struct timespec *tstamp) { - int local_queued_frames = bt_local_queued_frames(iodev); + struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; + int estimate_queued_frames = bt_queued_frames(iodev, 0); + int local_queued_frames = a2dp_queued_frames(&a2dpio->a2dp) + + buf_queued(a2dpio->pcm_buf) / + cras_get_format_bytes(iodev->format); clock_gettime(CLOCK_MONOTONIC_RAW, tstamp); - return MIN(iodev->buffer_size, local_queued_frames); + return MIN(iodev->buffer_size, + MAX(estimate_queued_frames, local_queued_frames)); } -/* - * Utility function to fill zero frames until buffer level reaches - * target_level. This is useful to allocate just enough data to write - * to controller, while not introducing extra latency. - */ -static int fill_zeros_to_target_level(struct cras_iodev *iodev, - unsigned int target_level) +static int no_stream(struct cras_iodev *iodev, int enable) { - unsigned int local_queued_frames = bt_local_queued_frames(iodev); + struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; + unsigned int buf_avail; + unsigned int format_bytes; + unsigned int target_bytes; + unsigned int target_total_bytes; + unsigned int bt_queued_bytes; + uint8_t *buf; + struct timespec tstamp; + int i; - if (local_queued_frames < target_level) - return cras_iodev_fill_odev_zeros( - iodev, target_level - local_queued_frames); - return 0; -} + format_bytes = cras_get_format_bytes(iodev->format); -/* - * dev_io_playback_write() has the logic to detect underrun scenario - * and calls into this underrun ops, by comparing buffer level with - * number of frames just written. Note that it's not correct 100% of - * the time in a2dp case, because we lose track of samples once they're - * flushed to socket. - */ -static int output_underrun(struct cras_iodev *iodev) -{ - unsigned int local_queued_frames = bt_local_queued_frames(iodev); - - /* - * Examples to help understand the check: - * - * [False-positive underrun] - * Assume min_buffer_level = 1000, written 900, and flushes - * 800 of data. Audio thread sees 1000 + 900 - 800 = 1100 of - * data left. This is merely 100(< 900) above min_buffer_level - * so audio_thread thinks it underruns, but actually not. - * - * [True underrun] - * min_buffer_level = 1000, written 200, and flushes 800 of - * data. Now that buffer runs lower than min_buffer_level so - * it's indeed an underrun. - */ - if (local_queued_frames > iodev->min_buffer_level) + if (enable) { + /* Target to have let hw_level = 2 * (frames in 10ms) */ + bt_queued_bytes = + cras_iodev_frames_queued(iodev, &tstamp) * format_bytes; + target_total_bytes = + 2 * + cras_time_to_frames(&no_stream_target_frames_ts, + iodev->format->frame_rate) * + format_bytes; + if (target_total_bytes <= bt_queued_bytes) + return 0; + target_total_bytes -= bt_queued_bytes; + + /* Loop twice to make sure target_total_bytes are filled. */ + for (i = 0; i < 2; i++) { + buf = buf_write_pointer_size(a2dpio->pcm_buf, + &buf_avail); + if (buf_avail == 0 || target_total_bytes == 0) + break; + target_bytes = MIN(buf_avail, target_total_bytes); + memset(buf, 0, target_bytes); + buf_increment_write(a2dpio->pcm_buf, target_bytes); + bt_queued_frames(iodev, target_bytes / format_bytes); + target_total_bytes -= target_bytes; + } + flush_data(iodev); return 0; - - return cras_iodev_fill_odev_zeros(iodev, iodev->min_cb_level); -} - -/* - * This will be called multiple times when a2dpio is in no_stream state - * frames_to_play_in_sleep ops determins how regular this will be called. - */ -static int enter_no_stream(struct a2dp_io *a2dpio) -{ - struct cras_iodev *odev = &a2dpio->base; - int rc; - /* - * Setting target level to 3 times of min_buffer_level. - * We want hw_level to stay bewteen 1-2 times of min_buffer_level on - * top of the underrun threshold(i.e one min_cb_level). - */ - rc = fill_zeros_to_target_level(odev, 3 * odev->min_buffer_level); - if (rc) - syslog(LOG_ERR, "Error in A2DP enter_no_stream"); - return encode_and_flush(odev); -} - -/* - * This is called when stream data is available to write. Prepare audio - * data to one min_buffer_level. Don't flush it now because stream data is - * coming right up which will trigger next flush at appropriate time. - */ -static int leave_no_stream(struct a2dp_io *a2dpio) -{ - struct cras_iodev *odev = &a2dpio->base; - - /* - * Since stream data is ready, just make sure hw_level doesn't underrun - * after one flush. Hence setting the target level to 2 times of - * min_buffer_level. - */ - return fill_zeros_to_target_level(odev, 2 * odev->min_buffer_level); -} - -/* - * Makes sure there's enough data(zero frames) to flush when no stream presents. - * Note that the underrun condition is when real buffer level goes below - * min_buffer_level, so we want to keep data at a reasonable higher level on top - * of that. - */ -static int no_stream(struct cras_iodev *odev, int enable) -{ - struct a2dp_io *a2dpio = (struct a2dp_io *)odev; - - if (enable) - return enter_no_stream(a2dpio); - else - return leave_no_stream(a2dpio); -} - -/* Encode as much PCM data as we can until the buffer level of a2dp_info - * reaches MTU. - * Returns: - * 0 for success, otherwise negative error code. - */ -static int encode_a2dp_packet(struct a2dp_io *a2dpio) -{ - int processed; - size_t format_bytes = cras_get_format_bytes(a2dpio->base.format); - - while (buf_queued(a2dpio->pcm_buf)) { - processed = a2dp_encode( - &a2dpio->a2dp, buf_read_pointer(a2dpio->pcm_buf), - buf_readable(a2dpio->pcm_buf), format_bytes, - cras_bt_transport_write_mtu(a2dpio->transport)); - if (processed == -ENOSPC || processed == 0) - break; - if (processed < 0) - return processed; - - buf_increment_read(a2dpio->pcm_buf, processed); } return 0; } -/* - * To be called when a2dp socket becomes writable. - */ -static int a2dp_socket_write_cb(void *arg, int revent) -{ - struct cras_iodev *iodev = (struct cras_iodev *)arg; - return encode_and_flush(iodev); -} - static int configure_dev(struct cras_iodev *iodev) { struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; int sock_depth; int err; socklen_t optlen; - int a2dp_payload_length; err = cras_bt_transport_acquire(a2dpio->transport); if (err < 0) { @@ -284,60 +215,34 @@ static int configure_dev(struct cras_iodev *iodev) if (!a2dpio->pcm_buf) return -ENOMEM; + iodev->buffer_size = PCM_BUF_MAX_SIZE_FRAMES; + /* Set up the socket to hold two MTUs full of data before returning * EAGAIN. This will allow the write to be throttled when a reasonable * amount of data is queued. */ sock_depth = 2 * cras_bt_transport_write_mtu(a2dpio->transport); setsockopt(cras_bt_transport_fd(a2dpio->transport), SOL_SOCKET, SO_SNDBUF, &sock_depth, sizeof(sock_depth)); + optlen = sizeof(sock_depth); getsockopt(cras_bt_transport_fd(a2dpio->transport), SOL_SOCKET, SO_SNDBUF, &sock_depth, &optlen); a2dpio->sock_depth_frames = a2dp_block_size(&a2dpio->a2dp, sock_depth) / cras_get_format_bytes(iodev->format); - /* - * Per avdtp_write, subtract the room for packet header first. - * Calculate how many frames are encapsulated in one a2dp packet, and - * the corresponding time period between two packets. - */ - a2dp_payload_length = cras_bt_transport_write_mtu(a2dpio->transport) - - sizeof(struct rtp_header) - - sizeof(struct rtp_payload); - a2dpio->write_block = - a2dp_block_size(&a2dpio->a2dp, a2dp_payload_length) / - cras_get_format_bytes(iodev->format); - cras_frames_to_time(a2dpio->write_block, iodev->format->frame_rate, - &a2dpio->flush_period); - - /* PCM buffer size plus one encoded a2dp packet. */ - iodev->buffer_size = PCM_BUF_MAX_SIZE_FRAMES + a2dpio->write_block; - - /* - * Buffer level less than one write_block can't be send over a2dp - * packet. Configure min_buffer_level to this value so when stream - * underruns, audio thread can take action to fill some zeros. - */ - iodev->min_buffer_level = a2dpio->write_block; - audio_thread_add_events_callback( - cras_bt_transport_fd(a2dpio->transport), a2dp_socket_write_cb, - iodev, POLLOUT | POLLERR | POLLHUP); - audio_thread_config_events_callback( - cras_bt_transport_fd(a2dpio->transport), TRIGGER_NONE); - return 0; -} + iodev->min_buffer_level = a2dpio->sock_depth_frames; -static int start(const struct cras_iodev *iodev) -{ - struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; + a2dpio->drain_complete = 0; + a2dpio->filled_zeros_bytes = 0; - /* - * This is called when iodev in open state, at the moment when - * output sample is ready. Initialize the next_flush_time for - * following flush calls. - */ - clock_gettime(CLOCK_MONOTONIC_RAW, &a2dpio->next_flush_time); + /* Initialize variables for bt_queued_frames() */ + a2dpio->bt_written_frames = 0; + clock_gettime(CLOCK_MONOTONIC_RAW, &a2dpio->dev_open_time); + audio_thread_add_write_callback(cras_bt_transport_fd(a2dpio->transport), + flush_data, iodev); + audio_thread_enable_callback(cras_bt_transport_fd(a2dpio->transport), + 0); return 0; } @@ -362,53 +267,26 @@ static int close_dev(struct cras_iodev *iodev) device = cras_bt_transport_device(a2dpio->transport); if (device) cras_bt_device_cancel_suspend(device); - a2dp_reset(&a2dpio->a2dp); + a2dp_drain(&a2dpio->a2dp); byte_buffer_destroy(&a2dpio->pcm_buf); cras_iodev_free_format(iodev); cras_iodev_free_audio_area(iodev); return 0; } -static unsigned int frames_to_play_in_sleep(struct cras_iodev *iodev, - unsigned int *hw_level, - struct timespec *hw_tstamp) -{ - struct a2dp_io *a2dpio = (struct a2dp_io *)iodev; - int frames_until; - - *hw_level = frames_queued(iodev, hw_tstamp); - if (*hw_level < a2dpio->write_block) - *hw_level = 0; - else - *hw_level -= a2dpio->write_block; - - frames_until = cras_frames_until_time(&a2dpio->next_flush_time, - iodev->format->frame_rate); - if (frames_until > 0) - return frames_until; - - /* If time has passed next_flush_time, for example when socket write - * throttles, sleep a moderate of time so that audio thread doesn't - * busy wake up. */ - return a2dpio->write_block; -} - -/* Encodes PCM data to a2dp frames and try to flush it to the socket. +/* Flushes queued buffer, including pcm and a2dp buffer. * Returns: * 0 when the flush succeeded, -1 when error occurred. */ -static int encode_and_flush(const struct cras_iodev *iodev) +static int flush_data(void *arg) { - int err; + struct cras_iodev *iodev = (struct cras_iodev *)arg; + int processed; size_t format_bytes; int written = 0; - unsigned int queued_frames; + int queued_frames; struct a2dp_io *a2dpio; struct cras_bt_device *device; - struct timespec now, ts; - static const struct timespec flush_wake_fuzz_ts = { - 0, 1000000 /* 1ms */ - }; a2dpio = (struct a2dp_io *)iodev; format_bytes = cras_get_format_bytes(iodev->format); @@ -419,51 +297,23 @@ static int encode_and_flush(const struct cras_iodev *iodev) if (device == NULL) return -EINVAL; - ATLOG(atlog, AUDIO_THREAD_A2DP_FLUSH, iodev->state, - a2dpio->next_flush_time.tv_sec, a2dpio->next_flush_time.tv_nsec); - - /* Only allow data to be flushed after start() ops is called. */ - if ((iodev->state != CRAS_IODEV_STATE_NORMAL_RUN) && - (iodev->state != CRAS_IODEV_STATE_NO_STREAM_RUN)) - return 0; - - err = encode_a2dp_packet(a2dpio); - if (err < 0) - return err; +encode_more: + while (buf_queued(a2dpio->pcm_buf)) { + processed = a2dp_encode( + &a2dpio->a2dp, buf_read_pointer(a2dpio->pcm_buf), + buf_readable(a2dpio->pcm_buf), format_bytes, + cras_bt_transport_write_mtu(a2dpio->transport)); + ATLOG(atlog, AUDIO_THREAD_A2DP_ENCODE, processed, + buf_queued(a2dpio->pcm_buf), + buf_readable(a2dpio->pcm_buf)); + if (processed == -ENOSPC || processed == 0) + break; + if (processed < 0) + return 0; -do_flush: - /* If flush gets called before targeted next flush time, do nothing. */ - clock_gettime(CLOCK_MONOTONIC_RAW, &now); - add_timespecs(&now, &flush_wake_fuzz_ts); - if (!timespec_after(&now, &a2dpio->next_flush_time)) { - if (iodev->buffer_size == bt_local_queued_frames(iodev)) { - /* - * If buffer is full, audio thread will no longer call - * into get/put buffer in subsequent wake-ups. In that - * case set the registered callback to be triggered at - * next audio thread wake up. - */ - audio_thread_config_events_callback( - cras_bt_transport_fd(a2dpio->transport), - TRIGGER_WAKEUP); - cras_audio_thread_event_a2dp_overrun(); - syslog(LOG_WARNING, "Buffer overrun in A2DP iodev"); - } - return 0; + buf_increment_read(a2dpio->pcm_buf, processed); } - /* If the A2DP write schedule miss exceeds a small threshold, log it for - * debug purpose. */ - subtract_timespecs(&now, &a2dpio->next_flush_time, &ts); - if (timespec_after(&ts, &throttle_log_threshold)) - ATLOG(atlog, AUDIO_THREAD_A2DP_THROTTLE_TIME, ts.tv_sec, - ts.tv_nsec, bt_local_queued_frames(iodev)); - - /* Log an event if the A2DP write schedule miss exceeds a large threshold - * that we consider it as something severe. */ - if (timespec_after(&ts, &throttle_event_threshold)) - cras_audio_thread_event_a2dp_throttle(); - written = a2dp_write(&a2dpio->a2dp, cras_bt_transport_fd(a2dpio->transport), cras_bt_transport_write_mtu(a2dpio->transport)); @@ -472,32 +322,18 @@ do_flush: if (written == -EAGAIN) { /* If EAGAIN error lasts longer than 5 seconds, suspend the * a2dp connection. */ - cras_bt_device_schedule_suspend(device, 5000, - A2DP_LONG_TX_FAILURE); - audio_thread_config_events_callback( - cras_bt_transport_fd(a2dpio->transport), TRIGGER_POLL); + cras_bt_device_schedule_suspend(device, 5000); + audio_thread_enable_callback( + cras_bt_transport_fd(a2dpio->transport), 1); return 0; } else if (written < 0) { /* Suspend a2dp immediately when receives error other than * EAGAIN. */ cras_bt_device_cancel_suspend(device); - cras_bt_device_schedule_suspend(device, 0, A2DP_TX_FATAL_ERROR); - /* Stop polling the socket in audio thread. Main thread will - * close this iodev soon. */ - audio_thread_config_events_callback( - cras_bt_transport_fd(a2dpio->transport), TRIGGER_NONE); + cras_bt_device_schedule_suspend(device, 0); return written; } - /* Update the next flush time if one block successfully been written. */ - if (written) - add_timespecs(&a2dpio->next_flush_time, &a2dpio->flush_period); - - /* a2dp_write no longer return -EAGAIN when reaches here, disable - * the polling write callback. */ - audio_thread_config_events_callback( - cras_bt_transport_fd(a2dpio->transport), TRIGGER_NONE); - /* Data succcessfully written to a2dp socket, cancel any scheduled * suspend timer. */ cras_bt_device_cancel_suspend(device); @@ -507,13 +343,12 @@ do_flush: * to min_buffer_level so that another A2DP write could causes underrun. */ queued_frames = buf_queued(a2dpio->pcm_buf) / format_bytes; - if (written && - (iodev->min_buffer_level + a2dpio->write_block < queued_frames)) { - err = encode_a2dp_packet(a2dpio); - if (err < 0) - return err; - goto do_flush; - } + if (written && (iodev->min_buffer_level + written < queued_frames)) + goto encode_more; + + /* everything written. */ + audio_thread_enable_callback(cras_bt_transport_fd(a2dpio->transport), + 0); return 0; } @@ -562,7 +397,13 @@ static int put_buffer(struct cras_iodev *iodev, unsigned nwritten) buf_increment_write(a2dpio->pcm_buf, written_bytes); - return encode_and_flush(iodev); + /* Set dev open time at when the first data arrives. */ + if (nwritten && !a2dpio->bt_written_frames) + clock_gettime(CLOCK_MONOTONIC_RAW, &a2dpio->dev_open_time); + + bt_queued_frames(iodev, nwritten); + + return flush_data(iodev); } static int flush_buffer(struct cras_iodev *iodev) @@ -643,7 +484,10 @@ struct cras_iodev *a2dp_iodev_create(struct cras_bt_transport *transport) snprintf(iodev->info.name, sizeof(iodev->info.name), "%s", name); iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0'; - iodev->info.stable_id = cras_bt_device_get_stable_id(device); + iodev->info.stable_id = + SuperFastHash(cras_bt_device_object_path(device), + strlen(cras_bt_device_object_path(device)), + strlen(cras_bt_device_object_path(device))); iodev->configure_dev = configure_dev; iodev->frames_queued = frames_queued; @@ -652,15 +496,12 @@ struct cras_iodev *a2dp_iodev_create(struct cras_bt_transport *transport) iodev->put_buffer = put_buffer; iodev->flush_buffer = flush_buffer; iodev->no_stream = no_stream; - iodev->output_underrun = output_underrun; iodev->close_dev = close_dev; iodev->update_supported_formats = update_supported_formats; iodev->update_active_node = update_active_node; iodev->set_volume = set_volume; - iodev->start = start; - iodev->frames_to_play_in_sleep = frames_to_play_in_sleep; - /* Create an empty ionode */ + /* Create a dummy ionode */ node = (struct cras_ionode *)calloc(1, sizeof(*node)); node->dev = iodev; strcpy(node->name, iodev->info.name); @@ -669,18 +510,11 @@ struct cras_iodev *a2dp_iodev_create(struct cras_bt_transport *transport) node->volume = 100; gettimeofday(&node->plugged_time, NULL); - /* Prepare active node before append, so bt_io can extract correct - * info from A2DP iodev and node. */ - cras_iodev_add_node(iodev, node); - cras_iodev_set_active_node(iodev, node); + /* A2DP does output only */ cras_bt_device_append_iodev( device, iodev, cras_bt_transport_profile(a2dpio->transport)); - - /* Record max supported channels into cras_iodev_info. */ - iodev->info.max_supported_channels = - (a2dp.channel_mode == SBC_CHANNEL_MODE_MONO) ? 1 : 2; - - ewma_power_disable(&iodev->ewma); + cras_iodev_add_node(iodev, node); + cras_iodev_set_active_node(iodev, node); return iodev; error: diff --git a/cras/src/server/cras_alsa_card.c b/cras/src/server/cras_alsa_card.c index 362e6a68..709cc1d5 100644 --- a/cras/src/server/cras_alsa_card.c +++ b/cras/src/server/cras_alsa_card.c @@ -14,7 +14,7 @@ #include "cras_alsa_io.h" #include "cras_alsa_mixer.h" #include "cras_alsa_ucm.h" -#include "cras_device_blocklist.h" +#include "cras_device_blacklist.h" #include "cras_card_config.h" #include "cras_config.h" #include "cras_iodev.h" @@ -25,8 +25,8 @@ #include "utlist.h" #define MAX_ALSA_CARDS 32 /* Alsa limit on number of cards. */ -#define MAX_ALSA_CARD_NAME_LENGTH 6 /* Alsa card name "hw:XX" + 1 for null. */ -#define MAX_ALSA_PCM_NAME_LENGTH 9 /* Alsa pcm name "hw:XX,YY" + 1 for null. */ +#define MAX_ALSA_PCM_NAME_LENGTH 6 /* Alsa names "hw:XX" + 1 for null. */ +#define MAX_INI_NAME_LENGTH 63 /* 63 chars + 1 for null where declared. */ #define MAX_COUPLED_OUTPUT_SIZE 4 struct iodev_list_node { @@ -43,7 +43,7 @@ struct hctl_poll_fd { }; /* Holds information about each sound card on the system. - * name - of the form hw:XX. + * name - of the form hw:XX,YY. * card_index - 0 based index, value of "XX" in the name. * iodevs - Input and output devices for this card. * mixer - Controls the mixer controls for this card. @@ -53,7 +53,7 @@ struct hctl_poll_fd { * config - Config info for this card, can be NULL if none found. */ struct cras_alsa_card { - char name[MAX_ALSA_CARD_NAME_LENGTH]; + char name[MAX_ALSA_PCM_NAME_LENGTH]; size_t card_index; struct iodev_list_node *iodevs; struct cras_alsa_mixer *mixer; @@ -84,7 +84,6 @@ struct cras_iodev *create_iodev_for_device( struct iodev_list_node *new_dev; struct iodev_list_node *node; int first = 1; - char pcm_name[MAX_ALSA_PCM_NAME_LENGTH]; /* Find whether this is the first device in this direction, and * avoid duplicate device indexes. */ @@ -104,28 +103,22 @@ struct cras_iodev *create_iodev_for_device( if (new_dev == NULL) return NULL; - /* Append device index to card namem, ex: 'hw:0', for the PCM name of - * target iodev. */ - snprintf(pcm_name, MAX_ALSA_PCM_NAME_LENGTH, "%s,%u", alsa_card->name, - device_index); - new_dev->direction = direction; - new_dev->iodev = - alsa_iodev_create(info->card_index, card_name, device_index, - pcm_name, dev_name, dev_id, info->card_type, - first, alsa_card->mixer, alsa_card->config, - alsa_card->ucm, alsa_card->hctl, direction, - info->usb_vendor_id, info->usb_product_id, - info->usb_serial_number); + new_dev->iodev = alsa_iodev_create( + info->card_index, card_name, device_index, dev_name, dev_id, + info->card_type, first, alsa_card->mixer, alsa_card->config, + alsa_card->ucm, alsa_card->hctl, direction, info->usb_vendor_id, + info->usb_product_id, info->usb_serial_number); if (new_dev->iodev == NULL) { - syslog(LOG_ERR, "Couldn't create alsa_iodev for %s", pcm_name); + syslog(LOG_ERR, "Couldn't create alsa_iodev for %u:%u\n", + info->card_index, device_index); free(new_dev); return NULL; } - syslog(LOG_DEBUG, "New %s device %s", + syslog(LOG_DEBUG, "New %s device %u:%d", direction == CRAS_STREAM_OUTPUT ? "playback" : "capture", - pcm_name); + info->card_index, device_index); DL_APPEND(alsa_card->iodevs, new_dev); return new_dev->iodev; @@ -146,15 +139,15 @@ static int card_has_hctl_jack(struct cras_alsa_card *alsa_card) } /* Check if a device should be ignored for this card. Returns non-zero if the - * device is in the blocklist and should be ignored. + * device is in the blacklist and should be ignored. */ static int should_ignore_dev(struct cras_alsa_card_info *info, - struct cras_device_blocklist *blocklist, + struct cras_device_blacklist *blacklist, size_t device_index) { if (info->card_type == ALSA_CARD_TYPE_USB) - return cras_device_blocklist_check( - blocklist, info->usb_vendor_id, info->usb_product_id, + return cras_device_blacklist_check( + blacklist, info->usb_vendor_id, info->usb_product_id, info->usb_desc_checksum, device_index); return 0; } @@ -178,7 +171,7 @@ static struct mixer_name *filter_controls(struct cras_use_case_mgr *ucm, /* Handles notifications from alsa controls. Called by main thread when a poll * fd provided by alsa signals there is an event available. */ -static void alsa_control_event_pending(void *arg, int revent) +static void alsa_control_event_pending(void *arg) { struct cras_alsa_card *card; @@ -195,7 +188,7 @@ static void alsa_control_event_pending(void *arg, int revent) static int add_controls_and_iodevs_by_matching(struct cras_alsa_card_info *info, - struct cras_device_blocklist *blocklist, + struct cras_device_blacklist *blacklist, struct cras_alsa_card *alsa_card, const char *card_name, snd_ctl_t *handle) { @@ -258,7 +251,7 @@ add_controls_and_iodevs_by_matching(struct cras_alsa_card_info *info, /* Check for playback devices. */ snd_pcm_info_set_stream(dev_info, SND_PCM_STREAM_PLAYBACK); if (snd_ctl_pcm_info(handle, dev_info) == 0 && - !should_ignore_dev(info, blocklist, dev_idx)) { + !should_ignore_dev(info, blacklist, dev_idx)) { struct cras_iodev *iodev = create_iodev_for_device( alsa_card, info, card_name, snd_pcm_info_get_name(dev_info), @@ -345,11 +338,6 @@ static int add_controls_and_iodevs_with_ucm(struct cras_alsa_card_info *info, /* Create all of the devices. */ DL_FOREACH (ucm_sections, section) { - /* If a UCM section specifies certain device as dependency - * then don't create an alsa iodev for it, just append it - * as node later. */ - if (section->dependent_dev_idx != -1) - continue; snd_pcm_info_set_device(dev_info, section->dev_idx); snd_pcm_info_set_subdevice(dev_info, 0); if (section->dir == CRAS_STREAM_OUTPUT) @@ -377,17 +365,11 @@ static int add_controls_and_iodevs_with_ucm(struct cras_alsa_card_info *info, section->dev_idx, section->dir); } - /* Setup jacks and controls for the devices. If a SectionDevice is - * dependent on another SectionDevice, it'll be added as a node to - * a existing ALSA iodev. */ + /* Setup jacks and controls for the devices. */ DL_FOREACH (ucm_sections, section) { DL_FOREACH (alsa_card->iodevs, node) { - if (node->direction != section->dir) - continue; - if (alsa_iodev_index(node->iodev) == section->dev_idx) - break; - if (alsa_iodev_index(node->iodev) == - section->dependent_dev_idx) + if (node->direction == section->dir && + alsa_iodev_index(node->iodev) == section->dev_idx) break; } if (node) { @@ -449,7 +431,7 @@ static void configure_echo_reference_dev(struct cras_alsa_card *alsa_card) struct cras_alsa_card *cras_alsa_card_create( struct cras_alsa_card_info *info, const char *device_config_dir, - struct cras_device_blocklist *blocklist, const char *ucm_suffix) + struct cras_device_blacklist *blacklist, const char *ucm_suffix) { snd_ctl_t *handle = NULL; int rc, n; @@ -469,7 +451,7 @@ struct cras_alsa_card *cras_alsa_card_create( return NULL; alsa_card->card_index = info->card_index; - snprintf(alsa_card->name, MAX_ALSA_CARD_NAME_LENGTH, "hw:%u", + snprintf(alsa_card->name, MAX_ALSA_PCM_NAME_LENGTH, "hw:%u", info->card_index); rc = snd_ctl_open(&handle, alsa_card->name, 0); @@ -490,10 +472,6 @@ struct cras_alsa_card *cras_alsa_card_create( goto error_bail; } - if (info->card_type != ALSA_CARD_TYPE_INTERNAL || - cras_system_check_ignore_ucm_suffix(card_name)) - ucm_suffix = NULL; - /* Read config file for this card if it exists. */ alsa_card->config = cras_card_config_create(device_config_dir, card_name); @@ -517,9 +495,6 @@ struct cras_alsa_card *cras_alsa_card_create( card_name, alsa_card->ucm ? "yes" : "no"); } - if (info->card_type == ALSA_CARD_TYPE_INTERNAL && !alsa_card->ucm) - syslog(LOG_ERR, "No ucm config on internal card %s", card_name); - rc = snd_hctl_open(&alsa_card->hctl, alsa_card->name, SND_CTL_NONBLOCK); if (rc < 0) { syslog(LOG_DEBUG, "failed to get hctl for %s", alsa_card->name); @@ -553,7 +528,7 @@ struct cras_alsa_card *cras_alsa_card_create( card_name, handle); else rc = add_controls_and_iodevs_by_matching( - info, blocklist, alsa_card, card_name, handle); + info, blacklist, alsa_card, card_name, handle); if (rc) goto error_bail; @@ -584,7 +559,7 @@ struct cras_alsa_card *cras_alsa_card_create( DL_APPEND(alsa_card->hctl_poll_fds, registered_fd); rc = cras_system_add_select_fd( registered_fd->fd, alsa_control_event_pending, - alsa_card, POLLIN); + alsa_card); if (rc < 0) { DL_DELETE(alsa_card->hctl_poll_fds, registered_fd); diff --git a/cras/src/server/cras_alsa_card.h b/cras/src/server/cras_alsa_card.h index a63bf90a..749a17fb 100644 --- a/cras/src/server/cras_alsa_card.h +++ b/cras/src/server/cras_alsa_card.h @@ -15,7 +15,7 @@ */ struct cras_alsa_card; -struct cras_device_blocklist; +struct cras_device_blacklist; /* Creates a cras_alsa_card instance for the given alsa device. Enumerates the * devices for the card and adds them to the system as possible playback or @@ -24,7 +24,7 @@ struct cras_device_blocklist; * card_info - Contains the card index, type, and priority. * device_config_dir - The directory of device configs which contains the * volume curves. - * blocklist - List of devices that should be ignored. + * blacklist - List of devices that should be ignored. * ucm_suffix - The ucm config name is formed as <card-name>.<suffix> * Returns: * A pointer to the newly created cras_alsa_card which must later be freed @@ -32,7 +32,7 @@ struct cras_device_blocklist; */ struct cras_alsa_card *cras_alsa_card_create( struct cras_alsa_card_info *info, const char *device_config_dir, - struct cras_device_blocklist *blocklist, const char *ucm_suffix); + struct cras_device_blacklist *blacklist, const char *ucm_suffix); /* Destroys a cras_alsa_card that was returned from cras_alsa_card_create. * Args: diff --git a/cras/src/server/cras_alsa_helpers.c b/cras/src/server/cras_alsa_helpers.c index 6cdc165a..b0729fd0 100644 --- a/cras/src/server/cras_alsa_helpers.c +++ b/cras/src/server/cras_alsa_helpers.c @@ -25,9 +25,6 @@ /* Time difference between two consecutive underrun logs. */ #define UNDERRUN_LOG_TIME_SECS 30 -/* Limit the number of channels supported for devices: b/158509536 */ -#define TEMP_CHANNEL_LIMIT 20 - /* Chances to give mmap_begin to work. */ static const size_t MAX_MMAP_BEGIN_ATTEMPTS = 3; /* Time to sleep between resume attempts. */ @@ -413,19 +410,8 @@ int cras_alsa_fill_properties(snd_pcm_t *handle, size_t **rates, } (*channel_counts)[num_found] = 0; if (num_found == 0) { - // Pull the max channel count and use that. - unsigned int max_channels = 0; - rc = snd_pcm_hw_params_get_channels_max(params, &max_channels); - if (rc < 0) { - syslog(LOG_WARNING, "No valid channel counts found."); - return -EINVAL; - } else if (max_channels > TEMP_CHANNEL_LIMIT) { - syslog(LOG_WARNING, "Can't support so many channels."); - return -EINVAL; - } else { - (*channel_counts)[0] = (size_t)max_channels; - (*channel_counts)[1] = 0; - } + syslog(LOG_WARNING, "No valid channel counts found."); + return -EINVAL; } num_found = 0; @@ -556,7 +542,7 @@ int cras_alsa_set_hwparams(snd_pcm_t *handle, struct cras_audio_format *format, return 0; } -int cras_alsa_set_swparams(snd_pcm_t *handle) +int cras_alsa_set_swparams(snd_pcm_t *handle, int *enable_htimestamp) { int err; snd_pcm_sw_params_t *swparams; @@ -593,7 +579,50 @@ int cras_alsa_set_swparams(snd_pcm_t *handle) return err; } + if (*enable_htimestamp) { + /* Use MONOTONIC_RAW time-stamps. */ + err = snd_pcm_sw_params_set_tstamp_type( + handle, swparams, SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW); + if (err < 0) { + syslog(LOG_ERR, "set_tstamp_type: %s\n", + snd_strerror(err)); + return err; + } + err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, + SND_PCM_TSTAMP_ENABLE); + if (err < 0) { + syslog(LOG_ERR, "set_tstamp_mode: %s\n", + snd_strerror(err)); + return err; + } + } + + /* This hack is required because ALSA-LIB does not provide any way to + * detect whether MONOTONIC_RAW timestamps are supported by the kernel. + * In ALSA-LIB, the code checks the hardware protocol version. */ err = snd_pcm_sw_params(handle, swparams); + if (err == -EINVAL && *enable_htimestamp) { + *enable_htimestamp = 0; + syslog(LOG_WARNING, + "MONOTONIC_RAW timestamps are not supported."); + + err = snd_pcm_sw_params_set_tstamp_type( + handle, swparams, SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY); + if (err < 0) { + syslog(LOG_ERR, "set_tstamp_type: %s\n", + snd_strerror(err)); + return err; + } + err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, + SND_PCM_TSTAMP_NONE); + if (err < 0) { + syslog(LOG_ERR, "set_tstamp_mode: %s\n", + snd_strerror(err)); + return err; + } + + err = snd_pcm_sw_params(handle, swparams); + } if (err < 0) { syslog(LOG_ERR, "sw_params: %s\n", snd_strerror(err)); diff --git a/cras/src/server/cras_alsa_helpers.h b/cras/src/server/cras_alsa_helpers.h index 01a42aea..38976749 100644 --- a/cras/src/server/cras_alsa_helpers.h +++ b/cras/src/server/cras_alsa_helpers.h @@ -135,10 +135,13 @@ int cras_alsa_set_hwparams(snd_pcm_t *handle, struct cras_audio_format *format, /* Sets up the swparams to alsa. * Args: * handle - The open PCM to configure. + * enable_htimestamp - If non-zero, enable and configure hardware timestamps, + * updated to reflect whether MONOTONIC RAW htimestamps + * are supported by the kernel implementation. * Returns: * 0 on success, negative error on failure. */ -int cras_alsa_set_swparams(snd_pcm_t *handle); +int cras_alsa_set_swparams(snd_pcm_t *handle, int *enable_htimestamp); /* Get the number of used frames in the alsa buffer. * diff --git a/cras/src/server/cras_alsa_io.c b/cras/src/server/cras_alsa_io.c index 275a6810..4aec9d68 100644 --- a/cras/src/server/cras_alsa_io.c +++ b/cras/src/server/cras_alsa_io.c @@ -38,6 +38,7 @@ #include "softvol_curve.h" #include "utlist.h" +#define MAX_ALSA_DEV_NAME_LENGTH 9 /* Alsa names "hw:XX,YY" + 1 for null. */ #define HOTWORD_DEV "Wake on Voice" #define DEFAULT "(default)" #define HDMI "HDMI" @@ -47,8 +48,6 @@ #define HEADPHONE "Headphone" #define MIC "Mic" #define USB "USB" -#define LOOPBACK_CAPTURE "Loopback Capture" -#define LOOPBACK_PLAYBACK "Loopback Playback" /* * For USB, pad the output buffer. This avoids a situation where there isn't a @@ -80,14 +79,12 @@ static const struct timespec no_stream_fill_zeros_duration = { * This extends cras_ionode to include alsa-specific information. * Members: * mixer_output - From cras_alsa_mixer. - * pcm_name - PCM name for snd_pcm_open. * volume_curve - Volume curve for this node. * jack - The jack associated with the node. */ struct alsa_output_node { struct cras_ionode base; struct mixer_control *mixer_output; - const char *pcm_name; struct cras_volume_curve *volume_curve; const struct cras_alsa_jack *jack; }; @@ -95,7 +92,6 @@ struct alsa_output_node { struct alsa_input_node { struct cras_ionode base; struct mixer_control *mixer_input; - const char *pcm_name; const struct cras_alsa_jack *jack; int8_t *channel_layout; }; @@ -103,7 +99,7 @@ struct alsa_input_node { /* * Child of cras_iodev, alsa_io handles ALSA interaction for sound devices. * base - The cras_iodev structure "base class". - * pcm_name - The PCM name passed to snd_pcm_open() (e.g. "hw:0,0"). + * dev - String that names this device (e.g. "hw:0,0"). * dev_name - value from snd_pcm_info_get_name * dev_id - value from snd_pcm_info_get_id * device_index - ALSA index of device, Y in "hw:X:Y". @@ -113,7 +109,10 @@ struct alsa_input_node { * is_first - true if this is the first iodev on the card. * fully_specified - true if this device and it's nodes were fully specified. * That is, don't automatically create nodes for it. + * jack_always_plugged - true if this node is always plugged even without jack. + * enable_htimestamp - True when the device's htimestamp is used. * handle - Handle to the opened ALSA device. + * num_underruns - Number of times we have run out of data (playback only). * num_severe_underruns - Number of times we have run out of data badly. Unlike num_underruns which records for the duration where device is opened, num_severe_underruns records @@ -125,6 +124,8 @@ struct alsa_input_node { * jack_list - List of alsa jack controls for this device. * ucm - CRAS use case manager, if configuration is found. * mmap_offset - offset returned from mmap_begin. + * dsp_name_default - the default dsp name for the device. It can be overridden + * by the jack specific dsp name. * poll_fd - Descriptor used to block until data is ready. * dma_period_set_microsecs - If non-zero, the value to apply to the dma_period. * free_running - true if device is playing zeros in the buffer without @@ -135,11 +136,10 @@ struct alsa_input_node { * severe_underrun_frames - The threshold for severe underrun. * default_volume_curve - Default volume curve that converts from an index * to dBFS. - * has_dependent_dev - true if this iodev has dependent device. */ struct alsa_io { struct cras_iodev base; - char *pcm_name; + char *dev; char *dev_name; char *dev_id; uint32_t device_index; @@ -147,7 +147,10 @@ struct alsa_io { enum CRAS_ALSA_CARD_TYPE card_type; int is_first; int fully_specified; + int jack_always_plugged; + int enable_htimestamp; snd_pcm_t *handle; + unsigned int num_underruns; unsigned int num_severe_underruns; snd_pcm_stream_t alsa_stream; struct cras_alsa_mixer *mixer; @@ -155,6 +158,7 @@ struct alsa_io { struct cras_alsa_jack_list *jack_list; struct cras_use_case_mgr *ucm; snd_pcm_uframes_t mmap_offset; + const char *dsp_name_default; int poll_fd; unsigned int dma_period_set_microsecs; int free_running; @@ -162,7 +166,6 @@ struct alsa_io { snd_pcm_uframes_t severe_underrun_frames; struct cras_volume_curve *default_volume_curve; int hwparams_set; - int has_dependent_dev; }; static void init_device_settings(struct alsa_io *aio); @@ -171,10 +174,6 @@ static int alsa_iodev_set_active_node(struct cras_iodev *iodev, struct cras_ionode *ionode, unsigned dev_enabled); -static int get_fixed_rate(struct alsa_io *aio); - -static int update_supported_formats(struct cras_iodev *iodev); - /* * Defines the default values of nodes. */ @@ -268,21 +267,6 @@ static const struct { .type = CRAS_NODE_TYPE_BLUETOOTH, .position = NODE_POSITION_EXTERNAL, }, - { - .name = "Echo Reference", - .type = CRAS_NODE_TYPE_ECHO_REFERENCE, - .position = NODE_POSITION_INTERNAL, - }, - { - .name = LOOPBACK_CAPTURE, - .type = CRAS_NODE_TYPE_ALSA_LOOPBACK, - .position = NODE_POSITION_INTERNAL, - }, - { - .name = LOOPBACK_PLAYBACK, - .type = CRAS_NODE_TYPE_ALSA_LOOPBACK, - .position = NODE_POSITION_INTERNAL, - }, }; static int set_hwparams(struct cras_iodev *iodev) @@ -329,7 +313,8 @@ static int frames_queued(const struct cras_iodev *iodev, aio->num_severe_underruns++; return rc; } - clock_gettime(CLOCK_MONOTONIC_RAW, tstamp); + if (!aio->enable_htimestamp) + clock_gettime(CLOCK_MONOTONIC_RAW, tstamp); if (iodev->direction == CRAS_STREAM_INPUT) return (int)frames; @@ -371,7 +356,7 @@ static int close_dev(struct cras_iodev *iodev) return 0; } -static int empty_hotword_cb(void *arg, int revents) +static int dummy_hotword_cb(void *arg) { /* Only need this once. */ struct alsa_io *aio = (struct alsa_io *)arg; @@ -390,42 +375,13 @@ static int open_dev(struct cras_iodev *iodev) struct alsa_io *aio = (struct alsa_io *)iodev; snd_pcm_t *handle; int rc; - const char *pcm_name = NULL; - int enable_noise_cancellation; - if (aio->base.direction == CRAS_STREAM_OUTPUT) { - struct alsa_output_node *aout = - (struct alsa_output_node *)aio->base.active_node; - pcm_name = aout->pcm_name; - } else { - struct alsa_input_node *ain = - (struct alsa_input_node *)aio->base.active_node; - pcm_name = ain->pcm_name; - } - - /* For legacy UCM path which doesn't have PlaybackPCM or CapturePCM. */ - if (pcm_name == NULL) - pcm_name = aio->pcm_name; - - rc = cras_alsa_pcm_open(&handle, pcm_name, aio->alsa_stream); + rc = cras_alsa_pcm_open(&handle, aio->dev, aio->alsa_stream); if (rc < 0) return rc; aio->handle = handle; - /* Enable or disable noise cancellation if it supports. */ - if (aio->ucm && iodev->direction == CRAS_STREAM_INPUT && - ucm_node_noise_cancellation_exists(aio->ucm, - iodev->active_node->name)) { - enable_noise_cancellation = - cras_system_get_noise_cancellation_enabled(); - rc = ucm_enable_node_noise_cancellation( - aio->ucm, iodev->active_node->name, - enable_noise_cancellation); - if (rc < 0) - return rc; - } - return 0; } @@ -439,6 +395,7 @@ static int configure_dev(struct cras_iodev *iodev) */ if (iodev->format == NULL) return -EINVAL; + aio->num_underruns = 0; aio->free_running = 0; aio->filled_zeros_for_draining = 0; aio->severe_underrun_frames = @@ -447,7 +404,7 @@ static int configure_dev(struct cras_iodev *iodev) cras_iodev_init_audio_area(iodev, iodev->format->num_channels); syslog(LOG_DEBUG, "Configure alsa device %s rate %zuHz, %zu channels", - aio->pcm_name, iodev->format->frame_rate, + aio->dev, iodev->format->frame_rate, iodev->format->num_channels); rc = set_hwparams(iodev); @@ -460,7 +417,7 @@ static int configure_dev(struct cras_iodev *iodev) return rc; /* Configure software params. */ - rc = cras_alsa_set_swparams(aio->handle); + rc = cras_alsa_set_swparams(aio->handle, &aio->enable_htimestamp); if (rc < 0) return rc; @@ -500,8 +457,8 @@ static int configure_dev(struct cras_iodev *iodev) free(ufds); if (aio->poll_fd >= 0) - audio_thread_add_events_callback( - aio->poll_fd, empty_hotword_cb, aio, POLLIN); + audio_thread_add_callback(aio->poll_fd, + dummy_hotword_cb, aio); } /* Capture starts right away, playback will wait for samples. */ @@ -791,7 +748,8 @@ static void set_alsa_capture_gain(struct cras_iodev *iodev) { const struct alsa_io *aio = (const struct alsa_io *)iodev; struct alsa_input_node *ain; - long min_capture_gain, max_capture_gain, gain; + long gain; + assert(aio); if (aio->mixer == NULL) return; @@ -799,31 +757,20 @@ static void set_alsa_capture_gain(struct cras_iodev *iodev) /* Only set the volume if the dev is active. */ if (!has_handle(aio)) return; - - ain = get_active_input(aio); - - cras_alsa_mixer_set_capture_mute(aio->mixer, - cras_system_get_capture_mute(), - ain ? ain->mixer_input : NULL); - - /* For USB device without UCM config, not change a gain control. */ - if (ain && ain->base.type == CRAS_NODE_TYPE_USB && !aio->ucm) - return; + gain = cras_iodev_adjust_active_node_gain( + iodev, cras_system_get_capture_gain()); /* Set hardware gain to 0dB if software gain is needed. */ if (cras_iodev_software_volume_needed(iodev)) gain = 0; - else { - min_capture_gain = cras_alsa_mixer_get_minimum_capture_gain( - aio->mixer, ain ? ain->mixer_input : NULL); - max_capture_gain = cras_alsa_mixer_get_maximum_capture_gain( - aio->mixer, ain ? ain->mixer_input : NULL); - gain = MAX(iodev->active_node->capture_gain, min_capture_gain); - gain = MIN(gain, max_capture_gain); - } + + ain = get_active_input(aio); cras_alsa_mixer_set_capture_dBFS(aio->mixer, gain, ain ? ain->mixer_input : NULL); + cras_alsa_mixer_set_capture_mute(aio->mixer, + cras_system_get_capture_mute(), + ain ? ain->mixer_input : NULL); } /* @@ -851,6 +798,28 @@ static void init_device_settings(struct alsa_io *aio) set_alsa_volume(&aio->base); set_alsa_mute(&aio->base); } else { + struct mixer_control *mixer_input = NULL; + struct alsa_input_node *ain = get_active_input(aio); + long min_capture_gain, max_capture_gain; + + if (ain) + mixer_input = ain->mixer_input; + + if (cras_iodev_software_volume_needed(&aio->base)) { + min_capture_gain = + cras_iodev_minimum_software_gain(&aio->base); + max_capture_gain = + cras_iodev_maximum_software_gain(&aio->base); + } else { + min_capture_gain = + cras_alsa_mixer_get_minimum_capture_gain( + aio->mixer, mixer_input); + max_capture_gain = + cras_alsa_mixer_get_maximum_capture_gain( + aio->mixer, mixer_input); + } + cras_system_set_capture_gain_limits(min_capture_gain, + max_capture_gain); set_alsa_capture_gain(&aio->base); } } @@ -868,7 +837,6 @@ static void free_alsa_iodev_resources(struct alsa_io *aio) { struct cras_ionode *node; struct alsa_output_node *aout; - struct alsa_input_node *ain; free(aio->base.supported_rates); free(aio->base.supported_channel_counts); @@ -878,10 +846,6 @@ static void free_alsa_iodev_resources(struct alsa_io *aio) if (aio->base.direction == CRAS_STREAM_OUTPUT) { aout = (struct alsa_output_node *)node; cras_volume_curve_destroy(aout->volume_curve); - free((void *)aout->pcm_name); - } else { - ain = (struct alsa_input_node *)node; - free((void *)ain->pcm_name); } cras_iodev_rm_node(&aio->base, node); free(node->softvol_scalers); @@ -889,8 +853,9 @@ static void free_alsa_iodev_resources(struct alsa_io *aio) free(node); } + free((void *)aio->dsp_name_default); cras_iodev_free_resources(&aio->base); - free(aio->pcm_name); + free(aio->dev); if (aio->dev_id) free(aio->dev_id); if (aio->dev_name) @@ -1102,50 +1067,71 @@ set_output_node_software_volume_needed(struct alsa_output_node *output, output->base.name); } -static void set_input_default_node_gain(struct alsa_input_node *input, - struct alsa_io *aio) +static void set_input_node_software_volume_needed(struct alsa_input_node *input, + struct alsa_io *aio) { - long gain; + long min_software_gain; + long max_software_gain; + int rc; - input->base.capture_gain = DEFAULT_CAPTURE_GAIN; - input->base.ui_gain_scaler = 1.0f; + input->base.software_volume_needed = 0; + input->base.min_software_gain = DEFAULT_MIN_CAPTURE_GAIN; + input->base.max_software_gain = 0; + /* Enable software gain only if max software gain is specified in UCM. */ if (!aio->ucm) return; - if (ucm_get_default_node_gain(aio->ucm, input->base.name, &gain) == 0) - input->base.capture_gain = gain; + rc = ucm_get_max_software_gain(aio->ucm, input->base.name, + &max_software_gain); + + /* If max software gain doesn't exist, skip min software gain setting. */ + if (rc) + return; + + input->base.software_volume_needed = 1; + input->base.max_software_gain = max_software_gain; + syslog(LOG_INFO, + "Use software gain for %s with max %ld because it is specified" + " in UCM", + input->base.name, max_software_gain); + + /* Enable min software gain if it is specified in UCM. */ + rc = ucm_get_min_software_gain(aio->ucm, input->base.name, + &min_software_gain); + if (rc) + return; + + if (min_software_gain > max_software_gain) { + syslog(LOG_ERR, + "Ignore MinSoftwareGain %ld because it is larger than " + "MaxSoftwareGain %ld", + min_software_gain, max_software_gain); + return; + } + + syslog(LOG_INFO, + "Use software gain for %s with min %ld because it is specified" + " in UCM", + input->base.name, min_software_gain); + input->base.min_software_gain = min_software_gain; } -static void set_input_node_intrinsic_sensitivity(struct alsa_input_node *input, - struct alsa_io *aio) +static void set_input_default_node_gain(struct alsa_input_node *input, + struct alsa_io *aio) { - long sensitivity; + long default_node_gain; int rc; - input->base.intrinsic_sensitivity = 0; + if (!aio->ucm) + return; - if (aio->ucm) { - rc = ucm_get_intrinsic_sensitivity(aio->ucm, input->base.name, - &sensitivity); - if (rc) - return; - } else if (input->base.type == CRAS_NODE_TYPE_USB) { - /* - * For USB devices without UCM config, trust the default capture gain. - * Set sensitivity to the default dbfs so the capture gain is 0. - */ - sensitivity = DEFAULT_CAPTURE_VOLUME_DBFS; - } else { + rc = ucm_get_default_node_gain(aio->ucm, input->base.name, + &default_node_gain); + if (rc) return; - } - input->base.intrinsic_sensitivity = sensitivity; - input->base.capture_gain = DEFAULT_CAPTURE_VOLUME_DBFS - sensitivity; - syslog(LOG_INFO, - "Use software gain %ld for %s because IntrinsicSensitivity %ld is" - " specified in UCM", - input->base.capture_gain, input->base.name, sensitivity); + input->base.capture_gain = default_node_gain; } static void check_auto_unplug_output_node(struct alsa_io *aio, @@ -1263,6 +1249,7 @@ static struct alsa_input_node *new_input(struct alsa_io *aio, { struct cras_iodev *iodev = &aio->base; struct alsa_input_node *input; + char *mic_positions; int err; input = (struct alsa_input_node *)calloc(1, sizeof(*input)); @@ -1279,10 +1266,22 @@ static struct alsa_input_node *new_input(struct alsa_io *aio, input->mixer_input = cras_input; strncpy(input->base.name, name, sizeof(input->base.name) - 1); set_node_initial_state(&input->base, aio->card_type); + set_input_node_software_volume_needed(input, aio); set_input_default_node_gain(input, aio); - set_input_node_intrinsic_sensitivity(input, aio); if (aio->ucm) { + /* Check mic positions only for internal mic. */ + if ((input->base.type == CRAS_NODE_TYPE_MIC) && + (input->base.position == NODE_POSITION_INTERNAL)) { + mic_positions = ucm_get_mic_positions(aio->ucm); + if (mic_positions) { + strncpy(input->base.mic_positions, + mic_positions, + sizeof(input->base.mic_positions) - 1); + free(mic_positions); + } + } + /* Check if channel map is specified in UCM. */ input->channel_layout = (int8_t *)malloc( CRAS_CH_MAX * sizeof(*input->channel_layout)); @@ -1388,7 +1387,8 @@ static const struct cras_alsa_jack *get_jack_from_node(struct cras_ionode *node) /* * Returns the dsp name specified in the ucm config. If there is a dsp name - * specified for the active node, use that. Otherwise NULL should be returned. + * specified for the active node, use that. Otherwise use the default dsp name + * for the alsa_io device. */ static const char *get_active_dsp_name(struct alsa_io *aio) { @@ -1397,7 +1397,7 @@ static const char *get_active_dsp_name(struct alsa_io *aio) if (node == NULL) return NULL; - return node->dsp_name; + return node->dsp_name ?: aio->dsp_name_default; } /* @@ -1426,73 +1426,6 @@ create_volume_curve_for_jack(const struct cras_card_config *config, } /* - * Updates max_supported_channels value into cras_iodev_info. - * Note that supported_rates, supported_channel_counts, and supported_formats of - * iodev will be updated to the latest values after calling. - */ -static void update_max_supported_channels(struct cras_iodev *iodev) -{ - struct alsa_io *aio = (struct alsa_io *)iodev; - unsigned int max_channels = 0; - size_t i; - bool active_node_predicted = false; - int rc; - - /* - * max_supported_channels might be wrong in dependent PCM cases. Always - * return 2 for such cases. - */ - if (aio->has_dependent_dev) { - max_channels = 2; - goto update_info; - } - - if (aio->handle) { - syslog(LOG_ERR, - "update_max_supported_channels should not be called " - "while device is opened."); - return; - } - - /* - * In the case of updating max_supported_channels on changing jack - * plugging status of devices, the active node may not be determined - * yet. Use the first node as the active node for obtaining the value of - * max_supported_channels. - */ - if (!iodev->active_node) { - if (!iodev->nodes) - goto update_info; - iodev->active_node = iodev->nodes; - syslog(LOG_DEBUG, - "Predict ionode %s as active node temporarily.", - iodev->active_node->name); - active_node_predicted = true; - } - - rc = open_dev(iodev); - if (active_node_predicted) - iodev->active_node = NULL; // Reset the predicted active_node. - if (rc) - goto update_info; - - rc = update_supported_formats(iodev); - if (rc) - goto close_iodev; - - for (i = 0; iodev->supported_channel_counts[i] != 0; i++) { - if (iodev->supported_channel_counts[i] > max_channels) - max_channels = iodev->supported_channel_counts[i]; - } - -close_iodev: - close_dev(iodev); - -update_info: - iodev->info.max_supported_channels = max_channels; -} - -/* * Callback that is called when an output jack is plugged or unplugged. */ static void jack_output_plug_event(const struct cras_alsa_jack *jack, @@ -1555,13 +1488,6 @@ static void jack_output_plug_event(const struct cras_alsa_jack *jack, cras_iodev_set_node_plugged(&node->base, plugged); check_auto_unplug_output_node(aio, &node->base, plugged); - - /* - * For HDMI plug event cases, update max supported channels according - * to the current active node. - */ - if (node->base.type == CRAS_NODE_TYPE_HDMI && plugged) - update_max_supported_channels(&aio->base); } /* @@ -1675,29 +1601,6 @@ static int get_fixed_rate(struct alsa_io *aio) return ucm_get_sample_rate_for_dev(aio->ucm, name, aio->base.direction); } -static size_t get_fixed_channels(struct alsa_io *aio) -{ - const char *name; - int rc; - size_t channels; - - if (aio->base.direction == CRAS_STREAM_OUTPUT) { - struct alsa_output_node *active = get_active_output(aio); - if (!active) - return -ENOENT; - name = active->base.name; - } else { - struct alsa_input_node *active = get_active_input(aio); - if (!active) - return -ENOENT; - name = active->base.name; - } - - rc = ucm_get_channels_for_dev(aio->ucm, name, aio->base.direction, - &channels); - return (rc) ? 0 : channels; -} - /* * Updates the supported sample rates and channel counts. */ @@ -1706,7 +1609,6 @@ static int update_supported_formats(struct cras_iodev *iodev) struct alsa_io *aio = (struct alsa_io *)iodev; int err; int fixed_rate; - size_t fixed_channels; free(iodev->supported_rates); iodev->supported_rates = NULL; @@ -1731,16 +1633,6 @@ static int update_supported_formats(struct cras_iodev *iodev) iodev->supported_rates[0] = fixed_rate; iodev->supported_rates[1] = 0; } - - /* Allow UCM to override supported channel counts. */ - fixed_channels = get_fixed_channels(aio); - if (fixed_channels > 0) { - free(iodev->supported_channel_counts); - iodev->supported_channel_counts = (size_t *)malloc( - 2 * sizeof(iodev->supported_channel_counts[0])); - iodev->supported_channel_counts[0] = fixed_channels; - iodev->supported_channel_counts[1] = 0; - } } return 0; } @@ -1861,8 +1753,8 @@ static int adjust_appl_ptr_samples_remaining(struct cras_iodev *odev) * If underrun happened, handle it. Because alsa_output_underrun function * has already called adjust_appl_ptr, we don't need to call it again. */ - if (real_hw_level <= odev->min_buffer_level) - return cras_iodev_output_underrun(odev, real_hw_level, 0); + if (real_hw_level < odev->min_buffer_level) + return odev->output_underrun(odev); if (real_hw_level > aio->filled_zeros_for_draining) valid_sample = real_hw_level - aio->filled_zeros_for_draining; @@ -1880,8 +1772,12 @@ static int adjust_appl_ptr_samples_remaining(struct cras_iodev *odev) static int alsa_output_underrun(struct cras_iodev *odev) { + struct alsa_io *aio = (struct alsa_io *)odev; int rc; + /* Update number of underruns we got. */ + aio->num_underruns++; + /* Fill whole buffer with zeros. This avoids samples left in buffer causing * noise when device plays them. */ rc = fill_whole_buffer_with_zeros(odev); @@ -1910,8 +1806,8 @@ static int possibly_enter_free_run(struct cras_iodev *odev) real_hw_level = rc; /* If underrun happened, handle it and enter free run state. */ - if (real_hw_level <= odev->min_buffer_level) { - rc = cras_iodev_output_underrun(odev, real_hw_level, 0); + if (real_hw_level < odev->min_buffer_level) { + rc = odev->output_underrun(odev); if (rc < 0) return rc; aio->free_running = 1; @@ -1944,10 +1840,6 @@ static int leave_free_run(struct cras_iodev *odev) struct alsa_io *aio = (struct alsa_io *)odev; int rc; - /* Restart rate estimation because free run internval should not - * be included. */ - cras_iodev_reset_rate_estimator(odev); - if (aio->free_running) rc = adjust_appl_ptr_for_leaving_free_run(odev); else @@ -1984,6 +1876,12 @@ static int is_free_running(const struct cras_iodev *odev) return aio->free_running; } +static unsigned int get_num_underruns(const struct cras_iodev *iodev) +{ + const struct alsa_io *aio = (const struct alsa_io *)iodev; + return aio->num_underruns; +} + static unsigned int get_num_severe_underruns(const struct cras_iodev *iodev) { const struct alsa_io *aio = (const struct alsa_io *)iodev; @@ -2008,7 +1906,8 @@ static void set_default_hotword_model(struct cras_iodev *iodev) return; } -static int get_valid_frames(struct cras_iodev *odev, struct timespec *tstamp) +static int get_valid_frames(const struct cras_iodev *odev, + struct timespec *tstamp) { struct alsa_io *aio = (struct alsa_io *)odev; int rc; @@ -2035,26 +1934,15 @@ static int get_valid_frames(struct cras_iodev *odev, struct timespec *tstamp) return 0; } -static int support_noise_cancellation(const struct cras_iodev *iodev) -{ - struct alsa_io *aio = (struct alsa_io *)iodev; - - if (!aio->ucm || !iodev->active_node) - return 0; - - return ucm_node_noise_cancellation_exists(aio->ucm, - iodev->active_node->name); -} - /* * Exported Interface. */ struct cras_iodev * alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, - const char *pcm_name, const char *dev_name, - const char *dev_id, enum CRAS_ALSA_CARD_TYPE card_type, - int is_first, struct cras_alsa_mixer *mixer, + const char *dev_name, const char *dev_id, + enum CRAS_ALSA_CARD_TYPE card_type, int is_first, + struct cras_alsa_mixer *mixer, const struct cras_card_config *config, struct cras_use_case_mgr *ucm, snd_hctl_t *hctl, enum CRAS_STREAM_DIRECTION direction, size_t usb_vid, @@ -2077,6 +1965,7 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, aio->is_first = is_first; aio->handle = NULL; aio->num_severe_underruns = 0; + aio->jack_always_plugged = 0; if (dev_name) { aio->dev_name = strdup(dev_name); if (!aio->dev_name) @@ -2089,10 +1978,11 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, } aio->free_running = 0; aio->filled_zeros_for_draining = 0; - aio->has_dependent_dev = 0; - aio->pcm_name = strdup(pcm_name); - if (aio->pcm_name == NULL) + aio->dev = (char *)malloc(MAX_ALSA_DEV_NAME_LENGTH); + if (aio->dev == NULL) goto cleanup_iodev; + snprintf(aio->dev, MAX_ALSA_DEV_NAME_LENGTH, "hw:%zu,%zu", card_index, + device_index); if (direction == CRAS_STREAM_INPUT) { aio->alsa_stream = SND_PCM_STREAM_CAPTURE; @@ -2120,10 +2010,10 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, iodev->get_hotword_models = get_hotword_models; iodev->no_stream = no_stream; iodev->is_free_running = is_free_running; + iodev->get_num_underruns = get_num_underruns; iodev->get_num_severe_underruns = get_num_severe_underruns; iodev->get_valid_frames = get_valid_frames; iodev->set_swap_mode_for_node = cras_iodev_dsp_set_swap_mode_for_node; - iodev->support_noise_cancellation = support_noise_cancellation; if (card_type == ALSA_CARD_TYPE_USB) iodev->min_buffer_level = USB_EXTRA_BUFFER_FRAMES; @@ -2131,7 +2021,6 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, iodev->ramp = cras_ramp_create(); if (iodev->ramp == NULL) goto cleanup_iodev; - iodev->initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; aio->mixer = mixer; aio->config = config; @@ -2148,6 +2037,8 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, unsigned int level; int rc; + aio->dsp_name_default = + ucm_get_dsp_name_default(ucm, direction); /* Set callback for swap mode if it is supported * in ucm modifier. */ if (ucm_swap_mode_exists(ucm)) @@ -2157,6 +2048,8 @@ alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, rc = ucm_get_min_buffer_level(ucm, &level); if (!rc && direction == CRAS_STREAM_OUTPUT) iodev->min_buffer_level = level; + + aio->enable_htimestamp = ucm_get_enable_htimestamp_flag(ucm); } set_iodev_name(iodev, card_name, dev_name, card_index, device_index, @@ -2270,9 +2163,6 @@ int alsa_iodev_legacy_complete_init(struct cras_iodev *iodev) set_default_hotword_model(iodev); - /* Record max supported channels into cras_iodev_info. */ - update_max_supported_channels(iodev); - return 0; } @@ -2288,17 +2178,9 @@ int alsa_iodev_ucm_add_nodes_and_jacks(struct cras_iodev *iodev, if (!aio || !section) return -EINVAL; - - /* Allow this section to add as a new node only if the device id - * or dependent device id matches this iodev. */ - if (((uint32_t)section->dev_idx != aio->device_index) && - ((uint32_t)section->dependent_dev_idx != aio->device_index)) + if ((uint32_t)section->dev_idx != aio->device_index) return -EINVAL; - /* Set flag has_dependent_dev for the case of dependent device. */ - if (section->dependent_dev_idx != -1) - aio->has_dependent_dev = 1; - /* This iodev is fully specified. Avoid automatic node creation. */ aio->fully_specified = 1; @@ -2315,14 +2197,15 @@ int alsa_iodev_ucm_add_nodes_and_jacks(struct cras_iodev *iodev, output_node = new_output(aio, control, section->name); if (!output_node) return -ENOMEM; - output_node->pcm_name = strdup(section->pcm_name); } else if (iodev->direction == CRAS_STREAM_INPUT) { input_node = new_input(aio, control, section->name); if (!input_node) return -ENOMEM; - input_node->pcm_name = strdup(section->pcm_name); } + if (section->jack_type && !strcmp(section->jack_type, "always")) + aio->jack_always_plugged = 1; + /* Find any jack controls for this device. */ rc = cras_alsa_jack_list_add_jack_for_section(aio->jack_list, section, &jack); @@ -2347,7 +2230,6 @@ int alsa_iodev_ucm_add_nodes_and_jacks(struct cras_iodev *iodev, void alsa_iodev_ucm_complete_init(struct cras_iodev *iodev) { struct alsa_io *aio = (struct alsa_io *)iodev; - struct cras_ionode *node; if (!iodev) return; @@ -2365,22 +2247,15 @@ void alsa_iodev_ucm_complete_init(struct cras_iodev *iodev) /* * Set plugged for the USB device per card when it appears if - * there is no jack reporting plug status + * there is no jack reporting plug status and the jack is set + * to be always plugged. */ - if (aio->card_type == ALSA_CARD_TYPE_USB) { - DL_FOREACH (iodev->nodes, node) { - if (!get_jack_from_node(node)) - cras_iodev_set_node_plugged(node, 1); - } + if (aio->card_type == ALSA_CARD_TYPE_USB && aio->jack_always_plugged && + !get_jack_from_node(iodev->active_node)) { + cras_iodev_set_node_plugged(iodev->active_node, 1); } set_default_hotword_model(iodev); - - node = iodev->active_node; - - /* Record max supported channels into cras_iodev_info. */ - if (node && node->plugged) - update_max_supported_channels(iodev); } void alsa_iodev_destroy(struct cras_iodev *iodev) @@ -2444,10 +2319,12 @@ static int alsa_iodev_set_active_node(struct cras_iodev *iodev, unsigned dev_enabled) { struct alsa_io *aio = (struct alsa_io *)iodev; - int rc = 0; - if (iodev->active_node == ionode) - goto skip; + if (iodev->active_node == ionode) { + enable_active_ucm(aio, dev_enabled); + init_device_settings(aio); + return 0; + } /* Disable jack ucm before switching node. */ enable_active_ucm(aio, 0); @@ -2457,16 +2334,7 @@ static int alsa_iodev_set_active_node(struct cras_iodev *iodev, cras_iodev_set_active_node(iodev, ionode); aio->base.dsp_name = get_active_dsp_name(aio); cras_iodev_update_dsp(iodev); -skip: enable_active_ucm(aio, dev_enabled); - if (ionode->type == CRAS_NODE_TYPE_HOTWORD) { - if (dev_enabled) { - rc = ucm_enable_hotword_model(aio->ucm); - if (rc < 0) - return rc; - } else - ucm_disable_all_hotword_models(aio->ucm); - } /* Setting the volume will also unmute if the system isn't muted. */ init_device_settings(aio); return 0; diff --git a/cras/src/server/cras_alsa_io.h b/cras/src/server/cras_alsa_io.h index f8e613d0..9bc0c1f9 100644 --- a/cras/src/server/cras_alsa_io.h +++ b/cras/src/server/cras_alsa_io.h @@ -21,7 +21,6 @@ struct ucm_section; * card_index - 0 based index, value of "XX" in "hw:XX,YY". * card_name - The name of the card. * device_index - 0 based index, value of "YY" in "hw:XX,YY". - * pcm_name - The pcm name passing to snd_pcm_open(), e.g hw:0,0 * dev_name - The name of the device. * dev_id - The id string of the device. * card_type - the type of the card this iodev belongs. @@ -39,9 +38,9 @@ struct ucm_section; */ struct cras_iodev * alsa_iodev_create(size_t card_index, const char *card_name, size_t device_index, - const char *pcm_name, const char *dev_name, - const char *dev_id, enum CRAS_ALSA_CARD_TYPE card_type, - int is_first, struct cras_alsa_mixer *mixer, + const char *dev_name, const char *dev_id, + enum CRAS_ALSA_CARD_TYPE card_type, int is_first, + struct cras_alsa_mixer *mixer, const struct cras_card_config *config, struct cras_use_case_mgr *ucm, snd_hctl_t *hctl, enum CRAS_STREAM_DIRECTION direction, size_t usb_vid, diff --git a/cras/src/server/cras_alsa_jack.c b/cras/src/server/cras_alsa_jack.c index 6d4d7bf5..a16e94e4 100644 --- a/cras/src/server/cras_alsa_jack.c +++ b/cras/src/server/cras_alsa_jack.c @@ -380,7 +380,7 @@ static void display_info_delay_cb(struct cras_timer *timer, void *arg) * file has data to read. Perform autoswitching to / from the * associated device when data is available. */ -static void gpio_switch_callback(void *arg, int events) +static void gpio_switch_callback(void *arg) { struct cras_alsa_jack *jack = arg; int i; @@ -408,30 +408,38 @@ static void gpio_switch_callback(void *arg, int events) static unsigned int gpio_jack_match_device(const struct cras_alsa_jack *jack, struct cras_alsa_jack_list *jack_list, + const char *card_name, enum CRAS_STREAM_DIRECTION direction) { - int target_dev_idx; + const char *target_device_name = NULL; + char current_device_name[CRAS_IODEV_NAME_BUFFER_SIZE]; + unsigned int rc; /* If the device name is not specified in UCM, assume it should be * associated with device 0. */ if (!jack_list->ucm || !jack->ucm_device) return jack_list->is_first_device; - /* If jack has valid ucm_device, that means this jack has already been - * associated to this card. Next step to match device index on this - * card. */ - target_dev_idx = ucm_get_alsa_dev_idx_for_dev( + /* Look for device name specified in a device section of UCM. */ + target_device_name = ucm_get_device_name_for_dev( jack_list->ucm, jack->ucm_device, direction); - if (target_dev_idx < 0) + if (!target_device_name) return jack_list->is_first_device; syslog(LOG_DEBUG, - "Matching GPIO jack, target device idx: %d, " + "Matching GPIO jack, target device name: %s, " "current card name: %s, device index: %zu\n", - target_dev_idx, jack_list->card_name, jack_list->device_index); + target_device_name, card_name, jack_list->device_index); - return (target_dev_idx == jack_list->device_index); + /* Device name of format "hw:<card_name>,<device_index>", should fit + * in the string of size CRAS_IODEV_NAME_BUFFER_SIZE.*/ + snprintf(current_device_name, sizeof(current_device_name), "hw:%s,%zu", + card_name, jack_list->device_index); + + rc = !strcmp(current_device_name, target_device_name); + free((void *)target_device_name); + return rc; } static int create_jack_for_gpio(struct cras_alsa_jack_list *jack_list, @@ -503,8 +511,8 @@ static int cras_complete_gpio_jack(struct gpio_switch_list_data *data, cras_free_jack(jack, 0); return -EIO; } - r = cras_system_add_select_fd(jack->gpio.fd, gpio_switch_callback, jack, - POLLIN); + r = cras_system_add_select_fd(jack->gpio.fd, gpio_switch_callback, + jack); if (r < 0) { /* Not yet registered with system select. */ cras_free_jack(jack, 0); @@ -532,6 +540,7 @@ static int open_and_monitor_gpio(struct gpio_switch_list_data *data, { struct cras_alsa_jack *jack; struct cras_alsa_jack_list *jack_list = data->jack_list; + const char *card_name = jack_list->card_name; enum CRAS_STREAM_DIRECTION direction = jack_list->direction; int r; @@ -544,7 +553,7 @@ static int open_and_monitor_gpio(struct gpio_switch_list_data *data, jack->ucm_device = ucm_get_dev_for_jack( jack_list->ucm, jack->gpio.device_name, direction); - if (!gpio_jack_match_device(jack, jack_list, direction)) { + if (!gpio_jack_match_device(jack, jack_list, card_name, direction)) { cras_free_jack(jack, 0); return -EIO; } @@ -719,31 +728,6 @@ static int gpio_switch_list_by_matching(const char *dev_path, return data->rc; } -/* Find ELD control for HDMI/DP gpio jack. */ -static snd_hctl_elem_t *find_eld_control_by_dev_index(snd_hctl_t *hctl, - unsigned int dev_idx) -{ - static const char eld_control_name[] = "ELD"; - snd_ctl_elem_id_t *elem_id; - - snd_ctl_elem_id_alloca(&elem_id); - snd_ctl_elem_id_clear(elem_id); - snd_ctl_elem_id_set_interface(elem_id, SND_CTL_ELEM_IFACE_PCM); - snd_ctl_elem_id_set_device(elem_id, dev_idx); - snd_ctl_elem_id_set_name(elem_id, eld_control_name); - return snd_hctl_find_elem(hctl, elem_id); -} - -/* For non-gpio jack, check if it's of type hdmi/dp by - * matching jack name. */ -static int is_jack_hdmi_dp(const char *jack_name) -{ - // TODO(hychao): Use the information provided in UCM instead of - // name matching. - static const char *hdmi_dp = "HDMI"; - return !!strstr(jack_name, hdmi_dp); -} - /* Find GPIO jacks for this jack_list. * Args: * jack_list - Jack list to add to. @@ -779,17 +763,8 @@ static int find_gpio_jacks(struct cras_alsa_jack_list *jack_list, gpio_switch_list_for_each(gpio_switch_list_with_section, &data); else gpio_switch_list_for_each(gpio_switch_list_by_matching, &data); - if (result_jack) { + if (result_jack) *result_jack = data.result_jack; - - /* Find ELD control only for HDMI/DP gpio jack. */ - if (*result_jack && - is_jack_hdmi_dp((*result_jack)->gpio.device_name)) - (*result_jack)->eld_control = - find_eld_control_by_dev_index( - jack_list->hctl, - jack_list->device_index); - } return data.rc; } @@ -844,6 +819,14 @@ static unsigned int hctl_jack_device_index(const char *name) return (unsigned int)device_index; } +/* For non-gpio jack, check if it's of type hdmi/dp by + * matching jack name. */ +static int is_jack_hdmi_dp(const char *jack_name) +{ + static const char *hdmi_dp = "HDMI/DP"; + return strncmp(jack_name, hdmi_dp, strlen(hdmi_dp)) == 0; +} + /* Checks if the given control name is in the supplied list of possible jack * control base names. */ static int is_jack_control_in_list(const char *const *list, @@ -884,6 +867,7 @@ static int find_jack_controls(struct cras_alsa_jack_list *jack_list) static const char *const input_jack_base_names[] = { "Mic Jack", }; + static const char eld_control_name[] = "ELD"; const char *const *jack_names; unsigned int num_jack_names; @@ -957,9 +941,17 @@ static int find_jack_controls(struct cras_alsa_jack_list *jack_list) name = snd_hctl_elem_get_name(jack->elem); if (!is_jack_hdmi_dp(name)) continue; - - jack->eld_control = find_eld_control_by_dev_index( - jack_list->hctl, jack_list->device_index); + for (elem = snd_hctl_first_elem(jack_list->hctl); elem != NULL; + elem = snd_hctl_elem_next(elem)) { + if (strcmp(snd_hctl_elem_get_name(elem), + eld_control_name)) + continue; + if (snd_hctl_elem_get_device(elem) != + jack_list->device_index) + continue; + jack->eld_control = elem; + break; + } } return 0; @@ -985,6 +977,7 @@ static int find_hctl_jack_for_section(struct cras_alsa_jack_list *jack_list, struct ucm_section *section, struct cras_alsa_jack **result_jack) { + static const char eld_control_name[] = "ELD"; snd_hctl_elem_t *elem; snd_ctl_elem_id_t *elem_id; struct cras_alsa_jack *jack; @@ -1035,8 +1028,10 @@ static int find_hctl_jack_for_section(struct cras_alsa_jack_list *jack_list, return 0; /* Look up ELD control. */ - jack->eld_control = find_eld_control_by_dev_index( - jack_list->hctl, jack_list->device_index); + snd_ctl_elem_id_set_name(elem_id, eld_control_name); + elem = snd_hctl_find_elem(jack_list->hctl, elem_id); + if (elem) + jack->eld_control = elem; return 0; } diff --git a/cras/src/server/cras_alsa_mixer.c b/cras/src/server/cras_alsa_mixer.c index 3379d959..99f4d61f 100644 --- a/cras/src/server/cras_alsa_mixer.c +++ b/cras/src/server/cras_alsa_mixer.c @@ -417,7 +417,7 @@ static int mixer_control_set_mute(const struct mixer_control *control, int muted) { const struct mixer_control_element *elem = NULL; - int rc = -EINVAL; + int rc; if (!control) return -EINVAL; DL_FOREACH (control->elements, elem) { @@ -943,7 +943,7 @@ void cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer *cras_mixer, long dBFS, assert(cras_mixer); /* dBFS is normally < 0 to specify the attenuation from max. max is the - * combined max of the main controls and the current output. + * combined max of the master controls and the current output. */ to_set = dBFS + cras_mixer->max_volume_dB; if (cras_alsa_mixer_has_volume(mixer_output)) @@ -959,9 +959,9 @@ void cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer *cras_mixer, long dBFS, if (!c->has_volume) continue; - if (mixer_control_set_dBFS(c, to_set) == 0 && - mixer_control_get_dBFS(c, &actual_dB) == 0) - to_set -= actual_dB; + mixer_control_set_dBFS(c, to_set); + mixer_control_get_dBFS(c, &actual_dB); + to_set -= actual_dB; } /* Apply the rest to the output-specific control. */ if (cras_alsa_mixer_has_volume(mixer_output)) @@ -1002,9 +1002,9 @@ void cras_alsa_mixer_set_capture_dBFS(struct cras_alsa_mixer *cras_mixer, if (!c->has_volume) continue; - if (mixer_control_set_dBFS(c, to_set) == 0 && - mixer_control_get_dBFS(c, &actual_dB) == 0) - to_set -= actual_dB; + mixer_control_set_dBFS(c, to_set); + mixer_control_get_dBFS(c, &actual_dB); + to_set -= actual_dB; } /* Apply the reset to input specific control */ diff --git a/cras/src/server/cras_alsa_mixer.h b/cras/src/server/cras_alsa_mixer.h index 878fbe54..6b306035 100644 --- a/cras/src/server/cras_alsa_mixer.h +++ b/cras/src/server/cras_alsa_mixer.h @@ -6,6 +6,9 @@ #ifndef _CRAS_ALSA_MIXER_H #define _CRAS_ALSA_MIXER_H +#include <alsa/asoundlib.h> +#include <iniparser.h> + #include "cras_types.h" /* cras_alsa_mixer represents the alsa mixer interface for an alsa card. It @@ -147,7 +150,7 @@ void cras_alsa_mixer_set_mute(struct cras_alsa_mixer *cras_mixer, int muted, * Args: * cras_mixer - Mixer to set the volume in. * muted - 1 if muted, 0 if not. - * mixer_input - The mixer input to mute if no card mute. + * mixer_input - The mixer input to mute if no master mute. */ void cras_alsa_mixer_set_capture_mute(struct cras_alsa_mixer *cras_mixer, int muted, diff --git a/cras/src/server/cras_alsa_plugin_io.c b/cras/src/server/cras_alsa_plugin_io.c deleted file mode 100644 index 32c1ae11..00000000 --- a/cras/src/server/cras_alsa_plugin_io.c +++ /dev/null @@ -1,265 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <alsa/asoundlib.h> -#include <alsa/use-case.h> -#include <stdio.h> -#include <sys/select.h> -#include <syslog.h> - -#include "cras_alsa_io.h" -#include "cras_alsa_jack.h" -#include "cras_alsa_mixer.h" -#include "cras_alsa_ucm.h" -#include "cras_iodev.h" -#include "cras_system_state.h" -#include "iniparser_wrapper.h" -#include "utlist.h" - -#define PLUGINS_INI "plugins.ini" -#define PLUGIN_KEY_CTL "ctl" -#define PLUGIN_KEY_DIR "dir" -#define PLUGIN_KEY_PCM "pcm" -#define PLUGIN_KEY_CARD "card" - -#define NULL_USB_VID 0x00 -#define NULL_USB_PID 0x00 -#define NULL_USB_SERIAL_NUMBER "serial-number-not-used" - -struct hctl_poll_fd { - int fd; - struct hctl_poll_fd *prev, *next; -}; - -struct alsa_plugin { - snd_hctl_t *hctl; - struct cras_alsa_mixer *mixer; - struct hctl_poll_fd *hctl_poll_fds; - struct cras_use_case_mgr *ucm; - struct cras_iodev *iodev; - struct alsa_plugin *next, *prev; -}; - -static struct alsa_plugin *plugins; - -static char ini_name[MAX_INI_NAME_LENGTH + 1]; -static char key_name[MAX_INI_NAME_LENGTH + 1]; -static dictionary *plugins_ini = NULL; - -static void hctl_event_pending(void *arg, int revents) -{ - struct alsa_plugin *plugin; - - plugin = (struct alsa_plugin *)arg; - if (plugin->hctl == NULL) - return; - - /* handle_events will trigger the callback registered with each control - * that has changed. */ - snd_hctl_handle_events(plugin->hctl); -} - -/* hctl poll descritpor */ -static void collect_poll_descriptors(struct alsa_plugin *plugin) -{ - struct hctl_poll_fd *registered_fd; - struct pollfd *pollfds; - int i, n, rc; - - n = snd_hctl_poll_descriptors_count(plugin->hctl); - if (n == 0) { - syslog(LOG_DEBUG, "No hctl descritpor to poll"); - return; - } - - pollfds = malloc(n * sizeof(*pollfds)); - if (pollfds == NULL) - return; - - n = snd_hctl_poll_descriptors(plugin->hctl, pollfds, n); - for (i = 0; i < n; i++) { - registered_fd = calloc(1, sizeof(*registered_fd)); - if (registered_fd == NULL) { - free(pollfds); - return; - } - registered_fd->fd = pollfds[i].fd; - DL_APPEND(plugin->hctl_poll_fds, registered_fd); - rc = cras_system_add_select_fd( - registered_fd->fd, hctl_event_pending, plugin, POLLIN); - if (rc < 0) { - DL_DELETE(plugin->hctl_poll_fds, registered_fd); - free(pollfds); - return; - } - } - free(pollfds); -} - -static void cleanup_poll_descriptors(struct alsa_plugin *plugin) -{ - struct hctl_poll_fd *poll_fd; - DL_FOREACH (plugin->hctl_poll_fds, poll_fd) { - cras_system_rm_select_fd(poll_fd->fd); - DL_DELETE(plugin->hctl_poll_fds, poll_fd); - free(poll_fd); - } -} - -static void destroy_plugin(struct alsa_plugin *plugin); - -void alsa_plugin_io_create(enum CRAS_STREAM_DIRECTION direction, - const char *pcm_name, const char *ctl_name, - const char *card_name) -{ - struct alsa_plugin *plugin; - struct ucm_section *section; - struct ucm_section *ucm_sections; - int rc; - - plugin = (struct alsa_plugin *)calloc(1, sizeof(*plugin)); - if (!plugin) { - syslog(LOG_ERR, "No memory to create alsa plugin"); - return; - } - - rc = snd_hctl_open(&plugin->hctl, ctl_name, SND_CTL_NONBLOCK); - if (rc < 0) { - syslog(LOG_ERR, "open hctl fail for plugin %s", ctl_name); - goto cleanup; - } - - rc = snd_hctl_nonblock(plugin->hctl, 1); - if (rc < 0) { - syslog(LOG_ERR, "Failed to nonblock hctl for %s", ctl_name); - goto cleanup; - } - rc = snd_hctl_load(plugin->hctl); - if (rc < 0) { - syslog(LOG_ERR, "Failed to load hctl for %s", ctl_name); - goto cleanup; - } - collect_poll_descriptors(plugin); - - plugin->mixer = cras_alsa_mixer_create(ctl_name); - - plugin->ucm = ucm_create(card_name); - - DL_APPEND(plugins, plugin); - - ucm_sections = ucm_get_sections(plugin->ucm); - DL_FOREACH (ucm_sections, section) { - rc = cras_alsa_mixer_add_controls_in_section(plugin->mixer, - section); - if (rc) - syslog(LOG_ERR, - "Failed adding control to plugin," - "section %s mixer_name %s", - section->name, section->mixer_name); - } - plugin->iodev = alsa_iodev_create(0, card_name, 0, pcm_name, "", "", - ALSA_CARD_TYPE_USB, 1, /* is first */ - plugin->mixer, NULL, plugin->ucm, - plugin->hctl, direction, NULL_USB_VID, - NULL_USB_PID, NULL_USB_SERIAL_NUMBER); - - DL_FOREACH (ucm_sections, section) { - if (section->dir != plugin->iodev->direction) - continue; - section->dev_idx = 0; - alsa_iodev_ucm_add_nodes_and_jacks(plugin->iodev, section); - } - - alsa_iodev_ucm_complete_init(plugin->iodev); - - return; -cleanup: - if (plugin) - destroy_plugin(plugin); -} - -static void destroy_plugin(struct alsa_plugin *plugin) -{ - cleanup_poll_descriptors(plugin); - if (plugin->hctl) - snd_hctl_close(plugin->hctl); - if (plugin->iodev) - alsa_iodev_destroy(plugin->iodev); - if (plugin->mixer) - cras_alsa_mixer_destroy(plugin->mixer); - - free(plugin); -} - -void alsa_pluigin_io_destroy_all() -{ - struct alsa_plugin *plugin; - - DL_FOREACH (plugins, plugin) - destroy_plugin(plugin); -} - -void cras_alsa_plugin_io_init(const char *device_config_dir) -{ - int nsec, i; - enum CRAS_STREAM_DIRECTION direction; - const char *sec_name; - const char *tmp, *pcm_name, *ctl_name, *card_name; - - snprintf(ini_name, MAX_INI_NAME_LENGTH, "%s/%s", device_config_dir, - PLUGINS_INI); - ini_name[MAX_INI_NAME_LENGTH] = '\0'; - - plugins_ini = iniparser_load_wrapper(ini_name); - if (!plugins_ini) - return; - - nsec = iniparser_getnsec(plugins_ini); - for (i = 0; i < nsec; i++) { - sec_name = iniparser_getsecname(plugins_ini, i); - - /* Parse dir=output or dir=input */ - snprintf(key_name, MAX_INI_NAME_LENGTH, "%s:%s", sec_name, - PLUGIN_KEY_DIR); - tmp = iniparser_getstring(plugins_ini, key_name, NULL); - if (strcmp(tmp, "output") == 0) - direction = CRAS_STREAM_OUTPUT; - else if (strcmp(tmp, "input") == 0) - direction = CRAS_STREAM_INPUT; - else - continue; - - /* pcm=<plugin-pcm-name> this name will be used with - * snd_pcm_open. */ - snprintf(key_name, MAX_INI_NAME_LENGTH, "%s:%s", sec_name, - PLUGIN_KEY_PCM); - pcm_name = iniparser_getstring(plugins_ini, key_name, NULL); - if (!pcm_name) - continue; - - /* ctl=<plugin-ctl-name> this name will be used with - * snd_hctl_open. */ - snprintf(key_name, MAX_INI_NAME_LENGTH, "%s:%s", sec_name, - PLUGIN_KEY_CTL); - ctl_name = iniparser_getstring(plugins_ini, key_name, NULL); - if (!ctl_name) - continue; - - /* card=<card-name> this name will be used with - * snd_use_case_mgr_open. */ - snprintf(key_name, MAX_INI_NAME_LENGTH, "%s:%s", sec_name, - PLUGIN_KEY_CARD); - card_name = iniparser_getstring(plugins_ini, key_name, NULL); - if (!card_name) - continue; - - syslog(LOG_DEBUG, - "Creating plugin for direction %s, pcm %s, ctl %s, card %s", - direction == CRAS_STREAM_OUTPUT ? "output" : "input", - pcm_name, ctl_name, card_name); - - alsa_plugin_io_create(direction, pcm_name, ctl_name, card_name); - } -} diff --git a/cras/src/server/cras_alsa_plugin_io.h b/cras/src/server/cras_alsa_plugin_io.h deleted file mode 100644 index 995f463e..00000000 --- a/cras/src/server/cras_alsa_plugin_io.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CRAS_ALSA_PLUGIN_IO_H_ -#define CRAS_ALSA_PLUGIN_IO_H_ - -/* - * Disclaimer: - * The ALSA plugin path in CRAS is intended to be used for development or - * testing. CrOS audio team is not responsible for nor provides hot-fix to - * any breakage if it’s used in production code. - */ - -void alsa_pluigin_io_destroy_all(); - -void cras_alsa_plugin_io_init(const char *device_config_dir); - -#endif /* CRAS_ALSA_PLUGIN_IO_H_ */ diff --git a/cras/src/server/cras_alsa_ucm.c b/cras/src/server/cras_alsa_ucm.c index 3e46f6a9..12ee81e6 100644 --- a/cras/src/server/cras_alsa_ucm.c +++ b/cras/src/server/cras_alsa_ucm.c @@ -13,53 +13,49 @@ #include "cras_util.h" #include "utlist.h" -static const char jack_control_var[] = "JackControl"; -static const char jack_dev_var[] = "JackDev"; +static const char jack_var[] = "JackName"; +static const char jack_type_var[] = "JackType"; static const char jack_switch_var[] = "JackSwitch"; static const char edid_var[] = "EDIDFile"; static const char cap_var[] = "CaptureControl"; +static const char mic_positions[] = "MicPositions"; static const char override_type_name_var[] = "OverrideNodeType"; +static const char output_dsp_name_var[] = "OutputDspName"; +static const char input_dsp_name_var[] = "InputDspName"; static const char dsp_name_var[] = "DspName"; -static const char playback_mixer_elem_var[] = "PlaybackMixerElem"; -static const char capture_mixer_elem_var[] = "CaptureMixerElem"; +static const char mixer_var[] = "MixerName"; +static const char swap_mode_suffix[] = "Swap Mode"; static const char min_buffer_level_var[] = "MinBufferLevel"; static const char dma_period_var[] = "DmaPeriodMicrosecs"; static const char disable_software_volume[] = "DisableSoftwareVolume"; static const char playback_device_name_var[] = "PlaybackPCM"; static const char playback_device_rate_var[] = "PlaybackRate"; -static const char playback_channels_var[] = "PlaybackChannels"; static const char capture_device_name_var[] = "CapturePCM"; static const char capture_device_rate_var[] = "CaptureRate"; static const char capture_channel_map_var[] = "CaptureChannelMap"; -static const char capture_channels_var[] = "CaptureChannels"; static const char coupled_mixers[] = "CoupledMixers"; -static const char dependent_device_name_var[] = "DependentPCM"; static const char preempt_hotword_var[] = "PreemptHotword"; static const char echo_reference_dev_name_var[] = "EchoReferenceDev"; - -/* SectionModifier prefixes and suffixes. */ -static const char hotword_model_prefix[] = "Hotword Model"; -static const char swap_mode_suffix[] = "Swap Mode"; -static const char noise_cancellation_suffix[] = "Noise Cancellation"; - /* - * Set this value in a SectionDevice to specify the intrinsic sensitivity in - * 0.01 dBFS/Pa. It currently only supports input devices. You should get the - * value by recording samples without either hardware or software gain. We are - * still working on building a standard process for measuring it. The value you - * see now in our UCM is just estimated value. If it is set, CRAS will enable - * software gain and use the value as a reference for calculating the - * appropriate software gain to apply to the device to meet our target volume. + * Set this value in a SectionDevice to specify the minimum software gain in + * 0.01 dB and enable software gain on this node. It must be used with + * MaxSoftwareGain. If not, the value will be ignored. */ -static const char intrinsic_sensitivity_var[] = "IntrinsicSensitivity"; - +static const char min_software_gain[] = "MinSoftwareGain"; +/* + * Set this value in a SectionDevice to specify the maximum software gain in + * 0.01 dB and enable software gain on this node. + */ +static const char max_software_gain[] = "MaxSoftwareGain"; /* * Set this value in a SectionDevice to specify the default node gain in * 0.01 dB. */ static const char default_node_gain[] = "DefaultNodeGain"; +static const char hotword_model_prefix[] = "Hotword Model"; static const char fully_specified_ucm_var[] = "FullySpecifiedUCM"; static const char main_volume_names[] = "MainVolumeNames"; +static const char enable_htimestamp_var[] = "EnableHtimestamp"; /* Use case verbs corresponding to CRAS_STREAM_TYPE. */ static const char *use_case_verbs[] = { @@ -67,8 +63,6 @@ static const char *use_case_verbs[] = { "Speech", "Pro Audio", "Accessibility", }; -static const size_t max_section_name_len = 100; - /* Represents a list of section names found in UCM. */ struct section_name { const char *name; @@ -77,10 +71,9 @@ struct section_name { struct cras_use_case_mgr { snd_use_case_mgr_t *mgr; - char *name; + const char *name; unsigned int avail_use_cases; enum CRAS_STREAM_TYPE use_case; - char *hotword_modifier; }; static inline const char *uc_verb(struct cras_use_case_mgr *mgr) @@ -315,42 +308,32 @@ ucm_get_devices_for_var(struct cras_use_case_mgr *mgr, const char *var, return section_names; } -static const char *ucm_get_value_for_dev(struct cras_use_case_mgr *mgr, - const char *value_var, const char *dev) +static const char * +ucm_get_playback_device_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev) { const char *name = NULL; int rc; - rc = get_var(mgr, value_var, dev, uc_verb(mgr), &name); + rc = get_var(mgr, playback_device_name_var, dev, uc_verb(mgr), &name); if (rc) return NULL; return name; } -static inline const char * -ucm_get_playback_device_name_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) -{ - return ucm_get_value_for_dev(mgr, playback_device_name_var, dev); -} - -static inline const char * +static const char * ucm_get_capture_device_name_for_dev(struct cras_use_case_mgr *mgr, const char *dev) { - return ucm_get_value_for_dev(mgr, capture_device_name_var, dev); -} + const char *name = NULL; + int rc; -/* Gets the value of DependentPCM property. This is used to structure two - * SectionDevices under one cras iodev to avoid two PCMs be open at the - * same time because of restriction in lower layer driver or hardware. - */ -static inline const char * -ucm_get_dependent_device_name_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) -{ - return ucm_get_value_for_dev(mgr, dependent_device_name_var, dev); + rc = get_var(mgr, capture_device_name_var, dev, uc_verb(mgr), &name); + if (rc) + return NULL; + + return name; } /* Get a list of mixer names specified in a UCM variable separated by ",". @@ -382,21 +365,6 @@ static struct mixer_name *ucm_get_mixer_names(struct cras_use_case_mgr *mgr, return names; } -/* Gets the modifier name of Noise Cancellation for the given node_name. */ -static void ucm_get_node_noise_cancellation_name(const char *node_name, - char *mod_name) -{ - size_t len = - strlen(node_name) + 1 + strlen(noise_cancellation_suffix) + 1; - if (len > max_section_name_len) { - syslog(LOG_ERR, - "Length of the given section name is %zu > %zu(max)", - len, max_section_name_len); - len = max_section_name_len; - } - snprintf(mod_name, len, "%s %s", node_name, noise_cancellation_suffix); -} - /* Exported Interface */ struct cras_use_case_mgr *ucm_create(const char *name) @@ -415,10 +383,6 @@ struct cras_use_case_mgr *ucm_create(const char *name) if (!mgr) return NULL; - mgr->name = strdup(name); - if (!mgr->name) - goto cleanup; - rc = snd_use_case_mgr_open(&mgr->mgr, name); if (rc) { syslog(LOG_WARNING, "Can not open ucm for card %s, rc = %d", @@ -426,8 +390,8 @@ struct cras_use_case_mgr *ucm_create(const char *name) goto cleanup; } + mgr->name = name; mgr->avail_use_cases = 0; - mgr->hotword_modifier = NULL; num_verbs = snd_use_case_get_list(mgr->mgr, "_verbs", &list); for (i = 0; i < num_verbs; i += 2) { for (j = 0; j < CRAS_STREAM_NUM_TYPES; ++j) { @@ -449,7 +413,6 @@ struct cras_use_case_mgr *ucm_create(const char *name) cleanup_mgr: snd_use_case_mgr_close(mgr->mgr); cleanup: - free(mgr->name); free(mgr); return NULL; } @@ -457,8 +420,6 @@ cleanup: void ucm_destroy(struct cras_use_case_mgr *mgr) { snd_use_case_mgr_close(mgr->mgr); - free(mgr->hotword_modifier); - free(mgr->name); free(mgr); } @@ -515,63 +476,12 @@ int ucm_enable_swap_mode(struct cras_use_case_mgr *mgr, const char *node_name, return rc; } -int ucm_node_noise_cancellation_exists(struct cras_use_case_mgr *mgr, - const char *node_name) -{ - char *node_modifier_name = NULL; - int exists; - - node_modifier_name = (char *)malloc(max_section_name_len); - if (!node_modifier_name) - return 0; - ucm_get_node_noise_cancellation_name(node_name, node_modifier_name); - exists = ucm_mod_exists_with_name(mgr, node_modifier_name); - free((void *)node_modifier_name); - return exists; -} - -int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr *mgr, - const char *node_name, int enable) -{ - char *node_modifier_name = NULL; - int rc; - - node_modifier_name = (char *)malloc(max_section_name_len); - if (!node_modifier_name) - return -ENOMEM; - ucm_get_node_noise_cancellation_name(node_name, node_modifier_name); - if (!ucm_mod_exists_with_name(mgr, node_modifier_name)) { - syslog(LOG_ERR, "Can not find modifier %s.", - node_modifier_name); - free((void *)node_modifier_name); - return -EPERM; - } - if (modifier_enabled(mgr, node_modifier_name) == !!enable) { - syslog(LOG_DEBUG, "Modifier %s is already %s.", - node_modifier_name, enable ? "enabled" : "disabled"); - free((void *)node_modifier_name); - return 0; - } - - syslog(LOG_DEBUG, "UCM %s Modifier %s", enable ? "enable" : "disable", - node_modifier_name); - rc = ucm_set_modifier_enabled(mgr, node_modifier_name, enable); - free((void *)node_modifier_name); - return rc; -} - int ucm_set_enabled(struct cras_use_case_mgr *mgr, const char *dev, int enable) { - int rc; if (device_enabled(mgr, dev) == !!enable) return 0; syslog(LOG_DEBUG, "UCM %s %s", enable ? "enable" : "disable", dev); - rc = snd_use_case_set(mgr->mgr, enable ? "_enadev" : "_disdev", dev); - if (rc && (rc != -ENOENT || ucm_has_fully_specified_ucm_flag(mgr))) { - syslog(LOG_ERR, "Can not %s UCM for device %s, rc = %d", - enable ? "enable" : "disable", dev, rc); - } - return rc; + return snd_use_case_set(mgr->mgr, enable ? "_enadev" : "_disdev", dev); } char *ucm_get_flag(struct cras_use_case_mgr *mgr, const char *flag_name) @@ -605,10 +515,33 @@ char *ucm_get_cap_control(struct cras_use_case_mgr *mgr, const char *ucm_dev) return control_name; } -inline const char *ucm_get_override_type_name(struct cras_use_case_mgr *mgr, - const char *dev) +char *ucm_get_mic_positions(struct cras_use_case_mgr *mgr) { - return ucm_get_value_for_dev(mgr, override_type_name_var, dev); + char *control_name = NULL; + const char *value; + int rc; + + rc = get_var(mgr, mic_positions, "", uc_verb(mgr), &value); + if (!rc) { + control_name = strdup(value); + free((void *)value); + } + + return control_name; +} + +const char *ucm_get_override_type_name(struct cras_use_case_mgr *mgr, + const char *dev) +{ + const char *override_type_name; + int rc; + + rc = get_var(mgr, override_type_name_var, dev, uc_verb(mgr), + &override_type_name); + if (rc) + return NULL; + + return override_type_name; } char *ucm_get_dev_for_jack(struct cras_use_case_mgr *mgr, const char *jack, @@ -617,8 +550,7 @@ char *ucm_get_dev_for_jack(struct cras_use_case_mgr *mgr, const char *jack, struct section_name *section_names, *c; char *ret = NULL; - section_names = - ucm_get_devices_for_var(mgr, jack_dev_var, jack, direction); + section_names = ucm_get_devices_for_var(mgr, jack_var, jack, direction); DL_FOREACH (section_names, c) { if (!strcmp(c->name, "Mic")) { @@ -646,16 +578,10 @@ char *ucm_get_dev_for_jack(struct cras_use_case_mgr *mgr, const char *jack, char *ucm_get_dev_for_mixer(struct cras_use_case_mgr *mgr, const char *mixer, enum CRAS_STREAM_DIRECTION dir) { - struct section_name *section_names = NULL, *c; + struct section_name *section_names, *c; char *ret = NULL; - if (dir == CRAS_STREAM_OUTPUT) { - section_names = ucm_get_devices_for_var( - mgr, playback_mixer_elem_var, mixer, dir); - } else if (dir == CRAS_STREAM_INPUT) { - section_names = ucm_get_devices_for_var( - mgr, capture_mixer_elem_var, mixer, dir); - } + section_names = ucm_get_devices_for_var(mgr, mixer_var, mixer, dir); if (section_names) ret = strdup(section_names->name); @@ -669,16 +595,46 @@ char *ucm_get_dev_for_mixer(struct cras_use_case_mgr *mgr, const char *mixer, return ret; } -inline const char *ucm_get_edid_file_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) +const char *ucm_get_edid_file_for_dev(struct cras_use_case_mgr *mgr, + const char *dev) +{ + const char *file_name; + int rc; + + rc = get_var(mgr, edid_var, dev, uc_verb(mgr), &file_name); + if (rc) + return NULL; + + return file_name; +} + +const char *ucm_get_dsp_name_default(struct cras_use_case_mgr *mgr, + int direction) { - return ucm_get_value_for_dev(mgr, edid_var, dev); + const char *var = (direction == CRAS_STREAM_OUTPUT) ? + output_dsp_name_var : + input_dsp_name_var; + const char *dsp_name = NULL; + int rc; + + rc = get_var(mgr, var, "", uc_verb(mgr), &dsp_name); + if (rc) + return NULL; + + return dsp_name; } -inline const char *ucm_get_dsp_name_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) +const char *ucm_get_dsp_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev) { - return ucm_get_value_for_dev(mgr, dsp_name_var, dev); + const char *dsp_name = NULL; + int rc; + + rc = get_var(mgr, dsp_name_var, dev, uc_verb(mgr), &dsp_name); + if (rc) + return NULL; + + return dsp_name; } int ucm_get_min_buffer_level(struct cras_use_case_mgr *mgr, unsigned int *level) @@ -706,29 +662,42 @@ unsigned int ucm_get_disable_software_volume(struct cras_use_case_mgr *mgr) return value; } -int ucm_get_default_node_gain(struct cras_use_case_mgr *mgr, const char *dev, +int ucm_get_min_software_gain(struct cras_use_case_mgr *mgr, const char *dev, long *gain) { int value; int rc; - rc = get_int(mgr, default_node_gain, dev, uc_verb(mgr), &value); + rc = get_int(mgr, min_software_gain, dev, uc_verb(mgr), &value); + if (rc) + return rc; + *gain = value; + return 0; +} + +int ucm_get_max_software_gain(struct cras_use_case_mgr *mgr, const char *dev, + long *gain) +{ + int value; + int rc; + + rc = get_int(mgr, max_software_gain, dev, uc_verb(mgr), &value); if (rc) return rc; *gain = value; return 0; } -int ucm_get_intrinsic_sensitivity(struct cras_use_case_mgr *mgr, - const char *dev, long *sensitivity) +int ucm_get_default_node_gain(struct cras_use_case_mgr *mgr, const char *dev, + long *gain) { int value; int rc; - rc = get_int(mgr, intrinsic_sensitivity_var, dev, uc_verb(mgr), &value); + rc = get_int(mgr, default_node_gain, dev, uc_verb(mgr), &value); if (rc) return rc; - *sensitivity = value; + *gain = value; return 0; } @@ -743,31 +712,29 @@ int ucm_get_preempt_hotword(struct cras_use_case_mgr *mgr, const char *dev) return value; } -static int get_device_index_from_target(const char *target_device_name); - -int ucm_get_alsa_dev_idx_for_dev(struct cras_use_case_mgr *mgr, const char *dev, - enum CRAS_STREAM_DIRECTION direction) +const char *ucm_get_device_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev, + enum CRAS_STREAM_DIRECTION direction) { - const char *pcm_name = NULL; - int dev_idx = -1; - if (direction == CRAS_STREAM_OUTPUT) - pcm_name = ucm_get_playback_device_name_for_dev(mgr, dev); + return ucm_get_playback_device_name_for_dev(mgr, dev); else if (direction == CRAS_STREAM_INPUT) - pcm_name = ucm_get_capture_device_name_for_dev(mgr, dev); - - if (pcm_name) { - dev_idx = get_device_index_from_target(pcm_name); - free((void *)pcm_name); - } - return dev_idx; + return ucm_get_capture_device_name_for_dev(mgr, dev); + return NULL; } -inline const char * +const char * ucm_get_echo_reference_dev_name_for_dev(struct cras_use_case_mgr *mgr, const char *dev) { - return ucm_get_value_for_dev(mgr, echo_reference_dev_name_var, dev); + const char *name = NULL; + int rc; + + rc = get_var(mgr, echo_reference_dev_name_var, dev, uc_verb(mgr), + &name); + if (rc) + return NULL; + return name; } int ucm_get_sample_rate_for_dev(struct cras_use_case_mgr *mgr, const char *dev, @@ -791,31 +758,6 @@ int ucm_get_sample_rate_for_dev(struct cras_use_case_mgr *mgr, const char *dev, return value; } -int ucm_get_channels_for_dev(struct cras_use_case_mgr *mgr, const char *dev, - enum CRAS_STREAM_DIRECTION direction, - size_t *channels) -{ - int value; - int rc; - const char *var_name; - - if (direction == CRAS_STREAM_OUTPUT) - var_name = playback_channels_var; - else if (direction == CRAS_STREAM_INPUT) - var_name = capture_channels_var; - else - return -EINVAL; - - rc = get_int(mgr, var_name, dev, uc_verb(mgr), &value); - if (rc) - return rc; - if (value < 0) - return -1; - - *channels = (size_t)value; - return 0; -} - int ucm_get_capture_chmap_for_dev(struct cras_use_case_mgr *mgr, const char *dev, int8_t *channel_layout) { @@ -861,125 +803,10 @@ static int get_device_index_from_target(const char *target_device_name) return -1; } -static const char *ucm_get_dir_for_device(struct cras_use_case_mgr *mgr, - const char *dev_name, - enum CRAS_STREAM_DIRECTION *dir) -{ - const char *pcm_name; - - pcm_name = ucm_get_playback_device_name_for_dev(mgr, dev_name); - - if (pcm_name) { - *dir = CRAS_STREAM_OUTPUT; - return pcm_name; - } - - pcm_name = ucm_get_capture_device_name_for_dev(mgr, dev_name); - if (pcm_name) { - *dir = CRAS_STREAM_INPUT; - return pcm_name; - } - - *dir = CRAS_STREAM_UNDEFINED; - return NULL; -} - -static int ucm_parse_device_section(struct cras_use_case_mgr *mgr, - const char *dev, - struct ucm_section **sections) -{ - enum CRAS_STREAM_DIRECTION dir; - int dev_idx = -1; - int dependent_dev_idx = -1; - const char *jack_name = NULL; - const char *jack_type = NULL; - const char *jack_dev = NULL; - const char *jack_control = NULL; - const char *mixer_name = NULL; - struct mixer_name *m_name; - int rc = 0; - const char *pcm_name; - const char *dependent_dev_name = NULL; - struct ucm_section *dev_sec; - const char *dev_name; - - dev_name = strdup(dev); - if (!dev_name) - return 0; - - pcm_name = ucm_get_dir_for_device(mgr, dev_name, &dir); - - if (pcm_name) - dev_idx = get_device_index_from_target(pcm_name); - - if (dir == CRAS_STREAM_UNDEFINED) { - syslog(LOG_ERR, - "UCM configuration for device '%s' missing" - " PlaybackPCM or CapturePCM definition.", - dev_name); - rc = -EINVAL; - goto error_cleanup; - } - - dependent_dev_name = - ucm_get_dependent_device_name_for_dev(mgr, dev_name); - if (dependent_dev_name) { - dependent_dev_idx = - get_device_index_from_target(dependent_dev_name); - } - - jack_dev = ucm_get_jack_dev_for_dev(mgr, dev_name); - jack_control = ucm_get_jack_control_for_dev(mgr, dev_name); - if (dir == CRAS_STREAM_OUTPUT) - mixer_name = ucm_get_playback_mixer_elem_for_dev(mgr, dev_name); - else if (dir == CRAS_STREAM_INPUT) - mixer_name = ucm_get_capture_mixer_elem_for_dev(mgr, dev_name); - - if (jack_dev) { - jack_name = jack_dev; - jack_type = "gpio"; - } else if (jack_control) { - jack_name = jack_control; - jack_type = "hctl"; - } - - dev_sec = ucm_section_create(dev_name, pcm_name, dev_idx, - dependent_dev_idx, dir, jack_name, - jack_type); - - if (!dev_sec) { - syslog(LOG_ERR, "Failed to allocate memory."); - rc = -ENOMEM; - goto error_cleanup; - } - - dev_sec->jack_switch = ucm_get_jack_switch_for_dev(mgr, dev_name); - - if (mixer_name) { - rc = ucm_section_set_mixer_name(dev_sec, mixer_name); - if (rc) - goto error_cleanup; - } - - m_name = ucm_get_mixer_names(mgr, dev_name, coupled_mixers, dir, - MIXER_NAME_VOLUME); - ucm_section_concat_coupled(dev_sec, m_name); - - DL_APPEND(*sections, dev_sec); - ucm_section_dump(dev_sec); -error_cleanup: - free((void *)dev_name); - free((void *)dependent_dev_name); - free((void *)jack_dev); - free((void *)jack_control); - free((void *)mixer_name); - free((void *)pcm_name); - return rc; -} - struct ucm_section *ucm_get_sections(struct cras_use_case_mgr *mgr) { struct ucm_section *sections = NULL; + struct ucm_section *dev_sec; const char **list; int num_devs; int i; @@ -993,17 +820,101 @@ struct ucm_section *ucm_get_sections(struct cras_use_case_mgr *mgr) /* snd_use_case_get_list fills list with pairs of device name and * comment, so device names are in even-indexed elements. */ + const char *dev_name; for (i = 0; i < num_devs; i += 2) { - if (ucm_parse_device_section(mgr, list[i], §ions) < 0) { - ucm_section_free_list(sections); - sections = NULL; - break; + enum CRAS_STREAM_DIRECTION dir = CRAS_STREAM_UNDEFINED; + int dev_idx = -1; + const char *jack_name; + const char *jack_type; + const char *mixer_name; + struct mixer_name *m_name; + int rc; + const char *target_device_name; + + dev_name = strdup(list[i]); + if (!dev_name) + continue; + + target_device_name = + ucm_get_playback_device_name_for_dev(mgr, dev_name); + if (target_device_name) + dir = CRAS_STREAM_OUTPUT; + else { + target_device_name = + ucm_get_capture_device_name_for_dev(mgr, + dev_name); + if (target_device_name) + dir = CRAS_STREAM_INPUT; + } + if (target_device_name) { + dev_idx = get_device_index_from_target( + target_device_name); + free((void *)target_device_name); + } + + if (dir == CRAS_STREAM_UNDEFINED) { + syslog(LOG_ERR, + "UCM configuration for device '%s' missing" + " PlaybackPCM or CapturePCM definition.", + dev_name); + goto error_cleanup; + } + + if (dev_idx == -1) { + syslog(LOG_ERR, + "PlaybackPCM or CapturePCM for '%s' must be in" + " the form 'hw:<card>,<number>'", + dev_name); + goto error_cleanup; + } + + jack_name = ucm_get_jack_name_for_dev(mgr, dev_name); + jack_type = ucm_get_jack_type_for_dev(mgr, dev_name); + mixer_name = ucm_get_mixer_name_for_dev(mgr, dev_name); + + dev_sec = ucm_section_create(dev_name, dev_idx, dir, jack_name, + jack_type); + if (jack_name) + free((void *)jack_name); + if (jack_type) + free((void *)jack_type); + + if (!dev_sec) { + syslog(LOG_ERR, "Failed to allocate memory."); + if (mixer_name) + free((void *)mixer_name); + goto error_cleanup; + } + + dev_sec->jack_switch = + ucm_get_jack_switch_for_dev(mgr, dev_name); + + if (mixer_name) { + rc = ucm_section_set_mixer_name(dev_sec, mixer_name); + free((void *)mixer_name); + if (rc) + goto error_cleanup; } + + m_name = ucm_get_mixer_names(mgr, dev_name, coupled_mixers, dir, + MIXER_NAME_VOLUME); + ucm_section_concat_coupled(dev_sec, m_name); + + DL_APPEND(sections, dev_sec); + ucm_section_dump(dev_sec); + free((void *)dev_name); } if (num_devs > 0) snd_use_case_free_list(list, num_devs); return sections; + +error_cleanup: + if (num_devs > 0) + snd_use_case_free_list(list, num_devs); + ucm_section_free_list(sections); + free((void *)dev_name); + return NULL; } char *ucm_get_hotword_models(struct cras_use_case_mgr *mgr) @@ -1057,61 +968,14 @@ char *ucm_get_hotword_models(struct cras_use_case_mgr *mgr) return models; } -void ucm_disable_all_hotword_models(struct cras_use_case_mgr *mgr) +int ucm_set_hotword_model(struct cras_use_case_mgr *mgr, const char *model) { const char **list; int num_enmods, mod_idx; - - if (!mgr) - return; - - /* Disable all currently enabled hotword model modifiers. */ - num_enmods = snd_use_case_get_list(mgr->mgr, "_enamods", &list); - if (num_enmods <= 0) - return; - - for (mod_idx = 0; mod_idx < num_enmods; mod_idx++) { - if (!strncmp(list[mod_idx], hotword_model_prefix, - strlen(hotword_model_prefix))) - ucm_set_modifier_enabled(mgr, list[mod_idx], 0); - } - snd_use_case_free_list(list, num_enmods); -} - -int ucm_enable_hotword_model(struct cras_use_case_mgr *mgr) -{ - if (mgr->hotword_modifier) - return ucm_set_modifier_enabled(mgr, mgr->hotword_modifier, 1); - return -EINVAL; -} - -static int ucm_is_modifier_enabled(struct cras_use_case_mgr *mgr, - char *modifier, long *value) -{ - int rc; - char *id; - size_t len = strlen(modifier) + 11 + 1; - - id = (char *)malloc(len); - - if (!id) - return -ENOMEM; - - snprintf(id, len, "_modstatus/%s", modifier); - rc = snd_use_case_geti(mgr->mgr, id, value); - free(id); - return rc; -} - -int ucm_set_hotword_model(struct cras_use_case_mgr *mgr, const char *model) -{ - char *model_mod; - long mod_status = 0; + char *model_mod = NULL; size_t model_mod_size = strlen(model) + 1 + strlen(hotword_model_prefix) + 1; - model_mod = (char *)malloc(model_mod_size); - if (!model_mod) return -ENOMEM; snprintf(model_mod, model_mod_size, "%s %s", hotword_model_prefix, @@ -1121,16 +985,21 @@ int ucm_set_hotword_model(struct cras_use_case_mgr *mgr, const char *model) return -EINVAL; } - /* If check failed, just move on, dont fail incoming model */ - if (mgr->hotword_modifier) - ucm_is_modifier_enabled(mgr, mgr->hotword_modifier, - &mod_status); + /* Disable all currently enabled horword model modifiers. */ + num_enmods = snd_use_case_get_list(mgr->mgr, "_enamods", &list); + if (num_enmods <= 0) + goto enable_mod; + + for (mod_idx = 0; mod_idx < num_enmods; mod_idx++) { + if (!strncmp(list[mod_idx], hotword_model_prefix, + strlen(hotword_model_prefix))) + ucm_set_modifier_enabled(mgr, list[mod_idx], 0); + } + snd_use_case_free_list(list, num_enmods); - ucm_disable_all_hotword_models(mgr); - free(mgr->hotword_modifier); - mgr->hotword_modifier = model_mod; - if (mod_status) - return ucm_enable_hotword_model(mgr); +enable_mod: + ucm_set_modifier_enabled(mgr, model_mod, 1); + free((void *)model_mod); return 0; } @@ -1146,18 +1015,17 @@ int ucm_has_fully_specified_ucm_flag(struct cras_use_case_mgr *mgr) return ret; } -inline const char * -ucm_get_playback_mixer_elem_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) +const char *ucm_get_mixer_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev) { - return ucm_get_value_for_dev(mgr, playback_mixer_elem_var, dev); -} + const char *name = NULL; + int rc; -inline const char * -ucm_get_capture_mixer_elem_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) -{ - return ucm_get_value_for_dev(mgr, capture_mixer_elem_var, dev); + rc = get_var(mgr, mixer_var, dev, uc_verb(mgr), &name); + if (rc) + return NULL; + + return name; } struct mixer_name *ucm_get_main_volume_names(struct cras_use_case_mgr *mgr) @@ -1203,16 +1071,37 @@ int ucm_list_section_devices_by_device_name( return listed; } -inline const char *ucm_get_jack_control_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) +const char *ucm_get_jack_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev) { - return ucm_get_value_for_dev(mgr, jack_control_var, dev); + const char *name = NULL; + int rc; + + rc = get_var(mgr, jack_var, dev, uc_verb(mgr), &name); + if (rc) + return NULL; + + return name; } -inline const char *ucm_get_jack_dev_for_dev(struct cras_use_case_mgr *mgr, - const char *dev) +const char *ucm_get_jack_type_for_dev(struct cras_use_case_mgr *mgr, + const char *dev) { - return ucm_get_value_for_dev(mgr, jack_dev_var, dev); + const char *name = NULL; + int rc; + + rc = get_var(mgr, jack_type_var, dev, uc_verb(mgr), &name); + if (rc) + return NULL; + + if (strcmp(name, "hctl") && strcmp(name, "gpio") && + strcmp(name, "always")) { + syslog(LOG_ERR, "Unknown jack type: %s", name); + if (name) + free((void *)name); + return NULL; + } + return name; } int ucm_get_jack_switch_for_dev(struct cras_use_case_mgr *mgr, const char *dev) @@ -1235,3 +1124,15 @@ unsigned int ucm_get_dma_period_for_dev(struct cras_use_case_mgr *mgr, return 0; return value; } + +unsigned int ucm_get_enable_htimestamp_flag(struct cras_use_case_mgr *mgr) +{ + char *flag; + int ret = 0; + flag = ucm_get_flag(mgr, enable_htimestamp_var); + if (!flag) + return 0; + ret = !strcmp(flag, "1"); + free(flag); + return ret; +} diff --git a/cras/src/server/cras_alsa_ucm.h b/cras/src/server/cras_alsa_ucm.h index 55c3cf62..36f68a01 100644 --- a/cras/src/server/cras_alsa_ucm.h +++ b/cras/src/server/cras_alsa_ucm.h @@ -67,28 +67,6 @@ int ucm_swap_mode_exists(struct cras_use_case_mgr *mgr); int ucm_enable_swap_mode(struct cras_use_case_mgr *mgr, const char *node_name, int enable); -/* Checks if modifier of noise cancellation for given node_name exists in ucm. - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * node_name - The node name. - * Returns: - * 1 if it exists, 0 otherwise. - */ -int ucm_node_noise_cancellation_exists(struct cras_use_case_mgr *mgr, - const char *node_name); - -/* Enables or disables noise cancellation for the given node_name. First checks - * if the modifier is already enabled or disabled. - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * node_name - The node name. - * enable - Enable device if non-zero. - * Returns: - * 0 on success or negative error code on failure. - */ -int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr *mgr, - const char *node_name, int enable); - /* Enables or disables a UCM device. First checks if the device is already * enabled or disabled. * Args: @@ -120,6 +98,15 @@ char *ucm_get_flag(struct cras_use_case_mgr *mgr, const char *flag_name); */ char *ucm_get_cap_control(struct cras_use_case_mgr *mgr, const char *ucm_dev); +/* Gets the mic positions string for internal mic. + * Args: + * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. + * Returns: + * A pointer to the allocated string containing the mic positions + * information, or NULL if not specified. + */ +char *ucm_get_mic_positions(struct cras_use_case_mgr *mgr); + /* Gets the new node type name which user wants to override the old one for * given ucm device. * Args: @@ -168,6 +155,17 @@ char *ucm_get_dev_for_mixer(struct cras_use_case_mgr *mgr, const char *mixer, const char *ucm_get_edid_file_for_dev(struct cras_use_case_mgr *mgr, const char *dev); +/* Gets the default dsp name. + * Args: + * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. + * direction - playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT). + * Returns: + * A pointer to the allocated string containing the default dsp name, or + * NULL if no default dsp name is found. + */ +const char *ucm_get_dsp_name_default(struct cras_use_case_mgr *mgr, + int direction); + /* Gets the dsp name which is associated with the given ucm device. * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. @@ -198,27 +196,38 @@ int ucm_get_min_buffer_level(struct cras_use_case_mgr *mgr, */ unsigned int ucm_get_disable_software_volume(struct cras_use_case_mgr *mgr); -/* Gets the value for default node gain. +/* Gets the value for minimum software gain. * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The device to check for default node gain. - * gain - The pointer to the returned value. + * dev - The device to check for minimum software gain. + * gain - The pointer to the returned value; * Returns: * 0 on success, other error codes on failure. */ -int ucm_get_default_node_gain(struct cras_use_case_mgr *mgr, const char *dev, +int ucm_get_min_software_gain(struct cras_use_case_mgr *mgr, const char *dev, long *gain); -/* Gets the value for intrinsic sensitivity. +/* Gets the value for maximum software gain. * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The device to query for intrinsic volume. - * sensitivity - The pointer to the returned value. + * dev - The device to check for maximum software gain. + * gain - The pointer to the returned value; * Returns: * 0 on success, other error codes on failure. */ -int ucm_get_intrinsic_sensitivity(struct cras_use_case_mgr *mgr, - const char *dev, long *sensitivity); +int ucm_get_max_software_gain(struct cras_use_case_mgr *mgr, const char *dev, + long *gain); + +/* Gets the value for default node gain. + * Args: + * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. + * dev - The device to check for default node gain. + * gain - The pointer to the returned value; + * Returns: + * 0 on success, other error codes on failure. + */ +int ucm_get_default_node_gain(struct cras_use_case_mgr *mgr, const char *dev, + long *gain); /* Gets the flag if an input device can preempt hotword recording. * Args: @@ -230,19 +239,20 @@ int ucm_get_intrinsic_sensitivity(struct cras_use_case_mgr *mgr, */ int ucm_get_preempt_hotword(struct cras_use_case_mgr *mgr, const char *dev); -/* Gets the ALSA device index on the card for given UCM dev. +/* Gets the device name of this device on the card.. * * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The UCM device to check for ALSA device index. + * dev - The device to check for device name * direction - playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT). * Returns: - * Non-negative integer for the ALSA device index on the card, -1 if not - * found. The ALSA device index is parsed from the PCM name which is - * formatted as "hw:<some-name>,<idx>". + * A pointer to the allocated string containing the device name, or NULL + * if no device name is found. The device name is of format + * "card_name:device_index". */ -int ucm_get_alsa_dev_idx_for_dev(struct cras_use_case_mgr *mgr, const char *dev, - enum CRAS_STREAM_DIRECTION direction); +const char *ucm_get_device_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev, + enum CRAS_STREAM_DIRECTION direction); /* Gets the node name of the echo reference device on the card. * Args: @@ -269,20 +279,6 @@ ucm_get_echo_reference_dev_name_for_dev(struct cras_use_case_mgr *mgr, int ucm_get_sample_rate_for_dev(struct cras_use_case_mgr *mgr, const char *dev, enum CRAS_STREAM_DIRECTION direction); -/* Gets the channel count at which to run this device. - * - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The device to check for channel count. - * direction - playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT). - * channels - The pointer to the returned channel count. - * Returns: - * 0 on success, other error codes on failure. - */ -int ucm_get_channels_for_dev(struct cras_use_case_mgr *mgr, const char *dev, - enum CRAS_STREAM_DIRECTION direction, - size_t *channels); - /* Gets the capture channel map for this device. * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. @@ -328,26 +324,11 @@ char *ucm_get_hotword_models(struct cras_use_case_mgr *mgr); /* Sets the desired hotword model. * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * model - locale for model * Returns: * 0 on success or negative error code on failure. */ int ucm_set_hotword_model(struct cras_use_case_mgr *mgr, const char *model); -/* Enable previously set hotword modifier - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * Returns: - * 0 on success or negative error code on failure. - */ -int ucm_enable_hotword_model(struct cras_use_case_mgr *mgr); - -/* Disable all hotword model modifiers - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - */ -void ucm_disable_all_hotword_models(struct cras_use_case_mgr *mgr); - /* Checks if this card has fully specified UCM config. * * Args: @@ -357,19 +338,7 @@ void ucm_disable_all_hotword_models(struct cras_use_case_mgr *mgr); */ int ucm_has_fully_specified_ucm_flag(struct cras_use_case_mgr *mgr); -/* Gets the playback mixer name of this device on the card. - * - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The device to check for device name - * Returns: - * A pointer to the allocated string containing the mixer name, or NULL - * if no device name is found. - */ -const char *ucm_get_playback_mixer_elem_for_dev(struct cras_use_case_mgr *mgr, - const char *dev); - -/* Gets the capture mixer name of this device on the card. +/* Gets the mixer name of this device on the card. * * Args: * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. @@ -378,8 +347,8 @@ const char *ucm_get_playback_mixer_elem_for_dev(struct cras_use_case_mgr *mgr, * A pointer to the allocated string containing the mixer name, or NULL * if no device name is found. */ -const char *ucm_get_capture_mixer_elem_for_dev(struct cras_use_case_mgr *mgr, - const char *dev); +const char *ucm_get_mixer_name_for_dev(struct cras_use_case_mgr *mgr, + const char *dev); /* Gets the mixer names for the main volume controls on the card. * @@ -450,30 +419,6 @@ const char *ucm_get_jack_name_for_dev(struct cras_use_case_mgr *mgr, const char *ucm_get_jack_type_for_dev(struct cras_use_case_mgr *mgr, const char *dev); -/* Gets the jack dev of this device on the card. - * - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The device to check for jack name. - * Returns: - * A pointer to the allocated string containing the input jack name, or NULL - * if no jack name is found. - */ -const char *ucm_get_jack_dev_for_dev(struct cras_use_case_mgr *mgr, - const char *dev); - -/* Gets the jack control of this device on the card. - * - * Args: - * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. - * dev - The device to check for jack type. - * Returns: - * A pointer to the allocated string containing the alsa jack name, or NULL - * if no jack type is found or the found jack type is invalid. - */ -const char *ucm_get_jack_control_for_dev(struct cras_use_case_mgr *mgr, - const char *dev); - /* Gets the jack switch number for this device. * Some sound cards can detect multiple types of connections into the * audio jack - for example distinguish between line-out and headphones @@ -509,4 +454,12 @@ unsigned int ucm_get_dma_period_for_dev(struct cras_use_case_mgr *mgr, */ unsigned int ucm_get_optimize_no_stream_flag(struct cras_use_case_mgr *mgr); +/* Retrieve the flag that enables use of htimestamp. + * Args: + * mgr - The cras_use_case_mgr pointer returned from alsa_ucm_create. + * Returns: + * 1 if the flag is enabled. 0 otherwise. + */ +unsigned int ucm_get_enable_htimestamp_flag(struct cras_use_case_mgr *mgr); + #endif /* _CRAS_ALSA_UCM_H */ diff --git a/cras/src/server/cras_alsa_ucm_section.c b/cras/src/server/cras_alsa_ucm_section.c index d4df8c7d..36d44220 100644 --- a/cras/src/server/cras_alsa_ucm_section.c +++ b/cras/src/server/cras_alsa_ucm_section.c @@ -13,11 +13,14 @@ static void ucm_section_free(struct ucm_section *section) { - free((void *)section->name); - free((void *)section->pcm_name); - free((void *)section->jack_name); - free((void *)section->jack_type); - free((void *)section->mixer_name); + if (section->name) + free((void *)section->name); + if (section->jack_name) + free((void *)section->jack_name); + if (section->jack_type) + free((void *)section->jack_type); + if (section->mixer_name) + free((void *)section->mixer_name); mixer_name_free(section->coupled); free(section); } @@ -31,8 +34,7 @@ void ucm_section_free_list(struct ucm_section *sections) } } -struct ucm_section *ucm_section_create(const char *name, const char *pcm_name, - int dev_idx, int dependent_dev_idx, +struct ucm_section *ucm_section_create(const char *name, int dev_idx, enum CRAS_STREAM_DIRECTION dir, const char *jack_name, const char *jack_type) @@ -48,16 +50,11 @@ struct ucm_section *ucm_section_create(const char *name, const char *pcm_name, return NULL; section->dev_idx = dev_idx; - section->dependent_dev_idx = dependent_dev_idx; section->dir = dir; section->name = strdup(name); if (!section->name) goto error; - section->pcm_name = strdup(pcm_name); - if (!section->pcm_name) - goto error; - if (jack_name) { section->jack_name = strdup(jack_name); if (!section->jack_name) diff --git a/cras/src/server/cras_alsa_ucm_section.h b/cras/src/server/cras_alsa_ucm_section.h index 77c5ed89..0ffa5ab4 100644 --- a/cras/src/server/cras_alsa_ucm_section.h +++ b/cras/src/server/cras_alsa_ucm_section.h @@ -17,12 +17,8 @@ extern "C" { struct ucm_section { /* Section name. */ const char *name; - /* Value of PlaybackPCM or CapturePCM. */ - const char *pcm_name; /* Device PCM index. */ int dev_idx; - /* Device PCM index to associate this section to. */ - int dependent_dev_idx; /* Output or Input. */ enum CRAS_STREAM_DIRECTION dir; /* Associated jack's name. */ @@ -31,7 +27,7 @@ struct ucm_section { const char *jack_type; /* Switch number for jack from linux/input.h, or -1. */ int jack_switch; - /* (Playback/Capture)MixerElem value. */ + /* MixerName value. */ const char *mixer_name; /* CoupledMixers value. */ struct mixer_name *coupled; @@ -42,10 +38,7 @@ struct ucm_section { * * Args: * name - Section name (must not be NULL). - * pcm_name - PCM name used for snd_pcm_open. * dev_idx - Section's device index (PCM number). - * dependent_dev_idx - Another ALSA device index (PCM number) under which - * we want to make this section a node. * dir - Device direction: INPUT or OUTPUT. * jack_name - Name of an associated jack (or NULL). * jack_type - Type of the associated jack (or NULL). @@ -53,8 +46,7 @@ struct ucm_section { * Returns: * A valid pointer on success, NULL for memory allocation error. */ -struct ucm_section *ucm_section_create(const char *name, const char *pcm_name, - int dev_idx, int dependent_dev_idx, +struct ucm_section *ucm_section_create(const char *name, int dev_idx, enum CRAS_STREAM_DIRECTION dir, const char *jack_name, const char *jack_type); diff --git a/cras/src/server/cras_apm_list.c b/cras/src/server/cras_apm_list.c index ab891137..d0ea9a96 100644 --- a/cras/src/server/cras_apm_list.c +++ b/cras/src/server/cras_apm_list.c @@ -22,6 +22,8 @@ #include "iniparser_wrapper.h" #include "utlist.h" +static const unsigned int MAX_INI_NAME_LEN = 63; + #define AEC_CONFIG_NAME "aec.ini" #define APM_CONFIG_NAME "apm.ini" @@ -61,10 +63,6 @@ * stream. * work_queue - A task queue instance created and destroyed by * libwebrtc_apm. - * is_aec_use_case - True if the input and output devices pair is in the - * typical AEC use case. This flag decides whether to use settings - * tuned specifically for this hardware if exists. Otherwise it uses - * the generic settings like run inside browser. */ struct cras_apm { webrtc_apm apm_ptr; @@ -75,7 +73,6 @@ struct cras_apm { struct cras_audio_format fmt; struct cras_audio_area *area; void *work_queue; - bool is_aec_use_case; struct cras_apm *prev, *next; }; @@ -84,10 +81,6 @@ struct cras_apm { * have more than one cras_apm when multiple input devices are * enabled. The most common scenario is the silent input iodev be * enabled when CRAS switches active input device. - * - * Note that cras_apm_list is owned and modified in main thread. - * Only in synchronized audio thread event this cras_apm_list is safe - * to access for passing single APM instance between threads. */ struct cras_apm_list { void *stream_ptr; @@ -97,22 +90,6 @@ struct cras_apm_list { }; /* - * Wrappers of APM instances that are active, which means it is associated - * to a dev/stream pair in audio thread and ready for processing. - * - * Members: - * apm - The APM for audio data processing. - * stream_ptr - Stream pointer from the associated dev/stream pair. - * effects - The effecets bit map of APM. - */ -struct active_apm { - struct cras_apm *apm; - void *stream_ptr; - int effects; - struct active_apm *prev, *next; -} * active_apms; - -/* * Object used to analyze playback audio from output iodev. It is responsible * to get buffer containing latest output data and provide it to the APM * instances which want to analyze reverse stream. @@ -135,8 +112,9 @@ struct cras_apm_reverse_module { }; static struct cras_apm_reverse_module *rmodule = NULL; +static struct cras_apm_list *apm_list = NULL; static const char *aec_config_dir = NULL; -static char ini_name[MAX_INI_NAME_LENGTH + 1]; +static char ini_name[MAX_INI_NAME_LEN + 1]; static dictionary *aec_ini = NULL; static dictionary *apm_ini = NULL; @@ -144,14 +122,14 @@ static dictionary *apm_ini = NULL; * or removed. */ static void update_process_reverse_flag() { - struct active_apm *active; + struct cras_apm_list *list; if (!rmodule) return; rmodule->process_reverse = 0; - DL_FOREACH (active_apms, active) { + DL_FOREACH (apm_list, list) { rmodule->process_reverse |= - !!(active->effects & APM_ECHO_CANCELLATION); + !!(list->effects & APM_ECHO_CANCELLATION); } } @@ -176,36 +154,33 @@ struct cras_apm_list *cras_apm_list_create(void *stream_ptr, uint64_t effects) if (effects == 0) return NULL; + DL_SEARCH_SCALAR(apm_list, list, stream_ptr, stream_ptr); + if (list) + return list; + list = (struct cras_apm_list *)calloc(1, sizeof(*list)); - if (list == NULL) { - syslog(LOG_ERR, "No memory in creating apm list"); - return NULL; - } list->stream_ptr = stream_ptr; list->effects = effects; list->apms = NULL; + DL_APPEND(apm_list, list); return list; } -static struct active_apm *get_active_apm(void *stream_ptr, void *dev_ptr) +struct cras_apm *cras_apm_list_get(struct cras_apm_list *list, void *dev_ptr) { - struct active_apm *active; + struct cras_apm *apm; + + if (list == NULL) + return NULL; - DL_FOREACH (active_apms, active) { - if ((active->apm->dev_ptr == dev_ptr) && - (active->stream_ptr == stream_ptr)) - return active; + DL_FOREACH (list->apms, apm) { + if (apm->dev_ptr == dev_ptr) + return apm; } return NULL; } -struct cras_apm *cras_apm_list_get_active_apm(void *stream_ptr, void *dev_ptr) -{ - struct active_apm *active = get_active_apm(stream_ptr, dev_ptr); - return active ? active->apm : NULL; -} - uint64_t cras_apm_list_get_effects(struct cras_apm_list *list) { if (list == NULL) @@ -214,7 +189,7 @@ uint64_t cras_apm_list_get_effects(struct cras_apm_list *list) return list->effects; } -void cras_apm_list_remove_apm(struct cras_apm_list *list, void *dev_ptr) +void cras_apm_list_remove(struct cras_apm_list *list, void *dev_ptr) { struct cras_apm *apm; @@ -240,12 +215,13 @@ static void get_best_channels(struct cras_audio_format *apm_fmt) int ch; int8_t layout[CRAS_CH_MAX]; - /* Using the format from dev_fmt is dangerous because input device - * could have wild configurations like unuse the 1st channel and - * connects 2nd channel to the only mic. Data in the first channel - * is what APM cares about so always construct a new channel layout - * containing subset of original channels that matches either FL, FR, - * or FC. + /* Assume device format has correct channel layout populated. */ + if (apm_fmt->num_channels <= 2) + return; + + /* If the device provides recording from more channels than we care + * about, construct a new channel layout containing subset of original + * channels that matches either FL, FR, or FC. * TODO(hychao): extend the logic when we have a stream that wants * to record channels like RR(rear right). */ @@ -264,10 +240,8 @@ static void get_best_channels(struct cras_audio_format *apm_fmt) apm_fmt->channel_layout[ch] = layout[ch]; } -struct cras_apm *cras_apm_list_add_apm(struct cras_apm_list *list, - void *dev_ptr, - const struct cras_audio_format *dev_fmt, - bool is_aec_use_case) +struct cras_apm *cras_apm_list_add(struct cras_apm_list *list, void *dev_ptr, + const struct cras_audio_format *dev_fmt) { struct cras_apm *apm; @@ -288,23 +262,8 @@ struct cras_apm *cras_apm_list_add_apm(struct cras_apm_list *list, apm->fmt = *dev_fmt; get_best_channels(&apm->fmt); - /* Use tuned settings only when the forward dev(capture) and reverse - * dev(playback) both are in typical AEC use case. */ - apm->is_aec_use_case = is_aec_use_case; - if (rmodule->odev) { - apm->is_aec_use_case &= - cras_iodev_is_aec_use_case(rmodule->odev->active_node); - } - - /* Use the configs tuned specifically for internal device. Otherwise - * just pass NULL so every other settings will be default. */ - apm->apm_ptr = - apm->is_aec_use_case ? - webrtc_apm_create(apm->fmt.num_channels, - apm->fmt.frame_rate, aec_ini, - apm_ini) : - webrtc_apm_create(apm->fmt.num_channels, - apm->fmt.frame_rate, NULL, NULL); + apm->apm_ptr = webrtc_apm_create(apm->fmt.num_channels, + apm->fmt.frame_rate, aec_ini, apm_ini); if (apm->apm_ptr == NULL) { syslog(LOG_ERR, "Fail to create webrtc apm for ch %zu" @@ -327,59 +286,25 @@ struct cras_apm *cras_apm_list_add_apm(struct cras_apm_list *list, cras_audio_area_config_channels(apm->area, &apm->fmt); DL_APPEND(list->apms, apm); + update_process_reverse_flag(); return apm; } -void cras_apm_list_start_apm(struct cras_apm_list *list, void *dev_ptr) +int cras_apm_list_destroy(struct cras_apm_list *list) { - struct active_apm *active; + struct cras_apm_list *tmp; struct cras_apm *apm; - if (list == NULL) - return; - - /* Check if this apm has already been started. */ - apm = cras_apm_list_get_active_apm(list->stream_ptr, dev_ptr); - if (apm) - return; - - DL_SEARCH_SCALAR(list->apms, apm, dev_ptr, dev_ptr); - if (apm == NULL) - return; - - active = (struct active_apm *)calloc(1, sizeof(*active)); - if (active == NULL) { - syslog(LOG_ERR, "No memory to start apm."); - return; - } - active->apm = apm; - active->stream_ptr = list->stream_ptr; - active->effects = list->effects; - DL_APPEND(active_apms, active); - - update_process_reverse_flag(); -} - -void cras_apm_list_stop_apm(struct cras_apm_list *list, void *dev_ptr) -{ - struct active_apm *active; - - if (list == NULL) - return; - - active = get_active_apm(list->stream_ptr, dev_ptr); - if (active) { - DL_DELETE(active_apms, active); - free(active); + DL_FOREACH (apm_list, tmp) { + if (tmp == list) { + DL_DELETE(apm_list, tmp); + break; + } } - update_process_reverse_flag(); -} - -int cras_apm_list_destroy(struct cras_apm_list *list) -{ - struct cras_apm *apm; + if (tmp == NULL) + return 0; DL_FOREACH (list->apms, apm) { DL_DELETE(list->apms, apm); @@ -387,6 +312,8 @@ int cras_apm_list_destroy(struct cras_apm_list *list) } free(list); + update_process_reverse_flag(); + return 0; } @@ -462,7 +389,8 @@ static void handle_device_disabled(struct cras_iodev *iodev, void *cb_data) static int process_reverse(struct float_buffer *fbuf, unsigned int frame_rate) { - struct active_apm *active; + struct cras_apm_list *list; + struct cras_apm *apm; int ret; float *const *wp; @@ -471,16 +399,18 @@ static int process_reverse(struct float_buffer *fbuf, unsigned int frame_rate) wp = float_buffer_write_pointer(fbuf); - DL_FOREACH (active_apms, active) { - if (!(active->effects & APM_ECHO_CANCELLATION)) + DL_FOREACH (apm_list, list) { + if (!(list->effects & APM_ECHO_CANCELLATION)) continue; - ret = webrtc_apm_process_reverse_stream_f(active->apm->apm_ptr, - fbuf->num_channels, - frame_rate, wp); - if (ret) { - syslog(LOG_ERR, "APM process reverse err"); - return ret; + DL_FOREACH (list->apms, apm) { + ret = webrtc_apm_process_reverse_stream_f( + apm->apm_ptr, fbuf->num_channels, frame_rate, + wp); + if (ret) { + syslog(LOG_ERR, "APM process reverse err"); + return ret; + } } } float_buffer_reset(fbuf); @@ -527,9 +457,9 @@ void reverse_data_configure(struct ext_dsp_module *ext, static void get_aec_ini(const char *config_dir) { - snprintf(ini_name, MAX_INI_NAME_LENGTH, "%s/%s", config_dir, + snprintf(ini_name, MAX_INI_NAME_LEN, "%s/%s", config_dir, AEC_CONFIG_NAME); - ini_name[MAX_INI_NAME_LENGTH] = '\0'; + ini_name[MAX_INI_NAME_LEN] = '\0'; if (aec_ini) { iniparser_freedict(aec_ini); @@ -542,9 +472,9 @@ static void get_aec_ini(const char *config_dir) static void get_apm_ini(const char *config_dir) { - snprintf(ini_name, MAX_INI_NAME_LENGTH, "%s/%s", config_dir, + snprintf(ini_name, MAX_INI_NAME_LEN, "%s/%s", config_dir, APM_CONFIG_NAME); - ini_name[MAX_INI_NAME_LENGTH] = '\0'; + ini_name[MAX_INI_NAME_LEN] = '\0'; if (apm_ini) { iniparser_freedict(apm_ini); @@ -689,13 +619,6 @@ struct cras_audio_format *cras_apm_list_get_format(struct cras_apm *apm) return &apm->fmt; } -bool cras_apm_list_get_use_tuned_settings(struct cras_apm *apm) -{ - /* If input and output devices in AEC use case, plus that a - * tuned setting is provided. */ - return apm->is_aec_use_case && (aec_ini || apm_ini); -} - void cras_apm_list_set_aec_dump(struct cras_apm_list *list, void *dev_ptr, int start, int fd) { diff --git a/cras/src/server/cras_apm_list.h b/cras/src/server/cras_apm_list.h index 7a36ceae..486b943d 100644 --- a/cras/src/server/cras_apm_list.h +++ b/cras/src/server/cras_apm_list.h @@ -27,25 +27,7 @@ int cras_apm_list_deinit(); /* * Creates an list to hold all APM instances created when a stream - * attaches to iodev(s). This should be called in main thread. - * - * Below diagram explains the life cycle of an APM instance, how are - * related APIs used, and in which thread should each API be called. - * - * Main thread Audio thread - * maintaining apm_list maintaining active_apms - * ----------- ------------ - * cras_apm_list_create - * cras_apm_list_add_apm -> cras_apm_list_start_apm - * - * cras_apm_list_get_active_apm - * cras_apm_list_process - * cras_apm_list_get_processed - * cras_apm_list_put_processed - * - * cras_apm_list_remove_apm <- cras_apm_list_stop_apm - * cras_apm_list_destroy - * + * attaches to an iodev. * Args: * stream_ptr - Pointer to the stream. * effects - Bit map specifying the enabled effects on this stream. @@ -55,39 +37,22 @@ struct cras_apm_list *cras_apm_list_create(void *stream_ptr, uint64_t effects); /* * Creates a cras_apm associated to given dev_ptr and adds it to the list. * If there already exists an APM instance linked to dev_ptr, we assume - * the open format is unchanged so just return it. This should be called - * in main thread. + * the open format is unchanged so just return it. * Args: * list - The list holding APM instances. * dev_ptr - Pointer to the iodev to add new APM for. * fmt - Format of the audio data used for this cras_apm. - * is_aec_use_case - If the dev_ptr is for typical AEC use case. */ -struct cras_apm *cras_apm_list_add_apm(struct cras_apm_list *list, - void *dev_ptr, - const struct cras_audio_format *fmt, - bool is_aec_use_case); +struct cras_apm *cras_apm_list_add(struct cras_apm_list *list, void *dev_ptr, + const struct cras_audio_format *fmt); /* - * Gets the active APM instance that is associated to given stream and dev pair. - * This should be called in audio thread. + * Gets the cras_apm instance in the list that associates with given dev. * Args: - * stream_ptr - Pointer to the stream. + * list - The list holding APM instances. * dev_ptr - The iodev as key to look up associated APM. */ -struct cras_apm *cras_apm_list_get_active_apm(void *stream_ptr, void *dev_ptr); - -/* - * Starts the APM instance in the list that is associated with dev_ptr by - * adding it to the active APM list in audio thread. - */ -void cras_apm_list_start_apm(struct cras_apm_list *list, void *dev_ptr); - -/* - * Stops the APM instance in the list that is associated with dev_ptr by - * removing it from the active APM list in audio thread. - */ -void cras_apm_list_stop_apm(struct cras_apm_list *list, void *dev_ptr); +struct cras_apm *cras_apm_list_get(struct cras_apm_list *list, void *dev_ptr); /* * Gets the effects bit map of the APM list. @@ -101,13 +66,12 @@ int cras_apm_list_destroy(struct cras_apm_list *list); /* * Removes an APM from the list, expected to be used when an iodev is no - * longer open for the client stream holding the APM list. This should - * be called in main thread. + * longer open for the client stream holding the APM list. * Args: * list - The list holding APM instances. * dev_ptr - Device pointer used to look up which apm to remove. */ -void cras_apm_list_remove_apm(struct cras_apm_list *list, void *dev_ptr); +void cras_apm_list_remove(struct cras_apm_list *list, void *dev_ptr); /* Passes audio data from hardware for cras_apm to process. * Args: @@ -143,11 +107,6 @@ void cras_apm_list_put_processed(struct cras_apm *apm, unsigned int frames); */ struct cras_audio_format *cras_apm_list_get_format(struct cras_apm *apm); -/* - * Gets if this apm instance is using tuned settings. - */ -bool cras_apm_list_get_use_tuned_settings(struct cras_apm *apm); - /* Sets debug recording to start or stop. * Args: * list - List contains the apm instance to start/stop debug recording. @@ -162,7 +121,7 @@ void cras_apm_list_set_aec_dump(struct cras_apm_list *list, void *dev_ptr, /* * If webrtc audio processing library is not available then define all - * cras_apm_list functions as empty. As long as cras_apm_list_add returns + * cras_apm_list functions as dummy. As long as cras_apm_list_add returns * NULL, non of the other functions should be called. */ static inline int cras_apm_list_init(const char *device_config_dir) @@ -178,13 +137,13 @@ static inline struct cras_apm_list *cras_apm_list_create(void *stream_ptr, return NULL; } static inline struct cras_apm * -cras_apm_list_add_apm(struct cras_apm_list *list, void *dev_ptr, - const struct cras_audio_format *fmt, bool is_aec_use_case) +cras_apm_list_add(struct cras_apm_list *list, void *dev_ptr, + const struct cras_audio_format *fmt) { return NULL; } -static inline struct cras_apm *cras_apm_list_get_active_apm(void *stream_ptr, - void *dev_ptr) +static inline struct cras_apm *cras_apm_list_get(struct cras_apm_list *list, + void *dev_ptr) { return NULL; } @@ -196,8 +155,8 @@ static inline int cras_apm_list_destroy(struct cras_apm_list *list) { return 0; } -static inline void cras_apm_list_remove_apm(struct cras_apm_list *list, - void *dev_ptr) +static inline void cras_apm_list_remove(struct cras_apm_list *list, + void *dev_ptr) { } @@ -218,14 +177,6 @@ static inline void cras_apm_list_put_processed(struct cras_apm *apm, unsigned int frames) { } -static inline void cras_apm_list_start_apm(struct cras_apm_list *list, - void *dev_ptr) -{ -} -static inline void cras_apm_list_stop_apm(struct cras_apm_list *list, - void *dev_ptr) -{ -} static inline struct cras_audio_format * cras_apm_list_get_format(struct cras_apm *apm) @@ -233,11 +184,6 @@ cras_apm_list_get_format(struct cras_apm *apm) return NULL; } -static inline bool cras_apm_list_get_use_tuned_settings(struct cras_apm *apm) -{ - return 0; -} - static inline void cras_apm_list_set_aec_dump(struct cras_apm_list *list, void *dev_ptr, int start, int fd) { diff --git a/cras/src/server/cras_audio_thread_monitor.c b/cras/src/server/cras_audio_thread_monitor.c index ed3afbac..59212459 100644 --- a/cras/src/server/cras_audio_thread_monitor.c +++ b/cras/src/server/cras_audio_thread_monitor.c @@ -50,16 +50,6 @@ int cras_audio_thread_event_send(enum CRAS_AUDIO_THREAD_EVENT_TYPE event_type) return cras_main_message_send(&msg.header); } -int cras_audio_thread_event_a2dp_overrun() -{ - return cras_audio_thread_event_send(AUDIO_THREAD_EVENT_A2DP_OVERRUN); -} - -int cras_audio_thread_event_a2dp_throttle() -{ - return cras_audio_thread_event_send(AUDIO_THREAD_EVENT_A2DP_THROTTLE); -} - int cras_audio_thread_event_debug() { return cras_audio_thread_event_send(AUDIO_THREAD_EVENT_DEBUG); @@ -85,11 +75,6 @@ int cras_audio_thread_event_drop_samples() return cras_audio_thread_event_send(AUDIO_THREAD_EVENT_DROP_SAMPLES); } -int cras_audio_thread_event_dev_overrun() -{ - return cras_audio_thread_event_send(AUDIO_THREAD_EVENT_DEV_OVERRUN); -} - static struct timespec last_event_snapshot_time[AUDIO_THREAD_EVENT_TYPE_COUNT]; /* diff --git a/cras/src/server/cras_audio_thread_monitor.h b/cras/src/server/cras_audio_thread_monitor.h index 39b21765..b7355caa 100644 --- a/cras/src/server/cras_audio_thread_monitor.h +++ b/cras/src/server/cras_audio_thread_monitor.h @@ -7,16 +7,6 @@ #define CRAS_AUDIO_THREAD_MONITOR_H_ /* - * Notifies the main thread when A2DP buffer overruns. - */ -int cras_audio_thread_event_a2dp_overrun(); - -/* - * Notifies the main thread when A2DP packet transmittion throttles. - */ -int cras_audio_thread_event_a2dp_throttle(); - -/* * Sends a debug event to the audio thread for debugging. */ int cras_audio_thread_event_debug(); @@ -42,11 +32,6 @@ int cras_audio_thread_event_severe_underrun(); int cras_audio_thread_event_drop_samples(); /* - * Notifies the main thread when a device overrun event happens. - */ -int cras_audio_thread_event_dev_overrun(); - -/* * Initializes audio thread monitor and sets main thread callback. */ int cras_audio_thread_monitor_init(); diff --git a/cras/src/server/cras_bt_battery_provider.c b/cras/src/server/cras_bt_battery_provider.c deleted file mode 100644 index 13e6590f..00000000 --- a/cras/src/server/cras_bt_battery_provider.c +++ /dev/null @@ -1,371 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include <dbus/dbus.h> -#include <errno.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> - -#include "cras_bt_adapter.h" -#include "cras_bt_battery_provider.h" -#include "cras_bt_constants.h" -#include "cras_dbus_util.h" -#include "cras_observer.h" -#include "utlist.h" - -/* CRAS registers one battery provider to BlueZ, so we use a singleton. */ -static struct cras_bt_battery_provider battery_provider = { - .object_path = CRAS_DEFAULT_BATTERY_PROVIDER, - .interface = BLUEZ_INTERFACE_BATTERY_PROVIDER, - .conn = NULL, - .is_registered = false, - .observer = NULL, - .batteries = NULL, -}; - -static int cmp_battery_address(const struct cras_bt_battery *battery, - const char *address) -{ - return strcmp(battery->address, address); -} - -static void replace_colon_with_underscore(char *str) -{ - for (int i = 0; str[i]; i++) { - if (str[i] == ':') - str[i] = '_'; - } -} - -/* Converts address XX:XX:XX:XX:XX:XX to Battery Provider object path: - * /org/chromium/Cras/Bluetooth/BatteryProvider/XX_XX_XX_XX_XX_XX - */ -static char *address_to_battery_path(const char *address) -{ - char *object_path = malloc(strlen(CRAS_DEFAULT_BATTERY_PROVIDER) + - strlen(address) + 2); - - sprintf(object_path, "%s/%s", CRAS_DEFAULT_BATTERY_PROVIDER, address); - replace_colon_with_underscore(object_path); - - return object_path; -} - -/* Converts address XX:XX:XX:XX:XX:XX to device object path: - * /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX - */ -static char *address_to_device_path(const char *address) -{ - char *object_path = malloc(strlen(CRAS_DEFAULT_BATTERY_PREFIX) + - strlen(address) + 1); - - sprintf(object_path, "%s%s", CRAS_DEFAULT_BATTERY_PREFIX, address); - replace_colon_with_underscore(object_path); - - return object_path; -} - -static struct cras_bt_battery *battery_new(const char *address, uint32_t level) -{ - struct cras_bt_battery *battery; - - battery = calloc(1, sizeof(struct cras_bt_battery)); - battery->address = strdup(address); - battery->object_path = address_to_battery_path(address); - battery->device_path = address_to_device_path(address); - battery->level = level; - - return battery; -} - -static void battery_free(struct cras_bt_battery *battery) -{ - if (battery->address) - free(battery->address); - if (battery->object_path) - free(battery->object_path); - if (battery->device_path) - free(battery->device_path); - free(battery); -} - -static void populate_battery_properties(DBusMessageIter *iter, - const struct cras_bt_battery *battery) -{ - DBusMessageIter dict, entry, variant; - const char *property_percentage = "Percentage"; - const char *property_device = "Device"; - uint8_t level = battery->level; - - dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); - - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, - &entry); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, - &property_percentage); - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_BYTE_AS_STRING, &variant); - dbus_message_iter_append_basic(&variant, DBUS_TYPE_BYTE, &level); - dbus_message_iter_close_container(&entry, &variant); - dbus_message_iter_close_container(&dict, &entry); - - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, - &entry); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, - &property_device); - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_OBJECT_PATH_AS_STRING, - &variant); - dbus_message_iter_append_basic(&variant, DBUS_TYPE_OBJECT_PATH, - &battery->device_path); - dbus_message_iter_close_container(&entry, &variant); - dbus_message_iter_close_container(&dict, &entry); - - dbus_message_iter_close_container(iter, &dict); -} - -/* Creates a new battery object and exposes it on D-Bus. */ -static struct cras_bt_battery * -get_or_create_battery(struct cras_bt_battery_provider *provider, - const char *address, uint32_t level) -{ - struct cras_bt_battery *battery; - DBusMessage *msg; - DBusMessageIter iter, dict, entry; - - LL_SEARCH(provider->batteries, battery, address, cmp_battery_address); - - if (battery) - return battery; - - syslog(LOG_DEBUG, "Creating new battery for %s", address); - - battery = battery_new(address, level); - LL_APPEND(provider->batteries, battery); - - msg = dbus_message_new_signal(CRAS_DEFAULT_BATTERY_PROVIDER, - DBUS_INTERFACE_OBJECT_MANAGER, - DBUS_SIGNAL_INTERFACES_ADDED); - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, - &battery->object_path); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sa{sv}}", - &dict); - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, - &entry); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, - &provider->interface); - populate_battery_properties(&entry, battery); - dbus_message_iter_close_container(&dict, &entry); - dbus_message_iter_close_container(&iter, &dict); - - if (!dbus_connection_send(provider->conn, msg, NULL)) { - syslog(LOG_ERR, - "Error sending " DBUS_SIGNAL_INTERFACES_ADDED " signal"); - } - - dbus_message_unref(msg); - - return battery; -} - -/* Updates the level of a battery object and signals it on D-Bus. */ -static void -update_battery_level(const struct cras_bt_battery_provider *provider, - struct cras_bt_battery *battery, uint32_t level) -{ - DBusMessage *msg; - DBusMessageIter iter; - - if (battery->level == level) - return; - - battery->level = level; - - msg = dbus_message_new_signal(battery->object_path, - DBUS_INTERFACE_PROPERTIES, - DBUS_SIGNAL_PROPERTIES_CHANGED); - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, - &provider->interface); - populate_battery_properties(&iter, battery); - - if (!dbus_connection_send(provider->conn, msg, NULL)) { - syslog(LOG_ERR, "Error sending " DBUS_SIGNAL_PROPERTIES_CHANGED - " signal"); - } - - dbus_message_unref(msg); -} - -/* Invoked when HFP sends an alert about a battery value change. */ -static void on_bt_battery_changed(void *context, const char *address, - uint32_t level) -{ - struct cras_bt_battery_provider *provider = context; - - syslog(LOG_DEBUG, "Battery changed for address %s, level %d", address, - level); - - if (!provider->is_registered) { - syslog(LOG_WARNING, "Received battery level update while " - "battery provider is not registered"); - return; - } - - struct cras_bt_battery *battery = - get_or_create_battery(provider, address, level); - - update_battery_level(provider, battery, level); -} - -/* Invoked when we receive a D-Bus return of RegisterBatteryProvider from - * BlueZ. - */ -static void -cras_bt_on_battery_provider_registered(DBusPendingCall *pending_call, - void *data) -{ - DBusMessage *reply; - struct cras_bt_battery_provider *provider = data; - struct cras_observer_ops observer_ops; - - reply = dbus_pending_call_steal_reply(pending_call); - dbus_pending_call_unref(pending_call); - - if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { - syslog(LOG_ERR, "RegisterBatteryProvider returned error: %s", - dbus_message_get_error_name(reply)); - dbus_message_unref(reply); - return; - } - - syslog(LOG_INFO, "RegisterBatteryProvider succeeded"); - - provider->is_registered = true; - - memset(&observer_ops, 0, sizeof(observer_ops)); - observer_ops.bt_battery_changed = on_bt_battery_changed; - provider->observer = cras_observer_add(&observer_ops, provider); - - dbus_message_unref(reply); -} - -int cras_bt_register_battery_provider(DBusConnection *conn, - const struct cras_bt_adapter *adapter) -{ - const char *adapter_path; - DBusMessage *method_call; - DBusMessageIter message_iter; - DBusPendingCall *pending_call; - - if (battery_provider.is_registered) { - syslog(LOG_ERR, "Battery Provider already registered"); - return -EBUSY; - } - - if (battery_provider.conn) - dbus_connection_unref(battery_provider.conn); - - battery_provider.conn = conn; - dbus_connection_ref(battery_provider.conn); - - adapter_path = cras_bt_adapter_object_path(adapter); - method_call = dbus_message_new_method_call( - BLUEZ_SERVICE, adapter_path, - BLUEZ_INTERFACE_BATTERY_PROVIDER_MANAGER, - "RegisterBatteryProvider"); - if (!method_call) - return -ENOMEM; - - dbus_message_iter_init_append(method_call, &message_iter); - dbus_message_iter_append_basic(&message_iter, DBUS_TYPE_OBJECT_PATH, - &battery_provider.object_path); - - if (!dbus_connection_send_with_reply(conn, method_call, &pending_call, - DBUS_TIMEOUT_USE_DEFAULT)) { - dbus_message_unref(method_call); - return -ENOMEM; - } - - dbus_message_unref(method_call); - - if (!pending_call) - return -EIO; - - if (!dbus_pending_call_set_notify( - pending_call, cras_bt_on_battery_provider_registered, - &battery_provider, NULL)) { - dbus_pending_call_cancel(pending_call); - dbus_pending_call_unref(pending_call); - return -ENOMEM; - } - - return 0; -} - -/* Removes a battery object and signals the removal on D-Bus as well. */ -static void cleanup_battery(struct cras_bt_battery_provider *provider, - struct cras_bt_battery *battery) -{ - DBusMessage *msg; - DBusMessageIter iter, entry; - - if (!battery) - return; - - LL_DELETE(provider->batteries, battery); - - msg = dbus_message_new_signal(CRAS_DEFAULT_BATTERY_PROVIDER, - DBUS_INTERFACE_OBJECT_MANAGER, - DBUS_SIGNAL_INTERFACES_REMOVED); - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, - &battery->object_path); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, &entry); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, - &provider->interface); - dbus_message_iter_close_container(&iter, &entry); - - if (!dbus_connection_send(provider->conn, msg, NULL)) { - syslog(LOG_ERR, "Error sending " DBUS_SIGNAL_INTERFACES_REMOVED - " signal"); - } - - dbus_message_unref(msg); - - battery_free(battery); -} - -void cras_bt_battery_provider_reset() -{ - struct cras_bt_battery *battery; - - syslog(LOG_INFO, "Resetting battery provider"); - - if (!battery_provider.is_registered) - return; - - battery_provider.is_registered = false; - - LL_FOREACH (battery_provider.batteries, battery) { - cleanup_battery(&battery_provider, battery); - } - - if (battery_provider.conn) { - dbus_connection_unref(battery_provider.conn); - battery_provider.conn = NULL; - } - - if (battery_provider.observer) { - cras_observer_remove(battery_provider.observer); - battery_provider.observer = NULL; - } -} diff --git a/cras/src/server/cras_bt_battery_provider.h b/cras/src/server/cras_bt_battery_provider.h deleted file mode 100644 index 1998cd78..00000000 --- a/cras/src/server/cras_bt_battery_provider.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CRAS_BT_BATTERY_PROVIDER_H_ -#define CRAS_BT_BATTERY_PROVIDER_H_ - -#include <dbus/dbus.h> -#include <stdbool.h> - -#include "cras_bt_adapter.h" - -/* Object to represent a battery that is exposed to BlueZ. */ -struct cras_bt_battery { - char *address; - char *object_path; - char *device_path; - uint32_t level; - struct cras_bt_battery *next; -}; - -/* Object to register as battery provider so that bluetoothd will monitor - * battery objects that we expose. - */ -struct cras_bt_battery_provider { - const char *object_path; - const char *interface; - DBusConnection *conn; - bool is_registered; - struct cras_observer_client *observer; - struct cras_bt_battery *batteries; -}; - -/* Registers battery provider to bluetoothd. This is used when a Bluetooth - * adapter got enumerated. - * Args: - * conn - The D-Bus connection. - * adapter - The enumerated bluetooth adapter. - */ -int cras_bt_register_battery_provider(DBusConnection *conn, - const struct cras_bt_adapter *adapter); - -/* Resets internal state of battery provider. */ -void cras_bt_battery_provider_reset(); - -#endif /* CRAS_BT_BATTERY_PROVIDER_H_ */ diff --git a/cras/src/server/cras_bt_constants.h b/cras/src/server/cras_bt_constants.h index 318aecab..8d9ad5dd 100644 --- a/cras/src/server/cras_bt_constants.h +++ b/cras/src/server/cras_bt_constants.h @@ -6,16 +6,12 @@ #ifndef CRAS_BT_CONSTANTS_H_ #define CRAS_BT_CONSTANTS_H_ -#define BLUEZ_SERVICE "org.bluez" +#define BLUEZ_SERVICE "org.chromium.Bluetooth" #define BLUEZ_INTERFACE_ADAPTER "org.bluez.Adapter1" -#define BLUEZ_INTERFACE_BATTERY_PROVIDER "org.bluez.BatteryProvider1" -#define BLUEZ_INTERFACE_BATTERY_PROVIDER_MANAGER \ - "org.bluez.BatteryProviderManager1" #define BLUEZ_INTERFACE_DEVICE "org.bluez.Device1" #define BLUEZ_INTERFACE_MEDIA "org.bluez.Media1" #define BLUEZ_INTERFACE_MEDIA_ENDPOINT "org.bluez.MediaEndpoint1" -#define BLUEZ_INTERFACE_MEDIA_PLAYER "org.mpris.MediaPlayer2.Player" #define BLUEZ_INTERFACE_MEDIA_TRANSPORT "org.bluez.MediaTransport1" #define BLUEZ_INTERFACE_PLAYER "org.bluez.MediaPlayer1" #define BLUEZ_INTERFACE_PROFILE "org.bluez.Profile1" @@ -24,9 +20,6 @@ #ifndef DBUS_INTERFACE_OBJECT_MANAGER #define DBUS_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager" #endif -#define DBUS_SIGNAL_INTERFACES_ADDED "InterfacesAdded" -#define DBUS_SIGNAL_INTERFACES_REMOVED "InterfacesRemoved" -#define DBUS_SIGNAL_PROPERTIES_CHANGED "PropertiesChanged" /* UUIDs taken from lib/uuid.h in the BlueZ source */ #define HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb" @@ -43,29 +36,4 @@ #define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805f9b34fb" -/* Constants for CRAS BT player */ -#define CRAS_DEFAULT_PLAYER "/org/chromium/Cras/Bluetooth/DefaultPlayer" -/* The longest possible player playback status is "forward-seek" */ -#define CRAS_PLAYER_PLAYBACK_STATUS_SIZE_MAX 13 * sizeof(char) -#define CRAS_PLAYER_PLAYBACK_STATUS_DEFAULT "playing" -/* Neither BlueZ or the MRPIS specs limited the player identity max size, 128 - * should be large enough for most. - */ -#define CRAS_PLAYER_IDENTITY_SIZE_MAX 128 * sizeof(char) -#define CRAS_PLAYER_IDENTITY_DEFAULT "DefaultPlayer" -#define CRAS_PLAYER_METADATA_SIZE_MAX 128 * sizeof(char) - -#define CRAS_DEFAULT_BATTERY_PROVIDER \ - "/org/chromium/Cras/Bluetooth/BatteryProvider" -#define CRAS_DEFAULT_BATTERY_PREFIX "/org/bluez/hci0/dev_" - -/* Instead of letting CRAS obtain the A2DP streaming packet size (a.k.a. AVDTP - * MTU) from BlueZ Media Transport, force the packet size to the default L2CAP - * packet size. This prevent the audio peripheral device to negotiate a larger - * packet size and later failed to fulfill it and causing audio artifact. This - * defined constant is for experiment only and is put back behind a - * chrome://flag. - */ -#define A2DP_FIX_PACKET_SIZE 672 - #endif /* CRAS_BT_CONSTANTS_H_ */ diff --git a/cras/src/server/cras_bt_device.c b/cras/src/server/cras_bt_device.c index 6b06dd13..bc6b43d9 100644 --- a/cras/src/server/cras_bt_device.c +++ b/cras/src/server/cras_bt_device.c @@ -31,10 +31,8 @@ #include "cras_iodev.h" #include "cras_iodev_list.h" #include "cras_main_message.h" -#include "cras_server_metrics.h" #include "cras_system_state.h" #include "cras_tm.h" -#include "sfh.h" #include "utlist.h" /* @@ -54,15 +52,12 @@ static const unsigned int PROFILE_DROP_SUSPEND_DELAY_MS = 5000; */ static const unsigned int CONN_WATCH_PERIOD_MS = 2000; static const unsigned int CONN_WATCH_MAX_RETRIES = 30; - -/* This is used when a critical SCO failure happens and is worth scheduling a - * suspend in case for some reason BT headset stays connected in baseband and - * confuses user. - */ -static const unsigned int SCO_SUSPEND_DELAY_MS = 5000; +static const unsigned int PROFILE_CONN_RETRIES = 3; static const unsigned int CRAS_SUPPORTED_PROFILES = - CRAS_BT_DEVICE_PROFILE_A2DP_SINK | CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; + CRAS_BT_DEVICE_PROFILE_A2DP_SINK | + CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE | + CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY; /* Object to represent a general bluetooth device, and used to * associate with some CRAS modules if it supports audio. @@ -78,8 +73,6 @@ static const unsigned int CRAS_SUPPORTED_PROFILES = * connected - If this devices is connected. * connected_profiles - OR'ed all connected audio profiles. * profiles - OR'ed by all audio profiles this device supports. - * hidden_profiles - OR'ed by all audio profiles this device actually - * supports but is not scanned by BlueZ. * bt_iodevs - The pointer to the cras_iodevs of this device. * active_profile - The flag to indicate the active audio profile this * device is currently using. @@ -91,8 +84,6 @@ static const unsigned int CRAS_SUPPORTED_PROFILES = * profile switch. * sco_fd - The file descriptor of the SCO connection. * sco_ref_count - The reference counts of the SCO connection. - * suspend_reason - The reason code for why suspend is scheduled. - * stable_id - The unique and persistent id of this bt_device. */ struct cras_bt_device { DBusConnection *conn; @@ -104,9 +95,8 @@ struct cras_bt_device { int paired; int trusted; int connected; - unsigned int connected_profiles; - unsigned int profiles; - unsigned int hidden_profiles; + enum cras_bt_device_profile connected_profiles; + enum cras_bt_device_profile profiles; struct cras_iodev *bt_iodevs[CRAS_NUM_DIRECTIONS]; unsigned int active_profile; int use_hardware_volume; @@ -116,8 +106,6 @@ struct cras_bt_device { struct cras_timer *switch_profile_timer; int sco_fd; size_t sco_ref_count; - enum cras_bt_device_suspend_reason suspend_reason; - unsigned int stable_id; struct cras_bt_device *prev, *next; }; @@ -134,8 +122,7 @@ struct bt_device_msg { enum BT_DEVICE_COMMAND cmd; struct cras_bt_device *device; struct cras_iodev *dev; - unsigned int arg1; - unsigned int arg2; + unsigned int arg; }; static struct cras_bt_device *devices; @@ -177,9 +164,6 @@ struct cras_bt_device *cras_bt_device_create(DBusConnection *conn, free(device); return NULL; } - device->stable_id = - SuperFastHash(device->object_path, strlen(device->object_path), - strlen(device->object_path)); DL_APPEND(devices, device); @@ -349,11 +333,6 @@ const char *cras_bt_device_object_path(const struct cras_bt_device *device) return device->object_path; } -int cras_bt_device_get_stable_id(const struct cras_bt_device *device) -{ - return device->stable_id; -} - struct cras_bt_adapter * cras_bt_device_adapter(const struct cras_bt_device *device) { @@ -407,25 +386,6 @@ void cras_bt_device_append_iodev(struct cras_bt_device *device, } } -/* - * Sets the audio nodes to 'plugged' means UI can select it and open it - * for streams. Sets to 'unplugged' to hide these nodes from UI, when device - * disconnects in progress. - */ -static void bt_device_set_nodes_plugged(struct cras_bt_device *device, - int plugged) -{ - struct cras_iodev *iodev; - - iodev = device->bt_iodevs[CRAS_STREAM_INPUT]; - if (iodev) - cras_iodev_set_node_plugged(iodev->active_node, plugged); - - iodev = device->bt_iodevs[CRAS_STREAM_OUTPUT]; - if (iodev) - cras_iodev_set_node_plugged(iodev->active_node, plugged); -} - static void bt_device_switch_profile(struct cras_bt_device *device, struct cras_iodev *bt_iodev, int enable_dev); @@ -436,8 +396,6 @@ void cras_bt_device_rm_iodev(struct cras_bt_device *device, struct cras_iodev *bt_iodev; int rc; - bt_device_set_nodes_plugged(device, 0); - bt_iodev = device->bt_iodevs[iodev->direction]; if (bt_iodev) { unsigned try_profile; @@ -509,8 +467,6 @@ static void bt_device_remove_conflict(struct cras_bt_device *device) cras_a2dp_suspend_connected_device(connected); } -static void bt_device_conn_watch_cb(struct cras_timer *timer, void *arg); - int cras_bt_device_audio_gateway_initialized(struct cras_bt_device *device) { BTLOG(btlog, BT_AUDIO_GATEWAY_INIT, device->profiles, 0); @@ -519,23 +475,10 @@ int cras_bt_device_audio_gateway_initialized(struct cras_bt_device *device) device->connected_profiles |= (CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE | CRAS_BT_DEVICE_PROFILE_HSP_HEADSET); - /* If device connects HFP but not reporting correct UUID, manually add - * it to allow CRAS to enumerate audio node for it. We're seeing this - * behavior on qualification test software. */ - if (!cras_bt_device_supports_profile( - device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE)) { - unsigned int profiles = - device->profiles | CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; - cras_bt_device_set_supported_profiles(device, profiles); - device->hidden_profiles |= CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; - bt_device_conn_watch_cb(NULL, (void *)device); - } - return 0; } -unsigned int -cras_bt_device_get_active_profile(const struct cras_bt_device *device) +int cras_bt_device_get_active_profile(const struct cras_bt_device *device) { return device->active_profile; } @@ -585,19 +528,6 @@ static void cras_bt_device_log_profile(const struct cras_bt_device *device, } } -static void cras_bt_device_log_profiles(const struct cras_bt_device *device, - unsigned int profiles) -{ - unsigned int profile; - - while (profiles) { - /* Get the LSB of profiles */ - profile = profiles & -profiles; - cras_bt_device_log_profile(device, profile); - profiles ^= profile; - } -} - static int cras_bt_device_is_profile_connected(const struct cras_bt_device *device, enum cras_bt_device_profile profile) @@ -605,9 +535,8 @@ cras_bt_device_is_profile_connected(const struct cras_bt_device *device, return !!(device->connected_profiles & profile); } -static void -bt_device_schedule_suspend(struct cras_bt_device *device, unsigned int msec, - enum cras_bt_device_suspend_reason suspend_reason); +static void bt_device_schedule_suspend(struct cras_bt_device *device, + unsigned int msec); /* Callback used to periodically check if supported profiles are connected. */ static void bt_device_conn_watch_cb(struct cras_timer *timer, void *arg) @@ -615,10 +544,6 @@ static void bt_device_conn_watch_cb(struct cras_timer *timer, void *arg) struct cras_tm *tm; struct cras_bt_device *device = (struct cras_bt_device *)arg; int rc; - bool a2dp_supported; - bool a2dp_connected; - bool hfp_supported; - bool hfp_connected; BTLOG(btlog, BT_DEV_CONN_WATCH_CB, device->conn_watch_retries, device->profiles); @@ -628,34 +553,27 @@ static void bt_device_conn_watch_cb(struct cras_timer *timer, void *arg) if (!device->profiles) return; - a2dp_supported = cras_bt_device_supports_profile( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK); - a2dp_connected = cras_bt_device_is_profile_connected( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK); - hfp_supported = cras_bt_device_supports_profile( - device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); - hfp_connected = cras_bt_device_is_profile_connected( - device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); - - /* If not both A2DP and HFP are supported, simply wait for BlueZ - * to notify us about the new connection. - * Otherwise, when seeing one but not the other profile is connected, - * send message to ask BlueZ to connect the pending one. - */ - if (a2dp_supported && hfp_supported) { - /* If both a2dp and hfp are not connected, do nothing. BlueZ - * should be responsible to notify connection of one profile. - */ - if (!a2dp_connected && hfp_connected) + /* If A2DP is not ready, try connect it after a while. */ + if (cras_bt_device_supports_profile(device, + CRAS_BT_DEVICE_PROFILE_A2DP_SINK) && + !cras_bt_device_is_profile_connected( + device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK)) { + if (0 == device->conn_watch_retries % PROFILE_CONN_RETRIES) cras_bt_device_connect_profile(device->conn, device, A2DP_SINK_UUID); - if (a2dp_connected && !hfp_connected) - cras_bt_device_connect_profile(device->conn, device, - HFP_HF_UUID); + goto arm_retry_timer; } - if (a2dp_supported != a2dp_connected || hfp_supported != hfp_connected) + /* If HFP is not ready, try connect it after a while. */ + if (cras_bt_device_supports_profile( + device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE) && + !cras_bt_device_is_profile_connected( + device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE)) { + if (0 == device->conn_watch_retries % PROFILE_CONN_RETRIES) + cras_bt_device_connect_profile(device->conn, device, + HFP_HF_UUID); goto arm_retry_timer; + } /* Expected profiles are all connected, no more connection watch * callback will be scheduled. @@ -675,11 +593,9 @@ static void bt_device_conn_watch_cb(struct cras_timer *timer, void *arg) if (rc) { syslog(LOG_ERR, "Start audio gateway failed, rc %d", rc); - bt_device_schedule_suspend(device, 0, - HFP_AG_START_FAILURE); + bt_device_schedule_suspend(device, 0); } } - bt_device_set_nodes_plugged(device, 1); return; arm_retry_timer: @@ -693,7 +609,7 @@ arm_retry_timer: bt_device_conn_watch_cb, device); } else { syslog(LOG_ERR, "Connection watch timeout."); - bt_device_schedule_suspend(device, 0, CONN_WATCH_TIME_OUT); + bt_device_schedule_suspend(device, 0); } } @@ -710,24 +626,16 @@ cras_bt_device_start_new_conn_watch_timer(struct cras_bt_device *device) tm, CONN_WATCH_PERIOD_MS, bt_device_conn_watch_cb, device); } -static void bt_device_cancel_suspend(struct cras_bt_device *device); - void cras_bt_device_set_connected(struct cras_bt_device *device, int value) { struct cras_tm *tm = cras_system_state_get_tm(); - if (!device->connected && value) { - BTLOG(btlog, BT_DEV_CONNECTED, device->profiles, - device->stable_id); - } + if (device->connected || value) + BTLOG(btlog, BT_DEV_CONNECTED_CHANGE, device->profiles, value); if (device->connected && !value) { - BTLOG(btlog, BT_DEV_DISCONNECTED, device->profiles, - device->stable_id); cras_bt_profile_on_device_disconnected(device); - /* Device is disconnected, resets connected profiles and the - * suspend timer which scheduled earlier. */ + /* Device is disconnected, resets connected profiles. */ device->connected_profiles = 0; - bt_device_cancel_suspend(device); } device->connected = value; @@ -741,48 +649,47 @@ void cras_bt_device_set_connected(struct cras_bt_device *device, int value) void cras_bt_device_notify_profile_dropped(struct cras_bt_device *device, enum cras_bt_device_profile profile) { - device->connected_profiles &= ~profile; - - /* Do nothing if device already disconnected. */ - if (!device->connected) - return; + device->connected_profiles &= !profile; /* If any profile, a2dp or hfp/hsp, has dropped for some reason, * we shall make sure this device is fully disconnected within * given time so that user does not see a headset stay connected * but works with partial function. */ - bt_device_schedule_suspend(device, PROFILE_DROP_SUSPEND_DELAY_MS, - UNEXPECTED_PROFILE_DROP); + bt_device_schedule_suspend(device, PROFILE_DROP_SUSPEND_DELAY_MS); } -/* Refresh the list of known supported profiles. +/* + * Check if the uuid is of a new audio profile that isn't listed + * as supported by device. * Args: - * device - The BT device holding scanned profiles bitmap. - * profiles - The OR'ed profiles the device claims to support as is notified - * by BlueZ. + * device - The BT device holding supported profiles bitmap. + * uuid - UUID string from the device properties notified by BlueZ. * Returns: - * The OR'ed profiles that are both supported by Cras and isn't previously - * supported by the device. + * True if uuid is a new audio profiles not already supported by device. */ -int cras_bt_device_set_supported_profiles(struct cras_bt_device *device, - unsigned int profiles) +int cras_bt_device_add_supported_profiles(struct cras_bt_device *device, + const char *uuid) { - /* Do nothing if no new profiles. */ - if ((device->profiles & profiles) == profiles) + enum cras_bt_device_profile profile = + cras_bt_device_profile_from_uuid(uuid); + + if (profile == 0) return 0; - unsigned int new_profiles = profiles & ~device->profiles; + /* Do nothing if this profile is not new. */ + if (device->profiles & profile) + return 0; /* Log this event as we might need to re-intialize the BT audio nodes * if new audio profile is reported for already connected device. */ - if (device->connected && (new_profiles & CRAS_SUPPORTED_PROFILES)) + if (device->connected && (profile & CRAS_SUPPORTED_PROFILES)) BTLOG(btlog, BT_NEW_AUDIO_PROFILE_AFTER_CONNECT, - device->profiles, new_profiles); - cras_bt_device_log_profiles(device, new_profiles); - device->profiles = profiles | device->hidden_profiles; + device->profiles, profile); + device->profiles |= profile; + cras_bt_device_log_profile(device, profile); - return (new_profiles & CRAS_SUPPORTED_PROFILES); + return (profile & CRAS_SUPPORTED_PROFILES); } void cras_bt_device_update_properties(struct cras_bt_device *device, @@ -850,7 +757,6 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, "as") == 0 && strcmp(key, "UUIDs") == 0) { DBusMessageIter uuid_array_iter; - unsigned int profiles = 0; dbus_message_iter_recurse(&variant_iter, &uuid_array_iter); @@ -860,21 +766,22 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, dbus_message_iter_get_basic(&uuid_array_iter, &uuid); - profiles |= - cras_bt_device_profile_from_uuid(uuid); + + /* + * If updated properties includes new audio + * profile, and device is connected, we need + * to start connection watcher. This is needed + * because on some bluetooth device, supported + * profiles do not present when device + * interface is added and they are updated + * later. + */ + if (cras_bt_device_add_supported_profiles( + device, uuid)) + watch_needed = device->connected; dbus_message_iter_next(&uuid_array_iter); } - - /* If updated properties includes new audio profile and - * device is connected, we need to start connection - * watcher. This is needed because on some bluetooth - * devices, supported profiles do not present when - * device interface is added and they are updated later. - */ - if (cras_bt_device_set_supported_profiles(device, - profiles)) - watch_needed = device->connected; } dbus_message_iter_next(properties_array_iter); @@ -905,7 +812,7 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, } else if (strcmp(key, "Connected") == 0) { device->connected = 0; } else if (strcmp(key, "UUIDs") == 0) { - device->profiles = device->hidden_profiles; + device->profiles = 0; } dbus_message_iter_next(invalidated_array_iter); @@ -945,7 +852,6 @@ static int bt_address(const char *str, struct sockaddr *addr) static int apply_codec_settings(int fd, uint8_t codec) { struct bt_voice voice; - uint32_t pkt_status; memset(&voice, 0, sizeof(voice)); if (codec == HFP_CODEC_ID_CVSD) @@ -963,12 +869,6 @@ static int apply_codec_settings(int fd, uint8_t codec) syslog(LOG_ERR, "Failed to apply voice setting"); return -1; } - - pkt_status = 1; - if (setsockopt(fd, SOL_BLUETOOTH, BT_PKT_STATUS, &pkt_status, - sizeof(pkt_status))) { - syslog(LOG_ERR, "Failed to enable BT_PKT_STATUS"); - } return 0; } @@ -978,7 +878,7 @@ int cras_bt_device_sco_connect(struct cras_bt_device *device, int codec) struct sockaddr addr; struct cras_bt_adapter *adapter; struct timespec timeout = { 1, 0 }; - struct pollfd pollfd; + struct pollfd *pollfds; adapter = cras_bt_device_adapter(device); if (!adapter) { @@ -992,8 +892,6 @@ int cras_bt_device_sco_connect(struct cras_bt_device *device, int codec) if (sk < 0) { syslog(LOG_ERR, "Failed to create socket: %s (%d)", strerror(errno), errno); - cras_server_metrics_hfp_sco_connection_error( - CRAS_METRICS_SCO_SKT_OPEN_ERROR); return -errno; } @@ -1008,6 +906,9 @@ int cras_bt_device_sco_connect(struct cras_bt_device *device, int codec) /* Connect to remote in nonblocking mode */ fcntl(sk, F_SETFL, O_NONBLOCK); + pollfds = (struct pollfd *)malloc(sizeof(*pollfds)); + pollfds[0].fd = sk; + pollfds[0].events = POLLOUT; if (bt_address(cras_bt_device_address(device), &addr)) goto error; @@ -1020,35 +921,22 @@ int cras_bt_device_sco_connect(struct cras_bt_device *device, int codec) if (err && errno != EINPROGRESS) { syslog(LOG_ERR, "Failed to connect: %s (%d)", strerror(errno), errno); - cras_server_metrics_hfp_sco_connection_error( - CRAS_METRICS_SCO_SKT_CONNECT_ERROR); goto error; } - pollfd.fd = sk; - pollfd.events = POLLOUT; - - err = ppoll(&pollfd, 1, &timeout, NULL); + err = ppoll(pollfds, 1, &timeout, NULL); if (err <= 0) { syslog(LOG_ERR, "Connect SCO: poll for writable timeout"); - cras_server_metrics_hfp_sco_connection_error( - CRAS_METRICS_SCO_SKT_POLL_TIMEOUT); goto error; } - if (pollfd.revents & (POLLERR | POLLHUP)) { - syslog(LOG_ERR, - "SCO socket error, revents: %u. Suspend in %u seconds", - pollfd.revents, SCO_SUSPEND_DELAY_MS); - cras_server_metrics_hfp_sco_connection_error( - CRAS_METRICS_SCO_SKT_POLL_ERR_HUP); - bt_device_schedule_suspend(device, SCO_SUSPEND_DELAY_MS, - HFP_SCO_SOCKET_ERROR); + if (pollfds[0].revents & (POLLERR | POLLHUP)) { + syslog(LOG_ERR, "SCO socket error, revents: %u", + pollfds[0].revents); + bt_device_schedule_suspend(device, 0); goto error; } - cras_server_metrics_hfp_sco_connection_error( - CRAS_METRICS_SCO_SKT_SUCCESS); BTLOG(btlog, BT_SCO_CONNECT, 1, sk); return sk; @@ -1065,23 +953,12 @@ int cras_bt_device_sco_packet_size(struct cras_bt_device *device, struct sco_options so; socklen_t len = sizeof(so); struct cras_bt_adapter *adapter; - uint32_t wbs_pkt_len = 0; - socklen_t optlen = sizeof(wbs_pkt_len); adapter = cras_bt_adapter_get(device->adapter_obj_path); if (cras_bt_adapter_on_usb(adapter)) { - if (codec == HFP_CODEC_ID_MSBC) { - /* BT_SNDMTU and BT_RCVMTU return the same value. */ - if (getsockopt(sco_socket, SOL_BLUETOOTH, BT_SNDMTU, - &wbs_pkt_len, &optlen)) - syslog(LOG_ERR, "Failed to get BT_SNDMTU"); - - return (wbs_pkt_len > 0) ? wbs_pkt_len : - USB_MSBC_PKT_SIZE; - } else { - return USB_CVSD_PKT_SIZE; - } + return (codec == HFP_CODEC_ID_MSBC) ? USB_MSBC_PKT_SIZE : + USB_CVSD_PKT_SIZE; } /* For non-USB cases, query the SCO MTU from driver. */ @@ -1111,8 +988,7 @@ int cras_bt_device_get_use_hardware_volume(struct cras_bt_device *device) static void init_bt_device_msg(struct bt_device_msg *msg, enum BT_DEVICE_COMMAND cmd, struct cras_bt_device *device, - struct cras_iodev *dev, unsigned int arg1, - unsigned int arg2) + struct cras_iodev *dev, unsigned int arg) { memset(msg, 0, sizeof(*msg)); msg->header.type = CRAS_MAIN_BT; @@ -1120,8 +996,7 @@ static void init_bt_device_msg(struct bt_device_msg *msg, msg->cmd = cmd; msg->device = device; msg->dev = dev; - msg->arg1 = arg1; - msg->arg2 = arg2; + msg->arg = arg; } int cras_bt_device_cancel_suspend(struct cras_bt_device *device) @@ -1129,20 +1004,19 @@ int cras_bt_device_cancel_suspend(struct cras_bt_device *device) struct bt_device_msg msg; int rc; - init_bt_device_msg(&msg, BT_DEVICE_CANCEL_SUSPEND, device, NULL, 0, 0); + init_bt_device_msg(&msg, BT_DEVICE_CANCEL_SUSPEND, device, NULL, 0); rc = cras_main_message_send((struct cras_main_message *)&msg); return rc; } -int cras_bt_device_schedule_suspend( - struct cras_bt_device *device, unsigned int msec, - enum cras_bt_device_suspend_reason suspend_reason) +int cras_bt_device_schedule_suspend(struct cras_bt_device *device, + unsigned int msec) { struct bt_device_msg msg; int rc; - init_bt_device_msg(&msg, BT_DEVICE_SCHEDULE_SUSPEND, device, NULL, msec, - suspend_reason); + init_bt_device_msg(&msg, BT_DEVICE_SCHEDULE_SUSPEND, device, NULL, + msec); rc = cras_main_message_send((struct cras_main_message *)&msg); return rc; } @@ -1176,7 +1050,7 @@ int cras_bt_device_switch_profile_enable_dev(struct cras_bt_device *device, int rc; init_bt_device_msg(&msg, BT_DEVICE_SWITCH_PROFILE_ENABLE_DEV, device, - bt_iodev, 0, 0); + bt_iodev, 0); rc = cras_main_message_send((struct cras_main_message *)&msg); return rc; } @@ -1187,8 +1061,7 @@ int cras_bt_device_switch_profile(struct cras_bt_device *device, struct bt_device_msg msg; int rc; - init_bt_device_msg(&msg, BT_DEVICE_SWITCH_PROFILE, device, bt_iodev, 0, - 0); + init_bt_device_msg(&msg, BT_DEVICE_SWITCH_PROFILE, device, bt_iodev, 0); rc = cras_main_message_send((struct cras_main_message *)&msg); return rc; } @@ -1277,45 +1150,21 @@ static void bt_device_suspend_cb(struct cras_timer *timer, void *arg) struct cras_bt_device *device = (struct cras_bt_device *)arg; BTLOG(btlog, BT_DEV_SUSPEND_CB, device->profiles, - device->suspend_reason); + device->connected_profiles); device->suspend_timer = NULL; - /* Error log the reason so we can track them in user reports. */ - switch (device->suspend_reason) { - case A2DP_LONG_TX_FAILURE: - syslog(LOG_ERR, "Suspend dev: A2DP long Tx failure"); - break; - case A2DP_TX_FATAL_ERROR: - syslog(LOG_ERR, "Suspend dev: A2DP Tx fatal error"); - break; - case CONN_WATCH_TIME_OUT: - syslog(LOG_ERR, "Suspend dev: Conn watch times out"); - break; - case HFP_SCO_SOCKET_ERROR: - syslog(LOG_ERR, "Suspend dev: SCO socket error"); - break; - case HFP_AG_START_FAILURE: - syslog(LOG_ERR, "Suspend dev: HFP AG start failure"); - break; - case UNEXPECTED_PROFILE_DROP: - syslog(LOG_ERR, "Suspend dev: Unexpected profile drop"); - break; - } - cras_a2dp_suspend_connected_device(device); cras_hfp_ag_suspend_connected_device(device); cras_bt_device_disconnect(device->conn, device); } -static void -bt_device_schedule_suspend(struct cras_bt_device *device, unsigned int msec, - enum cras_bt_device_suspend_reason suspend_reason) +static void bt_device_schedule_suspend(struct cras_bt_device *device, + unsigned int msec) { struct cras_tm *tm = cras_system_state_get_tm(); if (device->suspend_timer) return; - device->suspend_reason = suspend_reason; device->suspend_timer = cras_tm_create_timer(tm, msec, bt_device_suspend_cb, device); } @@ -1351,8 +1200,7 @@ static void bt_device_process_msg(struct cras_main_message *msg, void *arg) bt_device_switch_profile(bt_msg->device, bt_msg->dev, 1); break; case BT_DEVICE_SCHEDULE_SUSPEND: - bt_device_schedule_suspend(bt_msg->device, bt_msg->arg1, - bt_msg->arg2); + bt_device_schedule_suspend(bt_msg->device, bt_msg->arg); break; case BT_DEVICE_CANCEL_SUSPEND: bt_device_cancel_suspend(bt_msg->device); diff --git a/cras/src/server/cras_bt_device.h b/cras/src/server/cras_bt_device.h index 9d3a2b9e..904a5f47 100644 --- a/cras/src/server/cras_bt_device.h +++ b/cras/src/server/cras_bt_device.h @@ -13,16 +13,6 @@ struct cras_bt_device; struct cras_iodev; struct cras_timer; -/* All the reasons for when CRAS schedule a suspend to BT device. */ -enum cras_bt_device_suspend_reason { - A2DP_LONG_TX_FAILURE, - A2DP_TX_FATAL_ERROR, - CONN_WATCH_TIME_OUT, - HFP_SCO_SOCKET_ERROR, - HFP_AG_START_FAILURE, - UNEXPECTED_PROFILE_DROP, -}; - enum cras_bt_device_profile { CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE = (1 << 0), CRAS_BT_DEVICE_PROFILE_A2DP_SINK = (1 << 1), @@ -50,10 +40,6 @@ void cras_bt_device_reset(); struct cras_bt_device *cras_bt_device_get(const char *object_path); const char *cras_bt_device_object_path(const struct cras_bt_device *device); - -/* Gets the stable id of given cras_bt_device. */ -int cras_bt_device_get_stable_id(const struct cras_bt_device *device); - struct cras_bt_adapter * cras_bt_device_adapter(const struct cras_bt_device *device); const char *cras_bt_device_address(const struct cras_bt_device *device); @@ -67,8 +53,8 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, DBusMessageIter *invalidated_array_iter); /* Updates the supported profiles on dev. Expose for unit test. */ -int cras_bt_device_set_supported_profiles(struct cras_bt_device *device, - unsigned int profiles); +int cras_bt_device_add_supported_profiles(struct cras_bt_device *device, + const char *uuid); /* Checks if profile is claimed supported by the device. */ int cras_bt_device_supports_profile(const struct cras_bt_device *device, @@ -137,8 +123,7 @@ void cras_bt_device_rm_iodev(struct cras_bt_device *device, struct cras_iodev *iodev); /* Gets the active profile of the bt device. */ -unsigned int -cras_bt_device_get_active_profile(const struct cras_bt_device *device); +int cras_bt_device_get_active_profile(const struct cras_bt_device *device); /* Sets the active profile of the bt device. */ void cras_bt_device_set_active_profile(struct cras_bt_device *device, @@ -185,9 +170,8 @@ void cras_bt_device_a2dp_configured(struct cras_bt_device *device); int cras_bt_device_cancel_suspend(struct cras_bt_device *device); /* Schedules device to suspend after given delay. */ -int cras_bt_device_schedule_suspend( - struct cras_bt_device *device, unsigned int msec, - enum cras_bt_device_suspend_reason suspend_reason); +int cras_bt_device_schedule_suspend(struct cras_bt_device *device, + unsigned int msec); /* Notifies bt device that audio gateway is initialized. * Args: diff --git a/cras/src/server/cras_bt_io.c b/cras/src/server/cras_bt_io.c index acdca809..637f0a79 100644 --- a/cras/src/server/cras_bt_io.c +++ b/cras/src/server/cras_bt_io.c @@ -8,7 +8,6 @@ #include "cras_bt_io.h" #include "cras_bt_device.h" -#include "cras_hfp_iodev.h" #include "cras_utf8.h" #include "cras_iodev.h" #include "cras_iodev_list.h" @@ -70,7 +69,7 @@ static struct cras_ionode *add_profile_dev(struct cras_iodev *bt_iodev, n->base.type = CRAS_NODE_TYPE_BLUETOOTH; n->base.volume = 100; n->base.stable_id = dev->info.stable_id; - n->base.capture_gain = 0; + n->base.max_software_gain = 0; gettimeofday(&n->base.plugged_time, NULL); strcpy(n->base.name, dev->info.name); @@ -106,16 +105,6 @@ static void bt_switch_to_profile(struct cras_bt_device *device, } } -/* Switches the active profile to A2DP if it can. */ -static void bt_possibly_switch_to_a2dp(struct bt_io *btio) -{ - if (!cras_bt_device_has_a2dp(btio->device)) - return; - cras_bt_device_set_active_profile(btio->device, - CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); - cras_bt_device_switch_profile(btio->device, &btio->base); -} - /* Checks if bt device is active for the given profile. */ static int device_using_profile(struct cras_bt_device *device, @@ -136,7 +125,6 @@ static int open_dev(struct cras_iodev *iodev) { struct bt_io *btio = (struct bt_io *)iodev; struct cras_iodev *dev = active_profile_dev(iodev); - int rc; /* Force to use HFP if opening input dev. */ if (device_using_profile(btio->device, @@ -148,16 +136,8 @@ static int open_dev(struct cras_iodev *iodev) return -EAGAIN; } - if (dev && dev->open_dev) { - rc = dev->open_dev(dev); - if (rc == 0) - return 0; - - /* If input iodev open fails, switch profile back to A2DP. */ - if (iodev->direction == CRAS_STREAM_INPUT) - bt_possibly_switch_to_a2dp(btio); - return rc; - } + if (dev && dev->open_dev) + return dev->open_dev(dev); return 0; } @@ -170,6 +150,12 @@ static int update_supported_formats(struct cras_iodev *iodev) if (!dev) return -EINVAL; + if (dev->format == NULL) { + dev->format = (struct cras_audio_format *)malloc( + sizeof(*dev->format)); + *dev->format = *iodev->format; + } + if (dev->update_supported_formats) { rc = dev->update_supported_formats(dev); if (rc) @@ -200,9 +186,6 @@ static int update_supported_formats(struct cras_iodev *iodev) (length + 1) * sizeof(*iodev->supported_formats)); for (i = 0; i < length + 1; i++) iodev->supported_formats[i] = dev->supported_formats[i]; - - /* Record max supported channels into cras_iodev_info. */ - iodev->info.max_supported_channels = dev->info.max_supported_channels; return 0; } @@ -214,13 +197,7 @@ static int configure_dev(struct cras_iodev *iodev) return -EINVAL; /* Fill back the format iodev is using. */ - if (dev->format == NULL) { - dev->format = (struct cras_audio_format *)malloc( - sizeof(*dev->format)); - if (!dev->format) - return -ENOMEM; - *dev->format = *iodev->format; - } + *dev->format = *iodev->format; rc = dev->configure_dev(dev); if (rc) @@ -228,11 +205,6 @@ static int configure_dev(struct cras_iodev *iodev) iodev->buffer_size = dev->buffer_size; iodev->min_buffer_level = dev->min_buffer_level; - if (dev->start) - dev->state = CRAS_IODEV_STATE_OPEN; - else - dev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; - return 0; } @@ -244,21 +216,22 @@ static int close_dev(struct cras_iodev *iodev) if (!dev) return -EINVAL; - /* If input iodev is in open state and being closed, switch profile - * from HFP to A2DP. */ - if (cras_iodev_is_open(iodev) && - device_using_profile( + /* Force back to A2DP if closing HFP. */ + if (device_using_profile( btio->device, CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY | CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY) && - (iodev->direction == CRAS_STREAM_INPUT)) - bt_possibly_switch_to_a2dp(btio); + iodev->direction == CRAS_STREAM_INPUT && + cras_bt_device_has_a2dp(btio->device)) { + cras_bt_device_set_active_profile( + btio->device, CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); + cras_bt_device_switch_profile(btio->device, iodev); + } rc = dev->close_dev(dev); if (rc < 0) return rc; cras_iodev_free_format(iodev); - dev->state = CRAS_IODEV_STATE_CLOSE; return 0; } @@ -331,7 +304,6 @@ static void update_active_node(struct cras_iodev *iodev, unsigned node_idx, struct cras_ionode *node; struct bt_node *active = (struct bt_node *)iodev->active_node; struct cras_iodev *dev; - int rc; if (device_using_profile(btio->device, active->profile)) goto leave; @@ -355,38 +327,11 @@ leave: dev = active_profile_dev(iodev); if (dev && dev->update_active_node) dev->update_active_node(dev, node_idx, dev_enabled); - - /* Update supported formats here to get the supported formats from the - * new updated active profile dev. - */ - rc = update_supported_formats(iodev); - if (rc) { - syslog(LOG_ERR, "Failed to update supported formats, rc=%d", - rc); - } -} - -static int output_underrun(struct cras_iodev *iodev) -{ - struct cras_iodev *dev = active_profile_dev(iodev); - if (!dev) - return -EINVAL; - - if (dev->output_underrun) { - dev->min_cb_level = iodev->min_cb_level; - dev->max_cb_level = iodev->max_cb_level; - dev->buffer_size = iodev->buffer_size; - return dev->output_underrun(dev); - } - - return 0; } static int no_stream(struct cras_iodev *iodev, int enable) { struct cras_iodev *dev = active_profile_dev(iodev); - int rc; - if (!dev) return -EINVAL; @@ -401,15 +346,8 @@ static int no_stream(struct cras_iodev *iodev, int enable) dev->min_cb_level = iodev->min_cb_level; dev->max_cb_level = iodev->max_cb_level; dev->buffer_size = iodev->buffer_size; - rc = dev->no_stream(dev, enable); - if (rc < 0) - return rc; + return dev->no_stream(dev, enable); } - if (enable) - dev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; - else - dev->state = CRAS_IODEV_STATE_NORMAL_RUN; - return 0; } @@ -428,45 +366,14 @@ static int is_free_running(const struct cras_iodev *iodev) static int start(const struct cras_iodev *iodev) { struct cras_iodev *dev = active_profile_dev(iodev); - int rc; - if (!dev) return -EINVAL; - if (dev->start) { - rc = dev->start(dev); - if (rc) - return rc; - } - dev->state = CRAS_IODEV_STATE_NORMAL_RUN; + if (dev->start) + return dev->start(dev); return 0; } -static unsigned int frames_to_play_in_sleep(struct cras_iodev *iodev, - unsigned int *hw_level, - struct timespec *hw_tstamp) -{ - struct cras_iodev *dev = active_profile_dev(iodev); - if (!dev || !dev->frames_to_play_in_sleep) - return cras_iodev_default_frames_to_play_in_sleep( - iodev, hw_level, hw_tstamp); - - return dev->frames_to_play_in_sleep(dev, hw_level, hw_tstamp); -} - -static int get_valid_frames(struct cras_iodev *iodev, - struct timespec *hw_tstamp) -{ - struct cras_iodev *dev = active_profile_dev(iodev); - if (!dev) - return -EINVAL; - - if (dev->get_valid_frames) - return dev->get_valid_frames(dev, hw_tstamp); - - return cras_iodev_frames_queued(iodev, hw_tstamp); -} - struct cras_iodev *cras_bt_io_create(struct cras_bt_device *device, struct cras_iodev *dev, enum cras_bt_device_profile profile) @@ -501,11 +408,8 @@ struct cras_iodev *cras_bt_io_create(struct cras_bt_device *device, iodev->update_supported_formats = update_supported_formats; iodev->update_active_node = update_active_node; iodev->no_stream = no_stream; - iodev->output_underrun = output_underrun; iodev->is_free_running = is_free_running; - iodev->get_valid_frames = get_valid_frames; iodev->start = start; - iodev->frames_to_play_in_sleep = frames_to_play_in_sleep; /* Input also checks |software_volume_needed| flag for using software * gain. Keep it as false for BT input. @@ -518,30 +422,23 @@ struct cras_iodev *cras_bt_io_create(struct cras_bt_device *device, iodev->set_volume = set_bt_volume; } - /* Create the fake node so it's the only node exposed to UI, and - * point it to the first profile dev. */ + /* Create the dummy node set to plugged so it's the only node exposed + * to UI, and point it to the first profile dev. */ active = (struct bt_node *)calloc(1, sizeof(*active)); if (!active) - goto error; + return NULL; active->base.dev = iodev; active->base.idx = btio->next_node_id++; - active->base.type = dev->active_node->type; + active->base.type = CRAS_NODE_TYPE_BLUETOOTH; active->base.volume = 100; - active->base.stable_id = cras_bt_device_get_stable_id(device); - active->base.ui_gain_scaler = 1.0f; - /* - * If the same headset is connected in wideband mode, we shall assign - * a separate stable_id so the node priority/preference mechanism in - * Chrome UI doesn't break. - */ - if ((active->base.type == CRAS_NODE_TYPE_BLUETOOTH) && - (dev->direction == CRAS_STREAM_INPUT)) - active->base.stable_id = - SuperFastHash((const char *)&active->base.type, - sizeof(active->base.type), - active->base.stable_id); + active->base.plugged = 1; + active->base.stable_id = + SuperFastHash(cras_bt_device_object_path(device), + strlen(cras_bt_device_object_path(device)), + strlen(cras_bt_device_object_path(device))); active->profile = profile; active->profile_dev = dev; + gettimeofday(&active->base.plugged_time, NULL); strcpy(active->base.name, dev->info.name); /* The node name exposed to UI should be a valid UTF8 string. */ if (!is_utf8_string(active->base.name)) @@ -650,20 +547,6 @@ int cras_bt_io_on_profile(struct cras_iodev *bt_iodev, return !!(profile & btnode->profile); } -enum cras_bt_device_profile -cras_bt_io_profile_to_log(struct cras_iodev *bt_iodev) -{ - struct bt_node *btnode = (struct bt_node *)bt_iodev->active_node; - - if (btnode->profile & CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE) - return CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE; - - if (hfp_iodev_is_hsp(btnode->profile_dev)) - return CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY; - else - return CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY; -} - unsigned int cras_bt_io_try_remove(struct cras_iodev *bt_iodev, struct cras_iodev *dev) { diff --git a/cras/src/server/cras_bt_io.h b/cras/src/server/cras_bt_io.h index a867afd9..b833cd9e 100644 --- a/cras/src/server/cras_bt_io.h +++ b/cras/src/server/cras_bt_io.h @@ -30,12 +30,6 @@ int cras_bt_io_append(struct cras_iodev *bt_iodev, struct cras_iodev *dev, int cras_bt_io_on_profile(struct cras_iodev *bt_iodev, enum cras_bt_device_profile profile); -/* Returns A2DP, HFP or HSP that this bt_iodev is running for. - * Do NOT use this function except for logging. - */ -enum cras_bt_device_profile -cras_bt_io_profile_to_log(struct cras_iodev *bt_iodev); - /* Dry-run the profile device removal from bt_iodev. * Returns: * 0 if the bt_iodev will be empty and should to be destroied diff --git a/cras/src/server/cras_bt_manager.c b/cras/src/server/cras_bt_manager.c index a7103406..3a3ea4ae 100644 --- a/cras/src/server/cras_bt_manager.c +++ b/cras/src/server/cras_bt_manager.c @@ -19,7 +19,6 @@ #include "cras_bt_player.h" #include "cras_bt_profile.h" #include "cras_bt_transport.h" -#include "cras_bt_battery_provider.h" #include "utlist.h" struct cras_bt_event_log *btlog; @@ -42,6 +41,9 @@ static void cras_bt_interface_added(DBusConnection *conn, if (adapter) { cras_bt_adapter_update_properties( adapter, properties_array_iter, NULL); + cras_bt_register_endpoints(conn, adapter); + cras_bt_register_player(conn, adapter); + cras_bt_register_profiles(conn); syslog(LOG_INFO, "Bluetooth Adapter: %s added", cras_bt_adapter_address(adapter)); @@ -52,28 +54,6 @@ static void cras_bt_interface_added(DBusConnection *conn, } } - } else if (strcmp(interface_name, BLUEZ_INTERFACE_MEDIA) == 0) { - struct cras_bt_adapter *adapter; - - adapter = cras_bt_adapter_get(object_path); - if (adapter) { - cras_bt_register_endpoints(conn, adapter); - cras_bt_register_player(conn, adapter); - - syslog(LOG_INFO, - "Bluetooth Endpoint and/or Player: %s added", - cras_bt_adapter_address(adapter)); - } else { - syslog(LOG_WARNING, - "Failed to create Bluetooth Endpoint and/or Player: %s", - object_path); - } - - } else if (strcmp(interface_name, BLUEZ_PROFILE_MGMT_INTERFACE) == 0) { - cras_bt_register_profiles(conn); - - syslog(LOG_INFO, "Bluetooth Profile Manager added"); - } else if (strcmp(interface_name, BLUEZ_INTERFACE_DEVICE) == 0) { struct cras_bt_device *device; @@ -121,32 +101,6 @@ static void cras_bt_interface_added(DBusConnection *conn, object_path); } } - } else if (strcmp(interface_name, - BLUEZ_INTERFACE_BATTERY_PROVIDER_MANAGER) == 0) { - struct cras_bt_adapter *adapter; - int ret; - - syslog(LOG_INFO, - "Bluetooth Battery Provider Manager available"); - - adapter = cras_bt_adapter_get(object_path); - if (adapter) { - syslog(LOG_INFO, - "Registering Battery Provider for adapter %s", - cras_bt_adapter_address(adapter)); - ret = cras_bt_register_battery_provider(conn, adapter); - if (ret != 0) { - syslog(LOG_ERR, - "Error registering Battery Provider " - "for adapter %s: %s", - cras_bt_adapter_address(adapter), - strerror(-ret)); - } - } else { - syslog(LOG_WARNING, - "Adapter not available when trying to create " - "Battery Provider"); - } } } @@ -185,10 +139,6 @@ static void cras_bt_interface_removed(DBusConnection *conn, cras_bt_transport_object_path(transport)); cras_bt_transport_remove(transport); } - } else if (strcmp(interface_name, - BLUEZ_INTERFACE_BATTERY_PROVIDER_MANAGER) == 0) { - syslog(LOG_INFO, "Bluetooth Battery Provider Manager removed"); - cras_bt_battery_provider_reset(); } } diff --git a/cras/src/server/cras_bt_player.c b/cras/src/server/cras_bt_player.c index 446cd916..13343a65 100644 --- a/cras/src/server/cras_bt_player.c +++ b/cras/src/server/cras_bt_player.c @@ -4,18 +4,17 @@ */ #include <dbus/dbus.h> #include <errno.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> #include <syslog.h> -#include "cras_bt_adapter.h" #include "cras_bt_constants.h" +#include "cras_bt_adapter.h" #include "cras_bt_player.h" #include "cras_dbus_util.h" -#include "cras_utf8.h" #include "utlist.h" +#define CRAS_DEFAULT_PLAYER "/org/chromium/Cras/Bluetooth/DefaultPlayer" + static void cras_bt_on_player_registered(DBusPendingCall *pending_call, void *data) { @@ -110,11 +109,10 @@ static int cras_bt_add_player(DBusConnection *conn, */ static struct cras_bt_player player = { .object_path = CRAS_DEFAULT_PLAYER, - .playback_status = NULL, - .identity = NULL, + .playback_status = "playing", + .identity = "DefaultPlayer", .loop_status = "None", .shuffle = 0, - .metadata = NULL, .position = 0, .can_go_next = 0, .can_go_prev = 0, @@ -136,123 +134,6 @@ static DBusHandlerResult cras_bt_player_handle_message(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static struct cras_bt_player_metadata *cras_bt_player_metadata_init() -{ - struct cras_bt_player_metadata *metadata = - malloc(sizeof(struct cras_bt_player_metadata)); - metadata->title = calloc(1, CRAS_PLAYER_METADATA_SIZE_MAX); - metadata->album = calloc(1, CRAS_PLAYER_METADATA_SIZE_MAX); - metadata->artist = calloc(1, CRAS_PLAYER_METADATA_SIZE_MAX); - metadata->length = 0; - - return metadata; -} - -static void cras_bt_player_init() -{ - player.playback_status = malloc(CRAS_PLAYER_PLAYBACK_STATUS_SIZE_MAX); - player.identity = malloc(CRAS_PLAYER_IDENTITY_SIZE_MAX); - - strcpy(player.playback_status, CRAS_PLAYER_PLAYBACK_STATUS_DEFAULT); - strcpy(player.identity, CRAS_PLAYER_IDENTITY_DEFAULT); - player.position = 0; - - player.metadata = cras_bt_player_metadata_init(); -} - -static void cras_bt_player_append_metadata_artist(DBusMessageIter *iter, - const char *artist) -{ - DBusMessageIter dict, varient, array; - const char *artist_key = "xesam:artist"; - - dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, - &dict); - dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &artist_key); - dbus_message_iter_open_container( - &dict, DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &varient); - dbus_message_iter_open_container(&varient, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, &array); - dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &artist); - dbus_message_iter_close_container(&varient, &array); - dbus_message_iter_close_container(&dict, &varient); - dbus_message_iter_close_container(iter, &dict); -} - -static void cras_bt_player_append_metadata(DBusMessageIter *iter, - const char *title, - const char *artist, - const char *album, - dbus_int64_t length) -{ - DBusMessageIter varient, array; - dbus_message_iter_open_container( - iter, DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &varient); - dbus_message_iter_open_container( - &varient, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &array); - if (!is_utf8_string(title)) { - syslog(LOG_INFO, "Non-utf8 title: %s", title); - title = ""; - } - if (!is_utf8_string(album)) { - syslog(LOG_INFO, "Non-utf8 album: %s", album); - album = ""; - } - if (!is_utf8_string(artist)) { - syslog(LOG_INFO, "Non-utf8 artist: %s", artist); - artist = ""; - } - - append_key_value(&array, "xesam:title", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, &title); - append_key_value(&array, "xesam:album", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, &album); - append_key_value(&array, "mpris:length", DBUS_TYPE_INT64, - DBUS_TYPE_INT64_AS_STRING, &length); - cras_bt_player_append_metadata_artist(&array, artist); - - dbus_message_iter_close_container(&varient, &array); - dbus_message_iter_close_container(iter, &varient); -} - -static bool cras_bt_player_parse_metadata(const char *title, const char *album, - const char *artist, - const dbus_int64_t length) -{ - bool require_update = false; - - if (title && strcmp(player.metadata->title, title)) { - snprintf(player.metadata->title, CRAS_PLAYER_METADATA_SIZE_MAX, - "%s", title); - require_update = true; - } - if (artist && strcmp(player.metadata->artist, artist)) { - snprintf(player.metadata->artist, CRAS_PLAYER_METADATA_SIZE_MAX, - "%s", artist); - require_update = true; - } - if (album && strcmp(player.metadata->album, album)) { - snprintf(player.metadata->album, CRAS_PLAYER_METADATA_SIZE_MAX, - "%s", album); - require_update = true; - } - if (length && player.metadata->length != length) { - player.metadata->length = length; - require_update = true; - } - - return require_update; -} - int cras_bt_player_create(DBusConnection *conn) { static const DBusObjectPathVTable player_vtable = { @@ -265,7 +146,6 @@ int cras_bt_player_create(DBusConnection *conn) dbus_error_init(&dbus_error); - cras_bt_player_init(); if (!dbus_connection_register_object_path( conn, player.object_path, &player_vtable, &dbus_error)) { syslog(LOG_ERR, "Cannot register player %s", @@ -286,201 +166,3 @@ int cras_bt_register_player(DBusConnection *conn, { return cras_bt_add_player(conn, adapter, &player); } - -int cras_bt_player_update_playback_status(DBusConnection *conn, - const char *status) -{ - DBusMessage *msg; - DBusMessageIter iter, dict; - const char *playerInterface = BLUEZ_INTERFACE_MEDIA_PLAYER; - - if (!player.playback_status) - return -ENXIO; - - /* Verify the string value matches one of the possible status defined in - * bluez/profiles/audio/avrcp.c - */ - if (strcasecmp(status, "stopped") != 0 && - strcasecmp(status, "playing") != 0 && - strcasecmp(status, "paused") != 0 && - strcasecmp(status, "forward-seek") != 0 && - strcasecmp(status, "reverse-seek") != 0 && - strcasecmp(status, "error") != 0) - return -EINVAL; - - if (!strcasecmp(player.playback_status, status)) - return 0; - - strcpy(player.playback_status, status); - - msg = dbus_message_new_signal(CRAS_DEFAULT_PLAYER, - DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - if (!msg) - return -ENOMEM; - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, - &playerInterface); - dbus_message_iter_open_container( - &iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &dict); - append_key_value(&dict, "PlaybackStatus", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, &status); - dbus_message_iter_close_container(&iter, &dict); - - if (!dbus_connection_send(conn, msg, NULL)) { - dbus_message_unref(msg); - return -ENOMEM; - } - - dbus_message_unref(msg); - return 0; -} - -int cras_bt_player_update_identity(DBusConnection *conn, const char *identity) -{ - DBusMessage *msg; - DBusMessageIter iter, dict; - const char *playerInterface = BLUEZ_INTERFACE_MEDIA_PLAYER; - - if (!player.identity) - return -ENXIO; - - if (!identity) - return -EINVAL; - - if (!is_utf8_string(identity)) { - syslog(LOG_INFO, "Non-utf8 identity: %s", identity); - identity = ""; - } - - if (!strcasecmp(player.identity, identity)) - return 0; - - strcpy(player.identity, identity); - - msg = dbus_message_new_signal(CRAS_DEFAULT_PLAYER, - DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - if (!msg) - return -ENOMEM; - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, - &playerInterface); - dbus_message_iter_open_container( - &iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &dict); - append_key_value(&dict, "Identity", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, &identity); - dbus_message_iter_close_container(&iter, &dict); - - if (!dbus_connection_send(conn, msg, NULL)) { - dbus_message_unref(msg); - return -ENOMEM; - } - - dbus_message_unref(msg); - return 0; -} - -int cras_bt_player_update_position(DBusConnection *conn, - const dbus_int64_t position) -{ - DBusMessage *msg; - DBusMessageIter iter, dict; - const char *playerInterface = BLUEZ_INTERFACE_MEDIA_PLAYER; - - if (position < 0) - return -EINVAL; - - player.position = position; - - msg = dbus_message_new_signal(CRAS_DEFAULT_PLAYER, - DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - if (!msg) - return -ENOMEM; - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, - &playerInterface); - dbus_message_iter_open_container( - &iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &dict); - append_key_value(&dict, "Position", DBUS_TYPE_INT64, - DBUS_TYPE_INT64_AS_STRING, &player.position); - dbus_message_iter_close_container(&iter, &dict); - - if (!dbus_connection_send(conn, msg, NULL)) { - dbus_message_unref(msg); - return -ENOMEM; - } - - dbus_message_unref(msg); - return 0; -} - -int cras_bt_player_update_metadata(DBusConnection *conn, const char *title, - const char *artist, const char *album, - const dbus_int64_t length) -{ - DBusMessage *msg; - DBusMessageIter iter, array, dict; - const char *property = "Metadata"; - const char *playerInterface = BLUEZ_INTERFACE_MEDIA_PLAYER; - - if (!player.metadata) - return -ENXIO; - - msg = dbus_message_new_signal(CRAS_DEFAULT_PLAYER, - DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - if (!msg) - return -ENOMEM; - - dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, - &playerInterface); - dbus_message_iter_open_container( - &iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &array); - dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, - &dict); - dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &property); - - if (!cras_bt_player_parse_metadata(title, album, artist, length)) { - /* Nothing to update. */ - dbus_message_unref(msg); - return 0; - } - - cras_bt_player_append_metadata(&dict, player.metadata->title, - player.metadata->artist, - player.metadata->album, - player.metadata->length); - - dbus_message_iter_close_container(&array, &dict); - dbus_message_iter_close_container(&iter, &array); - - if (!dbus_connection_send(conn, msg, NULL)) { - dbus_message_unref(msg); - return -ENOMEM; - } - - dbus_message_unref(msg); - return 0; -} diff --git a/cras/src/server/cras_bt_player.h b/cras/src/server/cras_bt_player.h index 25a6c8c5..9b66d70e 100644 --- a/cras/src/server/cras_bt_player.h +++ b/cras/src/server/cras_bt_player.h @@ -11,27 +11,16 @@ #include "cras_bt_adapter.h" -/* Object to hold current metadata. This is not a full list of what BlueZ/MPRIS - * supports but a subset because Chromium only provides the following. - */ -struct cras_bt_player_metadata { - char *title; - char *artist; - char *album; - int64_t length; -}; - /* Object to register as media player so that bluetoothd will report hardware * volume from device through bt_transport. Properties of the player are defined * in BlueZ's media API. */ struct cras_bt_player { const char *object_path; - char *playback_status; - char *identity; + const char *playback_status; + const char *identity; const char *loop_status; - struct cras_bt_player_metadata *metadata; - int64_t position; + int position; bool can_go_next; bool can_go_prev; bool can_play; @@ -56,40 +45,4 @@ int cras_bt_player_create(DBusConnection *conn); int cras_bt_register_player(DBusConnection *conn, const struct cras_bt_adapter *adapter); -/* Updates playback status for player and notifies bluetoothd - * Args: - * conn - The dbus connection. - * status - The player playback status. - */ -int cras_bt_player_update_playback_status(DBusConnection *conn, - const char *status); - -/* Updates the player identity and notifies bluetoothd. - * Args: - * conn - The dbus connection. - * identity - The identity of the registered player. This could be the name - * of the app or the name of the site playing media. - */ -int cras_bt_player_update_identity(DBusConnection *conn, const char *identity); - -/* Updates the player current track's position and notifies bluetoothd. - * Args: - * conn - The dbus connection. - * position - The current track position in microseconds. - */ -int cras_bt_player_update_position(DBusConnection *conn, - const dbus_int64_t position); - -/* Updates the player current metadata and notifies bluetoothd. - * Args: - * conn - The dbus connection. - * title - The title associated to the current media session. - * artist - The artist associated to the current media session. - * album - The album associated to the current media session. - * length - The duration in microseconds associated to the current media - * session. - */ -int cras_bt_player_update_metadata(DBusConnection *conn, const char *title, - const char *artist, const char *album, - const dbus_int64_t length); #endif /* CRAS_BT_PLAYER_H_ */ diff --git a/cras/src/server/cras_bt_profile.c b/cras/src/server/cras_bt_profile.c index 9b4171fa..d180a1b4 100644 --- a/cras/src/server/cras_bt_profile.c +++ b/cras/src/server/cras_bt_profile.c @@ -362,46 +362,6 @@ int cras_bt_register_profile(DBusConnection *conn, return 0; } -int cras_bt_unregister_profile(DBusConnection *conn, - struct cras_bt_profile *profile) -{ - DBusMessage *method_call; - DBusMessageIter message_iter; - DBusError dbus_error; - DBusMessage *reply; - - method_call = dbus_message_new_method_call(BLUEZ_SERVICE, - PROFILE_MANAGER_OBJ_PATH, - BLUEZ_PROFILE_MGMT_INTERFACE, - "UnregisterProfile"); - - if (!method_call) - return -ENOMEM; - dbus_error_init(&dbus_error); - dbus_message_iter_init_append(method_call, &message_iter); - dbus_message_iter_append_basic(&message_iter, DBUS_TYPE_OBJECT_PATH, - &profile->object_path); - reply = dbus_connection_send_with_reply_and_block( - conn, method_call, DBUS_TIMEOUT_USE_DEFAULT, &dbus_error); - - if (!reply) { - dbus_error_free(&dbus_error); - dbus_message_unref(method_call); - return -EIO; - } - - dbus_message_unref(method_call); - - if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { - syslog(LOG_ERR, "Unregister profile returned error: %s", - dbus_message_get_error_name(reply)); - dbus_message_unref(reply); - return -EIO; - } - dbus_message_unref(reply); - return 0; -} - int cras_bt_register_profiles(DBusConnection *conn) { struct cras_bt_profile *profile; @@ -439,19 +399,6 @@ int cras_bt_add_profile(DBusConnection *conn, struct cras_bt_profile *profile) return 0; } -int cras_bt_rm_profile(DBusConnection *conn, struct cras_bt_profile *profile) -{ - DL_DELETE(profiles, profile); - - if (!dbus_connection_unregister_object_path(conn, - profile->object_path)) { - syslog(LOG_ERR, "Could not unregister BT profile %s", - profile->object_path); - return -ENOMEM; - } - return 0; -} - void cras_bt_profile_reset() { struct cras_bt_profile *profile; diff --git a/cras/src/server/cras_bt_profile.h b/cras/src/server/cras_bt_profile.h index 4f8ab448..ed426605 100644 --- a/cras/src/server/cras_bt_profile.h +++ b/cras/src/server/cras_bt_profile.h @@ -41,13 +41,6 @@ struct cras_bt_profile { */ int cras_bt_add_profile(DBusConnection *conn, struct cras_bt_profile *profile); -/* Removes |profile| from the list of profiles registered with bluez. - * Args: - * conn - The dbus connection. - * profile - Pointer to the profile structure to be removed. - */ -int cras_bt_rm_profile(DBusConnection *conn, struct cras_bt_profile *profile); - /* Gets the profile by object path. * Args: * path - The object path of the desired profile. @@ -64,22 +57,6 @@ void cras_bt_profile_reset(); /* Notifies all profiles when a device is disconnected. */ void cras_bt_profile_on_device_disconnected(struct cras_bt_device *device); -/* Registeres |profile| with bluez. - * Args: - * conn - The dbus connection. - * profile - Pointer to the profile structure to be registered. - */ -int cras_bt_register_profile(DBusConnection *conn, - struct cras_bt_profile *profile); - -/* Unregisteres |profile| with bluez. - * Args: - * conn - The dbus connection. - * profile - Pointer to the profile structure to be unregistered. - */ -int cras_bt_unregister_profile(DBusConnection *conn, - struct cras_bt_profile *profile); - /* Registers all added profiles. * Args: * conn - The dbus connection. diff --git a/cras/src/server/cras_bt_transport.c b/cras/src/server/cras_bt_transport.c index 402cd75a..9e06dacf 100644 --- a/cras/src/server/cras_bt_transport.c +++ b/cras/src/server/cras_bt_transport.c @@ -17,7 +17,6 @@ #include "cras_bt_log.h" #include "cras_bt_transport.h" #include "cras_bt_constants.h" -#include "cras_system_state.h" #include "utlist.h" struct cras_bt_transport { @@ -101,8 +100,6 @@ void cras_bt_transport_destroy(struct cras_bt_transport *transport) if (transport->fd >= 0) close(transport->fd); - cras_bt_device_set_use_hardware_volume(transport->device, 0); - free(transport->object_path); free(transport->configuration); free(transport); @@ -287,24 +284,17 @@ void cras_bt_transport_update_properties(struct cras_bt_transport *transport, } else if (type == DBUS_TYPE_OBJECT_PATH) { const char *obj_path; - if (strcmp(key, "Device") == 0) { - /* Property: object Device [readonly] */ - dbus_message_iter_get_basic(&variant_iter, - &obj_path); - transport->device = - cras_bt_device_get(obj_path); - if (!transport->device) { - syslog(LOG_ERR, - "Device %s not found at update " - "transport properties", - obj_path); - transport->device = - cras_bt_device_create( - transport->conn, - obj_path); - cras_bt_transport_update_device( - transport); - } + /* Property: object Device [readonly] */ + dbus_message_iter_get_basic(&variant_iter, &obj_path); + transport->device = cras_bt_device_get(obj_path); + if (!transport->device) { + syslog(LOG_ERR, + "Device %s not found at update" + "transport properties", + obj_path); + transport->device = cras_bt_device_create( + transport->conn, obj_path); + cras_bt_transport_update_device(transport); } } else if (strcmp(dbus_message_iter_get_signature(&variant_iter), "ay") == 0 && @@ -331,7 +321,6 @@ void cras_bt_transport_update_properties(struct cras_bt_transport *transport, dbus_message_iter_get_basic(&variant_iter, &volume); transport->volume = volume; - BTLOG(btlog, BT_TRANSPORT_UPDATE_VOLUME, volume, 0); cras_bt_transport_update_device(transport); } @@ -385,7 +374,6 @@ int cras_bt_transport_set_volume(struct cras_bt_transport *transport, DBusMessageIter message_iter, variant; DBusPendingCall *pending_call; - BTLOG(btlog, BT_TRANSPORT_SET_VOLUME, volume, 0); method_call = dbus_message_new_method_call(BLUEZ_SERVICE, transport->object_path, @@ -476,10 +464,6 @@ int cras_bt_transport_acquire(struct cras_bt_transport *transport) goto acquire_fail; } - if (cras_system_get_bt_fix_a2dp_packet_size_enabled() && - transport->write_mtu > A2DP_FIX_PACKET_SIZE) - transport->write_mtu = A2DP_FIX_PACKET_SIZE; - BTLOG(btlog, BT_TRANSPORT_ACQUIRE, 1, transport->fd); dbus_message_unref(reply); return 0; diff --git a/cras/src/server/cras_capture_rclient.c b/cras/src/server/cras_capture_rclient.c index 9b1f2b84..c13792cd 100644 --- a/cras/src/server/cras_capture_rclient.c +++ b/cras/src/server/cras_capture_rclient.c @@ -11,12 +11,63 @@ #include "cras_rclient.h" #include "cras_rclient_util.h" #include "cras_rstream.h" +#include "cras_system_state.h" #include "cras_types.h" #include "cras_util.h" +#include "stream_list.h" + +/* Entry point for handling a message from the client. Called from the main + * server context. */ +static int ccr_handle_message_from_client(struct cras_rclient *client, + const struct cras_server_message *msg, + int *fds, unsigned int num_fds) +{ + int rc = 0; + assert(client && msg); + + rc = rclient_validate_message_fds(msg, fds, num_fds); + if (rc < 0) { + for (int i = 0; i < (int)num_fds; i++) + if (fds[i] >= 0) + close(fds[i]); + return rc; + } + int fd = num_fds > 0 ? fds[0] : -1; + + switch (msg->id) { + case CRAS_SERVER_CONNECT_STREAM: { + int client_shm_fd = num_fds > 1 ? fds[1] : -1; + struct cras_connect_message cmsg; + if (MSG_LEN_VALID(msg, struct cras_connect_message)) { + rc = rclient_handle_client_stream_connect( + client, + (const struct cras_connect_message *)msg, fd, + client_shm_fd); + } else if (!convert_connect_message_old(msg, &cmsg)) { + rc = rclient_handle_client_stream_connect( + client, &cmsg, fd, client_shm_fd); + } else { + return -EINVAL; + } + break; + } + case CRAS_SERVER_DISCONNECT_STREAM: + if (!MSG_LEN_VALID(msg, struct cras_disconnect_stream_message)) + return -EINVAL; + rc = rclient_handle_client_stream_disconnect( + client, + (const struct cras_disconnect_stream_message *)msg); + break; + default: + break; + } + + return rc; +} /* Declarations of cras_rclient operators for cras_capture_rclient. */ static const struct cras_rclient_ops cras_capture_rclient_ops = { - .handle_message_from_client = rclient_handle_message_from_client, + .handle_message_from_client = ccr_handle_message_from_client, .send_message_to_client = rclient_send_message_to_client, .destroy = rclient_destroy, }; @@ -29,7 +80,24 @@ static const struct cras_rclient_ops cras_capture_rclient_ops = { * the connection has succeeded. */ struct cras_rclient *cras_capture_rclient_create(int fd, size_t id) { - return rclient_generic_create( - fd, id, &cras_capture_rclient_ops, - cras_stream_direction_mask(CRAS_STREAM_INPUT)); + struct cras_rclient *client; + struct cras_client_connected msg; + int state_fd; + + client = (struct cras_rclient *)calloc(1, sizeof(struct cras_rclient)); + if (!client) + return NULL; + + client->fd = fd; + client->id = id; + + client->ops = &cras_capture_rclient_ops; + client->supported_directions = + cras_stream_direction_mask(CRAS_STREAM_INPUT); + + cras_fill_client_connected(&msg, client->id); + state_fd = cras_sys_state_shm_fd(); + client->ops->send_message_to_client(client, &msg.header, &state_fd, 1); + + return client; } diff --git a/cras/src/server/cras_control_rclient.c b/cras/src/server/cras_control_rclient.c index cd0c4d3b..c0eea5d6 100644 --- a/cras/src/server/cras_control_rclient.c +++ b/cras/src/server/cras_control_rclient.c @@ -15,8 +15,6 @@ #include "cras_dsp.h" #include "cras_iodev.h" #include "cras_iodev_list.h" -#include "cras_hfp_ag_profile.h" -#include "cras_main_thread_log.h" #include "cras_messages.h" #include "cras_observer.h" #include "cras_rclient.h" @@ -25,6 +23,7 @@ #include "cras_system_state.h" #include "cras_types.h" #include "cras_util.h" +#include "stream_list.h" #include "utlist.h" /* Handles dumping audio thread debug info back to the client. */ @@ -272,14 +271,7 @@ static int direction_valid(enum CRAS_STREAM_DIRECTION direction) } /* Entry point for handling a message from the client. Called from the main - * server context. - * - * If the message from clients has incorrect length (truncated message), return - * an error up to CRAS server. - * If the message from clients has invalid content, should return the errors to - * clients by send_message_to_client and return 0 here. - * - */ + * server context. */ static int ccr_handle_message_from_client(struct cras_rclient *client, const struct cras_server_message *msg, int *fds, unsigned int num_fds) @@ -299,15 +291,18 @@ static int ccr_handle_message_from_client(struct cras_rclient *client, switch (msg->id) { case CRAS_SERVER_CONNECT_STREAM: { int client_shm_fd = num_fds > 1 ? fds[1] : -1; + struct cras_connect_message cmsg; if (MSG_LEN_VALID(msg, struct cras_connect_message)) { - rclient_handle_client_stream_connect( + return rclient_handle_client_stream_connect( client, (const struct cras_connect_message *)msg, fd, client_shm_fd); + } else if (!convert_connect_message_old(msg, &cmsg)) { + return rclient_handle_client_stream_connect( + client, &cmsg, fd, client_shm_fd); } else { return -EINVAL; } - break; } case CRAS_SERVER_DISCONNECT_STREAM: if (!MSG_LEN_VALID(msg, struct cras_disconnect_stream_message)) @@ -340,6 +335,14 @@ static int ccr_handle_message_from_client(struct cras_rclient *client, cras_system_set_mute_locked( ((const struct cras_set_system_mute *)msg)->mute); break; + case CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN: { + const struct cras_set_system_capture_gain *m = + (const struct cras_set_system_capture_gain *)msg; + if (!MSG_LEN_VALID(msg, struct cras_set_system_capture_gain)) + return -EINVAL; + cras_system_set_capture_gain(m->gain); + break; + } case CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE: if (!MSG_LEN_VALID(msg, struct cras_set_system_mute)) return -EINVAL; @@ -399,19 +402,6 @@ static int ccr_handle_message_from_client(struct cras_rclient *client, case CRAS_SERVER_GET_ATLOG_FD: get_atlog_fd(client); break; - case CRAS_SERVER_DUMP_MAIN: { - struct cras_client_audio_debug_info_ready msg; - struct cras_server_state *state; - - state = cras_system_state_get_no_lock(); - memcpy(&state->main_thread_debug_info.main_log, main_log, - sizeof(struct main_thread_event_log)); - - cras_fill_client_audio_debug_info_ready(&msg); - client->ops->send_message_to_client(client, &msg.header, NULL, - 0); - break; - } case CRAS_SERVER_DUMP_BT: { struct cras_client_audio_debug_info_ready msg; struct cras_server_state *state; @@ -419,15 +409,10 @@ static int ccr_handle_message_from_client(struct cras_rclient *client, state = cras_system_state_get_no_lock(); #ifdef CRAS_DBUS memcpy(&state->bt_debug_info.bt_log, btlog, - sizeof(struct cras_bt_event_log)); - memcpy(&state->bt_debug_info.wbs_logger, - cras_hfp_ag_get_wbs_logger(), - sizeof(struct packet_status_logger)); + sizeof(struct cras_bt_debug_info)); #else memset(&state->bt_debug_info.bt_log, 0, sizeof(struct cras_bt_debug_info)); - memset(&state->bt_debug_info.wbs_logger, 0, - sizeof(struct packet_status_logger)); #endif cras_fill_client_audio_debug_info_ready(&msg); @@ -473,33 +458,17 @@ static int ccr_handle_message_from_client(struct cras_rclient *client, case CRAS_CONFIG_GLOBAL_REMIX: { const struct cras_config_global_remix *m = (const struct cras_config_global_remix *)msg; - float *coefficient; - if (!MSG_LEN_VALID(msg, struct cras_config_global_remix) || m->num_channels > CRAS_MAX_REMIX_CHANNELS) return -EINVAL; - const size_t coefficient_len = - (size_t)m->num_channels * (size_t)m->num_channels; - const size_t size_with_coefficients = - sizeof(*m) + - coefficient_len * sizeof(m->coefficient[0]); + size_t size_with_coefficients = + sizeof(*m) + m->num_channels * m->num_channels * + sizeof(m->coefficient[0]); if (size_with_coefficients != msg->length) return -EINVAL; - - coefficient = - (float *)calloc(coefficient_len, sizeof(coefficient)); - if (!coefficient) { - syslog(LOG_ERR, - "Failed to create local coefficient array."); - break; - } - memcpy(coefficient, m->coefficient, - coefficient_len * sizeof(coefficient)); - audio_thread_config_global_remix( cras_iodev_list_get_audio_thread(), m->num_channels, - coefficient); - free(coefficient); + m->coefficient); break; } case CRAS_SERVER_GET_HOTWORD_MODELS: { @@ -562,11 +531,25 @@ static const struct cras_rclient_ops cras_control_rclient_ops = { * the conneciton has succeeded. */ struct cras_rclient *cras_control_rclient_create(int fd, size_t id) { - /* Supports all directions but not CRAS_STREAM_UNDEFINED. */ - int supported_directions = - CRAS_STREAM_ALL_DIRECTION ^ + struct cras_rclient *client; + struct cras_client_connected msg; + int state_fd; + + client = (struct cras_rclient *)calloc(1, sizeof(struct cras_rclient)); + if (!client) + return NULL; + + client->fd = fd; + client->id = id; + client->ops = &cras_control_rclient_ops; + client->supported_directions = CRAS_STREAM_ALL_DIRECTION; + /* Filters CRAS_STREAM_UNDEFINED stream out. */ + client->supported_directions ^= cras_stream_direction_mask(CRAS_STREAM_UNDEFINED); - return rclient_generic_create(fd, id, &cras_control_rclient_ops, - supported_directions); + cras_fill_client_connected(&msg, client->id); + state_fd = cras_sys_state_shm_fd(); + client->ops->send_message_to_client(client, &msg.header, &state_fd, 1); + + return client; } diff --git a/cras/src/server/cras_dbus.c b/cras/src/server/cras_dbus.c index 5975f1c6..d127485d 100644 --- a/cras/src/server/cras_dbus.c +++ b/cras/src/server/cras_dbus.c @@ -15,7 +15,7 @@ #include "cras_system_state.h" #include "cras_tm.h" -static void dbus_watch_callback(void *arg, int revents) +static void dbus_watch_callback(void *arg) { DBusWatch *watch = (DBusWatch *)arg; int r, flags; @@ -48,8 +48,7 @@ static dbus_bool_t dbus_watch_add(DBusWatch *watch, void *data) */ if ((flags & DBUS_WATCH_READABLE) && dbus_watch_get_enabled(watch)) { r = cras_system_add_select_fd(dbus_watch_get_unix_fd(watch), - dbus_watch_callback, watch, - POLLIN); + dbus_watch_callback, watch); if (r != 0) return FALSE; } diff --git a/cras/src/server/cras_dbus_control.c b/cras/src/server/cras_dbus_control.c index b66e1276..978c64a3 100644 --- a/cras/src/server/cras_dbus_control.c +++ b/cras/src/server/cras_dbus_control.c @@ -11,16 +11,12 @@ #include <syslog.h> #include "audio_thread.h" -#include "cras_bt_player.h" #include "cras_dbus.h" #include "cras_dbus_control.h" #include "cras_dbus_util.h" -#include "cras_hfp_ag_profile.h" #include "cras_iodev_list.h" -#include "cras_main_thread_log.h" #include "cras_observer.h" #include "cras_system_state.h" -#include "cras_utf8.h" #include "cras_util.h" #include "utlist.h" @@ -50,6 +46,9 @@ " <method name=\"SetSuspendAudio\">\n" \ " <arg name=\"suspend\" type=\"b\" direction=\"in\"/>\n" \ " </method>\n" \ + " <method name=\"SetInputGain\">\n" \ + " <arg name=\"gain\" type=\"i\" direction=\"in\"/>\n" \ + " </method>\n" \ " <method name=\"SetInputNodeGain\">\n" \ " <arg name=\"node_id\" type=\"t\" direction=\"in\"/>\n" \ " <arg name=\"gain\" type=\"i\" direction=\"in\"/>\n" \ @@ -60,6 +59,7 @@ " <method name=\"GetVolumeState\">\n" \ " <arg name=\"output_volume\" type=\"i\" direction=\"out\"/>\n" \ " <arg name=\"output_mute\" type=\"b\" direction=\"out\"/>\n" \ + " <arg name=\"input_gain\" type=\"i\" direction=\"out\"/>\n" \ " <arg name=\"input_mute\" type=\"b\" direction=\"out\"/>\n" \ " <arg name=\"output_user_mute\" type=\"b\" direction=\"out\"/>\n" \ " </method>\n" \ @@ -75,9 +75,6 @@ " <method name=\"GetSystemAecGroupId\">\n" \ " <arg name=\"group_id\" type=\"i\" direction=\"out\"/>\n" \ " </method>\n" \ - " <method name=\"GetDeprioritizeBtWbsMic\">\n" \ - " <arg name=\"deprioritized\" type=\"b\" direction=\"out\"/>\n" \ - " </method>\n" \ " <method name=\"SetActiveOutputNode\">\n" \ " <arg name=\"node_id\" type=\"t\" direction=\"in\"/>\n" \ " </method>\n" \ @@ -96,9 +93,6 @@ " <method name=\"RemoveActiveOutputNode\">\n" \ " <arg name=\"node_id\" type=\"t\" direction=\"in\"/>\n" \ " </method>\n" \ - " <method name=\"SetFixA2dpPacketSize\">\n" \ - " <arg name=\"toggle\" type=\"b\" direction=\"in\"/>\n" \ - " </method>\n" \ " <method name=\"GetNumberOfActiveStreams\">\n" \ " <arg name=\"num\" type=\"i\" direction=\"out\"/>\n" \ " </method>\n" \ @@ -108,9 +102,6 @@ " <method name=\"GetNumberOfActiveInputStreams\">\n" \ " <arg name=\"num\" type=\"i\" direction=\"out\"/>\n" \ " </method>\n" \ - " <method name=\"GetNumberOfInputStreamsWithPermission\">\n" \ - " <arg name=\"num\" type=\"a{sv}\" direction=\"out\"/>\n" \ - " </method>\n" \ " <method name=\"SetGlobalOutputChannelRemix\">\n" \ " <arg name=\"num_channels\" type=\"i\" direction=\"in\"/>\n" \ " <arg name=\"coefficient\" type=\"ad\" direction=\"in\"/>\n" \ @@ -125,21 +116,6 @@ " <method name=\"SetWbsEnabled\">\n" \ " <arg name=\"enabled\" type=\"b\" direction=\"in\"/>\n" \ " </method>\n" \ - " <method name=\"SetNoiseCancellationEnabled\">\n" \ - " <arg name=\"enabled\" type=\"b\" direction=\"in\"/>\n" \ - " </method>\n" \ - " <method name=\"SetPlayerPlaybackStatus\">\n" \ - " <arg name=\"status\" type=\"s\" direction=\"in\"/>\n" \ - " </method>\n" \ - " <method name=\"SetPlayerIdentity\">\n" \ - " <arg name=\"identity\" type=\"s\" direction=\"in\"/>\n" \ - " </method>\n" \ - " <method name=\"SetPlayerPosition\">\n" \ - " <arg name=\"position\" type=\"x\" direction=\"in\"/>\n" \ - " </method>\n" \ - " <method name=\"SetPlayerMetadata\">\n" \ - " <arg name=\"metadata\" type=\"a{sv}\" direction=\"in\"/>\n" \ - " </method>\n" \ " </interface>\n" \ " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" \ " <method name=\"Introspect\">\n" \ @@ -172,79 +148,6 @@ static int get_single_arg(DBusMessage *message, int dbus_type, void *arg) return 0; } -static bool get_string_metadata(DBusMessageIter *iter, const char **dst) -{ - if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) - return FALSE; - - dbus_message_iter_get_basic(iter, dst); - return TRUE; -} - -static bool get_int64_metadata(DBusMessageIter *iter, dbus_int64_t *dst) -{ - if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INT64) - return FALSE; - - dbus_message_iter_get_basic(iter, dst); - return TRUE; -} - -static bool get_metadata(DBusMessage *message, const char **title, - const char **artist, const char **album, - dbus_int64_t *length) -{ - DBusError dbus_error; - DBusMessageIter iter, dict; - - dbus_error_init(&dbus_error); - dbus_message_iter_init(message, &iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) - return FALSE; - - dbus_message_iter_recurse(&iter, &dict); - - while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { - DBusMessageIter entry, var; - const char *key; - - if (dbus_message_iter_get_arg_type(&dict) != - DBUS_TYPE_DICT_ENTRY) - return FALSE; - - dbus_message_iter_recurse(&dict, &entry); - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) - return FALSE; - - dbus_message_iter_get_basic(&entry, &key); - dbus_message_iter_next(&entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) - return FALSE; - - dbus_message_iter_recurse(&entry, &var); - if (strcasecmp(key, "title") == 0) { - if (!get_string_metadata(&var, title)) - return FALSE; - } else if (strcasecmp(key, "artist") == 0) { - if (!get_string_metadata(&var, artist)) - return FALSE; - } else if (strcasecmp(key, "album") == 0) { - if (!get_string_metadata(&var, album)) - return FALSE; - } else if (strcasecmp(key, "length") == 0) { - if (!get_int64_metadata(&var, length)) - return FALSE; - } else - syslog(LOG_WARNING, "%s not supported, ignoring", key); - - dbus_message_iter_next(&dict); - } - - return TRUE; -} - /* Helper to send an empty reply. */ static void send_empty_reply(DBusConnection *conn, DBusMessage *message) { @@ -376,7 +279,6 @@ static DBusHandlerResult handle_set_output_user_mute(DBusConnection *conn, return rc; cras_system_set_user_mute(new_mute); - MAINLOG(main_log, MAIN_THREAD_SET_OUTPUT_USER_MUTE, new_mute, 0, 0); send_empty_reply(conn, message); @@ -399,6 +301,23 @@ handle_set_suspend_audio(DBusConnection *conn, DBusMessage *message, void *arg) return DBUS_HANDLER_RESULT_HANDLED; } +static DBusHandlerResult handle_set_input_gain(DBusConnection *conn, + DBusMessage *message, void *arg) +{ + int rc; + dbus_int32_t new_gain; + + rc = get_single_arg(message, DBUS_TYPE_INT32, &new_gain); + if (rc) + return rc; + + cras_system_set_capture_gain(new_gain); + + send_empty_reply(conn, message); + + return DBUS_HANDLER_RESULT_HANDLED; +} + static DBusHandlerResult handle_set_input_node_gain(DBusConnection *conn, DBusMessage *message, void *arg) @@ -450,6 +369,7 @@ handle_get_volume_state(DBusConnection *conn, DBusMessage *message, void *arg) dbus_int32_t volume; dbus_bool_t system_muted; dbus_bool_t user_muted; + dbus_int32_t capture_gain; dbus_bool_t capture_muted; reply = dbus_message_new_method_return(message); @@ -457,10 +377,12 @@ handle_get_volume_state(DBusConnection *conn, DBusMessage *message, void *arg) volume = cras_system_get_volume(); system_muted = cras_system_get_system_mute(); user_muted = cras_system_get_user_mute(); + capture_gain = cras_system_get_capture_gain(); capture_muted = cras_system_get_capture_mute(); dbus_message_append_args(reply, DBUS_TYPE_INT32, &volume, DBUS_TYPE_BOOLEAN, &system_muted, + DBUS_TYPE_INT32, &capture_gain, DBUS_TYPE_BOOLEAN, &capture_muted, DBUS_TYPE_BOOLEAN, &user_muted, DBUS_TYPE_INVALID); @@ -507,6 +429,7 @@ static dbus_bool_t append_node_dict(DBusMessageIter *iter, dbus_uint64_t stable_dev_id = node->stable_id; const char *node_type = node->type; const char *node_name = node->name; + const char *mic_positions = node->mic_positions; dbus_bool_t active; dbus_uint64_t plugged_time = node->plugged_time.tv_sec * 1000000ULL + node->plugged_time.tv_usec; @@ -519,14 +442,6 @@ static dbus_bool_t append_node_dict(DBusMessageIter *iter, id = (id << 32) | node->ionode_idx; active = !!node->active; - // If dev_name is not utf8, libdbus may abort cras. - if (!is_utf8_string(dev_name)) { - syslog(LOG_ERR, - "Non-utf8 device name '%s' cannot be sent via dbus", - dev_name); - dev_name = ""; - } - if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict)) return FALSE; @@ -552,6 +467,9 @@ static dbus_bool_t append_node_dict(DBusMessageIter *iter, if (!append_key_value(&dict, "Name", DBUS_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING, &node_name)) return FALSE; + if (!append_key_value(&dict, "MicPositions", DBUS_TYPE_STRING, + DBUS_TYPE_STRING_AS_STRING, &mic_positions)) + return FALSE; if (!append_key_value(&dict, "Active", DBUS_TYPE_BOOLEAN, DBUS_TYPE_BOOLEAN_AS_STRING, &active)) return FALSE; @@ -678,27 +596,6 @@ static DBusHandlerResult handle_get_system_aec_group_id(DBusConnection *conn, } static DBusHandlerResult -handle_get_deprioritize_bt_wbs_mic(DBusConnection *conn, DBusMessage *message, - void *arg) -{ - DBusMessage *reply; - dbus_uint32_t serial = 0; - dbus_bool_t deprioritized; - - reply = dbus_message_new_method_return(message); - - deprioritized = cras_system_get_deprioritize_bt_wbs_mic(); - dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &deprioritized, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, reply, &serial); - - dbus_message_unref(reply); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult handle_set_active_node(DBusConnection *conn, DBusMessage *message, void *arg, enum CRAS_STREAM_DIRECTION direction) { @@ -752,24 +649,6 @@ handle_rm_active_node(DBusConnection *conn, DBusMessage *message, void *arg, return DBUS_HANDLER_RESULT_HANDLED; } -static DBusHandlerResult handle_set_fix_a2dp_packet_size(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - int rc; - dbus_bool_t enabled = FALSE; - - rc = get_single_arg(message, DBUS_TYPE_BOOLEAN, &enabled); - if (rc) - return rc; - - cras_system_set_bt_fix_a2dp_packet_size_enabled(enabled); - - send_empty_reply(conn, message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - static DBusHandlerResult handle_get_num_active_streams(DBusConnection *conn, DBusMessage *message, void *arg) @@ -812,65 +691,6 @@ handle_get_num_active_streams_use_output_hw(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static bool append_num_input_streams_with_permission( - DBusMessage *message, uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) -{ - DBusMessageIter array; - DBusMessageIter dict; - unsigned type; - - dbus_message_iter_init_append(message, &array); - for (type = 0; type < CRAS_NUM_CLIENT_TYPE; ++type) { - const char *client_type_str = cras_client_type_str(type); - if (!is_utf8_string(client_type_str)) { - syslog(LOG_ERR, - "Non-utf8 clinet_type_str '%s' cannot be sent " - "via dbus", - client_type_str); - client_type_str = ""; - } - - if (!dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, - "{sv}", &dict)) - return false; - if (!append_key_value(&dict, "ClientType", DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, - &client_type_str)) - return false; - if (!append_key_value(&dict, "NumStreamsWithPermission", - DBUS_TYPE_UINT32, - DBUS_TYPE_UINT32_AS_STRING, - &num_input_streams[type])) - return false; - if (!dbus_message_iter_close_container(&array, &dict)) - return false; - } - return true; -} - -static DBusHandlerResult -handle_get_num_input_streams_with_permission(DBusConnection *conn, - DBusMessage *message, void *arg) -{ - DBusMessage *reply; - dbus_uint32_t serial = 0; - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE] = {}; - - reply = dbus_message_new_method_return(message); - - cras_system_state_get_input_streams_with_permission(num_input_streams); - if (!append_num_input_streams_with_permission(reply, num_input_streams)) - goto error; - - dbus_connection_send(conn, reply, &serial); - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_HANDLED; - -error: - dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; -} - static DBusHandlerResult handle_set_global_output_channel_remix(DBusConnection *conn, DBusMessage *message, void *arg) @@ -961,124 +781,6 @@ static DBusHandlerResult handle_set_wbs_enabled(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static DBusHandlerResult -handle_set_noise_cancellation_enabled(DBusConnection *conn, - DBusMessage *message, void *arg) -{ - int rc; - dbus_bool_t enabled; - - rc = get_single_arg(message, DBUS_TYPE_BOOLEAN, &enabled); - if (rc) - return rc; - - cras_system_set_noise_cancellation_enabled(enabled); - - send_empty_reply(conn, message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult handle_set_player_playback_status(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - char *status; - DBusError dbus_error; - int rc; - - dbus_error_init(&dbus_error); - - rc = get_single_arg(message, DBUS_TYPE_STRING, &status); - if (rc) - return rc; - - rc = cras_bt_player_update_playback_status(conn, status); - if (rc) { - syslog(LOG_WARNING, - "CRAS failed to update BT Player Status: %d", rc); - } - - send_empty_reply(conn, message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult handle_set_player_identity(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - char *identity; - DBusError dbus_error; - int rc; - - dbus_error_init(&dbus_error); - - rc = get_single_arg(message, DBUS_TYPE_STRING, &identity); - if (rc) - return rc; - - rc = cras_bt_player_update_identity(conn, identity); - if (rc) { - syslog(LOG_WARNING, - "CRAS failed to update BT Player Identity: %d", rc); - } - - send_empty_reply(conn, message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult handle_set_player_position(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - dbus_int64_t position; - DBusError dbus_error; - int rc; - - dbus_error_init(&dbus_error); - - rc = get_single_arg(message, DBUS_TYPE_INT64, &position); - if (rc) - return rc; - - rc = cras_bt_player_update_position(conn, position); - if (rc) { - syslog(LOG_WARNING, - "CRAS failed to update BT Player Position: %d", rc); - } - - send_empty_reply(conn, message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult handle_set_player_metadata(DBusConnection *conn, - DBusMessage *message, - void *arg) -{ - DBusError dbus_error; - int rc; - - dbus_error_init(&dbus_error); - const char *title = NULL, *artist = NULL, *album = NULL; - dbus_int64_t length = 0; - - if (!get_metadata(message, &title, &artist, &album, &length)) - return -EINVAL; - - rc = cras_bt_player_update_metadata(conn, title, artist, album, length); - if (rc) { - syslog(LOG_WARNING, "CRAS failed to update BT Metadata: %d", - rc); - } - - send_empty_reply(conn, message); - - return DBUS_HANDLER_RESULT_HANDLED; -} - /* Handle incoming messages. */ static DBusHandlerResult handle_control_message(DBusConnection *conn, DBusMessage *message, void *arg) @@ -1124,6 +826,9 @@ static DBusHandlerResult handle_control_message(DBusConnection *conn, "SetSuspendAudio")) { return handle_set_suspend_audio(conn, message, arg); } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, + "SetInputGain")) { + return handle_set_input_gain(conn, message, arg); + } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, "SetInputNodeGain")) { return handle_set_input_node_gain(conn, message, arg); } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, @@ -1146,9 +851,6 @@ static DBusHandlerResult handle_control_message(DBusConnection *conn, "GetSystemAecGroupId")) { return handle_get_system_aec_group_id(conn, message, arg); } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "GetDeprioritizeBtWbsMic")) { - return handle_get_deprioritize_bt_wbs_mic(conn, message, arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, "SetActiveOutputNode")) { return handle_set_active_node(conn, message, arg, CRAS_STREAM_OUTPUT); @@ -1173,9 +875,6 @@ static DBusHandlerResult handle_control_message(DBusConnection *conn, return handle_rm_active_node(conn, message, arg, CRAS_STREAM_OUTPUT); } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "SetFixA2dpPacketSize")) { - return handle_set_fix_a2dp_packet_size(conn, message, arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, "GetNumberOfActiveStreams")) { return handle_get_num_active_streams(conn, message, arg); } else if (dbus_message_is_method_call( @@ -1185,11 +884,6 @@ static DBusHandlerResult handle_control_message(DBusConnection *conn, arg); } else if (dbus_message_is_method_call( message, CRAS_CONTROL_INTERFACE, - "GetNumberOfInputStreamsWithPermission")) { - return handle_get_num_input_streams_with_permission( - conn, message, arg); - } else if (dbus_message_is_method_call( - message, CRAS_CONTROL_INTERFACE, "GetNumberOfActiveOutputStreams")) { return handle_get_num_active_streams_use_output_hw( conn, message, arg); @@ -1206,22 +900,6 @@ static DBusHandlerResult handle_control_message(DBusConnection *conn, } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, "SetWbsEnabled")) { return handle_set_wbs_enabled(conn, message, arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "SetNoiseCancellationEnabled")) { - return handle_set_noise_cancellation_enabled(conn, message, - arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "SetPlayerPlaybackStatus")) { - return handle_set_player_playback_status(conn, message, arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "SetPlayerIdentity")) { - return handle_set_player_identity(conn, message, arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "SetPlayerPosition")) { - return handle_set_player_position(conn, message, arg); - } else if (dbus_message_is_method_call(message, CRAS_CONTROL_INTERFACE, - "SetPlayerMetadata")) { - return handle_set_player_metadata(conn, message, arg); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1333,8 +1011,8 @@ static void signal_active_node_changed(void *context, dbus_uint32_t serial = 0; msg = create_dbus_message((dir == CRAS_STREAM_OUTPUT) ? - "ActiveOutputNodeChanged" : - "ActiveInputNodeChanged"); + "ActiveOutputNodeChanged" : + "ActiveInputNodeChanged"); if (!msg) return; dbus_message_append_args(msg, DBUS_TYPE_UINT64, &node_id, @@ -1418,25 +1096,6 @@ static void signal_num_active_streams_changed(void *context, dbus_message_unref(msg); } -static void signal_num_input_streams_with_permission_changed( - void *context, uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) -{ - struct cras_dbus_control *control = (struct cras_dbus_control *)context; - dbus_uint32_t serial = 0; - DBusMessage *msg; - - msg = create_dbus_message("NumberOfInputStreamsWithPermissionChanged"); - if (!msg) - return; - - if (!append_num_input_streams_with_permission(msg, num_input_streams)) - goto error; - - dbus_connection_send(control->conn, msg, &serial); -error: - dbus_message_unref(msg); -} - static void signal_hotword_triggered(void *context, int64_t tv_sec, int64_t tv_nsec) { @@ -1502,8 +1161,6 @@ void cras_dbus_control_start(DBusConnection *conn) observer_ops.capture_mute_changed = signal_capture_mute; observer_ops.num_active_streams_changed = signal_num_active_streams_changed; - observer_ops.num_input_streams_with_permission_changed = - signal_num_input_streams_with_permission_changed; observer_ops.nodes_changed = signal_nodes_changed; observer_ops.active_node_changed = signal_active_node_changed; observer_ops.input_node_gain_changed = signal_node_capture_gain_changed; diff --git a/cras/src/server/cras_device_monitor.c b/cras/src/server/cras_device_monitor.c index e9730a0b..7dd0f5d7 100644 --- a/cras/src/server/cras_device_monitor.c +++ b/cras/src/server/cras_device_monitor.c @@ -13,7 +13,6 @@ enum CRAS_DEVICE_MONITOR_MSG_TYPE { RESET_DEVICE, SET_MUTE_STATE, - ERROR_CLOSE, }; struct cras_device_monitor_message { @@ -63,21 +62,6 @@ int cras_device_monitor_set_device_mute_state(unsigned int dev_idx) return 0; } -int cras_device_monitor_error_close(unsigned int dev_idx) -{ - struct cras_device_monitor_message msg; - int err; - - init_device_msg(&msg, ERROR_CLOSE, dev_idx); - err = cras_main_message_send((struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, "Failed to send device message %d", - ERROR_CLOSE); - return err; - } - return 0; -} - /* When device is in a bad state, e.g. severe underrun, * it might break how audio thread works and cause busy wake up loop. * Resetting the device can bring device back to normal state. @@ -100,10 +84,6 @@ static void handle_device_message(struct cras_main_message *msg, void *arg) case SET_MUTE_STATE: cras_iodev_list_set_dev_mute(device_msg->dev_idx); break; - case ERROR_CLOSE: - syslog(LOG_ERR, "Close erroneous device in main thread"); - cras_iodev_list_suspend_dev(device_msg->dev_idx); - break; default: syslog(LOG_ERR, "Unknown device message type %u", device_msg->message_type); diff --git a/cras/src/server/cras_device_monitor.h b/cras/src/server/cras_device_monitor.h index eca2372b..ac31adb9 100644 --- a/cras/src/server/cras_device_monitor.h +++ b/cras/src/server/cras_device_monitor.h @@ -15,8 +15,4 @@ int cras_device_monitor_set_device_mute_state(unsigned int dev_idx); /* Initializes device monitor and sets main thread callback. */ int cras_device_monitor_init(); -/* Asks main thread to close device because error has occured in audio - * thread. */ -int cras_device_monitor_error_close(unsigned int dev_idx); - #endif /* CRAS_DEVICE_MONITOR_H_ */ diff --git a/cras/src/server/cras_dsp.c b/cras/src/server/cras_dsp.c index 9c4cc7b5..1a2707d3 100644 --- a/cras/src/server/cras_dsp.c +++ b/cras/src/server/cras_dsp.c @@ -36,7 +36,7 @@ struct cras_dsp_context { static struct dumper *syslog_dumper; static const char *ini_filename; -static struct ini *global_ini; +static struct ini *ini; static struct cras_dsp_context *context_list; static void initialize_environment(struct cras_expr_env *env) @@ -60,7 +60,7 @@ static void destroy_pipeline(struct pipeline *pipeline) * this ini so its life cycle is aligned with the associated dsp * pipeline. */ - if (private_ini && (private_ini != global_ini)) + if (private_ini && (private_ini != ini)) cras_dsp_ini_free(private_ini); } @@ -123,21 +123,19 @@ static void cmd_load_pipeline(struct cras_dsp_context *ctx, static void cmd_reload_ini() { - struct ini *old_ini = global_ini; + struct ini *old_ini = ini; struct cras_dsp_context *ctx; - struct ini *new_ini = cras_dsp_ini_create(ini_filename); - if (!new_ini) { + ini = cras_dsp_ini_create(ini_filename); + if (!ini) { syslog(LOG_DEBUG, "cannot create dsp ini"); return; } DL_FOREACH (context_list, ctx) { - cmd_load_pipeline(ctx, new_ini); + cmd_load_pipeline(ctx, ini); } - global_ini = new_ini; - if (old_ini) cras_dsp_ini_free(old_ini); } @@ -155,11 +153,10 @@ void cras_dsp_init(const char *filename) void cras_dsp_stop() { syslog_dumper_free(syslog_dumper); - if (ini_filename) - free((char *)ini_filename); - if (global_ini) { - cras_dsp_ini_free(global_ini); - global_ini = NULL; + free((char *)ini_filename); + if (ini) { + cras_dsp_ini_free(ini); + ini = NULL; } } @@ -205,18 +202,18 @@ void cras_dsp_set_variable_boolean(struct cras_dsp_context *ctx, void cras_dsp_load_pipeline(struct cras_dsp_context *ctx) { - cmd_load_pipeline(ctx, global_ini); + cmd_load_pipeline(ctx, ini); } -void cras_dsp_load_mock_pipeline(struct cras_dsp_context *ctx, - unsigned int num_channels) +void cras_dsp_load_dummy_pipeline(struct cras_dsp_context *ctx, + unsigned int num_channels) { - struct ini *mock_ini; - mock_ini = create_mock_ini(ctx->purpose, num_channels); - if (mock_ini == NULL) - syslog(LOG_ERR, "Failed to create mock ini"); + struct ini *dummy_ini; + dummy_ini = create_dummy_ini(ctx->purpose, num_channels); + if (dummy_ini == NULL) + syslog(LOG_ERR, "Failed to create dummy ini"); else - cmd_load_pipeline(ctx, mock_ini); + cmd_load_pipeline(ctx, dummy_ini); } struct pipeline *cras_dsp_get_pipeline(struct cras_dsp_context *ctx) @@ -244,8 +241,8 @@ void cras_dsp_dump_info() struct pipeline *pipeline; struct cras_dsp_context *ctx; - if (global_ini) - cras_dsp_ini_dump(syslog_dumper, global_ini); + if (ini) + cras_dsp_ini_dump(syslog_dumper, ini); DL_FOREACH (context_list, ctx) { cras_expr_env_dump(syslog_dumper, &ctx->env); pipeline = ctx->pipeline; diff --git a/cras/src/server/cras_dsp.h b/cras/src/server/cras_dsp.h index 366e2e67..9a72f42b 100644 --- a/cras/src/server/cras_dsp.h +++ b/cras/src/server/cras_dsp.h @@ -54,11 +54,11 @@ void cras_dsp_set_variable_boolean(struct cras_dsp_context *ctx, * blocking the audio thread. */ void cras_dsp_load_pipeline(struct cras_dsp_context *ctx); -/* Loads a mock pipeline of source directly connects to sink, of given +/* Loads a dummy pipeline of source directly connects to sink, of given * number of channels. */ -void cras_dsp_load_mock_pipeline(struct cras_dsp_context *ctx, - unsigned int num_channels); +void cras_dsp_load_dummy_pipeline(struct cras_dsp_context *ctx, + unsigned int num_channels); /* Locks the pipeline in the context for access. Returns NULL if the * pipeline is still being loaded or cannot be loaded. */ diff --git a/cras/src/server/cras_dsp_ini.c b/cras/src/server/cras_dsp_ini.c index a331acf8..966c6b01 100644 --- a/cras/src/server/cras_dsp_ini.c +++ b/cras/src/server/cras_dsp_ini.c @@ -9,9 +9,10 @@ #include "cras_dsp_ini.h" #include "iniparser_wrapper.h" +#define MAX_INI_KEY_LENGTH 64 /* names like "output_source:output_0" */ #define MAX_NR_PORT 128 /* the max number of ports for a plugin */ #define MAX_PORT_NAME_LENGTH 20 /* names like "output_32" */ -#define MAX_MOCK_INI_CH 20 /* Max number of channels to create mock ini */ +#define MAX_DUMMY_INI_CH 8 /* Max number of channels to create dummy ini */ /* Format of the ini file (See dsp.ini.sample for an example). @@ -62,7 +63,7 @@ static const char *getstring(struct ini *ini, const char *sec_name, const char *key) { - char full_key[MAX_INI_KEY_LENGTH + 1]; + char full_key[MAX_INI_KEY_LENGTH]; snprintf(full_key, sizeof(full_key), "%s:%s", sec_name, key); return iniparser_getstring(ini->dict, full_key, NULL); } @@ -305,21 +306,19 @@ static int insert_swap_lr_plugin(struct ini *ini) return 0; } -struct ini *create_mock_ini(const char *purpose, unsigned int num_channels) +struct ini *create_dummy_ini(const char *purpose, unsigned int num_channels) { - static char mock_flow_names[MAX_MOCK_INI_CH][9] = { - "{tmp:0}", "{tmp:1}", "{tmp:2}", "{tmp:3}", "{tmp:4}", - "{tmp:5}", "{tmp:6}", "{tmp:7}", "{tmp:8}", "{tmp:9}", - "{tmp:10}", "{tmp:11}", "{tmp:12}", "{tmp:13}", "{tmp:14}", - "{tmp:15}", "{tmp:16}", "{tmp:17}", "{tmp:18}", "{tmp:19}", + static char dummy_flow_names[MAX_DUMMY_INI_CH][8] = { + "{tmp:0}", "{tmp:1}", "{tmp:2}", "{tmp:3}", + "{tmp:4}", "{tmp:5}", "{tmp:6}", "{tmp:7}", }; struct ini *ini; struct plugin *source, *sink; - int tmp_flow_ids[MAX_MOCK_INI_CH]; + int tmp_flow_ids[MAX_DUMMY_INI_CH]; int i; - if (num_channels > MAX_MOCK_INI_CH) { - syslog(LOG_ERR, "Unable to create %u channels of mock ini", + if (num_channels > MAX_DUMMY_INI_CH) { + syslog(LOG_ERR, "Unable to create %u channels of dummy ini", num_channels); return NULL; } @@ -331,7 +330,7 @@ struct ini *create_mock_ini(const char *purpose, unsigned int num_channels) } for (i = 0; i < num_channels; i++) - tmp_flow_ids[i] = add_new_flow(ini, mock_flow_names[i]); + tmp_flow_ids[i] = add_new_flow(ini, dummy_flow_names[i]); source = ARRAY_APPEND_ZERO(&ini->plugins); source->title = "source"; diff --git a/cras/src/server/cras_dsp_ini.h b/cras/src/server/cras_dsp_ini.h index c839d4b0..117cfd21 100644 --- a/cras/src/server/cras_dsp_ini.h +++ b/cras/src/server/cras_dsp_ini.h @@ -6,12 +6,12 @@ #ifndef CRAS_DSP_INI_H_ #define CRAS_DSP_INI_H_ -#include "iniparser_wrapper.h" - #ifdef __cplusplus extern "C" { #endif +#include <iniparser.h> + #include "array.h" #include "dumper.h" #include "cras_expr.h" @@ -71,7 +71,7 @@ struct ini { }; /* - * Creates a mock ini structure equivalent to: + * Creates a dummy ini structure equivalent to: * * [src] * out0={tmp:0} @@ -86,7 +86,7 @@ struct ini { * The caller of this function is responsible to free the returned * ini by calling cras_dsp_ini_free(). */ -struct ini *create_mock_ini(const char *purpose, unsigned int num_channels); +struct ini *create_dummy_ini(const char *purpose, unsigned int num_channels); /* Reads the ini file into the ini structure */ struct ini *cras_dsp_ini_create(const char *ini_filename); diff --git a/cras/src/server/cras_dsp_pipeline.c b/cras/src/server/cras_dsp_pipeline.c index 9e492ac5..945e5c3e 100644 --- a/cras/src/server/cras_dsp_pipeline.c +++ b/cras/src/server/cras_dsp_pipeline.c @@ -144,8 +144,8 @@ struct pipeline { int64_t total_samples; }; -static struct instance *find_instance_by_plugin(const instance_array *instances, - const struct plugin *plugin) +static struct instance *find_instance_by_plugin(instance_array *instances, + struct plugin *plugin) { int i; struct instance *instance; @@ -161,9 +161,9 @@ static struct instance *find_instance_by_plugin(const instance_array *instances, /* Finds out where the data sent to plugin:index come from. The issue * we need to handle here is the previous plugin may be disabled, so * we need to go upstream until we find the real origin */ -static int find_origin_port(struct ini *ini, const instance_array *instances, - const struct plugin *plugin, int index, - const struct plugin **origin, int *origin_index) +static int find_origin_port(struct ini *ini, instance_array *instances, + struct plugin *plugin, int index, + struct plugin **origin, int *origin_index) { enum port_type type; struct port *port; @@ -226,7 +226,7 @@ static int find_origin_port(struct ini *ini, const instance_array *instances, } static struct audio_port *find_output_audio_port(instance_array *instances, - const struct plugin *plugin, + struct plugin *plugin, int index) { int i; @@ -246,7 +246,7 @@ static struct audio_port *find_output_audio_port(instance_array *instances, } static struct control_port *find_output_control_port(instance_array *instances, - const struct plugin *plugin, + struct plugin *plugin, int index) { int i; @@ -317,7 +317,7 @@ static int topological_sort(struct pipeline *pipeline, ARRAY_ELEMENT_FOREACH (&plugin->ports, i, port) { int need_connect = (port->flow_id != INVALID_FLOW_ID && port->direction == PORT_INPUT); - const struct plugin *origin = NULL; + struct plugin *origin = NULL; int origin_index = 0; if (need_connect) { @@ -435,7 +435,6 @@ struct pipeline *cras_dsp_pipeline_create(struct ini *ini, if (rc < 0) { syslog(LOG_ERR, "failed to construct pipeline"); - cras_dsp_pipeline_free(pipeline); return NULL; } @@ -525,17 +524,6 @@ static int allocate_buffers(struct pipeline *pipeline) peak_buf = MAX(peak_buf, need_buf); } } - /* - * cras_dsp_pipeline_create creates pipeline with source and sink and it - * makes sure all ports could be accessed from some sources, which means - * that there is at least one source with out > 0 and in == 0. - * This will give us peak_buf > 0 in the previous calculation. - */ - if (peak_buf <= 0) { - syslog(LOG_ERR, "peak_buf = %d, which must be greater than 0.", - peak_buf); - return -1; - } /* then allocate the buffers */ pipeline->peak_buf = peak_buf; @@ -982,10 +970,9 @@ void cras_dsp_pipeline_dump(struct dumper *d, struct pipeline *pipeline) pipeline->min_time); dumpf(d, " max processing time per block: %" PRId64 "ns\n", pipeline->max_time); - if (pipeline->total_samples) - dumpf(d, " cpu load: %g%%\n", - pipeline->total_time * 1e-9 / pipeline->total_samples * - pipeline->sample_rate * 100); + dumpf(d, " cpu load: %g%%\n", + pipeline->total_time * 1e-9 / pipeline->total_samples * + pipeline->sample_rate * 100); dumpf(d, " instances (%d):\n", ARRAY_COUNT(&pipeline->instances)); ARRAY_ELEMENT_FOREACH (&pipeline->instances, i, instance) { struct dsp_module *module = instance->module; diff --git a/cras/src/server/cras_empty_iodev.c b/cras/src/server/cras_empty_iodev.c index 3471c756..574f5368 100644 --- a/cras/src/server/cras_empty_iodev.c +++ b/cras/src/server/cras_empty_iodev.c @@ -15,9 +15,9 @@ #include "cras_types.h" #include "utlist.h" -#define EMPTY_BUFFER_SIZE (32 * 1024) -#define MAX_EMPTY_FRAME_SIZE 8 -#define EMPTY_FRAMES (EMPTY_BUFFER_SIZE / MAX_EMPTY_FRAME_SIZE) +#define EMPTY_BUFFER_SIZE (16 * 1024) +#define EMPTY_FRAME_SIZE 4 +#define EMPTY_FRAMES (EMPTY_BUFFER_SIZE / EMPTY_FRAME_SIZE) static size_t empty_supported_rates[] = { 44100, 48000, 0 }; @@ -199,12 +199,11 @@ struct cras_iodev *empty_iodev_create(enum CRAS_STREAM_DIRECTION direction, iodev->update_active_node = update_active_node; iodev->no_stream = cras_iodev_default_no_stream_playback; - /* Create an empty ionode */ + /* Create a dummy ionode */ node = (struct cras_ionode *)calloc(1, sizeof(*node)); node->dev = iodev; node->type = node_type; node->volume = 100; - node->ui_gain_scaler = 1.0f; strcpy(node->name, "(default)"); cras_iodev_add_node(iodev, node); cras_iodev_set_active_node(iodev, node); @@ -231,12 +230,6 @@ struct cras_iodev *empty_iodev_create(enum CRAS_STREAM_DIRECTION direction, iodev->info.idx = SILENT_PLAYBACK_DEVICE; } - /* - * Record max supported channels into cras_iodev_info. - * The value is the max of empty_supported_channel_counts. - */ - iodev->info.max_supported_channels = 2; - return iodev; } diff --git a/cras/src/server/cras_fmt_conv.c b/cras/src/server/cras_fmt_conv.c index 842529b9..35ab8ecf 100644 --- a/cras/src/server/cras_fmt_conv.c +++ b/cras/src/server/cras_fmt_conv.c @@ -9,7 +9,6 @@ #include <syslog.h> #include <endian.h> #include <limits.h> -#include <math.h> #include "cras_fmt_conv.h" #include "cras_fmt_conv_ops.h" @@ -59,35 +58,17 @@ static int is_channel_layout_equal(const struct cras_audio_format *a, return 1; } -/* - * Calculates the normalize_factor abs_sum(ci) from given coefficients. - * Since sum(ci / abs_sum(ci)) <= 1, this could prevent sample overflow while - * upmixing or downmixing. - */ -static float normalize_factor(float *buf, size_t n) +static void normalize_buf(float *buf, size_t size) { int i; - float abs_sum = 0.0; - for (i = 0; i < n; i++) - abs_sum += fabs(buf[i]); - - return 1.0 / abs_sum; -} - -/* - * Normalize all channels with the same factor to maintain - * the energy ratio between original channels. - */ -static void normalize(float **mtx, size_t m, size_t n, float factor) -{ - int i, j; - for (i = 0; i < m; i++) - for (j = 0; j < n; j++) - mtx[i][j] *= factor; + float squre_sum = 0.0; + for (i = 0; i < size; i++) + squre_sum += buf[i] * buf[i]; + for (i = 0; i < size; i++) + buf[i] /= squre_sum; } -/* - * Populates the down mix matrix by rules: +/* Populates the down mix matrix by rules: * 1. Front/side left(right) channel will mix to left(right) of * full scale. * 2. Center and LFE will be split equally to left and right. @@ -121,46 +102,9 @@ static void surround51_to_stereo_downmix_mtx(float **mtx, mtx[STEREO_L][layout[CRAS_CH_LFE]] = 0.707; mtx[STEREO_R][layout[CRAS_CH_LFE]] = 0.707; } - normalize(mtx, 2, 6, normalize_factor(mtx[STEREO_L], 6)); -} - -/* Populates the down mix matrix by rules: - * 1. Front left(right) channel will mix to the front left(right) of - * full scale. - * 2. Rear and side left(right) channel will mix to the rear left(right) of - * full scale. - * 3. Center will be split equally to the front left and right. - * 4. LFE will be split equally to the other channels. - */ -static void surround51_to_quad_downmix_mtx(float **mtx, - int8_t layout[CRAS_CH_MAX]) -{ - if (layout[CRAS_CH_FL] != -1 && layout[CRAS_CH_FR] != -1) { - mtx[CRAS_CH_FL][layout[CRAS_CH_FL]] = 1.0; - mtx[CRAS_CH_FR][layout[CRAS_CH_FR]] = 1.0; - } - if (layout[CRAS_CH_RL] != -1 && layout[CRAS_CH_RR] != -1) { - mtx[CRAS_CH_RL][layout[CRAS_CH_RL]] = 1.0; - mtx[CRAS_CH_RR][layout[CRAS_CH_RR]] = 1.0; - } - if (layout[CRAS_CH_SL] != -1 && layout[CRAS_CH_SR] != -1) { - mtx[CRAS_CH_RL][layout[CRAS_CH_SL]] = 1.0; - mtx[CRAS_CH_RR][layout[CRAS_CH_SR]] = 1.0; - } - if (layout[CRAS_CH_FC] != -1) { - /* Split 1/2 power to the front L/R */ - mtx[CRAS_CH_FL][layout[CRAS_CH_FC]] = 0.707; - mtx[CRAS_CH_FR][layout[CRAS_CH_FC]] = 0.707; - } - if (layout[CRAS_CH_LFE] != -1) { - /* Split 1/4 power to the other channel */ - mtx[CRAS_CH_FL][layout[CRAS_CH_LFE]] = 0.5; - mtx[CRAS_CH_FR][layout[CRAS_CH_LFE]] = 0.5; - mtx[CRAS_CH_RL][layout[CRAS_CH_LFE]] = 0.5; - mtx[CRAS_CH_RR][layout[CRAS_CH_LFE]] = 0.5; - } - normalize(mtx, 4, 6, normalize_factor(mtx[CRAS_CH_FL], 6)); + normalize_buf(mtx[STEREO_L], 6); + normalize_buf(mtx[STEREO_R], 6); } static int is_supported_format(const struct cras_audio_format *fmt) @@ -216,31 +160,12 @@ static size_t stereo_to_51(struct cras_fmt_conv *conv, const uint8_t *in, return s16_stereo_to_51(left, right, center, in, in_frames, out); } -static size_t quad_to_51(struct cras_fmt_conv *conv, const uint8_t *in, - size_t in_frames, uint8_t *out) -{ - size_t fl, fr, rl, rr; - - fl = conv->out_fmt.channel_layout[CRAS_CH_FL]; - fr = conv->out_fmt.channel_layout[CRAS_CH_FR]; - rl = conv->out_fmt.channel_layout[CRAS_CH_RL]; - rr = conv->out_fmt.channel_layout[CRAS_CH_RR]; - - return s16_quad_to_51(fl, fr, rl, rr, in, in_frames, out); -} - static size_t _51_to_stereo(struct cras_fmt_conv *conv, const uint8_t *in, size_t in_frames, uint8_t *out) { return s16_51_to_stereo(in, in_frames, out); } -static size_t _51_to_quad(struct cras_fmt_conv *conv, const uint8_t *in, - size_t in_frames, uint8_t *out) -{ - return s16_51_to_quad(in, in_frames, out); -} - static size_t stereo_to_quad(struct cras_fmt_conv *conv, const uint8_t *in, size_t in_frames, uint8_t *out) { @@ -281,21 +206,6 @@ static size_t default_all_to_all(struct cras_fmt_conv *conv, const uint8_t *in, in_frames, out); } -// Fill min(in channels, out_channels), leave the rest 0s. -static size_t default_some_to_some(struct cras_fmt_conv *conv, - const uint8_t *in, - size_t in_frames, - uint8_t *out) -{ - size_t num_in_ch, num_out_ch; - - num_in_ch = conv->in_fmt.num_channels; - num_out_ch = conv->out_fmt.num_channels; - - return s16_some_to_some(&conv->out_fmt, num_in_ch, num_out_ch, in, - in_frames, out); -} - static size_t convert_channels(struct cras_fmt_conv *conv, const uint8_t *in, size_t in_frames, uint8_t *out) { @@ -411,10 +321,7 @@ struct cras_fmt_conv *cras_fmt_conv_create(const struct cras_audio_format *in, conv->channel_converter = quad_to_stereo; } else if (in->num_channels == 2 && out->num_channels == 6) { conv->channel_converter = stereo_to_51; - } else if (in->num_channels == 4 && out->num_channels == 6) { - conv->channel_converter = quad_to_51; - } else if (in->num_channels == 6 && - (out->num_channels == 2 || out->num_channels == 4)) { + } else if (in->num_channels == 6 && out->num_channels == 2) { int in_channel_layout_set = 0; /* Checks if channel_layout is set in the incoming format */ @@ -435,44 +342,28 @@ struct cras_fmt_conv *cras_fmt_conv_create(const struct cras_audio_format *in, return NULL; } conv->channel_converter = convert_channels; - if (out->num_channels == 4) { - surround51_to_quad_downmix_mtx( - conv->ch_conv_mtx, - conv->in_fmt.channel_layout); - } else { - surround51_to_stereo_downmix_mtx( - conv->ch_conv_mtx, - conv->in_fmt.channel_layout); - } + surround51_to_stereo_downmix_mtx( + conv->ch_conv_mtx, + conv->in_fmt.channel_layout); } else { - if (out->num_channels == 4) - conv->channel_converter = _51_to_quad; - else - conv->channel_converter = _51_to_stereo; + conv->channel_converter = _51_to_stereo; } - } else if (in->num_channels <= 8 && out->num_channels <= 8) { - // For average channel counts mix from all to all. - syslog(LOG_WARNING, - "Using all_to_all map for %zu to %zu", - in->num_channels, out->num_channels); - conv->channel_converter = default_all_to_all; } else { syslog(LOG_WARNING, - "Using some_to_some channel map for %zu to %zu", + "Using default channel map for %zu to %zu", in->num_channels, out->num_channels); - conv->channel_converter = default_some_to_some; + conv->channel_converter = default_all_to_all; } } else if (in->num_channels > 2 && !is_channel_layout_equal(in, out)) { conv->num_converters++; conv->ch_conv_mtx = cras_channel_conv_matrix_create(in, out); if (conv->ch_conv_mtx == NULL) { syslog(LOG_ERR, - "Failed to create channel conversion matrix." - "Fallback to default_all_to_all."); - conv->channel_converter = default_all_to_all; - } else { - conv->channel_converter = convert_channels; + "Failed to create channel conversion matrix"); + cras_fmt_conv_destroy(&conv); + return NULL; } + conv->channel_converter = convert_channels; } /* Set up sample rate conversion. */ if (in->frame_rate != out->frame_rate) { diff --git a/cras/src/server/cras_fmt_conv_ops.c b/cras/src/server/cras_fmt_conv_ops.c index adc55215..bf479c91 100644 --- a/cras/src/server/cras_fmt_conv_ops.c +++ b/cras/src/server/cras_fmt_conv_ops.c @@ -223,44 +223,6 @@ size_t s16_stereo_to_51(size_t left, size_t right, size_t center, } /* - * Channel converter: quad to 5.1 surround. - * - * Fit the front left/right of input to the front left/right of output - * and rear left/right of input to the rear left/right of output - * respectively and fill others with zero. - */ -size_t s16_quad_to_51(size_t font_left, size_t front_right, size_t rear_left, - size_t rear_right, const uint8_t *_in, size_t in_frames, - uint8_t *_out) -{ - size_t i; - const int16_t *in = (const int16_t *)_in; - int16_t *out = (int16_t *)_out; - - memset(out, 0, sizeof(*out) * 6 * in_frames); - - if (font_left != -1 && front_right != -1 && rear_left != -1 && - rear_right != -1) - for (i = 0; i < in_frames; i++) { - out[6 * i + font_left] = in[4 * i]; - out[6 * i + front_right] = in[4 * i + 1]; - out[6 * i + rear_left] = in[4 * i + 2]; - out[6 * i + rear_right] = in[4 * i + 3]; - } - else - /* Use default 5.1 channel mapping for the conversion. - */ - for (i = 0; i < in_frames; i++) { - out[6 * i] = in[4 * i]; - out[6 * i + 1] = in[4 * i + 1]; - out[6 * i + 4] = in[4 * i + 2]; - out[6 * i + 5] = in[4 * i + 3]; - } - - return in_frames; -} - -/* * Channel converter: 5.1 surround to stereo. * * The out buffer can have room for just stereo samples. This convert function @@ -273,69 +235,20 @@ size_t s16_51_to_stereo(const uint8_t *_in, size_t in_frames, uint8_t *_out) int16_t *out = (int16_t *)_out; static const unsigned int left_idx = 0; static const unsigned int right_idx = 1; - static const unsigned int center_idx = 2; - /* static const unsigned int lfe_idx = 3; */ - /* static const unsigned int left_surround_idx = 4; */ - /* static const unsigned int right_surround_idx = 5; */ - + /* static const unsigned int left_surround_idx = 2; */ + /* static const unsigned int right_surround_idx = 3; */ + static const unsigned int center_idx = 4; + /* static const unsigned int lfe_idx = 5; */ size_t i; - int16_t half_center; - /* Use the normalized_factor from the left channel = 1 / (|1| + |0.707|) - * to prevent mixing overflow. - */ - const float normalized_factor = 0.585; + for (i = 0; i < in_frames; i++) { - half_center = - in[6 * i + center_idx] * 0.707 * normalized_factor; + unsigned int half_center; + + half_center = in[6 * i + center_idx] / 2; out[2 * i + left_idx] = - in[6 * i + left_idx] * normalized_factor + half_center; + s16_add_and_clip(in[6 * i + left_idx], half_center); out[2 * i + right_idx] = - in[6 * i + right_idx] * normalized_factor + half_center; - } - return in_frames; -} - -/* - * Channel converter: 5.1 surround to quad (front L/R, rear L/R). - * - * The out buffer can have room for just quad samples. This convert function - * is used as the default behavior when channel layout is not set from the - * client side. - */ -size_t s16_51_to_quad(const uint8_t *_in, size_t in_frames, uint8_t *_out) -{ - const int16_t *in = (const int16_t *)_in; - int16_t *out = (int16_t *)_out; - static const unsigned int l_quad = 0; - static const unsigned int r_quad = 1; - static const unsigned int rl_quad = 2; - static const unsigned int rr_quad = 3; - - static const unsigned int l_51 = 0; - static const unsigned int r_51 = 1; - static const unsigned int center_51 = 2; - static const unsigned int lfe_51 = 3; - static const unsigned int rl_51 = 4; - static const unsigned int rr_51 = 5; - - /* Use normalized_factor from the left channel = 1 / (|1| + |0.707| + |0.5|) - * to prevent overflow. */ - const float normalized_factor = 0.453; - size_t i; - for (i = 0; i < in_frames; i++) { - int16_t half_center; - int16_t lfe; - - half_center = in[6 * i + center_51] * 0.707 * normalized_factor; - lfe = in[6 * i + lfe_51] * 0.5 * normalized_factor; - out[4 * i + l_quad] = normalized_factor * in[6 * i + l_51] + - half_center + lfe; - out[4 * i + r_quad] = normalized_factor * in[6 * i + r_51] + - half_center + lfe; - out[4 * i + rl_quad] = - normalized_factor * in[6 * i + rl_51] + lfe; - out[4 * i + rr_quad] = - normalized_factor * in[6 * i + rr_51] + lfe; + s16_add_and_clip(in[6 * i + right_idx], half_center); } return in_frames; } @@ -418,50 +331,20 @@ size_t s16_default_all_to_all(struct cras_audio_format *out_fmt, unsigned int in_ch, out_ch, i; const int16_t *in = (const int16_t *)_in; int16_t *out = (int16_t *)_out; - int32_t sum; - for (i = 0; i < in_frames; i++) { - sum = 0; + memset(out, 0, in_frames * cras_get_format_bytes(out_fmt)); + for (out_ch = 0; out_ch < num_out_ch; out_ch++) { for (in_ch = 0; in_ch < num_in_ch; in_ch++) { - sum += (int32_t)in[in_ch + i * num_in_ch]; - } - /* - * 1. Divide `int32_t` by `size_t` without an explicit - * conversion will generate corrupted results. - * 2. After the division, `sum` should be in the range of - * int16_t. No clipping is needed. - */ - sum /= (int32_t)num_in_ch; - for (out_ch = 0; out_ch < num_out_ch; out_ch++) { - out[out_ch + i * num_out_ch] = (int16_t)sum; + for (i = 0; i < in_frames; i++) { + out[out_ch + i * num_out_ch] += + in[in_ch + i * num_in_ch] / num_in_ch; + } } } return in_frames; } /* - * Copies the input channels across output channels. Drops input channels that - * don't fit. Ignores output channels greater than the number of input channels. - */ -size_t s16_some_to_some(const struct cras_audio_format *out_fmt, - const size_t num_in_ch, const size_t num_out_ch, - const uint8_t *_in, const size_t frame_count, - uint8_t *_out) -{ - unsigned int i; - const int16_t *in = (const int16_t *)_in; - int16_t *out = (int16_t *)_out; - const size_t num_copy_ch = MIN(num_in_ch, num_out_ch); - - memset(out, 0, frame_count * cras_get_format_bytes(out_fmt)); - for (i = 0; i < frame_count; i++, out += num_out_ch, in += num_in_ch) { - memcpy(out, in, num_copy_ch * sizeof(int16_t)); - } - - return frame_count; -} - -/* * Multiplies buffer vector with coefficient vector. */ int16_t s16_multiply_buf_with_coef(float *coef, const int16_t *buf, size_t size) diff --git a/cras/src/server/cras_fmt_conv_ops.h b/cras/src/server/cras_fmt_conv_ops.h index 0af7564b..6943f23e 100644 --- a/cras/src/server/cras_fmt_conv_ops.h +++ b/cras/src/server/cras_fmt_conv_ops.h @@ -46,23 +46,11 @@ size_t s16_stereo_to_51(size_t left, size_t right, size_t center, const uint8_t *in, size_t in_frames, uint8_t *out); /* - * Channel converter: quad to 5.1 surround. - */ -size_t s16_quad_to_51(size_t font_left, size_t front_right, size_t rear_left, - size_t rear_right, const uint8_t *in, size_t in_frames, - uint8_t *out); - -/* * Channel converter: 5.1 surround to stereo. */ size_t s16_51_to_stereo(const uint8_t *in, size_t in_frames, uint8_t *out); /* - * Channel converter: 5.1 surround to quad. - */ -size_t s16_51_to_quad(const uint8_t *in, size_t in_frames, uint8_t *out); - -/* * Channel converter: stereo to quad (front L/R, rear L/R). */ size_t s16_stereo_to_quad(size_t front_left, size_t front_right, @@ -85,15 +73,6 @@ size_t s16_default_all_to_all(struct cras_audio_format *out_fmt, uint8_t *out); /* - * Channel converter: N channels to M channels filling min(N,M) channels by - * directly copying to the destination. - */ -size_t s16_some_to_some(const struct cras_audio_format *out_fmt, - const size_t num_in_ch, const size_t num_out_ch, - const uint8_t *_in, const size_t frame_count, - uint8_t *_out); - -/* * Multiplies buffer vector with coefficient vector. */ int16_t s16_multiply_buf_with_coef(float *coef, const int16_t *buf, diff --git a/cras/src/server/cras_hfp_ag_profile.c b/cras/src/server/cras_hfp_ag_profile.c index b5fcecc3..63201914 100644 --- a/cras/src/server/cras_hfp_ag_profile.c +++ b/cras/src/server/cras_hfp_ag_profile.c @@ -21,11 +21,10 @@ #include "cras_system_state.h" #include "cras_iodev_list.h" #include "utlist.h" -#include "packet_status_logger.h" #define HFP_AG_PROFILE_NAME "Hands-Free Voice gateway" #define HFP_AG_PROFILE_PATH "/org/chromium/Cras/Bluetooth/HFPAG" -#define HFP_VERSION 0x0107 +#define HFP_VERSION_1_5 0x0105 #define HSP_AG_PROFILE_NAME "Headset Voice gateway" #define HSP_AG_PROFILE_PATH "/org/chromium/Cras/Bluetooth/HSPAG" #define HSP_VERSION_1_2 0x0102 @@ -72,12 +71,6 @@ " </attribute>" \ "</record>" -/* The supported features value in +BSRF command response of HFP AG in CRAS */ -#define BSRF_SUPPORTED_FEATURES (AG_ENHANCED_CALL_STATUS | AG_HF_INDICATORS) - -/* The "SupportedFeatures" attribute value of HFP AG service record in CRAS. */ -#define SDP_SUPPORTED_FEATURES FEATURES_AG_WIDE_BAND_SPEECH - /* Object representing the audio gateway role for HFP/HSP. * Members: * idev - The input iodev for HFP/HSP. @@ -103,7 +96,6 @@ struct audio_gateway { }; static struct audio_gateway *connected_ags; -static struct packet_status_logger wbs_logger; static int need_go_sco_pcm(struct cras_bt_device *device) { @@ -115,9 +107,6 @@ static void destroy_audio_gateway(struct audio_gateway *ag) { DL_DELETE(connected_ags, ag); - cras_server_metrics_hfp_battery_indicator( - hfp_slc_get_hf_supports_battery_indicator(ag->slc_handle)); - if (need_go_sco_pcm(ag->device)) { if (ag->idev) hfp_alsa_iodev_destroy(ag->idev); @@ -175,14 +164,6 @@ static int cras_hfp_ag_slc_initialized(struct hfp_slc_handle *handle) cras_server_metrics_hfp_wideband_support( hfp_slc_get_hf_codec_negotiation_supported(handle)); - /* Log the final selected codec given that codec negotiation is - * supported. - */ - if (hfp_slc_get_hf_codec_negotiation_supported(handle) && - hfp_slc_get_ag_codec_negotiation_supported(handle)) - cras_server_metrics_hfp_wideband_selected_codec( - hfp_slc_get_selected_codec(handle)); - /* Defer the starting of audio gateway to bt_device. */ return cras_bt_device_audio_gateway_initialized(ag->device); } @@ -268,8 +249,8 @@ static int cras_hfp_ag_new_connection(DBusConnection *conn, * TODO(hychao): AND the two conditions to let bluetooth daemon * control whether to turn on WBS feature. */ - ag_features = BSRF_SUPPORTED_FEATURES; - if (cras_system_get_bt_wbs_enabled() && adapter && + ag_features = profile->features; + if (cras_system_get_bt_wbs_enabled() && cras_bt_adapter_wbs_supported(adapter)) ag_features |= AG_CODEC_NEGOTIATION; @@ -289,10 +270,10 @@ static void cras_hfp_ag_request_disconnection(struct cras_bt_profile *profile, DL_FOREACH (connected_ags, ag) { if (ag->slc_handle && ag->device == device) { + destroy_audio_gateway(ag); cras_bt_device_notify_profile_dropped( ag->device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); - destroy_audio_gateway(ag); } } } @@ -305,9 +286,9 @@ static struct cras_bt_profile cras_hfp_ag_profile = { .name = HFP_AG_PROFILE_NAME, .object_path = HFP_AG_PROFILE_PATH, .uuid = HFP_AG_UUID, - .version = HFP_VERSION, + .version = HFP_VERSION_1_5, .role = NULL, - .features = SDP_SUPPORTED_FEATURES, + .features = CRAS_AG_SUPPORTED_FEATURES & 0x1F, .record = NULL, .release = cras_hfp_ag_release, .new_connection = cras_hfp_ag_new_connection, @@ -344,9 +325,8 @@ static int cras_hsp_ag_new_connection(DBusConnection *conn, ag->device = device; ag->conn = conn; ag->profile = cras_bt_device_profile_from_uuid(profile->uuid); - ag->slc_handle = - hfp_slc_create(rfcomm_fd, 1, BSRF_SUPPORTED_FEATURES, device, - NULL, cras_hfp_ag_slc_disconnected); + ag->slc_handle = hfp_slc_create(rfcomm_fd, 1, profile->features, device, + NULL, cras_hfp_ag_slc_disconnected); DL_APPEND(connected_ags, ag); cras_hfp_ag_slc_initialized(ag->slc_handle); return 0; @@ -361,9 +341,9 @@ static void cras_hsp_ag_request_disconnection(struct cras_bt_profile *profile, DL_FOREACH (connected_ags, ag) { if (ag->slc_handle && ag->device == device) { + destroy_audio_gateway(ag); cras_bt_device_notify_profile_dropped( ag->device, CRAS_BT_DEVICE_PROFILE_HSP_HEADSET); - destroy_audio_gateway(ag); } } } @@ -411,8 +391,8 @@ int cras_hfp_ag_start(struct cras_bt_device *device) ag->odev = hfp_alsa_iodev_create(out_aio, ag->device, ag->slc_handle, ag->profile); } else { - ag->info = hfp_info_create(); - hfp_info_set_wbs_logger(ag->info, &wbs_logger); + ag->info = hfp_info_create( + hfp_slc_get_selected_codec(ag->slc_handle)); ag->idev = hfp_iodev_create(CRAS_STREAM_INPUT, ag->device, ag->slc_handle, ag->profile, ag->info); @@ -455,11 +435,6 @@ struct hfp_slc_handle *cras_hfp_ag_get_slc(struct cras_bt_device *device) return NULL; } -struct packet_status_logger *cras_hfp_ag_get_wbs_logger() -{ - return &wbs_logger; -} - int cras_hsp_ag_profile_create(DBusConnection *conn) { return cras_bt_add_profile(conn, &cras_hsp_ag_profile); diff --git a/cras/src/server/cras_hfp_ag_profile.h b/cras/src/server/cras_hfp_ag_profile.h index 3de56184..4c1d49d2 100644 --- a/cras/src/server/cras_hfp_ag_profile.h +++ b/cras/src/server/cras_hfp_ag_profile.h @@ -7,22 +7,12 @@ #define CRAS_HFP_AG_PROFILE_H_ #include <dbus/dbus.h> -#include <stdbool.h> #include "cras_bt_device.h" #include "cras_hfp_slc.h" -/* - * For service record profile, 'SupportedFearues' attribute bit mapping - * for HFP AG. Bits 0 to 4 are identical to the unsolicited result code - * of +BRSF command. - */ -#define FEATURES_AG_THREE_WAY_CALLING 0x0001 -#define FEATURES_AG_EC_ANDOR_NR 0x0002 -#define FEATURES_AG_VOICE_RECOGNITION 0x0004 -#define FEATURES_AG_INBAND_RINGTONE 0x0008 -#define FEATURES_AG_ATTACH_NUMBER_TO_VOICETAG 0x0010 -#define FEATURES_AG_WIDE_BAND_SPEECH 0x0020 +/* The bitmap of HFP AG feature supported by CRAS */ +#define CRAS_AG_SUPPORTED_FEATURES (AG_ENHANCED_CALL_STATUS) struct hfp_slc_handle; @@ -53,7 +43,4 @@ struct hfp_slc_handle *cras_hfp_ag_get_active_handle(); /* Gets the SLC handle for given cras_bt_device. */ struct hfp_slc_handle *cras_hfp_ag_get_slc(struct cras_bt_device *device); -/* Gets the logger for WBS packet status. */ -struct packet_status_logger *cras_hfp_ag_get_wbs_logger(); - #endif /* CRAS_HFP_AG_PROFILE_H_ */ diff --git a/cras/src/server/cras_hfp_alsa_iodev.c b/cras/src/server/cras_hfp_alsa_iodev.c index c1b60b30..aecc47b9 100644 --- a/cras/src/server/cras_hfp_alsa_iodev.c +++ b/cras/src/server/cras_hfp_alsa_iodev.c @@ -12,6 +12,7 @@ #include "cras_iodev.h" #include "cras_system_state.h" #include "cras_util.h" +#include "sfh.h" #include "utlist.h" #include "cras_bt_device.h" @@ -32,15 +33,6 @@ struct hfp_alsa_io { struct cras_iodev *aio; }; -static int hfp_alsa_get_valid_frames(struct cras_iodev *iodev, - struct timespec *hw_tstamp) -{ - struct hfp_alsa_io *hfp_alsa_io = (struct hfp_alsa_io *)iodev; - struct cras_iodev *aio = hfp_alsa_io->aio; - - return aio->get_valid_frames(aio, hw_tstamp); -} - static int hfp_alsa_open_dev(struct cras_iodev *iodev) { struct hfp_alsa_io *hfp_alsa_io = (struct hfp_alsa_io *)iodev; @@ -51,7 +43,41 @@ static int hfp_alsa_open_dev(struct cras_iodev *iodev) static int hfp_alsa_update_supported_formats(struct cras_iodev *iodev) { + struct hfp_alsa_io *hfp_alsa_io = (struct hfp_alsa_io *)iodev; + struct cras_iodev *aio = hfp_alsa_io->aio; + int rc, i; + /* 16 bit, mono, 8kHz (narrow band speech); */ + rc = aio->update_supported_formats(aio); + if (rc) + return rc; + + for (i = 0; aio->supported_rates[i]; ++i) + if (aio->supported_rates[i] == 8000) + break; + if (aio->supported_rates[i] != 8000) + return -EINVAL; + + for (i = 0; aio->supported_channel_counts[i]; ++i) + if (aio->supported_channel_counts[i] == 1) + break; + if (aio->supported_channel_counts[i] != 1) + return -EINVAL; + + for (i = 0; aio->supported_formats[i]; ++i) + if (aio->supported_formats[i] == SND_PCM_FORMAT_S16_LE) + break; + if (aio->supported_formats[i] != SND_PCM_FORMAT_S16_LE) + return -EINVAL; + + free(aio->format); + aio->format = malloc(sizeof(struct cras_audio_format)); + if (!aio->format) + return -ENOMEM; + aio->format->format = SND_PCM_FORMAT_S16_LE; + aio->format->frame_rate = 8000; + aio->format->num_channels = 1; + free(iodev->supported_rates); iodev->supported_rates = malloc(2 * sizeof(*iodev->supported_rates)); if (!iodev->supported_rates) @@ -84,15 +110,6 @@ static int hfp_alsa_configure_dev(struct cras_iodev *iodev) struct cras_iodev *aio = hfp_alsa_io->aio; int rc; - /* Fill back the format iodev is using. */ - if (aio->format == NULL) { - aio->format = (struct cras_audio_format *)malloc( - sizeof(*aio->format)); - if (!aio->format) - return -ENOMEM; - *aio->format = *iodev->format; - } - rc = aio->configure_dev(aio); if (rc) { syslog(LOG_ERR, "Failed to configure aio: %d\n", rc); @@ -118,7 +135,6 @@ static int hfp_alsa_close_dev(struct cras_iodev *iodev) struct hfp_alsa_io *hfp_alsa_io = (struct hfp_alsa_io *)iodev; struct cras_iodev *aio = hfp_alsa_io->aio; - hfp_set_call_status(hfp_alsa_io->slc, 0); cras_bt_device_put_sco(hfp_alsa_io->device); cras_iodev_free_format(iodev); return aio->close_dev(aio); @@ -218,21 +234,6 @@ static int hfp_alsa_is_free_running(const struct cras_iodev *iodev) return aio->is_free_running(aio); } -static int hfp_alsa_output_underrun(struct cras_iodev *iodev) -{ - struct hfp_alsa_io *hfp_alsa_io = (struct hfp_alsa_io *)iodev; - struct cras_iodev *aio = hfp_alsa_io->aio; - - /* - * Copy iodev->min_cb_level and iodev->max_cb_level from the parent - * (i.e. hfp_alsa_iodev). output_underrun() of alsa_io will use them. - */ - aio->min_cb_level = iodev->min_cb_level; - aio->max_cb_level = iodev->max_cb_level; - - return aio->output_underrun(aio); -} - struct cras_iodev *hfp_alsa_iodev_create(struct cras_iodev *aio, struct cras_bt_device *device, struct hfp_slc_handle *slc, @@ -258,9 +259,13 @@ struct cras_iodev *hfp_alsa_iodev_create(struct cras_iodev *aio, name = cras_bt_device_name(device); if (!name) name = cras_bt_device_object_path(device); - snprintf(iodev->info.name, sizeof(iodev->info.name), "%s", name); + snprintf(iodev->info.name, sizeof(iodev->info.name), "%s.HFP_PCM", + name); iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = 0; - iodev->info.stable_id = cras_bt_device_get_stable_id(device); + iodev->info.stable_id = + SuperFastHash(cras_bt_device_object_path(device), + strlen(cras_bt_device_object_path(device)), + strlen(cras_bt_device_object_path(device))); iodev->open_dev = hfp_alsa_open_dev; iodev->update_supported_formats = hfp_alsa_update_supported_formats; @@ -276,10 +281,8 @@ struct cras_iodev *hfp_alsa_iodev_create(struct cras_iodev *aio, iodev->update_active_node = hfp_alsa_update_active_node; iodev->start = hfp_alsa_start; iodev->set_volume = hfp_alsa_set_volume; - iodev->get_valid_frames = hfp_alsa_get_valid_frames; iodev->no_stream = hfp_alsa_no_stream; iodev->is_free_running = hfp_alsa_is_free_running; - iodev->output_underrun = hfp_alsa_output_underrun; iodev->min_buffer_level = aio->min_buffer_level; @@ -288,28 +291,13 @@ struct cras_iodev *hfp_alsa_iodev_create(struct cras_iodev *aio, strcpy(node->name, iodev->info.name); node->plugged = 1; - /* If headset mic uses legacy narrow band, i.e CVSD codec, report a - * different node type so UI can set different plug priority. */ node->type = CRAS_NODE_TYPE_BLUETOOTH; - if ((hfp_slc_get_selected_codec(hfp_alsa_io->slc) == - HFP_CODEC_ID_CVSD) && - (iodev->direction == CRAS_STREAM_INPUT)) - node->type = CRAS_NODE_TYPE_BLUETOOTH_NB_MIC; node->volume = 100; gettimeofday(&node->plugged_time, NULL); - /* Prepare active node before append, so bt_io can extract correct - * info from hfp_alsa iodev and node. */ + cras_bt_device_append_iodev(device, iodev, profile); cras_iodev_add_node(iodev, node); cras_iodev_set_active_node(iodev, node); - cras_bt_device_append_iodev(device, iodev, profile); - - /* Record max supported channels into cras_iodev_info. */ - iodev->info.max_supported_channels = 1; - - /* Specifically disable EWMA calculation on this and the child iodev. */ - ewma_power_disable(&iodev->ewma); - ewma_power_disable(&aio->ewma); return iodev; } diff --git a/cras/src/server/cras_hfp_info.c b/cras/src/server/cras_hfp_info.c index fc407b29..02bc8b4c 100644 --- a/cras/src/server/cras_hfp_info.c +++ b/cras/src/server/cras_hfp_info.c @@ -10,7 +10,6 @@ #include <syslog.h> #include "audio_thread.h" -#include "bluetooth.h" #include "byte_buffer.h" #include "cras_hfp_info.h" #include "cras_hfp_slc.h" @@ -19,7 +18,6 @@ #include "cras_sbc_codec.h" #include "cras_server_metrics.h" #include "utlist.h" -#include "packet_status_logger.h" /* The max buffer size. Note that the actual used size must set to multiple * of SCO packet size, and the packet size does not necessarily be equal to @@ -41,21 +39,12 @@ /* For one mSBC 1 compressed wideband audio channel the HCI packets will * be 3 octets of HCI header + 60 octets of data. */ #define MSBC_PKT_SIZE 60 +#define WRITE_BUF_SIZE_BYTES MSBC_PKT_SIZE +#define HCI_SCO_HDR_SIZE_BYTES 3 +#define HCI_SCO_PKT_SIZE (MSBC_PKT_SIZE + HCI_SCO_HDR_SIZE_BYTES) #define H2_HEADER_0 0x01 -/* Supported HCI SCO packet sizes. The wideband speech mSBC frame parsing - * code ties to limited packet size values. Specifically list them out - * to check against when setting packet size. - * - * Temp buffer size should be set to least common multiple of HCI SCO packet - * size and MSBC_PKT_SIZE for optimizing buffer copy. - * To add a new supported packet size value, add corresponding entry to the - * lists, test the read/write msbc code, and fix the code if needed. - */ -static const size_t wbs_supported_packet_size[] = { 60, 24, 0 }; -static const size_t wbs_hci_sco_buffer_size[] = { 60, 120, 0 }; - /* Second octet of H2 header is composed by 4 bits fixed 0x8 and 4 bits * sequence number 0000, 0011, 1100, 1111. */ static const uint8_t h2_header_frames_count[] = { 0x08, 0x38, 0xc8, 0xf8 }; @@ -81,20 +70,11 @@ static const uint8_t h2_header_frames_count[] = { 0x08, 0x38, 0xc8, 0xf8 }; * read_cb - Callback to call when SCO socket can read. It returns the * number of PCM bytes read. * write_cb - Callback to call when SCO socket can write. - * write_buf - Temp buffer for writeing HCI SCO packet in wideband. - * read_buf - Temp buffer for reading HCI SCO packet in wideband. + * hci_sco_buf - Buffer to read one HCI SCO packet. * input_format_bytes - The audio format bytes for input device. 0 means * there is no input device for the hfp_info. * output_format_bytes - The audio format bytes for output device. 0 means * there is no output device for the hfp_info. - * write_wp - Write pointer of write_buf. - * write_rp - Read pointer of write_buf. - * read_wp - Write pointer of read_buf. - * read_rp - Read pointer of read_buf. - * read_align_cb - Callback used to align mSBC frame reading with read buf. - * msbc_read_current_corrupted - Flag to mark if the current mSBC frame - * read is corrupted. - * wbs_logger - The logger for packet status in WBS. */ struct hfp_info { int fd; @@ -111,17 +91,10 @@ struct hfp_info { unsigned int msbc_num_lost_frames; int (*read_cb)(struct hfp_info *info); int (*write_cb)(struct hfp_info *info); - uint8_t *write_buf; - uint8_t *read_buf; + uint8_t write_buf[WRITE_BUF_SIZE_BYTES]; + uint8_t hci_sco_buf[HCI_SCO_PKT_SIZE]; size_t input_format_bytes; size_t output_format_bytes; - size_t write_wp; - size_t write_rp; - size_t read_wp; - size_t read_rp; - int (*read_align_cb)(uint8_t *buf); - bool msbc_read_current_corrupted; - struct packet_status_logger *wbs_logger; }; int hfp_info_add_iodev(struct hfp_info *info, @@ -266,66 +239,43 @@ int hfp_write_msbc(struct hfp_info *info) size_t encoded; int err; int pcm_encoded; - unsigned int pcm_avail, to_write; + unsigned int pcm_avail; uint8_t *samples; uint8_t *wp; - if (info->write_rp + info->packet_size <= info->write_wp) - goto msbc_send_again; - - /* Make sure there are MSBC_CODE_SIZE bytes to encode. */ samples = buf_read_pointer_size(info->playback_buf, &pcm_avail); - if (pcm_avail < MSBC_CODE_SIZE) { - to_write = MSBC_CODE_SIZE - pcm_avail; - /* - * Size of playback_buf is multiple of MSBC_CODE_SIZE so we - * are safe to prepare the buffer by appending some zero bytes. - */ - wp = buf_write_pointer_size(info->playback_buf, &pcm_avail); - memset(wp, 0, to_write); - buf_increment_write(info->playback_buf, to_write); - - samples = buf_read_pointer_size(info->playback_buf, &pcm_avail); - if (pcm_avail < MSBC_CODE_SIZE) - return -EINVAL; - } - - /* Encode the next MSBC_CODE_SIZE of bytes. */ - wp = info->write_buf + info->write_wp; - wp[0] = H2_HEADER_0; - wp[1] = h2_header_frames_count[info->msbc_num_out_frames % 4]; - pcm_encoded = info->msbc_write->encode( - info->msbc_write, samples, pcm_avail, wp + MSBC_H2_HEADER_LEN, - MSBC_PKT_SIZE - MSBC_H2_HEADER_LEN, &encoded); - if (pcm_encoded < 0) { - syslog(LOG_ERR, "msbc encoding err: %s", strerror(pcm_encoded)); - return pcm_encoded; + wp = info->write_buf; + if (pcm_avail >= MSBC_CODE_SIZE) { + /* Encode more */ + wp[0] = H2_HEADER_0; + wp[1] = h2_header_frames_count[info->msbc_num_out_frames % 4]; + pcm_encoded = info->msbc_write->encode( + info->msbc_write, samples, pcm_avail, + wp + MSBC_H2_HEADER_LEN, + WRITE_BUF_SIZE_BYTES - MSBC_H2_HEADER_LEN, &encoded); + if (pcm_encoded < 0) { + syslog(LOG_ERR, "msbc encoding err: %s", + strerror(pcm_encoded)); + return pcm_encoded; + } + buf_increment_read(info->playback_buf, pcm_encoded); + pcm_avail -= pcm_encoded; + } else { + memset(wp, 0, WRITE_BUF_SIZE_BYTES); } - buf_increment_read(info->playback_buf, pcm_encoded); - pcm_avail -= pcm_encoded; - info->write_wp += MSBC_PKT_SIZE; - info->msbc_num_out_frames++; - - if (info->write_rp + info->packet_size > info->write_wp) - return 0; msbc_send_again: - err = send(info->fd, info->write_buf + info->write_rp, - info->packet_size, 0); + err = send(info->fd, info->write_buf, MSBC_PKT_SIZE, 0); if (err < 0) { if (errno == EINTR) goto msbc_send_again; return err; } - if (err != (int)info->packet_size) { + if (err != MSBC_PKT_SIZE) { syslog(LOG_ERR, "Partially write %d bytes for mSBC", err); return -1; } - info->write_rp += info->packet_size; - if (info->write_rp == info->write_wp) { - info->write_rp = 0; - info->write_wp = 0; - } + info->msbc_num_out_frames++; return err; } @@ -406,20 +356,6 @@ static const uint8_t *extract_msbc_frame(const uint8_t *input, int len, return NULL; } -/* Log value 0 when packet is received. */ -static void log_wbs_packet_received(struct hfp_info *info) -{ - if (info->wbs_logger) - packet_status_logger_update(info->wbs_logger, 0); -} - -/* Log value 1 when packet is lost. */ -static void log_wbs_packet_lost(struct hfp_info *info) -{ - if (info->wbs_logger) - packet_status_logger_update(info->wbs_logger, 1); -} - /* * Handle the case when mSBC frame is considered lost. * Args: @@ -436,8 +372,6 @@ static int handle_packet_loss(struct hfp_info *info) info->msbc_num_in_frames++; info->msbc_num_lost_frames++; - log_wbs_packet_lost(info); - in_bytes = buf_write_pointer_size(info->capture_buf, &pcm_avail); if (pcm_avail < MSBC_CODE_SIZE) return 0; @@ -452,16 +386,6 @@ static int handle_packet_loss(struct hfp_info *info) return decoded; } -/* Checks if mSBC frame header aligns with the beginning of buffer. */ -static int msbc_frame_align(uint8_t *buf) -{ - if ((buf[0] != H2_HEADER_0) || (buf[2] != MSBC_SYNC_WORD)) { - syslog(LOG_DEBUG, "Waiting for valid mSBC frame head"); - return 0; - } - return 1; -} - int hfp_read_msbc(struct hfp_info *info) { int err = 0; @@ -473,23 +397,8 @@ int hfp_read_msbc(struct hfp_info *info) const uint8_t *frame_head = NULL; unsigned int seq; - struct msghdr msg = { 0 }; - struct iovec iov; - struct cmsghdr *cmsg; - const unsigned int control_size = CMSG_SPACE(sizeof(int)); - char control[control_size]; - uint8_t pkt_status; - - memset(control, 0, sizeof(control)); recv_msbc_bytes: - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - iov.iov_base = info->read_buf + info->read_wp; - iov.iov_len = info->packet_size; - msg.msg_control = control; - msg.msg_controllen = control_size; - - err = recvmsg(info->fd, &msg, 0); + err = recv(info->fd, info->hci_sco_buf, HCI_SCO_PKT_SIZE, 0); if (err < 0) { syslog(LOG_ERR, "HCI SCO packet read err %s", strerror(errno)); if (errno == EINTR) @@ -500,78 +409,40 @@ recv_msbc_bytes: * Treat return code 0 (socket shutdown) as error here. BT stack * shall send signal to main thread for device disconnection. */ - if (err != (int)info->packet_size) { + if (err != HCI_SCO_PKT_SIZE) { syslog(LOG_ERR, "Partially read %d bytes for mSBC packet", err); return -1; } - /* Offset in input data breaks mSBC frame parsing. Discard this packet - * until read alignment succeed. */ - if (info->read_align_cb) { - if (!info->read_align_cb(info->read_buf)) - return 0; - else - info->read_align_cb = NULL; - } - info->read_wp += err; - - pkt_status = 0; - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_BLUETOOTH && - cmsg->cmsg_type == BT_SCM_PKT_STATUS) { - size_t len = cmsg->cmsg_len - sizeof(*cmsg); - memcpy(&pkt_status, CMSG_DATA(cmsg), len); - } - } - /* * HCI SCO packet status flag: * 0x00 - correctly received data. * 0x01 - possibly invalid data. * 0x10 - No data received. * 0x11 - Data partially lost. - * - * If the latest SCO packet read doesn't cross the boundary of a mSBC - * frame, the packet status flag can be used to derive if the current - * mSBC frame is corrupted. */ - if (info->read_rp + MSBC_PKT_SIZE >= info->read_wp) - info->msbc_read_current_corrupted |= (pkt_status > 0); - - /* Read buffer not enough to parse another mSBC frame. */ - if (info->read_rp + MSBC_PKT_SIZE > info->read_wp) - return 0; - - if (info->msbc_read_current_corrupted) { - syslog(LOG_DEBUG, "mSBC frame corrputed from packet status"); - info->msbc_read_current_corrupted = 0; - frame_head = NULL; - } else { - frame_head = - extract_msbc_frame(info->read_buf + info->read_rp, - info->read_wp - info->read_rp, &seq); - if (!frame_head) - syslog(LOG_DEBUG, "Failed to extract msbc frame"); + err = (info->hci_sco_buf[1] >> 4); + if (err) { + syslog(LOG_ERR, "HCI SCO status flag %u", err); + return handle_packet_loss(info); } - /* - * Done with parsing the raw bytes just read. If mSBC frame head not - * found, we shall handle it as packet loss. + /* There is chance that erroneous data reporting gives us false positive. + * If mSBC frame extraction fails, we shall handle it as packet loss. */ - info->read_rp += MSBC_PKT_SIZE; - if (info->read_rp == info->read_wp) { - info->read_rp = 0; - info->read_wp = 0; - } - if (!frame_head) + frame_head = + extract_msbc_frame(info->hci_sco_buf + HCI_SCO_HDR_SIZE_BYTES, + MSBC_PKT_SIZE, &seq); + if (!frame_head) { + syslog(LOG_ERR, "Failed to extract msbc frame"); return handle_packet_loss(info); + } /* * Consider packet loss when found discontinuity in sequence number. */ while (seq != (info->msbc_num_in_frames % 4)) { - syslog(LOG_DEBUG, "SCO packet seq unmatch"); + syslog(LOG_ERR, "SCO packet seq unmatch"); err = handle_packet_loss(info); if (err < 0) return err; @@ -599,7 +470,6 @@ recv_msbc_bytes: pcm_read += err; } else { /* Good mSBC frame decoded. */ - log_wbs_packet_received(info); buf_increment_write(info->capture_buf, pcm_decoded); info->msbc_num_in_frames++; cras_msbc_plc_handle_good_frames(info->msbc_plc, capture_buf, @@ -661,31 +531,24 @@ recv_sample: * 2. When input device not attached, ignore the data just read. * 3. When output device attached, write one chunk of MTU bytes of data. */ -static int hfp_info_callback(void *arg, int revents) +static int hfp_info_callback(void *arg) { struct hfp_info *info = (struct hfp_info *)arg; - int err = 0; + int err; if (!info->started) return 0; - /* Allow last read before handling error or hang-up events. */ - if (revents & POLLIN) { - err = info->read_cb(info); - if (err < 0) { - syslog(LOG_ERR, "Read error"); - goto read_write_error; - } + err = info->read_cb(info); + if (err < 0) { + syslog(LOG_ERR, "Read error"); + goto read_write_error; } + /* Ignore the bytes just read if input dev not in present */ if (!info->input_format_bytes) buf_increment_read(info->capture_buf, err); - if (revents & (POLLERR | POLLHUP)) { - syslog(LOG_ERR, "Error polling SCO socket, revent %d", revents); - goto read_write_error; - } - /* Without output stream's presence, we shall still send zero packets * to HF. This is required for some HF devices to start sending non-zero * data to AG. @@ -715,7 +578,7 @@ read_write_error: return 0; } -struct hfp_info *hfp_info_create() +struct hfp_info *hfp_info_create(int codec) { struct hfp_info *info; info = (struct hfp_info *)calloc(1, sizeof(*info)); @@ -730,6 +593,17 @@ struct hfp_info *hfp_info_create() if (!info->playback_buf) goto error; + if (codec == HFP_CODEC_ID_MSBC) { + info->write_cb = hfp_write_msbc; + info->read_cb = hfp_read_msbc; + info->msbc_read = cras_msbc_codec_create(); + info->msbc_write = cras_msbc_codec_create(); + info->msbc_plc = cras_msbc_plc_create(); + } else { + info->write_cb = hfp_write; + info->read_cb = hfp_read; + } + return info; error: @@ -743,18 +617,12 @@ error: return NULL; } -void hfp_info_set_wbs_logger(struct hfp_info *info, - struct packet_status_logger *wbs_logger) -{ - info->wbs_logger = wbs_logger; -} - int hfp_info_running(struct hfp_info *info) { return info->started; } -int hfp_info_start(int fd, unsigned int mtu, int codec, struct hfp_info *info) +int hfp_info_start(int fd, unsigned int mtu, struct hfp_info *info) { info->fd = fd; info->mtu = mtu; @@ -764,51 +632,12 @@ int hfp_info_start(int fd, unsigned int mtu, int codec, struct hfp_info *info) buf_reset(info->playback_buf); buf_reset(info->capture_buf); - if (codec == HFP_CODEC_ID_MSBC) { - int i; - for (i = 0; wbs_supported_packet_size[i] != 0; i++) { - if (info->packet_size == wbs_supported_packet_size[i]) - break; - } - /* In case of unsupported value, error log and fallback to - * MSBC_PKT_SIZE(60). */ - if (wbs_supported_packet_size[i] == 0) { - syslog(LOG_ERR, "Unsupported packet size %u", - info->packet_size); - i = 0; - } - info->packet_size = wbs_supported_packet_size[i]; - info->write_buf = (uint8_t *)malloc(wbs_hci_sco_buffer_size[i]); - info->read_buf = (uint8_t *)malloc(wbs_hci_sco_buffer_size[i]); - - info->write_cb = hfp_write_msbc; - info->read_cb = hfp_read_msbc; - info->msbc_read = cras_msbc_codec_create(); - info->msbc_write = cras_msbc_codec_create(); - info->msbc_plc = cras_msbc_plc_create(); - - packet_status_logger_init(info->wbs_logger); - } else { - info->write_cb = hfp_write; - info->read_cb = hfp_read; - } - - audio_thread_add_events_callback(info->fd, hfp_info_callback, info, - POLLIN | POLLERR | POLLHUP); + audio_thread_add_callback(info->fd, hfp_info_callback, info); info->started = 1; info->msbc_num_out_frames = 0; info->msbc_num_in_frames = 0; info->msbc_num_lost_frames = 0; - info->write_rp = 0; - info->write_wp = 0; - info->read_rp = 0; - info->read_wp = 0; - - /* Mark as aligned if packet size equals to MSBC_PKT_SIZE. */ - info->read_align_cb = - (info->packet_size == MSBC_PKT_SIZE) ? NULL : msbc_frame_align; - info->msbc_read_current_corrupted = 0; return 0; } @@ -825,28 +654,6 @@ int hfp_info_stop(struct hfp_info *info) info->fd = 0; info->started = 0; - /* Unset the write/read callbacks. */ - info->write_cb = NULL; - info->read_cb = NULL; - - if (info->write_buf) - free(info->write_buf); - if (info->read_buf) - free(info->read_buf); - - if (info->msbc_read) { - cras_sbc_codec_destroy(info->msbc_read); - info->msbc_read = NULL; - } - if (info->msbc_write) { - cras_sbc_codec_destroy(info->msbc_write); - info->msbc_write = NULL; - } - if (info->msbc_plc) { - cras_msbc_plc_destroy(info->msbc_plc); - info->msbc_plc = NULL; - } - if (info->msbc_num_in_frames) { cras_server_metrics_hfp_packet_loss( (float)info->msbc_num_lost_frames / @@ -864,5 +671,12 @@ void hfp_info_destroy(struct hfp_info *info) if (info->playback_buf) byte_buffer_destroy(&info->playback_buf); + if (info->msbc_read) + cras_sbc_codec_destroy(info->msbc_read); + if (info->msbc_write) + cras_sbc_codec_destroy(info->msbc_write); + if (info->msbc_plc) + cras_msbc_plc_destroy(info->msbc_plc); + free(info); } diff --git a/cras/src/server/cras_hfp_info.h b/cras/src/server/cras_hfp_info.h index 3472aeab..334278e5 100644 --- a/cras/src/server/cras_hfp_info.h +++ b/cras/src/server/cras_hfp_info.h @@ -24,25 +24,21 @@ struct hfp_packet_size_changed_callback { struct hfp_info; /* Creates an hfp_info instance. + * Args: + * codec - 1 for CVSD, 2 for mSBC per HFP 1.7 specification. */ -struct hfp_info *hfp_info_create(); +struct hfp_info *hfp_info_create(int codec); /* Destroys given hfp_info instance. */ void hfp_info_destroy(struct hfp_info *info); -/* Sets the wbs_logger to hfp_info instance. */ -void hfp_info_set_wbs_logger(struct hfp_info *info, - struct packet_status_logger *wbs_logger); - /* Checks if given hfp_info is running. */ int hfp_info_running(struct hfp_info *info); /* Starts the hfp_info to transmit and reveice samples to and from the file * descriptor of a SCO socket. This should be called from main thread. - * Args: - * codec - 1 for CVSD, 2 for mSBC per HFP 1.7 specification. */ -int hfp_info_start(int fd, unsigned int mtu, int codec, struct hfp_info *info); +int hfp_info_start(int fd, unsigned int mtu, struct hfp_info *info); /* Stops given hfp_info. This implies sample transmission will * stop and socket be closed. This should be called from main thread. diff --git a/cras/src/server/cras_hfp_iodev.c b/cras/src/server/cras_hfp_iodev.c index 6a4ced04..08e26d6d 100644 --- a/cras/src/server/cras_hfp_iodev.c +++ b/cras/src/server/cras_hfp_iodev.c @@ -17,6 +17,7 @@ #include "cras_iodev.h" #include "cras_system_state.h" #include "cras_util.h" +#include "sfh.h" #include "utlist.h" /* Implementation of bluetooth hands-free profile iodev. @@ -43,10 +44,12 @@ static int update_supported_formats(struct cras_iodev *iodev) { struct hfp_io *hfpio = (struct hfp_io *)iodev; + /* 16 bit, mono, 8kHz for narrowband and 16KHz for wideband */ + iodev->format->format = SND_PCM_FORMAT_S16_LE; + free(iodev->supported_rates); iodev->supported_rates = (size_t *)malloc(2 * sizeof(size_t)); - /* 16 bit, mono, 8kHz for narrowband and 16KHz for wideband */ iodev->supported_rates[0] = (hfp_slc_get_selected_codec(hfpio->slc) == HFP_CODEC_ID_MSBC) ? 16000 : @@ -122,12 +125,6 @@ static int frames_queued(const struct cras_iodev *iodev, return hfp_buf_queued(hfpio->info, iodev->direction); } -static int output_underrun(struct cras_iodev *iodev) -{ - /* Handle it the same way as cras_iodev_output_underrun(). */ - return cras_iodev_fill_odev_zeros(iodev, iodev->min_cb_level); -} - static int configure_dev(struct cras_iodev *iodev) { struct hfp_io *hfpio = (struct hfp_io *)iodev; @@ -136,18 +133,12 @@ static int configure_dev(struct cras_iodev *iodev) /* Assert format is set before opening device. */ if (iodev->format == NULL) return -EINVAL; - iodev->format->format = SND_PCM_FORMAT_S16_LE; cras_iodev_init_audio_area(iodev, iodev->format->num_channels); if (hfp_info_running(hfpio->info)) goto add_dev; - /* - * Might require a codec negotiation before building the sco connection. - */ - hfp_slc_codec_connection_setup(hfpio->slc); - sk = cras_bt_device_sco_connect(hfpio->device, hfp_slc_get_selected_codec(hfpio->slc)); if (sk < 0) @@ -157,8 +148,7 @@ static int configure_dev(struct cras_iodev *iodev) hfpio->device, sk, hfp_slc_get_selected_codec(hfpio->slc)); /* Start hfp_info */ - err = hfp_info_start(sk, mtu, hfp_slc_get_selected_codec(hfpio->slc), - hfpio->info); + err = hfp_info_start(sk, mtu, hfpio->info); if (err) goto error; @@ -260,12 +250,6 @@ static void update_active_node(struct cras_iodev *iodev, unsigned node_idx, { } -int hfp_iodev_is_hsp(struct cras_iodev *iodev) -{ - struct hfp_io *hfpio = (struct hfp_io *)iodev; - return hfp_slc_is_hsp(hfpio->slc); -} - void hfp_free_resources(struct hfp_io *hfpio) { struct cras_ionode *node; @@ -308,7 +292,10 @@ struct cras_iodev *hfp_iodev_create(enum CRAS_STREAM_DIRECTION dir, snprintf(iodev->info.name, sizeof(iodev->info.name), "%s", name); iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = 0; - iodev->info.stable_id = cras_bt_device_get_stable_id(device); + iodev->info.stable_id = + SuperFastHash(cras_bt_device_object_path(device), + strlen(cras_bt_device_object_path(device)), + strlen(cras_bt_device_object_path(device))); iodev->configure_dev = configure_dev; iodev->frames_queued = frames_queued; @@ -321,36 +308,22 @@ struct cras_iodev *hfp_iodev_create(enum CRAS_STREAM_DIRECTION dir, iodev->update_supported_formats = update_supported_formats; iodev->update_active_node = update_active_node; iodev->set_volume = set_hfp_volume; - iodev->output_underrun = output_underrun; node = (struct cras_ionode *)calloc(1, sizeof(*node)); node->dev = iodev; strcpy(node->name, iodev->info.name); node->plugged = 1; - /* If headset mic doesn't support the wideband speech, report a - * different node type so UI can set different plug priority. */ node->type = CRAS_NODE_TYPE_BLUETOOTH; - if (!hfp_slc_get_wideband_speech_supported(hfpio->slc) && - (dir == CRAS_STREAM_INPUT)) - node->type = CRAS_NODE_TYPE_BLUETOOTH_NB_MIC; - node->volume = 100; gettimeofday(&node->plugged_time, NULL); - /* Prepare active node before append, so bt_io can extract correct - * info from HFP iodev and node. */ + cras_bt_device_append_iodev(device, iodev, profile); cras_iodev_add_node(iodev, node); cras_iodev_set_active_node(iodev, node); - cras_bt_device_append_iodev(device, iodev, profile); hfpio->info = info; - /* Record max supported channels into cras_iodev_info. */ - iodev->info.max_supported_channels = 1; - - ewma_power_disable(&iodev->ewma); - return iodev; error: diff --git a/cras/src/server/cras_hfp_iodev.h b/cras/src/server/cras_hfp_iodev.h index b50aa259..b2762bef 100644 --- a/cras/src/server/cras_hfp_iodev.h +++ b/cras/src/server/cras_hfp_iodev.h @@ -23,11 +23,4 @@ struct cras_iodev *hfp_iodev_create(enum CRAS_STREAM_DIRECTION dir, void hfp_iodev_destroy(struct cras_iodev *iodev); -/* - * Returns if the iodev is running for a HSP connection. Note that - * hfp_iodev is implemented for both HFP and HSP connection. And this - * function allows caller to test if it falls to the rare case - HSP. - */ -int hfp_iodev_is_hsp(struct cras_iodev *iodev); - #endif /* CRAS_HFP_IODEV_H_ */ diff --git a/cras/src/server/cras_hfp_slc.c b/cras/src/server/cras_hfp_slc.c index 28f73edc..6b30a0b3 100644 --- a/cras/src/server/cras_hfp_slc.c +++ b/cras/src/server/cras_hfp_slc.c @@ -10,38 +10,28 @@ #include "cras_bt_device.h" #include "cras_bt_log.h" -#include "cras_observer.h" #include "cras_telephony.h" #include "cras_hfp_slc.h" -#include "cras_server_metrics.h" #include "cras_system_state.h" #include "cras_tm.h" -#include "cras_util.h" /* Message start and end with "\r\n". refer to spec 4.33. */ #define AT_CMD(cmd) "\r\n" cmd "\r\n" -/* The timeout between event reporting and HF indicator commands */ -#define HF_INDICATORS_TIMEOUT_MS 2000 -/* The sleep time before reading and processing the following AT commands during - * codec connection setup. - */ -#define CODEC_CONN_SLEEP_TIME_US 2000 +/* The timeout between service level initialized and codec negotiation + * completed. */ +#define CODEC_NEGOTIATION_TIMEOUT_MS 500 #define SLC_BUF_SIZE_BYTES 256 /* Indicator update command response and indicator indices. - * Note that indicator index starts from '1', index 0 is used for CRAS to record - * if the event report has been enabled or not. + * Note that indicator index starts from '1'. */ -#define CRAS_INDICATOR_ENABLE_INDEX 0 #define BATTERY_IND_INDEX 1 #define SIGNAL_IND_INDEX 2 #define SERVICE_IND_INDEX 3 #define CALL_IND_INDEX 4 #define CALLSETUP_IND_INDEX 5 #define CALLHELD_IND_INDEX 6 -#define ROAM_IND_INDEX 7 -#define INDICATOR_IND_MAX 8 #define INDICATOR_UPDATE_RSP \ "+CIND: " \ "(\"battchg\",(0-5))," \ @@ -69,19 +59,19 @@ * signal - Current signal strength of AG stored in SLC. * service - Current service availability of AG stored in SLC. * callheld - Current callheld status of AG stored in SLC. - * ind_event_reports - Activate statuses of indicator events reporting. + * ind_event_report - Activate status of indicator events reporting. * ag_supported_features - Supported AG features bitmap. - * hf_supported_features - Bit map of HF supported features. - * hf_supports_battery_indicator - Bit map of battery indicator support of - * connected HF. - * hf_battery - Current battery level of HF reported by the HF. The data - * range should be 0 ~ 100. Use -1 for no battery level reported. + * hf_codec_supported - Flags to indicate if codec is supported in HF. + * hf_supports_codec_negotiation - If the connected HF supports codec + * negotiation. * preferred_codec - CVSD or mSBC based on the situation and strategy. This - * needs not to be equal to selected_codec because codec negotiation + * need not to be equal to selected_codec because codec negotiation * process may fail. * selected_codec - The codec id defaults to HFP_CODEC_UNUSED and changes * only if codec negotiation is supported and the negotiation flow * has completed. + * pending_codec_negotiation - True if codec negotiation process has started + * but haven't got reply from HF. * telephony - A reference of current telephony handle. * device - The associated bt device. */ @@ -98,14 +88,13 @@ struct hfp_slc_handle { int signal; int service; int callheld; - int ind_event_reports[INDICATOR_IND_MAX]; + int ind_event_report; int ag_supported_features; bool hf_codec_supported[HFP_MAX_CODECS]; - int hf_supported_features; - int hf_supports_battery_indicator; - int hf_battery; + int hf_supports_codec_negotiation; int preferred_codec; int selected_codec; + int pending_codec_negotiation; struct cras_bt_device *device; struct cras_timer *timer; @@ -144,9 +133,7 @@ static int hfp_send_ind_event_report(struct hfp_slc_handle *handle, { char cmd[64]; - if (handle->is_hsp || - !handle->ind_event_reports[CRAS_INDICATOR_ENABLE_INDEX] || - !handle->ind_event_reports[ind_index]) + if (handle->is_hsp || !handle->ind_event_report) return 0; snprintf(cmd, 64, AT_CMD("+CIEV: %d,%d"), ind_index, value); @@ -194,10 +181,6 @@ static int call_waiting_notify(struct hfp_slc_handle *handle, const char *buf) */ static int cli_notification(struct hfp_slc_handle *handle, const char *cmd) { - if (strlen(cmd) < 9) { - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); - } handle->cli_active = (cmd[8] == '1'); return hfp_send(handle, AT_CMD("OK")); } @@ -211,8 +194,6 @@ static int dial_number(struct hfp_slc_handle *handle, const char *cmd) int rc, cmd_len; cmd_len = strlen(cmd); - if (cmd_len < 4) - goto error_out; if (cmd[3] == '>') { /* Handle memory dial. Extract memory location from command @@ -233,10 +214,6 @@ static int dial_number(struct hfp_slc_handle *handle, const char *cmd) handle->telephony->callsetup = 2; return hfp_send_ind_event_report(handle, CALLSETUP_IND_INDEX, 2); - -error_out: - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); } /* AT+VTS command to generate a DTMF code. Mandatory per spec 4.27. */ @@ -263,23 +240,36 @@ static void initialize_slc_handle(struct cras_timer *timer, void *arg) if (timer) handle->timer = NULL; + /* + * Catch the case if mSBC codec negotiation never complete or even + * failed. AG side falls back to use codec CVSD and also tells + * HF to select CVSD again. + */ + if ((handle->selected_codec == HFP_CODEC_UNUSED) && + handle->hf_codec_supported[HFP_CODEC_ID_MSBC]) { + handle->preferred_codec = HFP_CODEC_ID_CVSD; + select_preferred_codec(handle); + } + + /* + * Codec negotiation is considered to be ended at this point. + * The owner of init_cb may use hfp_slc_get_selected_codec() to + * query the final codec to use for this connection. + */ if (handle->init_cb) { handle->init_cb(handle); handle->init_cb = NULL; } } -/* Handles the event that headset request to start a codec connection - * procedure. +/* Tasks to execute after receiving an AT command. This is useful because + * some HF replies to command X only after it sends command Y. We rely on + * this function to achieve reliable codec negotiation. */ -static int bluetooth_codec_connection(struct hfp_slc_handle *handle, - const char *cmd) +static void post_at_command_tasks(struct hfp_slc_handle *handle) { - /* Reset current selected codec to force a new codec connection - * procedure when the next hfp_slc_codec_connection_setup is called. - */ - handle->selected_codec = HFP_CODEC_UNUSED; - return hfp_send(handle, AT_CMD("OK")); + if (handle->pending_codec_negotiation) + select_preferred_codec(handle); } /* Handles the event that headset request to select specific codec. */ @@ -288,136 +278,46 @@ static int bluetooth_codec_selection(struct hfp_slc_handle *handle, { char *tokens = strdup(cmd); char *codec; - int id, err; + int err; + handle->pending_codec_negotiation = 0; strtok(tokens, "="); codec = strtok(NULL, ","); - if (!codec) - goto bcs_cmd_cleanup; - id = atoi(codec); - if ((id <= HFP_CODEC_UNUSED) || (id >= HFP_MAX_CODECS)) { - syslog(LOG_ERR, "%s: invalid codec id: '%s'", __func__, cmd); - free(tokens); - return hfp_send(handle, AT_CMD("ERROR")); - } - - if (id != handle->preferred_codec) - syslog(LOG_WARNING, "%s: inconsistent codec id: '%s'", __func__, - cmd); - BTLOG(btlog, BT_CODEC_SELECTION, 1, id); - handle->selected_codec = id; + if (codec) { + BTLOG(btlog, BT_CODEC_SELECTION, 1, atoi(codec)); + handle->selected_codec = atoi(codec); + } -bcs_cmd_cleanup: - free(tokens); err = hfp_send(handle, AT_CMD("OK")); + initialize_slc_handle(NULL, (void *)handle); + free(tokens); return err; } /* - * AT+IPHONEACCEV command from HF to report state change.You can find details - * of this command in the Accessory Design Guidelines for Apple Devices R11 - * section 16.1. + * Possibly choose mSBC code from the supported codecs. Otherwise just + * initialize the SLC so the default CVSD codec is used. */ -static int apple_accessory_state_change(struct hfp_slc_handle *handle, - const char *cmd) +static void choose_codec_and_init_slc(struct hfp_slc_handle *handle) { - char *tokens, *num, *key, *val; - int i, level; - - /* AT+IPHONEACCEV=Number of key/value pairs,key1,val1,key2,val2,... - * Number of key/value pairs: The number of parameters coming next. - * key: the type of change being reported: - * 1 = Battery Level - * 2 = Dock State - * val: the value of the change: - * Battery Level: string value between '0' and '9' - * Dock State: 0 = undocked, 1 = docked - */ - tokens = strdup(cmd); - strtok(tokens, "="); - num = strtok(NULL, ","); - if (!num) { - free(tokens); - return hfp_send(handle, AT_CMD("ERROR")); - } - - for (i = 0; i < atoi(num); i++) { - key = strtok(NULL, ","); - val = strtok(NULL, ","); - if (!key || !val) { - syslog(LOG_WARNING, - "IPHONEACCEV: Expected %d kv pairs but got %d", - atoi(num), i); - break; - } + if (handle->hf_supports_codec_negotiation && + handle->hf_codec_supported[HFP_CODEC_ID_MSBC]) { + /* Sets preferred codec to mSBC, and schedule callback to + * select preferred codec until reply received or timeout. + */ + handle->preferred_codec = HFP_CODEC_ID_MSBC; + handle->pending_codec_negotiation = 1; - if (atoi(key) == 1) { - level = atoi(val); - if (level >= 0 && level < 10) { - cras_server_metrics_hfp_battery_report( - CRAS_HFP_BATTERY_INDICATOR_APPLE); - level = (level + 1) * 10; - if (handle->hf_battery != level) { - handle->hf_battery = level; - cras_observer_notify_bt_battery_changed( - cras_bt_device_address( - handle->device), - (uint32_t)(level)); - } - } else { - syslog(LOG_ERR, - "Get invalid battery status from cmd:%s", - cmd); - } - } + /* Delay init to give headset some time to confirm + * codec selection. */ + handle->timer = + cras_tm_create_timer(cras_system_state_get_tm(), + CODEC_NEGOTIATION_TIMEOUT_MS, + initialize_slc_handle, handle); + } else { + initialize_slc_handle(NULL, (void *)handle); } - free(tokens); - return hfp_send(handle, AT_CMD("OK")); -} - -/* - * AT+XAPL command from HF to enable Apple custom features. You can find details - * of it in the Accessory Design Guidelines for Apple Devices R11 section 15.1. - */ -static int apple_supported_features(struct hfp_slc_handle *handle, - const char *cmd) -{ - char *tokens, *features; - int apple_features, err; - char buf[64]; - - /* AT+XAPL=<vendorID>-<productID>-<version>,<features> - * Parse <features>, the only token we care about. - */ - tokens = strdup(cmd); - strtok(tokens, "="); - - strtok(NULL, ","); - features = strtok(NULL, ","); - if (!features) - goto error_out; - - apple_features = atoi(features); - - if (apple_features & APL_BATTERY) - handle->hf_supports_battery_indicator |= - CRAS_HFP_BATTERY_INDICATOR_APPLE; - - snprintf(buf, 64, AT_CMD("+XAPL=iPhone,%d"), - CRAS_APL_SUPPORTED_FEATURES); - err = hfp_send(handle, buf); - if (err) - goto error_out; - - err = hfp_send(handle, AT_CMD("OK")); - free(tokens); - return err; - -error_out: - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - free(tokens); - return hfp_send(handle, AT_CMD("ERROR")); } /* Handles the event when headset reports its available codecs list. */ @@ -441,11 +341,6 @@ static int available_codecs(struct hfp_slc_handle *handle, const char *cmd) id_str = strtok(NULL, ","); } - if (hfp_slc_get_wideband_speech_supported(handle)) - handle->preferred_codec = HFP_CODEC_ID_MSBC; - else - handle->preferred_codec = HFP_CODEC_ID_CVSD; - free(tokens); return hfp_send(handle, AT_CMD("OK")); } @@ -482,8 +377,7 @@ static int event_reporting(struct hfp_slc_handle *handle, const char *cmd) goto event_reporting_done; } if (atoi(mode) == FORWARD_UNSOLICIT_RESULT_CODE) - handle->ind_event_reports[CRAS_INDICATOR_ENABLE_INDEX] = - atoi(tmp); + handle->ind_event_report = atoi(tmp); err = hfp_send(handle, AT_CMD("OK")); if (err) { @@ -492,21 +386,13 @@ static int event_reporting(struct hfp_slc_handle *handle, const char *cmd) } /* - * Wait for HF to retrieve information about HF indicators and consider - * the Service Level Connection to be fully initialized, and thereby - * established, if HF doesn't support HF indicators. + * Consider the Service Level Connection to be fully initialized, + * and thereby established, after successfully responded with OK. + * However we should postpone the initialize call after codec selection, + * otherwise iodev could be open immediately while the headset is still + * communicating about which of CVSD or mSBC codec to use. */ - if (hfp_slc_get_hf_hf_indicators_supported(handle)) - handle->timer = - cras_tm_create_timer(cras_system_state_get_tm(), - HF_INDICATORS_TIMEOUT_MS, - initialize_slc_handle, handle); - /* - * Otherwise, regard the Service Level Connection to be fully - * initialized and ready for the potential codec negotiation. - */ - else - initialize_slc_handle(NULL, (void *)handle); + choose_codec_and_init_slc(handle); event_reporting_done: free(tokens); @@ -607,26 +493,6 @@ static int operator_selection(struct hfp_slc_handle *handle, const char *buf) return hfp_send(handle, AT_CMD("OK")); } -/* The AT+CHLD command is used to control call hold, release, and multiparty - * states. - */ -static int call_hold(struct hfp_slc_handle *handle, const char *buf) -{ - int rc; - - // Chrome OS doesn't yet support CHLD features but we need to reply - // the query with an empty feature list rather than "ERROR" to increase - // interoperability with certain devices (b/172413440). - if (strlen(buf) > 8 && buf[7] == '=' && buf[8] == '?') { - rc = hfp_send(handle, AT_CMD("+CHLD:")); - if (rc) - return rc; - return hfp_send(handle, AT_CMD("OK")); - } - - return hfp_send(handle, AT_CMD("ERROR")); -} - /* AT+CIND command retrieves the supported indicator and its corresponding * range and order index or read current status of indicators. Mandatory * support per spec 4.2. @@ -636,11 +502,6 @@ static int report_indicators(struct hfp_slc_handle *handle, const char *cmd) int err; char buf[64]; - if (strlen(cmd) < 8) { - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); - } - if (cmd[7] == '=') { /* Indicator update test command "AT+CIND=?" */ err = hfp_send(handle, AT_CMD(INDICATOR_UPDATE_RSP)); @@ -666,187 +527,16 @@ static int report_indicators(struct hfp_slc_handle *handle, const char *cmd) } /* AT+BIA command to change the subset of indicators that shall be - * sent by the AG. + * sent by the AG. It is okay to ignore this command here since we + * don't do event reporting(CMER). */ static int indicator_activation(struct hfp_slc_handle *handle, const char *cmd) { - char *ptr; - int idx = BATTERY_IND_INDEX; - - /* AT+BIA=[[<indrep 1>][,[<indrep 2>][,...[,[<indrep n>]]]]] - * According to the spec: - * - The indicator state can be omitted and the current reporting - * states of the indicator shall not change. - * Ex: AT+BIA=,1,,0 - * Only the 2nd and 4th indicators may be affected. - * - HF can provide fewer indicators than AG and states not provided - * shall not change. - * Ex: CRAS supports 7 indicators and gets AT+BIA=1,0,1 - * Only the first three indicators may be affected. - * - Call, Call Setup and Held Call are mandatory and should be always - * on no matter what state HF set. - */ - ptr = strchr(cmd, '='); - while (ptr && idx < INDICATOR_IND_MAX) { - if (idx != CALL_IND_INDEX && idx != CALLSETUP_IND_INDEX && - idx != CALLHELD_IND_INDEX) { - if (*(ptr + 1) == '1') - handle->ind_event_reports[idx] = 1; - else if (*(ptr + 1) == '0') - handle->ind_event_reports[idx] = 0; - } - ptr = strchr(ptr + 1, ','); - idx++; - } + /* AT+BIA=[[<indrep 1>][,[<indrep 2>][,...[,[<indrep n>]]]]] */ + syslog(LOG_ERR, "Bluetooth indicator activation command %s", cmd); return hfp_send(handle, AT_CMD("OK")); } -/* AT+BIND command to report, query and activate Generic Status Indicators. - * It is sent by the HF if both AG and HF support the HF indicator feature. - */ -static int indicator_support(struct hfp_slc_handle *handle, const char *cmd) -{ - char *tokens, *key; - int err, cmd_len; - - cmd_len = strlen(cmd); - if (cmd_len < 8) - goto error_out; - - if (cmd[7] == '=') { - /* AT+BIND=? (Read AG supported indicators) */ - if (cmd_len > 8 && cmd[8] == '?') { - /* +BIND: (<a>,<b>,<c>,...,<n>) (Response to AT+BIND=?) - * <a> ... <n>: 0-65535, entered as decimal unsigned - * integer values without leading zeros, referencing an - * HF indicator assigned number. - * 1 is for Enhanced Driver Status. - * 2 is for Battery Level. - * For the list of HF indicator assigned number, you can - * check the Bluetooth SIG Assigned Numbers web page. - */ - BTLOG(btlog, BT_HFP_HF_INDICATOR, 1, 0); - /* "2" is for HF Battery Level that we support. We don't - * support "1" but this is a workaround for Pixel Buds 2 - * which expects this exact combination for battery - * reporting (HFP 1.7 standard) to work. This workaround - * is fine since we don't enable Safety Drive with - * +BIND: 1,1 (b/172680041). - */ - err = hfp_send(handle, AT_CMD("+BIND: (1,2)")); - if (err < 0) - return err; - } - /* AT+BIND=<a>,<b>,...,<n>(List HF supported indicators) */ - else { - tokens = strdup(cmd); - strtok(tokens, "="); - key = strtok(NULL, ","); - while (key != NULL) { - if (atoi(key) == 2) - handle->hf_supports_battery_indicator |= - CRAS_HFP_BATTERY_INDICATOR_HFP; - key = strtok(NULL, ","); - } - free(tokens); - } - } - /* AT+BIND? (Read AG enabled/disabled status of indicators) */ - else if (cmd[7] == '?') { - /* +BIND: <a>,<state> (Unsolicited or Response to AT+BIND?) - * This response enables the AG to notify the HF which HF - * indicators are supported and their state, enabled or - * disabled. - * <a>: 1 or 2, referencing an HF indicator assigned number. - * <state>: 0-1, entered as integer values, where - * 0 = disabled, no value changes shall be sent for this - * indicator - * 1 = enabled, value changes may be sent for this indicator - */ - - /* We don't support Enhanced Driver Status, so explicitly - * disable it (b/172680041). - */ - err = hfp_send(handle, AT_CMD("+BIND: 1,0")); - if (err < 0) - return err; - - BTLOG(btlog, BT_HFP_HF_INDICATOR, 0, 0); - - err = hfp_send(handle, AT_CMD("+BIND: 2,1")); - if (err < 0) - return err; - - err = hfp_send(handle, AT_CMD("OK")); - if (err) - return err; - /* - * Consider the Service Level Connection to be fully initialized - * and thereby established, after successfully responded with OK - */ - initialize_slc_handle(NULL, (void *)handle); - return 0; - } else { - goto error_out; - } - /* This OK reply is required after both +BIND AT commands. It also - * covers the AT+BIND= <a>,<b>,...,<n> case. - */ - return hfp_send(handle, AT_CMD("OK")); - -error_out: - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); -} - -/* AT+BIEV command reports updated values of enabled HF indicators to the AG. - */ -static int indicator_state_change(struct hfp_slc_handle *handle, - const char *cmd) -{ - char *tokens, *key, *val; - int level; - /* AT+BIEV= <assigned number>,<value> (Update value of indicator) - * CRAS only supports battery level, which is with assigned number 2. - * Battery level should range from 0 to 100 defined by the spec. - */ - tokens = strdup(cmd); - strtok(tokens, "="); - key = strtok(NULL, ","); - if (!key) - goto error_out; - - if (atoi(key) == 2) { - val = strtok(NULL, ","); - if (!val) - goto error_out; - level = atoi(val); - if (level >= 0 && level <= 100) { - cras_server_metrics_hfp_battery_report( - CRAS_HFP_BATTERY_INDICATOR_HFP); - if (handle->hf_battery != level) { - handle->hf_battery = level; - cras_observer_notify_bt_battery_changed( - cras_bt_device_address(handle->device), - (uint32_t)(level)); - } - } else { - syslog(LOG_ERR, - "Get invalid battery status from cmd:%s", cmd); - } - } else { - goto error_out; - } - - free(tokens); - return hfp_send(handle, AT_CMD("OK")); - -error_out: - syslog(LOG_WARNING, "%s: invalid command: '%s'", __func__, cmd); - free(tokens); - return hfp_send(handle, AT_CMD("ERROR")); -} - /* AT+VGM and AT+VGS command reports the current mic and speaker gain * level respectively. Optional support per spec 4.28. */ @@ -855,21 +545,14 @@ static int signal_gain_setting(struct hfp_slc_handle *handle, const char *cmd) int gain; if (strlen(cmd) < 8) { - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); + syslog(LOG_ERR, "Invalid gain setting command %s", cmd); + return -EINVAL; } /* Map 0 to the smallest non-zero scale 6/100, and 15 to * 100/100 full. */ if (cmd[5] == 'S') { gain = atoi(&cmd[7]); - if (gain < 0 || gain > 15) { - syslog(LOG_ERR, - "signal_gain_setting: gain %d is not between 0 and 15", - gain); - return hfp_send(handle, AT_CMD("ERROR")); - } - BTLOG(btlog, BT_HFP_UPDATE_SPEAKER_GAIN, gain, 0); cras_bt_device_update_hardware_volume(handle->device, (gain + 1) * 100 / 16); } @@ -891,24 +574,23 @@ static int subscriber_number(struct hfp_slc_handle *handle, const char *buf) */ static int supported_features(struct hfp_slc_handle *handle, const char *cmd) { - int err; + int err, hf_features; char response[128]; char *tokens, *features; - if (strlen(cmd) < 9) { - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); - } + if (strlen(cmd) < 9) + return -EINVAL; + + handle->hf_supports_codec_negotiation = 0; tokens = strdup(cmd); strtok(tokens, "="); features = strtok(NULL, ","); - if (!features) - goto error_out; - handle->hf_supported_features = atoi(features); - BTLOG(btlog, BT_HFP_SUPPORTED_FEATURES, 0, - handle->hf_supported_features); + hf_features = atoi(features); + BTLOG(btlog, BT_HFP_SUPPORTED_FEATURES, 0, hf_features); + if (hf_features & HF_CODEC_NEGOTIATION) + handle->hf_supports_codec_negotiation = 1; free(tokens); /* AT+BRSF=<feature> command received, ignore the HF supported feature @@ -924,11 +606,6 @@ static int supported_features(struct hfp_slc_handle *handle, const char *cmd) return err; return hfp_send(handle, AT_CMD("OK")); - -error_out: - free(tokens); - syslog(LOG_ERR, "%s: malformed command: '%s'", __func__, cmd); - return hfp_send(handle, AT_CMD("ERROR")); } int hfp_event_speaker_gain(struct hfp_slc_handle *handle, int gain) @@ -937,7 +614,6 @@ int hfp_event_speaker_gain(struct hfp_slc_handle *handle, int gain) /* Normailize gain value to 0-15 */ gain = gain * 15 / 100; - BTLOG(btlog, BT_HFP_SET_SPEAKER_GAIN, gain, 0); snprintf(command, 128, AT_CMD("+VGS=%d"), gain); return hfp_send(handle, command); @@ -956,75 +632,11 @@ static int terminate_call(struct hfp_slc_handle *handle, const char *cmd) return cras_telephony_event_terminate_call(); } -/* AT+XEVENT is defined by Android to support vendor specific features. - * Currently, the only known supported case for CrOS is the battery event sent - * by some Plantronics headsets. - */ -static int vendor_specific_features(struct hfp_slc_handle *handle, - const char *cmd) -{ - char *tokens, *event, *level_str, *num_of_level_str; - int level, num_of_level; - - tokens = strdup(cmd); - strtok(tokens, "="); - event = strtok(NULL, ","); - if (!event) - goto error_out; - - /* AT+XEVENT=BATTERY,Level,NumberOfLevel,MinutesOfTalkTime,IsCharging - * Level: The charge level with a zero-based integer. - * NumberOfLevel: How many charging levels there are. - * MinuteOfTalkTime: The estimated number of talk minutes remaining. - * IsCharging: A 0 or 1 value. - * - * We only support the battery level and thus only care about the first - * 3 arguments. - */ - if (!strncmp(event, "BATTERY", 7)) { - level_str = strtok(NULL, ","); - num_of_level_str = strtok(NULL, ","); - if (!level_str || !num_of_level_str) - goto error_out; - - level = atoi(level_str); - num_of_level = atoi(num_of_level_str); - if (level < 0 || num_of_level <= 1 || level >= num_of_level) - goto error_out; - - level = (int64_t)level * 100 / (num_of_level - 1); - if (handle->hf_battery != level) { - handle->hf_supports_battery_indicator |= - CRAS_HFP_BATTERY_INDICATOR_PLANTRONICS; - cras_server_metrics_hfp_battery_report( - CRAS_HFP_BATTERY_INDICATOR_PLANTRONICS); - handle->hf_battery = level; - cras_observer_notify_bt_battery_changed( - cras_bt_device_address(handle->device), - (uint32_t)(level)); - } - } - - free(tokens); - /* For Plantronic headsets, it is required to reply "OK" for the first - * AT+XEVENT=USER-AGENT... command to tell the headset our support of - * the xevent protocol. Otherwise, all following events including - * BATTERY won't be sent. - */ - return hfp_send(handle, AT_CMD("OK")); - -error_out: - syslog(LOG_ERR, "%s: malformed vendor specific command: '%s'", __func__, - cmd); - free(tokens); - return hfp_send(handle, AT_CMD("ERROR")); -} - /* AT commands to support in order to conform HFP specification. * * An initialized service level connection is the pre-condition for all * call related procedures. Note that for the call related commands, - * we are good to just respond with a meaningless "OK". + * we are good to just respond with a dummy "OK". * * The procedure to establish a service level connection is described below: * @@ -1056,35 +668,27 @@ error_out: * AT+CMER= --> * <-- OK */ -static struct at_command at_commands[] = { - { "ATA", answer_call }, - { "ATD", dial_number }, - { "AT+BAC", available_codecs }, - { "AT+BCC", bluetooth_codec_connection }, - { "AT+BCS", bluetooth_codec_selection }, - { "AT+BIA", indicator_activation }, - { "AT+BIEV", indicator_state_change }, - { "AT+BIND", indicator_support }, - { "AT+BLDN", last_dialed_number }, - { "AT+BRSF", supported_features }, - { "AT+CCWA", call_waiting_notify }, - { "AT+CHUP", terminate_call }, - { "AT+CIND", report_indicators }, - { "AT+CKPD", key_press }, - { "AT+CLCC", list_current_calls }, - { "AT+CLIP", cli_notification }, - { "AT+CMEE", extended_errors }, - { "AT+CMER", event_reporting }, - { "AT+CNUM", subscriber_number }, - { "AT+COPS", operator_selection }, - { "AT+IPHONEACCEV", apple_accessory_state_change }, - { "AT+VG", signal_gain_setting }, - { "AT+VTS", dtmf_tone }, - { "AT+XAPL", apple_supported_features }, - { "AT+XEVENT", vendor_specific_features }, - { "AT+CHLD", call_hold }, - { 0 } -}; +static struct at_command at_commands[] = { { "ATA", answer_call }, + { "ATD", dial_number }, + { "AT+BAC", available_codecs }, + { "AT+BCS", + bluetooth_codec_selection }, + { "AT+BIA", indicator_activation }, + { "AT+BLDN", last_dialed_number }, + { "AT+BRSF", supported_features }, + { "AT+CCWA", call_waiting_notify }, + { "AT+CHUP", terminate_call }, + { "AT+CIND", report_indicators }, + { "AT+CKPD", key_press }, + { "AT+CLCC", list_current_calls }, + { "AT+CLIP", cli_notification }, + { "AT+CMEE", extended_errors }, + { "AT+CMER", event_reporting }, + { "AT+CNUM", subscriber_number }, + { "AT+COPS", operator_selection }, + { "AT+VG", signal_gain_setting }, + { "AT+VTS", dtmf_tone }, + { 0 } }; static int handle_at_command(struct hfp_slc_handle *slc_handle, const char *cmd) { @@ -1098,23 +702,21 @@ static int handle_at_command(struct hfp_slc_handle *slc_handle, const char *cmd) return hfp_send(slc_handle, AT_CMD("ERROR")); } -int handle_at_command_for_test(struct hfp_slc_handle *slc_handle, - const char *cmd) -{ - return handle_at_command(slc_handle, cmd); -} - -static int process_at_commands(struct hfp_slc_handle *handle) +static void slc_watch_callback(void *arg) { + struct hfp_slc_handle *handle = (struct hfp_slc_handle *)arg; ssize_t bytes_read; int err; bytes_read = read(handle->rfcomm_fd, &handle->buf[handle->buf_write_idx], SLC_BUF_SIZE_BYTES - handle->buf_write_idx - 1); - if (bytes_read < 0) - return bytes_read; - + if (bytes_read < 0) { + syslog(LOG_ERR, "Error reading slc command %s", + strerror(errno)); + handle->disconnect_cb(handle); + return; + } handle->buf_write_idx += bytes_read; handle->buf[handle->buf_write_idx] = '\0'; @@ -1128,7 +730,7 @@ static int process_at_commands(struct hfp_slc_handle *handle) err = handle_at_command(handle, &handle->buf[handle->buf_read_idx]); if (err < 0) - return 0; + return; /* Shift the read index */ handle->buf_read_idx = 1 + end_char - handle->buf; @@ -1151,21 +753,9 @@ static int process_at_commands(struct hfp_slc_handle *handle) handle->buf_write_idx = 0; } } - return bytes_read; -} -static void slc_watch_callback(void *arg, int revents) -{ - struct hfp_slc_handle *handle = (struct hfp_slc_handle *)arg; - int err; + post_at_command_tasks(handle); - err = process_at_commands(handle); - if (err < 0) { - syslog(LOG_ERR, "Error reading slc command %s", - strerror(errno)); - cras_system_rm_select_fd(handle->rfcomm_fd); - handle->disconnect_cb(handle); - } return; } @@ -1178,10 +768,6 @@ struct hfp_slc_handle *hfp_slc_create(int fd, int is_hsp, hfp_slc_disconnect_cb disconnect_cb) { struct hfp_slc_handle *handle; - int i; - - if (!disconnect_cb) - return NULL; handle = (struct hfp_slc_handle *)calloc(1, sizeof(*handle)); if (!handle) @@ -1190,7 +776,6 @@ struct hfp_slc_handle *hfp_slc_create(int fd, int is_hsp, handle->rfcomm_fd = fd; handle->is_hsp = is_hsp; handle->ag_supported_features = ag_supported_features; - handle->hf_supported_features = 0; handle->device = device; handle->init_cb = init_cb; handle->disconnect_cb = disconnect_cb; @@ -1198,16 +783,13 @@ struct hfp_slc_handle *hfp_slc_create(int fd, int is_hsp, handle->battery = 5; handle->signal = 5; handle->service = 1; - handle->ind_event_reports[CRAS_INDICATOR_ENABLE_INDEX] = 0; - for (i = BATTERY_IND_INDEX; i < INDICATOR_IND_MAX; i++) - handle->ind_event_reports[i] = 1; + handle->ind_event_report = 0; handle->telephony = cras_telephony_get(); handle->preferred_codec = HFP_CODEC_ID_CVSD; handle->selected_codec = HFP_CODEC_UNUSED; - handle->hf_supports_battery_indicator = CRAS_HFP_BATTERY_INDICATOR_NONE; - handle->hf_battery = -1; - cras_system_add_select_fd(handle->rfcomm_fd, slc_watch_callback, handle, - POLLIN | POLLERR | POLLHUP); + + cras_system_add_select_fd(handle->rfcomm_fd, slc_watch_callback, + handle); return handle; } @@ -1222,11 +804,6 @@ void hfp_slc_destroy(struct hfp_slc_handle *slc_handle) free(slc_handle); } -int hfp_slc_is_hsp(struct hfp_slc_handle *handle) -{ - return handle->is_hsp; -} - int hfp_slc_get_selected_codec(struct hfp_slc_handle *handle) { /* If codec negotiation is not supported on HF, or the negotiation @@ -1237,65 +814,6 @@ int hfp_slc_get_selected_codec(struct hfp_slc_handle *handle) return handle->selected_codec; } -int hfp_slc_codec_connection_setup(struct hfp_slc_handle *handle) -{ - /* The time we wait for codec selection response. */ - static struct timespec timeout = { 0, 100000000 }; - struct pollfd poll_fd; - int rc = 0; - struct timespec ts = timeout; - - /* - * Codec negotiation is not required, if either AG or HF doesn't support - * it or it has been done once. - */ - if (!hfp_slc_get_hf_codec_negotiation_supported(handle) || - !hfp_slc_get_ag_codec_negotiation_supported(handle) || - handle->selected_codec == handle->preferred_codec) - return 0; - -redo_codec_conn: - select_preferred_codec(handle); - - poll_fd.fd = handle->rfcomm_fd; - poll_fd.events = POLLIN; - - ts = timeout; - while (rc <= 0) { - rc = cras_poll(&poll_fd, 1, &ts, NULL); - if (rc == -ETIMEDOUT) { - /* - * Catch the case that the first initial codec - * negotiation timeout. At this point we're not sure - * if HF is good with the preferred codec from AG. - * Fallback to CVSD doesn't help because very likely - * HF won't reply that either. The best thing we can - * do is just leave a warning log. - */ - if (handle->selected_codec == HFP_CODEC_UNUSED) { - syslog(LOG_WARNING, - "Proceed using codec %d without HF reply", - handle->preferred_codec); - } - return rc; - } - } - - if (rc > 0) { - do { - usleep(CODEC_CONN_SLEEP_TIME_US); - rc = process_at_commands(handle); - } while (rc == -EAGAIN); - - if (rc <= 0) - return rc; - if (handle->selected_codec != handle->preferred_codec) - goto redo_codec_conn; - } - - return 0; -} - int hfp_set_call_status(struct hfp_slc_handle *handle, int call) { int old_call = handle->telephony->call; @@ -1372,29 +890,7 @@ int hfp_event_set_service(struct hfp_slc_handle *handle, int avail) return hfp_send_ind_event_report(handle, SERVICE_IND_INDEX, avail); } -int hfp_slc_get_ag_codec_negotiation_supported(struct hfp_slc_handle *handle) -{ - return handle->ag_supported_features & AG_CODEC_NEGOTIATION; -} - int hfp_slc_get_hf_codec_negotiation_supported(struct hfp_slc_handle *handle) { - return handle->hf_supported_features & HF_CODEC_NEGOTIATION; -} - -int hfp_slc_get_hf_hf_indicators_supported(struct hfp_slc_handle *handle) -{ - return handle->hf_supported_features & HF_HF_INDICATORS; -} - -bool hfp_slc_get_wideband_speech_supported(struct hfp_slc_handle *handle) -{ - return hfp_slc_get_ag_codec_negotiation_supported(handle) && - hfp_slc_get_hf_codec_negotiation_supported(handle) && - handle->hf_codec_supported[HFP_CODEC_ID_MSBC]; -} - -int hfp_slc_get_hf_supports_battery_indicator(struct hfp_slc_handle *handle) -{ - return handle->hf_supports_battery_indicator; + return handle->hf_supports_codec_negotiation; } diff --git a/cras/src/server/cras_hfp_slc.h b/cras/src/server/cras_hfp_slc.h index 99335eab..fd3ee551 100644 --- a/cras/src/server/cras_hfp_slc.h +++ b/cras/src/server/cras_hfp_slc.h @@ -18,7 +18,7 @@ struct cras_bt_device; #define HF_THREE_WAY_CALLING 0x0002 #define HF_CLI_PRESENTATION_CAP 0x0004 #define HF_VOICE_RECOGNITION 0x0008 -#define HF_REMOTE_VOLUME_CONTROL 0x0010 +#define HF_REMOVE_VOLUME_CTONTROL 0x0010 #define HF_ENHANCED_CALL_STATUS 0x0020 #define HF_ENHANCED_CALL_CONTROL 0x0040 #define HF_CODEC_NEGOTIATION 0x0080 @@ -38,32 +38,12 @@ struct cras_bt_device; #define AG_HF_INDICATORS 0x0400 #define AG_ESCO_S4_T2_SETTINGS 0x0800 -/* - * Apple specific bluetooth commands that extend accessory capabilities. - * Per Accessory Design Guidelines for Apple devices, command AT+XAPL - */ - -#define APL_RESERVED 0x01 -#define APL_BATTERY 0x02 -#define APL_DOCKED_OR_POWERED 0x04 -#define APL_SIRI 0x08 -#define APL_NOISE_REDUCTION 0x10 - -#define CRAS_APL_SUPPORTED_FEATURES (APL_BATTERY) - /* Codec ids for codec negotiation, per HFP 1.7.1 spec appendix B. */ #define HFP_CODEC_UNUSED 0 #define HFP_CODEC_ID_CVSD 1 #define HFP_CODEC_ID_MSBC 2 #define HFP_MAX_CODECS 3 -/* Hands-free HFP supported battery indicator bit definition. - * This is currently only used for logging purpose. */ -#define CRAS_HFP_BATTERY_INDICATOR_NONE 0x0 -#define CRAS_HFP_BATTERY_INDICATOR_HFP 0x1 -#define CRAS_HFP_BATTERY_INDICATOR_APPLE 0x2 -#define CRAS_HFP_BATTERY_INDICATOR_PLANTRONICS 0x4 - /* Callback to call when service level connection initialized. */ typedef int (*hfp_slc_init_cb)(struct hfp_slc_handle *handle); @@ -91,11 +71,6 @@ struct hfp_slc_handle *hfp_slc_create(int fd, int is_hsp, /* Destroys an hfp_slc_handle. */ void hfp_slc_destroy(struct hfp_slc_handle *handle); -/* Returns true if this SLC is created for headset profile(HSP), false - * means it's created for hands-free profile(HFP). - */ -int hfp_slc_is_hsp(struct hfp_slc_handle *handle); - /* Sets the call status to notify handsfree device. */ int hfp_set_call_status(struct hfp_slc_handle *handle, int call); @@ -133,24 +108,4 @@ int hfp_slc_get_selected_codec(struct hfp_slc_handle *handle); /* Gets if the remote HF supports codec negotiation. */ int hfp_slc_get_hf_codec_negotiation_supported(struct hfp_slc_handle *handle); -/* Gets if the remote HF supports HF indicator. */ -int hfp_slc_get_hf_hf_indicators_supported(struct hfp_slc_handle *handle); - -/* Gets if the HF side supports wideband speech. */ -bool hfp_slc_get_wideband_speech_supported(struct hfp_slc_handle *handle); - -/* Gets if the AG side supports codec negotiation. */ -int hfp_slc_get_ag_codec_negotiation_supported(struct hfp_slc_handle *handle); - -/* Gets an enum representing which spec the HF supports battery indicator. - * Apple, HFP, none, or both. */ -int hfp_slc_get_hf_supports_battery_indicator(struct hfp_slc_handle *handle); - -/* Init the codec negotiation process if needed. */ -int hfp_slc_codec_connection_setup(struct hfp_slc_handle *handle); - -// Expose internal AT command handling for fuzzing. -int handle_at_command_for_test(struct hfp_slc_handle *slc_handle, - const char *cmd); - #endif /* CRAS_HFP_SLC_H_ */ diff --git a/cras/src/server/cras_iodev.c b/cras/src/server/cras_iodev.c index 651cef71..cf6b71ef 100644 --- a/cras/src/server/cras_iodev.c +++ b/cras/src/server/cras_iodev.c @@ -21,7 +21,6 @@ #include "cras_dsp_pipeline.h" #include "cras_fmt_conv.h" #include "cras_iodev.h" -#include "cras_main_thread_log.h" #include "cras_iodev_list.h" #include "cras_mix.h" #include "cras_ramp.h" @@ -38,8 +37,6 @@ static const float RAMP_UNMUTE_DURATION_SECS = 0.5; static const float RAMP_NEW_STREAM_DURATION_SECS = 0.01; static const float RAMP_MUTE_DURATION_SECS = 0.1; -static const float RAMP_RESUME_MUTE_DURATION_SECS = 1; -static const float RAMP_SWITCH_MUTE_DURATION_SECS = 0.5; static const float RAMP_VOLUME_CHANGE_DURATION_SECS = 0.1; /* @@ -84,7 +81,7 @@ static int default_no_stream_playback(struct cras_iodev *odev) /* If underrun happened, handle underrun and get hw_level again. */ if (hw_level == 0) { - rc = cras_iodev_output_underrun(odev, hw_level, 0); + rc = cras_iodev_output_underrun(odev); if (rc < 0) return rc; @@ -239,7 +236,7 @@ int cras_iodev_is_zero_volume(const struct cras_iodev *odev) * | ---------------- | device from * | | S1 Open | | audio_thread and * | ---------------- | closes device - * | Device with empty start | | + * | Device with dummy start | | * | ops transits into | Sample is ready | * | no stream state right V | * | after open. ---------------- | @@ -264,9 +261,10 @@ static int cras_iodev_output_event_sample_ready(struct cras_iodev *odev) /* Starts ramping up if device should not be muted. * Both mute and volume are taken into consideration. */ - if (odev->ramp && !output_should_mute(odev)) { - cras_iodev_start_ramp(odev, odev->initial_ramp_request); - } + if (odev->ramp && !output_should_mute(odev)) + cras_iodev_start_ramp( + odev, + CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK); } if (odev->state == CRAS_IODEV_STATE_OPEN) { @@ -449,17 +447,6 @@ int cras_iodev_set_format(struct cras_iodev *iodev, snd_pcm_format_t actual_format; int rc; - /* Update supported formats on iodev before negotiating the final value - * with what stream requested. - */ - if (iodev->update_supported_formats) { - rc = iodev->update_supported_formats(iodev); - if (rc) { - syslog(LOG_ERR, "Failed to update formats"); - return rc; - } - } - /* If this device isn't already using a format, try to match the one * requested in "fmt". */ if (iodev->format == NULL) { @@ -468,6 +455,14 @@ int cras_iodev_set_format(struct cras_iodev *iodev, return -ENOMEM; *iodev->format = *fmt; + if (iodev->update_supported_formats) { + rc = iodev->update_supported_formats(iodev); + if (rc) { + syslog(LOG_ERR, "Failed to update formats"); + goto error; + } + } + /* Finds the actual rate of device before allocating DSP * because DSP needs to use the rate of device, not rate of * stream. */ @@ -527,8 +522,8 @@ static void add_ext_dsp_module_to_pipeline(struct cras_iodev *iodev) if (!pipeline) { cras_iodev_alloc_dsp(iodev); - cras_dsp_load_mock_pipeline(iodev->dsp_context, - iodev->format->num_channels); + cras_dsp_load_dummy_pipeline(iodev->dsp_context, + iodev->format->num_channels); pipeline = cras_dsp_get_pipeline(iodev->dsp_context); } /* dsp_context mutex locked. Now it's safe to modify dsp @@ -686,16 +681,10 @@ void cras_iodev_set_node_plugged(struct cras_ionode *node, int plugged) if (node->plugged == plugged) return; node->plugged = plugged; - MAINLOG(main_log, MAIN_THREAD_NODE_PLUGGED, node->dev->info.idx, - plugged, 0); if (plugged) { gettimeofday(&node->plugged_time, NULL); } else if (node == node->dev->active_node) { - /* - * Remove normal and pinned streams, when node unplugged. - * TODO(hychao): clean this up, per crbug.com/1006646 - */ - cras_iodev_list_disable_dev(node->dev, true); + cras_iodev_list_disable_dev(node->dev, false); } cras_iodev_list_notify_nodes_changed(); } @@ -719,30 +708,6 @@ void cras_iodev_set_active_node(struct cras_iodev *iodev, cras_iodev_list_notify_active_node_changed(iodev->direction); } -bool cras_iodev_is_aec_use_case(const struct cras_ionode *node) -{ - if ((node->type == CRAS_NODE_TYPE_INTERNAL_SPEAKER) || - (node->type == CRAS_NODE_TYPE_ECHO_REFERENCE)) - return true; - - if (node->type == CRAS_NODE_TYPE_MIC) - return (node->position == NODE_POSITION_INTERNAL) || - (node->position == NODE_POSITION_FRONT); - - return false; -} - -bool cras_iodev_is_on_internal_card(const struct cras_ionode *node) -{ - if (node->type == CRAS_NODE_TYPE_INTERNAL_SPEAKER) - return true; - if (node->type == CRAS_NODE_TYPE_HEADPHONE) - return true; - if (node->type == CRAS_NODE_TYPE_MIC) - return true; - return false; -} - float cras_iodev_get_software_volume_scaler(struct cras_iodev *iodev) { unsigned int volume; @@ -757,10 +722,13 @@ float cras_iodev_get_software_volume_scaler(struct cras_iodev *iodev) float cras_iodev_get_software_gain_scaler(const struct cras_iodev *iodev) { - if (cras_iodev_software_volume_needed(iodev)) - return convert_softvol_scaler_from_dB( - iodev->active_node->capture_gain); - return 1.0f; + float scaler = 1.0f; + if (cras_iodev_software_volume_needed(iodev)) { + long gain = cras_iodev_adjust_active_node_gain( + iodev, cras_system_get_capture_gain()); + scaler = convert_softvol_scaler_from_dB(gain); + } + return scaler; } int cras_iodev_get_valid_frames(struct cras_iodev *odev, @@ -957,24 +925,19 @@ int cras_iodev_open(struct cras_iodev *iodev, unsigned int cb_level, iodev->min_cb_level = MIN(iodev->buffer_size / 2, cb_level); iodev->max_cb_level = 0; iodev->largest_cb_level = 0; - iodev->num_underruns = 0; iodev->reset_request_pending = 0; iodev->state = CRAS_IODEV_STATE_OPEN; iodev->highest_hw_level = 0; iodev->input_dsp_offset = 0; - ewma_power_init(&iodev->ewma, iodev->format->frame_rate); - if (iodev->direction == CRAS_STREAM_OUTPUT) { /* If device supports start ops, device can be in open state. * Otherwise, device starts running right after opening. */ - if (iodev->start) { + if (iodev->start) iodev->state = CRAS_IODEV_STATE_OPEN; - } else { + else iodev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; - cras_iodev_fill_odev_zeros(iodev, iodev->min_cb_level); - } } else { iodev->input_data = input_data_create(iodev); /* If this is the echo reference dev, its ext_dsp_module will @@ -993,8 +956,8 @@ int cras_iodev_open(struct cras_iodev *iodev, unsigned int cb_level, /* * The device specific gain scaler to be used in audio thread. * It's expected to stick to 1.0f if device has hardware gain - * control. For alsa device, this gain value will be configured - * based on UCM labels IntrinsicSensitivity. + * control. For alsa device, this gain value can be configured + * through UCM labels DefaultNodeGain. */ iodev->software_gain_scaler = cras_iodev_get_software_gain_scaler(iodev); @@ -1019,11 +982,7 @@ int cras_iodev_close(struct cras_iodev *iodev) if (!cras_iodev_is_open(iodev)) return 0; - if (iodev->active_node) { - cras_server_metrics_device_runtime(iodev); - cras_server_metrics_device_gain(iodev); - cras_server_metrics_device_volume(iodev); - } + cras_server_metrics_device_runtime(iodev); if (iodev->input_data) { if (iodev->ext_dsp_module == &iodev->input_data->ext) @@ -1033,8 +992,7 @@ int cras_iodev_close(struct cras_iodev *iodev) rc = iodev->close_dev(iodev); if (rc) - syslog(LOG_ERR, "Error closing dev %s, rc %d", iodev->info.name, - rc); + return rc; iodev->state = CRAS_IODEV_STATE_CLOSE; if (iodev->ramp) cras_ramp_reset(iodev->ramp); @@ -1092,17 +1050,13 @@ int cras_iodev_put_output_buffer(struct cras_iodev *iodev, uint8_t *frames, /* Calculate whether the final output was non-empty, if requested. */ if (is_non_empty) { - const size_t bytes = nframes * cras_get_format_bytes(fmt); - - /* - * Speed up checking frames are all zeros using memcmp. - * frames contains all zeros if both conditions are met: - * - frames[0] is 0. - * - frames[i] == frames[i+1] for i in [0, 1, ..., bytes - 2]. - */ - *is_non_empty = bytes ? (*frames || memcmp(frames, frames + 1, - bytes - 1)) : - 0; + unsigned int i; + for (i = 0; i < nframes * cras_get_format_bytes(fmt); i++) { + if (frames[i]) { + *is_non_empty = 1; + break; + } + } } DL_FOREACH (iodev->loopbacks, loopback) { @@ -1111,9 +1065,6 @@ int cras_iodev_put_output_buffer(struct cras_iodev *iodev, uint8_t *frames, loopback->cb_data); } - ewma_power_calculate(&iodev->ewma, (int16_t *)frames, - iodev->format->num_channels, nframes); - rc = apply_dsp(iodev, frames, nframes); if (rc) return rc; @@ -1217,11 +1168,6 @@ int cras_iodev_get_input_buffer(struct cras_iodev *iodev, unsigned int *frames) *frames - iodev->input_dsp_offset); if (rc) return rc; - ewma_power_calculate_area( - &iodev->ewma, - (int16_t *)(hw_buffer + - iodev->input_dsp_offset * frame_bytes), - data->area, *frames - iodev->input_dsp_offset); } if (cras_system_get_capture_mute()) @@ -1297,6 +1243,9 @@ int cras_iodev_frames_queued(struct cras_iodev *iodev, int rc; rc = iodev->frames_queued(iodev, hw_tstamp); + if (rc == -EPIPE) + cras_audio_thread_event_severe_underrun(); + if (rc < 0) return rc; @@ -1346,7 +1295,7 @@ int cras_iodev_fill_odev_zeros(struct cras_iodev *odev, unsigned int frames) /* This assumes consecutive channel areas. */ buf = area->channels[0].buf; - memset(buf, 0, (size_t)frames_written * (size_t)frame_bytes); + memset(buf, 0, frames_written * frame_bytes); cras_iodev_put_output_buffer(odev, buf, frames_written, NULL, NULL); frames -= frames_written; @@ -1355,12 +1304,8 @@ int cras_iodev_fill_odev_zeros(struct cras_iodev *odev, unsigned int frames) return 0; } -int cras_iodev_output_underrun(struct cras_iodev *odev, unsigned int hw_level, - unsigned int frames_written) +int cras_iodev_output_underrun(struct cras_iodev *odev) { - ATLOG(atlog, AUDIO_THREAD_UNDERRUN, odev->info.idx, hw_level, - frames_written); - odev->num_underruns++; cras_audio_thread_event_underrun(); if (odev->output_underrun) return odev->output_underrun(odev); @@ -1381,10 +1326,9 @@ int cras_iodev_odev_should_wake(const struct cras_iodev *odev) odev->state == CRAS_IODEV_STATE_NO_STREAM_RUN); } -unsigned int -cras_iodev_default_frames_to_play_in_sleep(struct cras_iodev *odev, - unsigned int *hw_level, - struct timespec *hw_tstamp) +unsigned int cras_iodev_frames_to_play_in_sleep(struct cras_iodev *odev, + unsigned int *hw_level, + struct timespec *hw_tstamp) { int rc = cras_iodev_frames_queued(odev, hw_tstamp); unsigned int level = (rc < 0) ? 0 : rc; @@ -1427,19 +1371,6 @@ cras_iodev_default_frames_to_play_in_sleep(struct cras_iodev *odev, return 0; } -unsigned int cras_iodev_frames_to_play_in_sleep(struct cras_iodev *odev, - unsigned int *hw_level, - struct timespec *hw_tstamp) -{ - /* Use odev's own implementation, if not supported then fall back - * to default behavior below. */ - if (odev->frames_to_play_in_sleep) - return odev->frames_to_play_in_sleep(odev, hw_level, hw_tstamp); - else - return cras_iodev_default_frames_to_play_in_sleep( - odev, hw_level, hw_tstamp); -} - int cras_iodev_default_no_stream_playback(struct cras_iodev *odev, int enable) { if (enable) @@ -1472,7 +1403,9 @@ int cras_iodev_prepare_output_before_write_samples(struct cras_iodev *odev) unsigned int cras_iodev_get_num_underruns(const struct cras_iodev *iodev) { - return iodev->num_underruns; + if (iodev->get_num_underruns) + return iodev->get_num_underruns(iodev); + return 0; } unsigned int cras_iodev_get_num_severe_underruns(const struct cras_iodev *iodev) @@ -1500,7 +1433,7 @@ int cras_iodev_reset_request(struct cras_iodev *iodev) return cras_device_monitor_reset_device(iodev->info.idx); } -static void ramp_down_mute_callback(void *data) +static void ramp_mute_callback(void *data) { struct cras_iodev *odev = (struct cras_iodev *)data; cras_device_monitor_set_device_mute_state(odev->info.idx); @@ -1536,23 +1469,9 @@ int cras_iodev_start_ramp(struct cras_iodev *odev, from = 1.0; to = 0.0; duration_secs = RAMP_MUTE_DURATION_SECS; - cb = ramp_down_mute_callback; + cb = ramp_mute_callback; cb_data = (void *)odev; break; - case CRAS_IODEV_RAMP_REQUEST_RESUME_MUTE: - from = 0; - to = 0; - duration_secs = RAMP_RESUME_MUTE_DURATION_SECS; - odev->initial_ramp_request = - CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; - break; - case CRAS_IODEV_RAMP_REQUEST_SWITCH_MUTE: - from = 0; - to = 0; - duration_secs = RAMP_SWITCH_MUTE_DURATION_SECS; - odev->initial_ramp_request = - CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; - break; default: return -EINVAL; } @@ -1622,22 +1541,6 @@ int cras_iodev_set_mute(struct cras_iodev *iodev) void cras_iodev_update_highest_hw_level(struct cras_iodev *iodev, unsigned int hw_level) { - /* - * If the hw_level is unreasonably high and reach to the device's - * buffer size, regard it as a device overrun. - * In the normal status, the hw_level for should be between 1 to 2 - * largest_cb_level for an output device and 0 to 1 largest_cb_level - * for an input device. Therefore, larger than 3 can be considered - * unreasonable. - */ - if (hw_level == iodev->buffer_size && - iodev->largest_cb_level * 3 < iodev->buffer_size) { - ATLOG(atlog, AUDIO_THREAD_DEV_OVERRUN, iodev->info.idx, - hw_level, 0); - /* Only log the event when the first time it happens. */ - if (iodev->highest_hw_level != hw_level) - cras_audio_thread_event_dev_overrun(); - } iodev->highest_hw_level = MAX(iodev->highest_hw_level, hw_level); } @@ -1652,8 +1555,7 @@ void cras_iodev_update_highest_hw_level(struct cras_iodev *iodev, static int cras_iodev_drop_frames(struct cras_iodev *iodev, unsigned int frames) { struct timespec hw_tstamp; - int i, rc; - unsigned int target_frames, dropped_frames = 0; + int rc; if (iodev->direction != CRAS_STREAM_INPUT) return -EINVAL; @@ -1662,33 +1564,23 @@ static int cras_iodev_drop_frames(struct cras_iodev *iodev, unsigned int frames) if (rc < 0) return rc; - target_frames = MIN(frames, rc); + frames = MIN(frames, rc); + + rc = iodev->get_buffer(iodev, &iodev->input_data->area, &frames); + if (rc < 0) + return rc; + + rc = iodev->put_buffer(iodev, frames); + if (rc < 0) + return rc; /* - * Loop reading the buffer, at most twice. This is to cover when - * circular buffer is at the end and returns partial of the target - * frames. + * Tell rate estimator that some frames have been dropped to avoid calculating + * the wrong rate. */ - for (i = 0; (dropped_frames < target_frames) && (i < 2); i++) { - frames = target_frames - dropped_frames; - rc = iodev->get_buffer(iodev, &iodev->input_data->area, - &frames); - if (rc < 0) - return rc; - - rc = iodev->put_buffer(iodev, frames); - if (rc < 0) - return rc; - dropped_frames += frames; - /* - * Tell rate estimator that some frames have been dropped to - * avoid calculating the wrong rate. - */ - rate_estimator_add_frames(iodev->rate_est, -frames); - } + rate_estimator_add_frames(iodev->rate_est, -frames); - ATLOG(atlog, AUDIO_THREAD_DEV_DROP_FRAMES, iodev->info.idx, - dropped_frames, 0); + ATLOG(atlog, AUDIO_THREAD_DEV_DROP_FRAMES, iodev->info.idx, frames, 0); return frames; } @@ -1707,13 +1599,3 @@ int cras_iodev_drop_frames_by_time(struct cras_iodev *iodev, struct timespec ts) return rc; } - -bool cras_iodev_support_noise_cancellation(const struct cras_iodev *iodev) -{ - if (iodev->direction != CRAS_STREAM_INPUT) - return false; - - if (iodev->support_noise_cancellation) - return !!iodev->support_noise_cancellation(iodev); - return false; -} diff --git a/cras/src/server/cras_iodev.h b/cras/src/server/cras_iodev.h index 18a0962c..f6999336 100644 --- a/cras/src/server/cras_iodev.h +++ b/cras/src/server/cras_iodev.h @@ -19,7 +19,6 @@ #include "cras_dsp.h" #include "cras_iodev_info.h" #include "cras_messages.h" -#include "ewma_power.h" struct buffer_share; struct cras_fmt_conv; @@ -97,13 +96,13 @@ enum CRAS_IODEV_STATE { * plugged - true if the device is plugged. * plugged_time - If plugged is true, this is the time it was attached. * volume - per-node volume (0-100) - * capture_gain - Internal per-node capture gain/attenuation (in 100*dBFS) - * This is only used for CRAS internal tuning, no way to change by - * client. - * ui_gain_scaler - The adjustable gain scaler set by client. + * capture_gain - per-node capture gain/attenuation (in 100*dBFS) * left_right_swapped - If left and right output channels are swapped. * type - Type displayed to the user. * position - Specify where on the system this node locates. + * mic_positions - Whitespace-separated microphone positions using Cartesian + * coordinates in meters with ordering x, y, z. The string is formatted as: + * "x1 y1 z1 ... xn yn zn" for an n-microphone array. * name - Name displayed to the user. * dsp_name - The "DspName" variable specified in the ucm config. * active_hotword_model - name of the currently selected hotword model. @@ -111,8 +110,8 @@ enum CRAS_IODEV_STATE { * software_volume_needed - For output: True if the volume range of the node * is smaller than desired. For input: True if this node needs software * gain. - * intrinsic_sensitivity - The "IntrinsicSensitivity" in 0.01 dBFS/Pa - * specified in the ucm config. + * min_software_gain - The minimum software gain in 0.01 dB if needed. + * max_software_gain - The maximum software gain in 0.01 dB if needed. * stable_id - id for node that doesn't change after unplug/plug. * is_sco_pcm - Bool to indicate whether the ionode is for SCO over PCM. */ @@ -123,16 +122,17 @@ struct cras_ionode { struct timeval plugged_time; unsigned int volume; long capture_gain; - float ui_gain_scaler; int left_right_swapped; enum CRAS_NODE_TYPE type; enum CRAS_NODE_POSITION position; + char mic_positions[CRAS_NODE_MIC_POS_BUFFER_SIZE]; char name[CRAS_NODE_NAME_BUFFER_SIZE]; const char *dsp_name; char active_hotword_model[CRAS_NODE_HOTWORD_MODEL_BUFFER_SIZE]; float *softvol_scalers; int software_volume_needed; - long intrinsic_sensitivity; + long min_software_gain; + long max_software_gain; unsigned int stable_id; int is_sco_pcm; struct cras_ionode *prev, *next; @@ -140,8 +140,8 @@ struct cras_ionode { /* An input or output device, that can have audio routed to/from it. * set_volume - Function to call if the system volume changes. - * set_capture_gain - Function to call if active node's capture_gain changes. * set_mute - Function to call if the system mute state changes. + * set_capture_gain - Function to call if the system capture_gain changes. * set_capture_mute - Function to call if the system capture mute state changes. * set_swap_mode_for_node - Function to call to set swap mode for the node. * open_dev - Opens the device. @@ -175,17 +175,12 @@ struct cras_ionode { * set_hotword_model - Sets the hotword model to this iodev. * get_hotword_models - Gets a comma separated string of the list of supported * hotword models of this iodev. + * get_num_underruns - Gets number of underrun recorded so far. * get_num_severe_underruns - Gets number of severe underrun recorded since * iodev was created. * get_valid_frames - Gets number of valid frames in device which have not * played yet. Valid frames does not include zero samples * we filled under no streams state. - * frames_to_play_in_sleep - Returns the non-negative number of frames that - * audio thread can sleep before serving this playback dev the next time. - * Not implementing this ops means fall back to default behavior in - * cras_iodev_default_frames_to_play_in_sleep(). - * support_noise_cancellation - (Optional) Checks if the device supports noise - * cancellation. * format - The audio format being rendered or captured to hardware. * rate_est - Rate estimator to estimate the actual device rate. * area - Information about how the samples are stored. @@ -217,7 +212,6 @@ struct cras_ionode { * largest_cb_level - The largest callback level of streams attached to this * device. The difference with max_cb_level is it takes all * streams into account even if they have been removed. - * num_underruns - Number of times we have run out of data (playback only). * buf_state - If multiple streams are writing to this device, then this * keeps track of how much each stream has written. * idle_timeout - The timestamp when to close the dev after being idle. @@ -238,9 +232,6 @@ struct cras_ionode { * been processed by the input DSP. * input_data - Used to pass audio input data to streams with or without * stream side processing. - * initial_ramp_request - The value indicates which type of ramp the device - * should perform when some samples are ready for playback. - * ewma - The ewma instance to calculate iodev volume. */ struct cras_iodev { void (*set_volume)(struct cras_iodev *iodev); @@ -270,13 +261,10 @@ struct cras_iodev { int (*set_hotword_model)(struct cras_iodev *iodev, const char *model_name); char *(*get_hotword_models)(struct cras_iodev *iodev); + unsigned int (*get_num_underruns)(const struct cras_iodev *iodev); unsigned int (*get_num_severe_underruns)(const struct cras_iodev *iodev); - int (*get_valid_frames)(struct cras_iodev *odev, + int (*get_valid_frames)(const struct cras_iodev *odev, struct timespec *tstamp); - unsigned int (*frames_to_play_in_sleep)(struct cras_iodev *iodev, - unsigned int *hw_level, - struct timespec *hw_tstamp); - int (*support_noise_cancellation)(const struct cras_iodev *iodev); struct cras_audio_format *format; struct rate_estimator *rate_est; struct cras_audio_area *area; @@ -301,7 +289,6 @@ struct cras_iodev { unsigned int max_cb_level; unsigned int highest_hw_level; unsigned int largest_cb_level; - unsigned int num_underruns; struct buffer_share *buf_state; struct timespec idle_timeout; struct timespec open_ts; @@ -314,9 +301,7 @@ struct cras_iodev { int input_streaming; unsigned int input_frames_read; unsigned int input_dsp_offset; - unsigned int initial_ramp_request; struct input_data *input_data; - struct ewma_power ewma; struct cras_iodev *prev, *next; }; @@ -344,24 +329,12 @@ struct cras_iodev { * - CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK: Ramping is requested because * first sample of new stream is ready, there is no need to change mute/unmute * state. - * - * - CRAS_IODEV_RAMP_REQUEST_RESUME_MUTE: To prevent popped noise, mute the - * device for RAMP_RESUME_MUTE_DURATION_SECS seconds on sample ready after - * resume if there were playback stream before suspend. - * - * - CRAS_IODEV_RAMP_REQUEST_SWITCH_MUTE: To prevent popped noise, mute the - * device for RAMP_SWITCH_MUTE_DURATION_SECS seconds on sample ready after - * device switch if there were playback stream before switch. - * */ enum CRAS_IODEV_RAMP_REQUEST { - CRAS_IODEV_RAMP_REQUEST_NONE = 0, - CRAS_IODEV_RAMP_REQUEST_UP_UNMUTE = 1, - CRAS_IODEV_RAMP_REQUEST_DOWN_MUTE = 2, - CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK = 3, - CRAS_IODEV_RAMP_REQUEST_RESUME_MUTE = 4, - CRAS_IODEV_RAMP_REQUEST_SWITCH_MUTE = 5, + CRAS_IODEV_RAMP_REQUEST_UP_UNMUTE = 0, + CRAS_IODEV_RAMP_REQUEST_DOWN_MUTE = 1, + CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK = 2, }; /* @@ -459,12 +432,6 @@ void cras_iodev_rm_node(struct cras_iodev *iodev, struct cras_ionode *node); void cras_iodev_set_active_node(struct cras_iodev *iodev, struct cras_ionode *node); -/* Checks if the node is the typical playback or capture option for AEC usage. */ -bool cras_iodev_is_aec_use_case(const struct cras_ionode *node); - -/* Checks if the node is a playback or capture node on internal card. */ -bool cras_iodev_is_on_internal_card(const struct cras_ionode *node); - /* Adjust the system volume based on the volume of the given node. */ static inline unsigned int cras_iodev_adjust_node_volume(const struct cras_ionode *node, @@ -489,6 +456,17 @@ cras_iodev_adjust_active_node_volume(struct cras_iodev *iodev, return cras_iodev_adjust_node_volume(iodev->active_node, system_volume); } +/* Get the gain adjusted based on system for the active node. */ +static inline long +cras_iodev_adjust_active_node_gain(const struct cras_iodev *iodev, + long system_gain) +{ + if (!iodev->active_node) + return system_gain; + + return iodev->active_node->capture_gain + system_gain; +} + /* Returns true if the active node of the iodev needs software volume. */ static inline int cras_iodev_software_volume_needed(const struct cras_iodev *iodev) @@ -499,18 +477,39 @@ cras_iodev_software_volume_needed(const struct cras_iodev *iodev) if (!iodev->active_node) return 0; - if (iodev->active_node->intrinsic_sensitivity) - return 1; - return iodev->active_node->software_volume_needed; } -static inline float -cras_iodev_get_ui_gain_scaler(const struct cras_iodev *iodev) +/* Returns minimum software gain for the iodev. + * Args: + * iodev - The device. + * Returs: + * 0 if software gain is not needed, or if there is no active node. + * Returns min_software_gain on active node if there is one. */ +static inline long +cras_iodev_minimum_software_gain(const struct cras_iodev *iodev) { + if (!cras_iodev_software_volume_needed(iodev)) + return 0; if (!iodev->active_node) - return 1.0f; - return iodev->active_node->ui_gain_scaler; + return 0; + return iodev->active_node->min_software_gain; +} + +/* Returns maximum software gain for the iodev. + * Args: + * iodev - The device. + * Returs: + * 0 if software gain is not needed, or if there is no active node. + * Returns max_software_gain on active node if there is one. */ +static inline long +cras_iodev_maximum_software_gain(const struct cras_iodev *iodev) +{ + if (!cras_iodev_software_volume_needed(iodev)) + return 0; + if (!iodev->active_node) + return 0; + return iodev->active_node->max_software_gain; } /* Gets the software gain scaler should be applied on the deivce. @@ -664,17 +663,6 @@ void cras_iodev_set_ext_dsp_module(struct cras_iodev *iodev, /* Put 'frames' worth of zero samples into odev. */ int cras_iodev_fill_odev_zeros(struct cras_iodev *odev, unsigned int frames); -/* - * The default implementation of frames_to_play_in_sleep ops, used when an - * iodev doesn't have its own logic. - * The default behavior is to calculate how log it takes for buffer level to - * run to as low as min_buffer_level. - */ -unsigned int -cras_iodev_default_frames_to_play_in_sleep(struct cras_iodev *odev, - unsigned int *hw_level, - struct timespec *hw_tstamp); - /* Gets the number of frames to play when audio thread sleeps. * Args: * iodev[in] - The device. @@ -770,13 +758,10 @@ int cras_iodev_reset_request(struct cras_iodev *iodev); /* Handle output underrun. * Args: * odev[in] - The output device. - * hw_level[in] - The current hw_level. Used in the debug log. - * frames_written[in] - The number of written frames. Used in the debug log. * Returns: * 0 on success. Negative error code on failure. */ -int cras_iodev_output_underrun(struct cras_iodev *odev, unsigned int hw_level, - unsigned int frames_written); +int cras_iodev_output_underrun(struct cras_iodev *odev); /* Start ramping samples up/down on a device. * Args: @@ -839,12 +824,4 @@ void cras_iodev_update_highest_hw_level(struct cras_iodev *iodev, int cras_iodev_drop_frames_by_time(struct cras_iodev *iodev, struct timespec ts); -/* Checks if an input device supports noise cancellation. - * Args: - * iodev - The device. - * Returns: - * True if device supports noise cancellation. False otherwise. - */ -bool cras_iodev_support_noise_cancellation(const struct cras_iodev *iodev); - #endif /* CRAS_IODEV_H_ */ diff --git a/cras/src/server/cras_iodev_list.c b/cras/src/server/cras_iodev_list.c index b818c97b..c581acdf 100644 --- a/cras/src/server/cras_iodev_list.c +++ b/cras/src/server/cras_iodev_list.c @@ -11,7 +11,6 @@ #include "cras_iodev_info.h" #include "cras_iodev_list.h" #include "cras_loopback_iodev.h" -#include "cras_main_thread_log.h" #include "cras_observer.h" #include "cras_rstream.h" #include "cras_server.h" @@ -19,7 +18,6 @@ #include "cras_types.h" #include "cras_system_state.h" #include "server_stream.h" -#include "softvol_curve.h" #include "stream_list.h" #include "test_iodev.h" #include "utlist.h" @@ -54,8 +52,6 @@ struct device_enabled_cb { struct device_enabled_cb *next, *prev; }; -struct main_thread_event_log *main_log; - /* Lists for devs[CRAS_STREAM_INPUT] and devs[CRAS_STREAM_OUTPUT]. */ static struct iodev_list devs[CRAS_NUM_DIRECTIONS]; /* The observer client iodev_list used to listen on various events. */ @@ -91,9 +87,6 @@ static int stream_list_suspended = 0; static const unsigned int INIT_DEV_DELAY_MS = 1000; /* Flag to indicate that hotword streams are suspended. */ static int hotword_suspended = 0; -/* Flag to indicate that suspended hotword streams should be auto-resumed at - * system resume. */ -static int hotword_auto_resume = 0; static void idle_dev_check(struct cras_timer *timer, void *data); @@ -227,16 +220,10 @@ static const char *node_type_to_str(struct cras_ionode *node) return "USB"; case CRAS_NODE_TYPE_BLUETOOTH: return "BLUETOOTH"; - case CRAS_NODE_TYPE_BLUETOOTH_NB_MIC: - return "BLUETOOTH_NB_MIC"; case CRAS_NODE_TYPE_FALLBACK_NORMAL: return "FALLBACK_NORMAL"; case CRAS_NODE_TYPE_FALLBACK_ABNORMAL: return "FALLBACK_ABNORMAL"; - case CRAS_NODE_TYPE_ECHO_REFERENCE: - return "ECHO_REFERENCE"; - case CRAS_NODE_TYPE_ALSA_LOOPBACK: - return "ALSA_LOOPBACK"; case CRAS_NODE_TYPE_UNKNOWN: default: return "UNKNOWN"; @@ -263,10 +250,10 @@ static int fill_node_list(struct iodev_list *list, dev->is_enabled && (dev->active_node == node); node_info->volume = node->volume; node_info->capture_gain = node->capture_gain; - node_info->ui_gain_scaler = node->ui_gain_scaler; node_info->left_right_swapped = node->left_right_swapped; node_info->stable_id = node->stable_id; + strcpy(node_info->mic_positions, node->mic_positions); strcpy(node_info->name, node->name); strcpy(node_info->active_hotword_model, node->active_hotword_model); @@ -348,7 +335,7 @@ static void remove_all_streams_from_dev(struct cras_iodev *dev) DL_FOREACH (stream_list_get(stream_list), rstream) { if (rstream->apm_list == NULL) continue; - cras_apm_list_remove_apm(rstream->apm_list, dev); + cras_apm_list_remove(rstream->apm_list, dev); } } @@ -364,8 +351,7 @@ static void possibly_enable_echo_reference(struct cras_iodev *dev) if (dev->echo_reference_dev == NULL) return; - server_stream_create(stream_list, dev->echo_reference_dev->info.idx, - dev->format); + server_stream_create(stream_list, dev->echo_reference_dev->info.idx); } /* @@ -381,19 +367,33 @@ static void possibly_disable_echo_reference(struct cras_iodev *dev) } /* - * Removes all attached streams and close dev if it's opened. + * Close dev if it's opened, without the extra call to idle_dev_check. + * This is useful for closing a dev inside idle_dev_check function to + * avoid infinite recursive call. + * + * Returns: + * -EINVAL if device was not opened, otherwise return 0. */ -static void close_dev(struct cras_iodev *dev) +static int close_dev_without_idle_check(struct cras_iodev *dev) { if (!cras_iodev_is_open(dev)) - return; + return -EINVAL; - MAINLOG(main_log, MAIN_THREAD_DEV_CLOSE, dev->info.idx, 0, 0); remove_all_streams_from_dev(dev); dev->idle_timeout.tv_sec = 0; - /* close echo ref first to avoid underrun in hardware */ - possibly_disable_echo_reference(dev); cras_iodev_close(dev); + possibly_disable_echo_reference(dev); + return 0; +} + +static void close_dev(struct cras_iodev *dev) +{ + if (close_dev_without_idle_check(dev)) + return; + + if (idle_timer) + cras_tm_cancel_timer(cras_system_state_get_tm(), idle_timer); + idle_dev_check(NULL, NULL); } static void idle_dev_check(struct cras_timer *timer, void *data) @@ -412,7 +412,7 @@ static void idle_dev_check(struct cras_timer *timer, void *data) if (edev->dev->idle_timeout.tv_sec == 0) continue; if (timespec_after(&now, &edev->dev->idle_timeout)) { - close_dev(edev->dev); + close_dev_without_idle_check(edev->dev); continue; } num_idle_devs++; @@ -467,8 +467,6 @@ static int init_device(struct cras_iodev *dev, struct cras_rstream *rstream) if (cras_iodev_is_open(dev)) return 0; cancel_pending_init_retries(dev->info.idx); - MAINLOG(main_log, MAIN_THREAD_DEV_INIT, dev->info.idx, - rstream->format.num_channels, rstream->format.frame_rate); rc = cras_iodev_open(dev, rstream->cb_threshold, &rstream->format); if (rc) @@ -488,17 +486,10 @@ static void suspend_devs() struct enabled_dev *edev; struct cras_rstream *rstream; - MAINLOG(main_log, MAIN_THREAD_SUSPEND_DEVS, 0, 0, 0); - DL_FOREACH (stream_list_get(stream_list), rstream) { if (rstream->is_pinned) { struct cras_iodev *dev; - /* Skip closing hotword stream in the first pass. - * Closing an input device may resume hotword stream - * with its post_close_iodev_hook so we should deal - * with hotword stream in the second pass. - */ if ((rstream->flags & HOTWORD_STREAM) == HOTWORD_STREAM) continue; @@ -522,52 +513,15 @@ static void suspend_devs() DL_FOREACH (enabled_devs[CRAS_STREAM_INPUT], edev) { close_dev(edev->dev); } - - /* Doing this check after all the other enabled iodevs are closed to - * ensure preempted hotword streams obey the pause_at_suspend flag. - */ - if (cras_system_get_hotword_pause_at_suspend()) { - cras_iodev_list_suspend_hotword_streams(); - hotword_auto_resume = 1; - } } static int stream_added_cb(struct cras_rstream *rstream); static void resume_devs() { - struct enabled_dev *edev; struct cras_rstream *rstream; - int has_output_stream = 0; stream_list_suspended = 0; - - MAINLOG(main_log, MAIN_THREAD_RESUME_DEVS, 0, 0, 0); - - /* Auto-resume based on the local flag in case the system state flag has - * changed. - */ - if (hotword_auto_resume) { - cras_iodev_list_resume_hotword_stream(); - hotword_auto_resume = 0; - } - - /* - * To remove the short popped noise caused by applications that can not - * stop playback "right away" after resume, we mute all output devices - * for a short time if there is any output stream. - */ - DL_FOREACH (stream_list_get(stream_list), rstream) { - if (rstream->direction == CRAS_STREAM_OUTPUT) - has_output_stream++; - } - if (has_output_stream) { - DL_FOREACH (enabled_devs[CRAS_STREAM_OUTPUT], edev) { - edev->dev->initial_ramp_request = - CRAS_IODEV_RAMP_REQUEST_RESUME_MUTE; - } - } - DL_FOREACH (stream_list_get(stream_list), rstream) { if ((rstream->flags & HOTWORD_STREAM) == HOTWORD_STREAM) continue; @@ -584,6 +538,18 @@ void sys_suspend_change(void *arg, int suspended) resume_devs(); } +/* Called when the system capture gain changes. Pass the current capture_gain + * setting to the default input if it is active. */ +void sys_cap_gain_change(void *context, int32_t gain) +{ + struct cras_iodev *dev; + + DL_FOREACH (devs[CRAS_STREAM_INPUT].iodevs, dev) { + if (dev->set_capture_gain && cras_iodev_is_open(dev)) + dev->set_capture_gain(dev); + } +} + /* Called when the system capture mute state changes. Pass the current capture * mute setting to the default input if it is active. */ static void sys_cap_mute_change(void *context, int muted, int mute_locked) @@ -650,10 +616,8 @@ static int add_stream_to_open_devs(struct cras_rstream *stream, int i; if (stream->apm_list) { for (i = 0; i < num_iodevs; i++) - cras_apm_list_add_apm(stream->apm_list, iodevs[i], - iodevs[i]->format, - cras_iodev_is_aec_use_case( - iodevs[i]->active_node)); + cras_apm_list_add(stream->apm_list, iodevs[i], + iodevs[i]->format); } return audio_thread_add_stream(audio_thread, stream, iodevs, num_iodevs); @@ -674,39 +638,20 @@ static int init_and_attach_streams(struct cras_iodev *dev) /* If there are active streams to attach to this device, * open it. */ DL_FOREACH (stream_list_get(stream_list), stream) { - bool can_attach = 0; - if (stream->direction != dir) continue; /* - * For normal stream, if device is enabled by UI then it can - * attach to this dev. - */ - if (!stream->is_pinned) { - can_attach = dev_enabled; - } - /* - * If this is a pinned stream, attach it if its pinned dev id - * matches this device or any fallback dev. Note that attaching - * a pinned stream to fallback device is temporary. When the - * fallback dev gets disabled in possibly_disable_fallback() - * the check stream_list_has_pinned_stream() is key to allow - * all streams to be removed from fallback and close it. + * Don't attach this stream if (1) this stream pins to a + * different device, or (2) this is a normal stream, but + * device is not enabled. */ - else if ((stream->pinned_dev_idx == dev->info.idx) || - (SILENT_PLAYBACK_DEVICE == dev->info.idx) || - (SILENT_RECORD_DEVICE == dev->info.idx)) { - can_attach = 1; - } - - if (!can_attach) + if (stream->is_pinned) { + if (stream->pinned_dev_idx != dev->info.idx) + continue; + } else if (!dev_enabled) { continue; + } - /* - * Note that the stream list is descending ordered by channel - * count, which guarantees the first attachable stream will have - * the highest channel count. - */ rc = init_device(dev, stream); if (rc) { syslog(LOG_ERR, "Enable %s failed, rc = %d", @@ -778,11 +723,6 @@ static int init_pinned_device(struct cras_iodev *dev, return 0; } -/* - * Close device enabled by pinned stream. Since it's NOT in the enabled - * dev list, make sure update_active_node() is called to correctly - * configure the ALSA UCM or BT profile state. - */ static int close_pinned_device(struct cras_iodev *dev) { close_dev(dev); @@ -836,64 +776,34 @@ static int stream_added_cb(struct cras_rstream *rstream) struct cras_iodev *iodevs[10]; unsigned int num_iodevs; int rc; - bool iodev_reopened; if (stream_list_suspended) return 0; - MAINLOG(main_log, MAIN_THREAD_STREAM_ADDED, rstream->stream_id, - rstream->direction, rstream->buffer_frames); - if (rstream->is_pinned) return pinned_stream_added(rstream); /* Add the new stream to all enabled iodevs at once to avoid offset * in shm level between different ouput iodevs. */ num_iodevs = 0; - iodev_reopened = false; DL_FOREACH (enabled_devs[rstream->direction], edev) { if (num_iodevs >= ARRAY_SIZE(iodevs)) { syslog(LOG_ERR, "too many enabled devices"); break; } - if (cras_iodev_is_open(edev->dev) && - (rstream->format.num_channels > - edev->dev->format->num_channels) && - (rstream->format.num_channels <= - edev->dev->info.max_supported_channels)) { - /* Re-open the device with the format of the attached - * stream if it has higher channel count than the - * current format of the device, and doesn't exceed the - * max_supported_channels of the device. - * Fallback device will be transciently enabled during - * the device re-opening. + rc = init_device(edev->dev, rstream); + if (rc) { + /* Error log but don't return error here, because + * stopping audio could block video playback. */ - MAINLOG(main_log, MAIN_THREAD_DEV_REOPEN, - rstream->format.num_channels, - edev->dev->format->num_channels, - edev->dev->format->frame_rate); - syslog(LOG_INFO, "re-open %s for higher channel count", - edev->dev->info.name); - possibly_enable_fallback(rstream->direction, false); - cras_iodev_list_suspend_dev(edev->dev->info.idx); - cras_iodev_list_resume_dev(edev->dev->info.idx); - possibly_disable_fallback(rstream->direction); - iodev_reopened = true; - } else { - rc = init_device(edev->dev, rstream); - if (rc) { - /* Error log but don't return error here, because - * stopping audio could block video playback. - */ - syslog(LOG_ERR, "Init %s failed, rc = %d", - edev->dev->info.name, rc); - schedule_init_device_retry(edev->dev); - continue; - } - - iodevs[num_iodevs++] = edev->dev; + syslog(LOG_ERR, "Init %s failed, rc = %d", + edev->dev->info.name, rc); + schedule_init_device_retry(edev->dev); + continue; } + + iodevs[num_iodevs++] = edev->dev; } if (num_iodevs) { rc = add_stream_to_open_devs(rstream, iodevs, num_iodevs); @@ -901,9 +811,9 @@ static int stream_added_cb(struct cras_rstream *rstream) syslog(LOG_ERR, "adding stream to thread fail"); return rc; } - } else if (!iodev_reopened) { + } else { /* Enable fallback device if no other iodevs can be initialized - * or re-opened successfully. + * successfully. * For error codes like EAGAIN and ENOENT, a new iodev will be * enabled soon so streams are going to route there. As for the * rest of the error cases, silence will be played or recorded @@ -970,8 +880,6 @@ static int stream_removed_cb(struct cras_rstream *rstream) if (rc) return rc; - MAINLOG(main_log, MAIN_THREAD_STREAM_REMOVED, rstream->stream_id, 0, 0); - if (rstream->is_pinned) pinned_stream_removed(rstream); @@ -1018,7 +926,6 @@ static int disable_device(struct enabled_dev *edev, bool force) struct cras_rstream *stream; struct device_enabled_cb *callback; - MAINLOG(main_log, MAIN_THREAD_DEV_DISABLE, dev->info.idx, force, 0); /* * Remove from enabled dev list. However this dev could have a stream * pinned to it, only cancel pending init timers when force flag is set. @@ -1026,23 +933,26 @@ static int disable_device(struct enabled_dev *edev, bool force) DL_DELETE(enabled_devs[dir], edev); free(edev); dev->is_enabled = 0; - if (force) { + if (force) cancel_pending_init_retries(dev->info.idx); + + /* + * Pull all default streams off this device. + * Pull all pinned streams off as well if force is true. + */ + DL_FOREACH (stream_list_get(stream_list), stream) { + if (stream->direction != dev->direction) + continue; + if (stream->is_pinned && !force) + continue; + audio_thread_disconnect_stream(audio_thread, stream, dev); } - /* If there's a pinned stream exists, simply disconnect all the normal - * streams off this device and return. */ - else if (stream_list_has_pinned_stream(stream_list, dev->info.idx)) { - DL_FOREACH (stream_list_get(stream_list), stream) { - if (stream->direction != dev->direction) - continue; - if (stream->is_pinned) - continue; - audio_thread_disconnect_stream(audio_thread, stream, - dev); - } + /* If this is a force disable call, that guarantees pinned streams have + * all been detached. Otherwise check with stream_list to see if + * there's still a pinned stream using this device. + */ + if (!force && stream_list_has_pinned_stream(stream_list, dev->info.idx)) return 0; - } - DL_FOREACH (device_enable_cbs, callback) callback->disabled_cb(dev, callback->cb_data); close_dev(dev); @@ -1052,6 +962,36 @@ static int disable_device(struct enabled_dev *edev, bool force) } /* + * Assume the device is not in enabled_devs list. + * Assume there is no default stream on the device. + * An example is that this device is unplugged while it is playing + * a pinned stream. The device and stream may have been removed in + * audio thread due to I/O error handling. + */ +static int force_close_pinned_only_device(struct cras_iodev *dev) +{ + struct cras_rstream *rstream; + + /* Pull pinned streams off this device. Note that this is initiated + * from server side, so the pin stream still exist in stream_list + * pending client side to actually remove it. + */ + DL_FOREACH (stream_list_get(stream_list), rstream) { + if (rstream->direction != dev->direction) + continue; + if (!rstream->is_pinned) + continue; + if (dev->info.idx != rstream->pinned_dev_idx) + continue; + audio_thread_disconnect_stream(audio_thread, rstream, dev); + } + + close_dev(dev); + dev->update_active_node(dev, dev->active_node->idx, 0); + return 0; +} + +/* * Exported Interface. */ @@ -1062,13 +1002,12 @@ void cras_iodev_list_init() memset(&observer_ops, 0, sizeof(observer_ops)); observer_ops.output_volume_changed = sys_vol_change; observer_ops.output_mute_changed = sys_mute_change; + observer_ops.capture_gain_changed = sys_cap_gain_change; observer_ops.capture_mute_changed = sys_cap_mute_change; observer_ops.suspend_changed = sys_suspend_change; list_observer = cras_observer_add(&observer_ops, NULL); idle_timer = NULL; - main_log = main_thread_event_log_init(); - /* Create the audio stream list for the system. */ stream_list = stream_list_create(stream_added_cb, stream_removed_cb, @@ -1110,7 +1049,6 @@ void cras_iodev_list_deinit() empty_iodev_destroy(fallback_devs[CRAS_STREAM_INPUT]); empty_iodev_destroy(fallback_devs[CRAS_STREAM_OUTPUT]); stream_list_destroy(stream_list); - main_thread_event_log_deinit(main_log); if (list_observer) { cras_observer_remove(list_observer); list_observer = NULL; @@ -1146,8 +1084,6 @@ void cras_iodev_list_add_active_node(enum CRAS_STREAM_DIRECTION dir, if (!new_dev || new_dev->direction != dir) return; - MAINLOG(main_log, MAIN_THREAD_ADD_ACTIVE_NODE, new_dev->info.idx, 0, 0); - /* If the new dev is already enabled but its active node needs to be * changed. Disable new dev first, update active node, and then * re-enable it again. @@ -1187,7 +1123,7 @@ void cras_iodev_list_disable_dev(struct cras_iodev *dev, bool force_close) */ if (!edev_to_disable) { if (force_close) - close_pinned_device(dev); + force_close_pinned_only_device(dev); return; } @@ -1205,13 +1141,25 @@ void cras_iodev_list_disable_dev(struct cras_iodev *dev, bool force_close) void cras_iodev_list_suspend_dev(unsigned int dev_idx) { + struct cras_rstream *rstream; struct cras_iodev *dev = find_dev(dev_idx); if (!dev) return; - /* Remove all streams including the pinned streams, and close - * this iodev. */ + DL_FOREACH (stream_list_get(stream_list), rstream) { + if (rstream->direction != dev->direction) + continue; + /* Disconnect all streams that are either: + * (1) normal stream while dev is enabled by UI, or + * (2) stream specifically pins to this dev. + */ + if ((dev->is_enabled && !rstream->is_pinned) || + (rstream->is_pinned && + (dev->info.idx != rstream->pinned_dev_idx))) + audio_thread_disconnect_stream(audio_thread, rstream, + dev); + } close_dev(dev); dev->update_active_node(dev, dev->active_node->idx, 0); } @@ -1272,8 +1220,6 @@ int cras_iodev_list_add_output(struct cras_iodev *output) if (rc) return rc; - MAINLOG(main_log, MAIN_THREAD_ADD_TO_DEV_LIST, output->info.idx, - CRAS_STREAM_OUTPUT, 0); return 0; } @@ -1288,8 +1234,6 @@ int cras_iodev_list_add_input(struct cras_iodev *input) if (rc) return rc; - MAINLOG(main_log, MAIN_THREAD_ADD_TO_DEV_LIST, input->info.idx, - CRAS_STREAM_INPUT, 0); return 0; } @@ -1532,15 +1476,11 @@ void cras_iodev_list_select_node(enum CRAS_STREAM_DIRECTION direction, struct cras_iodev *new_dev = NULL; struct enabled_dev *edev; int new_node_already_enabled = 0; - struct cras_rstream *rstream; - int has_output_stream = 0; int rc; /* find the devices for the id. */ new_dev = find_dev(dev_index_of(node_id)); - MAINLOG(main_log, MAIN_THREAD_SELECT_NODE, dev_index_of(node_id), 0, 0); - /* Do nothing if the direction is mismatched. The new_dev == NULL case could happen if node_id is 0 (no selection), or the client tries to select a non-existing node (maybe it's unplugged just before @@ -1568,44 +1508,17 @@ void cras_iodev_list_select_node(enum CRAS_STREAM_DIRECTION direction, if (!new_node_already_enabled) possibly_enable_fallback(direction, false); + /* Disable all devices except for fallback device, and the new device, + * provided it is already enabled. */ DL_FOREACH (enabled_devs[direction], edev) { - /* Don't disable fallback devices. */ - if (edev->dev == fallback_devs[direction]) - continue; - /* - * Disable enabled device if it's not the new one, use non-force - * disable call so we don't interrupt existing pinned streams on - * it. - */ - if (edev->dev != new_dev) { + if (edev->dev != fallback_devs[direction] && + !(new_node_already_enabled && edev->dev == new_dev)) { disable_device(edev, false); } - /* - * Otherwise if this happens to be the new device but about to - * select to a different node (on the same dev). Force disable - * this device to avoid any pinned stream occupies it in audio - * thread and cause problem in later update_active_node call. - */ - else if (!new_node_already_enabled) { - disable_device(edev, true); - } } if (new_dev && !new_node_already_enabled) { new_dev->update_active_node(new_dev, node_index_of(node_id), 1); - - /* To reduce the popped noise of active device change, mute - * new_dev's for RAMP_SWITCH_MUTE_DURATION_SECS s. - */ - DL_FOREACH (stream_list_get(stream_list), rstream) { - if (rstream->direction == CRAS_STREAM_OUTPUT) - has_output_stream++; - } - if (direction == CRAS_STREAM_OUTPUT && has_output_stream) { - new_dev->initial_ramp_request = - CRAS_IODEV_RAMP_REQUEST_SWITCH_MUTE; - } - rc = enable_device(new_dev); if (rc == 0) { /* Disable fallback device after new device is enabled. @@ -1647,38 +1560,22 @@ static int set_node_volume(struct cras_iodev *iodev, unsigned int node_idx, if (iodev->set_volume) iodev->set_volume(iodev); cras_iodev_list_notify_node_volume(node); - MAINLOG(main_log, MAIN_THREAD_OUTPUT_NODE_VOLUME, iodev->info.idx, - volume, 0); return 0; } static int set_node_capture_gain(struct cras_iodev *iodev, - unsigned int node_idx, int value) + unsigned int node_idx, int capture_gain) { struct cras_ionode *node; - int db_scale; node = find_node(iodev, node_idx); if (!node) return -EINVAL; - /* Assert value in range 0 - 100. */ - if (value < 0) - value = 0; - if (value > 100) - value = 100; - - /* Linear maps (0, 50) to (-4000, 0) and (50, 100) to (0, 2000) dBFS. - * Calculate and store corresponding scaler in ui_gain_scaler. */ - db_scale = (value > 50) ? 40 : 80; - node->ui_gain_scaler = - convert_softvol_scaler_from_dB((value - 50) * db_scale); - + node->capture_gain = capture_gain; if (iodev->set_capture_gain) iodev->set_capture_gain(iodev); cras_iodev_list_notify_node_capture_gain(node); - MAINLOG(main_log, MAIN_THREAD_INPUT_NODE_GAIN, iodev->info.idx, value, - 0); return 0; } @@ -1881,24 +1778,6 @@ void cras_iodev_list_unregister_loopback(enum CRAS_LOOPBACK_TYPE type, } } -void cras_iodev_list_reset_for_noise_cancellation() -{ - struct cras_iodev *dev; - bool enabled = cras_system_get_noise_cancellation_enabled(); - - DL_FOREACH (devs[CRAS_STREAM_INPUT].iodevs, dev) { - if (!cras_iodev_is_open(dev) || - !cras_iodev_support_noise_cancellation(dev)) - continue; - syslog(LOG_INFO, "Re-open %s for %s noise cancellation", - dev->info.name, enabled ? "enabling" : "disabling"); - possibly_enable_fallback(CRAS_STREAM_INPUT, false); - cras_iodev_list_suspend_dev(dev->info.idx); - cras_iodev_list_resume_dev(dev->info.idx); - possibly_disable_fallback(CRAS_STREAM_INPUT); - } -} - void cras_iodev_list_reset() { struct enabled_dev *edev; diff --git a/cras/src/server/cras_iodev_list.h b/cras/src/server/cras_iodev_list.h index d6e9ba54..61c3a182 100644 --- a/cras/src/server/cras_iodev_list.h +++ b/cras/src/server/cras_iodev_list.h @@ -274,11 +274,6 @@ int cras_iodev_list_suspend_hotword_streams(); /* Resumes all hotwording streams. */ int cras_iodev_list_resume_hotword_stream(); -/* Sets the state of noise cancellation for input devices which supports noise - * cancellation by suspend, enable/disable, then resume. - */ -void cras_iodev_list_reset_for_noise_cancellation(); - /* For unit test only. */ void cras_iodev_list_reset(); diff --git a/cras/src/server/cras_loopback_iodev.c b/cras/src/server/cras_loopback_iodev.c index cf3ba4ae..dea96169 100644 --- a/cras/src/server/cras_loopback_iodev.c +++ b/cras/src/server/cras_loopback_iodev.c @@ -7,7 +7,6 @@ #include <sys/param.h> #include <syslog.h> -#include "audio_thread_log.h" #include "byte_buffer.h" #include "cras_audio_area.h" #include "cras_config.h" @@ -61,9 +60,6 @@ static int sample_hook_start(bool start, void *cb_data) /* * Called in the put buffer function of the sender that hooked to. - * - * Returns: - * Number of frames copied to the sample buffer in the hook. */ static int sample_hook(const uint8_t *frames, unsigned int nframes, const struct cras_audio_format *fmt, void *cb_data) @@ -71,26 +67,17 @@ static int sample_hook(const uint8_t *frames, unsigned int nframes, struct loopback_iodev *loopdev = (struct loopback_iodev *)cb_data; struct byte_buffer *sbuf = loopdev->sample_buffer; unsigned int frame_bytes = cras_get_format_bytes(fmt); - unsigned int frames_to_copy, bytes_to_copy, frames_copied = 0; - int i; - - for (i = 0; i < 2; i++) { - frames_to_copy = MIN(buf_writable(sbuf) / frame_bytes, nframes); - if (!frames_to_copy) - break; - - bytes_to_copy = frames_to_copy * frame_bytes; - memcpy(buf_write_pointer(sbuf), frames, bytes_to_copy); - buf_increment_write(sbuf, bytes_to_copy); - frames += bytes_to_copy; - nframes -= frames_to_copy; - frames_copied += frames_to_copy; - } + unsigned int frames_to_copy, bytes_to_copy; + + frames_to_copy = MIN(buf_writable(sbuf) / frame_bytes, nframes); + if (!frames_to_copy) + return 0; - ATLOG(atlog, AUDIO_THREAD_LOOPBACK_SAMPLE_HOOK, nframes + frames_copied, - frames_copied, 0); + bytes_to_copy = frames_to_copy * frame_bytes; + memcpy(buf_write_pointer(sbuf), frames, bytes_to_copy); + buf_increment_write(sbuf, bytes_to_copy); - return frames_copied; + return frames_to_copy; } static void update_first_output_to_loopback(struct loopback_iodev *loopdev) @@ -219,8 +206,6 @@ static int get_record_buffer(struct cras_iodev *iodev, unsigned int frame_bytes = cras_get_format_bytes(iodev->format); unsigned int avail_frames = buf_readable(sbuf) / frame_bytes; - ATLOG(atlog, AUDIO_THREAD_LOOPBACK_GET, *frames, avail_frames, 0); - *frames = MIN(avail_frames, *frames); iodev->area->frames = *frames; cras_audio_area_config_buf_pointers(iodev->area, iodev->format, @@ -236,9 +221,8 @@ static int put_record_buffer(struct cras_iodev *iodev, unsigned nframes) struct byte_buffer *sbuf = loopdev->sample_buffer; unsigned int frame_bytes = cras_get_format_bytes(iodev->format); - buf_increment_read(sbuf, (size_t)nframes * (size_t)frame_bytes); + buf_increment_read(sbuf, nframes * frame_bytes); loopdev->read_frames += nframes; - ATLOG(atlog, AUDIO_THREAD_LOOPBACK_PUT, nframes, 0, 0); return 0; } @@ -297,12 +281,6 @@ static struct cras_iodev *create_loopback_iodev(enum CRAS_LOOPBACK_TYPE type) iodev->put_buffer = put_record_buffer; iodev->flush_buffer = flush_record_buffer; - /* - * Record max supported channels into cras_iodev_info. - * The value is the max of loopback_supported_channel_counts. - */ - iodev->info.max_supported_channels = 2; - return iodev; } @@ -331,15 +309,15 @@ struct cras_iodev *loopback_iodev_create(enum CRAS_LOOPBACK_TYPE type) if (iodev == NULL) return NULL; - /* Create an empty ionode */ + /* Create a dummy ionode */ node = (struct cras_ionode *)calloc(1, sizeof(*node)); node->dev = iodev; node->type = node_type; node->plugged = 1; node->volume = 100; - node->ui_gain_scaler = 1.0f; node->stable_id = iodev->info.stable_id; node->software_volume_needed = 0; + node->max_software_gain = 0; strcpy(node->name, loopdev_names[type]); cras_iodev_add_node(iodev, node); cras_iodev_set_active_node(iodev, node); diff --git a/cras/src/server/cras_main_message.c b/cras/src/server/cras_main_message.c index b88e4000..9fe62afb 100644 --- a/cras/src/server/cras_main_message.c +++ b/cras/src/server/cras_main_message.c @@ -77,7 +77,7 @@ static int read_main_message(int msg_fd, uint8_t *buf, size_t max_len) return 0; } -static void handle_main_messages(void *arg, int revents) +static void handle_main_messages(void *arg) { uint8_t buf[256]; int rc; @@ -112,6 +112,5 @@ void cras_main_message_init() cras_make_fd_nonblocking(main_msg_fds[0]); cras_make_fd_nonblocking(main_msg_fds[1]); - cras_system_add_select_fd(main_msg_fds[0], handle_main_messages, NULL, - POLLIN); + cras_system_add_select_fd(main_msg_fds[0], handle_main_messages, NULL); } diff --git a/cras/src/server/cras_main_thread_log.h b/cras/src/server/cras_main_thread_log.h deleted file mode 100644 index 1d92585a..00000000 --- a/cras/src/server/cras_main_thread_log.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CRAS_MAIN_THREAD_LOG_H_ -#define CRAS_MAIN_THREAD_LOG_H_ - -#include <stdint.h> - -#include "cras_types.h" - -#define CRAS_MAIN_THREAD_LOGGING 1 - -#if (CRAS_MAIN_THREAD_LOGGING) -#define MAINLOG(log, event, data1, data2, data3) \ - main_thread_event_log_data(log, event, data1, data2, data3); -#else -#define MAINLOG(log, event, data1, data2, data3) -#endif - -extern struct main_thread_event_log *main_log; - -static inline struct main_thread_event_log *main_thread_event_log_init() -{ - struct main_thread_event_log *log; - log = (struct main_thread_event_log *)calloc( - 1, sizeof(struct main_thread_event_log)); - if (!log) - return NULL; - - log->len = MAIN_THREAD_EVENT_LOG_SIZE; - return log; -} - -static inline void -main_thread_event_log_deinit(struct main_thread_event_log *log) -{ - if (log) - free(log); -} - -static inline void main_thread_event_log_data(struct main_thread_event_log *log, - enum MAIN_THREAD_LOG_EVENTS event, - uint32_t data1, uint32_t data2, - uint32_t data3) -{ - struct timespec now; - - if (!log) - return; - - clock_gettime(CLOCK_MONOTONIC_RAW, &now); - log->log[log->write_pos].tag_sec = - (event << 24) | ((now.tv_sec % 86400) & 0x00ffffff); - log->log[log->write_pos].nsec = now.tv_nsec; - log->log[log->write_pos].data1 = data1; - log->log[log->write_pos].data2 = data2; - log->log[log->write_pos].data3 = data3; - log->write_pos++; - log->write_pos %= MAIN_THREAD_EVENT_LOG_SIZE; -} - -#endif /* CRAS_MAIN_THREAD_LOG_H_ */ diff --git a/cras/src/server/cras_observer.c b/cras/src/server/cras_observer.c index 0f17dc92..0f6ab96b 100644 --- a/cras/src/server/cras_observer.c +++ b/cras/src/server/cras_observer.c @@ -7,7 +7,6 @@ #include "cras_alert.h" #include "cras_iodev_list.h" -#include "cras_types.h" #include "utlist.h" struct cras_observer_client { @@ -35,8 +34,6 @@ struct cras_observer_alerts { * per-direciton. */ struct cras_alert *num_active_streams[CRAS_NUM_DIRECTIONS]; struct cras_alert *non_empty_audio_state_changed; - struct cras_alert *bt_battery_changed; - struct cras_alert *num_input_streams_with_permission; }; struct cras_observer_server { @@ -78,10 +75,6 @@ struct cras_observer_alert_data_streams { uint32_t num_active_streams; }; -struct cras_observer_alert_data_input_streams { - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]; -}; - struct cras_observer_alert_data_hotword_triggered { int64_t tv_sec; int64_t tv_nsec; @@ -91,11 +84,6 @@ struct cras_observer_non_empty_audio_state { int non_empty; }; -struct cras_observer_alert_data_bt_battery_changed { - const char *address; - uint32_t level; -}; - /* Global observer instance. */ static struct cras_observer_server *g_observer; @@ -259,20 +247,6 @@ static void num_active_streams_alert(void *arg, void *data) } } -static void num_input_streams_with_permission_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_input_streams *input_streams_data = - (struct cras_observer_alert_data_input_streams *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.num_input_streams_with_permission_changed) - client->ops.num_input_streams_with_permission_changed( - client->context, - input_streams_data->num_input_streams); - } -} - static void hotword_triggered_alert(void *arg, void *data) { struct cras_observer_client *client; @@ -302,20 +276,6 @@ static void non_empty_audio_state_changed_alert(void *arg, void *data) } } -static void bt_battery_changed_alert(void *arg, void *data) -{ - struct cras_observer_client *client; - struct cras_observer_alert_data_bt_battery_changed *triggered_data = - (struct cras_observer_alert_data_bt_battery_changed *)data; - - DL_FOREACH (g_observer->clients, client) { - if (client->ops.bt_battery_changed) - client->ops.bt_battery_changed(client->context, - triggered_data->address, - triggered_data->level); - } -} - static int cras_observer_server_set_alert(struct cras_alert **alert, cras_alert_cb cb, cras_alert_prepare prepare, @@ -372,8 +332,6 @@ int cras_observer_server_init() CRAS_OBSERVER_SET_ALERT(suspend_changed, NULL, 0); CRAS_OBSERVER_SET_ALERT(hotword_triggered, NULL, 0); CRAS_OBSERVER_SET_ALERT(non_empty_audio_state_changed, NULL, 0); - CRAS_OBSERVER_SET_ALERT(bt_battery_changed, NULL, 0); - CRAS_OBSERVER_SET_ALERT(num_input_streams_with_permission, NULL, 0); CRAS_OBSERVER_SET_ALERT_WITH_DIRECTION(num_active_streams, CRAS_STREAM_OUTPUT); @@ -405,9 +363,6 @@ void cras_observer_server_free() cras_alert_destroy(g_observer->alerts.suspend_changed); cras_alert_destroy(g_observer->alerts.hotword_triggered); cras_alert_destroy(g_observer->alerts.non_empty_audio_state_changed); - cras_alert_destroy(g_observer->alerts.bt_battery_changed); - cras_alert_destroy( - g_observer->alerts.num_input_streams_with_permission); cras_alert_destroy( g_observer->alerts.num_active_streams[CRAS_STREAM_OUTPUT]); cras_alert_destroy( @@ -585,21 +540,6 @@ void cras_observer_notify_num_active_streams(enum CRAS_STREAM_DIRECTION dir, cras_alert_pending_data(alert, &data, sizeof(data)); } -void cras_observer_notify_input_streams_with_permission( - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) -{ - struct cras_observer_alert_data_input_streams data; - struct cras_alert *alert; - - memcpy(&data.num_input_streams, num_input_streams, - sizeof(*num_input_streams) * CRAS_NUM_CLIENT_TYPE); - alert = g_observer->alerts.num_input_streams_with_permission; - if (!alert) - return; - - cras_alert_pending_data(alert, &data, sizeof(data)); -} - void cras_observer_notify_hotword_triggered(int64_t tv_sec, int64_t tv_nsec) { struct cras_observer_alert_data_hotword_triggered data; @@ -619,16 +559,4 @@ void cras_observer_notify_non_empty_audio_state_changed(int non_empty) cras_alert_pending_data( g_observer->alerts.non_empty_audio_state_changed, &data, sizeof(data)); -} - -void cras_observer_notify_bt_battery_changed(const char *address, - uint32_t level) -{ - struct cras_observer_alert_data_bt_battery_changed data; - - data.address = address; - data.level = level; - - cras_alert_pending_data(g_observer->alerts.bt_battery_changed, &data, - sizeof(data)); -} +}
\ No newline at end of file diff --git a/cras/src/server/cras_observer.h b/cras/src/server/cras_observer.h index 2dd013b8..109bd609 100644 --- a/cras/src/server/cras_observer.h +++ b/cras/src/server/cras_observer.h @@ -92,18 +92,10 @@ void cras_observer_notify_suspend_changed(int suspended); void cras_observer_notify_num_active_streams(enum CRAS_STREAM_DIRECTION dir, uint32_t num_active_streams); -/* Notify observers of the number of input streams with permission. */ -void cras_observer_notify_input_streams_with_permission( - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]); - /* Notify observers of the timestamp when hotword triggered. */ void cras_observer_notify_hotword_triggered(int64_t tv_sec, int64_t tv_nsec); /* Notify observers the non-empty audio state changed. */ void cras_observer_notify_non_empty_audio_state_changed(int active); -/* Notify observers the bluetooth headset battery level changed. */ -void cras_observer_notify_bt_battery_changed(const char *address, - uint32_t level); - #endif /* CRAS_OBSERVER_H */ diff --git a/cras/src/server/cras_playback_rclient.c b/cras/src/server/cras_playback_rclient.c index 54a75dbd..a282e8b1 100644 --- a/cras/src/server/cras_playback_rclient.c +++ b/cras/src/server/cras_playback_rclient.c @@ -11,12 +11,63 @@ #include "cras_rclient.h" #include "cras_rclient_util.h" #include "cras_rstream.h" +#include "cras_system_state.h" #include "cras_types.h" #include "cras_util.h" +#include "stream_list.h" + +/* Entry point for handling a message from the client. Called from the main + * server context. */ +static int cpr_handle_message_from_client(struct cras_rclient *client, + const struct cras_server_message *msg, + int *fds, unsigned int num_fds) +{ + int rc = 0; + assert(client && msg); + + rc = rclient_validate_message_fds(msg, fds, num_fds); + if (rc < 0) { + for (int i = 0; i < (int)num_fds; i++) + if (fds[i] >= 0) + close(fds[i]); + return rc; + } + int fd = num_fds > 0 ? fds[0] : -1; + + switch (msg->id) { + case CRAS_SERVER_CONNECT_STREAM: { + int client_shm_fd = num_fds > 1 ? fds[1] : -1; + struct cras_connect_message cmsg; + if (MSG_LEN_VALID(msg, struct cras_connect_message)) { + rc = rclient_handle_client_stream_connect( + client, + (const struct cras_connect_message *)msg, fd, + client_shm_fd); + } else if (!convert_connect_message_old(msg, &cmsg)) { + rc = rclient_handle_client_stream_connect( + client, &cmsg, fd, client_shm_fd); + } else { + return -EINVAL; + } + break; + } + case CRAS_SERVER_DISCONNECT_STREAM: + if (!MSG_LEN_VALID(msg, struct cras_disconnect_stream_message)) + return -EINVAL; + rc = rclient_handle_client_stream_disconnect( + client, + (const struct cras_disconnect_stream_message *)msg); + break; + default: + break; + } + + return rc; +} /* Declarations of cras_rclient operators for cras_playback_rclient. */ static const struct cras_rclient_ops cras_playback_rclient_ops = { - .handle_message_from_client = rclient_handle_message_from_client, + .handle_message_from_client = cpr_handle_message_from_client, .send_message_to_client = rclient_send_message_to_client, .destroy = rclient_destroy, }; @@ -29,7 +80,24 @@ static const struct cras_rclient_ops cras_playback_rclient_ops = { * the connection has succeeded. */ struct cras_rclient *cras_playback_rclient_create(int fd, size_t id) { - return rclient_generic_create( - fd, id, &cras_playback_rclient_ops, - cras_stream_direction_mask(CRAS_STREAM_OUTPUT)); + struct cras_rclient *client; + struct cras_client_connected msg; + int state_fd; + + client = (struct cras_rclient *)calloc(1, sizeof(struct cras_rclient)); + if (!client) + return NULL; + + client->fd = fd; + client->id = id; + + client->ops = &cras_playback_rclient_ops; + client->supported_directions = + cras_stream_direction_mask(CRAS_STREAM_OUTPUT); + + cras_fill_client_connected(&msg, client->id); + state_fd = cras_sys_state_shm_fd(); + client->ops->send_message_to_client(client, &msg.header, &state_fd, 1); + + return client; } diff --git a/cras/src/server/cras_ramp.c b/cras/src/server/cras_ramp.c index f0272047..5f40a777 100644 --- a/cras/src/server/cras_ramp.c +++ b/cras/src/server/cras_ramp.c @@ -62,11 +62,7 @@ int cras_ramp_start(struct cras_ramp *ramp, int mute_ramp, float from, float to, { struct cras_ramp_action action; - if (!ramp) - return -EINVAL; - - /* if from == to == 0 means we want to mute for duration_frames */ - if (from == to && from != 0) + if (from == to) return 0; /* Get current scaler position so it can serve as new start scaler. */ diff --git a/cras/src/server/cras_rclient.c b/cras/src/server/cras_rclient.c index d2646e75..38ba5c20 100644 --- a/cras/src/server/cras_rclient.c +++ b/cras/src/server/cras_rclient.c @@ -24,7 +24,6 @@ #include "cras_server_metrics.h" #include "cras_system_state.h" #include "cras_types.h" -#include "cras_unified_rclient.h" #include "cras_util.h" #include "stream_list.h" #include "utlist.h" @@ -59,16 +58,9 @@ int cras_rclient_send_message(const struct cras_rclient *client, return client->ops->send_message_to_client(client, msg, fds, num_fds); } -static void cras_rclient_set_client_type(struct cras_rclient *client, - enum CRAS_CLIENT_TYPE client_type) -{ - client->client_type = client_type; -} - struct cras_rclient *cras_rclient_create(int fd, size_t id, enum CRAS_CONNECTION_TYPE conn_type) { - struct cras_rclient *client; if (!cras_validate_connection_type(conn_type)) goto error; @@ -79,18 +71,6 @@ struct cras_rclient *cras_rclient_create(int fd, size_t id, return cras_playback_rclient_create(fd, id); case CRAS_CAPTURE: return cras_capture_rclient_create(fd, id); - case CRAS_VMS_LEGACY: - return cras_playback_rclient_create(fd, id); - case CRAS_VMS_UNIFIED: - return cras_unified_rclient_create(fd, id); - case CRAS_PLUGIN_PLAYBACK: - client = cras_playback_rclient_create(fd, id); - cras_rclient_set_client_type(client, CRAS_CLIENT_TYPE_PLUGIN); - return client; - case CRAS_PLUGIN_UNIFIED: - client = cras_unified_rclient_create(fd, id); - cras_rclient_set_client_type(client, CRAS_CLIENT_TYPE_PLUGIN); - return client; default: goto error; } diff --git a/cras/src/server/cras_rclient.h b/cras/src/server/cras_rclient.h index 3a3988c2..6cffb7d8 100644 --- a/cras/src/server/cras_rclient.h +++ b/cras/src/server/cras_rclient.h @@ -20,9 +20,6 @@ struct cras_server_message; * fd - Connection for client communication. * ops - cras_rclient_ops for the cras_rclient. * supported_directions - Bit mask for supported stream directions. - * client_type - Client type of this rclient. If this is set to value other - * than CRAS_CLIENT_TYPE_UNKNOWN, rclient will overwrite incoming - * messages' client type. */ struct cras_rclient { struct cras_observer_client *observer; @@ -30,7 +27,6 @@ struct cras_rclient { int fd; const struct cras_rclient_ops *ops; int supported_directions; - enum CRAS_CLIENT_TYPE client_type; }; /* Operations for cras_rclient. diff --git a/cras/src/server/cras_rclient_util.c b/cras/src/server/cras_rclient_util.c index 0af98863..c88df82e 100644 --- a/cras/src/server/cras_rclient_util.c +++ b/cras/src/server/cras_rclient_util.c @@ -12,7 +12,6 @@ #include "cras_rclient_util.h" #include "cras_rstream.h" #include "cras_server_metrics.h" -#include "cras_system_state.h" #include "cras_tm.h" #include "cras_types.h" #include "cras_util.h" @@ -43,8 +42,9 @@ int rclient_validate_message_fds(const struct cras_server_message *msg, goto error; break; case CRAS_SERVER_SET_AEC_DUMP: - if (num_fds > 1) + if (num_fds != 1) goto error; + syslog(LOG_ERR, "client msg for APM debug, fd %d", fds[0]); break; default: if (num_fds > 0) @@ -80,13 +80,6 @@ rclient_validate_stream_connect_message(const struct cras_rclient *client, msg->direction, client->id); return -EINVAL; } - - if (!cras_validate_client_type(msg->client_type)) { - syslog(LOG_ERR, - "stream_connect: invalid stream client_type: %x for " - "client: %zx.\n", - msg->client_type, client->id); - } return 0; } @@ -140,15 +133,10 @@ int rclient_handle_client_stream_connect(struct cras_rclient *client, struct cras_audio_format remote_fmt; struct cras_rstream_config stream_config; int rc, header_fd, samples_fd; - size_t samples_size; int stream_fds[2]; rc = rclient_validate_stream_connect_params(client, msg, aud_fd, client_shm_fd); - remote_fmt = unpack_cras_audio_format(&msg->format); - if (rc == 0 && !cras_audio_format_valid(&remote_fmt)) { - rc = -EINVAL; - } if (rc) { if (client_shm_fd >= 0) close(client_shm_fd); @@ -157,40 +145,26 @@ int rclient_handle_client_stream_connect(struct cras_rclient *client, goto reply_err; } + unpack_cras_audio_format(&remote_fmt, &msg->format); + /* When full, getting an error is preferable to blocking. */ cras_make_fd_nonblocking(aud_fd); - stream_config = cras_rstream_config_init_with_message( - client, msg, &aud_fd, &client_shm_fd, &remote_fmt); - /* Overwrite client_type if client->client_type is set. */ - if (client->client_type != CRAS_CLIENT_TYPE_UNKNOWN) - stream_config.client_type = client->client_type; + cras_rstream_config_init_with_message(client, msg, &aud_fd, + &client_shm_fd, &remote_fmt, + &stream_config); rc = stream_list_add(cras_iodev_list_get_stream_list(), &stream_config, &stream); if (rc) goto cleanup_config; - detect_rtc_stream_pair(cras_iodev_list_get_stream_list(), stream); - /* Tell client about the stream setup. */ syslog(LOG_DEBUG, "Send connected for stream %x\n", msg->stream_id); - - // Check that shm size is at most UINT32_MAX for non-shm streams. - samples_size = cras_rstream_get_samples_shm_size(stream); - if (samples_size > UINT32_MAX && stream_config.client_shm_fd < 0) { - syslog(LOG_ERR, - "Non client-provided shm stream has samples shm larger " - "than uint32_t: %zu", - samples_size); - if (aud_fd >= 0) - close(aud_fd); - rc = -EINVAL; - goto cleanup_config; - } - cras_fill_client_stream_connected(&stream_connected, 0, /* No error. */ - msg->stream_id, &remote_fmt, - samples_size, - cras_rstream_get_effects(stream)); + cras_fill_client_stream_connected( + &stream_connected, 0, /* No error. */ + msg->stream_id, &remote_fmt, + cras_rstream_get_samples_shm_size(stream), + cras_rstream_get_effects(stream)); reply = &stream_connected.header; rc = cras_rstream_get_shm_fds(stream, &header_fd, &samples_fd); @@ -210,6 +184,9 @@ int rclient_handle_client_stream_connect(struct cras_rclient *client, goto cleanup_config; } + /* Metrics logs the stream configurations. */ + cras_server_metrics_stream_config(&stream_config); + /* Cleanup local object explicitly. */ cras_rstream_config_cleanup(&stream_config); return 0; @@ -243,74 +220,3 @@ int rclient_handle_client_stream_disconnect( return stream_list_rm(cras_iodev_list_get_stream_list(), msg->stream_id); } - -/* Creates a client structure and sends a message back informing the client that - * the connection has succeeded. */ -struct cras_rclient *rclient_generic_create(int fd, size_t id, - const struct cras_rclient_ops *ops, - int supported_directions) -{ - struct cras_rclient *client; - struct cras_client_connected msg; - int state_fd; - - client = (struct cras_rclient *)calloc(1, sizeof(struct cras_rclient)); - if (!client) - return NULL; - - client->fd = fd; - client->id = id; - client->ops = ops; - client->supported_directions = supported_directions; - - cras_fill_client_connected(&msg, client->id); - state_fd = cras_sys_state_shm_fd(); - client->ops->send_message_to_client(client, &msg.header, &state_fd, 1); - - return client; -} - -/* A generic entry point for handling a message from the client. Called from - * the main server context. */ -int rclient_handle_message_from_client(struct cras_rclient *client, - const struct cras_server_message *msg, - int *fds, unsigned int num_fds) -{ - int rc = 0; - assert(client && msg); - - rc = rclient_validate_message_fds(msg, fds, num_fds); - if (rc < 0) { - for (int i = 0; i < (int)num_fds; i++) - if (fds[i] >= 0) - close(fds[i]); - return rc; - } - int fd = num_fds > 0 ? fds[0] : -1; - - switch (msg->id) { - case CRAS_SERVER_CONNECT_STREAM: { - int client_shm_fd = num_fds > 1 ? fds[1] : -1; - if (MSG_LEN_VALID(msg, struct cras_connect_message)) { - rclient_handle_client_stream_connect( - client, - (const struct cras_connect_message *)msg, fd, - client_shm_fd); - } else { - return -EINVAL; - } - break; - } - case CRAS_SERVER_DISCONNECT_STREAM: - if (!MSG_LEN_VALID(msg, struct cras_disconnect_stream_message)) - return -EINVAL; - rclient_handle_client_stream_disconnect( - client, - (const struct cras_disconnect_stream_message *)msg); - break; - default: - break; - } - - return rc; -} diff --git a/cras/src/server/cras_rclient_util.h b/cras/src/server/cras_rclient_util.h index 089c2ecb..4768a476 100644 --- a/cras/src/server/cras_rclient_util.h +++ b/cras/src/server/cras_rclient_util.h @@ -86,40 +86,30 @@ int rclient_handle_client_stream_disconnect( struct cras_rclient *client, const struct cras_disconnect_stream_message *msg); -/* Generic rclient create function for different types of rclients. - * Creates a client structure and sends a message back informing the client - * that the connection has succeeded. - * - * Args: - * fd - The file descriptor used for communication with the client. - * id - Unique identifier for this client. - * ops - cras_rclient_ops pointer for the client. - * supported_directions - supported directions for the this rclient. - * Returns: - * A pointer to the newly created rclient on success, NULL on failure. +/* + * Converts an old version of connect message to the correct + * cras_connect_message. Returns zero on success, negative on failure. + * Note that this is special check only for libcras transition in + * clients, from CRAS_PROTO_VER = 3 to 5. + * TODO(yuhsuan): clean up the function once clients transition is done. */ -struct cras_rclient *rclient_generic_create(int fd, size_t id, - const struct cras_rclient_ops *ops, - int supported_directions); +static inline int +convert_connect_message_old(const struct cras_server_message *msg, + struct cras_connect_message *cmsg) +{ + struct cras_connect_message_old *old; -/* Generic handle_message_from_client function for different types of rlicnets. - * Supports only stream connect and stream disconnect messages. - * - * If the message from clients has incorrect length (truncated message), return - * an error up to CRAS server. - * If the message from clients has invalid content, should return the errors to - * clients by send_message_to_client and return 0 here. - * - * Args: - * client - The cras_rclient which gets the message. - * msg - The cras_server_message from client. - * fds - The array for incoming fds from client. - * num_fds - The number of fds from client. - * Returns: - * 0 on success, negative error on failure. - */ -int rclient_handle_message_from_client(struct cras_rclient *client, - const struct cras_server_message *msg, - int *fds, unsigned int num_fds); + if (!MSG_LEN_VALID(msg, struct cras_connect_message_old)) + return -EINVAL; + + old = (struct cras_connect_message_old *)msg; + if (old->proto_version != 3 || CRAS_PROTO_VER != 5) + return -EINVAL; + + memcpy(cmsg, old, sizeof(*old)); + cmsg->client_type = CRAS_CLIENT_TYPE_LEGACY; + cmsg->client_shm_size = 0; + return 0; +} #endif /* CRAS_RCLIENT_UTIL_H_ */ diff --git a/cras/src/server/cras_rstream.c b/cras/src/server/cras_rstream.c index 3c0a0ce3..55beed2b 100644 --- a/cras/src/server/cras_rstream.c +++ b/cras/src/server/cras_rstream.c @@ -17,20 +17,63 @@ #include "cras_server_metrics.h" #include "cras_shm.h" #include "cras_types.h" +#include "buffer_share.h" #include "cras_system_state.h" -static bool cras_rstream_config_is_client_shm_stream( - const struct cras_rstream_config *config) +void cras_rstream_config_init( + struct cras_rclient *client, cras_stream_id_t stream_id, + enum CRAS_STREAM_TYPE stream_type, enum CRAS_CLIENT_TYPE client_type, + enum CRAS_STREAM_DIRECTION direction, uint32_t dev_idx, uint32_t flags, + uint32_t effects, const struct cras_audio_format *format, + size_t buffer_frames, size_t cb_threshold, int *audio_fd, + int *client_shm_fd, size_t client_shm_size, + struct cras_rstream_config *stream_config) { - return config && config->client_shm_fd >= 0 && - config->client_shm_size > 0; + stream_config->stream_id = stream_id; + stream_config->stream_type = stream_type; + stream_config->client_type = client_type; + stream_config->direction = direction; + stream_config->dev_idx = dev_idx; + stream_config->flags = flags; + stream_config->effects = effects; + stream_config->format = format; + stream_config->buffer_frames = buffer_frames; + stream_config->cb_threshold = cb_threshold; + stream_config->audio_fd = *audio_fd; + *audio_fd = -1; + stream_config->client_shm_fd = *client_shm_fd; + *client_shm_fd = -1; + stream_config->client_shm_size = client_shm_size; + stream_config->client = client; } -/* Setup the shared memory area used for audio samples. config->client_shm_fd - * must be closed after calling this function. +void cras_rstream_config_init_with_message( + struct cras_rclient *client, const struct cras_connect_message *msg, + int *aud_fd, int *client_shm_fd, + const struct cras_audio_format *remote_fmt, + struct cras_rstream_config *stream_config) +{ + cras_rstream_config_init(client, msg->stream_id, msg->stream_type, + msg->client_type, msg->direction, msg->dev_idx, + msg->flags, msg->effects, remote_fmt, + msg->buffer_frames, msg->cb_threshold, aud_fd, + client_shm_fd, msg->client_shm_size, + stream_config); +} + +void cras_rstream_config_cleanup(struct cras_rstream_config *stream_config) +{ + if (stream_config->audio_fd >= 0) + close(stream_config->audio_fd); + if (stream_config->client_shm_fd >= 0) + close(stream_config->client_shm_fd); +} + +/* Setup the shared memory area used for audio samples. client_shm_fd must be + * closed after calling this function. */ -static inline int setup_shm_area(struct cras_rstream *stream, - struct cras_rstream_config *config) +static inline int setup_shm_area(struct cras_rstream *stream, int client_shm_fd, + size_t client_shm_size) { const struct cras_audio_format *fmt = &stream->format; char header_name[NAME_MAX]; @@ -38,8 +81,6 @@ static inline int setup_shm_area(struct cras_rstream *stream, struct cras_shm_info header_info, samples_info; uint32_t frame_bytes, used_size; int rc; - bool client_shm_stream = - cras_rstream_config_is_client_shm_stream(config); if (stream->shm) { /* already setup */ @@ -58,9 +99,8 @@ static inline int setup_shm_area(struct cras_rstream *stream, fmt->num_channels; used_size = stream->buffer_frames * frame_bytes; - if (client_shm_stream) { - rc = cras_shm_info_init_with_fd(config->client_shm_fd, - config->client_shm_size, + if (client_shm_fd >= 0 && client_shm_size > 0) { + rc = cras_shm_info_init_with_fd(client_shm_fd, client_shm_size, &samples_info); } else { snprintf(samples_name, sizeof(samples_name), @@ -89,11 +129,6 @@ static inline int setup_shm_area(struct cras_rstream *stream, cras_shm_set_frame_bytes(stream->shm, frame_bytes); cras_shm_set_used_size(stream->shm, used_size); - if (client_shm_stream) { - for (int i = 0; i < 2; i++) - cras_shm_set_buffer_offset(stream->shm, i, - config->buffer_offsets[i]); - } stream->audio_area = cras_audio_area_create(stream->format.num_channels); @@ -104,16 +139,23 @@ static inline int setup_shm_area(struct cras_rstream *stream, static inline int buffer_meets_size_limit(size_t buffer_size, size_t rate) { - return (buffer_size < (CRAS_MAX_BUFFER_TIME_IN_S * rate)) && - (buffer_size > (CRAS_MIN_BUFFER_TIME_IN_US * rate) / 1000000); + return buffer_size > (CRAS_MIN_BUFFER_TIME_IN_US * rate) / 1000000; } /* Verifies that the given stream parameters are valid. */ -static int verify_rstream_parameters(const struct cras_rstream_config *config, - struct cras_rstream *const *stream_out) +static int verify_rstream_parameters(enum CRAS_STREAM_DIRECTION direction, + const struct cras_audio_format *format, + enum CRAS_STREAM_TYPE stream_type, + size_t buffer_frames, size_t cb_threshold, + int client_shm_fd, size_t client_shm_size, + struct cras_rclient *client, + struct cras_rstream **stream_out) { - const struct cras_audio_format *format = config->format; - + if (!buffer_meets_size_limit(buffer_frames, format->frame_rate)) { + syslog(LOG_ERR, "rstream: invalid buffer_frames %zu\n", + buffer_frames); + return -EINVAL; + } if (stream_out == NULL) { syslog(LOG_ERR, "rstream: stream_out can't be NULL\n"); return -EINVAL; @@ -122,33 +164,6 @@ static int verify_rstream_parameters(const struct cras_rstream_config *config, syslog(LOG_ERR, "rstream: format can't be NULL\n"); return -EINVAL; } - if (format->frame_rate < 4000 || format->frame_rate > 192000) { - syslog(LOG_ERR, "rstream: invalid frame_rate %zu\n", - format->frame_rate); - return -EINVAL; - } - /* - * Valid buffer settings: - * Frames in 1ms <= cb_threshold <= buffer_frames <= Frames in 10s. - */ - if (!buffer_meets_size_limit(config->buffer_frames, - format->frame_rate)) { - syslog(LOG_ERR, "rstream: invalid buffer_frames %zu\n", - config->buffer_frames); - return -EINVAL; - } - if (!buffer_meets_size_limit(config->cb_threshold, - format->frame_rate) || - config->cb_threshold > config->buffer_frames) { - syslog(LOG_ERR, "rstream: invalid cb_threshold %zu\n", - config->cb_threshold); - return -EINVAL; - } - if (format->num_channels < 0 || format->num_channels > CRAS_CH_MAX) { - syslog(LOG_ERR, "rstream: invalid num_channels %zu\n", - format->num_channels); - return -EINVAL; - } if ((format->format != SND_PCM_FORMAT_S16_LE) && (format->format != SND_PCM_FORMAT_S32_LE) && (format->format != SND_PCM_FORMAT_U8) && @@ -157,34 +172,24 @@ static int verify_rstream_parameters(const struct cras_rstream_config *config, format->format); return -EINVAL; } - if (config->direction != CRAS_STREAM_OUTPUT && - config->direction != CRAS_STREAM_INPUT) { + if (direction != CRAS_STREAM_OUTPUT && direction != CRAS_STREAM_INPUT) { syslog(LOG_ERR, "rstream: Invalid direction.\n"); return -EINVAL; } - if (config->stream_type < CRAS_STREAM_TYPE_DEFAULT || - config->stream_type >= CRAS_STREAM_NUM_TYPES) { + if (stream_type < CRAS_STREAM_TYPE_DEFAULT || + stream_type >= CRAS_STREAM_NUM_TYPES) { syslog(LOG_ERR, "rstream: Invalid stream type.\n"); return -EINVAL; } - if (config->client_type < CRAS_CLIENT_TYPE_UNKNOWN || - config->client_type >= CRAS_NUM_CLIENT_TYPE) { - syslog(LOG_ERR, "rstream: Invalid client type.\n"); + if (!buffer_meets_size_limit(cb_threshold, format->frame_rate)) { + syslog(LOG_ERR, "rstream: cb_threshold too low\n"); return -EINVAL; } - if ((config->client_shm_size > 0 && config->client_shm_fd < 0) || - (config->client_shm_size == 0 && config->client_shm_fd >= 0)) { + if ((client_shm_size > 0 && client_shm_fd < 0) || + (client_shm_size == 0 && client_shm_fd >= 0)) { syslog(LOG_ERR, "rstream: invalid client-provided shm info\n"); return -EINVAL; } - if (cras_rstream_config_is_client_shm_stream(config) && - (config->buffer_offsets[0] > config->client_shm_size || - config->buffer_offsets[1] > config->client_shm_size)) { - syslog(LOG_ERR, - "rstream: initial buffer offsets are outside shm area\n"); - return -EINVAL; - } - return 0; } @@ -243,6 +248,7 @@ static int read_and_handle_client_message(struct cras_rstream *stream) rc = get_audio_request_reply(stream, &msg); if (rc <= 0) { + syslog(LOG_ERR, "Got error from client: rc: %d", rc); clear_pending_reply(stream); return rc; } @@ -274,7 +280,11 @@ int cras_rstream_create(struct cras_rstream_config *config, struct cras_rstream *stream; int rc; - rc = verify_rstream_parameters(config, stream_out); + rc = verify_rstream_parameters( + config->direction, config->format, config->stream_type, + config->buffer_frames, config->cb_threshold, + config->client_shm_fd, config->client_shm_size, config->client, + stream_out); if (rc < 0) return rc; @@ -292,14 +302,14 @@ int cras_rstream_create(struct cras_rstream_config *config, stream->cb_threshold = config->cb_threshold; stream->client = config->client; stream->shm = NULL; - stream->main_dev.dev_id = NO_DEVICE; - stream->main_dev.dev_ptr = NULL; + stream->master_dev.dev_id = NO_DEVICE; + stream->master_dev.dev_ptr = NULL; stream->num_missed_cb = 0; stream->is_pinned = (config->dev_idx != NO_DEVICE); stream->pinned_dev_idx = config->dev_idx; - ewma_power_init(&stream->ewma, stream->format.frame_rate); - rc = setup_shm_area(stream, config); + rc = setup_shm_area(stream, config->client_shm_fd, + config->client_shm_size); if (rc < 0) { syslog(LOG_ERR, "failed to setup shm %d\n", rc); free(stream); @@ -318,20 +328,17 @@ int cras_rstream_create(struct cras_rstream_config *config, config->stream_id, config->buffer_frames, config->cb_threshold); *stream_out = stream; - cras_system_state_stream_added(stream->direction, stream->client_type); + cras_system_state_stream_added(stream->direction); clock_gettime(CLOCK_MONOTONIC_RAW, &stream->start_ts); - cras_server_metrics_stream_create(config); - return 0; } void cras_rstream_destroy(struct cras_rstream *stream) { - cras_server_metrics_stream_destroy(stream); - cras_system_state_stream_removed(stream->direction, - stream->client_type); + cras_server_metrics_missed_cb_frequency(stream); + cras_system_state_stream_removed(stream->direction); close(stream->fd); cras_audio_shm_destroy(stream->shm); cras_audio_area_destroy(stream->audio_area); @@ -353,7 +360,10 @@ cras_rstream_post_processing_format(const struct cras_rstream *stream, { struct cras_apm *apm; - apm = cras_apm_list_get_active_apm((void *)stream, dev_ptr); + if (NULL == stream->apm_list) + return NULL; + + apm = cras_apm_list_get(stream->apm_list, dev_ptr); if (NULL == apm) return NULL; return cras_apm_list_get_format(apm); @@ -431,12 +441,12 @@ void cras_rstream_dev_attach(struct cras_rstream *rstream, unsigned int dev_id, if (buffer_share_add_id(rstream->buf_state, dev_id, dev_ptr) == 0) rstream->num_attached_devs++; - /* TODO(hychao): Handle main device assignment for complicated + /* TODO(hychao): Handle master device assignment for complicated * routing case. */ - if (rstream->main_dev.dev_id == NO_DEVICE) { - rstream->main_dev.dev_id = dev_id; - rstream->main_dev.dev_ptr = dev_ptr; + if (rstream->master_dev.dev_id == NO_DEVICE) { + rstream->master_dev.dev_id = dev_id; + rstream->master_dev.dev_ptr = dev_ptr; } } @@ -445,18 +455,18 @@ void cras_rstream_dev_detach(struct cras_rstream *rstream, unsigned int dev_id) if (buffer_share_rm_id(rstream->buf_state, dev_id) == 0) rstream->num_attached_devs--; - if (rstream->main_dev.dev_id == dev_id) { + if (rstream->master_dev.dev_id == dev_id) { int i; struct id_offset *o; - /* Choose the first device id as a main device. */ - rstream->main_dev.dev_id = NO_DEVICE; - rstream->main_dev.dev_ptr = NULL; + /* Choose the first device id as master. */ + rstream->master_dev.dev_id = NO_DEVICE; + rstream->master_dev.dev_ptr = NULL; for (i = 0; i < rstream->buf_state->id_sz; i++) { o = &rstream->buf_state->wr_idx[i]; if (o->used) { - rstream->main_dev.dev_id = o->id; - rstream->main_dev.dev_ptr = o->data; + rstream->master_dev.dev_id = o->id; + rstream->master_dev.dev_ptr = o->data; break; } } @@ -479,16 +489,9 @@ void cras_rstream_update_input_write_pointer(struct cras_rstream *rstream) void cras_rstream_update_output_read_pointer(struct cras_rstream *rstream) { - size_t nfr = 0; - uint8_t *src; unsigned int nwritten = buffer_share_get_new_write_point(rstream->buf_state); - /* Retrieve the read pointer |src| start from which to calculate - * the EWMA power. */ - src = cras_shm_get_readable_frames(rstream->shm, 0, &nfr); - ewma_power_calculate(&rstream->ewma, (int16_t *)src, - rstream->format.num_channels, nwritten); cras_shm_buffer_read(rstream->shm, nwritten); } @@ -553,8 +556,5 @@ int cras_rstream_flush_old_audio_messages(struct cras_rstream *stream) } } while (err > 0); - if (err < 0) - syslog(LOG_ERR, "Error reading msg from client: rc: %d", err); - return 0; } diff --git a/cras/src/server/cras_rstream.h b/cras/src/server/cras_rstream.h index d57c13be..3329fe0c 100644 --- a/cras/src/server/cras_rstream.h +++ b/cras/src/server/cras_rstream.h @@ -9,23 +9,20 @@ #ifndef CRAS_RSTREAM_H_ #define CRAS_RSTREAM_H_ -#include "buffer_share.h" #include "cras_apm_list.h" #include "cras_shm.h" #include "cras_types.h" -#include "cras_rstream_config.h" -#include "ewma_power.h" struct cras_connect_message; struct cras_rclient; struct dev_mix; -/* Holds informations about the main active device. +/* Holds informations about the master active device. * Members: - * dev_id - id of the main device. - * dev_ptr - pointer to the main device. + * dev_id - id of the master device. + * dev_ptr - pointer to the master device. */ -struct main_dev_info { +struct master_dev_info { int dev_id; void *dev_ptr; }; @@ -42,7 +39,7 @@ struct main_dev_info { * fd - Socket for requesting and sending audio buffer events. * buffer_frames - Buffer size in frames. * cb_threshold - Callback client when this much is left. - * main_dev_info - The info of the main device this stream attaches to. + * master_dev_info - The info of the master device this stream attaches to. * is_draining - The stream is draining and waiting to be removed. * client - The client who uses this stream. * shm - shared memory @@ -56,7 +53,6 @@ struct main_dev_info { * first_missed_cb_ts - The time when the first missed callback happens. * buf_state - State of the buffer from all devices for this stream. * apm_list - List of audio processing module instances. - * ewma - The ewma instance to calculate stream volume. * num_attached_devs - Number of iodevs this stream has attached to. * num_missed_cb - Number of callback schedules have been missed. * queued_frames - Cached value of the number of queued frames in shm. @@ -74,7 +70,7 @@ struct cras_rstream { size_t buffer_frames; size_t cb_threshold; int is_draining; - struct main_dev_info main_dev; + struct master_dev_info master_dev; struct cras_rclient *client; struct cras_audio_shm *shm; struct cras_audio_area *audio_area; @@ -87,7 +83,6 @@ struct cras_rstream { struct timespec first_missed_cb_ts; struct buffer_share *buf_state; struct cras_apm_list *apm_list; - struct ewma_power ewma; int num_attached_devs; int num_missed_cb; int queued_frames; @@ -97,6 +92,85 @@ struct cras_rstream { struct cras_rstream *prev, *next; }; +/* Config for creating an rstream. + * stream_type - CRAS_STREAM_TYPE. + * client_type - CRAS_CLIENT_TYPE. + * direction - CRAS_STREAM_OUTPUT or CRAS_STREAM_INPUT. + * dev_idx - Pin to this device if != NO_DEVICE. + * flags - Any special handling for this stream. + * effects - Bit map of effects to be enabled on this stream. + * format - The audio format the stream wishes to use. + * buffer_frames - Total number of audio frames to buffer. + * cb_threshold - # of frames when to request more from the client. + * audio_fd - The fd to read/write audio signals to. May be -1 for server + * stream. Some functions may mutably borrow the config and move + * the fd ownership. + * client_shm_fd - The shm fd to use to back the samples area. May be -1. + * Some functions may dup this fd while borrowing the config. + * client_shm_size - The size of shm area backed by client_shm_fd. + * client - The client that owns this stream. + */ +struct cras_rstream_config { + cras_stream_id_t stream_id; + enum CRAS_STREAM_TYPE stream_type; + enum CRAS_CLIENT_TYPE client_type; + enum CRAS_STREAM_DIRECTION direction; + uint32_t dev_idx; + uint32_t flags; + uint32_t effects; + const struct cras_audio_format *format; + size_t buffer_frames; + size_t cb_threshold; + int audio_fd; + int client_shm_fd; + size_t client_shm_size; + struct cras_rclient *client; +}; + +/* Fills cras_rstream_config with given parameters. + * + * Args: + * audio_fd - The audio fd pointer from client. Its ownership will be moved to + * stream_config. + * client_shm_fd - The shared memory fd pointer for samples from client. Its + * ownership will be moved to stream_config. + * Other args - See comments in struct cras_rstream_config. + */ +void cras_rstream_config_init( + struct cras_rclient *client, cras_stream_id_t stream_id, + enum CRAS_STREAM_TYPE stream_type, enum CRAS_CLIENT_TYPE client_type, + enum CRAS_STREAM_DIRECTION direction, uint32_t dev_idx, uint32_t flags, + uint32_t effects, const struct cras_audio_format *format, + size_t buffer_frames, size_t cb_threshold, int *audio_fd, + int *client_shm_fd, size_t client_shm_size, + struct cras_rstream_config *stream_config); + +/* Fills cras_rstream_config with given parameters and a cras_connect_message. + * + * Args: + * client - The rclient which handles the connect message. + * msg - The cras_connect_message from client. + * aud_fd - The audio fd pointer from client. Its ownership will be moved to + * stream_config. + * client_shm_fd - The shared memory fd pointer for samples from client. Its + * ownership will be moved to stream_config. + * remote_format - The remote_format for the config. + * stream_config - The cras_rstream_config to be filled. + */ +void cras_rstream_config_init_with_message( + struct cras_rclient *client, const struct cras_connect_message *msg, + int *aud_fd, int *client_shm_fd, + const struct cras_audio_format *remote_format, + struct cras_rstream_config *stream_config); + +/* Cleans up given cras_rstream_config. All fds inside the config will be + * closed. + * + * Args: + * stream_config - The config to be cleaned up. + */ +void cras_rstream_config_cleanup(struct cras_rstream_config *stream_config); + /* Creates an rstream. * Args: * config - Params for configuration of the new rstream. It's a mutable @@ -260,12 +334,6 @@ void cras_rstream_dev_attach(struct cras_rstream *rstream, unsigned int dev_id, void *dev_ptr); void cras_rstream_dev_detach(struct cras_rstream *rstream, unsigned int dev_id); -static inline void *cras_rstream_dev_ptr(struct cras_rstream *rstream, - unsigned int dev_id) -{ - return buffer_share_get_data(rstream->buf_state, dev_id); -} - /* A device using this stream has read or written samples. */ void cras_rstream_dev_offset_update(struct cras_rstream *rstream, unsigned int frames, unsigned int dev_id); diff --git a/cras/src/server/cras_rstream_config.c b/cras/src/server/cras_rstream_config.c deleted file mode 100644 index c5cd9c57..00000000 --- a/cras/src/server/cras_rstream_config.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <fcntl.h> -#include <stdint.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <syslog.h> - -#include "cras_audio_area.h" -#include "cras_config.h" -#include "cras_messages.h" -#include "cras_rclient.h" -#include "cras_rstream.h" -#include "cras_rstream_config.h" -#include "cras_server_metrics.h" -#include "cras_shm.h" -#include "cras_types.h" -#include "cras_system_state.h" - -void cras_rstream_config_init( - struct cras_rclient *client, cras_stream_id_t stream_id, - enum CRAS_STREAM_TYPE stream_type, enum CRAS_CLIENT_TYPE client_type, - enum CRAS_STREAM_DIRECTION direction, uint32_t dev_idx, uint32_t flags, - uint32_t effects, const struct cras_audio_format *format, - size_t buffer_frames, size_t cb_threshold, int *audio_fd, - int *client_shm_fd, size_t client_shm_size, - const uint64_t buffer_offsets[2], - struct cras_rstream_config *stream_config) -{ - stream_config->stream_id = stream_id; - stream_config->stream_type = stream_type; - stream_config->client_type = client_type; - stream_config->direction = direction; - stream_config->dev_idx = dev_idx; - stream_config->flags = flags; - stream_config->effects = effects; - stream_config->format = format; - stream_config->buffer_frames = buffer_frames; - stream_config->cb_threshold = cb_threshold; - stream_config->audio_fd = *audio_fd; - *audio_fd = -1; - stream_config->client_shm_fd = *client_shm_fd; - *client_shm_fd = -1; - stream_config->client_shm_size = client_shm_size; - stream_config->buffer_offsets[0] = buffer_offsets[0]; - stream_config->buffer_offsets[1] = buffer_offsets[1]; - stream_config->client = client; -} - -struct cras_rstream_config cras_rstream_config_init_with_message( - struct cras_rclient *client, const struct cras_connect_message *msg, - int *aud_fd, int *client_shm_fd, - const struct cras_audio_format *remote_fmt) -{ - struct cras_rstream_config stream_config; - - const uint64_t buffer_offsets[2] = { msg->buffer_offsets[0], - msg->buffer_offsets[1] }; - cras_rstream_config_init(client, msg->stream_id, msg->stream_type, - msg->client_type, msg->direction, msg->dev_idx, - msg->flags, msg->effects, remote_fmt, - msg->buffer_frames, msg->cb_threshold, aud_fd, - client_shm_fd, msg->client_shm_size, - buffer_offsets, &stream_config); - return stream_config; -} - -void cras_rstream_config_cleanup(struct cras_rstream_config *stream_config) -{ - if (stream_config->audio_fd >= 0) - close(stream_config->audio_fd); - if (stream_config->client_shm_fd >= 0) - close(stream_config->client_shm_fd); -} diff --git a/cras/src/server/cras_rstream_config.h b/cras/src/server/cras_rstream_config.h deleted file mode 100644 index 4d3713ce..00000000 --- a/cras/src/server/cras_rstream_config.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Remote Stream Configuration - */ -#ifndef CRAS_RSTREAM_CONFIG_H_ -#define CRAS_RSTREAM_CONFIG_H_ - -#include "buffer_share.h" -#include "cras_shm.h" -#include "cras_types.h" - -struct cras_connect_message; -struct dev_mix; - -/* Config for creating an rstream. - * stream_type - CRAS_STREAM_TYPE. - * client_type - CRAS_CLIENT_TYPE. - * direction - CRAS_STREAM_OUTPUT or CRAS_STREAM_INPUT. - * dev_idx - Pin to this device if != NO_DEVICE. - * flags - Any special handling for this stream. - * effects - Bit map of effects to be enabled on this stream. - * format - The audio format the stream wishes to use. - * buffer_frames - Total number of audio frames to buffer. - * cb_threshold - # of frames when to request more from the client. - * audio_fd - The fd to read/write audio signals to. May be -1 for server - * stream. Some functions may mutably borrow the config and move - * the fd ownership. - * client_shm_fd - The shm fd to use to back the samples area. May be -1. - * Some functions may dup this fd while borrowing the config. - * client_shm_size - The size of shm area backed by client_shm_fd. - * buffer_offsets - Initial values for buffer_offset for a client shm stream. - * client - The client that owns this stream. - */ -struct cras_rstream_config { - cras_stream_id_t stream_id; - enum CRAS_STREAM_TYPE stream_type; - enum CRAS_CLIENT_TYPE client_type; - enum CRAS_STREAM_DIRECTION direction; - uint32_t dev_idx; - uint32_t flags; - uint32_t effects; - const struct cras_audio_format *format; - size_t buffer_frames; - size_t cb_threshold; - int audio_fd; - int client_shm_fd; - size_t client_shm_size; - uint32_t buffer_offsets[2]; - struct cras_rclient *client; -}; - -/* Fills cras_rstream_config with given parameters. - * - * Args: - * audio_fd - The audio fd pointer from client. Its ownership will be moved to - * stream_config. - * client_shm_fd - The shared memory fd pointer for samples from client. Its - * ownership will be moved to stream_config. - * Other args - See comments in struct cras_rstream_config. - */ -void cras_rstream_config_init( - struct cras_rclient *client, cras_stream_id_t stream_id, - enum CRAS_STREAM_TYPE stream_type, enum CRAS_CLIENT_TYPE client_type, - enum CRAS_STREAM_DIRECTION direction, uint32_t dev_idx, uint32_t flags, - uint32_t effects, const struct cras_audio_format *format, - size_t buffer_frames, size_t cb_threshold, int *audio_fd, - int *client_shm_fd, size_t client_shm_size, - const uint64_t buffer_offsets[2], - struct cras_rstream_config *stream_config); - -/* Fills cras_rstream_config with given parameters and a cras_connect_message. - * - * Args: - * client - The rclient which handles the connect message. - * msg - The cras_connect_message from client. - * aud_fd - The audio fd pointer from client. Its ownership will be moved to - * stream_config. - * client_shm_fd - The shared memory fd pointer for samples from client. Its - * ownership will be moved to stream_config. - * remote_format - The remote_format for the config. - * - * Returns a cras_rstream_config struct filled in with params from the message. - */ -struct cras_rstream_config cras_rstream_config_init_with_message( - struct cras_rclient *client, const struct cras_connect_message *msg, - int *aud_fd, int *client_shm_fd, - const struct cras_audio_format *remote_format); - -/* Cleans up given cras_rstream_config. All fds inside the config will be - * closed. - * - * Args: - * stream_config - The config to be cleaned up. - */ -void cras_rstream_config_cleanup(struct cras_rstream_config *stream_config); - -#endif /* CRAS_RSTREAM_CONFIG_H_ */ diff --git a/cras/src/server/cras_server.c b/cras/src/server/cras_server.c index 5f2ce632..97c83dfd 100644 --- a/cras/src/server/cras_server.c +++ b/cras/src/server/cras_server.c @@ -79,18 +79,16 @@ struct attached_client { * to watch file descriptors. The client can then read or write the fd. * Members: * fd - The file descriptor passed to select. - * callback - The funciton to call when fd is ready. + * callack - The funciton to call when fd is ready. * callback_data - Pointer passed to the callback. * pollfd - Pointer to struct pollfd for this callback. - * events - The events to poll for. */ struct client_callback { int select_fd; - void (*callback)(void *data, int revents); + void (*callback)(void *); void *callback_data; struct pollfd *pollfd; int deleted; - int events; struct client_callback *prev, *next; }; @@ -279,8 +277,8 @@ error: /* Add a file descriptor to be passed to select in the main loop. This is * registered with system state so that it is called when any client asks to * have a callback triggered based on an fd being readable. */ -static int add_select_fd(int fd, void (*cb)(void *data, int events), - void *callback_data, int events, void *server_data) +static int add_select_fd(int fd, void (*cb)(void *data), void *callback_data, + void *server_data) { struct client_callback *new_cb; struct client_callback *client_cb; @@ -303,7 +301,6 @@ static int add_select_fd(int fd, void (*cb)(void *data, int events), new_cb->callback = cb; new_cb->callback_data = callback_data; new_cb->deleted = 0; - new_cb->events = events; new_cb->pollfd = NULL; DL_APPEND(serv->client_callbacks, new_cb); @@ -477,7 +474,7 @@ int cras_server_init() * Returns 0 on success and leaves the created fd and the address information * in server_socket. * When error occurs, the created fd will be closed and the file path will be - * unlinked and returns negative error code. + * unlinked. */ static int create_and_listen_server_socket(enum CRAS_CONNECTION_TYPE conn_type, struct server_socket *server_socket) @@ -511,7 +508,7 @@ static int create_and_listen_server_socket(enum CRAS_CONNECTION_TYPE conn_type, sizeof(struct sockaddr_un)); if (rc < 0) { syslog(LOG_ERR, "Bind to server socket failed."); - rc = -errno; + rc = errno; goto error; } @@ -522,7 +519,7 @@ static int create_and_listen_server_socket(enum CRAS_CONNECTION_TYPE conn_type, if (listen(socket_fd, 5) != 0) { syslog(LOG_ERR, "Listen on server socket failed."); - rc = -errno; + rc = errno; goto error; } @@ -644,7 +641,7 @@ int cras_server_run(unsigned int profile_disable_mask) if (client_cb->deleted) continue; pollfds[num_pollfds].fd = client_cb->select_fd; - pollfds[num_pollfds].events = client_cb->events; + pollfds[num_pollfds].events = POLLIN; client_cb->pollfd = &pollfds[num_pollfds]; num_pollfds++; } @@ -690,9 +687,8 @@ int cras_server_run(unsigned int profile_disable_mask) /* Check any client-registered fd/callback pairs. */ DL_FOREACH (server_instance.client_callbacks, client_cb) if (!client_cb->deleted && client_cb->pollfd && - (client_cb->pollfd->revents & client_cb->events)) - client_cb->callback(client_cb->callback_data, - client_cb->pollfd->revents); + (client_cb->pollfd->revents & POLLIN)) + client_cb->callback(client_cb->callback_data); cleanup_select_fds(&server_instance); @@ -717,4 +713,4 @@ void cras_server_send_to_all_clients(const struct cras_client_message *msg) DL_FOREACH (server_instance.clients_head, client) cras_rclient_send_message(client->client, msg, NULL, 0); -} +}
\ No newline at end of file diff --git a/cras/src/server/cras_server_metrics.c b/cras/src/server/cras_server_metrics.c index 7e487107..5f51e83e 100644 --- a/cras/src/server/cras_server_metrics.c +++ b/cras/src/server/cras_server_metrics.c @@ -16,18 +16,13 @@ #include "cras_metrics.h" #include "cras_main_message.h" #include "cras_rstream.h" -#include "cras_server_metrics.h" #include "cras_system_state.h" -#define METRICS_NAME_BUFFER_SIZE 100 +#define METRICS_NAME_BUFFER_SIZE 50 const char kBusyloop[] = "Cras.Busyloop"; -const char kBusyloopLength[] = "Cras.BusyloopLength"; const char kDeviceTypeInput[] = "Cras.DeviceTypeInput"; const char kDeviceTypeOutput[] = "Cras.DeviceTypeOutput"; -const char kDeviceGain[] = "Cras.DeviceGain"; -const char kDeviceVolume[] = "Cras.DeviceVolume"; -const char kFetchDelayMilliSeconds[] = "Cras.FetchDelayMilliSeconds"; const char kHighestDeviceDelayInput[] = "Cras.HighestDeviceDelayInput"; const char kHighestDeviceDelayOutput[] = "Cras.HighestDeviceDelayOutput"; const char kHighestInputHardwareLevel[] = "Cras.HighestInputHardwareLevel"; @@ -49,23 +44,16 @@ const char kMissedCallbackSecondTimeInput[] = const char kMissedCallbackSecondTimeOutput[] = "Cras.MissedCallbackSecondTimeOutput"; const char kNoCodecsFoundMetric[] = "Cras.NoCodecsFoundAtBoot"; +const char kStreamTimeoutMilliSeconds[] = "Cras.StreamTimeoutMilliSeconds"; const char kStreamCallbackThreshold[] = "Cras.StreamCallbackThreshold"; const char kStreamClientTypeInput[] = "Cras.StreamClientTypeInput"; const char kStreamClientTypeOutput[] = "Cras.StreamClientTypeOutput"; const char kStreamFlags[] = "Cras.StreamFlags"; -const char kStreamEffects[] = "Cras.StreamEffects"; -const char kStreamRuntime[] = "Cras.StreamRuntime"; const char kStreamSamplingFormat[] = "Cras.StreamSamplingFormat"; const char kStreamSamplingRate[] = "Cras.StreamSamplingRate"; const char kUnderrunsPerDevice[] = "Cras.UnderrunsPerDevice"; -const char kHfpScoConnectionError[] = "Cras.HfpScoConnectionError"; -const char kHfpBatteryIndicatorSupported[] = - "Cras.HfpBatteryIndicatorSupported"; -const char kHfpBatteryReport[] = "Cras.HfpBatteryReport"; const char kHfpWidebandSpeechSupported[] = "Cras.HfpWidebandSpeechSupported"; const char kHfpWidebandSpeechPacketLoss[] = "Cras.HfpWidebandSpeechPacketLoss"; -const char kHfpWidebandSpeechSelectedCodec[] = - "Cras.kHfpWidebandSpeechSelectedCodec"; /* * Records missed callback frequency only when the runtime of stream is larger @@ -87,17 +75,10 @@ static const char *get_timespec_period_str(struct timespec ts) /* Type of metrics to log. */ enum CRAS_SERVER_METRICS_TYPE { - BT_BATTERY_INDICATOR_SUPPORTED, - BT_BATTERY_REPORT, - BT_SCO_CONNECTION_ERROR, BT_WIDEBAND_PACKET_LOSS, BT_WIDEBAND_SUPPORTED, - BT_WIDEBAND_SELECTED_CODEC, BUSYLOOP, - BUSYLOOP_LENGTH, - DEVICE_GAIN, DEVICE_RUNTIME, - DEVICE_VOLUME, HIGHEST_DEVICE_DELAY_INPUT, HIGHEST_DEVICE_DELAY_OUTPUT, HIGHEST_INPUT_HW_LEVEL, @@ -112,8 +93,7 @@ enum CRAS_SERVER_METRICS_TYPE { MISSED_CB_SECOND_TIME_INPUT, MISSED_CB_SECOND_TIME_OUTPUT, NUM_UNDERRUNS, - STREAM_CONFIG, - STREAM_RUNTIME + STREAM_CONFIG }; enum CRAS_METRICS_DEVICE_TYPE { @@ -138,21 +118,17 @@ enum CRAS_METRICS_DEVICE_TYPE { CRAS_METRICS_DEVICE_HFP, CRAS_METRICS_DEVICE_HSP, CRAS_METRICS_DEVICE_BLUETOOTH, - CRAS_METRICS_DEVICE_BLUETOOTH_NB_MIC, CRAS_METRICS_DEVICE_NO_DEVICE, CRAS_METRICS_DEVICE_NORMAL_FALLBACK, CRAS_METRICS_DEVICE_ABNORMAL_FALLBACK, CRAS_METRICS_DEVICE_SILENT_HOTWORD, CRAS_METRICS_DEVICE_UNKNOWN, - CRAS_METRICS_DEVICE_BLUETOOTH_WB_MIC, - CRAS_METRICS_DEVICE_ALSA_LOOPBACK, }; struct cras_server_metrics_stream_config { enum CRAS_STREAM_DIRECTION direction; unsigned cb_threshold; unsigned flags; - unsigned effects; int format; unsigned rate; enum CRAS_CLIENT_TYPE client_type; @@ -162,14 +138,6 @@ struct cras_server_metrics_device_data { enum CRAS_METRICS_DEVICE_TYPE type; enum CRAS_STREAM_DIRECTION direction; struct timespec runtime; - unsigned value; -}; - -struct cras_server_metrics_stream_data { - enum CRAS_CLIENT_TYPE client_type; - enum CRAS_STREAM_TYPE stream_type; - enum CRAS_STREAM_DIRECTION direction; - struct timespec runtime; }; struct cras_server_metrics_timespec_data { @@ -181,7 +149,6 @@ union cras_server_metrics_data { unsigned value; struct cras_server_metrics_stream_config stream_config; struct cras_server_metrics_device_data device_data; - struct cras_server_metrics_stream_data stream_data; struct cras_server_metrics_timespec_data timespec_data; }; @@ -264,15 +231,9 @@ metrics_device_type_str(enum CRAS_METRICS_DEVICE_TYPE device_type) return "HSP"; case CRAS_METRICS_DEVICE_BLUETOOTH: return "Bluetooth"; - case CRAS_METRICS_DEVICE_BLUETOOTH_NB_MIC: - return "BluetoothNarrowBandMic"; - case CRAS_METRICS_DEVICE_BLUETOOTH_WB_MIC: - return "BluetoothWideBandMic"; case CRAS_METRICS_DEVICE_NO_DEVICE: return "NoDevice"; - case CRAS_METRICS_DEVICE_ALSA_LOOPBACK: - return "AlsaLoopback"; - /* Other fallback devices. */ + /* Other dummy devices. */ case CRAS_METRICS_DEVICE_NORMAL_FALLBACK: return "NormalFallback"; case CRAS_METRICS_DEVICE_ABNORMAL_FALLBACK: @@ -286,58 +247,6 @@ metrics_device_type_str(enum CRAS_METRICS_DEVICE_TYPE device_type) } } -static inline const char * -metrics_client_type_str(enum CRAS_CLIENT_TYPE client_type) -{ - switch (client_type) { - case CRAS_CLIENT_TYPE_UNKNOWN: - return "Unknown"; - case CRAS_CLIENT_TYPE_LEGACY: - return "Legacy"; - case CRAS_CLIENT_TYPE_TEST: - return "Test"; - case CRAS_CLIENT_TYPE_PCM: - return "PCM"; - case CRAS_CLIENT_TYPE_CHROME: - return "Chrome"; - case CRAS_CLIENT_TYPE_ARC: - return "ARC"; - case CRAS_CLIENT_TYPE_CROSVM: - return "CrOSVM"; - case CRAS_CLIENT_TYPE_SERVER_STREAM: - return "ServerStream"; - case CRAS_CLIENT_TYPE_LACROS: - return "LaCrOS"; - case CRAS_CLIENT_TYPE_PLUGIN: - return "PluginVM"; - case CRAS_CLIENT_TYPE_ARCVM: - return "ARCVM"; - default: - return "InvalidType"; - } -} - -static inline const char * -metrics_stream_type_str(enum CRAS_STREAM_TYPE stream_type) -{ - switch (stream_type) { - case CRAS_STREAM_TYPE_DEFAULT: - return "Default"; - case CRAS_STREAM_TYPE_MULTIMEDIA: - return "Multimedia"; - case CRAS_STREAM_TYPE_VOICE_COMMUNICATION: - return "VoiceCommunication"; - case CRAS_STREAM_TYPE_SPEECH_RECOGNITION: - return "SpeechRecognition"; - case CRAS_STREAM_TYPE_PRO_AUDIO: - return "ProAudio"; - case CRAS_STREAM_TYPE_ACCESSIBILITY: - return "Accessibility"; - default: - return "InvalidType"; - } -} - static enum CRAS_METRICS_DEVICE_TYPE get_metrics_device_type(struct cras_iodev *iodev) { @@ -392,158 +301,25 @@ get_metrics_device_type(struct cras_iodev *iodev) return CRAS_METRICS_DEVICE_POST_DSP_LOOPBACK; case CRAS_NODE_TYPE_USB: return CRAS_METRICS_DEVICE_USB; - case CRAS_NODE_TYPE_BLUETOOTH: { + case CRAS_NODE_TYPE_BLUETOOTH: #ifdef CRAS_DBUS - enum cras_bt_device_profile profile = - cras_bt_io_profile_to_log(iodev); - switch (profile) { - case CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE: + if (cras_bt_io_on_profile(iodev, + CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE)) return CRAS_METRICS_DEVICE_A2DP; - case CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY: - /* HFP narrow band has its own node type so we know - * this is wideband mic for sure. */ - return (iodev->direction == CRAS_STREAM_INPUT) ? - CRAS_METRICS_DEVICE_BLUETOOTH_WB_MIC : - CRAS_METRICS_DEVICE_HFP; - case CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY: + if (cras_bt_io_on_profile( + iodev, CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY)) + return CRAS_METRICS_DEVICE_HFP; + if (cras_bt_io_on_profile( + iodev, CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY)) return CRAS_METRICS_DEVICE_HSP; - default: - break; - } #endif return CRAS_METRICS_DEVICE_BLUETOOTH; - } - case CRAS_NODE_TYPE_BLUETOOTH_NB_MIC: - return CRAS_METRICS_DEVICE_BLUETOOTH_NB_MIC; - case CRAS_NODE_TYPE_ALSA_LOOPBACK: - return CRAS_METRICS_DEVICE_ALSA_LOOPBACK; case CRAS_NODE_TYPE_UNKNOWN: default: return CRAS_METRICS_DEVICE_UNKNOWN; } } -/* - * Logs metrics for each group it belongs to. The UMA does not merge subgroups - * automatically so we need to log them separately. - * - * For example, if we call this function with argument (3, 48000, - * Cras.StreamSamplingRate, Input, Chrome), it will send 48000 to below - * metrics: - * Cras.StreamSamplingRate.Input.Chrome - * Cras.StreamSamplingRate.Input - * Cras.StreamSamplingRate - */ -static void log_sparse_histogram_each_level(int num, int sample, ...) -{ - char metrics_name[METRICS_NAME_BUFFER_SIZE] = {}; - va_list valist; - int i, len = 0; - - va_start(valist, sample); - - for (i = 0; i < num && len < METRICS_NAME_BUFFER_SIZE; i++) { - int metric_len = - snprintf(metrics_name + len, - METRICS_NAME_BUFFER_SIZE - len, "%s%s", - i ? "." : "", va_arg(valist, char *)); - // Exit early on error or running out of bufferspace. Avoids - // logging partial or corrupted strings. - if (metric_len < 0 || - metric_len > METRICS_NAME_BUFFER_SIZE - len) - break; - len += metric_len; - cras_metrics_log_sparse_histogram(metrics_name, sample); - } - - va_end(valist); -} - -static void log_histogram_each_level(int num, int sample, int min, int max, - int nbuckets, ...) -{ - char metrics_name[METRICS_NAME_BUFFER_SIZE] = {}; - va_list valist; - int i, len = 0; - - va_start(valist, nbuckets); - - for (i = 0; i < num && len < METRICS_NAME_BUFFER_SIZE; i++) { - int metric_len = - snprintf(metrics_name + len, - METRICS_NAME_BUFFER_SIZE - len, "%s%s", - i ? "." : "", va_arg(valist, char *)); - // Exit early on error or running out of bufferspace. Avoids - // logging partial or corrupted strings. - if (metric_len < 0 || - metric_len > METRICS_NAME_BUFFER_SIZE - len) - break; - len += metric_len; - cras_metrics_log_histogram(metrics_name, sample, min, max, - nbuckets); - } - - va_end(valist); -} - -int cras_server_metrics_hfp_sco_connection_error( - enum CRAS_METRICS_BT_SCO_ERROR_TYPE type) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - data.value = type; - init_server_metrics_msg(&msg, BT_SCO_CONNECTION_ERROR, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, "Failed to send metrics message: " - "BT_SCO_CONNECTION_ERROR"); - return err; - } - return 0; -} - -int cras_server_metrics_hfp_battery_indicator(int battery_indicator_support) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - data.value = battery_indicator_support; - init_server_metrics_msg(&msg, BT_BATTERY_INDICATOR_SUPPORTED, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, "Failed to send metrics message: " - "BT_BATTERY_INDICATOR_SUPPORTED"); - return err; - } - return 0; -} - -int cras_server_metrics_hfp_battery_report(int battery_report) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - data.value = battery_report; - init_server_metrics_msg(&msg, BT_BATTERY_REPORT, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, "Failed to send metrics message: " - "BT_BATTERY_REPORT"); - return err; - } - return 0; -} - int cras_server_metrics_hfp_packet_loss(float packet_loss_ratio) { struct cras_server_metrics_message msg; @@ -584,25 +360,6 @@ int cras_server_metrics_hfp_wideband_support(bool supported) return 0; } -int cras_server_metrics_hfp_wideband_selected_codec(int codec) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - data.value = codec; - init_server_metrics_msg(&msg, BT_WIDEBAND_SELECTED_CODEC, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, "Failed to send metrics message: " - "BT_WIDEBAND_SELECTED_CODEC"); - return err; - } - return 0; -} - int cras_server_metrics_device_runtime(struct cras_iodev *iodev) { struct cras_server_metrics_message msg; @@ -628,56 +385,6 @@ int cras_server_metrics_device_runtime(struct cras_iodev *iodev) return 0; } -int cras_server_metrics_device_gain(struct cras_iodev *iodev) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - if (iodev->direction == CRAS_STREAM_OUTPUT) - return 0; - - data.device_data.type = get_metrics_device_type(iodev); - data.device_data.value = - (unsigned)100 * iodev->active_node->ui_gain_scaler; - - init_server_metrics_msg(&msg, DEVICE_GAIN, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, "Failed to send metrics message: DEVICE_GAIN"); - return err; - } - - return 0; -} - -int cras_server_metrics_device_volume(struct cras_iodev *iodev) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - if (iodev->direction == CRAS_STREAM_INPUT) - return 0; - - data.device_data.type = get_metrics_device_type(iodev); - data.device_data.value = iodev->active_node->volume; - - init_server_metrics_msg(&msg, DEVICE_VOLUME, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, - "Failed to send metrics message: DEVICE_VOLUME"); - return err; - } - - return 0; -} - int cras_server_metrics_highest_device_delay( unsigned int hw_level, unsigned int largest_cb_level, enum CRAS_STREAM_DIRECTION direction) @@ -757,31 +464,13 @@ int cras_server_metrics_highest_hw_level(unsigned hw_level, return 0; } -/* Logs longest fetch delay of a stream. */ -int cras_server_metrics_longest_fetch_delay(const struct cras_rstream *stream) +int cras_server_metrics_longest_fetch_delay(unsigned delay_msec) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; int err; - data.stream_data.client_type = stream->client_type; - data.stream_data.stream_type = stream->stream_type; - data.stream_data.direction = stream->direction; - - /* - * There is no delay when the sleep_interval_ts larger than the - * longest_fetch_interval. - */ - if (!timespec_after(&stream->longest_fetch_interval, - &stream->sleep_interval_ts)) { - data.stream_data.runtime.tv_sec = 0; - data.stream_data.runtime.tv_nsec = 0; - } else { - subtract_timespecs(&stream->longest_fetch_interval, - &stream->sleep_interval_ts, - &data.stream_data.runtime); - } - + data.value = delay_msec; init_server_metrics_msg(&msg, LONGEST_FETCH_DELAY, data); err = cras_server_metrics_message_send( (struct cras_main_message *)&msg); @@ -813,9 +502,7 @@ int cras_server_metrics_num_underruns(unsigned num_underruns) return 0; } -/* Logs the frequency of missed callback. */ -static int -cras_server_metrics_missed_cb_frequency(const struct cras_rstream *stream) +int cras_server_metrics_missed_cb_frequency(const struct cras_rstream *stream) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; @@ -968,9 +655,7 @@ int cras_server_metrics_missed_cb_event(struct cras_rstream *stream) return rc; } -/* Logs the stream configurations from clients. */ -static int -cras_server_metrics_stream_config(const struct cras_rstream_config *config) +int cras_server_metrics_stream_config(struct cras_rstream_config *config) { struct cras_server_metrics_message msg; union cras_server_metrics_data data; @@ -979,7 +664,6 @@ cras_server_metrics_stream_config(const struct cras_rstream_config *config) data.stream_config.direction = config->direction; data.stream_config.cb_threshold = (unsigned)config->cb_threshold; data.stream_config.flags = (unsigned)config->flags; - data.stream_config.effects = (unsigned)config->effects; data.stream_config.format = (int)config->format->format; data.stream_config.rate = (unsigned)config->format->frame_rate; data.stream_config.client_type = config->client_type; @@ -996,50 +680,6 @@ cras_server_metrics_stream_config(const struct cras_rstream_config *config) return 0; } -/* Logs runtime of a stream. */ -int cras_server_metrics_stream_runtime(const struct cras_rstream *stream) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - struct timespec now; - int err; - - data.stream_data.client_type = stream->client_type; - data.stream_data.stream_type = stream->stream_type; - data.stream_data.direction = stream->direction; - clock_gettime(CLOCK_MONOTONIC_RAW, &now); - subtract_timespecs(&now, &stream->start_ts, &data.stream_data.runtime); - - init_server_metrics_msg(&msg, STREAM_RUNTIME, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, - "Failed to send metrics message: STREAM_RUNTIME"); - return err; - } - - return 0; -} - -int cras_server_metrics_stream_create(const struct cras_rstream_config *config) -{ - return cras_server_metrics_stream_config(config); -} - -int cras_server_metrics_stream_destroy(const struct cras_rstream *stream) -{ - int rc; - rc = cras_server_metrics_missed_cb_frequency(stream); - if (rc < 0) - return rc; - rc = cras_server_metrics_stream_runtime(stream); - if (rc < 0) - return rc; - return cras_server_metrics_longest_fetch_delay(stream); -} - int cras_server_metrics_busyloop(struct timespec *ts, unsigned count) { struct cras_server_metrics_message msg; @@ -1060,26 +700,6 @@ int cras_server_metrics_busyloop(struct timespec *ts, unsigned count) return 0; } -int cras_server_metrics_busyloop_length(unsigned length) -{ - struct cras_server_metrics_message msg; - union cras_server_metrics_data data; - int err; - - data.value = length; - - init_server_metrics_msg(&msg, BUSYLOOP_LENGTH, data); - - err = cras_server_metrics_message_send( - (struct cras_main_message *)&msg); - if (err < 0) { - syslog(LOG_ERR, - "Failed to send metrics message: BUSYLOOP_LENGTH"); - return err; - } - return 0; -} - static void metrics_device_runtime(struct cras_server_metrics_device_data data) { char metrics_name[METRICS_NAME_BUFFER_SIZE]; @@ -1098,44 +718,6 @@ static void metrics_device_runtime(struct cras_server_metrics_device_data data) cras_metrics_log_sparse_histogram(kDeviceTypeOutput, data.type); } -static void metrics_device_gain(struct cras_server_metrics_device_data data) -{ - char metrics_name[METRICS_NAME_BUFFER_SIZE]; - - snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.%s", kDeviceGain, - metrics_device_type_str(data.type)); - cras_metrics_log_histogram(metrics_name, data.value, 0, 2000, 20); -} - -static void metrics_device_volume(struct cras_server_metrics_device_data data) -{ - char metrics_name[METRICS_NAME_BUFFER_SIZE]; - - snprintf(metrics_name, METRICS_NAME_BUFFER_SIZE, "%s.%s", kDeviceVolume, - metrics_device_type_str(data.type)); - cras_metrics_log_histogram(metrics_name, data.value, 0, 100, 20); -} - -static void -metrics_longest_fetch_delay(struct cras_server_metrics_stream_data data) -{ - int fetch_delay_msec = - data.runtime.tv_sec * 1000 + data.runtime.tv_nsec / 1000000; - log_histogram_each_level(3, fetch_delay_msec, 0, 10000, 20, - kFetchDelayMilliSeconds, - metrics_client_type_str(data.client_type), - metrics_stream_type_str(data.stream_type)); -} - -static void metrics_stream_runtime(struct cras_server_metrics_stream_data data) -{ - log_histogram_each_level( - 4, (int)data.runtime.tv_sec, 0, 10000, 20, kStreamRuntime, - data.direction == CRAS_STREAM_INPUT ? "Input" : "Output", - metrics_client_type_str(data.client_type), - metrics_stream_type_str(data.stream_type)); -} - static void metrics_busyloop(struct cras_server_metrics_timespec_data data) { char metrics_name[METRICS_NAME_BUFFER_SIZE]; @@ -1149,37 +731,18 @@ static void metrics_busyloop(struct cras_server_metrics_timespec_data data) static void metrics_stream_config(struct cras_server_metrics_stream_config config) { - const char *direction; - - if (config.direction == CRAS_STREAM_INPUT) - direction = "Input"; - else - direction = "Output"; - /* Logs stream callback threshold. */ - log_sparse_histogram_each_level( - 3, config.cb_threshold, kStreamCallbackThreshold, direction, - metrics_client_type_str(config.client_type)); + cras_metrics_log_sparse_histogram(kStreamCallbackThreshold, + config.cb_threshold); /* Logs stream flags. */ - log_sparse_histogram_each_level( - 3, config.flags, kStreamFlags, direction, - metrics_client_type_str(config.client_type)); - - /* Logs stream effects. */ - log_sparse_histogram_each_level( - 3, config.effects, kStreamEffects, direction, - metrics_client_type_str(config.client_type)); + cras_metrics_log_sparse_histogram(kStreamFlags, config.flags); /* Logs stream sampling format. */ - log_sparse_histogram_each_level( - 3, config.format, kStreamSamplingFormat, direction, - metrics_client_type_str(config.client_type)); + cras_metrics_log_sparse_histogram(kStreamSamplingFormat, config.format); /* Logs stream sampling rate. */ - log_sparse_histogram_each_level( - 3, config.rate, kStreamSamplingRate, direction, - metrics_client_type_str(config.client_type)); + cras_metrics_log_sparse_histogram(kStreamSamplingRate, config.rate); /* Logs stream client type. */ if (config.direction == CRAS_STREAM_INPUT) @@ -1195,18 +758,6 @@ static void handle_metrics_message(struct cras_main_message *msg, void *arg) struct cras_server_metrics_message *metrics_msg = (struct cras_server_metrics_message *)msg; switch (metrics_msg->metrics_type) { - case BT_SCO_CONNECTION_ERROR: - cras_metrics_log_sparse_histogram(kHfpScoConnectionError, - metrics_msg->data.value); - break; - case BT_BATTERY_INDICATOR_SUPPORTED: - cras_metrics_log_sparse_histogram(kHfpBatteryIndicatorSupported, - metrics_msg->data.value); - break; - case BT_BATTERY_REPORT: - cras_metrics_log_sparse_histogram(kHfpBatteryReport, - metrics_msg->data.value); - break; case BT_WIDEBAND_PACKET_LOSS: cras_metrics_log_histogram(kHfpWidebandSpeechPacketLoss, metrics_msg->data.value, 0, 1000, @@ -1216,20 +767,9 @@ static void handle_metrics_message(struct cras_main_message *msg, void *arg) cras_metrics_log_sparse_histogram(kHfpWidebandSpeechSupported, metrics_msg->data.value); break; - case BT_WIDEBAND_SELECTED_CODEC: - cras_metrics_log_sparse_histogram( - kHfpWidebandSpeechSelectedCodec, - metrics_msg->data.value); - break; - case DEVICE_GAIN: - metrics_device_gain(metrics_msg->data.device_data); - break; case DEVICE_RUNTIME: metrics_device_runtime(metrics_msg->data.device_data); break; - case DEVICE_VOLUME: - metrics_device_volume(metrics_msg->data.device_data); - break; case HIGHEST_DEVICE_DELAY_INPUT: cras_metrics_log_histogram(kHighestDeviceDelayInput, metrics_msg->data.value, 1, 10000, @@ -1251,7 +791,9 @@ static void handle_metrics_message(struct cras_main_message *msg, void *arg) 20); break; case LONGEST_FETCH_DELAY: - metrics_longest_fetch_delay(metrics_msg->data.stream_data); + cras_metrics_log_histogram(kStreamTimeoutMilliSeconds, + metrics_msg->data.value, 1, 20000, + 10); break; case MISSED_CB_FIRST_TIME_INPUT: cras_metrics_log_histogram(kMissedCallbackFirstTimeInput, @@ -1301,16 +843,9 @@ static void handle_metrics_message(struct cras_main_message *msg, void *arg) case STREAM_CONFIG: metrics_stream_config(metrics_msg->data.stream_config); break; - case STREAM_RUNTIME: - metrics_stream_runtime(metrics_msg->data.stream_data); - break; case BUSYLOOP: metrics_busyloop(metrics_msg->data.timespec_data); break; - case BUSYLOOP_LENGTH: - cras_metrics_log_histogram( - kBusyloopLength, metrics_msg->data.value, 0, 1000, 50); - break; default: syslog(LOG_ERR, "Unknown metrics type %u", metrics_msg->metrics_type); diff --git a/cras/src/server/cras_server_metrics.h b/cras/src/server/cras_server_metrics.h index e8458087..b9eb1216 100644 --- a/cras/src/server/cras_server_metrics.h +++ b/cras/src/server/cras_server_metrics.h @@ -13,48 +13,15 @@ extern const char kNoCodecsFoundMetric[]; -enum CRAS_METRICS_BT_SCO_ERROR_TYPE { - CRAS_METRICS_SCO_SKT_SUCCESS = 0, - CRAS_METRICS_SCO_SKT_CONNECT_ERROR = 1, - CRAS_METRICS_SCO_SKT_OPEN_ERROR = 2, - CRAS_METRICS_SCO_SKT_POLL_TIMEOUT = 3, - CRAS_METRICS_SCO_SKT_POLL_ERR_HUP = 4, -}; - -/* Logs the error type happens when setting up SCO connection. This is mainly - * used to track whether the setup of SCO connection succeeds and the frequency - * of different errors. This will also be used to track if our fixes for these - * errors address the issues we find. - */ -int cras_server_metrics_hfp_sco_connection_error( - enum CRAS_METRICS_BT_SCO_ERROR_TYPE type); - -/* Logs an enum representing which spec does HFP headset supports battery - * indicator. Apple, HFP, none or both. */ -int cras_server_metrics_hfp_battery_indicator(int battery_indicator_support); - -/* Logs an enum representing the spec through which the battery level change - * event reported. Apple or HFP.*/ -int cras_server_metrics_hfp_battery_report(int battery_report); - /* Logs if connected HFP headset supports wideband speech. */ int cras_server_metrics_hfp_wideband_support(bool supported); -/* Logs the selected codec in HFP wideband connection. */ -int cras_server_metrics_hfp_wideband_selected_codec(int codec); - /* Logs the number of packet loss per 1000 packets under HFP capture. */ int cras_server_metrics_hfp_packet_loss(float packet_loss_ratio); /* Logs runtime of a device. */ int cras_server_metrics_device_runtime(struct cras_iodev *iodev); -/* Logs the gain of a device. */ -int cras_server_metrics_device_gain(struct cras_iodev *iodev); - -/* Logs the volume of a device. */ -int cras_server_metrics_device_volume(struct cras_iodev *iodev); - /* Logs the highest delay time of a device. */ int cras_server_metrics_highest_device_delay( unsigned int hw_level, unsigned int largest_cb_level, @@ -64,24 +31,24 @@ int cras_server_metrics_highest_device_delay( int cras_server_metrics_highest_hw_level(unsigned hw_level, enum CRAS_STREAM_DIRECTION direction); +/* Logs the longest fetch delay of a stream in millisecond. */ +int cras_server_metrics_longest_fetch_delay(unsigned delay_msec); + /* Logs the number of underruns of a device. */ int cras_server_metrics_num_underruns(unsigned num_underruns); -/* Logs the missed callback event. */ -int cras_server_metrics_missed_cb_event(struct cras_rstream *stream); +/* Logs the frequency of missed callback. */ +int cras_server_metrics_missed_cb_frequency(const struct cras_rstream *stream); -/* Logs information when a stream creates. */ -int cras_server_metrics_stream_create(const struct cras_rstream_config *config); +/* Logs the missed callback event. */ +int cras_server_metrics_missed_cb_event(const struct cras_rstream *stream); -/* Logs information when a stream destroys. */ -int cras_server_metrics_stream_destroy(const struct cras_rstream *stream); +/* Logs the stream configurations from clients. */ +int cras_server_metrics_stream_config(struct cras_rstream_config *config); /* Logs the number of busyloops for different time periods. */ int cras_server_metrics_busyloop(struct timespec *ts, unsigned count); -/* Logs the length of busyloops. */ -int cras_server_metrics_busyloop_length(unsigned length); - /* Initialize metrics logging stuff. */ int cras_server_metrics_init(); diff --git a/cras/src/server/cras_system_state.c b/cras/src/server/cras_system_state.c index 366afb5f..7aa3367e 100644 --- a/cras/src/server/cras_system_state.c +++ b/cras/src/server/cras_system_state.c @@ -3,7 +3,6 @@ * found in the LICENSE file. */ -#include <errno.h> #include <fcntl.h> #include <pthread.h> #include <string.h> @@ -14,11 +13,9 @@ #include <syslog.h> #include "cras_alsa_card.h" -#include "cras_alert.h" #include "cras_board_config.h" #include "cras_config.h" -#include "cras_device_blocklist.h" -#include "cras_iodev_list.h" +#include "cras_device_blacklist.h" #include "cras_observer.h" #include "cras_shm.h" #include "cras_system_state.h" @@ -32,11 +29,6 @@ struct card_list { struct card_list *prev, *next; }; -struct name_list { - char name[NAME_MAX]; - struct name_list *prev, *next; -}; - /* The system state. * Members: * exp_state - The exported system state shared with clients. @@ -48,7 +40,7 @@ struct name_list { * device_config_dir - Directory of device configs where volume curves live. * internal_ucm_suffix - The suffix to append to internal card name to * control which ucm config file to load. - * device_blocklist - Blocklist of device the server will ignore. + * device_blacklist - Blacklist of device the server will ignore. * cards - A list of active sound cards in the system. * update_lock - Protects the update_count, as audio threads can update the * stream count. @@ -56,8 +48,6 @@ struct name_list { * add_task - Function to handle adding a task for main thread to execute. * task_data - Data to be passed to add_task handler function. * main_thread_tid - The thread id of the main thread. - * bt_fix_a2dp_packet_size - The flag to override A2DP packet size set by - * Blueetoh peer devices to a smaller default value. */ static struct { struct cras_server_state *exp_state; @@ -67,14 +57,13 @@ static struct { size_t shm_size; const char *device_config_dir; const char *internal_ucm_suffix; - struct name_list *ignore_suffix_cards; - struct cras_device_blocklist *device_blocklist; + struct cras_device_blacklist *device_blacklist; struct card_list *cards; pthread_mutex_t update_lock; struct cras_tm *tm; /* Select loop callback registration. */ - int (*fd_add)(int fd, void (*cb)(void *data, int events), void *cb_data, - int events, void *select_data); + int (*fd_add)(int fd, void (*cb)(void *data), void *cb_data, + void *select_data); void (*fd_rm)(int fd, void *select_data); void *select_data; int (*add_task)(void (*callback)(void *data), void *callback_data, @@ -82,42 +71,8 @@ static struct { void *task_data; struct cras_audio_thread_snapshot_buffer snapshot_buffer; pthread_t main_thread_tid; - bool bt_fix_a2dp_packet_size; } state; -/* The string format is CARD1,CARD2,CARD3. Divide it into a list. */ -void init_ignore_suffix_cards(char *str) -{ - struct name_list *card; - char *ptr; - - state.ignore_suffix_cards = NULL; - - if (str == NULL) - return; - - ptr = strtok(str, ","); - while (ptr != NULL) { - card = (struct name_list *)calloc(1, sizeof(*card)); - if (!card) { - syslog(LOG_ERR, "Failed to call calloc: %d", errno); - return; - } - strncpy(card->name, ptr, NAME_MAX - 1); - DL_APPEND(state.ignore_suffix_cards, card); - ptr = strtok(NULL, ","); - } -} - -void deinit_ignore_suffix_cards() -{ - struct name_list *card; - DL_FOREACH (state.ignore_suffix_cards, card) { - DL_DELETE(state.ignore_suffix_cards, card); - free(card); - } -} - /* * Exported Interface. */ @@ -148,21 +103,20 @@ void cras_system_state_init(const char *device_config_dir, const char *shm_name, exp_state->mute = 0; exp_state->mute_locked = 0; exp_state->suspended = 0; + exp_state->capture_gain = DEFAULT_CAPTURE_GAIN; + exp_state->capture_gain_target = DEFAULT_CAPTURE_GAIN; exp_state->capture_mute = 0; exp_state->capture_mute_locked = 0; exp_state->min_volume_dBFS = DEFAULT_MIN_VOLUME_DBFS; exp_state->max_volume_dBFS = DEFAULT_MAX_VOLUME_DBFS; + exp_state->min_capture_gain = DEFAULT_MIN_CAPTURE_GAIN; + exp_state->max_capture_gain = DEFAULT_MAX_CAPTURE_GAIN; exp_state->num_streams_attached = 0; exp_state->default_output_buffer_size = board_config.default_output_buffer_size; exp_state->aec_supported = board_config.aec_supported; exp_state->aec_group_id = board_config.aec_group_id; - exp_state->bt_wbs_enabled = board_config.bt_wbs_enabled; - exp_state->deprioritize_bt_wbs_mic = - board_config.deprioritize_bt_wbs_mic; - exp_state->noise_cancellation_enabled = 0; - exp_state->hotword_pause_at_suspend = - board_config.hotword_pause_at_suspend; + exp_state->bt_wbs_enabled = 0; if ((rc = pthread_mutex_init(&state.update_lock, 0) != 0)) { syslog(LOG_ERR, "Fatal: system state mutex init"); @@ -172,13 +126,11 @@ void cras_system_state_init(const char *device_config_dir, const char *shm_name, state.exp_state = exp_state; /* Directory for volume curve configs. - * Note that device_config_dir does not affect device blocklist. - * Device blocklist is common to all boards so we do not need - * to change device blocklist at run time. */ + * Note that device_config_dir does not affect device blacklist. + * Device blacklist is common to all boards so we do not need + * to change device blacklist at run time. */ state.device_config_dir = device_config_dir; state.internal_ucm_suffix = NULL; - init_ignore_suffix_cards(board_config.ucm_ignore_suffix); - free(board_config.ucm_ignore_suffix); state.tm = cras_tm_init(); if (!state.tm) { @@ -186,9 +138,9 @@ void cras_system_state_init(const char *device_config_dir, const char *shm_name, exit(-ENOMEM); } - /* Read config file for blocklisted devices. */ - state.device_blocklist = - cras_device_blocklist_create(CRAS_CONFIG_FILE_DIR); + /* Read config file for blacklisted devices. */ + state.device_blacklist = + cras_device_blacklist_create(CRAS_CONFIG_FILE_DIR); /* Initialize snapshot buffer memory */ memset(&state.snapshot_buffer, 0, @@ -196,8 +148,6 @@ void cras_system_state_init(const char *device_config_dir, const char *shm_name, /* Save thread id of the main thread. */ state.main_thread_tid = pthread_self(); - - state.bt_fix_a2dp_packet_size = false; } void cras_system_state_set_internal_ucm_suffix(const char *internal_ucm_suffix) @@ -209,7 +159,7 @@ void cras_system_state_deinit() { /* Free any resources used. This prevents unit tests from leaking. */ - cras_device_blocklist_destroy(state.device_blocklist); + cras_device_blacklist_destroy(state.device_blacklist); cras_tm_deinit(state.tm); @@ -220,7 +170,6 @@ void cras_system_state_deinit() close(state.shm_fd_ro); } - deinit_ignore_suffix_cards(); pthread_mutex_destroy(&state.update_lock); } @@ -238,6 +187,21 @@ size_t cras_system_get_volume() return state.exp_state->volume; } +void cras_system_set_capture_gain(long gain) +{ + /* Adjust targeted gain to be in supported range. */ + state.exp_state->capture_gain_target = gain; + gain = MAX(gain, state.exp_state->min_capture_gain); + gain = MIN(gain, state.exp_state->max_capture_gain); + state.exp_state->capture_gain = gain; + cras_observer_notify_capture_gain(state.exp_state->capture_gain); +} + +long cras_system_get_capture_gain() +{ + return state.exp_state->capture_gain; +} + void cras_system_notify_mute(void) { cras_observer_notify_output_mute(state.exp_state->mute, @@ -346,7 +310,6 @@ void cras_system_set_suspended(int suspended) { state.exp_state->suspended = suspended; cras_observer_notify_suspend_changed(suspended); - cras_alert_process_all_pending_alerts(); } void cras_system_set_volume_limits(long min, long max) @@ -365,6 +328,24 @@ long cras_system_get_max_volume() return state.exp_state->max_volume_dBFS; } +void cras_system_set_capture_gain_limits(long min, long max) +{ + state.exp_state->min_capture_gain = MAX(min, DEFAULT_MIN_CAPTURE_GAIN); + state.exp_state->max_capture_gain = max; + /* Re-apply target gain subjected to the new supported range. */ + cras_system_set_capture_gain(state.exp_state->capture_gain_target); +} + +long cras_system_get_min_capture_gain() +{ + return state.exp_state->min_capture_gain; +} + +long cras_system_get_max_capture_gain() +{ + return state.exp_state->max_capture_gain; +} + int cras_system_get_default_output_buffer_size() { return state.exp_state->default_output_buffer_size; @@ -390,60 +371,6 @@ bool cras_system_get_bt_wbs_enabled() return !!state.exp_state->bt_wbs_enabled; } -bool cras_system_get_deprioritize_bt_wbs_mic() -{ - return !!state.exp_state->deprioritize_bt_wbs_mic; -} - -void cras_system_set_bt_fix_a2dp_packet_size_enabled(bool enabled) -{ - state.bt_fix_a2dp_packet_size = enabled; -} - -bool cras_system_get_bt_fix_a2dp_packet_size_enabled() -{ - return state.bt_fix_a2dp_packet_size; -} - -void cras_system_set_noise_cancellation_enabled(bool enabled) -{ - /* When the flag is toggled, propagate to all iodevs immediately. */ - if (cras_system_get_noise_cancellation_enabled() != enabled) { - state.exp_state->noise_cancellation_enabled = enabled; - cras_iodev_list_reset_for_noise_cancellation(); - } -} - -bool cras_system_get_noise_cancellation_enabled() -{ - return !!state.exp_state->noise_cancellation_enabled; -} - -bool cras_system_check_ignore_ucm_suffix(const char *card_name) -{ - /* Check the general case: ALSA Loopback card "Loopback". */ - if (!strcmp("Loopback", card_name)) - return true; - - /* Check board-specific ignore ucm suffix cards. */ - struct name_list *card; - DL_FOREACH (state.ignore_suffix_cards, card) { - if (!strcmp(card->name, card_name)) - return true; - } - return false; -} - -bool cras_system_get_hotword_pause_at_suspend() -{ - return !!state.exp_state->hotword_pause_at_suspend; -} - -void cras_system_set_hotword_pause_at_suspend(bool pause) -{ - state.exp_state->hotword_pause_at_suspend = pause; -} - int cras_system_add_alsa_card(struct cras_alsa_card_info *alsa_card_info) { struct card_list *card; @@ -459,10 +386,11 @@ int cras_system_add_alsa_card(struct cras_alsa_card_info *alsa_card_info) if (card_index == cras_alsa_card_get_index(card->card)) return -EEXIST; } - alsa_card = - cras_alsa_card_create(alsa_card_info, state.device_config_dir, - state.device_blocklist, - state.internal_ucm_suffix); + alsa_card = cras_alsa_card_create( + alsa_card_info, state.device_config_dir, state.device_blacklist, + (alsa_card_info->card_type == ALSA_CARD_TYPE_INTERNAL) ? + state.internal_ucm_suffix : + NULL); if (alsa_card == NULL) return -ENOMEM; card = calloc(1, sizeof(*card)); @@ -500,8 +428,8 @@ int cras_system_alsa_card_exists(unsigned alsa_card_index) } int cras_system_set_select_handler( - int (*add)(int fd, void (*callback)(void *data, int events), - void *callback_data, int events, void *select_data), + int (*add)(int fd, void (*callback)(void *data), void *callback_data, + void *select_data), void (*rm)(int fd, void *select_data), void *select_data) { if (state.fd_add != NULL || state.fd_rm != NULL) @@ -512,13 +440,12 @@ int cras_system_set_select_handler( return 0; } -int cras_system_add_select_fd(int fd, void (*callback)(void *data, int revents), - void *callback_data, int events) +int cras_system_add_select_fd(int fd, void (*callback)(void *data), + void *callback_data) { if (state.fd_add == NULL) return -EINVAL; - return state.fd_add(fd, callback, callback_data, events, - state.select_data); + return state.fd_add(fd, callback, callback_data, state.select_data); } int cras_system_set_add_task_handler(int (*add_task)(void (*cb)(void *data), @@ -548,8 +475,7 @@ void cras_system_rm_select_fd(int fd) state.fd_rm(fd, state.select_data); } -void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type) +void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction) { struct cras_server_state *s; @@ -559,19 +485,13 @@ void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction, s->num_active_streams[direction]++; s->num_streams_attached++; - if (direction == CRAS_STREAM_INPUT) { - s->num_input_streams_with_permission[client_type]++; - cras_observer_notify_input_streams_with_permission( - s->num_input_streams_with_permission); - } cras_system_state_update_complete(); cras_observer_notify_num_active_streams( direction, s->num_active_streams[direction]); } -void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type) +void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction) { struct cras_server_state *s; unsigned i, sum; @@ -589,11 +509,6 @@ void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction, cras_clock_gettime(CLOCK_MONOTONIC_RAW, &s->last_active_stream_time); s->num_active_streams[direction]--; - if (direction == CRAS_STREAM_INPUT) { - s->num_input_streams_with_permission[client_type]--; - cras_observer_notify_input_streams_with_permission( - s->num_input_streams_with_permission); - } cras_system_state_update_complete(); cras_observer_notify_num_active_streams( @@ -615,15 +530,6 @@ unsigned cras_system_state_get_active_streams_by_direction( return state.exp_state->num_active_streams[direction]; } -void cras_system_state_get_input_streams_with_permission( - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) -{ - unsigned type; - for (type = 0; type < CRAS_NUM_CLIENT_TYPE; ++type) - num_input_streams[type] = - state.exp_state->num_input_streams_with_permission[type]; -} - void cras_system_state_get_last_stream_active_time(struct cras_timespec *ts) { *ts = state.exp_state->last_active_stream_time; diff --git a/cras/src/server/cras_system_state.h b/cras/src/server/cras_system_state.h index bd09395c..270e54c2 100644 --- a/cras/src/server/cras_system_state.h +++ b/cras/src/server/cras_system_state.h @@ -20,12 +20,7 @@ #define CRAS_MAX_SYSTEM_VOLUME 100 #define DEFAULT_CAPTURE_GAIN 2000 /* 20dB of gain. */ -/* Default to -6 dBFS as 90% of CrOS boards use microphone with -26dBFS - * sensitivity under 94dB SPL @ 1kHz and we generally added 20dB gain to it. - * This is a temporary value that should be refined when the standard process - * measuring intrinsic sensitivity is built. */ -#define DEFAULT_CAPTURE_VOLUME_DBFS -600 -/* Default to 1--dB of range for playback and capture. */ +/* Default to 1--dB of range for palyback and capture. */ #define DEFAULT_MIN_VOLUME_DBFS -10000 #define DEFAULT_MAX_VOLUME_DBFS 0 #define DEFAULT_MIN_CAPTURE_GAIN -5000 @@ -57,8 +52,9 @@ void cras_system_set_volume(size_t volume); /* Gets the current system volume. */ size_t cras_system_get_volume(); -/* Gets the current system capture volume. As we remove the support of setting - * system capture gain, it should always be DEFAULT_CAPTURE_GAIN now. */ +/* Sets the system capture volume. Will be applied by the active device. */ +void cras_system_set_capture_gain(long gain); +/* Gets the current system capture volume. */ long cras_system_get_capture_gain(); /* Sets if the system is muted by the user. */ @@ -107,6 +103,19 @@ long cras_system_get_min_volume(); /* Returns the dB value when volume = CRAS_MAX_SYSTEM_VOLUME, in dB * 100. */ long cras_system_get_max_volume(); +/* Sets the limits in dB * 100 of the MAX and MIN capture gain. This will allow + * clients to query what range of control is available. Both arguments are + * specified as dB * 100. + * Args: + * min - minimum allowed capture gain. + * max - maximum allowed capture gaax. + */ +void cras_system_set_capture_gain_limits(long min, long max); +/* Returns the max value allowed for capture gain in dB * 100. */ +long cras_system_get_min_capture_gain(); +/* Returns the min value allowed for capture gain in dB * 100. */ +long cras_system_get_max_capture_gain(); + /* Returns the default value of output buffer size in frames. */ int cras_system_get_default_output_buffer_size(); @@ -122,33 +131,6 @@ void cras_system_set_bt_wbs_enabled(bool enabled); /* Gets the elable flag of bluetooth wideband speech feature. */ bool cras_system_get_bt_wbs_enabled(); -/* - * Returns if Bluetooth WBS mic should be deprioritized for selecting - * as default audio input option. - */ -bool cras_system_get_deprioritize_bt_wbs_mic(); - -/* Sets the flag to enable or disable Bluetooth fixed A2DP packet size. */ -void cras_system_set_bt_fix_a2dp_packet_size_enabled(bool enabled); - -/* Gets the flag of Bluetooth fixed A2DP packet size. */ -bool cras_system_get_bt_fix_a2dp_packet_size_enabled(); - -/* Sets the flag to enable or disable Noise Cancellation. */ -void cras_system_set_noise_cancellation_enabled(bool enabled); - -/* Gets the flag of Noise Cancellation. */ -bool cras_system_get_noise_cancellation_enabled(); - -/* Checks if the card ignores the ucm suffix. */ -bool cras_system_check_ignore_ucm_suffix(const char *card_name); - -/* Returns true if hotword detection is paused at system suspend. */ -bool cras_system_get_hotword_pause_at_suspend(); - -/* Sets whether to pause hotword detection at system suspend. */ -void cras_system_set_hotword_pause_at_suspend(bool pause); - /* Adds a card at the given index to the system. When a new card is found * (through a udev event notification) this will add the card to the system, * causing its devices to become available for playback/capture. @@ -192,8 +174,8 @@ int cras_system_alsa_card_exists(unsigned alsa_card_index); * 0 on success, or -EBUSY if there is already a registered handler. */ int cras_system_set_select_handler( - int (*add)(int fd, void (*callback)(void *data, int revents), - void *callback_data, int events, void *select_data), + int (*add)(int fd, void (*callback)(void *data), void *callback_data, + void *select_data), void (*rm)(int fd, void *select_data), void *select_data); /* Adds the fd and callback pair. When select indicates that fd is readable, @@ -202,12 +184,11 @@ int cras_system_set_select_handler( * fd - The file descriptor to pass to select(2). * callback - The callback to call when fd is ready. * callback_data - Value passed back to the callback. - * events - The events to poll for. * Returns: * 0 on success or a negative error code on failure. */ -int cras_system_add_select_fd(int fd, void (*callback)(void *data, int revents), - void *callback_data, int events); +int cras_system_add_select_fd(int fd, void (*callback)(void *data), + void *callback_data); /* Removes the fd from the list of fds that are passed to select. * Args: @@ -244,20 +225,16 @@ int cras_system_add_task(void (*callback)(void *data), void *callback_data); * subsystem is idle. * Args: * direction - Directions of audio streams. - * client_type - CRAS_CLIENT_TYPE of the audio stream. */ -void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type); +void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction); /* Signals that an audio input or output stream has been removed from the * system. This allows the count of active streams can be used to notice when * the audio subsystem is idle. * Args: * direction - Directions of audio stream. - * client_type - CRAS_CLIENT_TYPE of the audio stream. */ -void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type); +void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction); /* Returns the number of active playback and capture streams. */ unsigned cras_system_state_get_active_streams(); @@ -269,16 +246,6 @@ unsigned cras_system_state_get_active_streams(); unsigned cras_system_state_get_active_streams_by_direction( enum CRAS_STREAM_DIRECTION direction); -/* Returns the number of input streams with permission per CRAS_CLIENT_TYPE. - * - * Returns: - * num_input_streams - An array with length = CRAS_NUM_CLIENT_TYPE and each - * element is the number of the current input - * streams with permission in each client type. - */ -void cras_system_state_get_input_streams_with_permission( - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]); - /* Fills ts with the time the last stream was removed from the system, the time * the stream count went to zero. */ diff --git a/cras/src/server/cras_telephony.c b/cras/src/server/cras_telephony.c index 805fb137..ac95f7e1 100644 --- a/cras/src/server/cras_telephony.c +++ b/cras/src/server/cras_telephony.c @@ -41,12 +41,6 @@ " <method name=\"SetCallheld\">\n" \ " <arg name=\"value\" type=\"i\" direction=\"in\"/>\n" \ " </method>\n" \ - " <method name=\"SetCallsetup\">\n" \ - " <arg name=\"value\" type=\"i\" direction=\"in\"/>\n" \ - " </method>\n" \ - " <method name=\"SetCall\">\n" \ - " <arg name=\"value\" type=\"i\" direction=\"in\"/>\n" \ - " </method>\n" \ " </interface>\n" \ " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" \ " <method name=\"Introspect\">\n" \ @@ -226,46 +220,6 @@ static DBusHandlerResult handle_set_callheld(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static DBusHandlerResult handle_set_callsetup(DBusConnection *conn, - DBusMessage *message, void *arg) -{ - struct hfp_slc_handle *handle; - DBusHandlerResult rc; - int value; - - rc = get_single_arg(message, DBUS_TYPE_INT32, &value); - if (rc != DBUS_HANDLER_RESULT_HANDLED) - return rc; - - telephony_handle.callsetup = value; - handle = cras_hfp_ag_get_active_handle(); - if (handle) - hfp_event_update_callsetup(handle); - - send_empty_reply(conn, message); - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult handle_set_call(DBusConnection *conn, - DBusMessage *message, void *arg) -{ - struct hfp_slc_handle *handle; - DBusHandlerResult rc; - int value; - - rc = get_single_arg(message, DBUS_TYPE_INT32, &value); - if (rc != DBUS_HANDLER_RESULT_HANDLED) - return rc; - - telephony_handle.call = value; - handle = cras_hfp_ag_get_active_handle(); - if (handle) - hfp_event_update_call(handle); - - send_empty_reply(conn, message); - return DBUS_HANDLER_RESULT_HANDLED; -} - /* Handle incoming messages. */ static DBusHandlerResult handle_telephony_message(DBusConnection *conn, DBusMessage *message, void *arg) @@ -320,12 +274,6 @@ handle_telephony_message(DBusConnection *conn, DBusMessage *message, void *arg) } else if (dbus_message_is_method_call( message, CRAS_TELEPHONY_INTERFACE, "SetCallheld")) { return handle_set_callheld(conn, message, arg); - } else if (dbus_message_is_method_call( - message, CRAS_TELEPHONY_INTERFACE, "SetCallsetup")) { - return handle_set_callsetup(conn, message, arg); - } else if (dbus_message_is_method_call( - message, CRAS_TELEPHONY_INTERFACE, "SetCall")) { - return handle_set_call(conn, message, arg); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; diff --git a/cras/src/server/cras_udev.c b/cras/src/server/cras_udev.c index 16f0e3b2..dc4c2dd8 100644 --- a/cras/src/server/cras_udev.c +++ b/cras/src/server/cras_udev.c @@ -271,7 +271,7 @@ static void fill_usb_card_info(struct cras_alsa_card_info *card_info, card_info->usb_desc_checksum = calculate_desc_checksum(parent_dev); - syslog(LOG_INFO, + syslog(LOG_ERR, "USB card: vendor:%04x, product:%04x, serial num:%s, " "checksum:%08x", card_info->usb_vendor_id, card_info->usb_product_id, @@ -367,7 +367,7 @@ static void enumerate_devices(struct udev_callback_data *data) udev_enumerate_unref(enumerate); } -static void udev_sound_subsystem_callback(void *arg, int revents) +static void udev_sound_subsystem_callback(void *arg) { struct udev_callback_data *data = (struct udev_callback_data *)arg; struct udev_device *dev; @@ -408,9 +408,8 @@ void cras_udev_start_sound_subsystem_monitor() udev_monitor_enable_receiving(udev_data.mon); udev_data.fd = udev_monitor_get_fd(udev_data.mon); - r = cras_system_add_select_fd(udev_data.fd, - udev_sound_subsystem_callback, &udev_data, - POLLIN); + r = cras_system_add_select_fd( + udev_data.fd, udev_sound_subsystem_callback, &udev_data); assert(r == 0); compile_regex(&pcm_regex, pcm_regex_string); compile_regex(&card_regex, card_regex_string); diff --git a/cras/src/server/cras_unified_rclient.c b/cras/src/server/cras_unified_rclient.c deleted file mode 100644 index cdb7b47d..00000000 --- a/cras/src/server/cras_unified_rclient.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <syslog.h> - -#include "cras_iodev_list.h" -#include "cras_messages.h" -#include "cras_observer.h" -#include "cras_rclient.h" -#include "cras_rclient_util.h" -#include "cras_rstream.h" -#include "cras_types.h" -#include "cras_util.h" - -/* Declarations of cras_rclient operators for cras_unified_rclient. */ -static const struct cras_rclient_ops cras_unified_rclient_ops = { - .handle_message_from_client = rclient_handle_message_from_client, - .send_message_to_client = rclient_send_message_to_client, - .destroy = rclient_destroy, -}; - -/* - * Exported Functions. - */ - -/* Creates a client structure and sends a message back informing the client that - * the connection has succeeded. */ -struct cras_rclient *cras_unified_rclient_create(int fd, size_t id) -{ - int supported_directions = - cras_stream_direction_mask(CRAS_STREAM_OUTPUT) | - cras_stream_direction_mask(CRAS_STREAM_INPUT); - return rclient_generic_create(fd, id, &cras_unified_rclient_ops, - supported_directions); -} diff --git a/cras/src/server/cras_unified_rclient.h b/cras/src/server/cras_unified_rclient.h deleted file mode 100644 index 19973f88..00000000 --- a/cras/src/server/cras_unified_rclient.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CRAS_UNIFIED_RCLIENT_H_ -#define CRAS_UNIFIED_RCLIENT_H_ - -struct cras_rclient; - -/* Creates a unified rclient structure. This client supports only playback - * and capture functions but not control features. - * Args: - * fd - The file descriptor used for communication with the client. - * id - Unique identifier for this client. - * Returns: - * A pointer to the newly created rclient on success, NULL on failure. - */ -struct cras_rclient *cras_unified_rclient_create(int fd, size_t id); - -#endif /* CRAS_UNIFIED_RCLIENT_H_ */ diff --git a/cras/src/server/dev_io.c b/cras/src/server/dev_io.c index b311b221..97c61f92 100644 --- a/cras/src/server/dev_io.c +++ b/cras/src/server/dev_io.c @@ -10,7 +10,6 @@ #include "audio_thread_log.h" #include "cras_audio_area.h" #include "cras_audio_thread_monitor.h" -#include "cras_device_monitor.h" #include "cras_iodev.h" #include "cras_non_empty_audio_handler.h" #include "cras_rstream.h" @@ -48,78 +47,33 @@ static const int DROP_FRAMES_THRESHOLD_MS = 50; /* The number of devices playing/capturing non-empty stream(s). */ static int non_empty_device_count = 0; -/* The timestamp of last EIO error time. */ -static struct timespec last_io_err_time = { 0, 0 }; - -/* The gap time to avoid repeated error close request to main thread. */ -static const int ERROR_CLOSE_GAP_TIME_SECS = 10; - -/* Gets the main device which the stream is attached to. */ -static inline struct cras_iodev *get_main_dev(const struct dev_stream *stream) +/* Gets the master device which the stream is attached to. */ +static inline struct cras_iodev *get_master_dev(const struct dev_stream *stream) { - return (struct cras_iodev *)stream->stream->main_dev.dev_ptr; + return (struct cras_iodev *)stream->stream->master_dev.dev_ptr; } /* Updates the estimated sample rate of open device to all attached * streams. */ -static void update_estimated_rate(struct open_dev *adev, - struct open_dev *odev_list, - bool self_rate_need_update) +static void update_estimated_rate(struct open_dev *adev) { - struct cras_iodev *main_dev; + struct cras_iodev *master_dev; struct cras_iodev *dev = adev->dev; - struct cras_iodev *tracked_dev = NULL; struct dev_stream *dev_stream; - double dev_rate_ratio; - double main_dev_rate_ratio; - - /* - * If there is an output device on the same sound card running with the same - * sampling rate, use the rate of that output device for this device. - */ - if (dev->direction == CRAS_STREAM_INPUT && - cras_iodev_is_on_internal_card(dev->active_node)) { - struct open_dev *odev; - DL_FOREACH (odev_list, odev) { - if (!cras_iodev_is_on_internal_card( - odev->dev->active_node)) - continue; - if (odev->dev->format->frame_rate != - dev->format->frame_rate) - continue; - tracked_dev = odev->dev; - break; - } - } - - /* - * Self-owned rate esimator does not need to udpate rate. There is no tracked - * output device. So there is no need to update. - */ - if (!self_rate_need_update && !tracked_dev) - return; DL_FOREACH (dev->streams, dev_stream) { - main_dev = get_main_dev(dev_stream); - if (main_dev == NULL) { - syslog(LOG_ERR, "Fail to find main open dev."); + master_dev = get_master_dev(dev_stream); + if (master_dev == NULL) { + syslog(LOG_ERR, "Fail to find master open dev."); continue; } - if (tracked_dev) { - dev_rate_ratio = - cras_iodev_get_est_rate_ratio(tracked_dev); - main_dev_rate_ratio = dev_rate_ratio; - } else { - dev_rate_ratio = cras_iodev_get_est_rate_ratio(dev); - main_dev_rate_ratio = - cras_iodev_get_est_rate_ratio(main_dev); - } - - dev_stream_set_dev_rate(dev_stream, dev->format->frame_rate, - dev_rate_ratio, main_dev_rate_ratio, - adev->coarse_rate_adjust); + dev_stream_set_dev_rate( + dev_stream, dev->format->frame_rate, + cras_iodev_get_est_rate_ratio(dev), + cras_iodev_get_est_rate_ratio(master_dev), + adev->coarse_rate_adjust); } } @@ -138,7 +92,7 @@ static inline int count_non_empty_dev(struct open_dev *adevs) return count; } -int dev_io_check_non_empty_state_transition(struct open_dev *adevs) +static void check_non_empty_state_transition(struct open_dev *adevs) { int new_non_empty_dev_count = count_non_empty_dev(adevs); @@ -149,7 +103,6 @@ int dev_io_check_non_empty_state_transition(struct open_dev *adevs) 0); non_empty_device_count = new_non_empty_dev_count; - return non_empty_device_count > 0; } /* Checks whether it is time to fetch. */ @@ -172,19 +125,6 @@ static bool is_time_to_fetch(const struct dev_stream *dev_stream, return 0; } -/* The log only accepts uint32 arguments, so the float power - * must be written as bits and assumed to have a float when - * parsing the log. - */ -static uint32_t get_ewma_power_as_int(struct ewma_power *ewma) -{ - uint32_t pow_as_int = 0; - - if (sizeof(uint32_t) == sizeof(float)) - memcpy(&pow_as_int, &ewma->power, sizeof(uint32_t)); - return pow_as_int; -} - /* Asks any stream with room for more data. Sets the time stamp for all streams. * Args: * adev - The output device streams are attached to. @@ -246,15 +186,13 @@ static int fetch_streams(struct open_dev *adev) shm->header->write_offset[0], shm->header->write_offset[1]); dev_stream_update_next_wake_time(dev_stream); - cras_server_metrics_missed_cb_event(dev_stream->stream); continue; } dev_stream_set_delay(dev_stream, delay); ATLOG(atlog, AUDIO_THREAD_FETCH_STREAM, rstream->stream_id, - cras_rstream_get_cb_threshold(rstream), - get_ewma_power_as_int(&rstream->ewma)); + cras_rstream_get_cb_threshold(rstream), delay); rc = dev_stream_request_playback_samples(dev_stream, &now); if (rc < 0) { @@ -404,9 +342,7 @@ static bool input_devices_can_drop_samples(struct cras_iodev *iodev) if (!iodev->streams) return false; if (!iodev->active_node || - iodev->active_node->type == CRAS_NODE_TYPE_HOTWORD || - iodev->active_node->type == CRAS_NODE_TYPE_POST_MIX_PRE_DSP || - iodev->active_node->type == CRAS_NODE_TYPE_POST_DSP) + iodev->active_node->type == CRAS_NODE_TYPE_HOTWORD) return false; return true; } @@ -446,14 +382,11 @@ static int set_input_dev_wake_ts(struct open_dev *adev, bool *need_to_drop) clock_gettime(CLOCK_MONOTONIC_RAW, &level_tstamp); /* - * Drop frames from all devices if any device meets these requirements: - * 1. The hw_level is larger than largest_cb_level * 1.5 or larger than - * buffer_size * 0.5. - * 2. The time of those frames is larger than DROP_FRAMES_THRESHOLD_MS. + * If any input device has more than largest_cb_level * 1.5 frames, need to + * drop frames from all devices. */ if (input_devices_can_drop_samples(adev->dev) && - (rc >= adev->dev->largest_cb_level * 1.5 || - rc >= adev->dev->buffer_size * 0.5) && + rc >= adev->dev->largest_cb_level * 1.5 && cras_frames_to_ms(rc, adev->dev->format->frame_rate) >= DROP_FRAMES_THRESHOLD_MS) *need_to_drop = true; @@ -510,7 +443,7 @@ static int set_input_dev_wake_ts(struct open_dev *adev, bool *need_to_drop) * adev - The device to capture samples from. * Returns 0 on success. */ -static int capture_to_streams(struct open_dev *adev, struct open_dev *odev_list) +static int capture_to_streams(struct open_dev *adev) { struct cras_iodev *idev = adev->dev; snd_pcm_uframes_t remainder, hw_level, cap_limit; @@ -532,29 +465,14 @@ static int capture_to_streams(struct open_dev *adev, struct open_dev *odev_list) ATLOG(atlog, AUDIO_THREAD_READ_AUDIO_TSTAMP, idev->info.idx, hw_tstamp.tv_sec, hw_tstamp.tv_nsec); if (timespec_is_nonzero(&hw_tstamp)) { - bool self_rate_need_update; - if (hw_level < idev->min_cb_level / 2) adev->coarse_rate_adjust = 1; else if (hw_level > idev->max_cb_level * 2) adev->coarse_rate_adjust = -1; else adev->coarse_rate_adjust = 0; - - /* - * This values means whether the rate estimator in the device - * wants to update estimated rate. - */ - self_rate_need_update = - !!cras_iodev_update_rate(idev, hw_level, &hw_tstamp); - - /* - * Always calls update_estimated_rate so that new output rate - * has a chance to propagate to input. In update_estimated_rate, - * it will decide whether the new rate is from self rate estimator - * or from the tracked output device. - */ - update_estimated_rate(adev, odev_list, self_rate_need_update); + if (cras_iodev_update_rate(idev, hw_level, &hw_tstamp)) + update_estimated_rate(adev); } cap_limit = get_stream_limit(adev, hw_level, &cap_limit_stream); @@ -591,19 +509,24 @@ static int capture_to_streams(struct open_dev *adev, struct open_dev *odev_list) stream->stream, idev->buf_state, &area, &area_offset); - /* - * The UI gain scaler should always take effect. - * input_data will decide if stream and iodev internal - * software gains should be used or not, based on use - * case. + * The software gain scaler consist of two parts: + * (1) The device gain scaler used when lack of hardware + * gain control. Configured by the DefaultNodeGain label + * in alsa UCM config. + * (2) The gain scaler in cras_rstream set by app, for + * example the AGC module in Chrome. + * + * APM has more advanced gain control mechanism, we shall + * give APM total control of the captured samples without + * additional gain scaler at all. */ software_gain_scaler = - cras_iodev_get_ui_gain_scaler(idev) * - input_data_get_software_gain_scaler( - idev->input_data, - idev->software_gain_scaler, - stream->stream); + stream->stream->apm_list ? + 1.0f : + idev->software_gain_scaler * + cras_rstream_get_volume_scaler( + stream->stream); this_read = dev_stream_capture(stream, area, area_offset, @@ -625,8 +548,7 @@ static int capture_to_streams(struct open_dev *adev, struct open_dev *odev_list) break; } - ATLOG(atlog, AUDIO_THREAD_READ_AUDIO_DONE, remainder, - get_ewma_power_as_int(&idev->ewma), 0); + ATLOG(atlog, AUDIO_THREAD_READ_AUDIO_DONE, remainder, 0, 0); return 0; } @@ -640,13 +562,12 @@ static int capture_to_streams(struct open_dev *adev, struct open_dev *odev_list) * write_limit - The maximum number of frames to write to dst. * * Returns: - * The number of frames rendered on success. + * The number of frames rendered on success, a negative error code otherwise. * This number of frames is the minimum of the amount of frames each stream * could provide which is the maximum that can currently be rendered. */ -static unsigned int write_streams(struct open_dev **odevs, - struct open_dev *adev, uint8_t *dst, - size_t write_limit) +static int write_streams(struct open_dev **odevs, struct open_dev *adev, + uint8_t *dst, size_t write_limit) { struct cras_iodev *odev = adev->dev; struct dev_stream *curr; @@ -808,10 +729,9 @@ int write_output_samples(struct open_dev **odevs, struct open_dev *adev, adev->coarse_rate_adjust = 0; if (cras_iodev_update_rate(odev, hw_level, &hw_tstamp)) - update_estimated_rate(adev, NULL, true); + update_estimated_rate(adev); } - ATLOG(atlog, AUDIO_THREAD_FILL_AUDIO, adev->dev->info.idx, hw_level, - odev->min_cb_level); + ATLOG(atlog, AUDIO_THREAD_FILL_AUDIO, adev->dev->info.idx, hw_level, 0); /* Don't request more than hardware can hold. Note that min_buffer_level * has been subtracted from the actual hw_level so we need to take it @@ -830,6 +750,9 @@ int write_output_samples(struct open_dev **odevs, struct open_dev *adev, /* TODO(dgreid) - This assumes interleaved audio. */ dst = area->channels[0].buf; written = write_streams(odevs, adev, dst, frames); + if (written < 0) /* pcm has been closed */ + return (int)written; + if (written < (snd_pcm_sframes_t)frames) /* Got all the samples from client that we can, but it * won't fill the request. */ @@ -872,7 +795,7 @@ int write_output_samples(struct open_dev **odevs, struct open_dev *adev, } ATLOG(atlog, AUDIO_THREAD_FILL_AUDIO_DONE, hw_level, total_written, - get_ewma_power_as_int(&odev->ewma)); + odev->min_cb_level); return total_written; } @@ -928,7 +851,7 @@ static void get_input_devices_drop_time(struct open_dev *idev_list, static void dev_io_drop_samples(struct open_dev *idev_list) { struct open_dev *adev; - struct timespec drop_time = {}; + struct timespec drop_time; int rc; get_input_devices_drop_time(idev_list, &drop_time); @@ -993,46 +916,26 @@ int dev_io_send_captured_samples(struct open_dev *idev_list) static void handle_dev_err(int err_rc, struct open_dev **odevs, struct open_dev *adev) { - struct timespec diff, now; if (err_rc == -EPIPE) { /* Handle severe underrun. */ ATLOG(atlog, AUDIO_THREAD_SEVERE_UNDERRUN, adev->dev->info.idx, 0, 0); cras_iodev_reset_request(adev->dev); - cras_audio_thread_event_severe_underrun(); - } else if (err_rc == -EIO) { - syslog(LOG_WARNING, "I/O err, reseting %s dev %s", - adev->dev->direction == CRAS_STREAM_OUTPUT ? "output" : - "input", - adev->dev->info.name); - clock_gettime(CLOCK_REALTIME, &now); - subtract_timespecs(&now, &last_io_err_time, &diff); - if ((last_io_err_time.tv_sec == 0 && - last_io_err_time.tv_nsec == 0) || - diff.tv_sec > ERROR_CLOSE_GAP_TIME_SECS) - cras_iodev_reset_request(adev->dev); - else - cras_device_monitor_error_close(adev->dev->info.idx); - - last_io_err_time = now; - } else { - syslog(LOG_ERR, "Dev %s err %d", adev->dev->info.name, err_rc); } /* Device error, remove it. */ dev_io_rm_open_dev(odevs, adev); } -int dev_io_capture(struct open_dev **list, struct open_dev **olist) +int dev_io_capture(struct open_dev **list) { struct open_dev *idev_list = *list; - struct open_dev *odev_list = *olist; struct open_dev *adev; int rc; DL_FOREACH (idev_list, adev) { if (!cras_iodev_is_open(adev->dev)) continue; - rc = capture_to_streams(adev, odev_list); + rc = capture_to_streams(adev); if (rc < 0) handle_dev_err(rc, list, adev); } @@ -1125,8 +1028,10 @@ int dev_io_playback_write(struct open_dev **odevs, * we should handle it. */ if (hw_level <= total_written) { - rc = cras_iodev_output_underrun( - adev->dev, hw_level, total_written); + ATLOG(atlog, AUDIO_THREAD_UNDERRUN, + adev->dev->info.idx, hw_level, + total_written); + rc = cras_iodev_output_underrun(adev->dev); if (rc < 0) { handle_dev_err(rc, odevs, adev); } else { @@ -1183,9 +1088,11 @@ void dev_io_run(struct open_dev **odevs, struct open_dev **idevs, update_longest_wake(*idevs, &now); dev_io_playback_fetch(*odevs); - dev_io_capture(idevs, odevs); + dev_io_capture(idevs); dev_io_send_captured_samples(*idevs); dev_io_playback_write(odevs, output_converter); + + check_non_empty_state_transition(*odevs); } static int input_adev_ignore_wake(const struct open_dev *adev) @@ -1252,7 +1159,8 @@ static int get_next_stream_wake_from_list(struct dev_stream *streams, return ret; } -int dev_io_next_output_wake(struct open_dev **odevs, struct timespec *min_ts) +int dev_io_next_output_wake(struct open_dev **odevs, struct timespec *min_ts, + const struct timespec *now) { struct open_dev *adev; int ret = 0; @@ -1311,7 +1219,7 @@ void dev_io_rm_open_dev(struct open_dev **odev_list, struct open_dev *dev_to_rm) cras_server_metrics_highest_hw_level(dev_to_rm->dev->highest_hw_level, dev_to_rm->dev->direction); - dev_io_check_non_empty_state_transition(*odev_list); + check_non_empty_state_transition(*odev_list); ATLOG(atlog, AUDIO_THREAD_DEV_REMOVED, dev_to_rm->dev->info.idx, 0, 0); @@ -1337,61 +1245,14 @@ static void delete_stream_from_dev(struct cras_iodev *dev, dev_stream_destroy(out); } -/* - * Finds a matched input stream from open device list. - * The definition of the matched streams: Two streams having - * the same sampling rate and the same cb_threshold. - * This means their sleep time intervals should be very close - * if we neglect device estimated rate. - */ -static struct dev_stream * -find_matched_input_stream(const struct cras_rstream *out_stream, - struct open_dev *odev_list) -{ - struct open_dev *odev; - struct dev_stream *dev_stream; - size_t out_rate = out_stream->format.frame_rate; - size_t out_cb_threshold = cras_rstream_get_cb_threshold(out_stream); - - DL_FOREACH (odev_list, odev) { - DL_FOREACH (odev->dev->streams, dev_stream) { - if (dev_stream->stream->format.frame_rate != out_rate) - continue; - if (cras_rstream_get_cb_threshold(dev_stream->stream) != - out_cb_threshold) - continue; - return dev_stream; - } - } - return NULL; -} - -static bool -find_matched_input_stream_next_cb_ts(const struct cras_rstream *stream, - struct open_dev *odev_list, - const struct timespec **next_cb_ts, - const struct timespec **sleep_interval_ts) -{ - struct dev_stream *dev_stream = - find_matched_input_stream(stream, odev_list); - if (dev_stream) { - *next_cb_ts = dev_stream_next_cb_ts(dev_stream); - *sleep_interval_ts = dev_stream_sleep_interval_ts(dev_stream); - return *next_cb_ts != NULL; - } - return false; -} - -int dev_io_append_stream(struct open_dev **odevs, struct open_dev **idevs, +int dev_io_append_stream(struct open_dev **dev_list, struct cras_rstream *stream, struct cras_iodev **iodevs, unsigned int num_iodevs) { - struct open_dev **dev_list; struct open_dev *open_dev; struct cras_iodev *dev; struct dev_stream *out; struct timespec init_cb_ts; - const struct timespec *init_sleep_interval_ts = NULL; struct timespec extra_sleep; const struct timespec *stream_ts; unsigned int i; @@ -1399,11 +1260,6 @@ int dev_io_append_stream(struct open_dev **odevs, struct open_dev **idevs, int level; int rc = 0; - if (stream->direction == CRAS_STREAM_OUTPUT) - dev_list = odevs; - else - dev_list = idevs; - for (i = 0; i < num_iodevs; i++) { DL_SEARCH_SCALAR(*dev_list, open_dev, dev, iodevs[i]); if (!open_dev) @@ -1448,55 +1304,35 @@ int dev_io_append_stream(struct open_dev **odevs, struct open_dev **idevs, * may cause device buffer level stack up. */ if (stream->direction == CRAS_STREAM_OUTPUT) { - /* - * If there is a matched input stream, find its next cb time. - * Use that as the initial cb time for this output stream. - */ - const struct timespec *in_stream_ts; - const struct timespec *in_stream_sleep_interval_ts; - bool found_matched_input; - found_matched_input = - find_matched_input_stream_next_cb_ts( - stream, *idevs, &in_stream_ts, - &in_stream_sleep_interval_ts); - if (found_matched_input) { - init_cb_ts = *in_stream_ts; - init_sleep_interval_ts = - in_stream_sleep_interval_ts; - } else { - DL_FOREACH (dev->streams, out) { - stream_ts = dev_stream_next_cb_ts(out); - if (stream_ts && - (!cb_ts_set || - timespec_after(&init_cb_ts, - stream_ts))) { - init_cb_ts = *stream_ts; - cb_ts_set = true; - } + DL_FOREACH (dev->streams, out) { + stream_ts = dev_stream_next_cb_ts(out); + if (stream_ts && + (!cb_ts_set || + timespec_after(&init_cb_ts, stream_ts))) { + init_cb_ts = *stream_ts; + cb_ts_set = true; } - if (!cb_ts_set) { - level = cras_iodev_get_valid_frames( - dev, &init_cb_ts); - if (level < 0) { - syslog(LOG_ERR, - "Failed to set output init_cb_ts, rc = %d", - level); - rc = -EINVAL; - break; - } - level -= cras_frames_at_rate( - stream->format.frame_rate, - cras_rstream_get_cb_threshold( - stream), - dev->format->frame_rate); - if (level < 0) - level = 0; - cras_frames_to_time( - level, dev->format->frame_rate, - &extra_sleep); - add_timespecs(&init_cb_ts, - &extra_sleep); + } + if (!cb_ts_set) { + level = cras_iodev_get_valid_frames( + dev, &init_cb_ts); + if (level < 0) { + syslog(LOG_ERR, + "Failed to set output init_cb_ts, rc = %d", + level); + rc = -EINVAL; + break; } + level -= cras_frames_at_rate( + stream->format.frame_rate, + cras_rstream_get_cb_threshold(stream), + dev->format->frame_rate); + if (level < 0) + level = 0; + cras_frames_to_time(level, + dev->format->frame_rate, + &extra_sleep); + add_timespecs(&init_cb_ts, &extra_sleep); } } else { /* @@ -1515,7 +1351,7 @@ int dev_io_append_stream(struct open_dev **odevs, struct open_dev **idevs, } out = dev_stream_create(stream, dev->info.idx, dev->format, dev, - &init_cb_ts, init_sleep_interval_ts); + &init_cb_ts); if (!out) { rc = -EINVAL; break; @@ -1568,6 +1404,20 @@ int dev_io_remove_stream(struct open_dev **dev_list, struct cras_rstream *stream, struct cras_iodev *dev) { struct open_dev *open_dev; + struct timespec delay; + unsigned fetch_delay_msec; + + /* Metrics log the longest fetch delay of this stream. */ + if (timespec_after(&stream->longest_fetch_interval, + &stream->sleep_interval_ts)) { + subtract_timespecs(&stream->longest_fetch_interval, + &stream->sleep_interval_ts, &delay); + fetch_delay_msec = + delay.tv_sec * 1000 + delay.tv_nsec / 1000000; + if (fetch_delay_msec) + cras_server_metrics_longest_fetch_delay( + fetch_delay_msec); + } ATLOG(atlog, AUDIO_THREAD_STREAM_REMOVED, stream->stream_id, 0, 0); diff --git a/cras/src/server/dev_io.h b/cras/src/server/dev_io.h index ca71a809..3184e4c8 100644 --- a/cras/src/server/dev_io.h +++ b/cras/src/server/dev_io.h @@ -58,9 +58,8 @@ int write_output_samples(struct open_dev **odevs, struct open_dev *adev, * Captures samples from each device in the list. * list - Pointer to the list of input devices. Devices that fail to read * will be removed from the list. - * olist - Pointer to the list of output devices. */ -int dev_io_capture(struct open_dev **list, struct open_dev **olist); +int dev_io_capture(struct open_dev **list); /* * Send samples that have been captured to their streams. @@ -72,12 +71,6 @@ void dev_io_run(struct open_dev **odevs, struct open_dev **idevs, struct cras_fmt_conv *output_converter); /* - * Checks the non-empty device state in active output lists and return - * if there's at least one non-empty device. - */ -int dev_io_check_non_empty_state_transition(struct open_dev *adevs); - -/* * Fills min_ts with the next time the system should wake to service input. * Returns the number of devices waiting. */ @@ -87,7 +80,8 @@ int dev_io_next_input_wake(struct open_dev **idevs, struct timespec *min_ts); * Fills min_ts with the next time the system should wake to service output. * Returns the number of devices waiting. */ -int dev_io_next_output_wake(struct open_dev **odevs, struct timespec *min_ts); +int dev_io_next_output_wake(struct open_dev **odevs, struct timespec *min_ts, + const struct timespec *now); /* * Removes a device from a list of devices. @@ -102,7 +96,7 @@ struct open_dev *dev_io_find_open_dev(struct open_dev *odev_list, unsigned int dev_idx); /* Append a new stream to a specified set of iodevs. */ -int dev_io_append_stream(struct open_dev **odevs, struct open_dev **idevs, +int dev_io_append_stream(struct open_dev **dev_list, struct cras_rstream *stream, struct cras_iodev **iodevs, unsigned int num_iodevs); diff --git a/cras/src/server/dev_stream.c b/cras/src/server/dev_stream.c index be5a6dab..878bb8a7 100644 --- a/cras/src/server/dev_stream.c +++ b/cras/src/server/dev_stream.c @@ -63,8 +63,7 @@ unsigned int max_frames_for_conversion(unsigned int stream_frames, struct dev_stream *dev_stream_create(struct cras_rstream *stream, unsigned int dev_id, const struct cras_audio_format *dev_fmt, - void *dev_ptr, struct timespec *cb_ts, - const struct timespec *sleep_interval_ts) + void *dev_ptr, struct timespec *cb_ts) { struct dev_stream *out; struct cras_audio_format *stream_fmt = &stream->format; @@ -88,12 +87,9 @@ struct dev_stream *dev_stream_create(struct cras_rstream *stream, } else { /* * For input, take into account the stream specific processing - * like AEC. APM exists only in input path, and has no dependency - * to dev_stream. Starts APM in dev_stream's constructor just to - * align with its life cycle, and then gets the post processing - * format to configure format converter. + * like AEC. Use the post processing format to configure format + * converter. */ - cras_apm_list_start_apm(stream->apm_list, dev_ptr); ofmt = cras_rstream_post_processing_format(stream, dev_ptr) ?: dev_fmt, rc = config_format_converter(&out->conv, stream->direction, @@ -123,18 +119,10 @@ struct dev_stream *dev_stream_create(struct cras_rstream *stream, out->conv_buffer = byte_buffer_create(buf_bytes); out->conv_area = cras_audio_area_create(ofmt->num_channels); - /* Use sleep interval hint from argument if it is provided */ - if (sleep_interval_ts) { - stream->sleep_interval_ts = *sleep_interval_ts; - } else { - cras_frames_to_time(cras_rstream_get_cb_threshold(stream), - stream_fmt->frame_rate, - &stream->sleep_interval_ts); - } - + cras_frames_to_time(cras_rstream_get_cb_threshold(stream), + stream_fmt->frame_rate, &stream->sleep_interval_ts); stream->next_cb_ts = *cb_ts; - /* Sets up the stream & dev pair. */ cras_rstream_dev_attach(stream, dev_id, dev_ptr); return out; @@ -142,10 +130,6 @@ struct dev_stream *dev_stream_create(struct cras_rstream *stream, void dev_stream_destroy(struct dev_stream *dev_stream) { - void *dev_ptr = - cras_rstream_dev_ptr(dev_stream->stream, dev_stream->dev_id); - /* Stops the APM and then unlink the dev stream pair. */ - cras_apm_list_stop_apm(dev_stream->stream->apm_list, dev_ptr); cras_rstream_dev_detach(dev_stream->stream, dev_stream->dev_id); if (dev_stream->conv) { cras_audio_area_destroy(dev_stream->conv_area); @@ -157,9 +141,9 @@ void dev_stream_destroy(struct dev_stream *dev_stream) void dev_stream_set_dev_rate(struct dev_stream *dev_stream, unsigned int dev_rate, double dev_rate_ratio, - double main_rate_ratio, int coarse_rate_adjust) + double master_rate_ratio, int coarse_rate_adjust) { - if (dev_stream->dev_id == dev_stream->stream->main_dev.dev_id) { + if (dev_stream->dev_id == dev_stream->stream->master_dev.dev_id) { cras_fmt_conv_set_linear_resample_rates(dev_stream->conv, dev_rate, dev_rate); cras_frames_to_time_precise( @@ -167,8 +151,9 @@ void dev_stream_set_dev_rate(struct dev_stream *dev_stream, dev_stream->stream->format.frame_rate * dev_rate_ratio, &dev_stream->stream->sleep_interval_ts); } else { - double new_rate = dev_rate * dev_rate_ratio / main_rate_ratio + - coarse_rate_adjust_step * coarse_rate_adjust; + double new_rate = + dev_rate * dev_rate_ratio / master_rate_ratio + + coarse_rate_adjust_step * coarse_rate_adjust; cras_fmt_conv_set_linear_resample_rates(dev_stream->conv, dev_rate, new_rate); } @@ -268,8 +253,7 @@ static unsigned int capture_with_fmt_conv(struct dev_stream *dev_stream, total_read += read_frames; source_samples += read_frames * source_frame_bytes; buf_increment_write(dev_stream->conv_buffer, - (size_t)write_frames * - (size_t)dst_frame_bytes); + write_frames * dst_frame_bytes); } return total_read; @@ -327,7 +311,7 @@ capture_copy_converted_to_stream(struct dev_stream *dev_stream, software_gain_scaler); buf_increment_read(dev_stream->conv_buffer, - (size_t)write_frames * (size_t)frame_bytes); + write_frames * frame_bytes); total_written += write_frames; cras_rstream_dev_offset_update(rstream, write_frames, dev_stream->dev_id); diff --git a/cras/src/server/dev_stream.h b/cras/src/server/dev_stream.h index 6b34d5d7..c39a8017 100644 --- a/cras/src/server/dev_stream.h +++ b/cras/src/server/dev_stream.h @@ -46,47 +46,30 @@ struct dev_stream { int is_running; }; -/* - * Creates a dev_stream. - * - * Args: - * stream - The associated rstream. - * dev_id - Index of the device. - * dev_fmt - The format of the device. - * dev_ptr - A pointer to the device - * cb_ts - A pointer to the initial callback time. - * sleep_interval_ts - A pointer to the initial sleep interval. - * Set to null to calculate the value from device rate and block size. - * Note that we need this argument so that output device sleep interval - * can use input device sleep interval in the beginning to have perfect - * alignment in WebRTC use case. - * Returns the pointer to the created dev_stream. - */ struct dev_stream *dev_stream_create(struct cras_rstream *stream, unsigned int dev_id, const struct cras_audio_format *dev_fmt, - void *dev_ptr, struct timespec *cb_ts, - const struct timespec *sleep_interval_ts); + void *dev_ptr, struct timespec *cb_ts); void dev_stream_destroy(struct dev_stream *dev_stream); /* * Update the estimated sample rate of the device. For multiple active * devices case, the linear resampler will be configured by the estimated - * rate ration of the main device and the current active device the + * rate ration of the master device and the current active device the * rstream attaches to. * * Args: * dev_stream - The structure holding the stream. * dev_rate - The sample rate device is using. * dev_rate_ratio - The ratio of estimated rate and used rate. - * main_rate_ratio - The ratio of estimated rate and used rate of - * main device. + * master_rate_ratio - The ratio of estimated rate and used rate of + * master device. * coarse_rate_adjust - The flag to indicate the direction device * sample rate should adjust to. */ void dev_stream_set_dev_rate(struct dev_stream *dev_stream, unsigned int dev_rate, double dev_rate_ratio, - double main_rate_ratio, int coarse_rate_adjust); + double master_rate_ratio, int coarse_rate_adjust); /* * Renders count frames from shm into dst. Updates count if anything is diff --git a/cras/src/server/ewma_power.c b/cras/src/server/ewma_power.c deleted file mode 100644 index 5270ef0e..00000000 --- a/cras/src/server/ewma_power.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "ewma_power.h" -#include "math.h" - -/* One sample per 1ms. */ -#define EWMA_SAMPLE_RATE 1000 - -/* Smooth factor for EWMA, 1 - expf(-1.0/(rate * 0.01)) - * where the 0.01 corresponds to 10ms interval that is chosen and - * being used in Chrome for a long time. - * Here the |rate| is set to the down sampled EWMA_SAMPLE_RATE and - * whenever it changes the calculated |smooth_factor| should be updated - * accordingly. - */ -const static float smooth_factor = 0.095; - -void ewma_power_disable(struct ewma_power *ewma) -{ - ewma->enabled = 0; -} - -void ewma_power_init(struct ewma_power *ewma, unsigned int rate) -{ - ewma->enabled = 1; - ewma->power_set = 0; - ewma->step_fr = rate / EWMA_SAMPLE_RATE; -} - -void ewma_power_calculate(struct ewma_power *ewma, const int16_t *buf, - unsigned int channels, unsigned int size) -{ - int i, ch; - float power, f; - - if (!ewma->enabled) - return; - for (i = 0; i < size; i += ewma->step_fr * channels) { - power = 0.0f; - for (ch = 0; ch < channels; ch++) { - f = buf[i + ch] / 32768.0f; - power += f * f / channels; - } - if (!ewma->power_set) { - ewma->power = power; - ewma->power_set = 1; - } else { - ewma->power = smooth_factor * power + - (1 - smooth_factor) * ewma->power; - } - } -} - -void ewma_power_calculate_area(struct ewma_power *ewma, const int16_t *buf, - struct cras_audio_area *area, unsigned int size) -{ - int i, ch; - float power, f; - - if (!ewma->enabled) - return; - for (i = 0; i < size; i += ewma->step_fr * area->num_channels) { - power = 0.0f; - for (ch = 0; ch < area->num_channels; ch++) { - if (area->channels[ch].ch_set == 0) - continue; - f = buf[i + ch] / 32768.0f; - power += f * f / area->num_channels; - } - if (!ewma->power_set) { - ewma->power = power; - ewma->power_set = 1; - } else { - ewma->power = smooth_factor * power + - (1 - smooth_factor) * ewma->power; - } - } -} diff --git a/cras/src/server/ewma_power.h b/cras/src/server/ewma_power.h deleted file mode 100644 index 78d2e504..00000000 --- a/cras/src/server/ewma_power.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef EWMA_POWER_H_ -#define EWMA_POWER_H_ - -#include <stdbool.h> -#include <stdint.h> - -#include "cras_audio_area.h" - -/* - * The exponentially weighted moving average power module used to - * calculate the energe level in audio stream. - * Members: - * power_set - Flag to note if the first power value has set. - * enabled - Flag to enable ewma calculation. Set to false to - * make all calculations no-ops. - * power - The power value. - * step_fr - How many frames to sample one for EWMA calculation. - */ -struct ewma_power { - bool power_set; - bool enabled; - float power; - unsigned int step_fr; -}; - -/* - * Disables the ewma instance. - */ -void ewma_power_disable(struct ewma_power *ewma); - -/* - * Initializes the ewma_power object. - * Args: - * ewma - The ewma_power object to initialize. - * rate - The sample rate of the audio data that the ewma object - * will calculate power from. - */ -void ewma_power_init(struct ewma_power *ewma, unsigned int rate); - -/* - * Feeds an audio buffer to ewma_power object to calculate the - * latest power value. - * Args: - * ewma - The ewma_power object to calculate power. - * buf - Pointer to the audio data. - * channels - Number of channels of the audio data. - * size - Length in frames of the audio data. - */ -void ewma_power_calculate(struct ewma_power *ewma, const int16_t *buf, - unsigned int channels, unsigned int size); - -/* - * Feeds non-interleaved audio data to ewma_power to calculate the - * latest power value. This is similar to ewma_power_calculate but - * accepts cras_audio_area. - */ -void ewma_power_calculate_area(struct ewma_power *ewma, const int16_t *buf, - struct cras_audio_area *area, unsigned int size); - -#endif /* EWMA_POWER_H_ */ diff --git a/cras/src/server/float_buffer.h b/cras/src/server/float_buffer.h index ba3523d9..39a0187d 100644 --- a/cras/src/server/float_buffer.h +++ b/cras/src/server/float_buffer.h @@ -37,7 +37,7 @@ float_buffer_create(unsigned int max_size, unsigned int num_channels) b->fp = (float **)malloc(num_channels * sizeof(float *)); b->buf = (struct byte_buffer *)calloc( 1, sizeof(struct byte_buffer) + - sizeof(float) * max_size * num_channels); + max_size * num_channels * sizeof(float)); b->buf->max_size = max_size; b->buf->used_size = max_size; return b; diff --git a/cras/src/server/iniparser_wrapper.h b/cras/src/server/iniparser_wrapper.h index 89a213bb..b6d32f97 100644 --- a/cras/src/server/iniparser_wrapper.h +++ b/cras/src/server/iniparser_wrapper.h @@ -5,19 +5,11 @@ #ifndef INIPARSER_WRAPPER_H_ #define INIPARSER_WRAPPER_H_ -#ifdef HAVE_INIPARSER_INIPARSER_H -#include <iniparser/iniparser.h> -#else #include <iniparser.h> -#endif #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> -/* Allocate 63 chars + 1 for null where declared. */ -#define MAX_INI_NAME_LENGTH 63 -#define MAX_INI_KEY_LENGTH 63 /* names like "output_source:output_0" */ - static inline dictionary *iniparser_load_wrapper(const char *ini_name) { struct stat st; diff --git a/cras/src/server/input_data.c b/cras/src/server/input_data.c index cc0f10ba..b52c1668 100644 --- a/cras/src/server/input_data.c +++ b/cras/src/server/input_data.c @@ -151,7 +151,7 @@ int input_data_get_for_stream(struct input_data *data, struct cras_apm *apm; int stream_offset = buffer_share_id_offset(offsets, stream->stream_id); - apm = cras_apm_list_get_active_apm(stream, data->dev_ptr); + apm = cras_apm_list_get(stream->apm_list, data->dev_ptr); if (apm == NULL) { /* * Case 1 and 2 from above example. @@ -165,7 +165,7 @@ int input_data_get_for_stream(struct input_data *data, apm_processed = cras_apm_list_process(apm, data->fbuffer, stream_offset); if (apm_processed < 0) { - cras_apm_list_remove_apm(stream->apm_list, apm); + cras_apm_list_remove(stream->apm_list, apm); return 0; } buffer_share_offset_update(offsets, stream->stream_id, @@ -182,7 +182,7 @@ int input_data_put_for_stream(struct input_data *data, struct buffer_share *offsets, unsigned int frames) { struct cras_apm *apm = - cras_apm_list_get_active_apm(stream, data->dev_ptr); + cras_apm_list_get(stream->apm_list, data->dev_ptr); if (apm) cras_apm_list_put_processed(apm, frames); @@ -191,20 +191,3 @@ int input_data_put_for_stream(struct input_data *data, return 0; } - -float input_data_get_software_gain_scaler(struct input_data *data, - float idev_sw_gain_scaler, - struct cras_rstream *stream) -{ - struct cras_apm *apm; - /* - * APM has more advanced gain control mechanism. If it is using tuned - * settings, give APM total control of the captured samples without - * additional gain scaler at all. - */ - apm = cras_apm_list_get_active_apm(stream, data->dev_ptr); - if (apm && cras_apm_list_get_use_tuned_settings(apm)) - return 1.0f; - - return idev_sw_gain_scaler * cras_rstream_get_volume_scaler(stream); -} diff --git a/cras/src/server/input_data.h b/cras/src/server/input_data.h index 7ac80be4..bb120b4f 100644 --- a/cras/src/server/input_data.h +++ b/cras/src/server/input_data.h @@ -75,21 +75,4 @@ int input_data_put_for_stream(struct input_data *data, struct buffer_share *offsets, unsigned int frames); -/* - * The software gain scaler of input path consist of two parts: - * (1) The device gain scaler used when lack of hardware gain control. - * Configured by the IntrinsicSensitivity label in alsa UCM config. - * (2) The gain scaler in cras_rstream set by app, for example the AGC - * module in Chrome. - * Args: - * data - The input data that holds pointer to APM instance. - * idev_sw_agin_scaler - The gain scaler configured on input iodev. - * stream - To provide stream layer software gain. - * Returns: - * 1.0 if tuned APM in use, otherwise |iodev gain| * |cras_rstream gain| - */ -float input_data_get_software_gain_scaler(struct input_data *data, - float idev_sw_gain_scaler, - struct cras_rstream *stream); - #endif /* INPUT_DATA_H_ */ diff --git a/cras/src/server/rate_estimator.c b/cras/src/server/rate_estimator.c new file mode 100644 index 00000000..4b1277e3 --- /dev/null +++ b/cras/src/server/rate_estimator.c @@ -0,0 +1,109 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "math.h" + +#include "cras_util.h" +#include "rate_estimator.h" + +/* The max rate skew that considered reasonable */ +#define MAX_RATE_SKEW 100 + +static void least_square_reset(struct least_square *lsq) +{ + memset(lsq, 0, sizeof(*lsq)); +} + +void least_square_add_sample(struct least_square *lsq, double x, double y) +{ + lsq->sum_x += x; + lsq->sum_y += y; + lsq->sum_xy += x * y; + lsq->sum_x2 += x * x; + lsq->num_samples++; +} + +double least_square_best_fit_slope(struct least_square *lsq) +{ + double num, denom; + num = lsq->num_samples * lsq->sum_xy - lsq->sum_x * lsq->sum_y; + denom = lsq->num_samples * lsq->sum_x2 - lsq->sum_x * lsq->sum_x; + return num / denom; +} + +void rate_estimator_destroy(struct rate_estimator *re) +{ + if (re) + free(re); +} + +struct rate_estimator *rate_estimator_create(unsigned int rate, + const struct timespec *window_size, + double smooth_factor) +{ + struct rate_estimator *re; + + re = (struct rate_estimator *)calloc(1, sizeof(*re)); + if (re == NULL) + return NULL; + + re->window_size = *window_size; + re->estimated_rate = rate; + re->smooth_factor = smooth_factor; + + return re; +} + +void rate_estimator_add_frames(struct rate_estimator *re, int fr) +{ + re->level_diff += fr; +} + +double rate_estimator_get_rate(struct rate_estimator *re) +{ + return re->estimated_rate; +} + +void rate_estimator_reset_rate(struct rate_estimator *re, unsigned int rate) +{ + re->estimated_rate = rate; + least_square_reset(&re->lsq); + re->window_start_ts.tv_sec = 0; + re->window_start_ts.tv_nsec = 0; + re->window_frames = 0; + re->level_diff = 0; + re->last_level = 0; +} + +int rate_estimator_check(struct rate_estimator *re, int level, + struct timespec *now) +{ + struct timespec td; + + if (re->window_start_ts.tv_sec == 0) { + re->window_start_ts = *now; + return 0; + } + + subtract_timespecs(now, &re->window_start_ts, &td); + re->window_frames += abs(re->last_level - level + re->level_diff); + re->level_diff = 0; + re->last_level = level; + + least_square_add_sample(&re->lsq, + td.tv_sec + (double)td.tv_nsec / 1000000000L, + re->window_frames); + if (timespec_after(&td, &re->window_size) && re->lsq.num_samples > 1) { + double rate = least_square_best_fit_slope(&re->lsq); + if (fabs(re->estimated_rate - rate) < MAX_RATE_SKEW) + re->estimated_rate = + rate * (1 - re->smooth_factor) + + re->smooth_factor * re->estimated_rate; + least_square_reset(&re->lsq); + re->window_start_ts = *now; + re->window_frames = 0; + return 1; + } + return 0; +} diff --git a/cras/src/server/rate_estimator.h b/cras/src/server/rate_estimator.h new file mode 100644 index 00000000..c9a5aff9 --- /dev/null +++ b/cras/src/server/rate_estimator.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef RATE_ESTIMATOR_H_ +#define RATE_ESTIMATOR_H_ + +#include <time.h> + +/* Hold information to calculate linear least square from + * several (x, y) samples. + */ +struct least_square { + double sum_x; + double sum_y; + double sum_xy; + double sum_x2; + int num_samples; +}; + +/* An estimator holding the required information to determine the actual frame + * rate of an audio device. + * Members: + * last_level - Buffer level of the audio device at last check time. + * level_diff - Number of frames written to or read from audio device since + * the last check time. Rate estimator will use this change plus the + * difference of buffer level to derive the number of frames audio + * device has actually processed. + * window_start_ts - The start time of the current window. + * window_size - The size of the window. + * window_frames - The number of frames accumulated in current window. + * lsq - The helper used to estimate sample rate. + */ +struct rate_estimator { + int last_level; + int level_diff; + struct timespec window_start_ts; + struct timespec window_size; + int window_frames; + struct least_square lsq; + double smooth_factor; + double estimated_rate; +}; + +/* Creates a rate estimator. + * Args: + * rate - The initial value to estimate rate from. + * window_size - The window size of the rate estimator. + * smooth_factor - The coefficient used to calculate moving average + * from old estimated rate values. + */ +struct rate_estimator *rate_estimator_create(unsigned int rate, + const struct timespec *window_size, + double smooth_factor); +/* Destroy a rate estimator. */ +void rate_estimator_destroy(struct rate_estimator *re); + +/* Adds additional frames transmitted to/from audio device. + * Args: + * re - The rate estimator. + * fr - The number of frames written to the device. For input, this should + * be negative to indicate how many samples were read. + */ +void rate_estimator_add_frames(struct rate_estimator *re, int fr); + +/* Checks the timestamp and buffer level difference since last check time, + * and use them as a new sample to update the estimated rate. + * Args: + * re - The rate estimator. + * level - The current buffer level of audio device. + * now - The time at which this function is called. + * Returns: + * True if the estimated rate is updated and window is reset, + * otherwise false. + */ +int rate_estimator_check(struct rate_estimator *re, int level, + struct timespec *now); + +/* Gets the estimated rate. */ +double rate_estimator_get_rate(struct rate_estimator *re); + +/* Resets the estimated rate. */ +void rate_estimator_reset_rate(struct rate_estimator *re, unsigned int rate); + +#endif /* RATE_ESTIMATOR_H_ */ diff --git a/cras/src/server/rust/.gitignore b/cras/src/server/rust/.gitignore deleted file mode 100644 index 2f7896d1..00000000 --- a/cras/src/server/rust/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target/ diff --git a/cras/src/server/rust/Cargo.toml b/cras/src/server/rust/Cargo.toml deleted file mode 100644 index afebda83..00000000 --- a/cras/src/server/rust/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "cras_rust" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" - -[lib] -path = "src/rate_estimator.rs" -crate-type = ["staticlib"] - -[dependencies] -libc = "0.2.44" - -[profile.release] -lto = true -panic = "abort" -overflow-checks = true diff --git a/cras/src/server/rust/binding_generator/Cargo.toml b/cras/src/server/rust/binding_generator/Cargo.toml deleted file mode 100644 index 1ec73483..00000000 --- a/cras/src/server/rust/binding_generator/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "binding_generator" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" - -[dependencies] -cbindgen = "*" diff --git a/cras/src/server/rust/binding_generator/src/main.rs b/cras/src/server/rust/binding_generator/src/main.rs deleted file mode 100644 index f7803968..00000000 --- a/cras/src/server/rust/binding_generator/src/main.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -extern crate cbindgen; - -use cbindgen::Builder; - -const HEADER: &str = "// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Generated from files in cras/src/server/rust/src in adhd."; - -fn main() { - Builder::new() - .with_src("../src/rate_estimator.rs") - .rename_item("RateEstimator", "rate_estimator") - .rename_item("timespec", "struct timespec") - .with_no_includes() - .with_sys_include("time.h") - .with_include_guard("RATE_ESTIMATOR_H_") - .with_language(cbindgen::Language::C) - .with_header(HEADER) - .generate() - .expect("Unable to generate bindings") - .write_to_file("../src/headers/rate_estimator.h"); -} diff --git a/cras/src/server/rust/src/headers/rate_estimator.h b/cras/src/server/rust/src/headers/rate_estimator.h deleted file mode 100644 index 3ac9cfa9..00000000 --- a/cras/src/server/rust/src/headers/rate_estimator.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Generated from files in cras/src/server/rust/src in adhd. - -#ifndef RATE_ESTIMATOR_H_ -#define RATE_ESTIMATOR_H_ - -#include <time.h> - -/** - * An estimator holding the required information to determine the actual frame - * rate of an audio device. - * - * # Members - * * `last_level` - Buffer level of the audio device at last check time. - * * `level_diff` - Number of frames written to or read from audio device - * since the last check time. Rate estimator will use this - * change plus the difference of buffer level to derive the - * number of frames audio device has actually processed. - * * `window_start` - The start time of the current window. - * * `window_size` - The size of the window. - * * `window_frames` - The number of frames accumulated in current window. - * * `lsq` - The helper used to estimate sample rate. - * * `smooth_factor` - A scaling factor used to average the previous and new - * rate estimates to ensure that estimates do not change - * too quickly. - * * `estimated_rate` - The estimated rate at which samples are consumed. - */ -typedef struct rate_estimator rate_estimator; - -/** - * # Safety - * - * To use this function safely, `re` must be a pointer returned from - * rate_estimator_create, or null. - */ -void rate_estimator_add_frames(rate_estimator *re, int frames); - -/** - * # Safety - * - * To use this function safely, `re` must be a pointer returned from - * rate_estimator_create, or null, and `now` must be a valid pointer to a - * timespec. - */ -int32_t rate_estimator_check(rate_estimator *re, int level, - const struct timespec *now); - -/** - * # Safety - * - * To use this function safely, `window_size` must be a valid pointer to a - * timespec. - */ -rate_estimator *rate_estimator_create(unsigned int rate, - const struct timespec *window_size, - double smooth_factor); - -/** - * # Safety - * - * To use this function safely, `re` must be a pointer returned from - * rate_estimator_create, or null. - */ -void rate_estimator_destroy(rate_estimator *re); - -/** - * # Safety - * - * To use this function safely, `re` must be a pointer returned from - * rate_estimator_create, or null. - */ -double rate_estimator_get_rate(const rate_estimator *re); - -/** - * # Safety - * - * To use this function safely, `re` must be a pointer returned from - * rate_estimator_create, or null. - */ -void rate_estimator_reset_rate(rate_estimator *re, unsigned int rate); - -#endif /* RATE_ESTIMATOR_H_ */ diff --git a/cras/src/server/rust/src/rate_estimator.rs b/cras/src/server/rust/src/rate_estimator.rs deleted file mode 100644 index 585f346b..00000000 --- a/cras/src/server/rust/src/rate_estimator.rs +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -pub mod rate_estimator_bindings; - -use std::error; -use std::fmt; -use std::time::Duration; - -#[derive(Debug)] -pub enum Error { - InvalidSmoothFactor(f64), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - InvalidSmoothFactor(sf) => write!(f, "Smooth factor {} is not between 0.0 and 1.0", sf), - } - } -} - -type Result<T> = std::result::Result<T, Error>; - -const MAX_RATE_SKEW: f64 = 100.0; - -/// Hold information to calculate linear least square from -/// several (x, y) samples. -#[derive(Debug, Default)] -struct LeastSquares { - sum_x: f64, - sum_y: f64, - sum_xy: f64, - sum_x2: f64, - num_samples: u32, -} - -impl LeastSquares { - fn new() -> Self { - Self::default() - } - - fn add_sample(&mut self, x: f64, y: f64) { - self.sum_x += x; - self.sum_y += y; - self.sum_xy += x * y; - self.sum_x2 += x * x; - self.num_samples += 1; - } - - fn best_fit_slope(&self) -> f64 { - let num = self.num_samples as f64 * self.sum_xy - self.sum_x * self.sum_y; - let den = self.num_samples as f64 * self.sum_x2 - self.sum_x * self.sum_x; - num / den - } -} - -/// An estimator holding the required information to determine the actual frame -/// rate of an audio device. -/// -/// # Members -/// * `last_level` - Buffer level of the audio device at last check time. -/// * `level_diff` - Number of frames written to or read from audio device -/// since the last check time. Rate estimator will use this -/// change plus the difference of buffer level to derive the -/// number of frames audio device has actually processed. -/// * `window_start` - The start time of the current window. -/// * `window_size` - The size of the window. -/// * `window_frames` - The number of frames accumulated in current window. -/// * `lsq` - The helper used to estimate sample rate. -/// * `smooth_factor` - A scaling factor used to average the previous and new -/// rate estimates to ensure that estimates do not change -/// too quickly. -/// * `estimated_rate` - The estimated rate at which samples are consumed. -pub struct RateEstimator { - last_level: i32, - level_diff: i32, - window_start: Option<Duration>, - window_size: Duration, - window_frames: u32, - lsq: LeastSquares, - smooth_factor: f64, - estimated_rate: f64, -} - -impl RateEstimator { - /// Creates a rate estimator. - /// - /// # Arguments - /// * `rate` - The initial value to estimate rate from. - /// * `window_size` - The window size of the rate estimator. - /// * `smooth_factor` - The coefficient used to calculate moving average - /// from old estimated rate values. Must be between - /// 0.0 and 1.0 - /// - /// # Errors - /// * If `smooth_factor` is not between 0.0 and 1.0 - pub fn try_new(rate: u32, window_size: Duration, smooth_factor: f64) -> Result<Self> { - if smooth_factor < 0.0 || smooth_factor > 1.0 { - return Err(Error::InvalidSmoothFactor(smooth_factor)); - } - - Ok(RateEstimator { - last_level: 0, - level_diff: 0, - window_start: None, - window_size, - window_frames: 0, - lsq: LeastSquares::new(), - smooth_factor, - estimated_rate: rate as f64, - }) - } - - /// Resets the estimated rate - /// - /// Reset the estimated rate to `rate`, and erase all collected data. - pub fn reset_rate(&mut self, rate: u32) { - self.last_level = 0; - self.level_diff = 0; - self.window_start = None; - self.window_frames = 0; - self.lsq = LeastSquares::new(); - self.estimated_rate = rate as f64; - } - - /// Adds additional frames transmitted to/from audio device. - /// - /// # Arguments - /// * `frames` - The number of frames written to the device. For input, - /// this should be negative to indicate how many samples - /// were read. - pub fn add_frames(&mut self, frames: i32) { - self.level_diff += frames; - } - - /// Gets the estimated rate. - pub fn get_estimated_rate(&self) -> f64 { - self.estimated_rate - } - - /// Check the timestamp and buffer level difference since last check time, - /// and use them as a new sample to update the estimated rate. - /// - /// # Arguments - /// * `level` - The current buffer level of audio device. - /// * `now` - The time at which this function is called. - /// - /// # Returns - /// True if the estimated rate is updated and window is reset, - /// otherwise false. - pub fn update_estimated_rate(&mut self, level: i32, now: Duration) -> bool { - let start = match self.window_start { - None => { - self.window_start = Some(now); - return false; - } - Some(t) => t, - }; - - let delta = match now.checked_sub(start) { - Some(d) => d, - None => return false, - }; - self.window_frames += (self.last_level - level + self.level_diff).abs() as u32; - self.level_diff = 0; - self.last_level = level; - - let secs = (delta.as_secs() as f64) + delta.subsec_nanos() as f64 / 1_000_000_000.0; - self.lsq.add_sample(secs, self.window_frames as f64); - if delta > self.window_size && self.lsq.num_samples > 1 { - let rate = self.lsq.best_fit_slope(); - if (self.estimated_rate - rate).abs() < MAX_RATE_SKEW { - self.estimated_rate = - rate * (1.0 - self.smooth_factor) + self.estimated_rate * self.smooth_factor; - } - self.lsq = LeastSquares::new(); - self.window_start = Some(now); - self.window_frames = 0; - return true; - } - false - } -} diff --git a/cras/src/server/rust/src/rate_estimator_bindings.rs b/cras/src/server/rust/src/rate_estimator_bindings.rs deleted file mode 100644 index 3073ba73..00000000 --- a/cras/src/server/rust/src/rate_estimator_bindings.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2019 The Chromium OS 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 std::time::Duration; - -use libc; - -use crate::RateEstimator; - -/// # Safety -/// -/// To use this function safely, `window_size` must be a valid pointer to a -/// timespec. -#[no_mangle] -pub unsafe extern "C" fn rate_estimator_create( - rate: libc::c_uint, - window_size: *const libc::timespec, - smooth_factor: libc::c_double, -) -> *mut RateEstimator { - if window_size.is_null() { - return std::ptr::null_mut::<RateEstimator>(); - } - - let ts = &*window_size; - let window = Duration::new(ts.tv_sec as u64, ts.tv_nsec as u32); - - match RateEstimator::try_new(rate, window, smooth_factor) { - Ok(re) => Box::into_raw(Box::new(re)), - Err(_) => std::ptr::null_mut::<RateEstimator>(), - } -} - -/// # Safety -/// -/// To use this function safely, `re` must be a pointer returned from -/// rate_estimator_create, or null. -#[no_mangle] -pub unsafe extern "C" fn rate_estimator_destroy(re: *mut RateEstimator) { - if re.is_null() { - return; - } - - drop(Box::from_raw(re)); -} - -/// # Safety -/// -/// To use this function safely, `re` must be a pointer returned from -/// rate_estimator_create, or null. -#[no_mangle] -pub unsafe extern "C" fn rate_estimator_add_frames(re: *mut RateEstimator, frames: libc::c_int) { - if re.is_null() { - return; - } - - (*re).add_frames(frames) -} - -/// # Safety -/// -/// To use this function safely, `re` must be a pointer returned from -/// rate_estimator_create, or null, and `now` must be a valid pointer to a -/// timespec. -#[no_mangle] -pub unsafe extern "C" fn rate_estimator_check( - re: *mut RateEstimator, - level: libc::c_int, - now: *const libc::timespec, -) -> i32 { - if re.is_null() || now.is_null() { - return 0; - } - - let ts = &*now; - if ts.tv_sec < 0 || ts.tv_nsec < 0 { - return 0; - } - let secs = ts.tv_sec as u64 + (ts.tv_nsec / 1_000_000_000) as u64; - let nsecs = (ts.tv_nsec % 1_000_000_000) as u32; - let now = Duration::new(secs, nsecs); - - (*re).update_estimated_rate(level, now) as i32 -} - -/// # Safety -/// -/// To use this function safely, `re` must be a pointer returned from -/// rate_estimator_create, or null. -#[no_mangle] -pub unsafe extern "C" fn rate_estimator_get_rate(re: *const RateEstimator) -> libc::c_double { - if re.is_null() { - return 0.0; - } - - (*re).get_estimated_rate() -} - -/// # Safety -/// -/// To use this function safely, `re` must be a pointer returned from -/// rate_estimator_create, or null. -#[no_mangle] -pub unsafe extern "C" fn rate_estimator_reset_rate(re: *mut RateEstimator, rate: libc::c_uint) { - if re.is_null() { - return; - } - - (*re).reset_rate(rate) -} diff --git a/cras/src/server/server_stream.c b/cras/src/server/server_stream.c index 36d5496e..cc16cd8c 100644 --- a/cras/src/server/server_stream.c +++ b/cras/src/server/server_stream.c @@ -16,6 +16,18 @@ static unsigned int server_stream_block_size = 480; /* + * Server stream doesn't care what format is used, because no + * client is reading data from stream. The main point is to + * make pinned device open and let data flow through its dsp + * pipeline. + */ +static struct cras_audio_format format = { + SND_PCM_FORMAT_S16_LE, + 48000, + 2, +}; + +/* * Information of a stream created by server. Currently only * one server stream is allowed, for echo reference use. */ @@ -33,12 +45,10 @@ static void server_stream_add_cb(void *data) stream_list_add(stream_list, stream_config, &stream); } -void server_stream_create(struct stream_list *stream_list, unsigned int dev_idx, - struct cras_audio_format *format) +void server_stream_create(struct stream_list *stream_list, unsigned int dev_idx) { int audio_fd = -1; int client_shm_fd = -1; - uint64_t buffer_offsets[2] = { 0, 0 }; if (stream_config) { syslog(LOG_ERR, "server stream already exists, dev %u", @@ -53,9 +63,9 @@ void server_stream_create(struct stream_list *stream_list, unsigned int dev_idx, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_SERVER_STREAM, CRAS_STREAM_INPUT, dev_idx, /*flags=*/SERVER_ONLY, - /*effects=*/0, format, server_stream_block_size, + /*effects=*/0, &format, server_stream_block_size, server_stream_block_size, &audio_fd, &client_shm_fd, - /*client_shm_size=*/0, buffer_offsets, stream_config); + /*client_shm_size=*/0, stream_config); /* Schedule add stream in next main thread loop. */ cras_system_add_task(server_stream_add_cb, stream_list); @@ -83,5 +93,6 @@ void server_stream_destroy(struct stream_list *stream_list, syslog(LOG_ERR, "No server stream to destroy"); return; } - server_stream_rm_cb(stream_list); + /* Schedule remove stream in next main thread loop. */ + cras_system_add_task(server_stream_rm_cb, stream_list); } diff --git a/cras/src/server/server_stream.h b/cras/src/server/server_stream.h index e1eb8e10..595987cb 100644 --- a/cras/src/server/server_stream.h +++ b/cras/src/server/server_stream.h @@ -14,8 +14,8 @@ struct stream_list; * stream_list - List of stream to add new server stream to. * dev_idx - The id of the device that new server stream will pin to. */ -void server_stream_create(struct stream_list *stream_list, unsigned int dev_idx, - struct cras_audio_format *format); +void server_stream_create(struct stream_list *stream_list, + unsigned int dev_idx); /* * Asynchronously destroys existing server stream pinned to device of given idx. diff --git a/cras/src/server/stream_list.c b/cras/src/server/stream_list.c index 04ef9fe1..d247ec89 100644 --- a/cras/src/server/stream_list.c +++ b/cras/src/server/stream_list.c @@ -3,19 +3,12 @@ * found in the LICENSE file. */ -#include <syslog.h> #include "cras_rstream.h" #include "cras_tm.h" #include "cras_types.h" #include "stream_list.h" #include "utlist.h" -/* - * If the time difference of two streams is short than 10s, they may be the RTC - * streams. - */ -static const struct timespec RTC_STREAM_THRESHOLD = { 10, 0 }; - struct stream_list { struct cras_rstream *streams; struct cras_rstream *streams_to_delete; @@ -88,19 +81,12 @@ int stream_list_add(struct stream_list *list, struct cras_rstream **stream) { int rc; - struct cras_rstream *next_stream; rc = list->stream_create_cb(stream_config, stream); if (rc) return rc; - /* Keep stream list in descending order by channel count. */ - DL_FOREACH (list->streams, next_stream) { - if ((*stream)->format.num_channels >= - next_stream->format.num_channels) - break; - } - DL_INSERT(list->streams, next_stream, *stream); + DL_APPEND(list->streams, *stream); rc = list->stream_added_cb(*stream); if (rc) { DL_DELETE(list->streams, *stream); @@ -161,28 +147,3 @@ bool stream_list_has_pinned_stream(struct stream_list *list, } return false; } - -void detect_rtc_stream_pair(struct stream_list *list, - struct cras_rstream *stream) -{ - struct cras_rstream *next_stream; - if (stream->cb_threshold != 480) - return; - if (stream->client_type != CRAS_CLIENT_TYPE_CHROME && - stream->client_type != CRAS_CLIENT_TYPE_LACROS) - return; - DL_FOREACH (list->streams, next_stream) { - if (next_stream->cb_threshold == 480 && - next_stream->direction != stream->direction && - next_stream->client_type == stream->client_type && - timespec_diff_shorter_than(&stream->start_ts, - &next_stream->start_ts, - &RTC_STREAM_THRESHOLD)) { - stream->stream_type = - CRAS_STREAM_TYPE_VOICE_COMMUNICATION; - next_stream->stream_type = - CRAS_STREAM_TYPE_VOICE_COMMUNICATION; - return; - } - } -} diff --git a/cras/src/server/stream_list.h b/cras/src/server/stream_list.h index a527bc97..ae77a333 100644 --- a/cras/src/server/stream_list.h +++ b/cras/src/server/stream_list.h @@ -30,8 +30,8 @@ void stream_list_destroy(struct stream_list *list); struct cras_rstream *stream_list_get(struct stream_list *list); -/* Creates a cras_rstream from cras_rstream_config and inserts the cras_rstream - * to stream_list in descending order by channel count. +/* Creates a cras_rstream from cras_rstreaem_config and adds the cras_rstream + * to stream_list. * * Args: * list - stream_list to add streams. @@ -55,14 +55,3 @@ int stream_list_rm_all_client_streams(struct stream_list *list, */ bool stream_list_has_pinned_stream(struct stream_list *list, unsigned int dev_idx); - -/* - * Detects whether there is a RTC stream pair based on these rules: - * 1. The cb_threshold is 480. - * 2. The direction of two streams are opposite. - * 3. Two streams are from the same client. (Chrome or LaCrOS) - * 4. The start time of two streams are close enough. (shorter than 1s) - * If all rules are passed, set the stream type to the voice communication. - */ -void detect_rtc_stream_pair(struct stream_list *list, - struct cras_rstream *stream); diff --git a/cras/src/server/test_iodev.c b/cras/src/server/test_iodev.c index cb7d5f3a..47ff3363 100644 --- a/cras/src/server/test_iodev.c +++ b/cras/src/server/test_iodev.c @@ -102,8 +102,7 @@ static int put_buffer(struct cras_iodev *iodev, unsigned frames) struct test_iodev *testio = (struct test_iodev *)iodev; /* Input */ - buf_increment_read(testio->audbuff, - (size_t)frames * (size_t)testio->fmt_bytes); + buf_increment_read(testio->audbuff, frames * testio->fmt_bytes); return 0; } @@ -195,13 +194,7 @@ struct cras_iodev *test_iodev_create(enum CRAS_STREAM_DIRECTION direction, iodev->put_buffer = put_buffer; iodev->update_active_node = update_active_node; - /* - * Record max supported channels into cras_iodev_info. - * The value is the max of test_supported_channel_counts. - */ - iodev->info.max_supported_channels = 1; - - /* Create an empty ionode */ + /* Create a dummy ionode */ node = (struct cras_ionode *)calloc(1, sizeof(*node)); node->dev = iodev; node->plugged = 1; @@ -211,7 +204,7 @@ struct cras_iodev *test_iodev_create(enum CRAS_STREAM_DIRECTION direction, node->type = CRAS_NODE_TYPE_UNKNOWN; node->volume = 100; node->software_volume_needed = 0; - node->ui_gain_scaler = 1.0f; + node->max_software_gain = 0; strcpy(node->name, "(default)"); cras_iodev_add_node(iodev, node); cras_iodev_set_active_node(iodev, node); @@ -242,9 +235,8 @@ unsigned int test_iodev_add_samples(struct test_iodev *testio, uint8_t *samples, write_ptr = buf_write_pointer_size(testio->audbuff, &avail); count = MIN(count, avail); - memcpy(write_ptr, samples, (size_t)count * (size_t)testio->fmt_bytes); - buf_increment_write(testio->audbuff, - (size_t)count * (size_t)testio->fmt_bytes); + memcpy(write_ptr, samples, count * testio->fmt_bytes); + buf_increment_write(testio->audbuff, count * testio->fmt_bytes); return count; } diff --git a/cras/src/tests/a2dp_info_unittest.cc b/cras/src/tests/a2dp_info_unittest.cc index eb082b0c..4858c460 100644 --- a/cras/src/tests/a2dp_info_unittest.cc +++ b/cras/src/tests/a2dp_info_unittest.cc @@ -80,7 +80,7 @@ TEST(A2dpInfoInit, DestroyA2dp) { ASSERT_EQ(1, get_sbc_codec_destroy_called()); } -TEST(A2dpInfoInit, ResetA2dp) { +TEST(A2dpInfoInit, DrainA2dp) { ResetStubData(); init_a2dp(&a2dp, &sbc); a2dp.a2dp_buf_used = 99; @@ -88,7 +88,7 @@ TEST(A2dpInfoInit, ResetA2dp) { a2dp.seq_num = 11; a2dp.frame_count = 12; - a2dp_reset(&a2dp); + a2dp_drain(&a2dp); ASSERT_EQ(a2dp.a2dp_buf_used, 13); ASSERT_EQ(a2dp.frame_count, 0); diff --git a/cras/src/tests/a2dp_iodev_unittest.cc b/cras/src/tests/a2dp_iodev_unittest.cc index 06c1cd3c..c85b9d67 100644 --- a/cras/src/tests/a2dp_iodev_unittest.cc +++ b/cras/src/tests/a2dp_iodev_unittest.cc @@ -7,10 +7,11 @@ #include <stdio.h> extern "C" { -#include "cras_a2dp_iodev.c" +#include "a2dp-codecs.h" #include "audio_thread.h" #include "audio_thread_log.h" +#include "cras_a2dp_iodev.h" #include "cras_audio_area.h" #include "cras_bt_transport.h" #include "cras_iodev.h" @@ -21,15 +22,12 @@ extern "C" { #define MAX_A2DP_ENCODE_CALLS 8 #define MAX_A2DP_WRITE_CALLS 4 -/* Fake the codec to encode (512/4) frames into 128 bytes. */ -#define FAKE_A2DP_CODE_SIZE 512 -#define FAKE_A2DP_FRAME_LENGTH 128 - static struct cras_bt_transport* fake_transport; static cras_audio_format format; static size_t cras_bt_device_append_iodev_called; static size_t cras_bt_device_rm_iodev_called; static size_t cras_iodev_add_node_called; +static int cras_iodev_frames_queued_called; static size_t cras_iodev_rm_node_called; static size_t cras_iodev_set_active_node_called; static size_t cras_bt_transport_acquire_called; @@ -38,28 +36,28 @@ static size_t cras_bt_transport_release_called; static size_t init_a2dp_called; static int init_a2dp_return_val; static size_t destroy_a2dp_called; -static size_t a2dp_reset_called; +static size_t drain_a2dp_called; +static size_t a2dp_block_size_called; +static size_t a2dp_queued_frames_val; static size_t cras_iodev_free_format_called; static size_t cras_iodev_free_resources_called; +static int pcm_buf_size_val[MAX_A2DP_ENCODE_CALLS]; +static unsigned int a2dp_encode_processed_bytes_val[MAX_A2DP_ENCODE_CALLS]; +static unsigned int a2dp_encode_index; static int a2dp_write_return_val[MAX_A2DP_WRITE_CALLS]; static unsigned int a2dp_write_index; -static int a2dp_encode_called; -static cras_audio_area* mock_audio_area; +static cras_audio_area* dummy_audio_area; static thread_callback write_callback; static void* write_callback_data; static const char* fake_device_name = "fake device name"; static const char* cras_bt_device_name_ret; static unsigned int cras_bt_transport_write_mtu_ret; -static int cras_iodev_fill_odev_zeros_called; -static unsigned int cras_iodev_fill_odev_zeros_frames; -static int audio_thread_config_events_callback_called; -static enum AUDIO_THREAD_EVENTS_CB_TRIGGER - audio_thread_config_events_callback_trigger; void ResetStubData() { cras_bt_device_append_iodev_called = 0; cras_bt_device_rm_iodev_called = 0; cras_iodev_add_node_called = 0; + cras_iodev_frames_queued_called = 0; cras_iodev_rm_node_called = 0; cras_iodev_set_active_node_called = 0; cras_bt_transport_acquire_called = 0; @@ -68,20 +66,22 @@ void ResetStubData() { init_a2dp_called = 0; init_a2dp_return_val = 0; destroy_a2dp_called = 0; - a2dp_reset_called = 0; + drain_a2dp_called = 0; + a2dp_block_size_called = 0; + a2dp_queued_frames_val = 0; cras_iodev_free_format_called = 0; cras_iodev_free_resources_called = 0; + memset(a2dp_encode_processed_bytes_val, 0, + sizeof(a2dp_encode_processed_bytes_val)); + a2dp_encode_index = 0; a2dp_write_index = 0; - a2dp_encode_called = 0; - /* Fake the MTU value. min_buffer_level will be derived from this value. */ - cras_bt_transport_write_mtu_ret = 950; - cras_iodev_fill_odev_zeros_called = 0; + cras_bt_transport_write_mtu_ret = 800; fake_transport = reinterpret_cast<struct cras_bt_transport*>(0x123); - if (!mock_audio_area) { - mock_audio_area = (cras_audio_area*)calloc( - 1, sizeof(*mock_audio_area) + sizeof(cras_channel_area) * 2); + if (!dummy_audio_area) { + dummy_audio_area = (cras_audio_area*)calloc( + 1, sizeof(*dummy_audio_area) + sizeof(cras_channel_area) * 2); } write_callback = NULL; @@ -102,14 +102,12 @@ class A2dpIodev : public testing::Test { protected: virtual void SetUp() { ResetStubData(); - time_now.tv_sec = 0; - time_now.tv_nsec = 0; atlog = (audio_thread_event_log*)calloc(1, sizeof(audio_thread_event_log)); } virtual void TearDown() { - free(mock_audio_area); - mock_audio_area = NULL; + free(dummy_audio_area); + dummy_audio_area = NULL; free(atlog); } }; @@ -169,14 +167,12 @@ TEST_F(A2dpIodev, OpenIodev) { iodev_set_format(iodev, &format); iodev->configure_dev(iodev); - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; ASSERT_EQ(1, cras_bt_transport_acquire_called); iodev->close_dev(iodev); ASSERT_EQ(1, cras_bt_transport_release_called); - ASSERT_EQ(1, a2dp_reset_called); + ASSERT_EQ(1, drain_a2dp_called); ASSERT_EQ(1, cras_iodev_free_format_called); a2dp_iodev_destroy(iodev); @@ -185,74 +181,58 @@ TEST_F(A2dpIodev, OpenIodev) { TEST_F(A2dpIodev, GetPutBuffer) { struct cras_iodev* iodev; struct cras_audio_area *area1, *area2, *area3; - uint8_t* last_buf_head; + uint8_t* area1_buf; unsigned frames; - struct timespec tstamp; - struct a2dp_io* a2dpio; iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; iodev_set_format(iodev, &format); iodev->configure_dev(iodev); ASSERT_NE(write_callback, (void*)NULL); - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; + frames = 256; + iodev->get_buffer(iodev, &area1, &frames); + ASSERT_EQ(256, frames); + ASSERT_EQ(256, area1->frames); + area1_buf = area1->channels[0].buf; - /* (950 - 13) / 128 * 512 / 4 */ - ASSERT_EQ(iodev->min_buffer_level, 896); + /* Test 100 frames(400 bytes) put and all processed. */ + a2dp_encode_processed_bytes_val[0] = 400; + a2dp_write_index = 0; + a2dp_write_return_val[0] = 400; + iodev->put_buffer(iodev, 100); + write_callback(write_callback_data); + // Start with 4k frames. + EXPECT_EQ(400, pcm_buf_size_val[0]); - frames = 1500; - iodev->get_buffer(iodev, &area1, &frames); - ASSERT_EQ(1500, frames); - ASSERT_EQ(1500, area1->frames); - last_buf_head = area1->channels[0].buf; - iodev->put_buffer(iodev, 1000); - /* 1000 frames takes 8 encode call, FAKE_A2DP_CODE_SIZE / 4 = 128 - * and 7 * 128 < 1000 < 8 * 128 - */ - EXPECT_EQ(8, a2dp_encode_called); - /* Expect flushed one block, leaving 1000 - 896 = 104 queued and - * next_flush_time has shifted. */ - EXPECT_EQ(1, a2dp_write_index); - EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp)); - EXPECT_GT(a2dpio->next_flush_time.tv_nsec, 0); - - /* Assert buffer possition shifted 1000 * 4 bytes */ - frames = 1000; iodev->get_buffer(iodev, &area2, &frames); - ASSERT_EQ(1000, frames); - ASSERT_EQ(1000, area2->frames); - ASSERT_EQ(4000, area2->channels[0].buf - last_buf_head); - last_buf_head = area2->channels[0].buf; + ASSERT_EQ(256, frames); + ASSERT_EQ(256, area2->frames); - iodev->put_buffer(iodev, 700); - EXPECT_EQ(804, iodev->frames_queued(iodev, &tstamp)); - /* Assert that even next_flush_time is not met, pcm data still processed. - * Expect to takes 7 more encode calls to process the 804 frames of data. - * and 6 * 128 < 804 < 7 * 128 + /* Assert buf2 points to the same position as buf1 */ + ASSERT_EQ(400, area2->channels[0].buf - area1_buf); + + /* Test 100 frames(400 bytes) put, only 360 bytes processed, + * 40 bytes left in pcm buffer. */ - EXPECT_EQ(15, a2dp_encode_called); - EXPECT_EQ(768, a2dpio->a2dp.samples); + a2dp_encode_index = 0; + a2dp_encode_processed_bytes_val[0] = 360; + a2dp_encode_processed_bytes_val[1] = 0; + a2dp_write_index = 0; + a2dp_write_return_val[0] = 360; + a2dp_write_return_val[1] = 0; + iodev->put_buffer(iodev, 100); + write_callback(write_callback_data); + EXPECT_EQ(400, pcm_buf_size_val[0]); + ASSERT_EQ(40, pcm_buf_size_val[1]); - time_now.tv_nsec = 25000000; - frames = 50; iodev->get_buffer(iodev, &area3, &frames); - ASSERT_EQ(50, frames); - /* Assert buffer possition shifted 700 * 4 bytes */ - EXPECT_EQ(2800, area3->channels[0].buf - last_buf_head); - - iodev->put_buffer(iodev, 50); - /* 804 + 50 = 854 queued, 768 of them are encoded. */ - EXPECT_EQ(854, iodev->frames_queued(iodev, &tstamp)); - EXPECT_EQ(768, a2dpio->a2dp.samples); - /* Expect one a2dp encode call was executed for the left un-encoded frames. - * 854 - 768 = 86 < 128 */ - EXPECT_EQ(16, a2dp_encode_called); - /* Even time now has passed next_flush_time, no a2dp write gets called - * because the number of encoded samples is not sufficient for a flush. */ - EXPECT_EQ(1, a2dp_write_index); + + /* Existing buffer not completed processed, assert new buffer starts from + * current write pointer. + */ + ASSERT_EQ(256, frames); + EXPECT_EQ(800, area3->channels[0].buf - area1_buf); iodev->close_dev(iodev); a2dp_iodev_destroy(iodev); @@ -263,260 +243,70 @@ TEST_F(A2dpIodev, FramesQueued) { struct cras_audio_area* area; struct timespec tstamp; unsigned frames; - struct a2dp_io* a2dpio; iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; iodev_set_format(iodev, &format); time_now.tv_sec = 0; time_now.tv_nsec = 0; iodev->configure_dev(iodev); ASSERT_NE(write_callback, (void*)NULL); - /* a2dp_block_size(mtu) / format_bytes - * (950 - 13) / 128 * 512 / 4 = 896 */ - EXPECT_EQ(896, a2dpio->write_block); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; frames = 256; iodev->get_buffer(iodev, &area, &frames); ASSERT_EQ(256, frames); ASSERT_EQ(256, area->frames); - /* Data less than write_block hence not written. */ + /* Put 100 frames, proccessed 400 bytes to a2dp buffer. + * Assume 200 bytes written out, queued 50 frames in a2dp buffer. + */ + a2dp_encode_processed_bytes_val[0] = 400; + a2dp_write_return_val[0] = 50; + a2dp_queued_frames_val = 50; + time_now.tv_sec = 0; + time_now.tv_nsec = 1000000; iodev->put_buffer(iodev, 200); + write_callback(write_callback_data); EXPECT_EQ(200, iodev->frames_queued(iodev, &tstamp)); EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec); EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec); - /* 200 + 800 - 896 = 104 */ - a2dp_write_return_val[0] = 0; - frames = 800; - iodev->get_buffer(iodev, &area, &frames); - iodev->put_buffer(iodev, 800); - EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp)); - - /* Some time has passed, same amount of frames are queued. */ - time_now.tv_nsec = 15000000; - write_callback(write_callback_data, POLLOUT); - EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp)); - - /* Put 900 more frames. next_flush_time not yet passed so expect - * total 900 + 104 = 1004 are queued. */ - frames = 900; - iodev->get_buffer(iodev, &area, &frames); - iodev->put_buffer(iodev, 900); - EXPECT_EQ(1004, iodev->frames_queued(iodev, &tstamp)); - - /* Time passes next_flush_time, 1004 + 300 - 896 = 408 */ - time_now.tv_nsec = 25000000; - frames = 300; - iodev->get_buffer(iodev, &area, &frames); - iodev->put_buffer(iodev, 300); - EXPECT_EQ(408, iodev->frames_queued(iodev, &tstamp)); - - iodev->close_dev(iodev); - a2dp_iodev_destroy(iodev); -} - -TEST_F(A2dpIodev, SleepTimeWithWriteThrottle) { - struct cras_iodev* iodev; - struct cras_audio_area* area; - unsigned frames; - unsigned int level; - unsigned long target; - struct timespec tstamp; - struct a2dp_io* a2dpio; - - iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; - - iodev_set_format(iodev, &format); - iodev->configure_dev(iodev); - ASSERT_NE(write_callback, (void*)NULL); - /* a2dp_block_size(mtu) / format_bytes - * 900 / 128 * 512 / 4 = 896 */ - EXPECT_EQ(896, a2dpio->write_block); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; - - /* Both time now and next_flush_time are at 0. Expect write_block of - * time to sleep */ - EXPECT_EQ(a2dpio->write_block, - iodev->frames_to_play_in_sleep(iodev, &level, &tstamp)); - - /* Fake that 1000 frames are put and one block got flushed. - * Expect next_wake_time be fast forward by one flush_period. */ - frames = 1000; - iodev->get_buffer(iodev, &area, &frames); - ASSERT_EQ(1000, frames); - ASSERT_EQ(1000, area->frames); - - /* Expect the first block be flushed at time 0. */ - time_now.tv_nsec = 0; - a2dp_write_return_val[0] = 0; - EXPECT_EQ(0, iodev->put_buffer(iodev, 1000)); - EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp)); /* 1000 - 896 */ - - /* Same amount of frames are queued after some time has passed. */ - time_now.tv_nsec = 10000000; - EXPECT_EQ(104, iodev->frames_queued(iodev, &tstamp)); - - /* Expect to sleep the time between now(10ms) and next_flush_time(~20.3ms). */ - frames = iodev->frames_to_play_in_sleep(iodev, &level, &tstamp); - target = - a2dpio->write_block - time_now.tv_nsec * format.frame_rate / 1000000000; - EXPECT_GE(frames + 1, target); - EXPECT_GE(target + 1, frames); - - /* Time now has passed the next flush time(~20.3ms), expect to return - * write_block of time to sleep. */ - time_now.tv_nsec = 25000000; - EXPECT_EQ(a2dpio->write_block, - iodev->frames_to_play_in_sleep(iodev, &level, &tstamp)); - - a2dp_write_return_val[1] = 0; - frames = 1000; - iodev->get_buffer(iodev, &area, &frames); - EXPECT_EQ(0, iodev->put_buffer(iodev, 1000)); - EXPECT_EQ(208, iodev->frames_queued(iodev, &tstamp)); /* 104 + 1000 - 896 */ - - /* Flush another write_block of data, next_wake_time fast forward by - * another flush_period. Expect to sleep the time between now(25ms) - * and next_flush_time(~40.6ms). */ - frames = iodev->frames_to_play_in_sleep(iodev, &level, &tstamp); - target = a2dpio->write_block * 2 - - time_now.tv_nsec * format.frame_rate / 1000000000; - EXPECT_GE(frames + 1, target); - EXPECT_GE(target + 1, frames); - - /* Put 1000 more frames, and make a fake failure to this flush. */ - time_now.tv_nsec = 45000000; - a2dp_write_return_val[2] = -EAGAIN; - frames = 1000; - iodev->get_buffer(iodev, &area, &frames); - EXPECT_EQ(0, iodev->put_buffer(iodev, 1000)); - - /* Last a2dp write call failed with -EAGAIN, time now(45ms) is after - * next_flush_time. Expect to return exact |write_block| equivalant - * of time to sleep. */ - EXPECT_EQ(1208, iodev->frames_queued(iodev, &tstamp)); /* 208 + 1000 */ - EXPECT_EQ(a2dpio->write_block, - iodev->frames_to_play_in_sleep(iodev, &level, &tstamp)); - - /* Fake the event that socket becomes writable so data continues to flush. - * next_flush_time fast forwards by another flush_period. */ - a2dp_write_return_val[3] = 0; - write_callback(write_callback_data, POLLOUT); - EXPECT_EQ(312, iodev->frames_queued(iodev, &tstamp)); /* 1208 - 896 */ - - /* Expect to sleep the time between now and next_flush_time(~60.9ms). */ - frames = iodev->frames_to_play_in_sleep(iodev, &level, &tstamp); - target = a2dpio->write_block * 3 - - time_now.tv_nsec * format.frame_rate / 1000000000; - EXPECT_GE(frames + 1, target); - EXPECT_GE(target + 1, frames); - - iodev->close_dev(iodev); - a2dp_iodev_destroy(iodev); -} - -TEST_F(A2dpIodev, EnableThreadCallbackAtBufferFull) { - struct cras_iodev* iodev; - struct cras_audio_area* area; - struct timespec tstamp; - unsigned frames; - struct a2dp_io* a2dpio; - - iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; - - iodev_set_format(iodev, &format); + /* After writing another 200 frames, check for correct buffer level. */ time_now.tv_sec = 0; - time_now.tv_nsec = 0; - iodev->configure_dev(iodev); - ASSERT_NE(write_callback, (void*)NULL); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; - - audio_thread_config_events_callback_called = 0; - a2dp_write_return_val[0] = 0; - frames = iodev->buffer_size; - iodev->get_buffer(iodev, &area, &frames); - EXPECT_LE(frames, iodev->buffer_size); - EXPECT_EQ(0, iodev->put_buffer(iodev, frames)); - EXPECT_EQ(1, a2dp_write_index); - EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec); - EXPECT_EQ(1, audio_thread_config_events_callback_called); - EXPECT_EQ(TRIGGER_NONE, audio_thread_config_events_callback_trigger); - - /* Fastfoward time 1ms, not yet reaches the next flush time. */ - time_now.tv_nsec = 1000000; - - /* Cram into iodev as much data as possible. Expect its buffer to - * be full because flush time does not yet met. */ - frames = iodev->buffer_size; - iodev->get_buffer(iodev, &area, &frames); - EXPECT_LE(frames, iodev->buffer_size); - EXPECT_EQ(0, iodev->put_buffer(iodev, frames)); - frames = iodev->frames_queued(iodev, &tstamp); - EXPECT_EQ(frames, iodev->buffer_size); - - /* Expect a2dp_write didn't get called in last get/put buffer. And - * audio thread callback has been enabled. */ - EXPECT_EQ(1, a2dp_write_index); - EXPECT_EQ(2, audio_thread_config_events_callback_called); - EXPECT_EQ(TRIGGER_WAKEUP, audio_thread_config_events_callback_trigger); - - iodev->close_dev(iodev); - a2dp_iodev_destroy(iodev); -} - -TEST_F(A2dpIodev, FlushAtLowBufferLevel) { - struct cras_iodev* iodev; - struct cras_audio_area* area; - struct timespec tstamp; - unsigned frames; - - iodev = a2dp_iodev_create(fake_transport); - - iodev_set_format(iodev, &format); - iodev->configure_dev(iodev); - ASSERT_NE(write_callback, (void*)NULL); - - /* (950 - 13)/ 128 * 512 / 4 */ - ASSERT_EQ(iodev->min_buffer_level, 896); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; - - frames = 1500; - iodev->get_buffer(iodev, &area, &frames); - ASSERT_EQ(1500, frames); - ASSERT_EQ(1500, area->frames); + time_now.tv_nsec = 2000000; + a2dp_encode_index = 0; + a2dp_write_index = 0; + a2dp_encode_processed_bytes_val[0] = 400; + write_callback(write_callback_data); + /* 1000000 nsec has passed, estimated queued frames adjusted by 44 */ + EXPECT_EQ(156, iodev->frames_queued(iodev, &tstamp)); + EXPECT_EQ(400, pcm_buf_size_val[0]); + EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec); + EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec); - /* - * Assert put_buffer shouldn't trigger the 2nd call to a2dp_encode() - * because buffer is low: 896 < 1500 < 896 * 2 - */ - a2dp_write_return_val[0] = 0; - EXPECT_EQ(0, iodev->put_buffer(iodev, 1500)); - EXPECT_EQ(1, a2dp_write_index); + /* Queued frames and new put buffer are all written */ + a2dp_encode_processed_bytes_val[0] = 400; + a2dp_encode_processed_bytes_val[1] = 0; + a2dp_encode_index = 0; + a2dp_write_return_val[0] = 400; + a2dp_write_return_val[1] = -EAGAIN; + a2dp_write_index = 0; - /* 1500 - 896 */ - time_now.tv_nsec = 25000000; - EXPECT_EQ(604, iodev->frames_queued(iodev, &tstamp)); + /* Add wnother 200 samples, get back to the original level. */ + time_now.tv_sec = 0; + time_now.tv_nsec = 50000000; + a2dp_encode_processed_bytes_val[0] = 600; + a2dp_queued_frames_val = 50; + iodev->put_buffer(iodev, 200); + EXPECT_EQ(800, pcm_buf_size_val[0]); + EXPECT_EQ(100, iodev->frames_queued(iodev, &tstamp)); EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec); EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec); iodev->close_dev(iodev); a2dp_iodev_destroy(iodev); } -TEST_F(A2dpIodev, HandleUnderrun) { +TEST_F(A2dpIodev, FlushAtLowBufferLevel) { struct cras_iodev* iodev; struct cras_audio_area* area; struct timespec tstamp; @@ -528,188 +318,74 @@ TEST_F(A2dpIodev, HandleUnderrun) { time_now.tv_sec = 0; time_now.tv_nsec = 0; iodev->configure_dev(iodev); - /* (950 - 13) / 128 * 512 / 4 */ - EXPECT_EQ(896, iodev->min_buffer_level); + ASSERT_NE(write_callback, (void*)NULL); - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; + ASSERT_EQ(iodev->min_buffer_level, 400); - frames = 300; + frames = 700; iodev->get_buffer(iodev, &area, &frames); - ASSERT_EQ(300, frames); - ASSERT_EQ(300, area->frames); - a2dp_write_return_val[0] = -EAGAIN; - - time_now.tv_nsec = 10000000; - iodev->put_buffer(iodev, 300); - - time_now.tv_nsec = 20000000; - EXPECT_EQ(300, iodev->frames_queued(iodev, &tstamp)); - - /* Frames queued below min_buffer_level, which is derived from transport MTU. - * Assert min_cb_level of zero frames are filled. */ - iodev->min_cb_level = 150; - iodev->output_underrun(iodev); - ASSERT_EQ(1, cras_iodev_fill_odev_zeros_called); - EXPECT_EQ(150, cras_iodev_fill_odev_zeros_frames); - - iodev->close_dev(iodev); - a2dp_iodev_destroy(iodev); -} + ASSERT_EQ(700, frames); + ASSERT_EQ(700, area->frames); -TEST_F(A2dpIodev, LeavingNoStreamStateWithSmallStreamDoesntUnderrun) { - struct cras_iodev* iodev; - struct cras_audio_area* area; - struct timespec tstamp; - unsigned frames; - struct a2dp_io* a2dpio; + /* First call to a2dp_encode() processed 800 bytes. */ + a2dp_encode_processed_bytes_val[0] = 800; + a2dp_encode_processed_bytes_val[1] = 0; + a2dp_write_return_val[0] = 200; - iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; - - iodev_set_format(iodev, &format); - time_now.tv_sec = 0; - time_now.tv_nsec = 0; - iodev->configure_dev(iodev); - ASSERT_NE(write_callback, (void*)NULL); - /* (950 - 13)/ 128 * 512 / 4 */ - ASSERT_EQ(896, iodev->min_buffer_level); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; + /* put_buffer shouldn't trigger the 2nd call to a2dp_encode() because + * buffer is low. Fake some data to make sure this test case will fail + * when a2dp_encode() called twice. + */ + a2dp_encode_processed_bytes_val[2] = 800; + a2dp_encode_processed_bytes_val[3] = 0; + a2dp_write_return_val[1] = -EAGAIN; - /* Put iodev in no_stream state. Verify it doesn't underrun after each - * call of no_stream ops. */ - a2dp_write_return_val[0] = 0; - iodev->no_stream(iodev, 1); - EXPECT_EQ(1, a2dp_write_index); - EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec); - frames = iodev->frames_queued(iodev, &tstamp); - EXPECT_LE(iodev->min_buffer_level, frames); + time_now.tv_nsec = 10000000; + iodev->put_buffer(iodev, 700); - /* Some time has passed and a small stream of 200 frames block is added. - * Verify leaving no_stream state doesn't underrun immediately. */ time_now.tv_nsec = 20000000; - iodev->no_stream(iodev, 1); - frames = 200; - iodev->get_buffer(iodev, &area, &frames); - iodev->put_buffer(iodev, 200); - frames = iodev->frames_queued(iodev, &tstamp); - EXPECT_LE(iodev->min_buffer_level, frames); - + EXPECT_EQ(500, iodev->frames_queued(iodev, &tstamp)); + EXPECT_EQ(tstamp.tv_sec, time_now.tv_sec); + EXPECT_EQ(tstamp.tv_nsec, time_now.tv_nsec); iodev->close_dev(iodev); a2dp_iodev_destroy(iodev); } -TEST_F(A2dpIodev, NoStreamStateFillZerosToTargetLevel) { +TEST_F(A2dpIodev, NoStreamState) { struct cras_iodev* iodev; struct cras_audio_area* area; struct timespec tstamp; unsigned frames; - struct a2dp_io* a2dpio; iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; - iodev_set_format(iodev, &format); time_now.tv_sec = 0; time_now.tv_nsec = 0; iodev->configure_dev(iodev); ASSERT_NE(write_callback, (void*)NULL); - /* (950 - 13)/ 128 * 512 / 4 */ - ASSERT_EQ(896, iodev->min_buffer_level); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; + ASSERT_EQ(400, iodev->min_buffer_level); iodev->min_cb_level = 480; frames = 200; iodev->get_buffer(iodev, &area, &frames); iodev->put_buffer(iodev, 200); - a2dp_write_return_val[0] = 0; - iodev->no_stream(iodev, 1); - EXPECT_EQ(1, a2dp_write_index); - EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec); - - /* Some time has passed but not yet reach next flush. Entering no_stream - * fills buffer to 3 times of min_buffer_level. */ - time_now.tv_nsec = 10000000; iodev->no_stream(iodev, 1); - frames = iodev->frames_queued(iodev, &tstamp); - EXPECT_EQ(3 * iodev->min_buffer_level, frames); + EXPECT_EQ(1, cras_iodev_frames_queued_called); - /* Time has passed next flush time, expect one block is flushed. */ - a2dp_write_return_val[1] = 0; - time_now.tv_nsec = 25000000; - iodev->no_stream(iodev, 1); + /* no_stream will fill the buffer to hw_level = (441 (44100 * 0.01)) * 2 + * frames, but 200 < min_buffer_level so cras_iodev_frames_queued will return + * 0 in no_stream and no_stream will fill 882 frames to device buffer. + */ frames = iodev->frames_queued(iodev, &tstamp); - ASSERT_EQ(2 * iodev->min_buffer_level, frames); - EXPECT_EQ(2, a2dp_write_index); + ASSERT_EQ(1082, frames); - /* Leaving no_stream state fills buffer level back to 2 * min_buffer_level. - */ - a2dp_write_return_val[2] = 0; - time_now.tv_nsec = 30000000; + /* After leaving no stream state, output buffer won't be adjusted */ iodev->no_stream(iodev, 0); frames = iodev->frames_queued(iodev, &tstamp); - ASSERT_EQ(2 * iodev->min_buffer_level, frames); - EXPECT_EQ(2, a2dp_write_index); - - iodev->close_dev(iodev); - a2dp_iodev_destroy(iodev); + ASSERT_EQ(1082, frames); } -TEST_F(A2dpIodev, EnterNoStreamStateAtHighBufferLevelDoesntFillMore) { - struct cras_iodev* iodev; - struct cras_audio_area* area; - struct timespec tstamp; - unsigned frames, start_level; - struct a2dp_io* a2dpio; - - iodev = a2dp_iodev_create(fake_transport); - a2dpio = (struct a2dp_io*)iodev; - - iodev_set_format(iodev, &format); - time_now.tv_sec = 0; - time_now.tv_nsec = 0; - iodev->configure_dev(iodev); - ASSERT_NE(write_callback, (void*)NULL); - /* (950 - 13)/ 128 * 512 / 4 */ - ASSERT_EQ(896, iodev->min_buffer_level); - - iodev->start(iodev); - iodev->state = CRAS_IODEV_STATE_NORMAL_RUN; - - a2dp_write_return_val[0] = 0; - start_level = 6000; - frames = start_level; - iodev->get_buffer(iodev, &area, &frames); - iodev->put_buffer(iodev, frames); - frames = iodev->frames_queued(iodev, &tstamp); - /* Assert one block has fluxhed */ - EXPECT_EQ(start_level - iodev->min_buffer_level, frames); - EXPECT_EQ(1, a2dp_write_index); - EXPECT_EQ(a2dpio->flush_period.tv_nsec, a2dpio->next_flush_time.tv_nsec); - - a2dp_write_return_val[1] = 0; - time_now.tv_nsec = 25000000; - iodev->no_stream(iodev, 1); - frames = iodev->frames_queued(iodev, &tstamp); - /* Next flush time meets requirement so another block is flushed. */ - ASSERT_EQ(start_level - 2 * iodev->min_buffer_level, frames); - - a2dp_write_return_val[2] = 0; - time_now.tv_nsec = 50000000; - iodev->no_stream(iodev, 1); - frames = iodev->frames_queued(iodev, &tstamp); - /* Another block flushed at leaving no stream state. No more data - * filled because level is high. */ - ASSERT_EQ(start_level - 3 * iodev->min_buffer_level, frames); - - iodev->close_dev(iodev); - a2dp_iodev_destroy(iodev); -} } // namespace int main(int argc, char** argv) { @@ -722,7 +398,6 @@ extern "C" { int cras_bt_transport_configuration(const struct cras_bt_transport* transport, void* configuration, int len) { - memset(configuration, 0, len); cras_bt_transport_configuration_called++; return 0; } @@ -803,10 +478,6 @@ const char* cras_bt_device_object_path(const struct cras_bt_device* device) { return "/org/bluez/hci0/dev_1A_2B_3C_4D_5E_6F"; } -int cras_bt_device_get_stable_id(const struct cras_bt_device* device) { - return 123; -} - void cras_bt_device_append_iodev(struct cras_bt_device* device, struct cras_iodev* iodev, enum cras_bt_device_profile profile) { @@ -826,18 +497,13 @@ int cras_bt_device_cancel_suspend(struct cras_bt_device* device) { return 0; } -int cras_bt_device_schedule_suspend( - struct cras_bt_device* device, - unsigned int msec, - enum cras_bt_device_suspend_reason suspend_reason) { +int cras_bt_device_schedule_suspend(struct cras_bt_device* device, + unsigned int msec) { return 0; } int init_a2dp(struct a2dp_info* a2dp, a2dp_sbc_t* sbc) { init_a2dp_called++; - memset(a2dp, 0, sizeof(*a2dp)); - a2dp->frame_length = FAKE_A2DP_FRAME_LENGTH; - a2dp->codesize = FAKE_A2DP_CODE_SIZE; return init_a2dp_return_val; } @@ -846,20 +512,22 @@ void destroy_a2dp(struct a2dp_info* a2dp) { } int a2dp_codesize(struct a2dp_info* a2dp) { - return a2dp->codesize; + return 512; } int a2dp_block_size(struct a2dp_info* a2dp, int encoded_bytes) { - return encoded_bytes / a2dp->frame_length * a2dp->codesize; + a2dp_block_size_called++; + + // Assumes a2dp block size is 1:1 before/after encode. + return encoded_bytes; } -int a2dp_queued_frames(const struct a2dp_info* a2dp) { - return a2dp->samples; +int a2dp_queued_frames(struct a2dp_info* a2dp) { + return a2dp_queued_frames_val; } -void a2dp_reset(struct a2dp_info* a2dp) { - a2dp_reset_called++; - a2dp->samples = 0; +void a2dp_drain(struct a2dp_info* a2dp) { + drain_a2dp_called++; } int a2dp_encode(struct a2dp_info* a2dp, @@ -867,34 +535,19 @@ int a2dp_encode(struct a2dp_info* a2dp, int pcm_buf_size, int format_bytes, size_t link_mtu) { - int processed = 0; - a2dp_encode_called++; + unsigned int processed; - if (a2dp->a2dp_buf_used + a2dp->frame_length > link_mtu) - return 0; - if (pcm_buf_size < a2dp->codesize) + if (a2dp_encode_index == MAX_A2DP_ENCODE_CALLS) return 0; - - processed += a2dp->codesize; - a2dp->a2dp_buf_used += a2dp->frame_length; - a2dp->samples += processed / format_bytes; - + processed = a2dp_encode_processed_bytes_val[a2dp_encode_index]; + pcm_buf_size_val[a2dp_encode_index] = pcm_buf_size; + a2dp_encode_index++; return processed; } int a2dp_write(struct a2dp_info* a2dp, int stream_fd, size_t link_mtu) { - int ret, samples; - if (a2dp->frame_length + a2dp->a2dp_buf_used < link_mtu) - return 0; - - ret = a2dp_write_return_val[a2dp_write_index++]; - if (ret < 0) - return ret; - - samples = a2dp->samples; - a2dp->samples = 0; - a2dp->a2dp_buf_used = 0; - return samples; + return a2dp_write_return_val[a2dp_write_index++]; + ; } int clock_gettime(clockid_t clk_id, struct timespec* tp) { @@ -903,40 +556,38 @@ int clock_gettime(clockid_t clk_id, struct timespec* tp) { } void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) { - iodev->area = mock_audio_area; + iodev->area = dummy_audio_area; } void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} -int cras_iodev_fill_odev_zeros(struct cras_iodev* odev, unsigned int frames) { - struct cras_audio_area* area; - cras_iodev_fill_odev_zeros_called++; - cras_iodev_fill_odev_zeros_frames = frames; +int cras_iodev_frames_queued(struct cras_iodev* iodev, + struct timespec* hw_tstamp) { + int rc; + cras_iodev_frames_queued_called++; + rc = iodev->frames_queued(iodev, hw_tstamp); + if (rc < 0) + return 0; + unsigned int num_queued = (unsigned int)rc; + if (num_queued < iodev->min_buffer_level) + return 0; - odev->get_buffer(odev, &area, &frames); - odev->put_buffer(odev, frames); - return 0; + return num_queued - iodev->min_buffer_level; } void cras_audio_area_config_buf_pointers(struct cras_audio_area* area, const struct cras_audio_format* fmt, uint8_t* base_buffer) { - mock_audio_area->channels[0].buf = base_buffer; + dummy_audio_area->channels[0].buf = base_buffer; } struct audio_thread* cras_iodev_list_get_audio_thread() { return NULL; } -// From ewma_power -void ewma_power_disable(struct ewma_power* ewma) {} - // From audio_thread struct audio_thread_event_log* atlog; -void audio_thread_add_events_callback(int fd, - thread_callback cb, - void* data, - int events) { +void audio_thread_add_write_callback(int fd, thread_callback cb, void* data) { write_callback = cb; write_callback_data = data; } @@ -945,18 +596,5 @@ int audio_thread_rm_callback_sync(struct audio_thread* thread, int fd) { return 0; } -void audio_thread_config_events_callback( - int fd, - enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger) { - audio_thread_config_events_callback_called++; - audio_thread_config_events_callback_trigger = trigger; -} -} - -int cras_audio_thread_event_a2dp_overrun() { - return 0; -} - -int cras_audio_thread_event_a2dp_throttle() { - return 0; +void audio_thread_enable_callback(int fd, int enabled) {} } diff --git a/cras/src/tests/alsa_card_unittest.cc b/cras/src/tests/alsa_card_unittest.cc index cfb67560..dd75b1d9 100644 --- a/cras/src/tests/alsa_card_unittest.cc +++ b/cras/src/tests/alsa_card_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include <gtest/gtest.h> +#include <iniparser.h> #include <stdio.h> #include <sys/param.h> #include <syslog.h> @@ -75,10 +76,9 @@ static std::vector<int> cras_system_rm_select_fd_values; static size_t snd_hctl_handle_events_called; static size_t iniparser_freedict_called; static size_t iniparser_load_called; -static struct cras_device_blocklist* fake_blocklist; -static int cras_device_blocklist_check_retval; +static struct cras_device_blacklist* fake_blacklist; +static int cras_device_blacklist_check_retval; static unsigned ucm_create_called; -static char ucm_create_name[100]; static unsigned ucm_destroy_called; static size_t ucm_get_dev_for_mixer_called; static size_t ucm_get_flag_called; @@ -96,8 +96,6 @@ static int cras_alsa_mixer_add_controls_in_section_return_value; static int cras_alsa_mixer_add_main_volume_control_by_name_called; static int cras_alsa_mixer_add_main_volume_control_by_name_return_value; static int ucm_get_echo_reference_dev_name_for_dev_called; -static size_t cras_system_check_ignore_ucm_suffix_called; -static bool cras_system_check_ignore_ucm_suffix_value; static const char* ucm_get_echo_reference_dev_name_for_dev_return_value[4]; static void ResetStubData() { @@ -147,10 +145,9 @@ static void ResetStubData() { cras_system_rm_select_fd_values.clear(); iniparser_freedict_called = 0; iniparser_load_called = 0; - fake_blocklist = reinterpret_cast<struct cras_device_blocklist*>(3); - cras_device_blocklist_check_retval = 0; + fake_blacklist = reinterpret_cast<struct cras_device_blacklist*>(3); + cras_device_blacklist_check_retval = 0; ucm_create_called = 0; - memset(ucm_create_name, 0, sizeof(ucm_get_flag_name)); ucm_destroy_called = 0; ucm_get_dev_for_mixer_called = 0; ucm_get_flag_called = 0; @@ -169,8 +166,6 @@ static void ResetStubData() { cras_alsa_mixer_add_main_volume_control_by_name_called = 0; cras_alsa_mixer_add_main_volume_control_by_name_return_value = 0; ucm_get_echo_reference_dev_name_for_dev_called = 0; - cras_system_check_ignore_ucm_suffix_called = 0; - cras_system_check_ignore_ucm_suffix_value = 0; fake_dev1.nodes = NULL; fake_dev2.nodes = NULL; fake_dev3.nodes = NULL; @@ -184,7 +179,7 @@ TEST(AlsaCard, CreateFailInvalidCard) { ResetStubData(); card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 55; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -199,7 +194,7 @@ TEST(AlsaCard, CreateFailMixerInit) { card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; cras_alsa_mixer_create_return = static_cast<struct cras_alsa_mixer*>(NULL); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -215,7 +210,7 @@ TEST(AlsaCard, CreateFailCtlOpen) { card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; snd_ctl_open_return = -1; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(1, snd_ctl_open_called); @@ -234,7 +229,7 @@ TEST(AlsaCard, CreateFailHctlOpen) { snd_hctl_open_pointer_val = NULL; snd_hctl_open_return_value = -1; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(1, snd_ctl_open_called); @@ -256,7 +251,7 @@ TEST(AlsaCard, CreateFailHctlLoad) { card_info.card_index = 0; snd_hctl_load_return_value = -1; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(1, snd_ctl_open_called); @@ -282,7 +277,7 @@ TEST(AlsaCard, AddSelectForHctlNoDevices) { snd_hctl_poll_descriptors_fds = poll_fds; snd_hctl_poll_descriptors_num_fds = ARRAY_SIZE(poll_fds); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(1, snd_ctl_open_called); @@ -317,7 +312,7 @@ TEST(AlsaCard, AddSelectForHctlWithDevices) { snd_hctl_poll_descriptors_fds = poll_fds; snd_hctl_poll_descriptors_num_fds = ARRAY_SIZE(poll_fds); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -349,7 +344,7 @@ TEST(AlsaCard, CreateFailCtlCardInfo) { card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; snd_ctl_card_info_ret = -1; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(1, snd_ctl_open_called); @@ -365,7 +360,7 @@ TEST(AlsaCard, CreateNoDevices) { ResetStubData(); card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 1; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -390,7 +385,7 @@ TEST(AlsaCard, CreateOneOutputNextDevError) { snd_ctl_pcm_next_device_return_error = true; card_info.card_type = ALSA_CARD_TYPE_USB; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called); @@ -411,7 +406,7 @@ TEST(AlsaCard, CreateOneOutput) { snd_ctl_pcm_info_rets = info_rets; card_info.card_type = ALSA_CARD_TYPE_USB; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -436,7 +431,7 @@ TEST(AlsaCard, CreateOneOutput) { EXPECT_EQ(iniparser_load_called, iniparser_freedict_called); } -TEST(AlsaCard, CreateOneOutputBlocklisted) { +TEST(AlsaCard, CreateOneOutputBlacklisted) { struct cras_alsa_card* c; int dev_nums[] = {0}; int info_rets[] = {0, -1}; @@ -448,10 +443,10 @@ TEST(AlsaCard, CreateOneOutputBlocklisted) { snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets); snd_ctl_pcm_info_rets = info_rets; alsa_iodev_has_hctl_jacks_return = 0; - cras_device_blocklist_check_retval = 1; + cras_device_blacklist_check_retval = 1; card_info.card_type = ALSA_CARD_TYPE_USB; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -481,7 +476,7 @@ TEST(AlsaCard, CreateTwoOutputs) { snd_ctl_pcm_info_rets = info_rets; card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -514,7 +509,7 @@ TEST(AlsaCard, CreateTwoDuplicateDeviceIndex) { snd_ctl_pcm_info_rets = info_rets; card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -547,7 +542,7 @@ TEST(AlsaCard, CreateOneInput) { snd_ctl_pcm_info_rets = info_rets; card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -579,7 +574,7 @@ TEST(AlsaCard, CreateOneInputAndOneOutput) { snd_ctl_pcm_info_rets = info_rets; card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -611,7 +606,7 @@ TEST(AlsaCard, CreateOneInputAndOneOutputTwoDevices) { snd_ctl_pcm_info_rets = info_rets; card_info.card_type = ALSA_CARD_TYPE_INTERNAL; card_info.card_index = 0; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -662,7 +657,7 @@ TEST(AlsaCard, CreateOneOutputWithCoupledMixers) { DL_APPEND(ucm_get_coupled_mixer_names_return_value, mixer_name_1); DL_APPEND(ucm_get_coupled_mixer_names_return_value, mixer_name_2); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); @@ -708,7 +703,7 @@ TEST(AlsaCard, CreateFullyUCMNoSections) { card_info.card_index = 0; ucm_has_fully_specified_ucm_flag_return_value = 1; ucm_get_sections_return_value = NULL; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); @@ -751,7 +746,7 @@ TEST(AlsaCard, CreateFullyUCMTwoMainVolume) { DL_APPEND(ucm_get_main_volume_names_return_value, mixer_name_1); DL_APPEND(ucm_get_main_volume_names_return_value, mixer_name_2); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); @@ -771,81 +766,34 @@ TEST(AlsaCard, CreateFullyUCMTwoMainVolume) { EXPECT_EQ(iniparser_load_called, iniparser_freedict_called); } -TEST(AlsaCard, TwoUCMSecionsDependentPCM) { - struct cras_alsa_card* c; - cras_alsa_card_info card_info; - struct ucm_section* sections = NULL; - struct ucm_section* section; - - /* Create UCM so that MIC1 and MIC2 will be two nodes on the same iodev. */ - section = ucm_section_create("MIC1", "hw:0,3", 0, -1, CRAS_STREAM_INPUT, - "my-sound-card Headset Jack", "gpio"); - DL_APPEND(sections, section); - section = ucm_section_create("MIC2", "hw:0,5", 0, 3, CRAS_STREAM_INPUT, - "my-sound-card Headset Jack", "gpio"); - DL_APPEND(sections, section); - - ResetStubData(); - int info_rets[] = {0, 0}; - card_info.card_type = ALSA_CARD_TYPE_INTERNAL; - card_info.card_index = 0; - snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets); - snd_ctl_pcm_info_rets = info_rets; - ucm_has_fully_specified_ucm_flag_return_value = 1; - ucm_get_sections_return_value = sections; - ASSERT_NE(ucm_get_sections_return_value, (struct ucm_section*)NULL); - - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, - NULL); - - EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); - EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called); - EXPECT_EQ(1, snd_ctl_card_info_called); - EXPECT_EQ(1, ucm_get_sections_called); - EXPECT_EQ(1, snd_ctl_pcm_info_called); - EXPECT_EQ(2, cras_alsa_mixer_add_controls_in_section_called); - EXPECT_EQ(1, cras_alsa_iodev_create_called); - EXPECT_EQ(2, cras_alsa_iodev_ucm_add_nodes_and_jacks_called); - EXPECT_EQ(1, cras_alsa_iodev_ucm_complete_init_called); - - cras_alsa_card_destroy(c); - EXPECT_EQ(1, ucm_destroy_called); - EXPECT_EQ(1, cras_alsa_iodev_destroy_called); - EXPECT_EQ(cras_alsa_iodev_create_return[0], cras_alsa_iodev_destroy_arg); - EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called); - EXPECT_EQ(iniparser_load_called, iniparser_freedict_called); -} - struct ucm_section* GenerateUcmSections(void) { struct ucm_section* sections = NULL; struct ucm_section* section; - section = ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, + section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, "my-sound-card Headset Jack", "gpio"); ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("Speaker", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - NULL, NULL); + section = ucm_section_create("Speaker", 0, CRAS_STREAM_OUTPUT, NULL, NULL); ucm_section_add_coupled(section, "SPK-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "SPK-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("Internal Mic", "hw:0,1", 0, -1, - CRAS_STREAM_INPUT, NULL, NULL); + section = + ucm_section_create("Internal Mic", 0, CRAS_STREAM_INPUT, NULL, NULL); ucm_section_add_coupled(section, "INT-MIC-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "INT-MIC-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("Mic", "hw:0,1", 1, -1, CRAS_STREAM_INPUT, + section = ucm_section_create("Mic", 1, CRAS_STREAM_INPUT, "my-sound-card Headset Jack", "gpio"); ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("HDMI", "hw:0,1", 2, -1, CRAS_STREAM_OUTPUT, - NULL, NULL); + section = ucm_section_create("HDMI", 2, CRAS_STREAM_OUTPUT, NULL, NULL); ucm_section_set_mixer_name(section, "HDMI"); DL_APPEND(sections, section); @@ -865,7 +813,7 @@ TEST(AlsaCard, CreateFullyUCMFailureOnControls) { cras_alsa_mixer_add_controls_in_section_return_value = -EINVAL; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c); @@ -902,7 +850,7 @@ TEST(AlsaCard, CreateFullyUCMFourDevicesFiveSections) { cras_alsa_iodev_index_return[cras_alsa_iodev_create_return[3]] = 2; ASSERT_NE(ucm_get_sections_return_value, (struct ucm_section*)NULL); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); @@ -949,7 +897,7 @@ TEST(AlsaCard, GG) { ucm_get_echo_reference_dev_name_for_dev_return_value[0] = strdup(echo_ref); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, + c = cras_alsa_card_create(&card_info, device_config_dir, fake_blacklist, NULL); EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c); @@ -957,45 +905,6 @@ TEST(AlsaCard, GG) { cras_alsa_card_destroy(c); } -TEST(AlsaCard, UCMSuffix) { - struct cras_alsa_card* c; - cras_alsa_card_info card_info; - int info_rets[] = {0, 0, 0, 0, 0, -1}; - - ResetStubData(); - card_info.card_type = ALSA_CARD_TYPE_INTERNAL; - card_info.card_index = 0; - snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets); - snd_ctl_pcm_info_rets = info_rets; - ucm_has_fully_specified_ucm_flag_return_value = 1; - ucm_get_sections_return_value = GenerateUcmSections(); - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, - "1mic"); - EXPECT_EQ(0, strcmp(ucm_create_name, "TestName.1mic")); - EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix_called); - cras_alsa_card_destroy(c); -} - -TEST(AlsaCard, UCMIgnoreSuffix) { - struct cras_alsa_card* c; - cras_alsa_card_info card_info; - int info_rets[] = {0, 0, 0, 0, 0, -1}; - - ResetStubData(); - card_info.card_type = ALSA_CARD_TYPE_INTERNAL; - card_info.card_index = 0; - snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets); - snd_ctl_pcm_info_rets = info_rets; - ucm_has_fully_specified_ucm_flag_return_value = 1; - ucm_get_sections_return_value = GenerateUcmSections(); - cras_system_check_ignore_ucm_suffix_value = true; - c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist, - "1mic"); - EXPECT_EQ(0, strcmp(ucm_create_name, "TestName")); - EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix_called); - cras_alsa_card_destroy(c); -} - /* Stubs */ extern "C" { @@ -1026,7 +935,6 @@ void cras_alsa_mixer_destroy(struct cras_alsa_mixer* cras_mixer) { struct cras_iodev* alsa_iodev_create(size_t card_index, const char* card_name, size_t device_index, - const char* pcm_name, const char* dev_name, const char* dev_id, enum CRAS_ALSA_CARD_TYPE card_type, @@ -1195,18 +1103,17 @@ struct cras_volume_curve* cras_card_config_get_volume_curve_for_control( return NULL; } -int cras_device_blocklist_check(struct cras_device_blocklist* blocklist, +int cras_device_blacklist_check(struct cras_device_blacklist* blacklist, unsigned vendor_id, unsigned product_id, unsigned device_index) { - EXPECT_EQ(fake_blocklist, blocklist); + EXPECT_EQ(fake_blacklist, blacklist); - return cras_device_blocklist_check_retval; + return cras_device_blacklist_check_retval; } struct cras_use_case_mgr* ucm_create(const char* name) { ucm_create_called++; - strncpy(ucm_create_name, name, sizeof(ucm_create_name) - 1); return reinterpret_cast<struct cras_use_case_mgr*>(0x44); } @@ -1264,11 +1171,6 @@ int cras_alsa_mixer_add_controls_in_section(struct cras_alsa_mixer* cmix, return cras_alsa_mixer_add_controls_in_section_return_value; } -bool cras_system_check_ignore_ucm_suffix(const char* card_name) { - cras_system_check_ignore_ucm_suffix_called++; - return cras_system_check_ignore_ucm_suffix_value; -} - void ucm_free_mixer_names(struct mixer_name* names) { struct mixer_name* m; DL_FOREACH (names, m) { diff --git a/cras/src/tests/alsa_helpers_unittest.cc b/cras/src/tests/alsa_helpers_unittest.cc index 32df30af..0e8112cd 100644 --- a/cras/src/tests/alsa_helpers_unittest.cc +++ b/cras/src/tests/alsa_helpers_unittest.cc @@ -163,12 +163,34 @@ TEST(AlsaHelper, MatchChannelMapCapability51) { } TEST(AlsaHelper, Htimestamp) { - snd_pcm_t* mock_handle = reinterpret_cast<snd_pcm_t*>(0x1); + snd_pcm_t* dummy_handle = reinterpret_cast<snd_pcm_t*>(0x1); snd_pcm_uframes_t used; snd_pcm_uframes_t severe_underrun_frames = 480; struct timespec tstamp; + int htimestamp_enabled = 1; const char* dev_name = "dev_name"; + // Enable htimestamp use. + ResetStubData(); + EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled)); + EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 1); + EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 1); + EXPECT_EQ(1, htimestamp_enabled); + + // Try to enable htimestamp use: not supported. + ResetStubData(); + snd_pcm_sw_params_ret_vals.push_back(-EINVAL); + EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled)); + EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 2); + EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 2); + EXPECT_EQ(0, htimestamp_enabled); + + // Disable htimestamp use. + ResetStubData(); + EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled)); + EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 0); + EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 0); + ResetStubData(); tstamp.tv_sec = 0; tstamp.tv_nsec = 0; @@ -176,7 +198,7 @@ TEST(AlsaHelper, Htimestamp) { snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 10; snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 10000; - cras_alsa_get_avail_frames(mock_handle, 48000, severe_underrun_frames, + cras_alsa_get_avail_frames(dummy_handle, 48000, severe_underrun_frames, dev_name, &used, &tstamp); EXPECT_EQ(used, snd_pcm_htimestamp_avail_ret_val); EXPECT_EQ(tstamp.tv_sec, snd_pcm_htimestamp_tstamp_ret_val.tv_sec); @@ -184,7 +206,7 @@ TEST(AlsaHelper, Htimestamp) { } TEST(AlsaHelper, GetAvailFramesSevereUnderrun) { - snd_pcm_t* mock_handle = reinterpret_cast<snd_pcm_t*>(0x1); + snd_pcm_t* dummy_handle = reinterpret_cast<snd_pcm_t*>(0x1); snd_pcm_uframes_t avail; snd_pcm_uframes_t severe_underrun_frames = 480; snd_pcm_uframes_t buffer_size = 48000; @@ -194,7 +216,7 @@ TEST(AlsaHelper, GetAvailFramesSevereUnderrun) { ResetStubData(); snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames + 1; - rc = cras_alsa_get_avail_frames(mock_handle, buffer_size, + rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size, severe_underrun_frames, dev_name, &avail, &tstamp); // Returns -EPIPE when severe underrun happens. @@ -202,7 +224,7 @@ TEST(AlsaHelper, GetAvailFramesSevereUnderrun) { ResetStubData(); snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames; - rc = cras_alsa_get_avail_frames(mock_handle, buffer_size, + rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size, severe_underrun_frames, dev_name, &avail, &tstamp); // Underrun which is not severe enough will be masked. @@ -212,7 +234,7 @@ TEST(AlsaHelper, GetAvailFramesSevereUnderrun) { ResetStubData(); snd_pcm_htimestamp_avail_ret_val = buffer_size - 1; - rc = cras_alsa_get_avail_frames(mock_handle, buffer_size, + rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size, severe_underrun_frames, dev_name, &avail, &tstamp); // When avail < buffer_size, there is no underrun. diff --git a/cras/src/tests/alsa_io_unittest.cc b/cras/src/tests/alsa_io_unittest.cc index 021b4789..2211f343 100644 --- a/cras/src/tests/alsa_io_unittest.cc +++ b/cras/src/tests/alsa_io_unittest.cc @@ -32,7 +32,6 @@ static int cras_alsa_start_called; static uint8_t* cras_alsa_mmap_begin_buffer; static size_t cras_alsa_mmap_begin_frames; static size_t cras_alsa_fill_properties_called; -static bool cras_alsa_support_8_channels; static size_t alsa_mixer_set_dBFS_called; static int alsa_mixer_set_dBFS_value; static const struct mixer_control* alsa_mixer_set_dBFS_output; @@ -50,6 +49,8 @@ static struct mixer_control* cras_alsa_mixer_get_control_for_section_return_value; static size_t sys_get_volume_called; static size_t sys_get_volume_return_value; +static size_t sys_get_capture_gain_called; +static long sys_get_capture_gain_return_value; static size_t alsa_mixer_set_mute_called; static int alsa_mixer_set_mute_value; static size_t alsa_mixer_get_dB_range_called; @@ -76,6 +77,7 @@ static std::vector<struct mixer_control*> static std::vector<int> cras_alsa_mixer_set_output_active_state_values; static cras_audio_format* fake_format; static size_t sys_set_volume_limits_called; +static size_t sys_set_capture_gain_limits_called; static size_t cras_alsa_mixer_get_minimum_capture_gain_called; static size_t cras_alsa_mixer_get_maximum_capture_gain_called; static struct mixer_control* cras_alsa_jack_get_mixer_output_ret; @@ -94,7 +96,6 @@ static int cras_alsa_jack_list_has_hctl_jacks_return_val; static jack_state_change_callback* cras_alsa_jack_list_create_cb; static void* cras_alsa_jack_list_create_cb_data; static char test_card_name[] = "TestCard"; -static char test_pcm_name[] = "TestPCM"; static char test_dev_name[] = "TestDev"; static char test_dev_id[] = "TestDevId"; static size_t cras_iodev_add_node_called; @@ -105,6 +106,8 @@ static unsigned cras_alsa_jack_enable_ucm_called; static unsigned ucm_set_enabled_called; static size_t cras_iodev_update_dsp_called; static const char* cras_iodev_update_dsp_name; +static size_t ucm_get_dsp_name_default_called; +static const char* ucm_get_dsp_name_default_value; typedef std::map<const char*, std::string> DspNameMap; static size_t ucm_get_dsp_name_for_dev_called; static DspNameMap ucm_get_dsp_name_for_dev_values; @@ -120,6 +123,13 @@ static const char* cras_alsa_jack_get_name_ret_value = 0; static char default_jack_name[] = "Something Jack"; static int auto_unplug_input_node_ret = 0; static int auto_unplug_output_node_ret = 0; +static int ucm_get_min_software_gain_called; +static int ucm_get_min_software_gain_ret_value; +static long ucm_get_min_software_gain_value; +static int ucm_get_max_software_gain_called; +static int ucm_get_max_software_gain_ret_value; +static long ucm_get_max_software_gain_value; +static long cras_system_set_capture_gain_limits_set_value[2]; static long cras_alsa_mixer_get_minimum_capture_gain_ret_value; static long cras_alsa_mixer_get_maximum_capture_gain_ret_value; static snd_pcm_state_t snd_pcm_state_ret; @@ -137,15 +147,14 @@ static int cras_iodev_frames_queued_ret; static int cras_iodev_buffer_avail_ret; static int cras_alsa_resume_appl_ptr_called; static int cras_alsa_resume_appl_ptr_ahead; +static int ucm_get_enable_htimestamp_flag_ret; static const struct cras_volume_curve* fake_get_dBFS_volume_curve_val; static int cras_iodev_dsp_set_swap_mode_for_node_called; static std::map<std::string, long> ucm_get_default_node_gain_values; -static std::map<std::string, long> ucm_get_intrinsic_sensitivity_values; static thread_callback audio_thread_cb; static void* audio_thread_cb_data; static int hotword_send_triggered_msg_called; static struct timespec clock_gettime_retspec; -static unsigned cras_iodev_reset_rate_estimator_called; void ResetStubData() { cras_alsa_open_called = 0; @@ -154,8 +163,8 @@ void ResetStubData() { cras_alsa_get_avail_frames_avail = 0; cras_alsa_start_called = 0; cras_alsa_fill_properties_called = 0; - cras_alsa_support_8_channels = false; sys_get_volume_called = 0; + sys_get_capture_gain_called = 0; alsa_mixer_set_dBFS_called = 0; alsa_mixer_set_capture_dBFS_called = 0; sys_get_mute_called = 0; @@ -174,6 +183,8 @@ void ResetStubData() { cras_alsa_mixer_set_output_active_state_outputs.clear(); cras_alsa_mixer_set_output_active_state_values.clear(); sys_set_volume_limits_called = 0; + sys_set_capture_gain_limits_called = 0; + sys_get_capture_gain_return_value = 0; cras_alsa_mixer_get_minimum_capture_gain_called = 0; cras_alsa_mixer_get_maximum_capture_gain_called = 0; cras_alsa_mixer_get_output_volume_curve_called = 0; @@ -193,6 +204,8 @@ void ResetStubData() { ucm_set_enabled_called = 0; cras_iodev_update_dsp_called = 0; cras_iodev_update_dsp_name = 0; + ucm_get_dsp_name_default_called = 0; + ucm_get_dsp_name_default_value = NULL; ucm_get_dsp_name_for_dev_called = 0; ucm_get_dsp_name_for_dev_values.clear(); cras_iodev_free_resources_called = 0; @@ -204,8 +217,16 @@ void ResetStubData() { cras_alsa_jack_get_name_called = 0; cras_alsa_jack_get_name_ret_value = default_jack_name; cras_alsa_jack_update_monitor_fake_name = 0; + ucm_get_min_software_gain_called = 0; + ucm_get_min_software_gain_ret_value = -1; + ucm_get_min_software_gain_value = 0; + ucm_get_max_software_gain_called = 0; + ucm_get_max_software_gain_ret_value = -1; + ucm_get_max_software_gain_value = 0; cras_card_config_get_volume_curve_for_control_called = 0; cras_card_config_get_volume_curve_vals.clear(); + cras_system_set_capture_gain_limits_set_value[0] = -1; + cras_system_set_capture_gain_limits_set_value[1] = -1; cras_alsa_mixer_get_minimum_capture_gain_ret_value = 0; cras_alsa_mixer_get_maximum_capture_gain_ret_value = 0; snd_pcm_state_ret = SND_PCM_STATE_RUNNING; @@ -219,11 +240,10 @@ void ResetStubData() { cras_iodev_buffer_avail_ret = 0; cras_alsa_resume_appl_ptr_called = 0; cras_alsa_resume_appl_ptr_ahead = 0; + ucm_get_enable_htimestamp_flag_ret = 0; fake_get_dBFS_volume_curve_val = NULL; cras_iodev_dsp_set_swap_mode_for_node_called = 0; ucm_get_default_node_gain_values.clear(); - ucm_get_intrinsic_sensitivity_values.clear(); - cras_iodev_reset_rate_estimator_called = 0; } static long fake_get_dBFS(const struct cras_volume_curve* curve, @@ -244,13 +264,13 @@ static struct cras_iodev* alsa_iodev_create_with_default_parameters( struct cras_card_config* config, struct cras_use_case_mgr* ucm, enum CRAS_STREAM_DIRECTION direction) { - return alsa_iodev_create(card_index, test_card_name, 0, test_pcm_name, - test_dev_name, dev_id, card_type, is_first, mixer, - config, ucm, fake_hctl, direction, 0, 0, - (char*)"123"); + return alsa_iodev_create(card_index, test_card_name, 0, test_dev_name, dev_id, + card_type, is_first, mixer, config, ucm, fake_hctl, + direction, 0, 0, (char*)"123"); } namespace { + TEST(AlsaIoInit, InitializeInvalidDirection) { struct alsa_io* aio; @@ -272,13 +292,12 @@ TEST(AlsaIoInit, InitializePlayback) { /* Get volume curve twice for iodev, and default node. */ EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); + EXPECT_EQ(0, cras_alsa_fill_properties_called); EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); EXPECT_EQ( 0, strncmp(test_card_name, aio->base.info.name, strlen(test_card_name))); - EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_EQ("", cras_iodev_update_dsp_name); + EXPECT_EQ(0, ucm_get_dsp_name_default_called); + EXPECT_EQ(NULL, cras_iodev_update_dsp_name); ASSERT_NE(reinterpret_cast<const char*>(NULL), aio->dev_name); EXPECT_EQ(0, strcmp(test_dev_name, aio->dev_name)); ASSERT_NE(reinterpret_cast<const char*>(NULL), aio->dev_id); @@ -362,11 +381,6 @@ TEST(AlsaIoInit, DefaultNodeUSBCard) { ASSERT_STREQ(DEFAULT, aio->base.active_node->name); ASSERT_EQ(1, aio->base.active_node->plugged); EXPECT_EQ(2, cras_iodev_set_node_plugged_called); - - /* No extra gain applied. */ - ASSERT_EQ(DEFAULT_CAPTURE_VOLUME_DBFS, - aio->base.active_node->intrinsic_sensitivity); - ASSERT_EQ(0, aio->base.active_node->capture_gain); alsa_iodev_destroy((struct cras_iodev*)aio); } @@ -380,8 +394,6 @@ TEST(AlsaIoInit, OpenPlayback) { 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, NULL, CRAS_STREAM_OUTPUT); ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - /* Call open_dev once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_open_called); EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); aio = (struct alsa_io*)iodev; format.frame_rate = 48000; @@ -392,9 +404,9 @@ TEST(AlsaIoInit, OpenPlayback) { aio->free_running = 1; aio->filled_zeros_for_draining = 512; iodev->open_dev(iodev); - EXPECT_EQ(2, cras_alsa_open_called); + EXPECT_EQ(1, cras_alsa_open_called); iodev->configure_dev(iodev); - EXPECT_EQ(2, cras_alsa_open_called); + EXPECT_EQ(1, cras_alsa_open_called); EXPECT_EQ(1, sys_set_volume_limits_called); EXPECT_EQ(1, alsa_mixer_set_dBFS_called); EXPECT_EQ(0, cras_alsa_start_called); @@ -471,25 +483,120 @@ TEST(AlsaIoInit, UsbCardUseSoftwareVolume) { alsa_iodev_destroy(iodev); } -TEST(AlsaIoInit, SoftwareGainIntrinsicSensitivity) { +TEST(AlsaIoInit, UseSoftwareGain) { struct cras_iodev* iodev; struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - long intrinsic_sensitivity = -2700; + /* MaxSoftwareGain is specified in UCM */ + ResetStubData(); + ucm_get_min_software_gain_ret_value = 1; + ucm_get_min_software_gain_value = 1; + ucm_get_max_software_gain_ret_value = 0; + ucm_get_max_software_gain_value = 2000; + iodev = alsa_iodev_create_with_default_parameters( + 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, + CRAS_STREAM_INPUT); + ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); + EXPECT_EQ(1, iodev->active_node->software_volume_needed); + EXPECT_EQ(DEFAULT_MIN_CAPTURE_GAIN, iodev->active_node->min_software_gain); + EXPECT_EQ(2000, iodev->active_node->max_software_gain); + ASSERT_EQ(1, sys_set_capture_gain_limits_called); + /* The gain range is [DEFAULT_MIN_CAPTURE_GAIN, maximum software gain]. */ + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[0], + DEFAULT_MIN_CAPTURE_GAIN); + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[1], 2000); + + alsa_iodev_destroy(iodev); + + /* MaxSoftwareGain and MinSoftwareGain are specified in UCM. */ ResetStubData(); + ucm_get_min_software_gain_ret_value = 0; + ucm_get_min_software_gain_value = 1000; + ucm_get_max_software_gain_ret_value = 0; + ucm_get_max_software_gain_value = 2000; + iodev = alsa_iodev_create_with_default_parameters( + 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, + CRAS_STREAM_INPUT); + ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); + EXPECT_EQ(1, iodev->active_node->software_volume_needed); + EXPECT_EQ(1000, iodev->active_node->min_software_gain); + EXPECT_EQ(2000, iodev->active_node->max_software_gain); + ASSERT_EQ(1, sys_set_capture_gain_limits_called); + /* The gain range is [minimum software gain, maximum software gain]. */ + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[0], 1000); + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[1], 2000); - // Set intrinsic sensitivity to -2700 * 0.01 dBFS/Pa. - ucm_get_intrinsic_sensitivity_values[INTERNAL_MICROPHONE] = - intrinsic_sensitivity; + alsa_iodev_destroy(iodev); + + /* MinSoftwareGain is larger than MaxSoftwareGain in UCM. */ + ResetStubData(); + ucm_get_min_software_gain_ret_value = 0; + ucm_get_min_software_gain_value = 3000; + ucm_get_max_software_gain_ret_value = 0; + ucm_get_max_software_gain_value = 2000; + iodev = alsa_iodev_create_with_default_parameters( + 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, + CRAS_STREAM_INPUT); + ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); + EXPECT_EQ(1, iodev->active_node->software_volume_needed); + EXPECT_EQ(DEFAULT_MIN_CAPTURE_GAIN, iodev->active_node->min_software_gain); + EXPECT_EQ(2000, iodev->active_node->max_software_gain); + ASSERT_EQ(1, sys_set_capture_gain_limits_called); + /* The gain range is [DEFAULT_MIN_CAPTURE_GAIN, maximum software gain]. */ + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[0], + DEFAULT_MIN_CAPTURE_GAIN); + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[1], 2000); + + alsa_iodev_destroy(iodev); + + /* MaxSoftwareGain is not specified in UCM. */ + ResetStubData(); + ucm_get_max_software_gain_ret_value = 1; + ucm_get_max_software_gain_value = 1; + cras_alsa_mixer_get_minimum_capture_gain_ret_value = -500; + cras_alsa_mixer_get_maximum_capture_gain_ret_value = 500; + iodev = alsa_iodev_create_with_default_parameters( + 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, + CRAS_STREAM_INPUT); + ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); + EXPECT_EQ(0, iodev->active_node->software_volume_needed); + EXPECT_EQ(0, iodev->active_node->max_software_gain); + ASSERT_EQ(1, sys_set_capture_gain_limits_called); + /* The gain range is reported by controls. */ + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[0], -500); + ASSERT_EQ(cras_system_set_capture_gain_limits_set_value[1], 500); + + alsa_iodev_destroy(iodev); +} + +TEST(AlsaIoInit, SoftwareGainWithDefaultNodeGain) { + struct cras_iodev* iodev; + struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; + long system_gain = 500; + long default_node_gain = -1000; + + ResetStubData(); + + // Use software gain. + ucm_get_max_software_gain_ret_value = 0; + ucm_get_max_software_gain_value = 2000; + + // Set default node gain to -1000 * 0.01 dB. + ucm_get_default_node_gain_values[INTERNAL_MICROPHONE] = default_node_gain; // Assume this is the first device so it gets internal mic node name. iodev = alsa_iodev_create_with_default_parameters( 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, CRAS_STREAM_INPUT); ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - ASSERT_EQ(intrinsic_sensitivity, iodev->active_node->intrinsic_sensitivity); - ASSERT_EQ(DEFAULT_CAPTURE_VOLUME_DBFS - intrinsic_sensitivity, - iodev->active_node->capture_gain); + + // Gain on node is 300 * 0.01 dB. + iodev->active_node->capture_gain = default_node_gain; + + // cras_iodev will call cras_iodev_adjust_active_node_gain to get gain for + // software gain. + ASSERT_EQ(system_gain + default_node_gain, + cras_iodev_adjust_active_node_gain(iodev, system_gain)); alsa_iodev_destroy(iodev); } @@ -506,8 +613,7 @@ TEST(AlsaIoInit, RouteBasedOnJackCallback) { ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); + EXPECT_EQ(0, cras_alsa_fill_properties_called); EXPECT_EQ(1, cras_alsa_mixer_list_outputs_called); EXPECT_EQ(1, cras_alsa_jack_list_create_called); EXPECT_EQ(1, cras_alsa_jack_list_find_jacks_by_name_matching_called); @@ -536,8 +642,7 @@ TEST(AlsaIoInit, RouteBasedOnInputJackCallback) { ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); + EXPECT_EQ(0, cras_alsa_fill_properties_called); EXPECT_EQ(1, cras_alsa_jack_list_create_called); EXPECT_EQ(1, cras_alsa_jack_list_find_jacks_by_name_matching_called); EXPECT_EQ(0, cras_alsa_jack_list_add_jack_for_section_called); @@ -564,8 +669,7 @@ TEST(AlsaIoInit, InitializeCapture) { ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); + EXPECT_EQ(0, cras_alsa_fill_properties_called); EXPECT_EQ(1, cras_alsa_mixer_list_inputs_called); alsa_iodev_destroy((struct cras_iodev*)aio); @@ -593,6 +697,8 @@ TEST(AlsaIoInit, OpenCapture) { EXPECT_EQ(1, cras_alsa_open_called); EXPECT_EQ(1, cras_alsa_mixer_get_minimum_capture_gain_called); EXPECT_EQ(1, cras_alsa_mixer_get_maximum_capture_gain_called); + EXPECT_EQ(1, sys_set_capture_gain_limits_called); + EXPECT_EQ(1, sys_get_capture_gain_called); EXPECT_EQ(1, alsa_mixer_set_capture_dBFS_called); EXPECT_EQ(1, sys_get_capture_mute_called); EXPECT_EQ(1, alsa_mixer_set_capture_mute_called); @@ -608,7 +714,8 @@ TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithDefaultNodeGain) { struct cras_iodev* iodev; struct cras_audio_format format; struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - long default_node_gain = 1000; + long system_gain = 2000; + long default_node_gain = -1000; ResetStubData(); // Set default node gain to -1000 * 0.01 dB. @@ -624,24 +731,15 @@ TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithDefaultNodeGain) { // Check the default node gain is the same as what specified in UCM. EXPECT_EQ(default_node_gain, iodev->active_node->capture_gain); - cras_alsa_mixer_get_minimum_capture_gain_ret_value = 0; - cras_alsa_mixer_get_maximum_capture_gain_ret_value = 2000; - - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - iodev->close_dev(iodev); - - // Hardware gain is in the hardware gain range and set to 1000 * 0.01 dB. - EXPECT_EQ(default_node_gain, alsa_mixer_set_capture_dBFS_value); - - // Check we do respect the hardware maximum capture gain. - cras_alsa_mixer_get_maximum_capture_gain_ret_value = 500; + // System gain is set to 2000 * 0.01 dB. + sys_get_capture_gain_return_value = system_gain; iodev->open_dev(iodev); iodev->configure_dev(iodev); iodev->close_dev(iodev); - EXPECT_EQ(500, alsa_mixer_set_capture_dBFS_value); + // Hardware gain is set to (2000 - 1000) * 0.01 dB. + EXPECT_EQ(system_gain + default_node_gain, alsa_mixer_set_capture_dBFS_value); alsa_iodev_destroy(iodev); free(fake_format); @@ -654,6 +752,8 @@ TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithSoftwareGain) { /* Meet the requirements of using software gain. */ ResetStubData(); + ucm_get_max_software_gain_ret_value = 0; + ucm_get_max_software_gain_value = 2000; iodev = alsa_iodev_create_with_default_parameters( 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, @@ -664,6 +764,9 @@ TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithSoftwareGain) { format.num_channels = 1; cras_iodev_set_format(iodev, &format); + /* System gain is set to 1000 * 0.01 dB */ + sys_get_capture_gain_return_value = 1000; + iodev->open_dev(iodev); iodev->configure_dev(iodev); iodev->close_dev(iodev); @@ -673,43 +776,12 @@ TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithSoftwareGain) { /* Test the case where software gain is not needed. */ iodev->active_node->software_volume_needed = 0; - iodev->active_node->capture_gain = 1000; iodev->open_dev(iodev); iodev->configure_dev(iodev); iodev->close_dev(iodev); - /* Hardware gain is set to 1000 * 0.01 dB as got from catpure_gain.*/ - EXPECT_EQ(0, alsa_mixer_set_capture_dBFS_value); - - alsa_iodev_destroy(iodev); - free(fake_format); -} - -TEST(AlsaIoInit, OpenCaptureSetCaptureGainWithDefaultUsbDevice) { - struct cras_iodev* iodev; - struct cras_audio_format format; - - iodev = alsa_iodev_create_with_default_parameters(0, NULL, ALSA_CARD_TYPE_USB, - 0, fake_mixer, fake_config, - NULL, CRAS_STREAM_INPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init(iodev)); - - format.frame_rate = 48000; - format.num_channels = 1; - cras_iodev_set_format(iodev, &format); - - iodev->active_node->intrinsic_sensitivity = DEFAULT_CAPTURE_VOLUME_DBFS; - iodev->active_node->capture_gain = 0; - - ResetStubData(); - iodev->open_dev(iodev); - iodev->configure_dev(iodev); - - EXPECT_EQ(1, sys_get_capture_mute_called); - EXPECT_EQ(1, alsa_mixer_set_capture_mute_called); - - /* Not change mixer controls for USB devices without UCM config. */ - EXPECT_EQ(0, alsa_mixer_set_capture_dBFS_called); + /* Hardware gain is set to 1000 * 0.01 dB as got from system capture gain.*/ + EXPECT_EQ(1000, alsa_mixer_set_capture_dBFS_value); alsa_iodev_destroy(iodev); free(fake_format); @@ -783,6 +855,7 @@ TEST(AlsaIoInit, DspNameDefault) { struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; ResetStubData(); + ucm_get_dsp_name_default_value = "hello"; aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, CRAS_STREAM_OUTPUT); @@ -790,17 +863,19 @@ TEST(AlsaIoInit, DspNameDefault) { EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); EXPECT_EQ(1, ucm_get_dsp_name_for_dev_called); - EXPECT_STREQ("", cras_iodev_update_dsp_name); + EXPECT_EQ(1, ucm_get_dsp_name_default_called); + EXPECT_STREQ("hello", cras_iodev_update_dsp_name); alsa_iodev_destroy((struct cras_iodev*)aio); } -TEST(AlsaIoInit, DspName) { +TEST(AlsaIoInit, DspNameWithoutDefault) { struct alsa_io* aio; struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; ResetStubData(); + ucm_get_dsp_name_default_value = NULL; ucm_get_dsp_name_for_dev_values[DEFAULT] = "hello"; aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, @@ -809,6 +884,7 @@ TEST(AlsaIoInit, DspName) { EXPECT_EQ(2, cras_card_config_get_volume_curve_for_control_called); EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); EXPECT_EQ(1, ucm_get_dsp_name_for_dev_called); + EXPECT_EQ(1, ucm_get_dsp_name_default_called); EXPECT_STREQ("hello", cras_iodev_update_dsp_name); alsa_iodev_destroy((struct cras_iodev*)aio); @@ -822,14 +898,16 @@ TEST(AlsaIoInit, DspNameJackOverride) { static const char* jack_name = "jack"; ResetStubData(); + ucm_get_dsp_name_default_value = "default_dsp"; aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( 0, NULL, ALSA_CARD_TYPE_INTERNAL, 0, fake_mixer, fake_config, fake_ucm, CRAS_STREAM_OUTPUT); ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); EXPECT_EQ(1, ucm_get_dsp_name_for_dev_called); + EXPECT_EQ(1, ucm_get_dsp_name_default_called); EXPECT_EQ(1, cras_iodev_update_dsp_called); - EXPECT_STREQ("", cras_iodev_update_dsp_name); + EXPECT_STREQ("default_dsp", cras_iodev_update_dsp_name); cras_alsa_jack_get_name_ret_value = jack_name; ucm_get_dsp_name_for_dev_values[jack_name] = "override_dsp"; @@ -837,6 +915,7 @@ TEST(AlsaIoInit, DspNameJackOverride) { cras_alsa_jack_list_create_cb(jack, 1, cras_alsa_jack_list_create_cb_data); EXPECT_EQ(2, cras_alsa_jack_get_name_called); EXPECT_EQ(2, ucm_get_dsp_name_for_dev_called); + EXPECT_EQ(1, ucm_get_dsp_name_default_called); // Mark the jack node as active. alsa_iodev_set_active_node(&aio->base, aio->base.nodes->next, 1); @@ -846,9 +925,10 @@ TEST(AlsaIoInit, DspNameJackOverride) { // Mark the default node as active. alsa_iodev_set_active_node(&aio->base, aio->base.nodes, 1); + EXPECT_EQ(1, ucm_get_dsp_name_default_called); EXPECT_EQ(2, ucm_get_dsp_name_for_dev_called); EXPECT_EQ(3, cras_iodev_update_dsp_called); - EXPECT_STREQ("", cras_iodev_update_dsp_name); + EXPECT_STREQ("default_dsp", cras_iodev_update_dsp_name); alsa_iodev_destroy((struct cras_iodev*)aio); } @@ -911,30 +991,6 @@ TEST(AlsaIoInit, SwapMode) { free(fake_node); } -TEST(AlsaIoInit, MaxSupportedChannels) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - int i; - - // i = 0: cras_alsa_support_8_channels is false, support 2 channels only. - // i = 1: cras_alsa_support_8_channels is true, support up to 8 channels. - for (i = 0; i < 2; i++) { - ResetStubData(); - cras_alsa_support_8_channels = (bool)i; - - aio = (struct alsa_io*)alsa_iodev_create_with_default_parameters( - 0, test_dev_id, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, - NULL, CRAS_STREAM_OUTPUT); - ASSERT_EQ(0, alsa_iodev_legacy_complete_init((struct cras_iodev*)aio)); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - uint32_t max_channels = (cras_alsa_support_8_channels) ? 8 : 2; - EXPECT_EQ(max_channels, aio->base.info.max_supported_channels); - alsa_iodev_destroy((struct cras_iodev*)aio); - EXPECT_EQ(1, cras_iodev_free_resources_called); - } -} - // Test that system settins aren't touched if no streams active. TEST(AlsaOutputNode, SystemSettingsWhenInactive) { int rc; @@ -1039,8 +1095,8 @@ TEST(AlsaOutputNode, TwoJacksHeadphoneLineout) { EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); // First node 'Headphone' - section = ucm_section_create(HEADPHONE, "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - "fake-jack", "gpio"); + section = + ucm_section_create(HEADPHONE, 0, CRAS_STREAM_OUTPUT, "fake-jack", "gpio"); ucm_section_set_mixer_name(section, HEADPHONE); cras_alsa_jack_list_add_jack_for_section_result_jack = reinterpret_cast<struct cras_alsa_jack*>(10); @@ -1050,8 +1106,8 @@ TEST(AlsaOutputNode, TwoJacksHeadphoneLineout) { ucm_section_free_list(section); // Second node 'Line Out' - section = ucm_section_create("Line Out", "hw:0.1", 0, -1, CRAS_STREAM_OUTPUT, - "fake-jack", "gpio"); + section = ucm_section_create("Line Out", 0, CRAS_STREAM_OUTPUT, "fake-jack", + "gpio"); ucm_section_set_mixer_name(section, HEADPHONE); cras_alsa_jack_list_add_jack_for_section_result_jack = reinterpret_cast<struct cras_alsa_jack*>(20); @@ -1072,43 +1128,6 @@ TEST(AlsaOutputNode, TwoJacksHeadphoneLineout) { alsa_iodev_destroy(iodev); } -TEST(AlsaOutputNode, MaxSupportedChannels) { - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - struct ucm_section* section; - int i; - - // i = 0: cras_alsa_support_8_channels is false, support 2 channels only. - // i = 1: cras_alsa_support_8_channels is true, support up to 8 channels. - for (i = 0; i < 2; i++) { - ResetStubData(); - cras_alsa_support_8_channels = (bool)i; - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - - // Node without controls or jacks. - section = ucm_section_create(INTERNAL_SPEAKER, "hw:0,1", 1, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); - // Device index doesn't match. - EXPECT_EQ(-22, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - section->dev_idx = 0; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Complete initialization, and make first node active. - alsa_iodev_ucm_complete_init(iodev); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - uint32_t max_channels = (cras_alsa_support_8_channels) ? 8 : 2; - EXPECT_EQ(max_channels, iodev->info.max_supported_channels); - alsa_iodev_destroy(iodev); - } -} - TEST(AlsaOutputNode, OutputsFromUCM) { struct alsa_io* aio; struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; @@ -1137,8 +1156,8 @@ TEST(AlsaOutputNode, OutputsFromUCM) { EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); // First node. - section = ucm_section_create(INTERNAL_SPEAKER, "hw:0,1", 0, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); + section = + ucm_section_create(INTERNAL_SPEAKER, 0, CRAS_STREAM_OUTPUT, NULL, NULL); ucm_section_set_mixer_name(section, INTERNAL_SPEAKER); cras_alsa_jack_list_add_jack_for_section_result_jack = reinterpret_cast<struct cras_alsa_jack*>(1); @@ -1148,8 +1167,8 @@ TEST(AlsaOutputNode, OutputsFromUCM) { EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); // Add a second node (will use the same iodev). - section = ucm_section_create(HEADPHONE, "hw:0,2", 0, -1, CRAS_STREAM_OUTPUT, - jack_name, "hctl"); + section = + ucm_section_create(HEADPHONE, 0, CRAS_STREAM_OUTPUT, jack_name, "hctl"); ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME); cras_alsa_jack_list_add_jack_for_section_result_jack = NULL; @@ -1167,16 +1186,12 @@ TEST(AlsaOutputNode, OutputsFromUCM) { EXPECT_EQ(0, cras_iodev_set_node_plugged_called); // Complete initialization, and make first node active. - cras_alsa_support_8_channels = false; // Support 2 channels only. alsa_iodev_ucm_complete_init(iodev); EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); EXPECT_EQ(2, cras_alsa_jack_list_add_jack_for_section_called); EXPECT_EQ(2, cras_alsa_mixer_get_control_for_section_called); EXPECT_EQ(1, ucm_get_dma_period_for_dev_called); EXPECT_EQ(ucm_get_dma_period_for_dev_ret, aio->dma_period_set_microsecs); - /* Call cras_alsa_fill_properties once on update_max_supported_channels. */ - EXPECT_EQ(1, cras_alsa_fill_properties_called); - EXPECT_EQ(2, iodev->info.max_supported_channels); aio->handle = (snd_pcm_t*)0x24; @@ -1197,14 +1212,10 @@ TEST(AlsaOutputNode, OutputsFromUCM) { EXPECT_EQ(1, ucm_set_enabled_called); // Simulate jack plug event. - cras_alsa_support_8_channels = true; // Support up to 8 channels. cras_alsa_jack_get_mixer_output_ret = outputs[1]; cras_alsa_jack_get_name_ret_value = jack_name; jack_output_plug_event(reinterpret_cast<struct cras_alsa_jack*>(4), 0, aio); EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - /* Headphone plug event shouldn't trigger update_max_supported_channels. */ - EXPECT_EQ(0, cras_alsa_fill_properties_called); - EXPECT_EQ(2, iodev->info.max_supported_channels); alsa_iodev_destroy(iodev); } @@ -1226,8 +1237,8 @@ TEST(AlsaOutputNode, OutputNoControlsUCM) { EXPECT_EQ(1, cras_card_config_get_volume_curve_for_control_called); // Node without controls or jacks. - section = ucm_section_create(INTERNAL_SPEAKER, "hw:0,1", 1, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); + section = + ucm_section_create(INTERNAL_SPEAKER, 1, CRAS_STREAM_OUTPUT, NULL, NULL); // Device index doesn't match. EXPECT_EQ(-22, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); section->dev_idx = 0; @@ -1268,8 +1279,8 @@ TEST(AlsaOutputNode, OutputFromJackUCM) { // Node without controls or jacks. cras_alsa_jack_list_add_jack_for_section_result_jack = reinterpret_cast<struct cras_alsa_jack*>(1); - section = ucm_section_create(HEADPHONE, "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - jack_name, "hctl"); + section = + ucm_section_create(HEADPHONE, 0, CRAS_STREAM_OUTPUT, jack_name, "hctl"); ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); EXPECT_EQ(4, cras_card_config_get_volume_curve_for_control_called); EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called); @@ -1297,7 +1308,6 @@ TEST(AlsaOutputNode, InputsFromUCM) { static const char* jack_name = "TestCard - Headset Jack"; int rc; struct ucm_section* section; - long intrinsic_sensitivity = -2700; ResetStubData(); inputs[0] = reinterpret_cast<struct mixer_control*>(3); @@ -1316,8 +1326,9 @@ TEST(AlsaOutputNode, InputsFromUCM) { // First node. cras_alsa_mixer_get_control_for_section_return_value = inputs[0]; - section = ucm_section_create(INTERNAL_MICROPHONE, "hw:0,1", 0, -1, - CRAS_STREAM_INPUT, NULL, NULL); + ucm_get_max_software_gain_ret_value = -1; + section = + ucm_section_create(INTERNAL_MICROPHONE, 0, CRAS_STREAM_INPUT, NULL, NULL); ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME); ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); @@ -1325,18 +1336,17 @@ TEST(AlsaOutputNode, InputsFromUCM) { // Add a second node (will use the same iodev). cras_alsa_mixer_get_control_name_called = 0; - // Set intrinsic sensitivity to enable software gain. - ucm_get_intrinsic_sensitivity_values[MIC] = intrinsic_sensitivity; + ucm_get_max_software_gain_ret_value = 0; + ucm_get_max_software_gain_value = 2000; cras_alsa_jack_list_add_jack_for_section_result_jack = reinterpret_cast<struct cras_alsa_jack*>(1); cras_alsa_mixer_get_control_for_section_return_value = inputs[1]; - section = ucm_section_create(MIC, "hw:0,2", 0, -1, CRAS_STREAM_INPUT, - jack_name, "hctl"); + section = ucm_section_create(MIC, 0, CRAS_STREAM_INPUT, jack_name, "hctl"); ucm_section_set_mixer_name(section, MIC); ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); ucm_section_free_list(section); - // Jack plug of an unknown device should do nothing. + // Jack plug of an unkonwn device should do nothing. cras_alsa_jack_get_mixer_input_ret = NULL; cras_alsa_jack_get_name_ret_value = "Some other jack"; jack_input_plug_event(reinterpret_cast<struct cras_alsa_jack*>(4), 0, aio); @@ -1354,6 +1364,7 @@ TEST(AlsaOutputNode, InputsFromUCM) { EXPECT_EQ(2, cras_alsa_jack_list_add_jack_for_section_called); EXPECT_EQ(2, cras_alsa_mixer_get_control_for_section_called); EXPECT_EQ(1, cras_alsa_mixer_get_control_name_called); + EXPECT_EQ(1, sys_set_capture_gain_limits_called); EXPECT_EQ(2, cras_iodev_add_node_called); EXPECT_EQ(2, ucm_get_dma_period_for_dev_called); EXPECT_EQ(0, aio->dma_period_set_microsecs); @@ -1369,9 +1380,10 @@ TEST(AlsaOutputNode, InputsFromUCM) { EXPECT_EQ(1, cras_iodev_update_dsp_called); EXPECT_EQ(1, cras_alsa_jack_enable_ucm_called); EXPECT_EQ(1, ucm_set_enabled_called); + EXPECT_EQ(1, sys_set_capture_gain_limits_called); EXPECT_EQ(1, alsa_mixer_set_capture_mute_called); - ASSERT_EQ(DEFAULT_CAPTURE_VOLUME_DBFS - intrinsic_sensitivity, - iodev->active_node->capture_gain); + EXPECT_EQ(1, iodev->active_node->software_volume_needed); + EXPECT_EQ(2000, iodev->active_node->max_software_gain); alsa_iodev_destroy(iodev); } @@ -1392,8 +1404,8 @@ TEST(AlsaOutputNode, InputNoControlsUCM) { aio = reinterpret_cast<struct alsa_io*>(iodev); // Node without controls or jacks. - section = ucm_section_create(INTERNAL_MICROPHONE, "hw:0,1", 1, -1, - CRAS_STREAM_INPUT, NULL, NULL); + section = + ucm_section_create(INTERNAL_MICROPHONE, 1, CRAS_STREAM_INPUT, NULL, NULL); // Device index doesn't match. EXPECT_EQ(-22, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); section->dev_idx = 0; @@ -1434,8 +1446,7 @@ TEST(AlsaOutputNode, InputFromJackUCM) { // Node without controls or jacks. cras_alsa_jack_list_add_jack_for_section_result_jack = reinterpret_cast<struct cras_alsa_jack*>(1); - section = ucm_section_create(MIC, "hw:0,1", 0, -1, CRAS_STREAM_INPUT, - jack_name, "hctl"); + section = ucm_section_create(MIC, 0, CRAS_STREAM_INPUT, jack_name, "hctl"); ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called); EXPECT_EQ(1, cras_iodev_add_node_called); @@ -1543,83 +1554,6 @@ TEST(AlsaOutputNode, AutoUnplugInputNode) { alsa_iodev_destroy((struct cras_iodev*)aio); } -TEST(AlsaLoopback, InitializePlayback) { - struct alsa_io* aio; - struct cras_alsa_mixer* const fake_mixer = (struct cras_alsa_mixer*)2; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Alsa Loopback"; - struct mixer_control* outputs[1]; - struct ucm_section* section; - - ResetStubData(); - outputs[0] = reinterpret_cast<struct mixer_control*>(3); - cras_alsa_mixer_list_outputs_outputs = outputs; - cras_alsa_mixer_list_outputs_outputs_length = ARRAY_SIZE(outputs); - cras_alsa_mixer_get_control_name_values[outputs[0]] = LOOPBACK_PLAYBACK; - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 0, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_OUTPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // Add node. - section = ucm_section_create(LOOPBACK_PLAYBACK, "hw:0,1", 0, -1, - CRAS_STREAM_OUTPUT, jack_name, NULL); - ucm_section_set_mixer_name(section, LOOPBACK_PLAYBACK); - cras_alsa_jack_list_add_jack_for_section_result_jack = NULL; - cras_alsa_mixer_get_control_for_section_return_value = outputs[0]; - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Complete initialization, and check the loopback playback node is plugged as - // the active node. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_PLAYBACK, aio->alsa_stream); - ASSERT_NE(aio->base.active_node, (void*)NULL); - EXPECT_STREQ(LOOPBACK_PLAYBACK, aio->base.active_node->name); - EXPECT_EQ(1, aio->base.active_node->plugged); - - alsa_iodev_destroy(iodev); -} - -TEST(AlsaLoopback, InitializeCapture) { - struct alsa_io* aio; - struct cras_use_case_mgr* const fake_ucm = (struct cras_use_case_mgr*)3; - struct cras_iodev* iodev; - static const char* jack_name = "TestCard - Alsa Loopback"; - struct ucm_section* section; - - ResetStubData(); - - // Create the IO device. - iodev = alsa_iodev_create_with_default_parameters( - 1, NULL, ALSA_CARD_TYPE_INTERNAL, 1, fake_mixer, fake_config, fake_ucm, - CRAS_STREAM_INPUT); - ASSERT_NE(iodev, (void*)NULL); - aio = reinterpret_cast<struct alsa_io*>(iodev); - - // Node without controls or jacks. - cras_alsa_jack_list_add_jack_for_section_result_jack = - reinterpret_cast<struct cras_alsa_jack*>(1); - section = ucm_section_create(LOOPBACK_CAPTURE, "hw:0,1", 0, -1, - CRAS_STREAM_INPUT, jack_name, NULL); - ASSERT_EQ(0, alsa_iodev_ucm_add_nodes_and_jacks(iodev, section)); - ucm_section_free_list(section); - - // Complete initialization, and check the loopback capture node is plugged as - // the active node. - alsa_iodev_ucm_complete_init(iodev); - EXPECT_EQ(SND_PCM_STREAM_CAPTURE, aio->alsa_stream); - ASSERT_NE(aio->base.active_node, (void*)NULL); - EXPECT_STREQ(LOOPBACK_CAPTURE, aio->base.active_node->name); - EXPECT_EQ(1, aio->base.active_node->plugged); - - alsa_iodev_destroy(iodev); -} - TEST(AlsaInitNode, SetNodeInitialState) { struct cras_ionode node; struct cras_iodev dev; @@ -1933,6 +1867,11 @@ TEST_F(AlsaVolumeMuteSuite, GetVolumeCurveFromNode) { .get_dBFS = fake_get_dBFS, }; + fmt = (struct cras_audio_format*)malloc(sizeof(*fmt)); + memcpy(fmt, &fmt_, sizeof(fmt_)); + aio_output_->base.format = fmt; + aio_output_->handle = (snd_pcm_t*)0x24; + // Headphone jack plugged and has its own volume curve. cras_alsa_jack_get_mixer_output_ret = NULL; cras_alsa_jack_get_name_ret_value = HEADPHONE; @@ -1941,16 +1880,6 @@ TEST_F(AlsaVolumeMuteSuite, GetVolumeCurveFromNode) { EXPECT_EQ(1, cras_alsa_jack_update_node_type_called); EXPECT_EQ(3, cras_card_config_get_volume_curve_for_control_called); - // These settings should be placed after plugging jacks to make it safer. - // If is HDMI jack, plug event will trigger update_max_supported_channels() - // and do open_dev() and close_dev() once. close_dev() will perform alsa_io - // cleanup. - // Headphone jack won't trigger, but we still place here due to coherence. - fmt = (struct cras_audio_format*)malloc(sizeof(*fmt)); - memcpy(fmt, &fmt_, sizeof(fmt_)); - aio_output_->base.format = fmt; - aio_output_->handle = (snd_pcm_t*)0x24; - // Switch to node 'Headphone'. node = aio_output_->base.nodes->next; aio_output_->base.active_node = node; @@ -1975,6 +1904,7 @@ TEST_F(AlsaVolumeMuteSuite, SetVolume) { aio_output_->base.format = fmt; aio_output_->handle = (snd_pcm_t*)0x24; + aio_output_->num_underruns = 3; // Something non-zero. sys_get_volume_return_value = fake_system_volume; rc = aio_output_->base.configure_dev(&aio_output_->base); ASSERT_EQ(0, rc); @@ -2055,7 +1985,6 @@ class AlsaFreeRunTestSuite : public testing::Test { fmt_.frame_rate = 48000; fmt_.num_channels = 2; aio.base.frames_queued = frames_queued; - aio.base.output_underrun = alsa_output_underrun; aio.base.direction = CRAS_STREAM_OUTPUT; aio.base.format = &fmt_; aio.base.buffer_size = BUFFER_SIZE; @@ -2207,7 +2136,6 @@ TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunNotInFreeRunMoreRemain) { EXPECT_EQ(0, cras_iodev_fill_odev_zeros_frames); EXPECT_EQ(0, aio.free_running); EXPECT_EQ(0, aio.filled_zeros_for_draining); - EXPECT_EQ(1, cras_iodev_reset_rate_estimator_called); } TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunNotInFreeRunLessRemain) { @@ -2232,7 +2160,6 @@ TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunNotInFreeRunLessRemain) { EXPECT_EQ(96, cras_iodev_fill_odev_zeros_frames); EXPECT_EQ(0, aio.free_running); EXPECT_EQ(0, aio.filled_zeros_for_draining); - EXPECT_EQ(1, cras_iodev_reset_rate_estimator_called); } TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunInFreeRun) { @@ -2250,7 +2177,6 @@ TEST_F(AlsaFreeRunTestSuite, LeaveFreeRunInFreeRun) { cras_alsa_resume_appl_ptr_ahead); EXPECT_EQ(0, aio.free_running); EXPECT_EQ(0, aio.filled_zeros_for_draining); - EXPECT_EQ(1, cras_iodev_reset_rate_estimator_called); } // Reuse AlsaFreeRunTestSuite for output underrun handling because they are @@ -2260,9 +2186,12 @@ TEST_F(AlsaFreeRunTestSuite, OutputUnderrun) { int16_t* zeros; snd_pcm_uframes_t offset; + aio.num_underruns = 0; + // Ask alsa_io to handle output underrun. rc = alsa_output_underrun(&aio.base); EXPECT_EQ(0, rc); + EXPECT_EQ(1, aio.num_underruns); // mmap buffer should be filled with zeros. zeros = (int16_t*)calloc(BUFFER_SIZE * 2, sizeof(*zeros)); @@ -2306,7 +2235,7 @@ TEST(AlsaHotwordNode, HotwordTriggeredSendMessage) { ASSERT_EQ(0, rc); ASSERT_NE(reinterpret_cast<thread_callback>(NULL), audio_thread_cb); - audio_thread_cb(audio_thread_cb_data, POLLIN); + audio_thread_cb(audio_thread_cb_data); EXPECT_EQ(1, hotword_send_triggered_msg_called); alsa_iodev_destroy(iodev); } @@ -2442,21 +2371,9 @@ int cras_alsa_fill_properties(snd_pcm_t* handle, (*rates)[0] = 44100; (*rates)[1] = 48000; (*rates)[2] = 0; - - if (cras_alsa_support_8_channels) { // Support up to 8 channels. - *channel_counts = (size_t*)malloc(sizeof(**channel_counts) * 6); - (*channel_counts)[0] = 6; - (*channel_counts)[1] = 4; - (*channel_counts)[2] = 2; - (*channel_counts)[3] = 1; - (*channel_counts)[4] = 8; - (*channel_counts)[5] = 0; - } else { // Support 2 channels only. - *channel_counts = (size_t*)malloc(sizeof(**channel_counts) * 2); - (*channel_counts)[0] = 2; - (*channel_counts)[1] = 0; - } - + *channel_counts = (size_t*)malloc(sizeof(**channel_counts) * 2); + (*channel_counts)[0] = 2; + (*channel_counts)[1] = 0; *formats = (snd_pcm_format_t*)malloc(sizeof(**formats) * 2); (*formats)[0] = SND_PCM_FORMAT_S16_LE; (*formats)[1] = (snd_pcm_format_t)0; @@ -2471,7 +2388,7 @@ int cras_alsa_set_hwparams(snd_pcm_t* handle, unsigned int dma_period_time) { return 0; } -int cras_alsa_set_swparams(snd_pcm_t* handle) { +int cras_alsa_set_swparams(snd_pcm_t* handle, int* enable_htimestamp) { return 0; } int cras_alsa_get_avail_frames(snd_pcm_t* handle, @@ -2545,6 +2462,11 @@ size_t cras_system_get_volume() { return sys_get_volume_return_value; } +long cras_system_get_capture_gain() { + sys_get_capture_gain_called++; + return sys_get_capture_gain_return_value; +} + int cras_system_get_mute() { sys_get_mute_called++; return sys_get_mute_return_value; @@ -2559,8 +2481,10 @@ void cras_system_set_volume_limits(long min, long max) { sys_set_volume_limits_called++; } -bool cras_system_get_noise_cancellation_enabled() { - return false; +void cras_system_set_capture_gain_limits(long min, long max) { + cras_system_set_capture_gain_limits_set_value[0] = min; + cras_system_set_capture_gain_limits_set_value[1] = max; + sys_set_capture_gain_limits_called++; } // From cras_alsa_mixer. @@ -2711,6 +2635,15 @@ const char* cras_alsa_jack_get_name(const struct cras_alsa_jack* jack) { return cras_alsa_jack_get_name_ret_value; } +const char* ucm_get_dsp_name_default(struct cras_use_case_mgr* mgr, + int direction) { + ucm_get_dsp_name_default_called++; + if (ucm_get_dsp_name_default_value) + return strdup(ucm_get_dsp_name_default_value); + else + return NULL; +} + const char* ucm_get_dsp_name_for_dev(struct cras_use_case_mgr* mgr, const char* dev) { DspNameMap::iterator it; @@ -2753,6 +2686,10 @@ char* ucm_get_flag(struct cras_use_case_mgr* mgr, const char* flag_name) { return NULL; } +char* ucm_get_mic_positions(struct cras_use_case_mgr* mgr) { + return NULL; +} + int ucm_swap_mode_exists(struct cras_use_case_mgr* mgr) { return ucm_swap_mode_exists_ret_value; } @@ -2770,10 +2707,30 @@ int ucm_get_min_buffer_level(struct cras_use_case_mgr* mgr, return 0; } +unsigned int ucm_get_enable_htimestamp_flag(struct cras_use_case_mgr* mgr) { + return ucm_get_enable_htimestamp_flag_ret; +} + unsigned int ucm_get_disable_software_volume(struct cras_use_case_mgr* mgr) { return 0; } +int ucm_get_min_software_gain(struct cras_use_case_mgr* mgr, + const char* dev, + long* gain) { + ucm_get_min_software_gain_called++; + *gain = ucm_get_min_software_gain_value; + return ucm_get_min_software_gain_ret_value; +} + +int ucm_get_max_software_gain(struct cras_use_case_mgr* mgr, + const char* dev, + long* gain) { + ucm_get_max_software_gain_called++; + *gain = ucm_get_max_software_gain_value; + return ucm_get_max_software_gain_ret_value; +} + char* ucm_get_hotword_models(struct cras_use_case_mgr* mgr) { return NULL; } @@ -2804,24 +2761,6 @@ int ucm_get_preempt_hotword(struct cras_use_case_mgr* mgr, const char* dev) { return 0; } -int ucm_get_channels_for_dev(struct cras_use_case_mgr* mgr, - const char* dev, - enum CRAS_STREAM_DIRECTION direction, - size_t* channels) { - return -EINVAL; -} - -int ucm_node_noise_cancellation_exists(struct cras_use_case_mgr* mgr, - const char* node_name) { - return 0; -} - -int ucm_enable_node_noise_cancellation(struct cras_use_case_mgr* mgr, - const char* node_name, - int enable) { - return 0; -} - struct cras_volume_curve* cras_volume_curve_create_default() { return &default_curve; } @@ -2858,7 +2797,7 @@ void audio_thread_destroy(audio_thread* thread) {} void cras_iodev_update_dsp(struct cras_iodev* iodev) { cras_iodev_update_dsp_called++; - cras_iodev_update_dsp_name = iodev->dsp_name ?: ""; + cras_iodev_update_dsp_name = iodev->dsp_name; } void cras_iodev_set_node_plugged(struct cras_ionode* ionode, int plugged) { @@ -2903,12 +2842,6 @@ const char* cras_alsa_jack_get_ucm_device(const struct cras_alsa_jack* jack) { return NULL; } -void ucm_disable_all_hotword_models(struct cras_use_case_mgr* mgr) {} - -int ucm_enable_hotword_model(struct cras_use_case_mgr* mgr) { - return 0; -} - int ucm_get_default_node_gain(struct cras_use_case_mgr* mgr, const char* dev, long* gain) { @@ -2920,23 +2853,11 @@ int ucm_get_default_node_gain(struct cras_use_case_mgr* mgr, return 0; } -int ucm_get_intrinsic_sensitivity(struct cras_use_case_mgr* mgr, - const char* dev, - long* vol) { - if (ucm_get_intrinsic_sensitivity_values.find(dev) == - ucm_get_intrinsic_sensitivity_values.end()) - return 1; - - *vol = ucm_get_intrinsic_sensitivity_values[dev]; - return 0; -} - void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) {} void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} int cras_iodev_reset_rate_estimator(const struct cras_iodev* iodev) { - cras_iodev_reset_rate_estimator_called++; return 0; } @@ -2960,10 +2881,7 @@ void cras_audio_area_config_buf_pointers(struct cras_audio_area* area, const struct cras_audio_format* fmt, uint8_t* base_buffer) {} -void audio_thread_add_events_callback(int fd, - thread_callback cb, - void* data, - int events) { +void audio_thread_add_callback(int fd, thread_callback cb, void* data) { audio_thread_cb = cb; audio_thread_cb_data = data; } @@ -3014,12 +2932,6 @@ int cras_iodev_default_no_stream_playback(struct cras_iodev* odev, int enable) { return 0; } -int cras_iodev_output_underrun(struct cras_iodev* odev, - unsigned int hw_level, - unsigned int frames_written) { - return odev->output_underrun(odev); -} - enum CRAS_IODEV_STATE cras_iodev_state(const struct cras_iodev* iodev) { return iodev->state; } diff --git a/cras/src/tests/alsa_jack_unittest.cc b/cras/src/tests/alsa_jack_unittest.cc index 1aa95491..24b43a31 100644 --- a/cras/src/tests/alsa_jack_unittest.cc +++ b/cras/src/tests/alsa_jack_unittest.cc @@ -86,7 +86,7 @@ static unsigned long eviocbit_ret[NBITS(SW_CNT)]; static int gpio_switch_eviocgbit_fd; static const char* edid_file_ret; static unsigned ucm_get_override_type_name_called; -static int ucm_get_alsa_dev_idx_for_dev_value; +static char* ucm_get_device_name_for_dev_value; static snd_hctl_t* fake_hctl = (snd_hctl_t*)2; static void ResetStubData() { @@ -137,7 +137,7 @@ static void ResetStubData() { ucm_get_dev_for_jack_return = false; edid_file_ret = NULL; ucm_get_override_type_name_called = 0; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; memset(eviocbit_ret, 0, sizeof(eviocbit_ret)); } @@ -216,15 +216,14 @@ static struct cras_alsa_jack_list* run_test_with_elem_list( EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list)); EXPECT_EQ(ucm ? njacks : 0, ucm_get_dev_for_jack_called); EXPECT_EQ(ucm ? njacks : 0, ucm_get_override_type_name_called); - EXPECT_EQ(1, snd_hctl_first_elem_called); + EXPECT_EQ(1 + nhdmi_jacks, snd_hctl_first_elem_called); EXPECT_EQ(njacks, snd_hctl_elem_set_callback_called); - EXPECT_EQ(nhdmi_jacks, snd_hctl_find_elem_called); /* For some functions, the number of calls to them could * be larger then expected count if there is ELD control * in given elements. */ - EXPECT_GE(snd_hctl_elem_next_called, nelems); - EXPECT_GE(snd_hctl_elem_get_name_called, nelems); + EXPECT_GE(snd_hctl_elem_next_called, nelems + nhdmi_jacks); + EXPECT_GE(snd_hctl_elem_get_name_called, nelems + njacks); if (direction == CRAS_STREAM_OUTPUT) { EXPECT_EQ(njacks, cras_alsa_mixer_get_output_matching_name_called); @@ -418,7 +417,7 @@ TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMMatched) { /* PlaybackPCM matched, so create jack even if this is not the first device.*/ ucm_get_dev_for_jack_return = true; - ucm_get_alsa_dev_idx_for_dev_value = 1; + ucm_get_device_name_for_dev_value = strdup("hw:c1,1"); run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Headset Jack"); @@ -434,7 +433,7 @@ TEST(AlsaJacks, CreateGPIOHpUCMCapturePCMMatched) { /* CapturePCM matched, so create jack even if this is not the first device.*/ ucm_get_dev_for_jack_return = true; - ucm_get_alsa_dev_idx_for_dev_value = 1; + ucm_get_device_name_for_dev_value = strdup("hw:c1,1"); run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Mic Jack"); @@ -450,7 +449,7 @@ TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotMatched) { /* PlaybackPCM not matched, do not create jack. */ ucm_get_dev_for_jack_return = true; - ucm_get_alsa_dev_idx_for_dev_value = 2; + ucm_get_device_name_for_dev_value = strdup("hw:c1,2"); run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Headset Jack"); @@ -466,7 +465,7 @@ TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotSpecifiedFirstDevice) { /* PlaybackPCM not specified, create jack for the first device. */ ucm_get_dev_for_jack_return = true; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Headset Jack"); @@ -482,7 +481,7 @@ TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotSpecifiedSecondDevice) { /* PlaybackPCM not specified, do not create jack for the second device. */ ucm_get_dev_for_jack_return = true; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Headset Jack"); @@ -498,7 +497,7 @@ TEST(AlsaJacks, CreateGPIOHpNoUCMFirstDevice) { /* No UCM for this jack, create jack for the first device. */ ucm_get_dev_for_jack_return = false; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Headset Jack"); @@ -514,7 +513,7 @@ TEST(AlsaJacks, CreateGPIOHpNoUCMSecondDevice) { /* No UCM for this jack, dot not create jack for the second device. */ ucm_get_dev_for_jack_return = false; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; run_gpio_jack_test(device_index, is_first_device, direction, should_create_jack, "c1 Headset Jack"); @@ -530,7 +529,7 @@ TEST(AlsaJacks, CreateGPIOMicNoUCMFirstDeviceMicJack) { // No UCM for this jack, create jack for the first device. ucm_get_dev_for_jack_return = false; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; // Mic Jack is a valid name for microphone jack. run_gpio_jack_test(device_index, is_first_device, direction, @@ -547,7 +546,7 @@ TEST(AlsaJacks, CreateGPIOMicNoUCMFirstDeviceHeadsetJack) { // No UCM for this jack, create jack for the first device. ucm_get_dev_for_jack_return = false; - ucm_get_alsa_dev_idx_for_dev_value = -1; + ucm_get_device_name_for_dev_value = NULL; // Headset Jack is a valid name for microphone jack. run_gpio_jack_test(device_index, is_first_device, direction, @@ -679,7 +678,7 @@ TEST(AlsaJacks, CreateHDMIJacksWithELD) { ASSERT_NE(static_cast<struct cras_alsa_jack_list*>(NULL), jack_list); /* Assert get device is called for the ELD control */ - EXPECT_EQ(1, snd_hctl_find_elem_called); + EXPECT_EQ(1, snd_hctl_elem_get_device_called); cras_alsa_jack_list_destroy(jack_list); } @@ -729,7 +728,7 @@ TEST(AlsaJacks, CreateHCTLHeadphoneJackFromUCM) { struct cras_alsa_jack_list* jack_list; struct ucm_section* section; - section = ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, + section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, "Headphone Jack", "hctl"); ResetStubData(); @@ -765,7 +764,7 @@ TEST(AlsaJacks, CreateGPIOHeadphoneJackFromUCM) { struct cras_alsa_jack* jack; struct ucm_section* section; - section = ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, + section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, "c1 Headphone Jack", "gpio"); ResetStubData(); @@ -807,7 +806,7 @@ TEST(AlsaJacks, BadJackTypeFromUCM) { struct cras_alsa_jack_list* jack_list; struct ucm_section* section; - section = ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, + section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, "Headphone Jack", "badtype"); ResetStubData(); @@ -829,7 +828,7 @@ TEST(AlsaJacks, NoJackTypeFromUCM) { struct cras_alsa_jack_list* jack_list; struct ucm_section* section; - section = ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, + section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, "Headphone Jack", NULL); ResetStubData(); @@ -1054,10 +1053,10 @@ const char* ucm_get_override_type_name(struct cras_use_case_mgr* mgr, return NULL; } -int ucm_get_alsa_dev_idx_for_dev(struct cras_use_case_mgr* mgr, - const char* dev, - enum CRAS_STREAM_DIRECTION direction) { - return ucm_get_alsa_dev_idx_for_dev_value; +const char* ucm_get_device_name_for_dev(struct cras_use_case_mgr* mgr, + const char* dev, + enum CRAS_STREAM_DIRECTION direction) { + return ucm_get_device_name_for_dev_value; } cras_timer* cras_tm_create_timer(cras_tm* tm, diff --git a/cras/src/tests/alsa_mixer_unittest.cc b/cras/src/tests/alsa_mixer_unittest.cc index b3db9de5..d61ba3df 100644 --- a/cras/src/tests/alsa_mixer_unittest.cc +++ b/cras/src/tests/alsa_mixer_unittest.cc @@ -381,7 +381,7 @@ TEST(AlsaMixer, CreateOneUnknownElementWithVolume) { mixer_control_destroy(mixer_output); } -TEST(AlsaMixer, CreateOneMainElement) { +TEST(AlsaMixer, CreateOneMasterElement) { struct cras_alsa_mixer* c; int element_playback_volume[] = { 1, @@ -419,10 +419,10 @@ TEST(AlsaMixer, CreateOneMainElement) { EXPECT_EQ(3, snd_mixer_selem_get_name_called); EXPECT_EQ(1, snd_mixer_elem_next_called); - /* set mute should be called for Main. */ + /* set mute should be called for Master. */ cras_alsa_mixer_set_mute(c, 0, NULL); EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); - /* set volume should be called for Main. */ + /* set volume should be called for Master. */ cras_alsa_mixer_set_dBFS(c, 0, NULL); EXPECT_EQ(1, snd_mixer_selem_set_playback_dB_all_called); @@ -515,15 +515,15 @@ TEST(AlsaMixer, CreateTwoMainVolumeElements) { EXPECT_EQ(5, snd_mixer_selem_get_name_called); EXPECT_EQ(3, snd_mixer_selem_has_playback_switch_called); - /* Set mute should be called for Main only. */ + /* Set mute should be called for Master only. */ cras_alsa_mixer_set_mute(c, 0, NULL); EXPECT_EQ(1, snd_mixer_selem_set_playback_switch_all_called); - /* Set volume should be called for Main and PCM. If Main doesn't set to + /* Set volume should be called for Master and PCM. If Master doesn't set to * anything but zero then the entire volume should be passed to the PCM * control.*/ - /* Set volume should be called for Main and PCM. (without mixer_output) */ + /* Set volume should be called for Master and PCM. (without mixer_output) */ snd_mixer_selem_get_playback_dB_return_values = get_dB_returns; snd_mixer_selem_get_playback_dB_return_values_length = ARRAY_SIZE(get_dB_returns); @@ -557,8 +557,8 @@ TEST(AlsaMixer, CreateTwoMainVolumeElements) { EXPECT_EQ(1, snd_mixer_selem_has_playback_switch_called); EXPECT_EQ(1, snd_mixer_selem_get_playback_dB_range_called); - /* Set volume should be called for Main, PCM, and the mixer_output passed - * in. If Main doesn't set to anything but zero then the entire volume + /* Set volume should be called for Master, PCM, and the mixer_output passed + * in. If Master doesn't set to anything but zero then the entire volume * should be passed to the PCM control.*/ cras_alsa_mixer_set_dBFS(c, -50, mixer_output); EXPECT_EQ(3, snd_mixer_selem_set_playback_dB_all_called); @@ -566,8 +566,8 @@ TEST(AlsaMixer, CreateTwoMainVolumeElements) { EXPECT_EQ(30, set_dB_values[0]); EXPECT_EQ(30, set_dB_values[1]); EXPECT_EQ(30, set_dB_values[2]); - /* Set volume should be called for Main and PCM. Since the controls were - * sorted, Main should get the volume remaining after PCM is set, in this + /* Set volume should be called for Master and PCM. Since the controls were + * sorted, Master should get the volume remaining after PCM is set, in this * case -50 - -24 = -26. */ long get_dB_returns2[] = { -25, @@ -584,7 +584,7 @@ TEST(AlsaMixer, CreateTwoMainVolumeElements) { cras_alsa_mixer_set_dBFS(c, -50, mixer_output); EXPECT_EQ(2, snd_mixer_selem_set_playback_dB_all_called); EXPECT_EQ(2, snd_mixer_selem_get_playback_dB_called); - EXPECT_EQ(54, set_dB_values[0]); // Main + EXPECT_EQ(54, set_dB_values[0]); // Master EXPECT_EQ(30, set_dB_values[1]); // PCM cras_alsa_mixer_destroy(c); @@ -639,7 +639,7 @@ TEST(AlsaMixer, CreateTwoMainCaptureElements) { EXPECT_EQ(5, snd_mixer_selem_get_name_called); EXPECT_EQ(3, snd_mixer_selem_has_capture_switch_called); - /* Set mute should be called for Main only. */ + /* Set mute should be called for Master only. */ cras_alsa_mixer_set_capture_mute(c, 0, NULL); EXPECT_EQ(1, snd_mixer_selem_set_capture_switch_all_called); /* Set volume should be called for Capture and Digital Capture. If Capture @@ -773,7 +773,7 @@ class AlsaMixerOutputs : public testing::Test { ResetStubData(); snd_mixer_first_elem_return_value = - reinterpret_cast<snd_mixer_elem_t*>(1); // Main + reinterpret_cast<snd_mixer_elem_t*>(1); // Master snd_mixer_elem_next_return_values = elements; snd_mixer_elem_next_return_values_length = ARRAY_SIZE(elements); snd_mixer_selem_has_playback_volume_return_values = element_playback_volume; @@ -1275,32 +1275,29 @@ class AlsaMixerFullySpeced : public testing::Test { for (i = 0; i < ARRAY_SIZE(elements); i++) snd_mixer_find_elem_map[element_names[i]] = elements[i]; - section = ucm_section_create("NullElement", "hw:0,1", 0, -1, - CRAS_STREAM_OUTPUT, NULL, NULL); + section = + ucm_section_create("NullElement", 0, CRAS_STREAM_OUTPUT, NULL, NULL); ucm_section_set_mixer_name(section, "Unknown"); DL_APPEND(sections, section); - section = - ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - "my-sound-card Headset Jack", "gpio"); + section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT, + "my-sound-card Headset Jack", "gpio"); ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("Speaker", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - NULL, NULL); + section = ucm_section_create("Speaker", 0, CRAS_STREAM_OUTPUT, NULL, NULL); ucm_section_add_coupled(section, "SPK-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "SPK-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("Mic", "hw:0,1", 0, -1, CRAS_STREAM_INPUT, + section = ucm_section_create("Mic", 0, CRAS_STREAM_INPUT, "my-sound-card Headset Jack", "gpio"); ucm_section_set_mixer_name(section, "CAPTURE"); DL_APPEND(sections, section); - section = ucm_section_create("Internal Mic", "hw:0,1", 0, -1, - CRAS_STREAM_INPUT, NULL, NULL); + section = + ucm_section_create("Internal Mic", 0, CRAS_STREAM_INPUT, NULL, NULL); ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME); ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME); DL_APPEND(sections, section); - section = ucm_section_create("HDMI", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT, - NULL, NULL); + section = ucm_section_create("HDMI", 0, CRAS_STREAM_OUTPUT, NULL, NULL); ucm_section_set_mixer_name(section, "HDMI"); DL_APPEND(sections, section); ASSERT_NE(sections, (struct ucm_section*)NULL); diff --git a/cras/src/tests/alsa_ucm_unittest.cc b/cras/src/tests/alsa_ucm_unittest.cc index 1b351ddf..0773079e 100644 --- a/cras/src/tests/alsa_ucm_unittest.cc +++ b/cras/src/tests/alsa_ucm_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include <gtest/gtest.h> +#include <iniparser.h> #include <stdio.h> #include <syslog.h> @@ -28,13 +29,11 @@ static unsigned snd_use_case_get_called; static std::vector<std::string> snd_use_case_get_id; static int snd_use_case_set_return; static std::map<std::string, std::string> snd_use_case_get_value; -static std::map<std::string, unsigned> snd_use_case_geti_value; static unsigned snd_use_case_set_called; static std::vector<std::pair<std::string, std::string> > snd_use_case_set_param; static std::map<std::string, const char**> fake_list; static std::map<std::string, unsigned> fake_list_size; static unsigned snd_use_case_free_list_called; -static unsigned snd_use_case_geti_called; static std::vector<std::string> list_devices_callback_names; static std::vector<void*> list_devices_callback_args; static struct cras_use_case_mgr cras_ucm_mgr; @@ -47,12 +46,10 @@ static void ResetStubData() { snd_use_case_set_return = 0; snd_use_case_get_called = 0; snd_use_case_set_called = 0; - snd_use_case_geti_called = 0; snd_use_case_set_param.clear(); snd_use_case_free_list_called = 0; snd_use_case_get_id.clear(); snd_use_case_get_value.clear(); - snd_use_case_geti_value.clear(); fake_list.clear(); fake_list_size.clear(); fake_list["_verbs"] = avail_verbs; @@ -61,7 +58,6 @@ static void ResetStubData() { list_devices_callback_args.clear(); snd_use_case_mgr_open_mgr_ptr = reinterpret_cast<snd_use_case_mgr_t*>(0x55); cras_ucm_mgr.use_case = CRAS_STREAM_TYPE_DEFAULT; - cras_ucm_mgr.hotword_modifier = NULL; } static void list_devices_callback(const char* section_name, void* arg) { @@ -273,8 +269,8 @@ TEST(AlsaUcm, GetDevForJack) { fake_list["_devices/HiFi"] = devices; fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=JackDev/Dev1/HiFi"; - std::string id_2 = "=JackDev/Dev2/HiFi"; + std::string id_1 = "=JackName/Dev1/HiFi"; + std::string id_2 = "=JackName/Dev2/HiFi"; std::string value_1 = "Value1"; std::string value_2 = "Value2"; @@ -300,8 +296,8 @@ TEST(AlsaUcm, GetDevForHeadphoneJack) { fake_list["_devices/HiFi"] = devices; fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=JackDev/Mic/HiFi"; - std::string id_2 = "=JackDev/Headphone/HiFi"; + std::string id_1 = "=JackName/Mic/HiFi"; + std::string id_2 = "=JackName/Headphone/HiFi"; std::string value = "JackValue"; snd_use_case_get_value[id_1] = value; @@ -326,8 +322,8 @@ TEST(AlsaUcm, GetDevForMicJack) { fake_list["_devices/HiFi"] = devices; fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=JackDev/Headphone/HiFi"; - std::string id_2 = "=JackDev/Mic/HiFi"; + std::string id_1 = "=JackName/Headphone/HiFi"; + std::string id_2 = "=JackName/Mic/HiFi"; std::string value = "JackValue"; snd_use_case_get_value[id_1] = value; @@ -352,8 +348,8 @@ TEST(AlsaUcm, GetDevForMixer) { fake_list["_devices/HiFi"] = devices; fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=PlaybackMixerElem/Dev1/HiFi"; - std::string id_2 = "=CaptureMixerElem/Dev2/HiFi"; + std::string id_1 = "=MixerName/Dev1/HiFi"; + std::string id_2 = "=MixerName/Dev2/HiFi"; std::string value_1 = "Value1"; std::string value_2 = "Value2"; @@ -372,8 +368,9 @@ TEST(AlsaUcm, GetDevForMixer) { free((void*)dev_name_in); } -TEST(AlsaUcm, GetAlsaDeviceIndexForDevice) { +TEST(AlsaUcm, GetDeviceNameForDevice) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; + const char *input_dev_name, *output_dev_name; const char* devices[] = {"Dev1", "Comment for Dev1", "Dev2", "Comment for Dev2"}; @@ -383,17 +380,24 @@ TEST(AlsaUcm, GetAlsaDeviceIndexForDevice) { fake_list_size["_devices/HiFi"] = 4; std::string id_1 = "=CapturePCM/Dev1/HiFi"; std::string id_2 = "=PlaybackPCM/Dev2/HiFi"; - std::string value_1 = "PCMName,1"; - std::string value_2 = "PCMName,2"; + std::string value_1 = "DeviceName1"; + std::string value_2 = "DeviceName2"; snd_use_case_get_value[id_1] = value_1; snd_use_case_get_value[id_2] = value_2; - EXPECT_EQ(1, ucm_get_alsa_dev_idx_for_dev(mgr, "Dev1", CRAS_STREAM_INPUT)); - EXPECT_EQ(2, ucm_get_alsa_dev_idx_for_dev(mgr, "Dev2", CRAS_STREAM_OUTPUT)); + input_dev_name = ucm_get_device_name_for_dev(mgr, "Dev1", CRAS_STREAM_INPUT); + output_dev_name = + ucm_get_device_name_for_dev(mgr, "Dev2", CRAS_STREAM_OUTPUT); + ASSERT_TRUE(input_dev_name); + ASSERT_TRUE(output_dev_name); + EXPECT_EQ(0, strcmp(input_dev_name, value_1.c_str())); + EXPECT_EQ(0, strcmp(output_dev_name, value_2.c_str())); ASSERT_EQ(2, snd_use_case_get_called); EXPECT_EQ(snd_use_case_get_id[0], id_1); EXPECT_EQ(snd_use_case_get_id[1], id_2); + free((void*)input_dev_name); + free((void*)output_dev_name); } TEST(AlsaUcm, GetDeviceRateForDevice) { @@ -424,38 +428,6 @@ TEST(AlsaUcm, GetDeviceRateForDevice) { EXPECT_EQ(snd_use_case_get_id[1], id_2); } -TEST(AlsaUcm, GetDeviceChannelsForDevice) { - struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - int rc; - size_t input_dev_channels, output_dev_channels; - const char* devices[] = {"Dev1", "Comment for Dev1", "Dev2", - "Comment for Dev2"}; - - ResetStubData(); - - fake_list["_devices/HiFi"] = devices; - fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=CaptureChannels/Dev1/HiFi"; - std::string id_2 = "=PlaybackChannels/Dev2/HiFi"; - std::string value_1 = "4"; - std::string value_2 = "8"; - - snd_use_case_get_value[id_1] = value_1; - snd_use_case_get_value[id_2] = value_2; - rc = ucm_get_channels_for_dev(mgr, "Dev1", CRAS_STREAM_INPUT, - &input_dev_channels); - EXPECT_EQ(0, rc); - EXPECT_EQ(4, input_dev_channels); - rc = ucm_get_channels_for_dev(mgr, "Dev2", CRAS_STREAM_OUTPUT, - &output_dev_channels); - EXPECT_EQ(0, rc); - EXPECT_EQ(8, output_dev_channels); - - ASSERT_EQ(2, snd_use_case_get_called); - EXPECT_EQ(snd_use_case_get_id[0], id_1); - EXPECT_EQ(snd_use_case_get_id[1], id_2); -} - TEST(AlsaUcm, GetCaptureChannelMapForDevice) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; int8_t channel_layout[CRAS_CH_MAX]; @@ -527,85 +499,26 @@ TEST(AlsaUcm, SetHotwordModel) { const char* modifiers[] = {"Hotword Model en", "Comment1", "Hotword Model jp", "Comment2", "Hotword Model de", "Comment3"}; - const char* enabled_mods[] = {"Hotword Model jp"}; - int ret; - std::string id = "_modstatus/Hotword Model jp"; + const char* enabled_mods[] = {"Hotword Model en"}; ResetStubData(); - snd_use_case_geti_value[id] = 1; fake_list["_modifiers/HiFi"] = modifiers; fake_list_size["_modifiers/HiFi"] = 6; EXPECT_EQ(-EINVAL, ucm_set_hotword_model(mgr, "zh")); EXPECT_EQ(0, snd_use_case_set_called); - ret = ucm_set_hotword_model(mgr, "jp"); - - EXPECT_EQ(0, ret); - EXPECT_EQ(0, snd_use_case_set_called); - EXPECT_EQ(0, strcmp(mgr->hotword_modifier, "Hotword Model jp")); - fake_list["_enamods"] = enabled_mods; fake_list_size["_enamods"] = 1; - ret = ucm_set_hotword_model(mgr, "de"); - EXPECT_EQ(0, ret); - EXPECT_EQ(2, snd_use_case_set_called); - EXPECT_EQ(1, snd_use_case_geti_called); - EXPECT_EQ( - snd_use_case_set_param[0], - std::make_pair(std::string("_dismod"), std::string("Hotword Model jp"))); - EXPECT_EQ( - snd_use_case_set_param[1], - std::make_pair(std::string("_enamod"), std::string("Hotword Model de"))); - free(mgr->hotword_modifier); -} - -TEST(AlsaUcm, DisableAllHotwordModels) { - struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - const char* modifiers[] = {"Hotword Model en", "Comment1", - "Hotword Model jp", "Comment2", - "Hotword Model de", "Comment3"}; - const char* enabled_mods[] = {"Hotword Model en"}; - ResetStubData(); - - fake_list["_modifiers/HiFi"] = modifiers; - fake_list_size["_modifiers/HiFi"] = 6; - fake_list["_enamods"] = enabled_mods; - fake_list_size["_enamods"] = 1; - - ucm_disable_all_hotword_models(mgr); + ucm_set_hotword_model(mgr, "jp"); - EXPECT_EQ(1, snd_use_case_set_called); + EXPECT_EQ(2, snd_use_case_set_called); EXPECT_EQ( snd_use_case_set_param[0], std::make_pair(std::string("_dismod"), std::string("Hotword Model en"))); -} - -TEST(AlsaUcm, EnableHotwordModel) { - struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - const char* modifiers[] = {"Hotword Model en", "Comment1", - "Hotword Model jp", "Comment2", - "Hotword Model de", "Comment3"}; - const char* enabled_mods[] = {""}; - int ret; - ResetStubData(); - - fake_list["_modifiers/HiFi"] = modifiers; - fake_list_size["_modifiers/HiFi"] = 6; - fake_list["_enamods"] = enabled_mods; - fake_list_size["_enamods"] = 0; - - EXPECT_EQ(-EINVAL, ucm_enable_hotword_model(mgr)); - - mgr->hotword_modifier = strdup("Hotword Model de"); - ret = ucm_enable_hotword_model(mgr); - - EXPECT_EQ(0, ret); - EXPECT_EQ(1, snd_use_case_set_called); EXPECT_EQ( - snd_use_case_set_param[0], - std::make_pair(std::string("_enamod"), std::string("Hotword Model de"))); - free(mgr->hotword_modifier); + snd_use_case_set_param[1], + std::make_pair(std::string("_enamod"), std::string("Hotword Model jp"))); } TEST(AlsaUcm, SwapModeExists) { @@ -693,76 +606,6 @@ TEST(AlsaUcm, DisableSwapMode) { EXPECT_EQ(1, snd_use_case_set_called); } -TEST(AlsaUcm, NoiseCancellationExists) { - struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - int rc; - const char* node = "Internal Mic"; - const char* modifiers_1[] = {"Internal Mic Noise Cancellation", "Comment"}; - const char* modifiers_2[] = {"Internal Mic Noise Augmentation", "Comment"}; - const char* modifiers_3[] = {"Microphone Noise Cancellation", "Comment"}; - - ResetStubData(); - - fake_list["_modifiers/HiFi"] = modifiers_1; - fake_list_size["_modifiers/HiFi"] = 2; - rc = ucm_node_noise_cancellation_exists(mgr, node); - EXPECT_EQ(1, rc); - - fake_list["_modifiers/HiFi"] = modifiers_2; - fake_list_size["_modifiers/HiFi"] = 2; - rc = ucm_node_noise_cancellation_exists(mgr, node); - EXPECT_EQ(0, rc); - - fake_list["_modifiers/HiFi"] = modifiers_3; - fake_list_size["_modifiers/HiFi"] = 2; - rc = ucm_node_noise_cancellation_exists(mgr, node); - EXPECT_EQ(0, rc); -} - -TEST(AlsaUcm, EnableDisableNoiseCancellation) { - struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - int rc; - const char* modifiers[] = {"Internal Mic Noise Cancellation", "Comment1", - "Microphone Noise Cancellation", "Comment2"}; - const char* modifiers_enabled[] = {"Internal Mic Noise Cancellation"}; - - ResetStubData(); - - fake_list["_modifiers/HiFi"] = modifiers; - fake_list_size["_modifiers/HiFi"] = 4; - - fake_list["_enamods"] = modifiers_enabled; - fake_list_size["_enamods"] = 1; - - snd_use_case_set_return = 0; - - rc = ucm_enable_node_noise_cancellation(mgr, "Line In", 1); - EXPECT_EQ(-EPERM, rc); // Modifier is not existed - EXPECT_EQ(0, snd_use_case_set_called); - - rc = ucm_enable_node_noise_cancellation(mgr, "Line In", 0); - EXPECT_EQ(-EPERM, rc); // Modifier is not existed - EXPECT_EQ(0, snd_use_case_set_called); - - rc = ucm_enable_node_noise_cancellation(mgr, "Microphone", 0); - EXPECT_EQ(0, rc); // Modifier is already disabled - EXPECT_EQ(0, snd_use_case_set_called); - - rc = ucm_enable_node_noise_cancellation(mgr, "Microphone", 1); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, snd_use_case_set_called); - - snd_use_case_set_called = 0; - - rc = ucm_enable_node_noise_cancellation(mgr, "Internal Mic", 1); - EXPECT_EQ(0, rc); // Modifier is already enabled - EXPECT_EQ(0, snd_use_case_set_called); - - rc = ucm_enable_node_noise_cancellation(mgr, "Internal Mic", 0); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, snd_use_case_set_called); -} - TEST(AlsaFlag, GetFlag) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; char* flag_value; @@ -924,36 +767,61 @@ TEST(AlsaUcm, FreeMixerNames) { mixer_name_free(mixer_names_1); } -TEST(AlsaUcm, DefaultNodeGain) { +TEST(AlsaUcm, MaxSoftwareGain) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - long default_node_gain; + long max_software_gain; int ret; - std::string id = "=DefaultNodeGain/Internal Mic/HiFi"; - std::string value = "-2000"; + std::string id = "=MaxSoftwareGain/Internal Mic/HiFi"; + std::string value = "2000"; ResetStubData(); /* Value can be found in UCM. */ snd_use_case_get_value[id] = value; - ret = ucm_get_default_node_gain(mgr, "Internal Mic", &default_node_gain); + ret = ucm_get_max_software_gain(mgr, "Internal Mic", &max_software_gain); EXPECT_EQ(0, ret); - EXPECT_EQ(-2000, default_node_gain); + EXPECT_EQ(2000, max_software_gain); ResetStubData(); /* Value can not be found in UCM. */ - ret = ucm_get_default_node_gain(mgr, "Internal Mic", &default_node_gain); + ret = ucm_get_max_software_gain(mgr, "Internal Mic", &max_software_gain); + + ASSERT_TRUE(ret); +} + +TEST(AlsaUcm, MinSoftwareGain) { + struct cras_use_case_mgr* mgr = &cras_ucm_mgr; + long min_software_gain; + int ret; + std::string id = "=MinSoftwareGain/Internal Mic/HiFi"; + std::string value = "2000"; + + ResetStubData(); + + /* Value can be found in UCM. */ + snd_use_case_get_value[id] = value; + + ret = ucm_get_min_software_gain(mgr, "Internal Mic", &min_software_gain); + + EXPECT_EQ(0, ret); + EXPECT_EQ(2000, min_software_gain); + + ResetStubData(); + + /* Value can not be found in UCM. */ + ret = ucm_get_min_software_gain(mgr, "Internal Mic", &min_software_gain); ASSERT_TRUE(ret); } -TEST(AlsaUcm, IntrinsicSensitivity) { +TEST(AlsaUcm, DefaultNodeGain) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - long intrinsic_vol; + long default_node_gain; int ret; - std::string id = "=IntrinsicSensitivity/Internal Mic/HiFi"; + std::string id = "=DefaultNodeGain/Internal Mic/HiFi"; std::string value = "-2000"; ResetStubData(); @@ -961,15 +829,15 @@ TEST(AlsaUcm, IntrinsicSensitivity) { /* Value can be found in UCM. */ snd_use_case_get_value[id] = value; - ret = ucm_get_intrinsic_sensitivity(mgr, "Internal Mic", &intrinsic_vol); + ret = ucm_get_default_node_gain(mgr, "Internal Mic", &default_node_gain); EXPECT_EQ(0, ret); - EXPECT_EQ(-2000, intrinsic_vol); + EXPECT_EQ(-2000, default_node_gain); ResetStubData(); /* Value can not be found in UCM. */ - ret = ucm_get_intrinsic_sensitivity(mgr, "Internal Mic", &intrinsic_vol); + ret = ucm_get_default_node_gain(mgr, "Internal Mic", &default_node_gain); ASSERT_TRUE(ret); } @@ -996,6 +864,28 @@ TEST(AlsaUcm, UseFullySpecifiedUCMConfig) { ASSERT_FALSE(fully_specified_flag); } +TEST(AlsaUcm, EnableHtimestampFlag) { + struct cras_use_case_mgr* mgr = &cras_ucm_mgr; + unsigned int enable_htimestamp_flag; + + std::string id = "=EnableHtimestamp//HiFi"; + ResetStubData(); + + /* Flag is not set */ + enable_htimestamp_flag = ucm_get_enable_htimestamp_flag(mgr); + ASSERT_FALSE(enable_htimestamp_flag); + + /* Flag is set to "1". */ + snd_use_case_get_value[id] = std::string("1"); + enable_htimestamp_flag = ucm_get_enable_htimestamp_flag(mgr); + ASSERT_TRUE(enable_htimestamp_flag); + + /* Flag is set to "0". */ + snd_use_case_get_value[id] = std::string("0"); + enable_htimestamp_flag = ucm_get_enable_htimestamp_flag(mgr); + ASSERT_FALSE(enable_htimestamp_flag); +} + TEST(AlsaUcm, GetMixerNameForDevice) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; const char *mixer_name_1, *mixer_name_2; @@ -1006,15 +896,15 @@ TEST(AlsaUcm, GetMixerNameForDevice) { fake_list["_devices/HiFi"] = devices; fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=PlaybackMixerElem/Dev1/HiFi"; - std::string id_2 = "=CaptureMixerElem/Dev2/HiFi"; + std::string id_1 = "=MixerName/Dev1/HiFi"; + std::string id_2 = "=MixerName/Dev2/HiFi"; std::string value_1 = "MixerName1"; std::string value_2 = "MixerName2"; snd_use_case_get_value[id_1] = value_1; snd_use_case_get_value[id_2] = value_2; - mixer_name_1 = ucm_get_playback_mixer_elem_for_dev(mgr, "Dev1"); - mixer_name_2 = ucm_get_capture_mixer_elem_for_dev(mgr, "Dev2"); + mixer_name_1 = ucm_get_mixer_name_for_dev(mgr, "Dev1"); + mixer_name_2 = ucm_get_mixer_name_for_dev(mgr, "Dev2"); EXPECT_EQ(0, strcmp(mixer_name_1, value_1.c_str())); EXPECT_EQ(0, strcmp(mixer_name_2, value_2.c_str())); @@ -1100,7 +990,7 @@ TEST(AlsaUcm, ListSectionsByDeviceNameInput) { EXPECT_EQ(callback_arg, list_devices_callback_args[1]); } -TEST(AlsaUcm, GetJackDevForDevice) { +TEST(AlsaUcm, GetJackNameForDevice) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; const char *jack_name_1, *jack_name_2; const char* devices[] = {"Dev1", "Comment for Dev1", "Dev2", @@ -1110,12 +1000,12 @@ TEST(AlsaUcm, GetJackDevForDevice) { fake_list["_devices/HiFi"] = devices; fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=JackDev/Dev1/HiFi"; - std::string value_1 = "JackDev1"; + std::string id_1 = "=JackName/Dev1/HiFi"; + std::string value_1 = "JackName1"; snd_use_case_get_value[id_1] = value_1; - jack_name_1 = ucm_get_jack_dev_for_dev(mgr, "Dev1"); - jack_name_2 = ucm_get_jack_dev_for_dev(mgr, "Dev2"); + jack_name_1 = ucm_get_jack_name_for_dev(mgr, "Dev1"); + jack_name_2 = ucm_get_jack_name_for_dev(mgr, "Dev2"); EXPECT_EQ(0, strcmp(jack_name_1, value_1.c_str())); EXPECT_EQ(NULL, jack_name_2); @@ -1124,28 +1014,43 @@ TEST(AlsaUcm, GetJackDevForDevice) { free((void*)jack_name_2); } -TEST(AlsaUcm, GetJackControlForDevice) { +TEST(AlsaUcm, GetJackTypeForDevice) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; - const char *jack_name_1, *jack_name_2; - const char* devices[] = {"Dev1", "Comment for Dev1", "Dev2", - "Comment for Dev2"}; + const char *jack_type_1, *jack_type_2, *jack_type_3, *jack_type_4; + const char* devices[] = { + "Dev1", "Comment for Dev1", "Dev2", "Comment for Dev2", + "Dev3", "Comment for Dev3", "Dev4", "Comment for Dev4"}; ResetStubData(); fake_list["_devices/HiFi"] = devices; - fake_list_size["_devices/HiFi"] = 4; - std::string id_1 = "=JackControl/Dev1/HiFi"; - std::string value_1 = "JackControl1"; + fake_list_size["_devices/HiFi"] = 8; + std::string id_1 = "=JackType/Dev1/HiFi"; + std::string value_1 = "hctl"; + std::string id_2 = "=JackType/Dev2/HiFi"; + std::string value_2 = "gpio"; + std::string id_3 = "=JackType/Dev3/HiFi"; + std::string value_3 = "something"; snd_use_case_get_value[id_1] = value_1; - jack_name_1 = ucm_get_jack_control_for_dev(mgr, "Dev1"); - jack_name_2 = ucm_get_jack_control_for_dev(mgr, "Dev2"); + snd_use_case_get_value[id_2] = value_2; + snd_use_case_get_value[id_3] = value_3; - EXPECT_EQ(0, strcmp(jack_name_1, value_1.c_str())); - EXPECT_EQ(NULL, jack_name_2); + jack_type_1 = ucm_get_jack_type_for_dev(mgr, "Dev1"); + jack_type_2 = ucm_get_jack_type_for_dev(mgr, "Dev2"); + jack_type_3 = ucm_get_jack_type_for_dev(mgr, "Dev3"); + jack_type_4 = ucm_get_jack_type_for_dev(mgr, "Dev4"); - free((void*)jack_name_1); - free((void*)jack_name_2); + /* Only "hctl" and "gpio" are valid types. */ + EXPECT_EQ(0, strcmp(jack_type_1, value_1.c_str())); + EXPECT_EQ(0, strcmp(jack_type_2, value_2.c_str())); + EXPECT_EQ(NULL, jack_type_3); + EXPECT_EQ(NULL, jack_type_4); + + free((void*)jack_type_1); + free((void*)jack_type_2); + free((void*)jack_type_3); + free((void*)jack_type_4); } TEST(AlsaUcm, GetPeriodFramesForDevice) { @@ -1171,6 +1076,7 @@ TEST(AlsaUcm, GetPeriodFramesForDevice) { dma_period_2 = ucm_get_dma_period_for_dev(mgr, "Dev2"); dma_period_3 = ucm_get_dma_period_for_dev(mgr, "Dev3"); + /* Only "hctl" and "gpio" are valid types. */ EXPECT_EQ(1000, dma_period_1); EXPECT_EQ(0, dma_period_2); EXPECT_EQ(0, dma_period_3); @@ -1182,22 +1088,18 @@ TEST(AlsaUcm, UcmSection) { struct mixer_name* controls = NULL; struct mixer_name* m_name; int dev_idx = 0; - int dependent_dev_idx = -1; size_t i; enum CRAS_STREAM_DIRECTION dir = CRAS_STREAM_OUTPUT; static const char* name = "Headphone"; - static const char* pcm_name = "hw:0,1"; static const char* jack_name = "my-card-name Headset Jack"; static const char* jack_type = "gpio"; static const char* mixer_name = "Control1"; static const char* coupled_names[] = {"Coupled1", "Coupled2"}; - section = - ucm_section_create(NULL, NULL, 0, -1, CRAS_STREAM_OUTPUT, NULL, NULL); + section = ucm_section_create(NULL, 0, CRAS_STREAM_OUTPUT, NULL, NULL); EXPECT_EQ(reinterpret_cast<struct ucm_section*>(NULL), section); - section = ucm_section_create(name, pcm_name, dev_idx, dependent_dev_idx, dir, - jack_name, jack_type); + section = ucm_section_create(name, dev_idx, dir, jack_name, jack_type); EXPECT_NE(reinterpret_cast<struct ucm_section*>(NULL), section); EXPECT_NE(name, section->name); EXPECT_EQ(0, strcmp(name, section->name)); @@ -1252,7 +1154,6 @@ TEST(AlsaUcm, GetSections) { struct ucm_section* section; struct mixer_name* m_name; int section_count = 0; - int dev_idx; int i = 0; const char* devices[] = {"Headphone", "The headphones jack.", "Speaker", "The speakers.", @@ -1260,47 +1161,49 @@ TEST(AlsaUcm, GetSections) { "Internal Mic", "Internal Microphones", "HDMI", "HDMI output"}; const char* ids[] = {"=PlaybackPCM/Headphone/HiFi", - "=JackDev/Headphone/HiFi", + "=JackName/Headphone/HiFi", + "=JackType/Headphone/HiFi", "=JackSwitch/Headphone/HiFi", "=CoupledMixers/Headphone/HiFi", "=PlaybackPCM/Speaker/HiFi", "=CoupledMixers/Speaker/HiFi", - "=DependentPCM/Speaker/HiFi", "=CapturePCM/Mic/HiFi", - "=JackDev/Mic/HiFi", + "=JackName/Mic/HiFi", + "=JackType/Mic/HiFi", "=JackSwitch/Mic/HiFi", - "=CaptureMixerElem/Mic/HiFi", + "=MixerName/Mic/HiFi", "=CapturePCM/Internal Mic/HiFi", "=CoupledMixers/Internal Mic/HiFi", "=JackSwitch/Internal Mic/HiFi", "=PlaybackPCM/HDMI/HiFi", - "=PlaybackMixerElem/HDMI/HiFi", + "=MixerName/HDMI/HiFi", NULL}; const char* values[] = { "hw:my-sound-card,0", "my-sound-card Headset Jack", + "gpio", "2", "HP-L,HP-R", - "hw:my-sound-card,1", - "SPK-L,SPK-R", "hw:my-sound-card,0", + "SPK-L,SPK-R", - "hw:my-sound-card,2", + "hw:my-sound-card,0", "my-sound-card Headset Jack", + "gpio", "0", "CAPTURE", - "hw:my-sound-card,3", + "hw:my-sound-card,0", "MIC-L,MIC-R", "-10", - "hw:my-sound-card,4", + "hw:my-sound-card,2", "HDMI", }; @@ -1321,12 +1224,11 @@ TEST(AlsaUcm, GetSections) { // Headphone section = sections; - EXPECT_EQ(0, strcmp(section->pcm_name, "hw:my-sound-card,0")); EXPECT_EQ(0, strcmp(section->name, "Headphone")); EXPECT_EQ(0, section->dev_idx); EXPECT_EQ(CRAS_STREAM_OUTPUT, section->dir); EXPECT_EQ(0, strcmp(section->jack_name, values[1])); - EXPECT_EQ(0, strcmp(section->jack_type, "gpio")); + EXPECT_EQ(0, strcmp(section->jack_type, values[2])); EXPECT_EQ(NULL, section->mixer_name); ASSERT_NE((struct mixer_name*)NULL, section->coupled); m_name = section->coupled; @@ -1335,19 +1237,16 @@ TEST(AlsaUcm, GetSections) { EXPECT_EQ(0, strcmp(m_name->name, "HP-R")); EXPECT_EQ(NULL, m_name->next); EXPECT_EQ(2, section->jack_switch); - dev_idx = section->dev_idx; // Speaker section = section->next; - EXPECT_EQ(0, strcmp(section->pcm_name, "hw:my-sound-card,1")); EXPECT_EQ(0, strcmp(section->name, "Speaker")); - EXPECT_EQ(1, section->dev_idx); + EXPECT_EQ(0, section->dev_idx); EXPECT_EQ(CRAS_STREAM_OUTPUT, section->dir); EXPECT_EQ(NULL, section->jack_name); EXPECT_EQ(NULL, section->jack_type); EXPECT_EQ(-1, section->jack_switch); EXPECT_EQ(NULL, section->mixer_name); - EXPECT_EQ(dev_idx, section->dependent_dev_idx); ASSERT_NE((struct mixer_name*)NULL, section->coupled); m_name = section->coupled; EXPECT_EQ(0, strcmp(m_name->name, "SPK-L")); @@ -1357,12 +1256,11 @@ TEST(AlsaUcm, GetSections) { // Mic section = section->next; - EXPECT_EQ(0, strcmp(section->pcm_name, "hw:my-sound-card,2")); EXPECT_EQ(0, strcmp(section->name, "Mic")); - EXPECT_EQ(2, section->dev_idx); + EXPECT_EQ(0, section->dev_idx); EXPECT_EQ(CRAS_STREAM_INPUT, section->dir); EXPECT_EQ(0, strcmp(section->jack_name, values[1])); - EXPECT_EQ(0, strcmp(section->jack_type, "gpio")); + EXPECT_EQ(0, strcmp(section->jack_type, values[2])); EXPECT_EQ(0, section->jack_switch); ASSERT_NE((const char*)NULL, section->mixer_name); EXPECT_EQ(0, strcmp(section->mixer_name, "CAPTURE")); @@ -1370,9 +1268,8 @@ TEST(AlsaUcm, GetSections) { // Internal Mic section = section->next; - EXPECT_EQ(0, strcmp(section->pcm_name, "hw:my-sound-card,3")); EXPECT_EQ(0, strcmp(section->name, "Internal Mic")); - EXPECT_EQ(3, section->dev_idx); + EXPECT_EQ(0, section->dev_idx); EXPECT_EQ(CRAS_STREAM_INPUT, section->dir); EXPECT_EQ(NULL, section->jack_name); EXPECT_EQ(NULL, section->jack_type); @@ -1386,9 +1283,8 @@ TEST(AlsaUcm, GetSections) { // HDMI section = section->next; - EXPECT_EQ(0, strcmp(section->pcm_name, "hw:my-sound-card,4")); EXPECT_EQ(0, strcmp(section->name, "HDMI")); - EXPECT_EQ(4, section->dev_idx); + EXPECT_EQ(2, section->dev_idx); EXPECT_EQ(CRAS_STREAM_OUTPUT, section->dir); EXPECT_EQ(NULL, section->jack_name); EXPECT_EQ(NULL, section->jack_type); @@ -1405,7 +1301,7 @@ TEST(AlsaUcm, GetSectionsMissingPCM) { struct ucm_section* sections; int i = 0; const char* devices[] = {"Headphone", "The headphones jack."}; - const char* ids[] = {"=JackDev/Headphone/HiFi", + const char* ids[] = {"=JackName/Headphone/HiFi", "=CoupledMixers/Headphone/HiFi", NULL}; const char* values[] = { "my-sound-card Headset Jack", @@ -1426,6 +1322,34 @@ TEST(AlsaUcm, GetSectionsMissingPCM) { EXPECT_EQ(NULL, sections); } +TEST(AlsaUcm, GetSectionsBadPCM) { + struct cras_use_case_mgr* mgr = &cras_ucm_mgr; + struct ucm_section* sections; + int i = 0; + const char* devices[] = {"Headphone", "The headphones jack."}; + const char* ids[] = {"=PlaybackPCM/Headphone/HiFi", + "=JackName/Headphone/HiFi", + "=CoupledMixers/Headphone/HiFi", NULL}; + const char* values[] = { + "hw:my-sound-card:0", + "my-sound-card Headset Jack", + "HP-L,HP-R", + }; + + ResetStubData(); + + fake_list["_devices/HiFi"] = devices; + fake_list_size["_devices/HiFi"] = ARRAY_SIZE(devices); + + while (ids[i]) { + snd_use_case_get_value[ids[i]] = values[i]; + i++; + } + + sections = ucm_get_sections(mgr); + EXPECT_EQ(NULL, sections); +} + TEST(AlsaUcm, CheckUseCaseVerbs) { struct cras_use_case_mgr* mgr = &cras_ucm_mgr; @@ -1540,19 +1464,6 @@ int snd_use_case_free_list(const char* list[], int items) { return 0; } -int snd_use_case_geti(snd_use_case_mgr_t* uc_mgr, - const char* identifier, - long* value) { - snd_use_case_geti_called++; - if (snd_use_case_geti_value.find(identifier) == - snd_use_case_geti_value.end()) { - *value = 0; - return -1; - } - *value = snd_use_case_geti_value[identifier]; - return 0; -} - } /* extern "C" */ } // namespace diff --git a/cras/src/tests/apm_list_unittest.cc b/cras/src/tests/apm_list_unittest.cc index 65e712fb..2c91cf9b 100644 --- a/cras/src/tests/apm_list_unittest.cc +++ b/cras/src/tests/apm_list_unittest.cc @@ -16,8 +16,6 @@ extern "C" { #include "webrtc_apm.h" } -#define FILENAME_TEMPLATE "ApmTest.XXXXXX" - namespace { static void* stream_ptr = reinterpret_cast<void*>(0x123); @@ -30,12 +28,8 @@ static unsigned int webrtc_apm_process_stream_f_called; static unsigned int webrtc_apm_process_reverse_stream_f_called; static device_enabled_callback_t device_enabled_callback_val; static struct ext_dsp_module* ext_dsp_module_value; -static struct cras_ionode fake_node; static struct cras_iodev fake_iodev; static int webrtc_apm_create_called; -static bool cras_iodev_is_aec_use_case_ret; -static dictionary* webrtc_apm_create_aec_ini_val = NULL; -static dictionary* webrtc_apm_create_apm_ini_val = NULL; TEST(ApmList, ApmListCreate) { list = cras_apm_list_create(stream_ptr, 0); @@ -48,175 +42,30 @@ TEST(ApmList, ApmListCreate) { cras_apm_list_destroy(list); } -static char* prepare_tempdir() { - char dirname[sizeof(FILENAME_TEMPLATE) + 1]; - char filename[64]; - char* tempdir; - FILE* fp; - - strcpy(dirname, FILENAME_TEMPLATE); - tempdir = mkdtemp(dirname); - snprintf(filename, 64, "%s/apm.ini", tempdir); - fp = fopen(filename, "w"); - fprintf(fp, "%s", "[foo]\n"); - fclose(fp); - fp = NULL; - snprintf(filename, 64, "%s/aec.ini", tempdir); - fp = fopen(filename, "w"); - fprintf(fp, "%s", "[bar]\n"); - fclose(fp); - fp = NULL; - return strdup(tempdir); -} - -static void delete_tempdir(char* dir) { - char filename[64]; - - snprintf(filename, 64, "%s/apm.ini", dir); - unlink(filename); - snprintf(filename, 64, "%s/aec.ini", dir); - unlink(filename); - rmdir(dir); -} - -static void init_channel_layout(struct cras_audio_format* fmt) { - int i; - for (i = 0; i < CRAS_CH_MAX; i++) - fmt->channel_layout[i] = -1; -} - -TEST(ApmList, AddApmInputDevUnuseFirstChannel) { - struct cras_audio_format fmt; - struct cras_audio_format* val; - struct cras_apm* apm; - int ch; - const int num_test_casts = 9; - int test_layouts[num_test_casts][CRAS_CH_MAX] = { - {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; - int test_num_channels[num_test_casts] = {1, 2, 2, 2, 2, 3, 4, 4, 4}; - - fmt.frame_rate = 48000; - fmt.format = SND_PCM_FORMAT_S16_LE; - - cras_apm_list_init(""); - list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION); - EXPECT_NE((void*)NULL, list); - - for (int i = 0; i < num_test_casts; i++) { - fmt.num_channels = test_num_channels[i]; - init_channel_layout(&fmt); - for (ch = 0; ch < CRAS_CH_MAX; ch++) - fmt.channel_layout[ch] = test_layouts[i][ch]; - - /* Input dev is of aec use case. */ - apm = cras_apm_list_add_apm(list, dev_ptr, &fmt, 1); - EXPECT_NE((void*)NULL, apm); - - /* Assert that the post-processing format never has an unset - * first channel in the layout. */ - bool first_channel_found_in_layout = 0; - val = cras_apm_list_get_format(apm); - for (ch = 0; ch < CRAS_CH_MAX; ch++) - if (0 == val->channel_layout[ch]) - first_channel_found_in_layout = 1; - - EXPECT_EQ(1, first_channel_found_in_layout); - - cras_apm_list_remove_apm(list, dev_ptr); - } - - cras_apm_list_destroy(list); - cras_apm_list_deinit(); -} - TEST(ApmList, AddRemoveApm) { struct cras_audio_format fmt; - char* dir; fmt.num_channels = 2; fmt.frame_rate = 48000; fmt.format = SND_PCM_FORMAT_S16_LE; - fake_iodev.active_node = &fake_node; - fake_node.type = CRAS_NODE_TYPE_INTERNAL_SPEAKER; - - dir = prepare_tempdir(); - cras_apm_list_init(dir); - cras_iodev_is_aec_use_case_ret = 1; list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION); EXPECT_NE((void*)NULL, list); - /* Input dev is of aec use case. */ - EXPECT_NE((void*)NULL, cras_apm_list_add_apm(list, dev_ptr, &fmt, 1)); - EXPECT_NE((void*)NULL, webrtc_apm_create_aec_ini_val); - EXPECT_NE((void*)NULL, webrtc_apm_create_apm_ini_val); - EXPECT_EQ((void*)NULL, cras_apm_list_get_active_apm(stream_ptr, dev_ptr)); - - cras_apm_list_start_apm(list, dev_ptr); - EXPECT_NE((void*)NULL, cras_apm_list_get_active_apm(stream_ptr, dev_ptr)); - EXPECT_EQ((void*)NULL, cras_apm_list_get_active_apm(stream_ptr, dev_ptr2)); - - /* Input dev is not of aec use case. */ - EXPECT_NE((void*)NULL, cras_apm_list_add_apm(list, dev_ptr2, &fmt, 0)); - EXPECT_EQ((void*)NULL, webrtc_apm_create_aec_ini_val); - EXPECT_EQ((void*)NULL, webrtc_apm_create_apm_ini_val); - cras_apm_list_start_apm(list, dev_ptr2); - cras_apm_list_stop_apm(list, dev_ptr); - - EXPECT_EQ((void*)NULL, cras_apm_list_get_active_apm(stream_ptr, dev_ptr)); - EXPECT_NE((void*)NULL, cras_apm_list_get_active_apm(stream_ptr, dev_ptr2)); - - cras_apm_list_stop_apm(list, dev_ptr2); - cras_apm_list_remove_apm(list, dev_ptr); - cras_apm_list_remove_apm(list, dev_ptr2); - - cras_apm_list_destroy(list); - cras_apm_list_deinit(); - delete_tempdir(dir); - free(dir); -} - -TEST(ApmList, OutputTypeNotAecUseCase) { - struct cras_audio_format fmt; - char* dir; - - fmt.num_channels = 2; - fmt.frame_rate = 48000; - fmt.format = SND_PCM_FORMAT_S16_LE; - fake_iodev.active_node = &fake_node; - - dir = prepare_tempdir(); - cras_apm_list_init(dir); + EXPECT_NE((void*)NULL, cras_apm_list_add(list, dev_ptr, &fmt)); + EXPECT_EQ((void*)NULL, cras_apm_list_get(list, dev_ptr2)); - list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION); - EXPECT_NE((void*)NULL, list); + EXPECT_NE((void*)NULL, cras_apm_list_add(list, dev_ptr2, &fmt)); + EXPECT_NE((void*)NULL, cras_apm_list_get(list, dev_ptr)); - /* Output device is of aec use case. */ - cras_iodev_is_aec_use_case_ret = 1; - EXPECT_NE((void*)NULL, cras_apm_list_add_apm(list, dev_ptr, &fmt, 1)); - EXPECT_NE((void*)NULL, webrtc_apm_create_aec_ini_val); - EXPECT_NE((void*)NULL, webrtc_apm_create_apm_ini_val); - cras_apm_list_remove_apm(list, dev_ptr); + cras_apm_list_remove(list, dev_ptr); + EXPECT_EQ((void*)NULL, cras_apm_list_get(list, dev_ptr)); + EXPECT_NE((void*)NULL, cras_apm_list_get(list, dev_ptr2)); - /* Output device is not of aec use case. */ - cras_iodev_is_aec_use_case_ret = 0; - EXPECT_NE((void*)NULL, cras_apm_list_add_apm(list, dev_ptr, &fmt, 1)); - EXPECT_EQ((void*)NULL, webrtc_apm_create_aec_ini_val); - EXPECT_EQ((void*)NULL, webrtc_apm_create_apm_ini_val); - cras_apm_list_remove_apm(list, dev_ptr); + cras_apm_list_remove(list, dev_ptr2); + EXPECT_EQ((void*)NULL, cras_apm_list_get(list, dev_ptr2)); cras_apm_list_destroy(list); - cras_apm_list_deinit(); - delete_tempdir(dir); - free(dir); } TEST(ApmList, ApmProcessForwardBuffer) { @@ -228,16 +77,11 @@ TEST(ApmList, ApmProcessForwardBuffer) { fmt.num_channels = 2; fmt.frame_rate = 48000; fmt.format = SND_PCM_FORMAT_S16_LE; - init_channel_layout(&fmt); - fmt.channel_layout[CRAS_CH_FL] = 0; - fmt.channel_layout[CRAS_CH_FR] = 1; - - cras_apm_list_init(""); list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION); EXPECT_NE((void*)NULL, list); - apm = cras_apm_list_add_apm(list, dev_ptr, &fmt, 1); + apm = cras_apm_list_add(list, dev_ptr, &fmt); buf = float_buffer_create(500, 2); float_buffer_written(buf, 300); @@ -274,7 +118,6 @@ TEST(ApmList, ApmProcessForwardBuffer) { float_buffer_destroy(&buf); cras_apm_list_destroy(list); - cras_apm_list_deinit(); } TEST(ApmList, ApmProcessReverseData) { @@ -316,8 +159,7 @@ TEST(ApmList, ApmProcessReverseData) { list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION); EXPECT_NE((void*)NULL, list); - apm = cras_apm_list_add_apm(list, dev_ptr, &fmt, 1); - cras_apm_list_start_apm(list, dev_ptr); + apm = cras_apm_list_add(list, dev_ptr, &fmt); ext_dsp_module_value->run(ext_dsp_module_value, 250); EXPECT_EQ(0, webrtc_apm_process_reverse_stream_f_called); @@ -338,22 +180,19 @@ TEST(ApmList, StreamAddToAlreadyOpenedDev) { fmt.frame_rate = 48000; fmt.format = SND_PCM_FORMAT_S16_LE; - cras_apm_list_init(""); - webrtc_apm_create_called = 0; list = cras_apm_list_create(stream_ptr, APM_ECHO_CANCELLATION); EXPECT_NE((void*)NULL, list); - apm1 = cras_apm_list_add_apm(list, dev_ptr, &fmt, 1); + apm1 = cras_apm_list_add(list, dev_ptr, &fmt); EXPECT_EQ(1, webrtc_apm_create_called); EXPECT_NE((void*)NULL, apm1); - apm2 = cras_apm_list_add_apm(list, dev_ptr, &fmt, 1); + apm2 = cras_apm_list_add(list, dev_ptr, &fmt); EXPECT_EQ(1, webrtc_apm_create_called); EXPECT_EQ(apm1, apm2); cras_apm_list_destroy(list); - cras_apm_list_deinit(); } extern "C" { @@ -372,9 +211,6 @@ void cras_iodev_set_ext_dsp_module(struct cras_iodev* iodev, struct ext_dsp_module* ext) { ext_dsp_module_value = ext; } -bool cras_iodev_is_aec_use_case(const struct cras_ionode* node) { - return cras_iodev_is_aec_use_case_ret; -} struct cras_audio_area* cras_audio_area_create(int num_channels) { return &fake_audio_area; } @@ -405,8 +241,6 @@ webrtc_apm webrtc_apm_create(unsigned int num_channels, dictionary* aec_ini, dictionary* apm_ini) { webrtc_apm_create_called++; - webrtc_apm_create_aec_ini_val = aec_ini; - webrtc_apm_create_apm_ini_val = apm_ini; return reinterpret_cast<webrtc_apm>(0x11); } void webrtc_apm_dump_configs(dictionary* aec_ini, dictionary* apm_ini) {} diff --git a/cras/src/tests/audio_thread_unittest.cc b/cras/src/tests/audio_thread_unittest.cc index 93045e0b..e06514e3 100644 --- a/cras/src/tests/audio_thread_unittest.cc +++ b/cras/src/tests/audio_thread_unittest.cc @@ -18,7 +18,6 @@ extern "C" { #define FIRST_CB_LEVEL 480 static int cras_audio_thread_event_busyloop_called; -static int cras_audio_thread_event_severe_underrun_called; static unsigned int cras_rstream_dev_offset_called; static unsigned int cras_rstream_dev_offset_ret[MAX_CALLS]; static const struct cras_rstream* @@ -56,7 +55,6 @@ static struct cras_iodev* cras_iodev_start_ramp_odev; static enum CRAS_IODEV_RAMP_REQUEST cras_iodev_start_ramp_request; static struct timespec clock_gettime_retspec; static struct timespec init_cb_ts_; -static struct timespec sleep_interval_ts_; static std::map<const struct dev_stream*, struct timespec> dev_stream_wake_time_val; static int cras_device_monitor_set_device_mute_state_called; @@ -965,7 +963,6 @@ TEST_F(StreamDeviceSuite, DoPlaybackSevereUnderrun) { thread_add_stream(thread_, &rstream, &piodev, 1); // Assume device is running and there is a severe underrun. - cras_audio_thread_event_severe_underrun_called = 0; iodev.state = CRAS_IODEV_STATE_NORMAL_RUN; frames_queued_ = -EPIPE; @@ -978,7 +975,6 @@ TEST_F(StreamDeviceSuite, DoPlaybackSevereUnderrun) { // Audio thread should ask main thread to reset device. EXPECT_EQ(1, cras_iodev_reset_request_called); EXPECT_EQ(&iodev, cras_iodev_reset_request_iodev); - EXPECT_EQ(1, cras_audio_thread_event_severe_underrun_called); thread_rm_open_dev(thread_, CRAS_STREAM_OUTPUT, iodev.info.idx); TearDownRstream(&rstream); @@ -1226,12 +1222,10 @@ struct dev_stream* dev_stream_create(struct cras_rstream* stream, unsigned int dev_id, const struct cras_audio_format* dev_fmt, void* dev_ptr, - struct timespec* cb_ts, - const struct timespec* sleep_interval_ts) { + struct timespec* cb_ts) { struct dev_stream* out = static_cast<dev_stream*>(calloc(1, sizeof(*out))); out->stream = stream; init_cb_ts_ = *cb_ts; - sleep_interval_ts_ = *sleep_interval_ts; return out; } @@ -1271,7 +1265,7 @@ void dev_stream_set_delay(const struct dev_stream* dev_stream, void dev_stream_set_dev_rate(struct dev_stream* dev_stream, unsigned int dev_rate, double dev_rate_ratio, - double main_rate_ratio, + double master_rate_ratio, int coarse_rate_adjust) {} void dev_stream_update_frames(const struct dev_stream* dev_stream) {} @@ -1317,9 +1311,7 @@ int cras_iodev_fill_odev_zeros(struct cras_iodev* odev, unsigned int frames) { return 0; } -int cras_iodev_output_underrun(struct cras_iodev* odev, - unsigned int hw_level, - unsigned int frames_written) { +int cras_iodev_output_underrun(struct cras_iodev* odev) { cras_iodev_output_underrun_called++; return 0; } @@ -1412,19 +1404,12 @@ int cras_device_monitor_set_device_mute_state(unsigned int dev_idx) { cras_device_monitor_set_device_mute_state_called++; return 0; } -int cras_device_monitor_error_close(unsigned int dev_idx) { - return 0; -} int cras_iodev_drop_frames_by_time(struct cras_iodev* iodev, struct timespec ts) { return 0; } -bool cras_iodev_is_on_internal_card(const struct cras_ionode* node) { - return 0; -} - // From librt. int clock_gettime(clockid_t clk_id, struct timespec* tp) { *tp = clock_gettime_retspec; @@ -1457,16 +1442,6 @@ int cras_audio_thread_event_drop_samples() { return 0; } -int cras_audio_thread_event_severe_underrun() { - cras_audio_thread_event_severe_underrun_called++; - return 0; -} - -float input_data_get_software_gain_scaler(struct input_data* data, - float idev_sw_gain_scaler, - struct cras_rstream* stream) { - return 1.0; -} } // extern "C" int main(int argc, char** argv) { diff --git a/cras/src/tests/audio_thread_unittest_obsolete.cc b/cras/src/tests/audio_thread_unittest_obsolete.cc index ae9f5ef3..0baeb38f 100644 --- a/cras/src/tests/audio_thread_unittest_obsolete.cc +++ b/cras/src/tests/audio_thread_unittest_obsolete.cc @@ -52,8 +52,8 @@ static unsigned int dev_stream_mix_called; static struct timespec time_now; static int cras_fmt_conversion_needed_return_val; -static struct cras_audio_area* mock_audio_area1; -static struct cras_audio_area* mock_audio_area2; +static struct cras_audio_area* dummy_audio_area1; +static struct cras_audio_area* dummy_audio_area2; static struct cras_audio_format cras_iodev_set_format_val; static struct dev_stream_capture_call dev_stream_capture_call; @@ -95,18 +95,18 @@ class ReadStreamSuite : public testing::Test { SetupRstream(&rstream2_, 2); shm2_ = cras_rstream_input_shm(rstream2_); - mock_audio_area1 = (cras_audio_area*)calloc( + dummy_audio_area1 = (cras_audio_area*)calloc( 1, sizeof(cras_audio_area) + 2 * sizeof(cras_channel_area)); - mock_audio_area1->num_channels = 2; - channel_area_set_channel(&mock_audio_area1->channels[0], CRAS_CH_FL); - channel_area_set_channel(&mock_audio_area1->channels[1], CRAS_CH_FR); - rstream_->input_audio_area = mock_audio_area1; - mock_audio_area2 = (cras_audio_area*)calloc( + dummy_audio_area1->num_channels = 2; + channel_area_set_channel(&dummy_audio_area1->channels[0], CRAS_CH_FL); + channel_area_set_channel(&dummy_audio_area1->channels[1], CRAS_CH_FR); + rstream_->input_audio_area = dummy_audio_area1; + dummy_audio_area2 = (cras_audio_area*)calloc( 1, sizeof(cras_audio_area) + 2 * sizeof(cras_channel_area)); - mock_audio_area2->num_channels = 2; - channel_area_set_channel(&mock_audio_area2->channels[0], CRAS_CH_FL); - channel_area_set_channel(&mock_audio_area2->channels[1], CRAS_CH_FR); - rstream2_->input_audio_area = mock_audio_area2; + dummy_audio_area2->num_channels = 2; + channel_area_set_channel(&dummy_audio_area2->channels[0], CRAS_CH_FL); + channel_area_set_channel(&dummy_audio_area2->channels[1], CRAS_CH_FR); + rstream2_->input_audio_area = dummy_audio_area2; dev_stream_mix_dont_fill_next = 0; dev_stream_mix_count = 0; @@ -123,8 +123,8 @@ class ReadStreamSuite : public testing::Test { free(rstream_); free(shm2_->area); free(rstream2_); - free(mock_audio_area1); - free(mock_audio_area2); + free(dummy_audio_area1); + free(dummy_audio_area2); } void SetupRstream(struct cras_rstream** rstream, int fd) { @@ -1444,18 +1444,18 @@ class ActiveDevicesSuite : public testing::Test { rstream2_->buffer_frames -= 50; rstream2_->cb_threshold -= 50; - mock_audio_area1 = (cras_audio_area*)calloc( + dummy_audio_area1 = (cras_audio_area*)calloc( 1, sizeof(cras_audio_area) + 2 * sizeof(cras_channel_area)); - mock_audio_area1->num_channels = 2; - channel_area_set_channel(&mock_audio_area1->channels[0], CRAS_CH_FL); - channel_area_set_channel(&mock_audio_area1->channels[1], CRAS_CH_FR); - rstream_->input_audio_area = mock_audio_area1; - mock_audio_area2 = (cras_audio_area*)calloc( + dummy_audio_area1->num_channels = 2; + channel_area_set_channel(&dummy_audio_area1->channels[0], CRAS_CH_FL); + channel_area_set_channel(&dummy_audio_area1->channels[1], CRAS_CH_FR); + rstream_->input_audio_area = dummy_audio_area1; + dummy_audio_area2 = (cras_audio_area*)calloc( 1, sizeof(cras_audio_area) + 2 * sizeof(cras_channel_area)); - mock_audio_area2->num_channels = 2; - channel_area_set_channel(&mock_audio_area2->channels[0], CRAS_CH_FL); - channel_area_set_channel(&mock_audio_area2->channels[1], CRAS_CH_FR); - rstream2_->input_audio_area = mock_audio_area2; + dummy_audio_area2->num_channels = 2; + channel_area_set_channel(&dummy_audio_area2->channels[0], CRAS_CH_FL); + channel_area_set_channel(&dummy_audio_area2->channels[1], CRAS_CH_FR); + rstream2_->input_audio_area = dummy_audio_area2; cras_iodev_set_format_called = 0; close_dev_called_ = 0; @@ -1483,8 +1483,8 @@ class ActiveDevicesSuite : public testing::Test { shm = cras_rstream_output_shm(rstream_); free(shm->header); free(rstream_); - free(mock_audio_area1); - free(mock_audio_area2); + free(dummy_audio_area1); + free(dummy_audio_area2); } void SetupRstream(struct cras_rstream** rstream) { diff --git a/cras/src/tests/bt_device_unittest.cc b/cras/src/tests/bt_device_unittest.cc index ccb581cc..d2e9a13f 100644 --- a/cras/src/tests/bt_device_unittest.cc +++ b/cras/src/tests/bt_device_unittest.cc @@ -15,8 +15,6 @@ extern "C" { #define FAKE_OBJ_PATH "/obj/path" } -static const unsigned int CONN_WATCH_MAX_RETRIES = 30; - static struct cras_iodev* cras_bt_io_create_profile_ret; static struct cras_iodev* cras_bt_io_append_btio_val; static struct cras_ionode* cras_bt_io_get_profile_ret; @@ -32,7 +30,6 @@ static cras_main_message* cras_main_message_send_msg; static cras_message_callback cras_main_message_add_handler_callback; static void* cras_main_message_add_handler_callback_data; static int cras_tm_create_timer_called; -static int cras_tm_cancel_timer_called; static int cras_a2dp_start_called; static int cras_a2dp_suspend_connected_device_called; static int cras_hfp_ag_remove_conflict_called; @@ -44,10 +41,6 @@ static int dbus_message_new_method_call_called; static const char* dbus_message_new_method_call_method; static struct cras_bt_device* cras_a2dp_connected_device_ret; static struct cras_bt_device* cras_a2dp_suspend_connected_device_dev; -static struct cras_timer* cras_tm_cancel_timer_arg; -static struct cras_timer* cras_tm_create_timer_ret; -static size_t cras_iodev_set_node_plugged_called; -static int cras_iodev_set_node_plugged_value; struct MockDBusMessage { int type; @@ -65,7 +58,6 @@ void ResetStubData() { cras_bt_io_try_remove_ret = 0; cras_main_message_send_msg = NULL; cras_tm_create_timer_called = 0; - cras_tm_cancel_timer_called = 0; cras_a2dp_start_called = 0; cras_a2dp_suspend_connected_device_called = 0; cras_hfp_ag_remove_conflict_called = 0; @@ -74,7 +66,6 @@ void ResetStubData() { dbus_message_new_method_call_method = NULL; dbus_message_new_method_call_called = 0; cras_a2dp_connected_device_ret = NULL; - cras_iodev_set_node_plugged_called = 0; } static void FreeMockDBusMessage(MockDBusMessage* head) { @@ -87,12 +78,11 @@ static void FreeMockDBusMessage(MockDBusMessage* head) { delete head; } -static struct MockDBusMessage* NewMockDBusConnectedMessage(long connected) { +static struct MockDBusMessage* NewMockDBusConnectedMessage() { MockDBusMessage* msg = new MockDBusMessage{DBUS_TYPE_ARRAY, NULL}; MockDBusMessage* dict = new MockDBusMessage{DBUS_TYPE_STRING, (void*)strdup("Connected")}; - MockDBusMessage* variant = - new MockDBusMessage{DBUS_TYPE_BOOLEAN, (void*)connected}; + MockDBusMessage* variant = new MockDBusMessage{DBUS_TYPE_BOOLEAN, (void*)1}; msg->recurse = dict; dict->next = new MockDBusMessage{DBUS_TYPE_INVALID, NULL}; @@ -176,8 +166,6 @@ TEST_F(BtDeviceTestSuite, AppendRmIodev) { CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); cras_bt_device_rm_iodev(device, &d2_); EXPECT_EQ(1, cras_bt_io_remove_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_value); /* Test A2DP disconnection will cause bt_io destroy. */ cras_bt_io_try_remove_ret = 0; @@ -185,8 +173,6 @@ TEST_F(BtDeviceTestSuite, AppendRmIodev) { EXPECT_EQ(1, cras_bt_io_remove_called); EXPECT_EQ(1, cras_bt_io_destroy_called); EXPECT_EQ(0, cras_bt_device_get_active_profile(device)); - EXPECT_EQ(2, cras_iodev_set_node_plugged_called); - EXPECT_EQ(0, cras_iodev_set_node_plugged_value); cras_bt_device_remove(device); } @@ -228,10 +214,9 @@ TEST_F(BtDeviceTestSuite, SetDeviceConnectedA2dpOnly) { device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); EXPECT_NE((void*)NULL, device); - cras_bt_device_set_supported_profiles(device, - CRAS_BT_DEVICE_PROFILE_A2DP_SINK); + cras_bt_device_add_supported_profiles(device, A2DP_SINK_UUID); - cur = msg_root = NewMockDBusConnectedMessage(1); + cur = msg_root = NewMockDBusConnectedMessage(); cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); EXPECT_EQ(1, cras_tm_create_timer_called); EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); @@ -239,22 +224,14 @@ TEST_F(BtDeviceTestSuite, SetDeviceConnectedA2dpOnly) { /* Schedule another timer, if A2DP not yet configured. */ cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(2, cras_tm_create_timer_called); - - /* ConnectProfile must not be called, since this is A2DP only case. */ - EXPECT_EQ(0, dbus_message_new_method_call_called); + EXPECT_EQ(1, dbus_message_new_method_call_called); + EXPECT_STREQ("ConnectProfile", dbus_message_new_method_call_method); cras_bt_device_a2dp_configured(device); - - /* Prepate the iodev created by cras_a2dp_start. */ - cras_bt_io_create_profile_ret = &bt_iodev1; - cras_bt_device_append_iodev(device, &d1_, CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); - cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(2, cras_tm_create_timer_called); EXPECT_EQ(1, cras_hfp_ag_remove_conflict_called); EXPECT_EQ(1, cras_a2dp_start_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_value); cras_bt_device_remove(device); FreeMockDBusMessage(msg_root); @@ -269,11 +246,10 @@ TEST_F(BtDeviceTestSuite, SetDeviceConnectedHfpHspOnly) { device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); EXPECT_NE((void*)NULL, device); - cras_bt_device_set_supported_profiles( - device, CRAS_BT_DEVICE_PROFILE_HSP_HEADSET | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); + cras_bt_device_add_supported_profiles(device, HSP_HS_UUID); + cras_bt_device_add_supported_profiles(device, HFP_HF_UUID); - cur = msg_root = NewMockDBusConnectedMessage(1); + cur = msg_root = NewMockDBusConnectedMessage(); cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); EXPECT_EQ(1, cras_tm_create_timer_called); EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); @@ -281,23 +257,15 @@ TEST_F(BtDeviceTestSuite, SetDeviceConnectedHfpHspOnly) { /* Schedule another timer, if HFP AG not yet intialized. */ cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(2, cras_tm_create_timer_called); - - /* ConnectProfile must not be called, since this is HFP only case. */ - EXPECT_EQ(0, dbus_message_new_method_call_called); + EXPECT_EQ(1, dbus_message_new_method_call_called); + EXPECT_STREQ("ConnectProfile", dbus_message_new_method_call_method); cras_bt_device_audio_gateway_initialized(device); - /* Prepate the iodev created by ag initialization. */ - cras_bt_io_create_profile_ret = &bt_iodev2; - cras_bt_device_append_iodev(device, &d3_, - CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(2, cras_tm_create_timer_called); EXPECT_EQ(1, cras_hfp_ag_remove_conflict_called); EXPECT_EQ(1, cras_hfp_ag_start_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_called); - EXPECT_EQ(1, cras_iodev_set_node_plugged_value); cras_bt_device_remove(device); FreeMockDBusMessage(msg_root); @@ -312,12 +280,11 @@ TEST_F(BtDeviceTestSuite, SetDeviceConnectedA2dpHfpHsp) { device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); EXPECT_NE((void*)NULL, device); - cras_bt_device_set_supported_profiles( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK | - CRAS_BT_DEVICE_PROFILE_HSP_HEADSET | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); + cras_bt_device_add_supported_profiles(device, A2DP_SINK_UUID); + cras_bt_device_add_supported_profiles(device, HSP_HS_UUID); + cras_bt_device_add_supported_profiles(device, HFP_HF_UUID); - cur = msg_root = NewMockDBusConnectedMessage(1); + cur = msg_root = NewMockDBusConnectedMessage(); cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); EXPECT_EQ(1, cras_tm_create_timer_called); EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); @@ -326,19 +293,12 @@ TEST_F(BtDeviceTestSuite, SetDeviceConnectedA2dpHfpHsp) { cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(2, cras_tm_create_timer_called); - /* ConnectProfile must not be called, since the first profile connection - * should be initiated by Bluez. - */ - EXPECT_EQ(0, dbus_message_new_method_call_called); - cras_bt_device_audio_gateway_initialized(device); /* Schedule another timer, because A2DP is not ready. */ cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(3, cras_tm_create_timer_called); EXPECT_EQ(0, cras_hfp_ag_start_called); - - /* ConnectProfile should be called to connect A2DP, since HFP is connected */ EXPECT_EQ(1, dbus_message_new_method_call_called); EXPECT_STREQ("ConnectProfile", dbus_message_new_method_call_method); @@ -363,12 +323,11 @@ TEST_F(BtDeviceTestSuite, DevConnectedConflictCheck) { device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); EXPECT_NE((void*)NULL, device); - cras_bt_device_set_supported_profiles( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK | - CRAS_BT_DEVICE_PROFILE_HSP_HEADSET | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); + cras_bt_device_add_supported_profiles(device, A2DP_SINK_UUID); + cras_bt_device_add_supported_profiles(device, HSP_HS_UUID); + cras_bt_device_add_supported_profiles(device, HFP_HF_UUID); - cur = msg_root = NewMockDBusConnectedMessage(1); + cur = msg_root = NewMockDBusConnectedMessage(); cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); cras_bt_device_audio_gateway_initialized(device); cras_bt_device_a2dp_configured(device); @@ -402,34 +361,42 @@ TEST_F(BtDeviceTestSuite, A2dpDropped) { device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); EXPECT_NE((void*)NULL, device); - cras_bt_device_set_supported_profiles( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK | - CRAS_BT_DEVICE_PROFILE_HSP_HEADSET | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); + cras_bt_device_add_supported_profiles(device, A2DP_SINK_UUID); + cras_bt_device_add_supported_profiles(device, HSP_HS_UUID); + cras_bt_device_add_supported_profiles(device, HFP_HF_UUID); - cur = msg_root = NewMockDBusConnectedMessage(1); + cur = msg_root = NewMockDBusConnectedMessage(); cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); - cras_bt_device_audio_gateway_initialized(device); - cras_bt_device_a2dp_configured(device); EXPECT_EQ(1, cras_tm_create_timer_called); EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); + /* Schedule another timer, if HFP AG not yet intialized. */ + cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); + EXPECT_EQ(2, cras_tm_create_timer_called); + EXPECT_EQ(1, dbus_message_new_method_call_called); + EXPECT_STREQ("ConnectProfile", dbus_message_new_method_call_method); + + cras_bt_device_a2dp_configured(device); + + cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); + EXPECT_EQ(3, cras_tm_create_timer_called); + cras_bt_device_notify_profile_dropped(device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK); - EXPECT_EQ(2, cras_tm_create_timer_called); + EXPECT_EQ(4, cras_tm_create_timer_called); /* Expect suspend timer is scheduled. */ cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(1, cras_a2dp_suspend_connected_device_called); EXPECT_EQ(1, cras_hfp_ag_suspend_connected_device_called); - EXPECT_EQ(1, dbus_message_new_method_call_called); + EXPECT_EQ(2, dbus_message_new_method_call_called); EXPECT_STREQ("Disconnect", dbus_message_new_method_call_method); cras_bt_device_remove(device); FreeMockDBusMessage(msg_root); } -TEST_F(BtDeviceTestSuite, DevConnectDisconnectBackToBack) { +TEST_F(BtDeviceTestSuite, ConnectionWatchTimeout) { struct cras_bt_device* device; struct MockDBusMessage *msg_root, *cur; @@ -438,89 +405,26 @@ TEST_F(BtDeviceTestSuite, DevConnectDisconnectBackToBack) { device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); EXPECT_NE((void*)NULL, device); - cras_bt_device_set_supported_profiles( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK | - CRAS_BT_DEVICE_PROFILE_HSP_HEADSET | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); + cras_bt_device_add_supported_profiles(device, A2DP_SINK_UUID); + cras_bt_device_add_supported_profiles(device, HSP_HS_UUID); + cras_bt_device_add_supported_profiles(device, HFP_HF_UUID); - cur = msg_root = NewMockDBusConnectedMessage(1); + cur = msg_root = NewMockDBusConnectedMessage(); cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); EXPECT_EQ(1, cras_tm_create_timer_called); EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); - FreeMockDBusMessage(msg_root); - - cras_bt_device_a2dp_configured(device); - cras_bt_device_audio_gateway_initialized(device); - /* Expect suspend timer is scheduled. */ - cras_tm_create_timer_ret = reinterpret_cast<struct cras_timer*>(0x101); - cras_bt_device_notify_profile_dropped(device, - CRAS_BT_DEVICE_PROFILE_A2DP_SINK); - EXPECT_EQ(2, cras_tm_create_timer_called); - /* Another profile drop won't schedule another timer because one is - * already armed. */ - EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); - cras_bt_device_notify_profile_dropped(device, - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); + /* Schedule another timer, if HFP AG not yet intialized. */ + cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); EXPECT_EQ(2, cras_tm_create_timer_called); - - cur = msg_root = NewMockDBusConnectedMessage(0); - cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); - - /* When BlueZ reports headset disconnection, cancel the pending timer. */ - EXPECT_EQ(cras_tm_cancel_timer_called, 1); - EXPECT_EQ(cras_tm_cancel_timer_arg, (void*)0x101); - FreeMockDBusMessage(msg_root); - - /* Headset connects again. */ - cur = msg_root = NewMockDBusConnectedMessage(1); - cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); - EXPECT_EQ(3, cras_tm_create_timer_called); - EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); - FreeMockDBusMessage(msg_root); - - /* Headset disconnects, later profile drop events shouldn't trigger - * suspend timer because headset is already in disconnected stats. - */ - cur = msg_root = NewMockDBusConnectedMessage(0); - cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); - FreeMockDBusMessage(msg_root); - - cras_tm_create_timer_called = 0; - cras_bt_device_notify_profile_dropped(device, - CRAS_BT_DEVICE_PROFILE_A2DP_SINK); - EXPECT_EQ(0, cras_tm_create_timer_called); - cras_bt_device_notify_profile_dropped(device, - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); - EXPECT_EQ(0, cras_tm_create_timer_called); - - cras_bt_device_remove(device); -} - -TEST_F(BtDeviceTestSuite, ConnectionWatchTimeout) { - struct cras_bt_device* device; - struct MockDBusMessage *msg_root, *cur; - - ResetStubData(); - - device = cras_bt_device_create(NULL, FAKE_OBJ_PATH); - EXPECT_NE((void*)NULL, device); - - cras_bt_device_set_supported_profiles( - device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK | - CRAS_BT_DEVICE_PROFILE_HSP_HEADSET | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); - - cur = msg_root = NewMockDBusConnectedMessage(1); - cras_bt_device_update_properties(device, (DBusMessageIter*)&cur, NULL); - EXPECT_EQ(1, cras_tm_create_timer_called); - EXPECT_NE((void*)NULL, cras_tm_create_timer_cb); + EXPECT_EQ(1, dbus_message_new_method_call_called); + EXPECT_STREQ("ConnectProfile", dbus_message_new_method_call_method); cras_bt_device_a2dp_configured(device); - for (unsigned int i = 0; i < CONN_WATCH_MAX_RETRIES; i++) { + for (int i = 0; i < 29; i++) { cras_tm_create_timer_cb(NULL, cras_tm_create_timer_cb_data); - EXPECT_EQ(i + 2, cras_tm_create_timer_called); + EXPECT_EQ(i + 3, cras_tm_create_timer_called); EXPECT_EQ(0, cras_a2dp_start_called); EXPECT_EQ(0, cras_hfp_ag_start_called); EXPECT_EQ(0, cras_hfp_ag_remove_conflict_called); @@ -647,11 +551,6 @@ int cras_iodev_close(struct cras_iodev* dev) { return 0; } -void cras_iodev_set_node_plugged(struct cras_ionode* ionode, int plugged) { - cras_iodev_set_node_plugged_called++; - cras_iodev_set_node_plugged_value = plugged; -} - int cras_iodev_list_dev_is_enabled(const struct cras_iodev* dev) { return 0; } @@ -695,13 +594,10 @@ struct cras_timer* cras_tm_create_timer(struct cras_tm* tm, cras_tm_create_timer_called++; cras_tm_create_timer_cb = cb; cras_tm_create_timer_cb_data = cb_data; - return cras_tm_create_timer_ret; + return NULL; } -void cras_tm_cancel_timer(struct cras_tm* tm, struct cras_timer* t) { - cras_tm_cancel_timer_called++; - cras_tm_cancel_timer_arg = t; -} +void cras_tm_cancel_timer(struct cras_tm* tm, struct cras_timer* t) {} DBusMessage* dbus_message_new_method_call(const char* destination, const char* path, diff --git a/cras/src/tests/bt_io_unittest.cc b/cras/src/tests/bt_io_unittest.cc index dd02652f..97f4dae4 100644 --- a/cras/src/tests/bt_io_unittest.cc +++ b/cras/src/tests/bt_io_unittest.cc @@ -59,8 +59,6 @@ class BtIoBasicSuite : public testing::Test { ResetStubData(); SetUpIodev(&iodev_, CRAS_STREAM_OUTPUT); SetUpIodev(&iodev2_, CRAS_STREAM_OUTPUT); - iodev_.active_node = &node_; - iodev2_.active_node = &node2_; update_supported_formats_called_ = 0; frames_queued_called_ = 0; @@ -139,8 +137,6 @@ class BtIoBasicSuite : public testing::Test { static struct cras_iodev* bt_iodev; static struct cras_iodev iodev_; static struct cras_iodev iodev2_; - static struct cras_ionode node_; - static struct cras_ionode node2_; static unsigned int update_supported_formats_called_; static unsigned int frames_queued_called_; static unsigned int delay_frames_called_; @@ -153,8 +149,6 @@ class BtIoBasicSuite : public testing::Test { struct cras_iodev* BtIoBasicSuite::bt_iodev; struct cras_iodev BtIoBasicSuite::iodev_; struct cras_iodev BtIoBasicSuite::iodev2_; -struct cras_ionode BtIoBasicSuite::node_; -struct cras_ionode BtIoBasicSuite::node2_; unsigned int BtIoBasicSuite::update_supported_formats_called_; unsigned int BtIoBasicSuite::frames_queued_called_; unsigned int BtIoBasicSuite::delay_frames_called_; @@ -178,7 +172,6 @@ TEST_F(BtIoBasicSuite, CreateBtIo) { bt_iodev->update_supported_formats(bt_iodev); EXPECT_EQ(1, update_supported_formats_called_); - bt_iodev->state = CRAS_IODEV_STATE_OPEN; bt_iodev->configure_dev(bt_iodev); EXPECT_EQ(1, configure_dev_called_); bt_iodev->frames_queued(bt_iodev, &tstamp); @@ -235,7 +228,6 @@ TEST_F(BtIoBasicSuite, SwitchProfileOnCloseInputDev) { iodev_.direction = CRAS_STREAM_INPUT; bt_iodev = cras_bt_io_create(fake_device, &iodev_, CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - bt_iodev->state = CRAS_IODEV_STATE_OPEN; cras_bt_device_get_active_profile_ret = CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY | @@ -254,7 +246,6 @@ TEST_F(BtIoBasicSuite, NoSwitchProfileOnCloseInputDevNoSupportA2dp) { iodev_.direction = CRAS_STREAM_INPUT; bt_iodev = cras_bt_io_create(fake_device, &iodev_, CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - bt_iodev->state = CRAS_IODEV_STATE_OPEN; cras_bt_device_get_active_profile_ret = CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY | @@ -266,23 +257,6 @@ TEST_F(BtIoBasicSuite, NoSwitchProfileOnCloseInputDevNoSupportA2dp) { cras_bt_io_destroy(bt_iodev); } -TEST_F(BtIoBasicSuite, NoSwitchProfileOnCloseInputDevInCloseState) { - ResetStubData(); - iodev_.direction = CRAS_STREAM_INPUT; - bt_iodev = cras_bt_io_create(fake_device, &iodev_, - CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - bt_iodev->state = CRAS_IODEV_STATE_CLOSE; - - cras_bt_device_get_active_profile_ret = - CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY | - CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY; - cras_bt_device_has_a2dp_ret = 1; - bt_iodev->close_dev(bt_iodev); - - EXPECT_EQ(0, cras_bt_device_switch_profile_called); - cras_bt_io_destroy(bt_iodev); -} - TEST_F(BtIoBasicSuite, SwitchProfileOnAppendA2dpDev) { ResetStubData(); bt_iodev = cras_bt_io_create(fake_device, &iodev_, @@ -423,8 +397,7 @@ int cras_iodev_list_rm_input(struct cras_iodev* dev) { } // From bt device -unsigned int cras_bt_device_get_active_profile( - const struct cras_bt_device* device) { +int cras_bt_device_get_active_profile(const struct cras_bt_device* device) { return cras_bt_device_get_active_profile_ret; } @@ -458,10 +431,6 @@ const char* cras_bt_device_object_path(const struct cras_bt_device* device) { return "/fake/object/path"; } -int cras_bt_device_get_stable_id(const struct cras_bt_device* device) { - return 123; -} - int cras_bt_device_get_use_hardware_volume(struct cras_bt_device* device) { return 1; } @@ -474,20 +443,4 @@ int cras_iodev_default_no_stream_playback(struct cras_iodev* odev, int enable) { return 0; } -int cras_iodev_frames_queued(struct cras_iodev* iodev, - struct timespec* hw_tstamp) { - return 0; -} - -unsigned int cras_iodev_default_frames_to_play_in_sleep( - struct cras_iodev* odev, - unsigned int* hw_level, - struct timespec* hw_tstamp) { - return 0; -} - -int hfp_iodev_is_hsp(struct cras_iodev* iodev) { - return 0; -} - } // extern "C" diff --git a/cras/src/tests/capture_rclient_unittest.cc b/cras/src/tests/capture_rclient_unittest.cc index 446fddfa..5e0bc58c 100644 --- a/cras/src/tests/capture_rclient_unittest.cc +++ b/cras/src/tests/capture_rclient_unittest.cc @@ -20,18 +20,22 @@ extern "C" { } static unsigned int cras_make_fd_nonblocking_called; static unsigned int cras_observer_remove_called; +static unsigned int cras_server_metrics_stream_config_called; static int stream_list_add_called; static int stream_list_add_return; static unsigned int stream_list_rm_called; -static struct cras_audio_shm mock_shm; -static struct cras_rstream mock_rstream; +static struct cras_audio_shm dummy_shm; +static struct cras_rstream dummy_rstream; +static unsigned int cras_rstream_config_init_with_message_called; void ResetStubData() { cras_make_fd_nonblocking_called = 0; cras_observer_remove_called = 0; + cras_server_metrics_stream_config_called = 0; stream_list_add_called = 0; stream_list_add_return = 0; stream_list_rm_called = 0; + cras_rstream_config_init_with_message_called = 0; } namespace { @@ -106,12 +110,13 @@ TEST_F(CCRMessageSuite, StreamConnectMessage) { cras_fill_connect_message(&msg, CRAS_STREAM_INPUT, stream_id, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, 480, 240, /*flags=*/0, /*effects=*/0, fmt, - NO_DEVICE); + NO_DEVICE, /*client_shm_size=*/0); ASSERT_EQ(stream_id, msg.stream_id); fd_ = 100; rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); EXPECT_EQ(1, cras_make_fd_nonblocking_called); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); EXPECT_EQ(1, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); @@ -133,14 +138,16 @@ TEST_F(CCRMessageSuite, StreamConnectMessageInvalidDirection) { continue; cras_fill_connect_message(&msg, dir, stream_id, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, 480, 240, /*flags=*/0, - /*effects=*/0, fmt, NO_DEVICE); + /*effects=*/0, fmt, NO_DEVICE, + /*client_shm_size=*/0); ASSERT_EQ(stream_id, msg.stream_id); fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); EXPECT_EQ(0, cras_make_fd_nonblocking_called); + EXPECT_EQ(0, cras_rstream_config_init_with_message_called); EXPECT_EQ(0, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); @@ -160,14 +167,15 @@ TEST_F(CCRMessageSuite, StreamConnectMessageInvalidClientId) { cras_fill_connect_message(&msg, CRAS_STREAM_INPUT, stream_id, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, 480, 240, /*flags=*/0, /*effects=*/0, fmt, - NO_DEVICE); + NO_DEVICE, /*client_shm_size=*/0); ASSERT_EQ(stream_id, msg.stream_id); fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); EXPECT_EQ(0, cras_make_fd_nonblocking_called); + EXPECT_EQ(0, cras_rstream_config_init_with_message_called); EXPECT_EQ(0, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); @@ -177,6 +185,43 @@ TEST_F(CCRMessageSuite, StreamConnectMessageInvalidClientId) { EXPECT_EQ(stream_id, out_msg.stream_id); } +/* + * TODO(yuhsaun): Remove this test when there are no client uses the old + * craslib. (CRAS_PROTO_VER = 3) + */ +TEST_F(CCRMessageSuite, StreamConnectMessageOldProtocal) { + struct cras_client_stream_connected out_msg; + int rc; + + struct cras_connect_message_old msg; + cras_stream_id_t stream_id = 0x10002; + + msg.proto_version = 3; + msg.direction = CRAS_STREAM_INPUT; + msg.stream_id = stream_id; + msg.stream_type = CRAS_STREAM_TYPE_DEFAULT; + msg.buffer_frames = 480; + msg.cb_threshold = 240; + msg.flags = 0; + msg.effects = 0; + pack_cras_audio_format(&msg.format, &fmt); + msg.dev_idx = NO_DEVICE; + msg.header.id = CRAS_SERVER_CONNECT_STREAM; + msg.header.length = sizeof(struct cras_connect_message_old); + + fd_ = 100; + rc = + rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); + EXPECT_EQ(1, cras_make_fd_nonblocking_called); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); + EXPECT_EQ(1, stream_list_add_called); + EXPECT_EQ(0, stream_list_rm_called); + + rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); + EXPECT_EQ(sizeof(out_msg), rc); + EXPECT_EQ(stream_id, out_msg.stream_id); +} + TEST_F(CCRMessageSuite, StreamDisconnectMessage) { struct cras_disconnect_stream_message msg; cras_stream_id_t stream_id = 0x10002; @@ -223,6 +268,11 @@ unsigned int cras_rstream_get_effects(const struct cras_rstream* stream) { return 0; } +int cras_server_metrics_stream_config(struct cras_rstream_config* config) { + cras_server_metrics_stream_config_called++; + return 0; +} + int cras_send_with_fds(int sockfd, const void* buf, size_t len, @@ -252,27 +302,30 @@ int stream_list_add(struct stream_list* list, struct cras_rstream** stream) { int ret; - *stream = &mock_rstream; + *stream = &dummy_rstream; stream_list_add_called++; ret = stream_list_add_return; if (ret) stream_list_add_return = -EINVAL; - mock_rstream.shm = &mock_shm; - mock_rstream.direction = config->direction; - mock_rstream.stream_id = config->stream_id; + dummy_rstream.shm = &dummy_shm; + dummy_rstream.direction = config->direction; + dummy_rstream.stream_id = config->stream_id; return ret; } -bool cras_audio_format_valid(const struct cras_audio_format* fmt) { - return true; +void cras_rstream_config_init_with_message( + struct cras_rclient* client, + const struct cras_connect_message* msg, + int* aud_fd, + int* client_shm_fd, + const struct cras_audio_format* remote_fmt, + struct cras_rstream_config* stream_config) { + cras_rstream_config_init_with_message_called++; } -void detect_rtc_stream_pair(struct stream_list* list, - struct cras_rstream* stream) { - return; -} +void cras_rstream_config_cleanup(struct cras_rstream_config* stream_config) {} } // extern "C" diff --git a/cras/src/tests/control_rclient_unittest.cc b/cras/src/tests/control_rclient_unittest.cc index 63e3c8f0..634bfe1a 100644 --- a/cras/src/tests/control_rclient_unittest.cc +++ b/cras/src/tests/control_rclient_unittest.cc @@ -9,7 +9,6 @@ extern "C" { #include "audio_thread.h" #include "cras_bt_log.h" -#include "cras_main_thread_log.h" #include "cras_messages.h" #include "cras_rclient.h" #include "cras_rstream.h" @@ -21,14 +20,13 @@ extern "C" { } // Stub data. -static int audio_thread_config_global_remix_called; -static float audio_thread_config_global_remix_copy[CRAS_MAX_REMIX_CHANNELS * - CRAS_MAX_REMIX_CHANNELS]; static int cras_rstream_create_return; static struct cras_rstream* cras_rstream_create_stream_out; static int cras_iodev_attach_stream_retval; static size_t cras_system_set_volume_value; static int cras_system_set_volume_called; +static size_t cras_system_set_capture_gain_value; +static int cras_system_set_capture_gain_called; static size_t cras_system_set_mute_value; static int cras_system_set_mute_called; static size_t cras_system_set_user_mute_value; @@ -47,8 +45,9 @@ static unsigned int stream_list_add_stream_called; static unsigned int stream_list_disconnect_stream_called; static unsigned int cras_iodev_list_rm_input_called; static unsigned int cras_iodev_list_rm_output_called; -static struct cras_audio_shm mock_shm; -static struct cras_rstream mock_rstream; +static unsigned int cras_server_metrics_stream_config_called; +static struct cras_audio_shm dummy_shm; +static struct cras_rstream dummy_rstream; static size_t cras_observer_num_ops_registered; static size_t cras_observer_register_notify_called; static size_t cras_observer_add_called; @@ -60,16 +59,17 @@ static size_t cras_observer_set_ops_called; static size_t cras_observer_ops_are_empty_called; static struct cras_observer_ops cras_observer_ops_are_empty_empty_ops; static size_t cras_observer_remove_called; +static unsigned int cras_rstream_config_init_with_message_called; void ResetStubData() { - audio_thread_config_global_remix_called = 0; - memset(audio_thread_config_global_remix_copy, 0, - sizeof(audio_thread_config_global_remix_copy)); cras_rstream_create_return = 0; cras_rstream_create_stream_out = (struct cras_rstream*)NULL; cras_iodev_attach_stream_retval = 0; + cras_server_metrics_stream_config_called = 0; cras_system_set_volume_value = 0; cras_system_set_volume_called = 0; + cras_system_set_capture_gain_value = 0; + cras_system_set_capture_gain_called = 0; cras_system_set_mute_value = 0; cras_system_set_mute_called = 0; cras_system_set_user_mute_value = 0; @@ -101,6 +101,7 @@ void ResetStubData() { memset(&cras_observer_ops_are_empty_empty_ops, 0, sizeof(cras_observer_ops_are_empty_empty_ops)); cras_observer_remove_called = 0; + cras_rstream_config_init_with_message_called = 0; } namespace { @@ -160,7 +161,6 @@ class RClientMessagesSuite : public testing::Test { connect_msg_.dev_idx = NO_DEVICE; connect_msg_.client_shm_size = 0; btlog = cras_bt_event_log_init(); - main_log = main_thread_event_log_init(); ResetStubData(); } @@ -170,7 +170,6 @@ class RClientMessagesSuite : public testing::Test { close(pipe_fds_[0]); close(pipe_fds_[1]); cras_bt_event_log_deinit(btlog); - main_thread_event_log_deinit(main_log); } void RegisterNotification(enum CRAS_CLIENT_MESSAGE_ID msg_id, @@ -195,15 +194,17 @@ TEST_F(RClientMessagesSuite, AudThreadAttachFail) { fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); EXPECT_EQ(sizeof(out_msg), rc); EXPECT_EQ(stream_id_, out_msg.stream_id); EXPECT_NE(0, out_msg.err); EXPECT_EQ(0, cras_iodev_list_rm_output_called); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); EXPECT_EQ(1, stream_list_add_stream_called); EXPECT_EQ(0, stream_list_disconnect_stream_called); + EXPECT_EQ(0, cras_server_metrics_stream_config_called); } TEST_F(RClientMessagesSuite, ConnectMsgWithBadFd) { @@ -212,7 +213,7 @@ TEST_F(RClientMessagesSuite, ConnectMsgWithBadFd) { rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, NULL, 0); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EBADF, rc); rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); EXPECT_EQ(sizeof(out_msg), rc); @@ -220,6 +221,33 @@ TEST_F(RClientMessagesSuite, ConnectMsgWithBadFd) { EXPECT_NE(0, out_msg.err); EXPECT_EQ(stream_list_add_stream_called, stream_list_disconnect_stream_called); + EXPECT_EQ(0, cras_server_metrics_stream_config_called); +} + +TEST_F(RClientMessagesSuite, ConnectMsgFromOldClient) { + struct cras_client_stream_connected out_msg; + int rc; + + cras_rstream_create_stream_out = rstream_; + cras_iodev_attach_stream_retval = 0; + + connect_msg_.header.length = sizeof(struct cras_connect_message_old); + connect_msg_.proto_version = 3; + + fd_ = 100; + rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, + &fd_, 1); + EXPECT_EQ(0, rc); + EXPECT_EQ(1, cras_make_fd_nonblocking_called); + + rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); + EXPECT_EQ(sizeof(out_msg), rc); + EXPECT_EQ(stream_id_, out_msg.stream_id); + EXPECT_EQ(0, out_msg.err); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); + EXPECT_EQ(1, stream_list_add_stream_called); + EXPECT_EQ(0, stream_list_disconnect_stream_called); + EXPECT_EQ(1, cras_server_metrics_stream_config_called); } TEST_F(RClientMessagesSuite, StreamConnectMessageValidDirection) { @@ -245,8 +273,10 @@ TEST_F(RClientMessagesSuite, StreamConnectMessageValidDirection) { EXPECT_EQ(sizeof(out_msg), rc); EXPECT_EQ(stream_id_, out_msg.stream_id); EXPECT_EQ(0, out_msg.err); + EXPECT_EQ(called, cras_rstream_config_init_with_message_called); EXPECT_EQ(called, stream_list_add_stream_called); EXPECT_EQ(0, stream_list_disconnect_stream_called); + EXPECT_EQ(called, cras_server_metrics_stream_config_called); } } @@ -261,7 +291,7 @@ TEST_F(RClientMessagesSuite, StreamConnectMessageInvalidDirection) { fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); EXPECT_EQ(0, cras_make_fd_nonblocking_called); rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); @@ -270,6 +300,7 @@ TEST_F(RClientMessagesSuite, StreamConnectMessageInvalidDirection) { EXPECT_EQ(-EINVAL, out_msg.err); EXPECT_EQ(0, stream_list_add_stream_called); EXPECT_EQ(0, stream_list_disconnect_stream_called); + EXPECT_EQ(0, cras_server_metrics_stream_config_called); } TEST_F(RClientMessagesSuite, StreamConnectMessageInvalidClientId) { @@ -281,8 +312,9 @@ TEST_F(RClientMessagesSuite, StreamConnectMessageInvalidClientId) { fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); EXPECT_EQ(0, cras_make_fd_nonblocking_called); + EXPECT_EQ(0, cras_rstream_config_init_with_message_called); EXPECT_EQ(0, stream_list_add_stream_called); EXPECT_EQ(0, stream_list_disconnect_stream_called); @@ -309,8 +341,10 @@ TEST_F(RClientMessagesSuite, SuccessReply) { EXPECT_EQ(sizeof(out_msg), rc); EXPECT_EQ(stream_id_, out_msg.stream_id); EXPECT_EQ(0, out_msg.err); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); EXPECT_EQ(1, stream_list_add_stream_called); EXPECT_EQ(0, stream_list_disconnect_stream_called); + EXPECT_EQ(1, cras_server_metrics_stream_config_called); } TEST_F(RClientMessagesSuite, SuccessCreateThreadReply) { @@ -330,8 +364,10 @@ TEST_F(RClientMessagesSuite, SuccessCreateThreadReply) { EXPECT_EQ(sizeof(out_msg), rc); EXPECT_EQ(stream_id_, out_msg.stream_id); EXPECT_EQ(0, out_msg.err); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); EXPECT_EQ(1, stream_list_add_stream_called); EXPECT_EQ(0, stream_list_disconnect_stream_called); + EXPECT_EQ(1, cras_server_metrics_stream_config_called); } TEST_F(RClientMessagesSuite, SetVolume) { @@ -349,6 +385,21 @@ TEST_F(RClientMessagesSuite, SetVolume) { EXPECT_EQ(66, cras_system_set_volume_value); } +TEST_F(RClientMessagesSuite, SetCaptureVolume) { + struct cras_set_system_volume msg; + int rc; + + msg.header.id = CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN; + msg.header.length = sizeof(msg); + msg.volume = 66; + + rc = + rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); + EXPECT_EQ(0, rc); + EXPECT_EQ(1, cras_system_set_capture_gain_called); + EXPECT_EQ(66, cras_system_set_capture_gain_value); +} + TEST_F(RClientMessagesSuite, SetMute) { struct cras_set_system_mute msg; int rc; @@ -418,23 +469,6 @@ TEST_F(RClientMessagesSuite, DumpSnapshots) { EXPECT_EQ(1, cras_system_state_dump_snapshots_called); } -TEST_F(RClientMessagesSuite, ConfigGlobalRemix) { - int rc; - struct cras_config_global_remix msg; - const int num_channels = 2; - float coefficient[4] = {0.1, 0.2, 0.3, 0.4}; - cras_fill_config_global_remix_command(&msg, num_channels, coefficient, - num_channels * num_channels); - - rc = - rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); - EXPECT_EQ(0, rc); - EXPECT_EQ(1, audio_thread_config_global_remix_called); - for (unsigned i = 0; i < (unsigned)num_channels * num_channels; i++) { - EXPECT_EQ(audio_thread_config_global_remix_copy[i], coefficient[i]); - } -} - void RClientMessagesSuite::RegisterNotification( enum CRAS_CLIENT_MESSAGE_ID msg_id, void* callback, @@ -588,6 +622,21 @@ TEST_F(RClientMessagesSuite, SendOutputMuteChanged) { EXPECT_EQ(msg->mute_locked, mute_locked); } +TEST_F(RClientMessagesSuite, SendCaptureGainChanged) { + void* void_client = reinterpret_cast<void*>(rclient_); + char buf[1024]; + ssize_t rc; + struct cras_client_volume_changed* msg = + (struct cras_client_volume_changed*)buf; + const int32_t gain = 90; + + send_capture_gain_changed(void_client, gain); + rc = read(pipe_fds_[0], buf, sizeof(buf)); + ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); + EXPECT_EQ(msg->header.id, CRAS_CLIENT_CAPTURE_GAIN_CHANGED); + EXPECT_EQ(msg->volume, gain); +} + TEST_F(RClientMessagesSuite, SendCaptureMuteChanged) { void* void_client = reinterpret_cast<void*>(rclient_); char buf[1024]; @@ -713,7 +762,6 @@ int main(int argc, char** argv) { extern "C" { struct cras_bt_event_log* btlog; -struct main_thread_event_log* main_log; struct audio_thread* cras_iodev_list_get_audio_thread() { return iodev_get_thread_return; @@ -748,9 +796,6 @@ int audio_thread_resume(struct audio_thread* thread) { int audio_thread_config_global_remix(struct audio_thread* thread, unsigned int num_channels, const float* coefficient) { - audio_thread_config_global_remix_called++; - memcpy(audio_thread_config_global_remix_copy, coefficient, - num_channels * num_channels * sizeof(coefficient)); return 0; } @@ -817,6 +862,11 @@ void cras_system_set_volume(size_t volume) { cras_system_set_volume_called++; } +void cras_system_set_capture_gain(long gain) { + cras_system_set_capture_gain_value = gain; + cras_system_set_capture_gain_called++; +} + // From system_state. void cras_system_set_mute(int mute) { cras_system_set_mute_value = mute; @@ -887,16 +937,16 @@ int stream_list_add(struct stream_list* list, struct cras_rstream** stream) { int ret; - *stream = &mock_rstream; + *stream = &dummy_rstream; stream_list_add_stream_called++; ret = stream_list_add_stream_return; if (ret) stream_list_add_stream_return = -EINVAL; - mock_rstream.shm = &mock_shm; - mock_rstream.direction = config->direction; - mock_rstream.stream_id = config->stream_id; + dummy_rstream.shm = &dummy_shm; + dummy_rstream.direction = config->direction; + dummy_rstream.stream_id = config->stream_id; return ret; } @@ -959,19 +1009,21 @@ void cras_observer_remove(struct cras_observer_client* client) { cras_observer_remove_called++; } -bool cras_audio_format_valid(const struct cras_audio_format* fmt) { - return true; -} - -struct packet_status_logger* cras_hfp_ag_get_wbs_logger() { - return NULL; +int cras_server_metrics_stream_config(struct cras_rstream_config* config) { + cras_server_metrics_stream_config_called++; + return 0; } -void detect_rtc_stream_pair(struct stream_list* list, - struct cras_rstream* stream) { - return; +void cras_rstream_config_init_with_message( + struct cras_rclient* client, + const struct cras_connect_message* msg, + int* aud_fd, + int* client_shm_fd, + const struct cras_audio_format* remote_fmt, + struct cras_rstream_config* stream_config) { + cras_rstream_config_init_with_message_called++; } -void cras_system_set_hotword_pause_at_suspend(bool pause) {} +void cras_rstream_config_cleanup(struct cras_rstream_config* stream_config) {} } // extern "C" diff --git a/cras/src/tests/cras_abi_unittest.cc b/cras/src/tests/cras_abi_unittest.cc deleted file mode 100644 index d566a9b7..00000000 --- a/cras/src/tests/cras_abi_unittest.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <gtest/gtest.h> - -extern "C" { -#include "cras_client.c" -#include "cras_client.h" - -inline int libcras_unsupported_func(struct libcras_client* client) { - CHECK_VERSION(client, INT_MAX); - return 0; -} - -cras_stream_id_t cb_stream_id; -uint8_t* cb_buf; -unsigned int cb_frames; -struct timespec cb_latency; -void* cb_usr_arg; -int get_stream_cb_called; -struct timespec now; - -int get_stream_cb(struct libcras_stream_cb_data* data) { - get_stream_cb_called++; - EXPECT_NE((void*)NULL, data); - EXPECT_EQ(0, libcras_stream_cb_data_get_stream_id(data, &cb_stream_id)); - EXPECT_EQ(0, libcras_stream_cb_data_get_buf(data, &cb_buf)); - EXPECT_EQ(0, libcras_stream_cb_data_get_frames(data, &cb_frames)); - EXPECT_EQ(0, libcras_stream_cb_data_get_latency(data, &cb_latency)); - EXPECT_EQ(0, libcras_stream_cb_data_get_usr_arg(data, &cb_usr_arg)); - return 0; -} -} - -namespace { -class CrasAbiTestSuite : public testing::Test { - protected: - struct cras_audio_shm* InitShm(int frames) { - struct cras_audio_shm* shm = - static_cast<struct cras_audio_shm*>(calloc(1, sizeof(*shm))); - shm->header = - static_cast<cras_audio_shm_header*>(calloc(1, sizeof(*shm->header))); - cras_shm_set_frame_bytes(shm, 4); - uint32_t used_size = frames * 4; - cras_shm_set_used_size(shm, used_size); - shm->samples_info.length = used_size * 2; - memcpy(&shm->header->config, &shm->config, sizeof(shm->config)); - return shm; - } - - void DestroyShm(struct cras_audio_shm* shm) { - if (shm) - free(shm->header); - free(shm); - } - - virtual void SetUp() { get_stream_cb_called = 0; } -}; - -TEST_F(CrasAbiTestSuite, CheckUnsupportedFunction) { - auto* client = libcras_client_create(); - EXPECT_NE((void*)NULL, client); - EXPECT_EQ(-ENOSYS, libcras_unsupported_func(client)); - libcras_client_destroy(client); -} - -TEST_F(CrasAbiTestSuite, BasicStream) { - auto* client = libcras_client_create(); - EXPECT_NE((void*)NULL, client); - auto* stream = libcras_stream_params_create(); - EXPECT_NE((void*)NULL, stream); - /* Returns timeout because there is no real CRAS server in unittest. */ - EXPECT_EQ(-ETIMEDOUT, libcras_client_connect_timeout(client, 0)); - EXPECT_EQ(0, libcras_client_run_thread(client)); - EXPECT_EQ(0, libcras_stream_params_set(stream, CRAS_STREAM_INPUT, 480, 480, - CRAS_STREAM_TYPE_DEFAULT, - CRAS_CLIENT_TYPE_TEST, 0, NULL, NULL, - NULL, 48000, SND_PCM_FORMAT_S16, 2)); - cras_stream_id_t id; - /* Fails to add a stream because the stream callback is not set. */ - EXPECT_EQ(-EINVAL, libcras_client_add_pinned_stream(client, 0, &id, stream)); - /* Fails to set a stream volume because the stream is not added. */ - EXPECT_EQ(-EINVAL, libcras_client_set_stream_volume(client, id, 1.0)); - EXPECT_EQ(0, libcras_client_rm_stream(client, id)); - EXPECT_EQ(0, libcras_client_stop(client)); - libcras_stream_params_destroy(stream); - libcras_client_destroy(client); -} - -TEST_F(CrasAbiTestSuite, StreamCallback) { - struct client_stream stream; - struct cras_stream_params params; - stream.id = 0x123; - stream.direction = CRAS_STREAM_INPUT; - stream.flags = 0; - stream.config = ¶ms; - params.stream_cb = get_stream_cb; - params.cb_threshold = 480; - params.user_data = (void*)0x321; - stream.shm = InitShm(960); - stream.shm->header->write_offset[0] = 960 * 4; - stream.shm->header->write_buf_idx = 0; - stream.shm->header->read_offset[0] = 0; - stream.shm->header->read_buf_idx = 0; - now.tv_sec = 100; - now.tv_nsec = 0; - stream.shm->header->ts.tv_sec = 90; - stream.shm->header->ts.tv_nsec = 0; - - handle_capture_data_ready(&stream, 480); - - EXPECT_EQ(1, get_stream_cb_called); - EXPECT_EQ(stream.id, cb_stream_id); - EXPECT_EQ(cras_shm_get_write_buffer_base(stream.shm), cb_buf); - EXPECT_EQ(480, cb_frames); - EXPECT_EQ(10, cb_latency.tv_sec); - EXPECT_EQ(0, cb_latency.tv_nsec); - EXPECT_EQ((void*)0x321, cb_usr_arg); - - DestroyShm(stream.shm); -} - -} // namespace - -extern "C" { - -int clock_gettime(clockid_t clk_id, struct timespec* tp) { - *tp = now; - return 0; -} -} - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - openlog(NULL, LOG_PERROR, LOG_USER); - return RUN_ALL_TESTS(); -} diff --git a/cras/src/tests/dev_io_stubs.cc b/cras/src/tests/dev_io_stubs.cc index d97dde50..b74162b8 100644 --- a/cras/src/tests/dev_io_stubs.cc +++ b/cras/src/tests/dev_io_stubs.cc @@ -151,11 +151,6 @@ void add_stream_to_dev(IodevPtr& dev, const StreamPtr& stream) { static_cast<size_t>(dev->max_cb_level)); dev->largest_cb_level = std::max(stream->rstream->cb_threshold, static_cast<size_t>(dev->max_cb_level)); - - if (stream->rstream->main_dev.dev_id == NO_DEVICE) { - stream->rstream->main_dev.dev_id = dev->info.idx; - stream->rstream->main_dev.dev_ptr = dev.get(); - } } void fill_audio_format(cras_audio_format* format, unsigned int rate) { diff --git a/cras/src/tests/dev_io_unittest.cc b/cras/src/tests/dev_io_unittest.cc index 2dbf344e..a18dd48a 100644 --- a/cras/src/tests/dev_io_unittest.cc +++ b/cras/src/tests/dev_io_unittest.cc @@ -8,7 +8,6 @@ #include <time.h> #include <memory> -#include <unordered_map> extern "C" { #include "cras_iodev.h" // stubbed @@ -28,15 +27,7 @@ struct audio_thread_event_log* atlog; #include "rstream_stub.h" static float dev_stream_capture_software_gain_scaler_val; -static float input_data_get_software_gain_scaler_val; static unsigned int dev_stream_capture_avail_ret = 480; -struct set_dev_rate_data { - unsigned int dev_rate; - double dev_rate_ratio; - double main_rate_ratio; - int coarse_rate_adjust; -}; -std::unordered_map<struct dev_stream*, set_dev_rate_data> set_dev_rate_map; namespace { @@ -47,7 +38,6 @@ class DevIoSuite : public testing::Test { iodev_stub_reset(); rstream_stub_reset(); fill_audio_format(&format, 48000); - set_dev_rate_map.clear(); stream = create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format); } @@ -79,90 +69,25 @@ TEST_F(DevIoSuite, SendCapturedFails) { TEST_F(DevIoSuite, CaptureGain) { struct open_dev* dev_list = NULL; - struct open_dev* odev_list = NULL; struct timespec ts; DevicePtr dev = create_device(CRAS_STREAM_INPUT, cb_threshold, &format, CRAS_NODE_TYPE_MIC); dev->dev->state = CRAS_IODEV_STATE_NORMAL_RUN; + dev->dev->software_gain_scaler = 0.99f; iodev_stub_frames_queued(dev->dev.get(), 20, ts); DL_APPEND(dev_list, dev->odev.get()); add_stream_to_dev(dev->dev, stream); - /* The applied scaler gain should match what is reported by input_data. */ - dev->dev->active_node->ui_gain_scaler = 1.0f; - input_data_get_software_gain_scaler_val = 1.0f; - dev_io_capture(&dev_list, &odev_list); + /* For stream that uses APM, always apply gain scaler 1.0f regardless of + * what node/stream gains are. */ + stream->rstream->apm_list = reinterpret_cast<struct cras_apm_list*>(0xf0f); + dev_io_capture(&dev_list); EXPECT_EQ(1.0f, dev_stream_capture_software_gain_scaler_val); - input_data_get_software_gain_scaler_val = 0.99f; - dev_io_capture(&dev_list, &odev_list); + stream->rstream->apm_list = 0x0; + dev_io_capture(&dev_list); EXPECT_EQ(0.99f, dev_stream_capture_software_gain_scaler_val); - - dev->dev->active_node->ui_gain_scaler = 0.6f; - input_data_get_software_gain_scaler_val = 0.7f; - dev_io_capture(&dev_list, &odev_list); - EXPECT_FLOAT_EQ(0.42f, dev_stream_capture_software_gain_scaler_val); -} - -/* - * When input and output devices are on the internal sound card, - * and their device rates are the same, use the estimated rate - * on the output device as the estimated rate of input device. - */ -TEST_F(DevIoSuite, CopyOutputEstimatedRate) { - struct open_dev* idev_list = NULL; - struct open_dev* odev_list = NULL; - struct timespec ts; - DevicePtr out_dev = create_device(CRAS_STREAM_OUTPUT, cb_threshold, &format, - CRAS_NODE_TYPE_INTERNAL_SPEAKER); - DevicePtr in_dev = create_device(CRAS_STREAM_INPUT, cb_threshold, &format, - CRAS_NODE_TYPE_MIC); - - in_dev->dev->state = CRAS_IODEV_STATE_NORMAL_RUN; - iodev_stub_frames_queued(in_dev->dev.get(), 20, ts); - DL_APPEND(idev_list, in_dev->odev.get()); - add_stream_to_dev(in_dev->dev, stream); - DL_APPEND(odev_list, out_dev->odev.get()); - iodev_stub_on_internal_card(out_dev->dev->active_node, 1); - iodev_stub_on_internal_card(in_dev->dev->active_node, 1); - - iodev_stub_est_rate_ratio(in_dev->dev.get(), 0.8f); - iodev_stub_est_rate_ratio(out_dev->dev.get(), 1.2f); - - dev_io_capture(&idev_list, &odev_list); - - EXPECT_FLOAT_EQ(1.2f, set_dev_rate_map[stream->dstream.get()].dev_rate_ratio); -} - -/* - * When input and output devices are not both on the internal sound card, - * estimated rates are independent. - */ -TEST_F(DevIoSuite, InputOutputIndependentEstimatedRate) { - struct open_dev* idev_list = NULL; - struct open_dev* odev_list = NULL; - struct timespec ts; - DevicePtr out_dev = create_device(CRAS_STREAM_OUTPUT, cb_threshold, &format, - CRAS_NODE_TYPE_INTERNAL_SPEAKER); - DevicePtr in_dev = create_device(CRAS_STREAM_INPUT, cb_threshold, &format, - CRAS_NODE_TYPE_USB); - - in_dev->dev->state = CRAS_IODEV_STATE_NORMAL_RUN; - iodev_stub_frames_queued(in_dev->dev.get(), 20, ts); - DL_APPEND(idev_list, in_dev->odev.get()); - add_stream_to_dev(in_dev->dev, stream); - DL_APPEND(odev_list, out_dev->odev.get()); - iodev_stub_on_internal_card(out_dev->dev->active_node, 1); - iodev_stub_on_internal_card(in_dev->dev->active_node, 0); - - iodev_stub_est_rate_ratio(in_dev->dev.get(), 0.8f); - iodev_stub_est_rate_ratio(out_dev->dev.get(), 1.2f); - iodev_stub_update_rate(in_dev->dev.get(), 1); - - dev_io_capture(&idev_list, &odev_list); - - EXPECT_FLOAT_EQ(0.8f, set_dev_rate_map[stream->dstream.get()].dev_rate_ratio); } /* @@ -207,49 +132,6 @@ TEST_F(DevIoSuite, SendCapturedNeedToResetDevices) { } /* - * If any hw_level is larger than 0.5 * buffer_size and - * DROP_FRAMES_THRESHOLD_MS, reset all input devices. - */ - -TEST_F(DevIoSuite, SendCapturedNeedToResetDevices2) { - struct timespec start; - struct timespec drop_time; - struct open_dev* dev_list = NULL; - bool rc; - - stream = create_stream(1, 1, CRAS_STREAM_INPUT, 2000, &format); - - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - AddFakeDataToStream(stream.get(), 0); - - DevicePtr dev1 = - create_device(CRAS_STREAM_INPUT, 2048, &format, CRAS_NODE_TYPE_MIC); - DevicePtr dev2 = - create_device(CRAS_STREAM_INPUT, 10000, &format, CRAS_NODE_TYPE_MIC); - DL_APPEND(dev_list, dev1->odev.get()); - DL_APPEND(dev_list, dev2->odev.get()); - add_stream_to_dev(dev1->dev, stream); - add_stream_to_dev(dev2->dev, stream); - - iodev_stub_frames_queued(dev1->dev.get(), 2480, start); - iodev_stub_frames_queued(dev2->dev.get(), 2480, start); - EXPECT_EQ(0, dev_io_send_captured_samples(dev_list)); - - /* - * Should drop frames to one min_cb_level, which is 2480 - 2000 = 480 (10ms). - */ - rc = iodev_stub_get_drop_time(dev1->dev.get(), &drop_time); - EXPECT_EQ(true, rc); - EXPECT_EQ(0, drop_time.tv_sec); - EXPECT_EQ(10000000, drop_time.tv_nsec); - - rc = iodev_stub_get_drop_time(dev2->dev.get(), &drop_time); - EXPECT_EQ(true, rc); - EXPECT_EQ(0, drop_time.tv_sec); - EXPECT_EQ(10000000, drop_time.tv_nsec); -} - -/* * If the hw_level is larger than 1.5 * largest_cb_level but less than * DROP_FRAMES_THRESHOLD_MS, do nothing. */ @@ -274,10 +156,7 @@ TEST_F(DevIoSuite, SendCapturedLevelLessThanThreshold) { EXPECT_EQ(false, rc); } -/* - * If all hw_level is less than 1.5 * largest_cb_level and 0.5 * buffer_size, - * do nothing. - */ +/* If all hw_level is less than 1.5 * largest_cb_level, do nothing. */ TEST_F(DevIoSuite, SendCapturedNoNeedToResetDevices) { struct timespec start; struct timespec drop_time; @@ -307,50 +186,6 @@ TEST_F(DevIoSuite, SendCapturedNoNeedToResetDevices) { EXPECT_EQ(false, rc); } -/* - * On loopback and hotword devices, if any hw_level is larger than - * 1.5 * largest_cb_level and DROP_FRAMES_THRESHOLD_MS, do nothing. - */ -TEST_F(DevIoSuite, SendCapturedNoNeedToDrop) { - struct timespec start; - struct timespec drop_time; - struct open_dev* dev_list = NULL; - bool rc; - - clock_gettime(CLOCK_MONOTONIC_RAW, &start); - AddFakeDataToStream(stream.get(), 0); - - DevicePtr dev1 = - create_device(CRAS_STREAM_INPUT, 480, &format, CRAS_NODE_TYPE_HOTWORD); - DevicePtr dev2 = create_device(CRAS_STREAM_INPUT, 480, &format, - CRAS_NODE_TYPE_POST_MIX_PRE_DSP); - DevicePtr dev3 = - create_device(CRAS_STREAM_INPUT, 480, &format, CRAS_NODE_TYPE_POST_DSP); - - DL_APPEND(dev_list, dev1->odev.get()); - DL_APPEND(dev_list, dev2->odev.get()); - DL_APPEND(dev_list, dev3->odev.get()); - - add_stream_to_dev(dev1->dev, stream); - add_stream_to_dev(dev2->dev, stream); - add_stream_to_dev(dev3->dev, stream); - - iodev_stub_frames_queued(dev1->dev.get(), 4800, start); - iodev_stub_frames_queued(dev2->dev.get(), 4800, start); - iodev_stub_frames_queued(dev2->dev.get(), 4800, start); - - EXPECT_EQ(0, dev_io_send_captured_samples(dev_list)); - - rc = iodev_stub_get_drop_time(dev1->dev.get(), &drop_time); - EXPECT_EQ(false, rc); - - rc = iodev_stub_get_drop_time(dev2->dev.get(), &drop_time); - EXPECT_EQ(false, rc); - - rc = iodev_stub_get_drop_time(dev3->dev.get(), &drop_time); - EXPECT_EQ(false, rc); -} - /* Stubs */ extern "C" { @@ -369,20 +204,10 @@ int input_data_put_for_stream(struct input_data* data, return 0; } -float input_data_get_software_gain_scaler(struct input_data* data, - float idev_sw_gain_scaler, - struct cras_rstream* stream) { - return input_data_get_software_gain_scaler_val; -} - int cras_audio_thread_event_drop_samples() { return 0; } -int cras_audio_thread_event_severe_underrun() { - return 0; -} - int dev_stream_attached_devs(const struct dev_stream* dev_stream) { return 0; } @@ -402,16 +227,8 @@ int dev_stream_mix(struct dev_stream* dev_stream, void dev_stream_set_dev_rate(struct dev_stream* dev_stream, unsigned int dev_rate, double dev_rate_ratio, - double main_rate_ratio, - int coarse_rate_adjust) { - set_dev_rate_data new_data; - new_data.dev_rate = dev_rate; - new_data.dev_rate_ratio = dev_rate_ratio; - new_data.main_rate_ratio = main_rate_ratio; - new_data.coarse_rate_adjust = coarse_rate_adjust; - - set_dev_rate_map[dev_stream] = new_data; -} + double master_rate_ratio, + int coarse_rate_adjust) {} int dev_stream_capture_update_rstream(struct dev_stream* dev_stream) { return 0; } @@ -451,11 +268,7 @@ struct dev_stream* dev_stream_create(struct cras_rstream* stream, unsigned int dev_id, const struct cras_audio_format* dev_fmt, void* dev_ptr, - struct timespec* cb_ts, - const struct timespec* sleep_interval_ts) { - return 0; -} -int cras_device_monitor_error_close(unsigned int dev_idx) { + struct timespec* cb_ts) { return 0; } } // extern "C" diff --git a/cras/src/tests/dev_stream_unittest.cc b/cras/src/tests/dev_stream_unittest.cc index 700376fb..39c16e48 100644 --- a/cras/src/tests/dev_stream_unittest.cc +++ b/cras/src/tests/dev_stream_unittest.cc @@ -334,36 +334,18 @@ TEST_F(CreateSuite, CreateSRC44to48) { out_fmt.frame_rate = 48000; // Output from converter is device rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = - dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts, NULL); + dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device output. unsigned int device_frames = cras_frames_at_rate(in_fmt.frame_rate, kBufferFrames, out_fmt.frame_rate); - EXPECT_LE(kBufferFrames, device_frames); // Soundness check. + EXPECT_LE(kBufferFrames, device_frames); // Sanity check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); } -TEST_F(CreateSuite, CreateOutputWithSchedule) { - struct dev_stream* dev_stream; - unsigned int dev_id = 9; - // init_cb_ts and non-null init_sleep_ts will be used. - struct timespec init_cb_ts = {1, 2}; - struct timespec init_sleep_ts = {3, 4}; - - rstream_.direction = CRAS_STREAM_OUTPUT; - dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_48, (void*)0x55, - &init_cb_ts, &init_sleep_ts); - - EXPECT_EQ(init_cb_ts.tv_sec, rstream_.next_cb_ts.tv_sec); - EXPECT_EQ(init_cb_ts.tv_nsec, rstream_.next_cb_ts.tv_nsec); - EXPECT_EQ(init_sleep_ts.tv_sec, rstream_.sleep_interval_ts.tv_sec); - EXPECT_EQ(init_sleep_ts.tv_nsec, rstream_.sleep_interval_ts.tv_nsec); - dev_stream_destroy(dev_stream); -} - TEST_F(CreateSuite, CreateSRC44from48Input) { struct dev_stream* dev_stream; struct cras_audio_format processed_fmt = fmt_s16le_48; @@ -376,13 +358,13 @@ TEST_F(CreateSuite, CreateSRC44from48Input) { config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); cras_rstream_post_processing_format_val = &processed_fmt; dev_stream = - dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts, NULL); + dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device input. unsigned int device_frames = cras_frames_at_rate(out_fmt.frame_rate, kBufferFrames, in_fmt.frame_rate); - EXPECT_LE(kBufferFrames, device_frames); // Soundness check. + EXPECT_LE(kBufferFrames, device_frames); // Sanity check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_EQ(&processed_fmt, config_format_converter_from_fmt); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); @@ -396,8 +378,8 @@ TEST_F(CreateSuite, CreateSRC48to44) { in_fmt.frame_rate = 48000; // Stream rate. out_fmt.frame_rate = 44100; // Device rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); - dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, - &cb_ts, NULL); + dev_stream = + dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream input. @@ -414,8 +396,8 @@ TEST_F(CreateSuite, CreateSRC48from44Input) { in_fmt.frame_rate = 44100; // Device rate. out_fmt.frame_rate = 48000; // Stream rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); - dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, - &cb_ts, NULL); + dev_stream = + dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream output. @@ -432,13 +414,13 @@ TEST_F(CreateSuite, CreateSRC8to48) { out_fmt.frame_rate = 48000; // Device rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = - dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts, NULL); + dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device output. unsigned int device_frames = cras_frames_at_rate(in_fmt.frame_rate, kBufferFrames, out_fmt.frame_rate); - EXPECT_LE(kBufferFrames, device_frames); // Soundness check. + EXPECT_LE(kBufferFrames, device_frames); // Sanity check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); @@ -453,13 +435,13 @@ TEST_F(CreateSuite, CreateSRC8from48Input) { out_fmt.frame_rate = 8000; // Stream rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = - dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts, NULL); + dev_stream_create(&rstream_, 0, &fmt_s16le_48, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for device input. unsigned int device_frames = cras_frames_at_rate(out_fmt.frame_rate, kBufferFrames, in_fmt.frame_rate); - EXPECT_LE(kBufferFrames, device_frames); // Soundness check. + EXPECT_LE(kBufferFrames, device_frames); // Sanity check. EXPECT_LE(device_frames, config_format_converter_frames); EXPECT_LE(device_frames, dev_stream->conv_buffer_size_frames); dev_stream_destroy(dev_stream); @@ -473,7 +455,7 @@ TEST_F(CreateSuite, CreateSRC48to8) { out_fmt.frame_rate = 8000; // Device rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = - dev_stream_create(&rstream_, 0, &fmt_s16le_8, (void*)0x55, &cb_ts, NULL); + dev_stream_create(&rstream_, 0, &fmt_s16le_8, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream input. @@ -491,7 +473,7 @@ TEST_F(CreateSuite, CreateSRC48from8Input) { out_fmt.frame_rate = 48000; // Stream rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = - dev_stream_create(&rstream_, 0, &fmt_s16le_8, (void*)0x55, &cb_ts, NULL); + dev_stream_create(&rstream_, 0, &fmt_s16le_8, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream output. @@ -508,8 +490,8 @@ TEST_F(CreateSuite, CreateSRC48MonoFrom44StereoInput) { in_fmt.frame_rate = 44100; // Device rate. out_fmt.frame_rate = 48000; // Stream rate. config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); - dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, - &cb_ts, NULL); + dev_stream = + dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); // Converter tmp and output buffers are large enough for stream output. @@ -528,8 +510,8 @@ TEST_F(CreateSuite, CaptureAvailConvBufHasSamples) { rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); - dev_stream = dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, - &cb_ts, NULL); + dev_stream = + dev_stream_create(&rstream_, 0, &fmt_s16le_44_1, (void*)0x55, &cb_ts); EXPECT_EQ(1, config_format_converter_called); EXPECT_NE(static_cast<byte_buffer*>(NULL), dev_stream->conv_buffer); EXPECT_LE( @@ -547,16 +529,16 @@ TEST_F(CreateSuite, CaptureAvailConvBufHasSamples) { dev_stream_destroy(dev_stream); } -TEST_F(CreateSuite, SetDevRateNotMainDev) { +TEST_F(CreateSuite, SetDevRateNotMasterDev) { struct dev_stream* dev_stream; unsigned int dev_id = 9; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; - rstream_.main_dev.dev_id = 4; + rstream_.master_dev.dev_id = 4; config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); dev_stream_set_dev_rate(dev_stream, 44100, 1.01, 1.0, 0); EXPECT_EQ(1, cras_fmt_conv_set_linear_resample_rates_called); @@ -575,17 +557,17 @@ TEST_F(CreateSuite, SetDevRateNotMainDev) { dev_stream_destroy(dev_stream); } -TEST_F(CreateSuite, SetDevRateMainDev) { +TEST_F(CreateSuite, SetDevRateMasterDev) { struct dev_stream* dev_stream; unsigned int dev_id = 9; unsigned int expected_ts_nsec; rstream_.format = fmt_s16le_48; rstream_.direction = CRAS_STREAM_INPUT; - rstream_.main_dev.dev_id = dev_id; + rstream_.master_dev.dev_id = dev_id; config_format_converter_conv = reinterpret_cast<struct cras_fmt_conv*>(0x33); dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); dev_stream_set_dev_rate(dev_stream, 44100, 1.01, 1.0, 0); EXPECT_EQ(1, cras_fmt_conv_set_linear_resample_rates_called); @@ -679,7 +661,7 @@ TEST_F(CreateSuite, DevStreamFlushAudioMessages) { unsigned int dev_id = 9; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); dev_stream_flush_old_audio_messages(dev_stream); EXPECT_EQ(1, cras_rstream_flush_old_audio_messages_called); @@ -691,7 +673,7 @@ TEST_F(CreateSuite, DevStreamIsPending) { unsigned int dev_id = 9; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); // dev_stream_is_pending_reply is only a wrapper. cras_rstream_is_pending_reply_ret = 0; @@ -712,7 +694,7 @@ TEST_F(CreateSuite, StreamCanSend) { rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream. rstream_.next_cb_ts.tv_sec = 1; @@ -809,7 +791,7 @@ TEST_F(CreateSuite, StreamCanSendBulkAudio) { rstream_.direction = CRAS_STREAM_INPUT; rstream_.flags |= BULK_AUDIO_OK; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream. rstream_.next_cb_ts.tv_sec = 1; @@ -882,7 +864,7 @@ TEST_F(CreateSuite, TriggerOnlyStreamSendOnlyOnce) { rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); dev_stream->stream->flags = TRIGGER_ONLY; dev_stream->stream->triggered = 0; @@ -914,7 +896,7 @@ TEST_F(CreateSuite, InputDevStreamWakeTimeByNextCbTs) { rstream_.direction = CRAS_STREAM_INPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream. rstream_.next_cb_ts.tv_sec = 1; @@ -947,8 +929,8 @@ TEST_F(CreateSuite, InputDevStreamWakeTimeByDevice) { int needed_frames_from_device = 0; rstream_.direction = CRAS_STREAM_INPUT; - dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_48, (void*)0x55, - &cb_ts, NULL); + dev_stream = + dev_stream_create(&rstream_, dev_id, &fmt_s16le_48, (void*)0x55, &cb_ts); // Assume there is a next_cb_ts on rstream, that is, 1.005 seconds. rstream_.next_cb_ts.tv_sec = 1; @@ -1012,7 +994,7 @@ TEST_F(CreateSuite, UpdateNextWakeTime) { rstream_.direction = CRAS_STREAM_OUTPUT; dev_stream = dev_stream_create(&rstream_, dev_id, &fmt_s16le_44_1, - (void*)0x55, &cb_ts, NULL); + (void*)0x55, &cb_ts); // Case 1: The new next_cb_ts is greater than now. Do not need to reschedule. rstream_.next_cb_ts.tv_sec = 2; @@ -1188,11 +1170,6 @@ struct cras_audio_format* cras_rstream_post_processing_format( void* dev_ptr) { return cras_rstream_post_processing_format_val; } -void* buffer_share_get_data(const struct buffer_share* mix, unsigned int id) { - return NULL; -}; -void cras_apm_list_start_apm(struct cras_apm_list* list, void* dev_ptr){}; -void cras_apm_list_stop_apm(struct cras_apm_list* list, void* dev_ptr){}; int config_format_converter(struct cras_fmt_conv** conv, enum CRAS_STREAM_DIRECTION dir, @@ -1314,7 +1291,7 @@ int cras_rstream_flush_old_audio_messages(struct cras_rstream* stream) { return 0; } -int cras_server_metrics_missed_cb_event(struct cras_rstream* stream) { +int cras_server_metrics_missed_cb_event(const struct cras_rstream* stream) { cras_server_metrics_missed_cb_event_called++; return 0; } diff --git a/cras/src/tests/device_blacklist_unittest.cc b/cras/src/tests/device_blacklist_unittest.cc new file mode 100644 index 00000000..2c1edf06 --- /dev/null +++ b/cras/src/tests/device_blacklist_unittest.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <gtest/gtest.h> +#include <stdio.h> + +extern "C" { +#include "cras_device_blacklist.h" +} + +namespace { + +static const char CONFIG_PATH[] = CRAS_UT_TMPDIR; +static const char CONFIG_FILENAME[] = "device_blacklist"; + +void CreateConfigFile(const char* config_text) { + FILE* f; + char card_path[128]; + + snprintf(card_path, sizeof(card_path), "%s/%s", CONFIG_PATH, CONFIG_FILENAME); + f = fopen(card_path, "w"); + if (f == NULL) + return; + + fprintf(f, "%s", config_text); + + fclose(f); +} + +TEST(Blacklist, EmptyBlacklist) { + static const char empty_config_text[] = ""; + struct cras_device_blacklist* blacklist; + + CreateConfigFile(empty_config_text); + + blacklist = cras_device_blacklist_create(CONFIG_PATH); + ASSERT_NE(static_cast<cras_device_blacklist*>(NULL), blacklist); + EXPECT_EQ(0, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0008, 0, 0)); + + cras_device_blacklist_destroy(blacklist); +} + +TEST(Blacklist, BlackListOneUsbOutput) { + static const char usb_output_config_text[] = + "[USB_Outputs]\n" + "0d8c_0008_00000012_0 = 1\n"; + struct cras_device_blacklist* blacklist; + + CreateConfigFile(usb_output_config_text); + + blacklist = cras_device_blacklist_create(CONFIG_PATH); + ASSERT_NE(static_cast<cras_device_blacklist*>(NULL), blacklist); + + EXPECT_EQ(0, cras_device_blacklist_check(blacklist, 0x0d8d, 0x0008, 0x12, 0)); + EXPECT_EQ(0, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0009, 0x12, 0)); + EXPECT_EQ(0, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0008, 0x13, 0)); + EXPECT_EQ(0, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0008, 0x12, 1)); + EXPECT_EQ(1, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0008, 0x12, 0)); + + cras_device_blacklist_destroy(blacklist); +} + +TEST(Blacklist, BlackListTwoUsbOutput) { + static const char usb_output_config_text[] = + "[USB_Outputs]\n" + "0d8c_0008_00000000_0 = 1\n" + "0d8c_0009_00000000_0 = 1\n"; + struct cras_device_blacklist* blacklist; + + CreateConfigFile(usb_output_config_text); + + blacklist = cras_device_blacklist_create(CONFIG_PATH); + ASSERT_NE(static_cast<cras_device_blacklist*>(NULL), blacklist); + + EXPECT_EQ(1, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0009, 0, 0)); + EXPECT_EQ(1, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0008, 0, 0)); + EXPECT_EQ(0, cras_device_blacklist_check(blacklist, 0x0d8c, 0x0008, 0, 1)); + + cras_device_blacklist_destroy(blacklist); +} + +} // namespace + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/cras/src/tests/device_blocklist_unittest.cc b/cras/src/tests/device_blocklist_unittest.cc deleted file mode 100644 index 44a976e1..00000000 --- a/cras/src/tests/device_blocklist_unittest.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <gtest/gtest.h> -#include <stdio.h> - -extern "C" { -#include "cras_device_blocklist.h" -} - -namespace { - -static const char CONFIG_PATH[] = CRAS_UT_TMPDIR; -static const char CONFIG_FILENAME[] = "device_blocklist"; - -void CreateConfigFile(const char* config_text) { - FILE* f; - char card_path[128]; - - snprintf(card_path, sizeof(card_path), "%s/%s", CONFIG_PATH, CONFIG_FILENAME); - f = fopen(card_path, "w"); - if (f == NULL) - return; - - fprintf(f, "%s", config_text); - - fclose(f); -} - -TEST(Blocklist, EmptyBlocklist) { - static const char empty_config_text[] = ""; - struct cras_device_blocklist* blocklist; - - CreateConfigFile(empty_config_text); - - blocklist = cras_device_blocklist_create(CONFIG_PATH); - ASSERT_NE(static_cast<cras_device_blocklist*>(NULL), blocklist); - EXPECT_EQ(0, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0008, 0, 0)); - - cras_device_blocklist_destroy(blocklist); -} - -TEST(Blocklist, BlockListOneUsbOutput) { - static const char usb_output_config_text[] = - "[USB_Outputs]\n" - "0d8c_0008_00000012_0 = 1\n"; - struct cras_device_blocklist* blocklist; - - CreateConfigFile(usb_output_config_text); - - blocklist = cras_device_blocklist_create(CONFIG_PATH); - ASSERT_NE(static_cast<cras_device_blocklist*>(NULL), blocklist); - - EXPECT_EQ(0, cras_device_blocklist_check(blocklist, 0x0d8d, 0x0008, 0x12, 0)); - EXPECT_EQ(0, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0009, 0x12, 0)); - EXPECT_EQ(0, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0008, 0x13, 0)); - EXPECT_EQ(0, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0008, 0x12, 1)); - EXPECT_EQ(1, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0008, 0x12, 0)); - - cras_device_blocklist_destroy(blocklist); -} - -TEST(Blocklist, BlockListTwoUsbOutput) { - static const char usb_output_config_text[] = - "[USB_Outputs]\n" - "0d8c_0008_00000000_0 = 1\n" - "0d8c_0009_00000000_0 = 1\n"; - struct cras_device_blocklist* blocklist; - - CreateConfigFile(usb_output_config_text); - - blocklist = cras_device_blocklist_create(CONFIG_PATH); - ASSERT_NE(static_cast<cras_device_blocklist*>(NULL), blocklist); - - EXPECT_EQ(1, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0009, 0, 0)); - EXPECT_EQ(1, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0008, 0, 0)); - EXPECT_EQ(0, cras_device_blocklist_check(blocklist, 0x0d8c, 0x0008, 0, 1)); - - cras_device_blocklist_destroy(blocklist); -} - -} // namespace - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/cras/src/tests/empty_iodev_unittest.cc b/cras/src/tests/empty_iodev_unittest.cc index 148d5301..585fba32 100644 --- a/cras/src/tests/empty_iodev_unittest.cc +++ b/cras/src/tests/empty_iodev_unittest.cc @@ -13,7 +13,7 @@ extern "C" { static struct timespec clock_gettime_retspec; static struct cras_audio_format fake_format; -static cras_audio_area mock_audio_area; +static cras_audio_area dummy_audio_area; namespace { @@ -57,7 +57,7 @@ int cras_iodev_default_no_stream_playback(struct cras_iodev* odev, int enable) { } void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) { - iodev->area = &mock_audio_area; + iodev->area = &dummy_audio_area; } void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} diff --git a/cras/src/tests/ewma_power_unittest.cc b/cras/src/tests/ewma_power_unittest.cc deleted file mode 100644 index 10f03189..00000000 --- a/cras/src/tests/ewma_power_unittest.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <gtest/gtest.h> - -extern "C" { -#include "ewma_power.h" -} - -namespace { - -TEST(EWMAPower, RelativePowerValue) { - struct ewma_power ewma; - int16_t buf[480]; - float f; - int i; - - for (i = 0; i < 480; i++) - buf[i] = 0x00fe; - - ewma_power_init(&ewma, 48000); - EXPECT_EQ(48, ewma.step_fr); - - ewma_power_calculate(&ewma, buf, 1, 480); - EXPECT_LT(0.0f, ewma.power); - - // After 10ms of silence the power value decreases. - f = ewma.power; - for (i = 0; i < 480; i++) - buf[i] = 0x00; - ewma_power_calculate(&ewma, buf, 1, 480); - EXPECT_LT(ewma.power, f); - - // After 300ms of silence the power value decreases to insignificant low. - for (i = 0; i < 30; i++) - ewma_power_calculate(&ewma, buf, 1, 480); - EXPECT_LT(ewma.power, 1.0e-10); -} - -TEST(EWMAPower, PowerInStereoData) { - struct ewma_power ewma; - int16_t buf[960]; - int i; - float f; - - ewma_power_init(&ewma, 48000); - - for (i = 0; i < 960; i += 2) { - buf[i] = 0x0; - buf[i + 1] = 0x00fe; - } - ewma_power_calculate(&ewma, buf, 2, 480); - EXPECT_LT(0.0f, ewma.power); - - // After 10ms of silence the power value decreases. - f = ewma.power; - for (i = 0; i < 960; i++) - buf[i] = 0x0; - ewma_power_calculate(&ewma, buf, 2, 480); - EXPECT_LT(ewma.power, f); - - // After 300ms of silence the power value decreases to insignificant low. - for (i = 0; i < 30; i++) - ewma_power_calculate(&ewma, buf, 2, 480); - EXPECT_LT(ewma.power, 1.0e-10); - - // Assume the data is silent in the other channel. - ewma_power_init(&ewma, 48000); - - for (i = 0; i < 960; i += 2) { - buf[i] = 0x0ffe; - buf[i + 1] = 0x0; - } - ewma_power_calculate(&ewma, buf, 2, 480); - EXPECT_LT(0.0f, ewma.power); -} - -TEST(EWMAPower, PowerInAudioArea) { - struct ewma_power ewma; - struct cras_audio_area* area = cras_audio_area_create(4); - struct cras_audio_format* fmt = - cras_audio_format_create(SND_PCM_FORMAT_S16_LE, 48000, 4); - int8_t layout[CRAS_CH_MAX] = {0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int16_t buf[1920]; - int i; - float f; - - cras_audio_format_set_channel_layout(fmt, layout); - cras_audio_area_config_channels(area, fmt); - - for (i = 0; i < 1920; i += 4) { - buf[i] = 0x0ffe; - buf[i + 1] = 0x0; - buf[i + 2] = 0x0; - buf[i + 3] = 0x0ffe; - } - ewma_power_init(&ewma, 48000); - ewma_power_calculate_area(&ewma, buf, area, 480); - f = ewma.power; - EXPECT_LT(0.0f, f); - - /* Change the layout in the same audio area. Expect the power be lower because - * one of the channel is now silent. */ - layout[CRAS_CH_FR] = 2; - cras_audio_format_set_channel_layout(fmt, layout); - cras_audio_area_config_channels(area, fmt); - ewma_power_init(&ewma, 48000); - ewma_power_calculate_area(&ewma, buf, area, 480); - EXPECT_GT(f, ewma.power); - - /* Change layout to the two silent channels. Expect power is 0.0f. */ - layout[CRAS_CH_FL] = 1; - cras_audio_format_set_channel_layout(fmt, layout); - cras_audio_area_config_channels(area, fmt); - ewma_power_init(&ewma, 48000); - ewma_power_calculate_area(&ewma, buf, area, 480); - EXPECT_EQ(0.0f, ewma.power); - - cras_audio_format_destroy(fmt); - cras_audio_area_destroy(area); -} - -} // namespace - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/cras/src/tests/fmt_conv_ops_unittest.cc b/cras/src/tests/fmt_conv_ops_unittest.cc index 0baf37b1..d58d618e 100644 --- a/cras/src/tests/fmt_conv_ops_unittest.cc +++ b/cras/src/tests/fmt_conv_ops_unittest.cc @@ -4,8 +4,6 @@ #include <gtest/gtest.h> #include <limits.h> -#include <math.h> -#include <stdint.h> #include <sys/param.h> #include <memory> @@ -418,39 +416,6 @@ TEST(FormatConverterOpsTest, StereoTo51S16LECenter) { } } -// Test Quad to 5.1 conversion. S16_LE. -TEST(FormatConverterOpsTest, QuadTo51S16LE) { - const size_t frames = 4096; - const size_t in_ch = 4; - const size_t out_ch = 6; - const unsigned int fl_quad = 0; - const unsigned int fr_quad = 1; - const unsigned int rl_quad = 2; - const unsigned int rr_quad = 3; - - const unsigned int fl_51 = 0; - const unsigned int fr_51 = 1; - const unsigned int center_51 = 2; - const unsigned int lfe_51 = 3; - const unsigned int rl_51 = 4; - const unsigned int rr_51 = 5; - - S16LEPtr src = CreateS16LE(frames * in_ch); - S16LEPtr dst = CreateS16LE(frames * out_ch); - - size_t ret = s16_quad_to_51(fl_51, fr_51, rl_51, rr_51, (uint8_t*)src.get(), - frames, (uint8_t*)dst.get()); - EXPECT_EQ(ret, frames); - for (size_t i = 0; i < frames; ++i) { - EXPECT_EQ(0, dst[i * 6 + center_51]); - EXPECT_EQ(0, dst[i * 6 + lfe_51]); - EXPECT_EQ(src[i * 4 + fl_quad], dst[i * 6 + fl_51]); - EXPECT_EQ(src[i * 4 + fr_quad], dst[i * 6 + fr_51]); - EXPECT_EQ(src[i * 4 + rl_quad], dst[i * 6 + rl_51]); - EXPECT_EQ(src[i * 4 + rr_quad], dst[i * 6 + rr_51]); - } -} - // Test Stereo to 5.1 conversion. S16_LE, LeftRight. TEST(FormatConverterOpsTest, StereoTo51S16LELeftRight) { const size_t frames = 4096; @@ -512,7 +477,7 @@ TEST(FormatConverterOpsTest, _51ToStereoS16LE) { const size_t out_ch = 2; const size_t left = 0; const size_t right = 1; - const size_t center = 2; + const size_t center = 4; S16LEPtr src = CreateS16LE(frames * in_ch); S16LEPtr dst = CreateS16LE(frames * out_ch); @@ -521,58 +486,11 @@ TEST(FormatConverterOpsTest, _51ToStereoS16LE) { s16_51_to_stereo((uint8_t*)src.get(), frames, (uint8_t*)dst.get()); EXPECT_EQ(ret, frames); - /* Use the normalized_factor from the left channel = 1 / (|1| + |0.707|) - * to prevent mixing overflow. - */ - const float normalized_factor = 0.585; - - for (size_t i = 0; i < frames; ++i) { - int16_t half_center = src[i * 6 + center] * 0.707 * normalized_factor; - int16_t l = normalized_factor * src[i * 6 + left] + half_center; - int16_t r = normalized_factor * src[i * 6 + right] + half_center; - - EXPECT_EQ(l, dst[i * 2 + left]); - EXPECT_EQ(r, dst[i * 2 + right]); - } -} - -// Test 5.1 to Quad conversion. S16_LE. -TEST(FormatConverterOpsTest, _51ToQuadS16LE) { - const size_t frames = 4096; - const size_t in_ch = 6; - const size_t out_ch = 4; - const unsigned int fl_quad = 0; - const unsigned int fr_quad = 1; - const unsigned int rl_quad = 2; - const unsigned int rr_quad = 3; - - const unsigned int fl_51 = 0; - const unsigned int fr_51 = 1; - const unsigned int center_51 = 2; - const unsigned int lfe_51 = 3; - const unsigned int rl_51 = 4; - const unsigned int rr_51 = 5; - - S16LEPtr src = CreateS16LE(frames * in_ch); - S16LEPtr dst = CreateS16LE(frames * out_ch); - - size_t ret = s16_51_to_quad((uint8_t*)src.get(), frames, (uint8_t*)dst.get()); - EXPECT_EQ(ret, frames); - - /* Use normalized_factor from the left channel = 1 / (|1| + |0.707| + |0.5|) - * to prevent overflow. */ - const float normalized_factor = 0.453; for (size_t i = 0; i < frames; ++i) { - int16_t half_center = src[i * 6 + center_51] * 0.707 * normalized_factor; - int16_t lfe = src[6 * i + lfe_51] * 0.5 * normalized_factor; - int16_t fl = normalized_factor * src[6 * i + fl_51] + half_center + lfe; - int16_t fr = normalized_factor * src[6 * i + fr_51] + half_center + lfe; - int16_t rl = normalized_factor * src[6 * i + rl_51] + lfe; - int16_t rr = normalized_factor * src[6 * i + rr_51] + lfe; - EXPECT_EQ(fl, dst[4 * i + fl_quad]); - EXPECT_EQ(fr, dst[4 * i + fr_quad]); - EXPECT_EQ(rl, dst[4 * i + rl_quad]); - EXPECT_EQ(rr, dst[4 * i + rr_quad]); + int16_t half_center = src[i * 6 + center] / 2; + EXPECT_EQ(S16AddAndClip(src[i * 6 + left], half_center), dst[i * 2 + left]); + EXPECT_EQ(S16AddAndClip(src[i * 6 + right], half_center), + dst[i * 2 + right]); } } @@ -701,42 +619,12 @@ TEST(FormatConverterOpsTest, StereoTo3chS16LE) { EXPECT_EQ(ret, frames); for (size_t i = 0; i < frames; ++i) { - int32_t sum = 0; for (size_t k = 0; k < in_ch; ++k) - sum += (int32_t)src[i * in_ch + k]; - src[i * in_ch + 0] = (int16_t)(sum / (int32_t)in_ch); - } - for (size_t i = 0; i < frames; ++i) { - for (size_t k = 0; k < out_ch; ++k) - EXPECT_EQ(src[i * in_ch + 0], dst[i * out_ch + k]); - } -} - -// Test 6ch to 8ch conversion. S16_LE. -TEST(FormatConverterOpsTest, 6chTo8chS16LE) { - const size_t frames = 65536; - const size_t in_ch = 6; - const size_t out_ch = 8; - struct cras_audio_format fmt = { - .format = SND_PCM_FORMAT_S16_LE, - .frame_rate = 48000, - .num_channels = 8, - }; - - S16LEPtr src = CreateS16LE(frames * in_ch); - S16LEPtr dst = CreateS16LE(frames * out_ch); - for (size_t i = 0; i < frames; ++i) { - for (size_t k = 0; k < in_ch; k++) { - src[i * in_ch + k] = (k == 0) ? (INT16_MIN + (int16_t)i) : 0; - } + src[i * in_ch + k] /= in_ch; + for (size_t k = 1; k < in_ch; ++k) + src[i * in_ch + 0] += src[i * in_ch + k]; } - - size_t ret = s16_default_all_to_all(&fmt, in_ch, out_ch, (uint8_t*)src.get(), - frames, (uint8_t*)dst.get()); - EXPECT_EQ(ret, frames); - for (size_t i = 0; i < frames; ++i) { - src[i * in_ch + 0] /= (int16_t)in_ch; for (size_t k = 0; k < out_ch; ++k) EXPECT_EQ(src[i * in_ch + 0], dst[i * out_ch + k]); } @@ -788,65 +676,6 @@ TEST(FormatConverterOpsTest, ConvertChannelsS16LE) { } } -// Test Stereo to 20ch conversion. S16_LE. -TEST(FormatConverterOpsTest, TwoToTwentyS16LE) { - const size_t frames = 4096; - const size_t in_ch = 2; - const size_t out_ch = 20; - struct cras_audio_format fmt = { - .format = SND_PCM_FORMAT_S16_LE, - .frame_rate = 48000, - .num_channels = 20, - }; - - S16LEPtr src = CreateS16LE(frames * in_ch); - S16LEPtr dst = CreateS16LE(frames * out_ch); - - size_t ret = s16_some_to_some(&fmt, in_ch, out_ch, (uint8_t*)src.get(), - frames, (uint8_t*)dst.get()); - EXPECT_EQ(ret, frames); - - for (size_t i = 0; i < frames; ++i) { - size_t k; - // Input channles should be directly copied over. - for (k = 0; k < in_ch; ++k) { - EXPECT_EQ(src[i * in_ch + k], dst[i * out_ch + k]); - } - // The rest should be zeroed. - for (; k < out_ch; ++k) { - EXPECT_EQ(0, dst[i * out_ch + k]); - } - - } -} - -// Test 20ch to Stereo. S16_LE. -TEST(FormatConverterOpsTest, TwentyToTwoS16LE) { - const size_t frames = 4096; - const size_t in_ch = 20; - const size_t out_ch = 2; - struct cras_audio_format fmt = { - .format = SND_PCM_FORMAT_S16_LE, - .frame_rate = 48000, - .num_channels = 2, - }; - - S16LEPtr src = CreateS16LE(frames * in_ch); - S16LEPtr dst = CreateS16LE(frames * out_ch); - - size_t ret = s16_some_to_some(&fmt, in_ch, out_ch, (uint8_t*)src.get(), - frames, (uint8_t*)dst.get()); - EXPECT_EQ(ret, frames); - - for (size_t i = 0; i < frames; ++i) { - size_t k; - // Input channles should be directly copied over. - for (k = 0; k < out_ch; ++k) { - EXPECT_EQ(src[i * in_ch + k], dst[i * out_ch + k]); - } - } -} - extern "C" {} // extern "C" int main(int argc, char** argv) { diff --git a/cras/src/tests/fmt_conv_unittest.cc b/cras/src/tests/fmt_conv_unittest.cc index c66984ee..5474f172 100644 --- a/cras/src/tests/fmt_conv_unittest.cc +++ b/cras/src/tests/fmt_conv_unittest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include <gtest/gtest.h> -#include <math.h> #include <sys/param.h> extern "C" { @@ -460,81 +459,6 @@ TEST(FormatConverterTest, SurroundToStereo) { free(out_buff); } -// Test 5.1 to Quad mix. -TEST(FormatConverterTest, SurroundToQuad) { - struct cras_fmt_conv* c; - struct cras_audio_format in_fmt; - struct cras_audio_format out_fmt; - - size_t out_frames; - int16_t* in_buff; - int16_t* out_buff; - unsigned int i; - const size_t buf_size = 4096; - unsigned int in_buf_size = 4096; - - ResetStub(); - in_fmt.format = SND_PCM_FORMAT_S16_LE; - out_fmt.format = SND_PCM_FORMAT_S16_LE; - in_fmt.num_channels = 6; - out_fmt.num_channels = 4; - in_fmt.frame_rate = 48000; - out_fmt.frame_rate = 48000; - for (i = 0; i < CRAS_CH_MAX; i++) - in_fmt.channel_layout[i] = surround_channel_center_layout[i]; - - c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0); - ASSERT_NE(c, (void*)NULL); - - out_frames = cras_fmt_conv_out_frames_to_in(c, buf_size); - EXPECT_EQ(buf_size, out_frames); - - out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size); - EXPECT_EQ(buf_size, out_frames); - - in_buff = (int16_t*)malloc(buf_size * 2 * cras_get_format_bytes(&in_fmt)); - - const int16_t in_fl = 100; - const int16_t in_fr = 200; - const int16_t in_rl = 200; - const int16_t in_rr = 300; - const int16_t in_fc = 60; - const int16_t in_lfe = 90; - - for (i = 0; i < buf_size; i++) { - in_buff[i * 6 + CRAS_CH_FL] = in_fl; - in_buff[i * 6 + CRAS_CH_FR] = in_fr; - in_buff[i * 6 + CRAS_CH_RL] = in_rl; - in_buff[i * 6 + CRAS_CH_RR] = in_rr; - in_buff[i * 6 + CRAS_CH_FC] = in_fc; - in_buff[i * 6 + CRAS_CH_LFE] = in_lfe; - } - out_buff = (int16_t*)malloc(buf_size * 2 * cras_get_format_bytes(&out_fmt)); - out_frames = cras_fmt_conv_convert_frames( - c, (uint8_t*)in_buff, (uint8_t*)out_buff, &in_buf_size, buf_size); - EXPECT_EQ(buf_size, out_frames); - - // This is the sum of mtx[CRAS_CH_FL] coefficients. - const float normalize_factor = 1.0 / (1 + 0.707 + 0.5); - - for (i = 0; i < buf_size; i++) { - int16_t lfe = 0.5 * normalize_factor * in_lfe; - int16_t center = 0.707 * normalize_factor * in_fc; - int16_t fl = normalize_factor * in_fl + center + lfe; - int16_t fr = normalize_factor * in_fr + center + lfe; - int16_t rl = normalize_factor * in_rl + lfe; - int16_t rr = normalize_factor * in_rr + lfe; - - EXPECT_EQ(fl, out_buff[i * 4 + CRAS_CH_FL]); - EXPECT_EQ(fr, out_buff[i * 4 + CRAS_CH_FR]); - EXPECT_EQ(rl, out_buff[i * 4 + CRAS_CH_RL]); - EXPECT_EQ(rr, out_buff[i * 4 + CRAS_CH_RR]); - } - cras_fmt_conv_destroy(&c); - free(in_buff); - free(out_buff); -} - // Test Quad to Stereo mix. TEST(FormatConverterTest, QuadToStereo) { struct cras_fmt_conv* c; diff --git a/cras/src/tests/hfp_ag_profile_unittest.cc b/cras/src/tests/hfp_ag_profile_unittest.cc index 3ecd2407..56c99088 100644 --- a/cras/src/tests/hfp_ag_profile_unittest.cc +++ b/cras/src/tests/hfp_ag_profile_unittest.cc @@ -167,25 +167,6 @@ int cras_bt_add_profile(DBusConnection* conn, struct cras_bt_profile* profile) { return 0; } -int cras_bt_rm_profile(DBusConnection* conn, struct cras_bt_profile* profile) { - internal_bt_profile = NULL; - return 0; -} - -int cras_bt_register_profile(DBusConnection* conn, - struct cras_bt_profile* profile) { - return 0; -} - -int cras_bt_register_profiles(DBusConnection* conn) { - return 0; -} - -int cras_bt_unregister_profile(DBusConnection* conn, - struct cras_bt_profile* profile) { - return 0; -} - struct hfp_info* hfp_info_create() { return NULL; } @@ -243,22 +224,11 @@ struct hfp_slc_handle* hfp_slc_create(int fd, int hfp_slc_get_selected_codec(struct hfp_slc_handle* handle) { return HFP_CODEC_ID_CVSD; } -int hfp_slc_get_ag_codec_negotiation_supported(struct hfp_slc_handle* handle) { - return 1; -} int hfp_slc_get_hf_codec_negotiation_supported(struct hfp_slc_handle* handle) { return 1; } -int hfp_slc_get_hf_supports_battery_indicator(struct hfp_slc_handle* handle) { - return 0; -} - -int hfp_slc_get_hf_battery_level(struct hfp_slc_handle* handle) { - return -1; -} - struct cras_bt_device* cras_a2dp_connected_device() { return NULL; } @@ -270,10 +240,6 @@ int cras_bt_device_supports_profile(const struct cras_bt_device* device, void cras_a2dp_suspend_connected_device(struct cras_bt_device* device) {} -const char* cras_bt_device_address(const struct cras_bt_device* device) { - return ""; -} - int cras_bt_device_audio_gateway_initialized(struct cras_bt_device* device) { return 0; } @@ -286,22 +252,10 @@ void cras_bt_device_notify_profile_dropped( cras_bt_device_notify_profile_dropped_profile = profile; } -void hfp_info_set_wbs_logger(struct hfp_info* info, - struct packet_status_logger* wbs_logger) {} - -void cras_observer_notify_bt_battery_changed(const char* address, - uint32_t level) { - return; -} - bool cras_system_get_bt_wbs_enabled() { return true; } -int cras_server_metrics_hfp_wideband_selected_codec(int codec) { - return HFP_CODEC_ID_MSBC; -} - } // extern "C" int main(int argc, char** argv) { diff --git a/cras/src/tests/hfp_alsa_iodev_unittest.cc b/cras/src/tests/hfp_alsa_iodev_unittest.cc index 8756c201..a4d5ba94 100644 --- a/cras/src/tests/hfp_alsa_iodev_unittest.cc +++ b/cras/src/tests/hfp_alsa_iodev_unittest.cc @@ -22,7 +22,6 @@ struct hfp_alsa_io { static struct cras_iodev fake_sco_out, fake_sco_in; static struct cras_bt_device* fake_device; static struct hfp_slc_handle* fake_slc; -static struct cras_audio_format fake_format; static size_t cras_bt_device_append_iodev_called; static size_t cras_bt_device_rm_iodev_called; @@ -58,7 +57,6 @@ _FAKE_CALL1(open_dev); _FAKE_CALL1(update_supported_formats); _FAKE_CALL1(configure_dev); _FAKE_CALL1(close_dev); -_FAKE_CALL1(output_underrun); _FAKE_CALL2(frames_queued); _FAKE_CALL1(delay_frames); _FAKE_CALL3(get_buffer); @@ -68,7 +66,6 @@ _FAKE_CALL3(update_active_node); _FAKE_CALL1(start); _FAKE_CALL2(no_stream); _FAKE_CALL1(is_free_running); -_FAKE_CALL2(get_valid_frames); static void ResetStubData() { cras_bt_device_append_iodev_called = 0; @@ -133,14 +130,6 @@ static void ResetStubData() { fake_sco_out.is_free_running = fake_sco_in.is_free_running = (int (*)(const struct cras_iodev*))fake_is_free_running; fake_is_free_running_called = 0; - - fake_sco_out.output_underrun = - (int (*)(struct cras_iodev*))fake_output_underrun; - fake_output_underrun_called = 0; - - fake_sco_out.get_valid_frames = - (int (*)(struct cras_iodev*, struct timespec*))fake_get_valid_frames; - fake_get_valid_frames_called = 0; } namespace { @@ -227,8 +216,7 @@ TEST_F(HfpAlsaIodev, UpdateSupportedFormat) { CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); iodev->update_supported_formats(iodev); - // update_supported_format on alsa_io is not called. - EXPECT_EQ(0, fake_update_supported_formats_called); + EXPECT_EQ(1, fake_update_supported_formats_called); for (size_t i = 0; i < 2; ++i) { EXPECT_EQ(supported_rates[i], iodev->supported_rates[i]); EXPECT_EQ(supported_channel_counts[i], iodev->supported_channel_counts[i]); @@ -241,23 +229,13 @@ TEST_F(HfpAlsaIodev, UpdateSupportedFormat) { TEST_F(HfpAlsaIodev, ConfigureDev) { struct cras_iodev* iodev; size_t buf_size = 8192; - struct hfp_alsa_io* hfp_alsa_io; fake_sco_out.direction = CRAS_STREAM_OUTPUT; fake_sco_out.buffer_size = buf_size; iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc, CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - hfp_alsa_io = (struct hfp_alsa_io*)iodev; - iodev->format = &fake_format; iodev->configure_dev(iodev); - EXPECT_EQ(fake_format.num_channels, hfp_alsa_io->aio->format->num_channels); - EXPECT_EQ(fake_format.frame_rate, hfp_alsa_io->aio->format->frame_rate); - EXPECT_EQ(fake_format.format, hfp_alsa_io->aio->format->format); - for (int i = 0; i < CRAS_CH_MAX; i++) - EXPECT_EQ(fake_format.channel_layout[i], - hfp_alsa_io->aio->format->channel_layout[i]); - EXPECT_EQ(1, fake_configure_dev_called); EXPECT_EQ(1, hfp_set_call_status_called); EXPECT_EQ(buf_size, iodev->buffer_size); @@ -273,7 +251,6 @@ TEST_F(HfpAlsaIodev, CloseDev) { CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); iodev->close_dev(iodev); - EXPECT_EQ(1, hfp_set_call_status_called); EXPECT_EQ(1, cras_iodev_free_format_called); EXPECT_EQ(1, fake_close_dev_called); @@ -415,38 +392,6 @@ TEST_F(HfpAlsaIodev, IsFreeRunning) { hfp_alsa_iodev_destroy(iodev); } -TEST_F(HfpAlsaIodev, OutputUnderrun) { - struct cras_iodev* iodev; - - fake_sco_out.direction = CRAS_STREAM_OUTPUT; - iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc, - CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - iodev->min_cb_level = 0xab; - iodev->max_cb_level = 0xcd; - - iodev->output_underrun(iodev); - - EXPECT_EQ(0xab, fake_sco_out.min_cb_level); - EXPECT_EQ(0xcd, fake_sco_out.max_cb_level); - EXPECT_EQ(1, fake_output_underrun_called); - - hfp_alsa_iodev_destroy(iodev); -} - -TEST_F(HfpAlsaIodev, GetValidFrames) { - struct cras_iodev* iodev; - struct timespec ts; - - fake_sco_out.direction = CRAS_STREAM_OUTPUT; - iodev = hfp_alsa_iodev_create(&fake_sco_out, fake_device, fake_slc, - CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); - - iodev->get_valid_frames(iodev, &ts); - - EXPECT_EQ(1, fake_get_valid_frames_called); - - hfp_alsa_iodev_destroy(iodev); -} } // namespace extern "C" { @@ -477,9 +422,6 @@ void cras_iodev_set_active_node(struct cras_iodev* iodev, iodev->active_node = node; } -// From ewma_power -void ewma_power_disable(struct ewma_power* ewma) {} - size_t cras_system_get_volume() { return 0; } @@ -507,10 +449,6 @@ const char* cras_bt_device_object_path(const struct cras_bt_device* device) { return "/fake/object/path"; } -int cras_bt_device_get_stable_id(const struct cras_bt_device* device) { - return 123; -} - void cras_iodev_free_resources(struct cras_iodev* iodev) { cras_iodev_free_resources_called++; } diff --git a/cras/src/tests/hfp_info_unittest.cc b/cras/src/tests/hfp_info_unittest.cc index 24f536ae..482c3a99 100644 --- a/cras/src/tests/hfp_info_unittest.cc +++ b/cras/src/tests/hfp_info_unittest.cc @@ -3,15 +3,10 @@ * found in the LICENSE file. */ -#include <gmock/gmock.h> #include <gtest/gtest.h> #include <stdint.h> #include <time.h> -using testing::MatchesRegex; -using testing::internal::CaptureStdout; -using testing::internal::GetCapturedStdout; - extern "C" { #include "cras_hfp_info.c" #include "sbc_codec_stub.h" @@ -43,7 +38,7 @@ namespace { TEST(HfpInfo, AddRmDev) { ResetStubData(); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); dev.direction = CRAS_STREAM_OUTPUT; @@ -61,7 +56,7 @@ TEST(HfpInfo, AddRmDev) { TEST(HfpInfo, AddRmDevInvalid) { ResetStubData(); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); dev.direction = CRAS_STREAM_OUTPUT; @@ -82,10 +77,10 @@ TEST(HfpInfo, AcquirePlaybackBuffer) { ResetStubData(); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); - hfp_info_start(1, 48, HFP_CODEC_ID_CVSD, info); + hfp_info_start(1, 48, info); dev.direction = CRAS_STREAM_OUTPUT; ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format)); @@ -130,10 +125,10 @@ TEST(HfpInfo, AcquireCaptureBuffer) { ResetStubData(); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); - hfp_info_start(1, 48, HFP_CODEC_ID_CVSD, info); + hfp_info_start(1, 48, info); dev.direction = CRAS_STREAM_INPUT; ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format)); @@ -178,11 +173,11 @@ TEST(HfpInfo, HfpReadWriteFD) { ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); dev.direction = CRAS_STREAM_INPUT; - hfp_info_start(sock[1], 48, HFP_CODEC_ID_CVSD, info); + hfp_info_start(sock[1], 48, info); ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format)); /* Mock the sco fd and send some fake data */ @@ -229,10 +224,10 @@ TEST(HfpInfo, StartHfpInfo) { ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); - hfp_info_start(sock[0], 48, HFP_CODEC_ID_CVSD, info); + hfp_info_start(sock[0], 48, info); ASSERT_EQ(1, hfp_info_running(info)); ASSERT_EQ(cb_data, (void*)info); @@ -252,16 +247,16 @@ TEST(HfpInfo, StartHfpInfoAndRead) { ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); /* Start and send two chunk of fake data */ - hfp_info_start(sock[1], 48, HFP_CODEC_ID_CVSD, info); + hfp_info_start(sock[1], 48, info); send(sock[0], sample, 48, 0); send(sock[0], sample, 48, 0); /* Trigger thread callback */ - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); dev.direction = CRAS_STREAM_INPUT; ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format)); @@ -273,7 +268,7 @@ TEST(HfpInfo, StartHfpInfoAndRead) { /* Trigger thread callback after idev added. */ ts.tv_sec = 0; ts.tv_nsec = 5000000; - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); rc = hfp_buf_queued(info, dev.direction); ASSERT_EQ(48 / 2, rc); @@ -297,15 +292,15 @@ TEST(HfpInfo, StartHfpInfoAndWrite) { ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_CVSD); ASSERT_NE(info, (void*)NULL); - hfp_info_start(sock[1], 48, HFP_CODEC_ID_CVSD, info); + hfp_info_start(sock[1], 48, info); send(sock[0], sample, 48, 0); send(sock[0], sample, 48, 0); /* Trigger thread callback */ - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); /* Without odev in presence, zero packet should be sent. */ rc = recv(sock[0], sample, 48, 0); @@ -319,7 +314,7 @@ TEST(HfpInfo, StartHfpInfoAndWrite) { /* Put some fake data and trigger thread callback again */ buf_increment_write(info->playback_buf, 1008); - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); /* Assert some samples written */ rc = recv(sock[0], sample, 48, 0); @@ -331,44 +326,30 @@ TEST(HfpInfo, StartHfpInfoAndWrite) { } void send_mSBC_packet(int fd, unsigned seq, int broken_pkt) { - /* The first three bytes of hci_sco_buf are h2 header, frame count and mSBC - * sync word. The second octet of H2 header is composed by 4 bits fixed 0x8 - * and 4 bits sequence number 0000, 0011, 1100, 1111. + /* These three bytes are h2 header, frame count and mSBC sync word. + * The second octet of H2 header is composed by 4 bits fixed 0x8 and 4 bits + * sequence number 0000, 0011, 1100, 1111. */ - uint8_t headers[4] = {0x08, 0x38, 0xc8, 0xf8}; - uint8_t hci_sco_buf[] = { - 0x01, 0x00, 0xAD, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, - 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, - 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, - 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c}; - struct msghdr msg = {0}; - struct iovec iov; - struct cmsghdr* cmsg; - const unsigned int control_size = CMSG_SPACE(sizeof(int)); - char control[control_size] = {0}; - uint8_t pkt_status = 0; - - hci_sco_buf[1] = headers[seq % 4]; - - /* Assume typical 60 bytes case. */ - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - iov.iov_base = hci_sco_buf; - iov.iov_len = 60; - msg.msg_control = control; - msg.msg_controllen = control_size; - + uint8_t headers[4][3] = {{0x01, 0x08, 0xAD}, + {0x01, 0x38, 0xAD}, + {0x01, 0xc8, 0xAD}, + {0x01, 0xf8, 0xAD}}; + /* These three bytes are HCI SCO Data packet header, we only care the + * Packet_Status_Flag bits, which are the bit 4 to 5 in the second octet. + */ + uint8_t sco_header[] = {0x01, 0x01, 0x3c}; + uint8_t zero_frame[] = { + 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 0xb6, 0xdd, + 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, + 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, + 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, + 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c}; if (broken_pkt) - pkt_status = 0x11; + sco_header[1] = 0x11; - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_BLUETOOTH; - cmsg->cmsg_type = BT_SCM_PKT_STATUS; - cmsg->cmsg_len = CMSG_LEN(sizeof(pkt_status)); - memcpy(CMSG_DATA(cmsg), &pkt_status, sizeof(pkt_status)); - - sendmsg(fd, &msg, 0); + send(fd, sco_header, 3, 0); + send(fd, headers[seq % 4], 3, 0); + send(fd, zero_frame, 57, 0); } TEST(HfpInfo, StartHfpInfoAndReadMsbc) { @@ -382,19 +363,17 @@ TEST(HfpInfo, StartHfpInfoAndReadMsbc) { set_sbc_codec_decoded_out(MSBC_CODE_SIZE); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_MSBC); ASSERT_NE(info, (void*)NULL); - ASSERT_EQ(0, get_msbc_codec_create_called()); - ASSERT_EQ(0, cras_msbc_plc_create_called); - - /* Start and send an mSBC packets with all zero samples */ - hfp_info_start(sock[1], 63, HFP_CODEC_ID_MSBC, info); ASSERT_EQ(2, get_msbc_codec_create_called()); ASSERT_EQ(1, cras_msbc_plc_create_called); + + /* Start and send an mSBC packets with all zero samples */ + hfp_info_start(sock[1], 63, info); send_mSBC_packet(sock[0], pkt_count++, 0); /* Trigger thread callback */ - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); /* Expect one empty mSBC packet is send, because no odev in presence. */ rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0); @@ -409,7 +388,7 @@ TEST(HfpInfo, StartHfpInfoAndReadMsbc) { send_mSBC_packet(sock[0], pkt_count, 0); /* Trigger thread callback after idev added. */ - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0); ASSERT_EQ(MSBC_PKT_SIZE, rc); @@ -422,7 +401,7 @@ TEST(HfpInfo, StartHfpInfoAndReadMsbc) { */ pkt_count++; send_mSBC_packet(sock[0], pkt_count, 0); - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0); ASSERT_EQ(MSBC_PKT_SIZE, rc); @@ -439,7 +418,7 @@ TEST(HfpInfo, StartHfpInfoAndReadMsbc) { set_sbc_codec_decoded_fail(1); - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0); ASSERT_EQ(MSBC_PKT_SIZE, rc); @@ -455,7 +434,7 @@ TEST(HfpInfo, StartHfpInfoAndReadMsbc) { set_sbc_codec_decoded_fail(1); - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0); ASSERT_EQ(MSBC_PKT_SIZE, rc); @@ -480,14 +459,14 @@ TEST(HfpInfo, StartHfpInfoAndWriteMsbc) { set_sbc_codec_encoded_out(57); ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); - info = hfp_info_create(); + info = hfp_info_create(HFP_CODEC_ID_MSBC); ASSERT_NE(info, (void*)NULL); - hfp_info_start(sock[1], 63, HFP_CODEC_ID_MSBC, info); + hfp_info_start(sock[1], 63, info); send(sock[0], sample, 63, 0); /* Trigger thread callback */ - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); dev.direction = CRAS_STREAM_OUTPUT; ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format)); @@ -498,7 +477,7 @@ TEST(HfpInfo, StartHfpInfoAndWriteMsbc) { /* Put some fake data and trigger thread callback again */ send(sock[0], sample, 63, 0); buf_increment_write(info->playback_buf, 240); - thread_cb((struct hfp_info*)cb_data, POLLIN); + thread_cb((struct hfp_info*)cb_data); /* Assert some samples written */ rc = recv(sock[0], sample, 60, 0); @@ -509,26 +488,6 @@ TEST(HfpInfo, StartHfpInfoAndWriteMsbc) { hfp_info_destroy(info); } -TEST(HfpInfo, WBSLoggerPacketStatusDumpBinary) { - struct packet_status_logger logger; - char log_regex[64]; - int num_wraps[5] = {0, 0, 0, 1, 1}; - int wp[5] = {40, 150, 162, 100, 32}; - - /* Expect the log line wraps at correct length to avoid feedback redact. */ - snprintf(log_regex, 64, "([01D]{%d}\n)*", PACKET_STATUS_LOG_LINE_WRAP); - - packet_status_logger_init(&logger); - logger.size = PACKET_STATUS_LEN_BYTES * 8; - for (int i = 0; i < 5; i++) { - CaptureStdout(); - logger.num_wraps = num_wraps[i]; - logger.wp = wp[i]; - packet_status_logger_dump_binary(&logger); - EXPECT_THAT(GetCapturedStdout(), MatchesRegex(log_regex)); - } -} - } // namespace extern "C" { @@ -537,10 +496,7 @@ struct audio_thread* cras_iodev_list_get_audio_thread() { return NULL; } -void audio_thread_add_events_callback(int fd, - thread_callback cb, - void* data, - int events) { +void audio_thread_add_callback(int fd, thread_callback cb, void* data) { thread_cb = cb; cb_data = data; return; @@ -574,10 +530,6 @@ int cras_msbc_plc_handle_good_frames(struct cras_msbc_plc* plc, cras_msbc_plc_handle_good_frames_called++; return MSBC_CODE_SIZE; } -void packet_status_logger_init(struct packet_status_logger* logger) {} - -void packet_status_logger_update(struct packet_status_logger* logger, - bool val) {} } int main(int argc, char** argv) { diff --git a/cras/src/tests/hfp_iodev_unittest.cc b/cras/src/tests/hfp_iodev_unittest.cc index 1275ef2c..9bfb2dda 100644 --- a/cras/src/tests/hfp_iodev_unittest.cc +++ b/cras/src/tests/hfp_iodev_unittest.cc @@ -43,7 +43,7 @@ static size_t hfp_fill_output_with_zeros_called; static size_t hfp_force_output_level_called; static size_t hfp_force_output_level_target; static size_t fake_buffer_size = 500; -static cras_audio_area* mock_audio_area; +static cras_audio_area* dummy_audio_area; void ResetStubData() { cras_bt_device_append_iodev_called = 0; @@ -73,9 +73,9 @@ void ResetStubData() { fake_info = reinterpret_cast<struct hfp_info*>(0x123); - if (!mock_audio_area) { - mock_audio_area = (cras_audio_area*)calloc( - 1, sizeof(*mock_audio_area) + sizeof(cras_channel_area) * 2); + if (!dummy_audio_area) { + dummy_audio_area = (cras_audio_area*)calloc( + 1, sizeof(*dummy_audio_area) + sizeof(cras_channel_area) * 2); } } @@ -86,8 +86,8 @@ class HfpIodev : public testing::Test { virtual void SetUp() { ResetStubData(); } virtual void TearDown() { - free(mock_audio_area); - mock_audio_area = NULL; + free(dummy_audio_area); + dummy_audio_area = NULL; } }; @@ -243,9 +243,6 @@ void cras_iodev_set_active_node(struct cras_iodev* iodev, iodev->active_node = node; } -// From ewma_power -void ewma_power_disable(struct ewma_power* ewma) {} - // From system_state. size_t cras_system_get_volume() { return 0; @@ -285,10 +282,6 @@ const char* cras_bt_device_object_path(const struct cras_bt_device* device) { return "/fake/object/path"; } -int cras_bt_device_get_stable_id(const struct cras_bt_device* device) { - return 123; -} - // From cras_hfp_info int hfp_info_add_iodev(struct hfp_info* info, enum CRAS_STREAM_DIRECTION direction, @@ -313,7 +306,7 @@ int hfp_info_running(struct hfp_info* info) { return hfp_info_running_return_val; } -int hfp_info_start(int fd, unsigned int mtu, int codec, struct hfp_info* info) { +int hfp_info_start(int fd, unsigned int mtu, struct hfp_info* info) { hfp_info_start_called++; return 0; } @@ -358,7 +351,7 @@ void hfp_force_output_level(struct hfp_info* info, unsigned int level) { } void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) { - iodev->area = mock_audio_area; + iodev->area = dummy_audio_area; } void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} @@ -367,14 +360,10 @@ void cras_iodev_free_resources(struct cras_iodev* iodev) { cras_iodev_free_resources_called++; } -int cras_iodev_fill_odev_zeros(struct cras_iodev* odev, unsigned int frames) { - return 0; -} - void cras_audio_area_config_buf_pointers(struct cras_audio_area* area, const struct cras_audio_format* fmt, uint8_t* base_buffer) { - mock_audio_area->channels[0].buf = base_buffer; + dummy_audio_area->channels[0].buf = base_buffer; } int hfp_set_call_status(struct hfp_slc_handle* handle, int call) { @@ -389,18 +378,6 @@ int hfp_slc_get_selected_codec(struct hfp_slc_handle* handle) { return HFP_CODEC_ID_CVSD; } -bool hfp_slc_get_wideband_speech_supported(struct hfp_slc_handle* handle) { - return false; -} - -int hfp_slc_codec_connection_setup(struct hfp_slc_handle* handle) { - return 0; -} - -int hfp_slc_is_hsp(struct hfp_slc_handle* handle) { - return 0; -} - } // extern "C" int main(int argc, char** argv) { diff --git a/cras/src/tests/hfp_slc_unittest.cc b/cras/src/tests/hfp_slc_unittest.cc index 966278f4..f98a1f3e 100644 --- a/cras/src/tests/hfp_slc_unittest.cc +++ b/cras/src/tests/hfp_slc_unittest.cc @@ -17,7 +17,6 @@ extern "C" { static struct hfp_slc_handle* handle; static struct cras_telephony_handle fake_telephony; static int cras_bt_device_update_hardware_volume_called; -static int cras_observer_notify_bt_batter_changed_called; static int slc_initialized_cb_called; static int slc_disconnected_cb_called; static int cras_system_add_select_fd_called; @@ -36,7 +35,6 @@ void ResetStubData() { slc_initialized_cb_called = 0; cras_system_add_select_fd_called = 0; cras_bt_device_update_hardware_volume_called = 0; - cras_observer_notify_bt_batter_changed_called = 0; slc_cb = NULL; slc_cb_data = NULL; } @@ -61,8 +59,6 @@ TEST(HfpSlc, InitializeSlc) { char* chp; ResetStubData(); - btlog = cras_bt_event_log_init(); - ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device, slc_initialized_cb, slc_disconnected_cb); @@ -112,7 +108,6 @@ TEST(HfpSlc, InitializeSlc) { ASSERT_EQ(1, cras_bt_device_update_hardware_volume_called); hfp_slc_destroy(handle); - cras_bt_event_log_deinit(btlog); } TEST(HfpSlc, DisconnectSlc) { @@ -134,108 +129,6 @@ TEST(HfpSlc, DisconnectSlc) { hfp_slc_destroy(handle); } -TEST(HfpSlc, InitializeSlcSupportsHfIndicator) { - int err; - int sock[2]; - char buf[256]; - char* chp; - ResetStubData(); - - btlog = cras_bt_event_log_init(); - - ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock)); - handle = hfp_slc_create(sock[0], 0, AG_ENHANCED_CALL_STATUS, device, - slc_initialized_cb, slc_disconnected_cb); - - /* Fake that HF supports HF indicator. */ - err = write(sock[1], "AT+BRSF=256\r", 12); - ASSERT_EQ(err, 12); - slc_cb(slc_cb_data); - err = read(sock[1], buf, 256); - - err = write(sock[1], "AT+CIND=?\r", 10); - ASSERT_EQ(10, err); - slc_cb(slc_cb_data); - err = read(sock[1], buf, 256); - - /* Assert "\r\n+CIND: ... \r\n" response is received */ - chp = strstr(buf, "\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - ASSERT_EQ(0, strncmp("\r\n+CIND:", chp, 8)); - chp += 2; - chp = strstr(chp, "\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - - /* Assert "\r\nOK\r\n" response is received */ - chp += 2; - chp = strstr(chp, "\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - ASSERT_EQ(0, strncmp("\r\nOK", chp, 4)); - - err = write(sock[1], "AT+CMER=3,0,0,1\r", 16); - ASSERT_EQ(16, err); - slc_cb(slc_cb_data); - - ASSERT_NE((void*)NULL, cras_tm_timer_cb); - ASSERT_EQ(0, slc_initialized_cb_called); - - /* Assert "\r\nOK\r\n" response is received */ - err = read(sock[1], buf, 256); - - chp = strstr(buf, "\r\nOK\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - - err = write(sock[1], "AT+BIND=2\r", 10); - ASSERT_EQ(err, 10); - slc_cb(slc_cb_data); - - /* Assert "\r\nOK\r\n" response is received */ - err = read(sock[1], buf, 256); - - chp = strstr(buf, "\r\nOK\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - - err = write(sock[1], "AT+BIND=?\r", 10); - ASSERT_EQ(err, 10); - slc_cb(slc_cb_data); - - /* Assert "\r\n+BIND: (2)\r\n" response is received */ - err = read(sock[1], buf, 256); - - chp = strstr(buf, "\r\n+BIND: (1,2)\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - chp = strstr(buf, "\r\nOK\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - - err = write(sock[1], "AT+BIND?\r", 9); - ASSERT_EQ(err, 9); - slc_cb(slc_cb_data); - - /* Assert "\r\n+BIND: 2,1\r\n" response is received */ - err = read(sock[1], buf, 256); - - chp = strstr(buf, "\r\n+BIND: 2,1\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - chp = strstr(buf, "\r\nOK\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - - ASSERT_EQ(1, slc_initialized_cb_called); - - err = write(sock[1], "AT+VGS=13\r", 10); - ASSERT_EQ(err, 10); - slc_cb(slc_cb_data); - - err = read(sock[1], buf, 256); - - chp = strstr(buf, "\r\nOK\r\n"); - ASSERT_NE((void*)NULL, (void*)chp); - - ASSERT_EQ(1, cras_bt_device_update_hardware_volume_called); - - hfp_slc_destroy(handle); - cras_bt_event_log_deinit(btlog); -} - TEST(HfpSlc, CodecNegotiation) { int codec; int err; @@ -274,26 +167,37 @@ TEST(HfpSlc, CodecNegotiation) { codec = hfp_slc_get_selected_codec(handle); EXPECT_EQ(HFP_CODEC_ID_MSBC, codec); - /* Fake HF selects mSBC codec. */ - err = write(sock[1], "AT+BCS=2\r", 9); + /* Assert CRAS initiates codec selection to mSBC. */ + memset(buf, 0, 256); + err = read(sock[1], buf, 256); + pos = strstr(buf, "\r\n+BCS:2\r\n"); + ASSERT_NE((void*)NULL, pos); + + err = write(sock[1], "AT+VGS=9\r", 9); ASSERT_EQ(err, 9); + slc_cb(slc_cb_data); - err = hfp_slc_codec_connection_setup(handle); /* Assert CRAS initiates codec selection to mSBC. */ memset(buf, 0, 256); err = read(sock[1], buf, 256); pos = strstr(buf, "\r\n+BCS:2\r\n"); ASSERT_NE((void*)NULL, pos); - err = write(sock[1], "AT+VGS=9\r", 9); + /* Fake that receiving codec selection from HF. */ + err = write(sock[1], "AT+BCS=2\r", 9); ASSERT_EQ(err, 9); slc_cb(slc_cb_data); + memset(buf, 0, 256); + err = read(sock[1], buf, 256); + pos = strstr(buf, "\r\n+BCS:2\r\n"); + ASSERT_EQ((void*)NULL, pos); + hfp_slc_destroy(handle); cras_bt_event_log_deinit(btlog); } -TEST(HfpSlc, CodecNegotiationCapabilityChanged) { +TEST(HfpSlc, CodecNegotiationTimeout) { int codec; int err; int sock[2]; @@ -327,41 +231,30 @@ TEST(HfpSlc, CodecNegotiationCapabilityChanged) { ASSERT_EQ(err, 16); slc_cb(slc_cb_data); + ASSERT_NE((void*)NULL, cras_tm_timer_cb); + /* Assert that AG side prefers mSBC codec. */ codec = hfp_slc_get_selected_codec(handle); EXPECT_EQ(HFP_CODEC_ID_MSBC, codec); - /* Fake HF selects mSBC codec. */ - err = write(sock[1], "AT+BCS=2\r", 9); - ASSERT_EQ(err, 9); - - err = hfp_slc_codec_connection_setup(handle); /* Assert CRAS initiates codec selection to mSBC. */ memset(buf, 0, 256); err = read(sock[1], buf, 256); pos = strstr(buf, "\r\n+BCS:2\r\n"); ASSERT_NE((void*)NULL, pos); - /* Fake that HF changes supported codecs. */ - err = write(sock[1], "AT+BAC=1\r", 9); - ASSERT_EQ(err, 9); - slc_cb(slc_cb_data); - err = read(sock[1], buf, 256); + /* Assume codec negotiation failed. so timeout is reached. */ + cras_tm_timer_cb(NULL, cras_tm_timer_cb_data); - /* Fake HF selects CVSD codec. */ - err = write(sock[1], "AT+BCS=1\r", 9); - ASSERT_EQ(err, 9); + codec = hfp_slc_get_selected_codec(handle); + EXPECT_EQ(HFP_CODEC_ID_CVSD, codec); - err = hfp_slc_codec_connection_setup(handle); - /* Assert CRAS initiates codec selection to CVSD. */ + /* Expects CRAS fallback and selects to CVSD codec. */ memset(buf, 0, 256); err = read(sock[1], buf, 256); pos = strstr(buf, "\r\n+BCS:1\r\n"); ASSERT_NE((void*)NULL, pos); - codec = hfp_slc_get_selected_codec(handle); - EXPECT_EQ(HFP_CODEC_ID_CVSD, codec); - hfp_slc_destroy(handle); cras_bt_event_log_deinit(btlog); } @@ -393,20 +286,11 @@ int cras_system_add_select_fd(int fd, void cras_system_rm_select_fd(int fd) {} -const char* cras_bt_device_address(struct cras_bt_device* device) { - return ""; -} - void cras_bt_device_update_hardware_volume(struct cras_bt_device* device, int volume) { cras_bt_device_update_hardware_volume_called++; } -void cras_observer_notify_bt_battery_changed(const char* address, - uint32_t level) { - cras_observer_notify_bt_batter_changed_called++; -} - /* To return fake errno */ int* __errno_location() { return &fake_errno; @@ -426,13 +310,6 @@ struct cras_timer* cras_tm_create_timer(struct cras_tm* tm, return reinterpret_cast<struct cras_timer*>(0x404); } -int cras_poll(struct pollfd* fds, - nfds_t nfds, - struct timespec* timeout, - const sigset_t* sigmask) { - return 1; -} - void cras_tm_cancel_timer(struct cras_tm* tm, struct cras_timer* t) {} } diff --git a/cras/src/tests/input_data_unittest.cc b/cras/src/tests/input_data_unittest.cc index 3c6ae9f1..f1c3fd71 100644 --- a/cras/src/tests/input_data_unittest.cc +++ b/cras/src/tests/input_data_unittest.cc @@ -14,16 +14,12 @@ extern "C" { namespace { -#define FAKE_CRAS_APM_PTR reinterpret_cast<struct cras_apm*>(0x99) - #ifdef HAVE_WEBRTC_APM static struct cras_audio_area apm_area; static unsigned int cras_apm_list_process_offset_val; static unsigned int cras_apm_list_process_called; -static struct cras_apm* cras_apm_list_get_active_ret = NULL; -static bool cras_apm_list_get_use_tuned_settings_val; +static struct cras_apm* cras_apm_list_get_ret = NULL; #endif // HAVE_WEBRTC_APM -static float cras_rstream_get_volume_scaler_val; TEST(InputData, GetForInputStream) { void* dev_ptr = reinterpret_cast<void*>(0x123); @@ -59,7 +55,7 @@ TEST(InputData, GetForInputStream) { EXPECT_EQ(600, offset); #ifdef HAVE_WEBRTC_APM EXPECT_EQ(0, cras_apm_list_process_called); - cras_apm_list_get_active_ret = FAKE_CRAS_APM_PTR; + cras_apm_list_get_ret = reinterpret_cast<struct cras_apm*>(0x99); #endif // HAVE_WEBRTC_APM input_data_get_for_stream(data, &stream, offsets, &area, &offset); @@ -79,44 +75,10 @@ TEST(InputData, GetForInputStream) { buffer_share_destroy(offsets); } -TEST(InputData, GetSWCaptureGain) { - void* dev_ptr = reinterpret_cast<void*>(0x123); - struct input_data* data = NULL; - struct cras_rstream stream; - float gain; - - cras_rstream_get_volume_scaler_val = 0.8f; - stream.stream_id = 123; - -#ifdef HAVE_WEBRTC_APM - data = input_data_create(dev_ptr); - - cras_apm_list_get_active_ret = FAKE_CRAS_APM_PTR; - cras_apm_list_get_use_tuned_settings_val = 1; - gain = input_data_get_software_gain_scaler(data, 0.7f, &stream); - EXPECT_FLOAT_EQ(1.0f, gain); - - cras_apm_list_get_active_ret = NULL; - gain = input_data_get_software_gain_scaler(data, 0.7f, &stream); - EXPECT_FLOAT_EQ(0.56f, gain); - - cras_apm_list_get_active_ret = FAKE_CRAS_APM_PTR; - cras_apm_list_get_use_tuned_settings_val = 0; - gain = input_data_get_software_gain_scaler(data, 0.6f, &stream); - EXPECT_FLOAT_EQ(0.48f, gain); - input_data_destroy(&data); -#endif // HAVE_WEBRTC_APM - - data = input_data_create(dev_ptr); - gain = input_data_get_software_gain_scaler(data, 0.6f, &stream); - EXPECT_FLOAT_EQ(0.48f, gain); - input_data_destroy(&data); -} - extern "C" { #ifdef HAVE_WEBRTC_APM -struct cras_apm* cras_apm_list_get_active_apm(void* stream_ptr, void* dev_ptr) { - return cras_apm_list_get_active_ret; +struct cras_apm* cras_apm_list_get(struct cras_apm_list* list, void* dev_ptr) { + return cras_apm_list_get_ret; } int cras_apm_list_process(struct cras_apm* apm, struct float_buffer* input, @@ -129,16 +91,10 @@ int cras_apm_list_process(struct cras_apm* apm, struct cras_audio_area* cras_apm_list_get_processed(struct cras_apm* apm) { return &apm_area; } -void cras_apm_list_remove_apm(struct cras_apm_list* list, void* dev_ptr) {} +void cras_apm_list_remove(struct cras_apm_list* list, void* dev_ptr) {} void cras_apm_list_put_processed(struct cras_apm* apm, unsigned int frames) {} -bool cras_apm_list_get_use_tuned_settings(struct cras_apm* apm) { - return cras_apm_list_get_use_tuned_settings_val; -} #endif // HAVE_WEBRTC_APM -float cras_rstream_get_volume_scaler(struct cras_rstream* rstream) { - return cras_rstream_get_volume_scaler_val; -} } // extern "C" } // namespace diff --git a/cras/src/tests/iodev_list_unittest.cc b/cras/src/tests/iodev_list_unittest.cc index 8c71214a..798f2955 100644 --- a/cras/src/tests/iodev_list_unittest.cc +++ b/cras/src/tests/iodev_list_unittest.cc @@ -12,7 +12,6 @@ extern "C" { #include "audio_thread.h" #include "cras_iodev.h" #include "cras_iodev_list.h" -#include "cras_main_thread_log.h" #include "cras_observer_ops.h" #include "cras_ramp.h" #include "cras_rstream.h" @@ -44,8 +43,8 @@ static struct audio_thread thread; static struct cras_iodev loopback_input; static int cras_iodev_close_called; static struct cras_iodev* cras_iodev_close_dev; -static struct cras_iodev mock_hotword_iodev; -static struct cras_iodev mock_empty_iodev[2]; +static struct cras_iodev dummy_hotword_iodev; +static struct cras_iodev dummy_empty_iodev[2]; static stream_callback* stream_add_cb; static stream_callback* stream_rm_cb; static struct cras_rstream* stream_list_get_ret; @@ -84,7 +83,6 @@ static size_t cras_observer_notify_node_left_right_swapped_called; static size_t cras_observer_notify_input_node_gain_called; static int cras_iodev_open_called; static int cras_iodev_open_ret[8]; -static struct cras_audio_format cras_iodev_open_fmt; static int set_mute_called; static std::vector<struct cras_iodev*> set_mute_dev_vector; static std::vector<unsigned int> audio_thread_dev_start_ramp_dev_vector; @@ -95,7 +93,6 @@ static struct cras_rstream* audio_thread_disconnect_stream_stream; static int audio_thread_disconnect_stream_called; static struct cras_iodev fake_sco_in_dev, fake_sco_out_dev; static struct cras_ionode fake_sco_in_node, fake_sco_out_node; -static int server_state_hotword_pause_at_suspend; int dev_idx_in_vector(std::vector<unsigned int> v, unsigned int idx) { return std::find(v.begin(), v.end(), idx) != v.end(); @@ -132,10 +129,6 @@ class IoDevTestSuite : public testing::Test { channel_counts_[0] = 2; channel_counts_[1] = 0; - fmt_.format = SND_PCM_FORMAT_S16_LE; - fmt_.frame_rate = 48000; - fmt_.num_channels = 2; - memset(&d1_, 0, sizeof(d1_)); memset(&d2_, 0, sizeof(d2_)); memset(&d3_, 0, sizeof(d3_)); @@ -234,17 +227,14 @@ class IoDevTestSuite : public testing::Test { DL_APPEND(fake_sco_out_dev.nodes, &fake_sco_out_node); fake_sco_in_node.is_sco_pcm = 0; fake_sco_out_node.is_sco_pcm = 0; - mock_empty_iodev[0].state = CRAS_IODEV_STATE_CLOSE; - mock_empty_iodev[0].update_active_node = update_active_node; - mock_empty_iodev[1].state = CRAS_IODEV_STATE_CLOSE; - mock_empty_iodev[1].update_active_node = update_active_node; - mock_hotword_iodev.update_active_node = update_active_node; - server_state_hotword_pause_at_suspend = 0; + dummy_empty_iodev[0].state = CRAS_IODEV_STATE_CLOSE; + dummy_empty_iodev[0].update_active_node = update_active_node; + dummy_empty_iodev[1].state = CRAS_IODEV_STATE_CLOSE; + dummy_empty_iodev[1].update_active_node = update_active_node; + dummy_hotword_iodev.update_active_node = update_active_node; } - virtual void TearDown() { - cras_iodev_list_reset(); - } + virtual void TearDown() { cras_iodev_list_reset(); } static void set_volume_1(struct cras_iodev* iodev) { set_volume_1_called_++; } @@ -276,7 +266,6 @@ class IoDevTestSuite : public testing::Test { struct cras_iodev d1_; struct cras_iodev d2_; struct cras_iodev d3_; - struct cras_audio_format fmt_; size_t sample_rates_[3]; size_t channel_counts_[2]; static int set_volume_1_called_; @@ -314,8 +303,6 @@ TEST_F(IoDevTestSuite, SetSuspendResume) { rc = cras_iodev_list_add_output(&d1_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - audio_thread_add_open_dev_called = 0; cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d1_.info.idx, 1)); @@ -361,138 +348,6 @@ TEST_F(IoDevTestSuite, SetSuspendResume) { EXPECT_EQ(3, cras_observer_notify_active_node_called); } -/* Check that the suspend/resume call of active iodev will be triggered and - * fallback device will be transciently enabled while adding a new stream whose - * channel count is higher than the active iodev. */ -TEST_F(IoDevTestSuite, ReopenDevForHigherChannels) { - struct cras_rstream rstream, rstream2; - struct cras_rstream* stream_list = NULL; - int rc; - - memset(&rstream, 0, sizeof(rstream)); - memset(&rstream2, 0, sizeof(rstream2)); - rstream.format = fmt_; - rstream2.format = fmt_; - rstream2.format.num_channels = 6; - - cras_iodev_list_init(); - - d1_.direction = CRAS_STREAM_OUTPUT; - rc = cras_iodev_list_add_output(&d1_); - ASSERT_EQ(0, rc); - - d1_.format = &fmt_; - d1_.info.max_supported_channels = 2; - - audio_thread_add_open_dev_called = 0; - cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, - cras_make_node_id(d1_.info.idx, 1)); - DL_APPEND(stream_list, &rstream); - stream_list_get_ret = stream_list; - stream_add_cb(&rstream); - EXPECT_EQ(1, audio_thread_add_stream_called); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - EXPECT_EQ(1, cras_iodev_open_called); - EXPECT_EQ(2, cras_iodev_open_fmt.num_channels); - - audio_thread_add_stream_called = 0; - audio_thread_add_open_dev_called = 0; - cras_iodev_open_called = 0; - - /* stream_list should be descending ordered by channel count. */ - DL_PREPEND(stream_list, &rstream2); - stream_list_get_ret = stream_list; - stream_add_cb(&rstream2); - /* The channel count(=6) of rstream2 exceeds d1's max_supported_channels(=2), - * rstream2 will be added directly to d1, which will not be re-opened. */ - EXPECT_EQ(1, audio_thread_add_stream_called); - EXPECT_EQ(0, audio_thread_add_open_dev_called); - EXPECT_EQ(0, cras_iodev_open_called); - - d1_.info.max_supported_channels = 6; - stream_rm_cb(&rstream2); - - audio_thread_add_stream_called = 0; - audio_thread_add_open_dev_called = 0; - cras_iodev_open_called = 0; - - stream_add_cb(&rstream2); - /* Added both rstreams to fallback device, then re-opened d1. */ - EXPECT_EQ(4, audio_thread_add_stream_called); - EXPECT_EQ(2, audio_thread_add_open_dev_called); - EXPECT_EQ(2, cras_iodev_open_called); - EXPECT_EQ(6, cras_iodev_open_fmt.num_channels); - - cras_iodev_list_deinit(); -} - -/* Check that after resume, all output devices enter ramp mute state if there is - * any output stream. */ -TEST_F(IoDevTestSuite, RampMuteAfterResume) { - struct cras_rstream rstream, rstream2; - struct cras_rstream* stream_list = NULL; - int rc; - - memset(&rstream, 0, sizeof(rstream)); - - cras_iodev_list_init(); - - d1_.direction = CRAS_STREAM_OUTPUT; - d1_.initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; - rc = cras_iodev_list_add_output(&d1_); - ASSERT_EQ(0, rc); - - d2_.direction = CRAS_STREAM_INPUT; - d2_.initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; - rc = cras_iodev_list_add_input(&d2_); - ASSERT_EQ(0, rc); - - d1_.format = &fmt_; - d2_.format = &fmt_; - - audio_thread_add_open_dev_called = 0; - cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, - cras_make_node_id(d1_.info.idx, 1)); - - rstream.direction = CRAS_STREAM_OUTPUT; - DL_APPEND(stream_list, &rstream); - stream_add_cb(&rstream); - EXPECT_EQ(1, audio_thread_add_stream_called); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - - rstream2.direction = CRAS_STREAM_INPUT; - DL_APPEND(stream_list, &rstream2); - stream_add_cb(&rstream2); - - /* Suspend and resume */ - observer_ops->suspend_changed(NULL, 1); - stream_list_get_ret = stream_list; - observer_ops->suspend_changed(NULL, 0); - - /* Test only output device that has stream will be muted after resume */ - EXPECT_EQ(d1_.initial_ramp_request, CRAS_IODEV_RAMP_REQUEST_RESUME_MUTE); - EXPECT_EQ(CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK, - d2_.initial_ramp_request); - - /* Reset d1 ramp_mute and remove output stream to test again */ - d1_.initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; - DL_DELETE(stream_list, &rstream); - stream_list_get_ret = stream_list; - stream_rm_cb(&rstream); - - /* Suspend and resume */ - observer_ops->suspend_changed(NULL, 1); - stream_list_get_ret = stream_list; - observer_ops->suspend_changed(NULL, 0); - - EXPECT_EQ(CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK, - d1_.initial_ramp_request); - EXPECT_EQ(CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK, - d2_.initial_ramp_request); - - cras_iodev_list_deinit(); -} - TEST_F(IoDevTestSuite, InitDevFailShouldEnableFallback) { int rc; struct cras_rstream rstream; @@ -505,8 +360,6 @@ TEST_F(IoDevTestSuite, InitDevFailShouldEnableFallback) { rc = cras_iodev_list_add_output(&d1_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - cras_iodev_list_select_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d1_.info.idx, 0)); @@ -540,9 +393,6 @@ TEST_F(IoDevTestSuite, InitDevWithEchoRef) { rc = cras_iodev_list_add_input(&d2_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - d2_.format = &fmt_; - cras_iodev_list_select_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d1_.info.idx, 0)); /* No close call happened, because no stream exists. */ @@ -588,9 +438,6 @@ TEST_F(IoDevTestSuite, SelectNodeOpenFailShouldScheduleRetry) { rc = cras_iodev_list_add_output(&d2_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - d2_.format = &fmt_; - cras_iodev_list_select_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d1_.info.idx, 1)); DL_APPEND(stream_list, &rstream); @@ -660,15 +507,12 @@ TEST_F(IoDevTestSuite, InitDevFailShouldScheduleRetry) { struct cras_rstream* stream_list = NULL; memset(&rstream, 0, sizeof(rstream)); - rstream.format = fmt_; cras_iodev_list_init(); d1_.direction = CRAS_STREAM_OUTPUT; rc = cras_iodev_list_add_output(&d1_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - cras_iodev_list_select_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d1_.info.idx, 0)); @@ -683,7 +527,8 @@ TEST_F(IoDevTestSuite, InitDevFailShouldScheduleRetry) { EXPECT_EQ(2, cras_iodev_open_called); EXPECT_EQ(1, audio_thread_add_stream_called); EXPECT_EQ(0, update_active_node_called); - EXPECT_EQ(&mock_empty_iodev[CRAS_STREAM_OUTPUT], audio_thread_add_stream_dev); + EXPECT_EQ(&dummy_empty_iodev[CRAS_STREAM_OUTPUT], + audio_thread_add_stream_dev); EXPECT_NE((void*)NULL, cras_tm_timer_cb); EXPECT_EQ(1, cras_tm_create_timer_called); @@ -694,7 +539,6 @@ TEST_F(IoDevTestSuite, InitDevFailShouldScheduleRetry) { EXPECT_EQ(1, cras_tm_create_timer_called); EXPECT_EQ(1, audio_thread_add_stream_called); - mock_empty_iodev[CRAS_STREAM_OUTPUT].format = &fmt_; cras_tm_timer_cb = NULL; cras_iodev_open_ret[3] = -5; stream_add_cb(&rstream); @@ -718,8 +562,6 @@ TEST_F(IoDevTestSuite, PinnedStreamInitFailShouldScheduleRetry) { rc = cras_iodev_list_add_output(&d1_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - rstream.is_pinned = 1; rstream.pinned_dev_idx = d1_.info.idx; @@ -775,9 +617,6 @@ TEST_F(IoDevTestSuite, SelectNode) { rc = cras_iodev_list_add_output(&d2_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - d2_.format = &fmt_; - audio_thread_add_open_dev_called = 0; audio_thread_rm_open_dev_called = 0; @@ -848,9 +687,6 @@ TEST_F(IoDevTestSuite, SelectPreviouslyEnabledNode) { rc = cras_iodev_list_add_output(&d2_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - d2_.format = &fmt_; - audio_thread_add_open_dev_called = 0; audio_thread_rm_open_dev_called = 0; device_enabled_count = 0; @@ -983,7 +819,6 @@ TEST_F(IoDevTestSuite, AddWrongDirection) { TEST_F(IoDevTestSuite, AddRemoveOutput) { struct cras_iodev_info* dev_info; int rc; - cras_iodev_list_init(); rc = cras_iodev_list_add_output(&d1_); EXPECT_EQ(0, rc); @@ -1015,7 +850,6 @@ TEST_F(IoDevTestSuite, AddRemoveOutput) { EXPECT_EQ(0, rc); free(dev_info); EXPECT_EQ(0, cras_observer_notify_active_node_called); - cras_iodev_list_deinit(); } // Test output_mute_changed callback. @@ -1094,56 +928,39 @@ TEST_F(IoDevTestSuite, OutputMuteChangedToUnmute) { // Test enable/disable an iodev. TEST_F(IoDevTestSuite, EnableDisableDevice) { - struct cras_rstream rstream; - cras_iodev_list_init(); device_enabled_count = 0; device_disabled_count = 0; - memset(&rstream, 0, sizeof(rstream)); EXPECT_EQ(0, cras_iodev_list_add_output(&d1_)); EXPECT_EQ(0, cras_iodev_list_set_device_enabled_callback( device_enabled_cb, device_disabled_cb, (void*)0xABCD)); - // Enable a device, fallback should be diabled accordingly. + // Enable a device. cras_iodev_list_enable_dev(&d1_); EXPECT_EQ(&d1_, device_enabled_dev); EXPECT_EQ((void*)0xABCD, device_enabled_cb_data); EXPECT_EQ(1, device_enabled_count); - EXPECT_EQ(1, device_disabled_count); EXPECT_EQ(&d1_, cras_iodev_list_get_first_enabled_iodev(CRAS_STREAM_OUTPUT)); - // Connect a normal stream. - cras_iodev_open_called = 0; - stream_add_cb(&rstream); - EXPECT_EQ(1, cras_iodev_open_called); - - stream_list_has_pinned_stream_ret[d1_.info.idx] = 0; - // Disable a device. Expect dev is closed because there's no pinned stream. - update_active_node_called = 0; + // Disable a device. cras_iodev_list_disable_dev(&d1_, false); EXPECT_EQ(&d1_, device_disabled_dev); - EXPECT_EQ(2, device_disabled_count); + EXPECT_EQ(1, device_disabled_count); EXPECT_EQ((void*)0xABCD, device_disabled_cb_data); - EXPECT_EQ(1, audio_thread_rm_open_dev_called); - EXPECT_EQ(1, cras_iodev_close_called); - EXPECT_EQ(&d1_, cras_iodev_close_dev); - EXPECT_EQ(1, update_active_node_called); - EXPECT_EQ(0, cras_iodev_list_set_device_enabled_callback( device_enabled_cb, device_disabled_cb, (void*)0xCDEF)); EXPECT_EQ(2, cras_observer_notify_active_node_called); EXPECT_EQ(0, cras_iodev_list_set_device_enabled_callback(NULL, NULL, NULL)); - cras_iodev_list_deinit(); } // Test adding/removing an input dev to the list. TEST_F(IoDevTestSuite, AddRemoveInput) { struct cras_iodev_info* dev_info; int rc, i; - uint64_t found_mask; + uint32_t found_mask; d1_.direction = CRAS_STREAM_INPUT; d2_.direction = CRAS_STREAM_INPUT; @@ -1176,8 +993,8 @@ TEST_F(IoDevTestSuite, AddRemoveInput) { found_mask = 0; for (i = 0; i < rc; i++) { uint32_t idx = dev_info[i].idx; - EXPECT_EQ(0, (found_mask & (static_cast<uint64_t>(1) << idx))); - found_mask |= (static_cast<uint64_t>(1) << idx); + EXPECT_EQ(0, (found_mask & (1 << idx))); + found_mask |= (1 << idx); } } if (rc > 0) @@ -1213,7 +1030,6 @@ TEST_F(IoDevTestSuite, AddRemoveInputNoSem) { d2_.direction = CRAS_STREAM_INPUT; server_state_update_begin_return = NULL; - cras_iodev_list_init(); rc = cras_iodev_list_add_input(&d1_); EXPECT_EQ(0, rc); @@ -1224,7 +1040,6 @@ TEST_F(IoDevTestSuite, AddRemoveInputNoSem) { EXPECT_EQ(0, cras_iodev_list_rm_input(&d1_)); EXPECT_EQ(0, cras_iodev_list_rm_input(&d2_)); - cras_iodev_list_deinit(); } // Test removing the last input. @@ -1438,10 +1253,6 @@ TEST_F(IoDevTestSuite, AddActiveNode) { rc = cras_iodev_list_add_output(&d3_); ASSERT_EQ(0, rc); - d1_.format = &fmt_; - d2_.format = &fmt_; - d3_.format = &fmt_; - audio_thread_add_open_dev_called = 0; cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d3_.info.idx, 1)); @@ -1478,57 +1289,6 @@ TEST_F(IoDevTestSuite, AddActiveNode) { cras_iodev_list_deinit(); } -TEST_F(IoDevTestSuite, OutputDevIdleClose) { - int rc; - struct cras_rstream rstream; - - memset(&rstream, 0, sizeof(rstream)); - cras_iodev_list_init(); - - d1_.direction = CRAS_STREAM_OUTPUT; - rc = cras_iodev_list_add_output(&d1_); - EXPECT_EQ(0, rc); - - d1_.format = &fmt_; - - audio_thread_add_open_dev_called = 0; - cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, - cras_make_node_id(d1_.info.idx, 1)); - EXPECT_EQ(0, audio_thread_add_open_dev_called); - EXPECT_EQ(0, audio_thread_rm_open_dev_called); - - // If a stream is added, the device should be opened. - stream_add_cb(&rstream); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - - audio_thread_rm_open_dev_called = 0; - audio_thread_drain_stream_return = 0; - clock_gettime_retspec.tv_sec = 15; - stream_rm_cb(&rstream); - EXPECT_EQ(1, audio_thread_drain_stream_called); - EXPECT_EQ(0, audio_thread_rm_open_dev_called); - EXPECT_EQ(1, cras_tm_create_timer_called); - - // Expect no rm dev happen because idle time not yet expire, and - // new timer should be scheduled for the rest of the idle time. - clock_gettime_retspec.tv_sec += 7; - cras_tm_timer_cb(NULL, NULL); - EXPECT_EQ(0, audio_thread_rm_open_dev_called); - EXPECT_EQ(2, cras_tm_create_timer_called); - - // Expect d1_ be closed upon unplug, and the timer stay armed. - cras_iodev_list_rm_output(&d1_); - EXPECT_EQ(1, audio_thread_rm_open_dev_called); - EXPECT_EQ(0, cras_tm_cancel_timer_called); - - // When timer eventually fired expect there's no more new - // timer scheduled because d1_ has closed already. - clock_gettime_retspec.tv_sec += 4; - cras_tm_timer_cb(NULL, NULL); - EXPECT_EQ(2, cras_tm_create_timer_called); - cras_iodev_list_deinit(); -} - TEST_F(IoDevTestSuite, DrainTimerCancel) { int rc; struct cras_rstream rstream; @@ -1541,8 +1301,6 @@ TEST_F(IoDevTestSuite, DrainTimerCancel) { rc = cras_iodev_list_add_output(&d1_); EXPECT_EQ(0, rc); - d1_.format = &fmt_; - audio_thread_add_open_dev_called = 0; cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, cras_make_node_id(d1_.info.idx, 1)); @@ -1607,107 +1365,6 @@ TEST_F(IoDevTestSuite, RemoveThenSelectActiveNode) { cras_iodev_list_deinit(); } -TEST_F(IoDevTestSuite, CloseDevWithPinnedStream) { - int rc; - struct cras_rstream rstream1, rstream2; - cras_iodev_list_init(); - - d1_.direction = CRAS_STREAM_OUTPUT; - d1_.info.idx = 1; - rc = cras_iodev_list_add_output(&d1_); - EXPECT_EQ(0, rc); - - memset(&rstream1, 0, sizeof(rstream1)); - memset(&rstream2, 0, sizeof(rstream2)); - rstream2.is_pinned = 1; - rstream2.pinned_dev_idx = d1_.info.idx; - - d1_.format = &fmt_; - audio_thread_add_open_dev_called = 0; - EXPECT_EQ(0, audio_thread_add_open_dev_called); - EXPECT_EQ(0, audio_thread_rm_open_dev_called); - - // Add a normal stream - stream_add_cb(&rstream1); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - - // Add a pinned stream, expect another dev open call triggered. - cras_iodev_open_called = 0; - stream_add_cb(&rstream2); - EXPECT_EQ(1, cras_iodev_open_called); - - // Force disable d1_ and make sure d1_ gets closed. - audio_thread_rm_open_dev_called = 0; - update_active_node_called = 0; - cras_iodev_close_called = 0; - cras_iodev_list_disable_dev(&d1_, 1); - EXPECT_EQ(1, audio_thread_rm_open_dev_called); - EXPECT_EQ(1, cras_iodev_close_called); - EXPECT_EQ(&d1_, cras_iodev_close_dev); - EXPECT_EQ(1, update_active_node_called); - - // Add back the two streams, one normal one pinned. - audio_thread_add_open_dev_called = 0; - audio_thread_rm_open_dev_called = 0; - cras_iodev_open_called = 0; - stream_add_cb(&rstream2); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - EXPECT_EQ(1, cras_iodev_open_called); - stream_add_cb(&rstream1); - - // Suspend d1_ and make sure d1_ gets closed. - update_active_node_called = 0; - cras_iodev_close_called = 0; - cras_iodev_list_suspend_dev(d1_.info.idx); - EXPECT_EQ(1, audio_thread_rm_open_dev_called); - EXPECT_EQ(1, cras_iodev_close_called); - EXPECT_EQ(&d1_, cras_iodev_close_dev); - EXPECT_EQ(1, update_active_node_called); - - cras_iodev_list_resume_dev(d1_.info.idx); - - cras_iodev_list_deinit(); -} - -TEST_F(IoDevTestSuite, DisableDevWithPinnedStream) { - int rc; - struct cras_rstream rstream1; - cras_iodev_list_init(); - - d1_.direction = CRAS_STREAM_OUTPUT; - rc = cras_iodev_list_add_output(&d1_); - EXPECT_EQ(0, rc); - - memset(&rstream1, 0, sizeof(rstream1)); - rstream1.is_pinned = 1; - rstream1.pinned_dev_idx = d1_.info.idx; - - d1_.format = &fmt_; - audio_thread_add_open_dev_called = 0; - cras_iodev_list_add_active_node(CRAS_STREAM_OUTPUT, - cras_make_node_id(d1_.info.idx, 1)); - EXPECT_EQ(0, audio_thread_add_open_dev_called); - EXPECT_EQ(0, audio_thread_rm_open_dev_called); - - // Add a pinned stream. - cras_iodev_open_called = 0; - stream_add_cb(&rstream1); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - EXPECT_EQ(1, cras_iodev_open_called); - - // Disable d1_ expect no close dev triggered because pinned stream. - stream_list_has_pinned_stream_ret[d1_.info.idx] = 1; - audio_thread_rm_open_dev_called = 0; - update_active_node_called = 0; - cras_iodev_close_called = 0; - cras_iodev_list_disable_dev(&d1_, 0); - EXPECT_EQ(0, audio_thread_rm_open_dev_called); - EXPECT_EQ(0, cras_iodev_close_called); - EXPECT_EQ(0, update_active_node_called); - - cras_iodev_list_deinit(); -} - TEST_F(IoDevTestSuite, AddRemovePinnedStream) { struct cras_rstream rstream; @@ -1726,9 +1383,6 @@ TEST_F(IoDevTestSuite, AddRemovePinnedStream) { d2_.info.idx = 2; EXPECT_EQ(0, cras_iodev_list_add_output(&d2_)); - d1_.format = &fmt_; - d2_.format = &fmt_; - // Setup pinned stream. memset(&rstream, 0, sizeof(rstream)); rstream.is_pinned = 1; @@ -1753,7 +1407,7 @@ TEST_F(IoDevTestSuite, AddRemovePinnedStream) { EXPECT_EQ(2, update_active_node_called); // Unselect d1_ and select to d2_ EXPECT_EQ(&d2_, update_active_node_iodev_val[0]); - EXPECT_EQ(&mock_empty_iodev[CRAS_STREAM_OUTPUT], + EXPECT_EQ(&dummy_empty_iodev[CRAS_STREAM_OUTPUT], update_active_node_iodev_val[1]); // Remove pinned stream from d1, check d1 is closed after stream removed. @@ -1788,9 +1442,6 @@ TEST_F(IoDevTestSuite, SuspendResumePinnedStream) { d2_.direction = CRAS_STREAM_OUTPUT; EXPECT_EQ(0, cras_iodev_list_add_output(&d2_)); - d1_.format = &fmt_; - d2_.format = &fmt_; - // Setup pinned stream. memset(&rstream, 0, sizeof(rstream)); rstream.is_pinned = 1; @@ -1846,8 +1497,6 @@ TEST_F(IoDevTestSuite, HotwordStreamsAddedThenSuspendResume) { d1_.direction = CRAS_STREAM_INPUT; EXPECT_EQ(0, cras_iodev_list_add_input(&d1_)); - d1_.format = &fmt_; - memset(&rstream, 0, sizeof(rstream)); rstream.is_pinned = 1; rstream.pinned_dev_idx = d1_.info.idx; @@ -1870,14 +1519,14 @@ TEST_F(IoDevTestSuite, HotwordStreamsAddedThenSuspendResume) { EXPECT_EQ(&d1_, audio_thread_disconnect_stream_dev); EXPECT_EQ(2, audio_thread_add_stream_called); EXPECT_EQ(&rstream, audio_thread_add_stream_stream); - EXPECT_EQ(&mock_hotword_iodev, audio_thread_add_stream_dev); + EXPECT_EQ(&dummy_hotword_iodev, audio_thread_add_stream_dev); /* Resume hotword streams, verify the stream disconnects from * the empty iodev and connects back to the real hotword iodev. */ EXPECT_EQ(0, cras_iodev_list_resume_hotword_stream()); EXPECT_EQ(2, audio_thread_disconnect_stream_called); EXPECT_EQ(&rstream, audio_thread_disconnect_stream_stream); - EXPECT_EQ(&mock_hotword_iodev, audio_thread_disconnect_stream_dev); + EXPECT_EQ(&dummy_hotword_iodev, audio_thread_disconnect_stream_dev); EXPECT_EQ(3, audio_thread_add_stream_called); EXPECT_EQ(&rstream, audio_thread_add_stream_stream); EXPECT_EQ(&d1_, audio_thread_add_stream_dev); @@ -1893,8 +1542,6 @@ TEST_F(IoDevTestSuite, HotwordStreamsAddedAfterSuspend) { d1_.direction = CRAS_STREAM_INPUT; EXPECT_EQ(0, cras_iodev_list_add_input(&d1_)); - d1_.format = &fmt_; - memset(&rstream, 0, sizeof(rstream)); rstream.is_pinned = 1; rstream.pinned_dev_idx = d1_.info.idx; @@ -1911,7 +1558,7 @@ TEST_F(IoDevTestSuite, HotwordStreamsAddedAfterSuspend) { /* Hotword stream connected, verify it is added to the empty iodev. */ EXPECT_EQ(0, stream_add_cb(&rstream)); EXPECT_EQ(1, audio_thread_add_stream_called); - EXPECT_EQ(&mock_hotword_iodev, audio_thread_add_stream_dev); + EXPECT_EQ(&dummy_hotword_iodev, audio_thread_add_stream_dev); EXPECT_EQ(&rstream, audio_thread_add_stream_stream); /* Resume hotword streams, now the existing hotword stream should disconnect @@ -1919,7 +1566,7 @@ TEST_F(IoDevTestSuite, HotwordStreamsAddedAfterSuspend) { EXPECT_EQ(0, cras_iodev_list_resume_hotword_stream()); EXPECT_EQ(1, audio_thread_disconnect_stream_called); EXPECT_EQ(&rstream, audio_thread_disconnect_stream_stream); - EXPECT_EQ(&mock_hotword_iodev, audio_thread_disconnect_stream_dev); + EXPECT_EQ(&dummy_hotword_iodev, audio_thread_disconnect_stream_dev); EXPECT_EQ(2, audio_thread_add_stream_called); EXPECT_EQ(&rstream, audio_thread_add_stream_stream); EXPECT_EQ(&d1_, audio_thread_add_stream_dev); @@ -1944,105 +1591,6 @@ TEST_F(IoDevTestSuite, GetSCOPCMIodevs) { cras_iodev_list_deinit(); } -TEST_F(IoDevTestSuite, HotwordStreamsPausedAtSystemSuspend) { - struct cras_rstream rstream; - struct cras_rstream* stream_list = NULL; - cras_iodev_list_init(); - - node1.type = CRAS_NODE_TYPE_HOTWORD; - d1_.direction = CRAS_STREAM_INPUT; - EXPECT_EQ(0, cras_iodev_list_add_input(&d1_)); - - d1_.format = &fmt_; - - memset(&rstream, 0, sizeof(rstream)); - rstream.is_pinned = 1; - rstream.pinned_dev_idx = d1_.info.idx; - rstream.flags = HOTWORD_STREAM; - - /* Add a hotword stream. */ - EXPECT_EQ(0, stream_add_cb(&rstream)); - EXPECT_EQ(1, audio_thread_add_stream_called); - EXPECT_EQ(&d1_, audio_thread_add_stream_dev); - EXPECT_EQ(&rstream, audio_thread_add_stream_stream); - - DL_APPEND(stream_list, &rstream); - stream_list_get_ret = stream_list; - - server_state_hotword_pause_at_suspend = 1; - - /* Trigger system suspend. Verify hotword stream is moved to empty dev. */ - observer_ops->suspend_changed(NULL, 1); - EXPECT_EQ(1, audio_thread_disconnect_stream_called); - EXPECT_EQ(&rstream, audio_thread_disconnect_stream_stream); - EXPECT_EQ(&d1_, audio_thread_disconnect_stream_dev); - EXPECT_EQ(2, audio_thread_add_stream_called); - EXPECT_EQ(&rstream, audio_thread_add_stream_stream); - EXPECT_EQ(&mock_hotword_iodev, audio_thread_add_stream_dev); - - /* Trigger system resume. Verify hotword stream is moved to real dev.*/ - observer_ops->suspend_changed(NULL, 0); - EXPECT_EQ(2, audio_thread_disconnect_stream_called); - EXPECT_EQ(&rstream, audio_thread_disconnect_stream_stream); - EXPECT_EQ(&mock_hotword_iodev, audio_thread_disconnect_stream_dev); - EXPECT_EQ(3, audio_thread_add_stream_called); - EXPECT_EQ(&rstream, audio_thread_add_stream_stream); - EXPECT_EQ(&d1_, audio_thread_add_stream_dev); - - server_state_hotword_pause_at_suspend = 0; - audio_thread_disconnect_stream_called = 0; - audio_thread_add_stream_called = 0; - - /* Trigger system suspend. Verify hotword stream is not touched. */ - observer_ops->suspend_changed(NULL, 1); - EXPECT_EQ(0, audio_thread_disconnect_stream_called); - EXPECT_EQ(0, audio_thread_add_stream_called); - - /* Trigger system resume. Verify hotword stream is not touched.*/ - observer_ops->suspend_changed(NULL, 0); - EXPECT_EQ(0, audio_thread_disconnect_stream_called); - EXPECT_EQ(0, audio_thread_add_stream_called); - - cras_iodev_list_deinit(); -} - -TEST_F(IoDevTestSuite, SetNoiseCancellation) { - struct cras_rstream rstream; - struct cras_rstream* stream_list = NULL; - int rc; - - memset(&rstream, 0, sizeof(rstream)); - - cras_iodev_list_init(); - - d1_.direction = CRAS_STREAM_INPUT; - rc = cras_iodev_list_add_input(&d1_); - ASSERT_EQ(0, rc); - - d1_.format = &fmt_; - - rstream.direction = CRAS_STREAM_INPUT; - - audio_thread_add_open_dev_called = 0; - audio_thread_rm_open_dev_called = 0; - cras_iodev_list_add_active_node(CRAS_STREAM_INPUT, - cras_make_node_id(d1_.info.idx, 1)); - DL_APPEND(stream_list, &rstream); - stream_add_cb(&rstream); - stream_list_get_ret = stream_list; - EXPECT_EQ(1, audio_thread_add_stream_called); - EXPECT_EQ(1, audio_thread_add_open_dev_called); - - // reset_for_noise_cancellation causes device suspend & resume - // While suspending d1_: rm d1_, open fallback - // While resuming d1_: rm fallback, open d1_ - cras_iodev_list_reset_for_noise_cancellation(); - EXPECT_EQ(3, audio_thread_add_open_dev_called); - EXPECT_EQ(2, audio_thread_rm_open_dev_called); - - cras_iodev_list_deinit(); -} - } // namespace int main(int argc, char** argv) { @@ -2053,7 +1601,6 @@ int main(int argc, char** argv) { extern "C" { // Stubs -struct main_thread_event_log* main_log; struct cras_server_state* cras_system_state_update_begin() { return server_state_update_begin_return; @@ -2065,10 +1612,6 @@ int cras_system_get_mute() { return system_get_mute_return; } -bool cras_system_get_noise_cancellation_enabled() { - return false; -} - struct audio_thread* audio_thread_create() { return &thread; } @@ -2139,9 +1682,9 @@ struct cras_iodev* empty_iodev_create(enum CRAS_STREAM_DIRECTION direction, enum CRAS_NODE_TYPE node_type) { struct cras_iodev* dev; if (node_type == CRAS_NODE_TYPE_HOTWORD) { - dev = &mock_hotword_iodev; + dev = &dummy_hotword_iodev; } else { - dev = &mock_empty_iodev[direction]; + dev = &dummy_empty_iodev[direction]; } dev->direction = direction; if (dev->active_node == NULL) { @@ -2180,8 +1723,6 @@ int cras_iodev_open(struct cras_iodev* iodev, const struct cras_audio_format* fmt) { if (cras_iodev_open_ret[cras_iodev_open_called] == 0) iodev->state = CRAS_IODEV_STATE_OPEN; - cras_iodev_open_fmt = *fmt; - iodev->format = &cras_iodev_open_fmt; return cras_iodev_open_ret[cras_iodev_open_called++]; } @@ -2189,7 +1730,6 @@ int cras_iodev_close(struct cras_iodev* iodev) { iodev->state = CRAS_IODEV_STATE_CLOSE; cras_iodev_close_called++; cras_iodev_close_dev = iodev; - iodev->format = NULL; return 0; } @@ -2208,19 +1748,13 @@ void cras_iodev_set_node_plugged(struct cras_ionode* node, int plugged) { set_node_plugged_called++; } -bool cras_iodev_support_noise_cancellation(const struct cras_iodev* iodev) { - return true; -} - int cras_iodev_start_volume_ramp(struct cras_iodev* odev, unsigned int old_volume, unsigned int new_volume) { cras_iodev_start_volume_ramp_called++; return 0; } -bool cras_iodev_is_aec_use_case(const struct cras_ionode* node) { - return 1; -} + bool stream_list_has_pinned_stream(struct stream_list* list, unsigned int dev_idx) { return stream_list_has_pinned_stream_ret[dev_idx]; @@ -2336,13 +1870,12 @@ int audio_thread_dev_start_ramp(struct audio_thread* thread, } #ifdef HAVE_WEBRTC_APM -struct cras_apm* cras_apm_list_add_apm(struct cras_apm_list* list, - void* dev_ptr, - const struct cras_audio_format* fmt, - bool is_internal_dev) { +struct cras_apm* cras_apm_list_add(struct cras_apm_list* list, + void* dev_ptr, + const struct cras_audio_format* fmt) { return NULL; } -void cras_apm_list_remove_apm(struct cras_apm_list* list, void* dev_ptr) {} +void cras_apm_list_remove(struct cras_apm_list* list, void* dev_ptr) {} int cras_apm_list_init(const char* device_config_dir) { return 0; } @@ -2355,8 +1888,4 @@ int clock_gettime(clockid_t clk_id, struct timespec* tp) { return 0; } -bool cras_system_get_hotword_pause_at_suspend() { - return !!server_state_hotword_pause_at_suspend; -} - } // extern "C" diff --git a/cras/src/tests/iodev_stub.cc b/cras/src/tests/iodev_stub.cc index 2e84faac..25d59da0 100644 --- a/cras/src/tests/iodev_stub.cc +++ b/cras/src/tests/iodev_stub.cc @@ -21,30 +21,12 @@ struct cb_data { std::unordered_map<cras_iodev*, cb_data> frames_queued_map; std::unordered_map<cras_iodev*, cb_data> valid_frames_map; std::unordered_map<cras_iodev*, timespec> drop_time_map; -std::unordered_map<const cras_iodev*, double> est_rate_ratio_map; -std::unordered_map<const cras_iodev*, int> update_rate_map; -std::unordered_map<const cras_ionode*, int> on_internal_card_map; } // namespace void iodev_stub_reset() { frames_queued_map.clear(); valid_frames_map.clear(); drop_time_map.clear(); - est_rate_ratio_map.clear(); - update_rate_map.clear(); - on_internal_card_map.clear(); -} - -void iodev_stub_est_rate_ratio(cras_iodev* iodev, double ratio) { - est_rate_ratio_map.insert({iodev, ratio}); -} - -void iodev_stub_update_rate(cras_iodev* iodev, int data) { - update_rate_map.insert({iodev, data}); -} - -void iodev_stub_on_internal_card(cras_ionode* node, int data) { - on_internal_card_map.insert({node, data}); } void iodev_stub_frames_queued(cras_iodev* iodev, int ret, timespec ts) { @@ -85,11 +67,7 @@ int cras_iodev_get_valid_frames(struct cras_iodev* iodev, } double cras_iodev_get_est_rate_ratio(const struct cras_iodev* iodev) { - auto elem = est_rate_ratio_map.find(iodev); - if (elem != est_rate_ratio_map.end()) { - return elem->second; - } - return 1.0f; + return 1.0; } int cras_iodev_get_dsp_delay(const struct cras_iodev* iodev) { @@ -115,10 +93,6 @@ struct dev_stream* cras_iodev_rm_stream(struct cras_iodev* iodev, int cras_iodev_update_rate(struct cras_iodev* iodev, unsigned int level, struct timespec* level_tstamp) { - auto elem = update_rate_map.find(iodev); - if (elem != update_rate_map.end()) { - return elem->second; - } return 0; } @@ -176,9 +150,7 @@ int cras_iodev_odev_should_wake(const struct cras_iodev* odev) { return 1; } -int cras_iodev_output_underrun(struct cras_iodev* odev, - unsigned int hw_level, - unsigned int frames_written) { +int cras_iodev_output_underrun(struct cras_iodev* odev) { return 0; } @@ -214,12 +186,4 @@ int cras_iodev_drop_frames_by_time(struct cras_iodev* iodev, drop_time_map.insert({iodev, ts}); return 0; } - -bool cras_iodev_is_on_internal_card(const struct cras_ionode* node) { - auto elem = on_internal_card_map.find(node); - if (elem != on_internal_card_map.end()) { - return elem->second; - } - return 1; -} } // extern "C" diff --git a/cras/src/tests/iodev_stub.h b/cras/src/tests/iodev_stub.h index e8016dd3..dde1b9f4 100644 --- a/cras/src/tests/iodev_stub.h +++ b/cras/src/tests/iodev_stub.h @@ -10,12 +10,6 @@ void iodev_stub_reset(); -void iodev_stub_est_rate_ratio(cras_iodev* iodev, double ratio); - -void iodev_stub_update_rate(cras_iodev* iodev, int data); - -void iodev_stub_on_internal_card(cras_ionode* node, int data); - void iodev_stub_frames_queued(cras_iodev* iodev, int ret, timespec ts); void iodev_stub_valid_frames(cras_iodev* iodev, int ret, timespec ts); diff --git a/cras/src/tests/iodev_unittest.cc b/cras/src/tests/iodev_unittest.cc index 24b2b38d..61f8f694 100644 --- a/cras/src/tests/iodev_unittest.cc +++ b/cras/src/tests/iodev_unittest.cc @@ -9,7 +9,6 @@ extern "C" { #include "audio_thread_log.h" #include "cras_audio_area.h" #include "cras_iodev.h" -#include "cras_main_thread_log.h" #include "cras_ramp.h" #include "cras_rstream.h" #include "dev_stream.h" @@ -60,7 +59,7 @@ static unsigned int cras_mix_mute_count; static unsigned int cras_dsp_num_input_channels_return; static unsigned int cras_dsp_num_output_channels_return; struct cras_dsp_context* cras_dsp_context_new_return; -static unsigned int cras_dsp_load_mock_pipeline_called; +static unsigned int cras_dsp_load_dummy_pipeline_called; static unsigned int rate_estimator_add_frames_num_frames; static unsigned int rate_estimator_add_frames_called; static int cras_system_get_mute_return; @@ -74,6 +73,7 @@ static unsigned int post_dsp_hook_called; static const uint8_t* post_dsp_hook_frames; static void* post_dsp_hook_cb_data; static int iodev_buffer_size; +static long cras_system_get_capture_gain_ret_value; static uint8_t audio_buffer[BUFFER_SIZE]; static struct cras_audio_area* audio_area; static unsigned int put_buffer_nframes; @@ -85,6 +85,7 @@ struct audio_thread_event_log* atlog; static unsigned int simple_no_stream_called; static int simple_no_stream_enable; static int dev_stream_playback_frames_ret; +static int get_num_underruns_ret; static int device_monitor_reset_device_called; static int output_underrun_called; static int set_mute_called; @@ -113,7 +114,6 @@ static int buffer_share_get_new_write_point_ret; static int ext_mod_configure_called; static struct input_data* input_data_create_ret; static double rate_estimator_get_rate_ret; -static int cras_audio_thread_event_dev_overrun_called; static char* atlog_name; @@ -148,7 +148,7 @@ void ResetStubData() { cras_dsp_num_input_channels_return = 2; cras_dsp_num_output_channels_return = 2; cras_dsp_context_new_return = NULL; - cras_dsp_load_mock_pipeline_called = 0; + cras_dsp_load_dummy_pipeline_called = 0; rate_estimator_add_frames_num_frames = 0; rate_estimator_add_frames_called = 0; cras_system_get_mute_return = 0; @@ -159,6 +159,7 @@ void ResetStubData() { post_dsp_hook_called = 0; post_dsp_hook_frames = NULL; iodev_buffer_size = 0; + cras_system_get_capture_gain_ret_value = 0; // Assume there is some data in audio buffer. memset(audio_buffer, 0xff, sizeof(audio_buffer)); if (audio_area) { @@ -180,6 +181,7 @@ void ResetStubData() { atlog_rw_shm_fd = atlog_ro_shm_fd = -1; atlog = audio_thread_event_log_init(atlog_name); } + get_num_underruns_ret = 0; device_monitor_reset_device_called = 0; output_underrun_called = 0; set_mute_called = 0; @@ -209,7 +211,6 @@ void ResetStubData() { buffer_share_add_id_called = 0; ext_mod_configure_called = 0; rate_estimator_get_rate_ret = 0; - cras_audio_thread_event_dev_overrun_called = 0; } namespace { @@ -268,14 +269,9 @@ class IoDevSetFormatTestSuite : public testing::Test { iodev_.dsp_context = NULL; cras_audio_format_set_channel_layout_called = 0; - - main_log = main_thread_event_log_init(); } - virtual void TearDown() { - cras_iodev_free_format(&iodev_); - main_thread_event_log_deinit(main_log); - } + virtual void TearDown() { cras_iodev_free_format(&iodev_); } struct cras_iodev iodev_; size_t sample_rates_[3]; @@ -1062,8 +1058,6 @@ TEST(IoNodePlug, PlugUnplugNode) { struct cras_iodev iodev; struct cras_ionode ionode, ionode2; - main_log = main_thread_event_log_init(); - memset(&iodev, 0, sizeof(iodev)); memset(&ionode, 0, sizeof(ionode)); memset(&ionode2, 0, sizeof(ionode2)); @@ -1085,7 +1079,6 @@ TEST(IoNodePlug, PlugUnplugNode) { EXPECT_EQ(1, cras_iodev_list_disable_dev_called); cras_iodev_set_node_plugged(&ionode2, 0); EXPECT_EQ(1, cras_iodev_list_disable_dev_called); - main_thread_event_log_deinit(main_log); } TEST(IoDev, AddRemoveNode) { @@ -1176,15 +1169,21 @@ TEST(IoDev, SoftwareGain) { iodev.active_node = &ionode; iodev.active_node->dev = &iodev; - ionode.capture_gain = 2400; + ionode.capture_gain = 400; ionode.software_volume_needed = 1; + ionode.max_software_gain = 3000; + // Check that system volume changes software volume if needed. + cras_system_get_capture_gain_ret_value = 2000; + // system_gain + node_gain = 2000 + 400 = 2400 // 2400 * 0.01 dB is 15.848931 EXPECT_FLOAT_EQ(15.848931, cras_iodev_get_software_gain_scaler(&iodev)); + EXPECT_FLOAT_EQ(3000, cras_iodev_maximum_software_gain(&iodev)); // Software gain scaler should be 1.0 if software gain is not needed. ionode.software_volume_needed = 0; EXPECT_FLOAT_EQ(1.0, cras_iodev_get_software_gain_scaler(&iodev)); + EXPECT_FLOAT_EQ(0, cras_iodev_maximum_software_gain(&iodev)); } // This get_buffer implementation set returned frames larger than requested @@ -1233,8 +1232,6 @@ TEST(IoDev, OpenOutputDeviceNoStart) { iodev.configure_dev = configure_dev; iodev.direction = CRAS_STREAM_OUTPUT; iodev.format = &audio_fmt; - iodev.get_buffer = get_buffer; - iodev.put_buffer = put_buffer; ResetStubData(); iodev.state = CRAS_IODEV_STATE_CLOSE; @@ -1255,8 +1252,6 @@ TEST(IoDev, OpenOutputDeviceWithLowRateFmt) { iodev.configure_dev = configure_dev; iodev.direction = CRAS_STREAM_OUTPUT; iodev.format = &audio_fmt; - iodev.get_buffer = get_buffer; - iodev.put_buffer = put_buffer; ResetStubData(); cras_audio_format low_rate_fmt = audio_fmt; @@ -1378,8 +1373,6 @@ TEST(IoDev, AddRmStream) { iodev.no_stream = simple_no_stream; iodev.format = &audio_fmt; iodev.state = CRAS_IODEV_STATE_NORMAL_RUN; - iodev.get_buffer = get_buffer; - iodev.put_buffer = put_buffer; rstream1.cb_threshold = 800; stream1.stream = &rstream1; stream1.is_running = 0; @@ -1433,8 +1426,6 @@ TEST(IoDev, RmStreamUpdateFetchTime) { iodev.no_stream = simple_no_stream; iodev.format = &audio_fmt; iodev.state = CRAS_IODEV_STATE_NORMAL_RUN; - iodev.get_buffer = get_buffer; - iodev.put_buffer = put_buffer; rstream1.direction = CRAS_STREAM_OUTPUT; rstream2.direction = CRAS_STREAM_OUTPUT; rstream3.direction = CRAS_STREAM_OUTPUT; @@ -1482,8 +1473,6 @@ TEST(IoDev, StartStreams) { iodev1.configure_dev = configure_dev; iodev1.format = &audio_fmt; iodev1.state = CRAS_IODEV_STATE_NORMAL_RUN; - iodev1.get_buffer = get_buffer; - iodev1.put_buffer = put_buffer; iodev2.configure_dev = configure_dev; iodev2.format = &audio_fmt; iodev2.state = CRAS_IODEV_STATE_NORMAL_RUN; @@ -1733,7 +1722,7 @@ TEST(IoDev, PrepareOutputBeforeWriteSamples) { // Assume device has ramp member. iodev.ramp = reinterpret_cast<struct cras_ramp*>(0x1); - iodev.initial_ramp_request = CRAS_IODEV_RAMP_REQUEST_UP_START_PLAYBACK; + // Case 4.1: Assume device with ramp is started and is in no stream state. iodev.state = CRAS_IODEV_STATE_NO_STREAM_RUN; // Assume sample is ready. @@ -2112,13 +2101,18 @@ TEST(IoDev, FramesToPlayInSleep) { EXPECT_EQ(got_frames, hw_level - fmt.frame_rate / 1000 * 5); } +static unsigned int get_num_underruns(const struct cras_iodev* iodev) { + return get_num_underruns_ret; +} + TEST(IoDev, GetNumUnderruns) { struct cras_iodev iodev; memset(&iodev, 0, sizeof(iodev)); EXPECT_EQ(0, cras_iodev_get_num_underruns(&iodev)); - iodev.num_underruns = 10; + iodev.get_num_underruns = get_num_underruns; + get_num_underruns_ret = 10; EXPECT_EQ(10, cras_iodev_get_num_underruns(&iodev)); } @@ -2131,8 +2125,6 @@ TEST(IoDev, RequestReset) { iodev.configure_dev = configure_dev; iodev.direction = CRAS_STREAM_OUTPUT; iodev.format = &audio_fmt; - iodev.get_buffer = get_buffer; - iodev.put_buffer = put_buffer; iodev.state = CRAS_IODEV_STATE_CLOSE; iodev_buffer_size = 1024; @@ -2181,7 +2173,7 @@ TEST(IoDev, HandleOutputUnderrun) { iodev.min_cb_level = frames; // Default case, fill one block of zeros. - EXPECT_EQ(0, cras_iodev_output_underrun(&iodev, 0, 0)); + EXPECT_EQ(0, cras_iodev_output_underrun(&iodev)); EXPECT_EQ(frames, put_buffer_nframes); zeros = (int16_t*)calloc(frames * 2, sizeof(*zeros)); @@ -2191,7 +2183,7 @@ TEST(IoDev, HandleOutputUnderrun) { // Test iodev has output_underrun ops. iodev.output_underrun = output_underrun; - EXPECT_EQ(0, cras_iodev_output_underrun(&iodev, 0, 0)); + EXPECT_EQ(0, cras_iodev_output_underrun(&iodev)); EXPECT_EQ(1, output_underrun_called); } @@ -2240,12 +2232,12 @@ TEST(IoDev, SetExtDspMod) { EXPECT_EQ(3, cras_dsp_get_pipeline_called); EXPECT_EQ(3, cras_dsp_pipeline_set_sink_ext_module_called); - /* If pipeline doesn't exist, mock pipeline should be loaded. */ + /* If pipeline doesn't exist, dummy pipeline should be loaded. */ cras_dsp_get_pipeline_ret = 0x0; cras_iodev_set_ext_dsp_module(&iodev, &ext); EXPECT_EQ(3, ext_mod_configure_called); EXPECT_EQ(5, cras_dsp_get_pipeline_called); - EXPECT_EQ(1, cras_dsp_load_mock_pipeline_called); + EXPECT_EQ(1, cras_dsp_load_dummy_pipeline_called); EXPECT_EQ(4, cras_dsp_pipeline_set_sink_ext_module_called); } @@ -2357,71 +2349,8 @@ TEST(IoDev, DropDeviceFramesByTime) { EXPECT_EQ(-360, rate_estimator_add_frames_num_frames); } -TEST(IoDev, AecUseCaseCheck) { - struct cras_ionode node; - - /* test output types */ - node.type = CRAS_NODE_TYPE_INTERNAL_SPEAKER; - EXPECT_EQ(1, cras_iodev_is_aec_use_case(&node)); - node.type = CRAS_NODE_TYPE_HEADPHONE; - EXPECT_EQ(0, cras_iodev_is_aec_use_case(&node)); - node.type = CRAS_NODE_TYPE_HDMI; - EXPECT_EQ(0, cras_iodev_is_aec_use_case(&node)); - node.type = CRAS_NODE_TYPE_USB; - EXPECT_EQ(0, cras_iodev_is_aec_use_case(&node)); - node.type = CRAS_NODE_TYPE_BLUETOOTH; - EXPECT_EQ(0, cras_iodev_is_aec_use_case(&node)); - - /* test mic positions */ - node.type = CRAS_NODE_TYPE_MIC; - node.position = NODE_POSITION_INTERNAL; - EXPECT_EQ(1, cras_iodev_is_aec_use_case(&node)); - node.position = NODE_POSITION_FRONT; - EXPECT_EQ(1, cras_iodev_is_aec_use_case(&node)); - node.position = NODE_POSITION_EXTERNAL; - EXPECT_EQ(0, cras_iodev_is_aec_use_case(&node)); - node.position = NODE_POSITION_REAR; - EXPECT_EQ(0, cras_iodev_is_aec_use_case(&node)); -} - -TEST(IoDev, DeviceOverrun) { - struct cras_iodev iodev; - - iodev.buffer_size = 4096; - iodev.largest_cb_level = 2048; - cras_iodev_update_highest_hw_level(&iodev, 4096); - EXPECT_EQ(0, cras_audio_thread_event_dev_overrun_called); - - iodev.largest_cb_level = 1024; - iodev.highest_hw_level = 1024; - cras_iodev_update_highest_hw_level(&iodev, 2048); - EXPECT_EQ(0, cras_audio_thread_event_dev_overrun_called); - - cras_iodev_update_highest_hw_level(&iodev, 4096); - EXPECT_EQ(1, cras_audio_thread_event_dev_overrun_called); - - cras_iodev_update_highest_hw_level(&iodev, 4096); - EXPECT_EQ(1, cras_audio_thread_event_dev_overrun_called); -} - -TEST(IoDev, OnInternalCard) { - static struct cras_ionode node; - node.type = CRAS_NODE_TYPE_INTERNAL_SPEAKER; - EXPECT_EQ(1, cras_iodev_is_on_internal_card(&node)); - node.type = CRAS_NODE_TYPE_HEADPHONE; - EXPECT_EQ(1, cras_iodev_is_on_internal_card(&node)); - node.type = CRAS_NODE_TYPE_MIC; - EXPECT_EQ(1, cras_iodev_is_on_internal_card(&node)); - node.type = CRAS_NODE_TYPE_USB; - EXPECT_EQ(0, cras_iodev_is_on_internal_card(&node)); - node.type = CRAS_NODE_TYPE_BLUETOOTH; - EXPECT_EQ(0, cras_iodev_is_on_internal_card(&node)); -} - extern "C" { -struct main_thread_event_log* main_log; - // From libpthread. int pthread_create(pthread_t* thread, const pthread_attr_t* attr, @@ -2461,7 +2390,7 @@ unsigned int buffer_share_get_new_write_point(struct buffer_share* mix) { return buffer_share_get_new_write_point_ret; } -int buffer_share_add_id(struct buffer_share* mix, unsigned int id, void* data) { +int buffer_share_add_id(struct buffer_share* mix, unsigned int id) { buffer_share_add_id_called++; return 0; } @@ -2476,11 +2405,9 @@ unsigned int buffer_share_id_offset(const struct buffer_share* mix, } // From cras_system_state. -void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type) {} +void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction) {} -void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type) {} +void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction) {} // From cras_dsp struct cras_dsp_context* cras_dsp_context_new(int sample_rate, @@ -2495,9 +2422,9 @@ void cras_dsp_context_free(struct cras_dsp_context* ctx) { } void cras_dsp_load_pipeline(struct cras_dsp_context* ctx) {} -void cras_dsp_load_mock_pipeline(struct cras_dsp_context* ctx, - unsigned int num_channels) { - cras_dsp_load_mock_pipeline_called++; +void cras_dsp_load_dummy_pipeline(struct cras_dsp_context* ctx, + unsigned int num_channels) { + cras_dsp_load_dummy_pipeline_called++; } void cras_dsp_set_variable_string(struct cras_dsp_context* ctx, @@ -2614,6 +2541,10 @@ size_t cras_system_get_volume() { return cras_system_get_volume_return; } +long cras_system_get_capture_gain() { + return cras_system_get_capture_gain_ret_value; +} + int cras_system_get_mute() { return cras_system_get_mute_return; } @@ -2759,12 +2690,11 @@ void input_data_destroy(struct input_data** data) {} void input_data_set_all_streams_read(struct input_data* data, unsigned int nframes) {} -int cras_audio_thread_event_underrun() { +int cras_audio_thread_event_severe_underrun() { return 0; } -int cras_audio_thread_event_dev_overrun() { - cras_audio_thread_event_dev_overrun_called++; +int cras_audio_thread_event_underrun() { return 0; } @@ -2772,22 +2702,6 @@ int cras_server_metrics_device_runtime(struct cras_iodev* iodev) { return 0; } -int cras_server_metrics_device_volume(struct cras_iodev* iodev) { - return 0; -} - -void ewma_power_init(struct ewma_power* ewma, unsigned int rate){}; - -void ewma_power_calculate(struct ewma_power* ewma, - const int16_t* buf, - unsigned int channels, - unsigned int size){}; - -void ewma_power_calculate_area(struct ewma_power* ewma, - const int16_t* buf, - struct cras_audio_area* area, - unsigned int size){}; - } // extern "C" } // namespace diff --git a/cras/src/tests/loopback_iodev_unittest.cc b/cras/src/tests/loopback_iodev_unittest.cc index fde50375..3cdaffb6 100644 --- a/cras/src/tests/loopback_iodev_unittest.cc +++ b/cras/src/tests/loopback_iodev_unittest.cc @@ -7,11 +7,6 @@ #include <stdlib.h> extern "C" { -// For audio_thread_log.h use. -struct audio_thread_event_log* atlog; -int atlog_rw_shm_fd; -int atlog_ro_shm_fd; -#include "audio_thread_log.h" #include "cras_audio_area.h" #include "cras_iodev.h" #include "cras_iodev_list.h" @@ -29,7 +24,7 @@ static const unsigned int kFrameBytes = 4; static const unsigned int kBufferSize = kBufferFrames * kFrameBytes; static struct timespec time_now; -static cras_audio_area* mock_audio_area; +static cras_audio_area* dummy_audio_area; static loopback_hook_data_t loop_hook; static struct cras_iodev* enabled_dev; static unsigned int cras_iodev_list_add_input_called; @@ -41,13 +36,11 @@ static void* device_enabled_callback_cb_data; static int cras_iodev_list_register_loopback_called; static int cras_iodev_list_unregister_loopback_called; -static char* atlog_name; - class LoopBackTestSuite : public testing::Test { protected: virtual void SetUp() { - mock_audio_area = (cras_audio_area*)calloc( - 1, sizeof(*mock_audio_area) + sizeof(cras_channel_area) * 2); + dummy_audio_area = (cras_audio_area*)calloc( + 1, sizeof(*dummy_audio_area) + sizeof(cras_channel_area) * 2); for (unsigned int i = 0; i < kBufferSize; i++) { buf_[i] = rand(); } @@ -65,11 +58,6 @@ class LoopBackTestSuite : public testing::Test { cras_iodev_list_set_device_enabled_callback_called = 0; cras_iodev_list_register_loopback_called = 0; cras_iodev_list_unregister_loopback_called = 0; - - ASSERT_FALSE(asprintf(&atlog_name, "/ATlog-%d", getpid()) < 0); - /* To avoid un-used variable warning. */ - atlog_rw_shm_fd = atlog_ro_shm_fd = -1; - atlog = audio_thread_event_log_init(atlog_name); } virtual void TearDown() { @@ -77,9 +65,7 @@ class LoopBackTestSuite : public testing::Test { EXPECT_EQ(1, cras_iodev_list_rm_input_called); EXPECT_EQ(NULL, device_enabled_callback_cb); EXPECT_EQ(NULL, device_disabled_callback_cb); - free(mock_audio_area); - audio_thread_event_log_deinit(atlog, atlog_name); - free(atlog_name); + free(dummy_audio_area); } uint8_t buf_[kBufferSize]; @@ -224,7 +210,7 @@ extern "C" { void cras_audio_area_config_buf_pointers(struct cras_audio_area* area, const struct cras_audio_format* fmt, uint8_t* base_buffer) { - mock_audio_area->channels[0].buf = base_buffer; + dummy_audio_area->channels[0].buf = base_buffer; } void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} @@ -232,7 +218,7 @@ void cras_iodev_free_audio_area(struct cras_iodev* iodev) {} void cras_iodev_free_format(struct cras_iodev* iodev) {} void cras_iodev_init_audio_area(struct cras_iodev* iodev, int num_channels) { - iodev->area = mock_audio_area; + iodev->area = dummy_audio_area; } void cras_iodev_add_node(struct cras_iodev* iodev, struct cras_ionode* node) { diff --git a/cras/src/tests/metrics_stub.cc b/cras/src/tests/metrics_stub.cc index 96e8918b..d0f19c37 100644 --- a/cras/src/tests/metrics_stub.cc +++ b/cras/src/tests/metrics_stub.cc @@ -26,7 +26,7 @@ int cras_server_metrics_longest_fetch_delay(unsigned delay_msec) { return 0; } -int cras_server_metrics_missed_cb_event(struct cras_rstream* stream) { +int cras_server_metrics_missed_cb_event(const struct cras_rstream* stream) { return 0; } @@ -34,14 +34,6 @@ int cras_server_metrics_num_underruns(unsigned num_underruns) { return 0; } -int cras_server_metrics_hfp_battery_indicator(int battery_indicator_support) { - return 0; -} - -int cras_server_metrics_hfp_battery_report(int battery_report) { - return 0; -} - int cras_server_metrics_hfp_wideband_support(bool supported) { return 0; } @@ -50,17 +42,8 @@ int cras_server_metrics_hfp_packet_loss(float packet_loss_ratio) { return 0; } -int cras_server_metrics_hfp_sco_connection_error( - enum CRAS_METRICS_BT_SCO_ERROR_TYPE type) { - return 0; -} - int cras_server_metrics_busyloop(struct timespec* ts, unsigned count) { return 0; } -int cras_server_metrics_busyloop_length(unsigned count) { - return 0; -} - } // extern "C" diff --git a/cras/src/tests/observer_unittest.cc b/cras/src/tests/observer_unittest.cc index 2a8fae2c..5c9ca141 100644 --- a/cras/src/tests/observer_unittest.cc +++ b/cras/src/tests/observer_unittest.cc @@ -11,8 +11,6 @@ extern "C" { #include "cras_observer.c" -#include "cras_observer.h" -#include "cras_types.h" } namespace { @@ -58,9 +56,6 @@ static size_t cb_num_active_streams_changed_called; static std::vector<enum CRAS_STREAM_DIRECTION> cb_num_active_streams_changed_dir; static std::vector<uint32_t> cb_num_active_streams_changed_num; -static size_t cb_num_input_streams_with_permission_called; -static std::vector<std::vector<uint32_t>> - cb_num_input_streams_with_permission_array; static void ResetStubData() { cras_alert_destroy_called = 0; @@ -104,8 +99,6 @@ static void ResetStubData() { cb_num_active_streams_changed_called = 0; cb_num_active_streams_changed_dir.clear(); cb_num_active_streams_changed_num.clear(); - cb_num_input_streams_with_permission_called = 0; - cb_num_input_streams_with_permission_array.clear(); } /* System output volume changed. */ @@ -197,15 +190,6 @@ void cb_num_active_streams_changed(void* context, cb_num_active_streams_changed_num.push_back(num_active_streams); } -void cb_num_input_streams_with_permission_changed( - void* context, - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) { - cb_num_input_streams_with_permission_called++; - cb_context.push_back(context); - cb_num_input_streams_with_permission_array.push_back(std::vector<uint32_t>( - num_input_streams, num_input_streams + CRAS_NUM_CLIENT_TYPE)); -} - class ObserverTest : public testing::Test { protected: virtual void SetUp() { @@ -214,7 +198,7 @@ class ObserverTest : public testing::Test { ResetStubData(); rc = cras_observer_server_init(); ASSERT_EQ(0, rc); - EXPECT_EQ(17, cras_alert_create_called); + EXPECT_EQ(15, cras_alert_create_called); EXPECT_EQ(reinterpret_cast<void*>(output_volume_alert), cras_alert_add_callback_map[g_observer->alerts.output_volume]); EXPECT_EQ(reinterpret_cast<void*>(output_mute_alert), @@ -256,9 +240,6 @@ class ObserverTest : public testing::Test { EXPECT_EQ(reinterpret_cast<void*>(non_empty_audio_state_changed_alert), cras_alert_add_callback_map[g_observer->alerts .non_empty_audio_state_changed]); - EXPECT_EQ( - reinterpret_cast<void*>(bt_battery_changed_alert), - cras_alert_add_callback_map[g_observer->alerts.bt_battery_changed]); cras_observer_get_ops(NULL, &ops1_); EXPECT_NE(0, cras_observer_ops_are_empty(&ops1_)); @@ -272,7 +253,7 @@ class ObserverTest : public testing::Test { virtual void TearDown() { cras_observer_server_free(); - EXPECT_EQ(17, cras_alert_destroy_called); + EXPECT_EQ(15, cras_alert_destroy_called); ResetStubData(); } @@ -594,37 +575,6 @@ TEST_F(ObserverTest, NotifyNumActiveStreams) { DoObserverRemoveClear(num_active_streams_alert, data); }; -TEST_F(ObserverTest, NotifyNumInputStreamsWithPermission) { - struct cras_observer_alert_data_input_streams* data; - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE] = {}; - for (unsigned type = 0; type < CRAS_NUM_CLIENT_TYPE; ++type) { - num_input_streams[type] = (uint32_t)type; - } - - cras_observer_notify_input_streams_with_permission(num_input_streams); - ASSERT_EQ(cras_alert_pending_data_size_value, sizeof(*data)); - ASSERT_NE(cras_alert_pending_data_value, reinterpret_cast<void*>(NULL)); - data = reinterpret_cast<struct cras_observer_alert_data_input_streams*>( - cras_alert_pending_data_value); - for (unsigned type = 0; type < CRAS_NUM_CLIENT_TYPE; ++type) { - EXPECT_EQ(data->num_input_streams[type], num_input_streams[type]); - } - - ops1_.num_input_streams_with_permission_changed = - cb_num_input_streams_with_permission_changed; - ops2_.num_input_streams_with_permission_changed = - cb_num_input_streams_with_permission_changed; - DoObserverAlert(num_input_streams_with_permission_alert, data); - ASSERT_EQ(2, cb_num_input_streams_with_permission_called); - for (auto cb_num_input_streams : cb_num_input_streams_with_permission_array) { - ASSERT_EQ(cb_num_input_streams.size(), (size_t)CRAS_NUM_CLIENT_TYPE); - for (unsigned type = 0; type < CRAS_NUM_CLIENT_TYPE; ++type) { - EXPECT_EQ(cb_num_input_streams[type], num_input_streams[type]); - } - } - DoObserverRemoveClear(num_input_streams_with_permission_alert, data); -} - TEST_F(ObserverTest, NotifyHotwordTriggered) { struct cras_observer_alert_data_hotword_triggered* data; @@ -652,21 +602,6 @@ TEST_F(ObserverTest, NonEmpyAudioStateChanged) { EXPECT_EQ(data->non_empty, 1); } -TEST_F(ObserverTest, BluetoothBatteryChanged) { - struct cras_observer_alert_data_bt_battery_changed* data; - const char* address = "test"; - - cras_observer_notify_bt_battery_changed(address, 30); - EXPECT_EQ(cras_alert_pending_alert_value, - g_observer->alerts.bt_battery_changed); - ASSERT_EQ(cras_alert_pending_data_size_value, sizeof(*data)); - ASSERT_NE(cras_alert_pending_data_value, reinterpret_cast<void*>(NULL)); - data = reinterpret_cast<struct cras_observer_alert_data_bt_battery_changed*>( - cras_alert_pending_data_value); - EXPECT_EQ(data->address, address); - EXPECT_EQ(data->level, 30); -} - // Stubs extern "C" { diff --git a/cras/src/tests/playback_rclient_unittest.cc b/cras/src/tests/playback_rclient_unittest.cc index 31ceda74..aa24bc28 100644 --- a/cras/src/tests/playback_rclient_unittest.cc +++ b/cras/src/tests/playback_rclient_unittest.cc @@ -18,22 +18,24 @@ extern "C" { #include "cras_playback_rclient.c" #include "cras_rclient_util.c" } -static bool audio_format_valid; static unsigned int cras_make_fd_nonblocking_called; static unsigned int cras_observer_remove_called; +static unsigned int cras_server_metrics_stream_config_called; static int stream_list_add_called; static int stream_list_add_return; static unsigned int stream_list_rm_called; -static struct cras_audio_shm mock_shm; -static struct cras_rstream mock_rstream; +static struct cras_audio_shm dummy_shm; +static struct cras_rstream dummy_rstream; +static unsigned int cras_rstream_config_init_with_message_called; void ResetStubData() { - audio_format_valid = true; cras_make_fd_nonblocking_called = 0; cras_observer_remove_called = 0; + cras_server_metrics_stream_config_called = 0; stream_list_add_called = 0; stream_list_add_return = 0; stream_list_rm_called = 0; + cras_rstream_config_init_with_message_called = 0; } namespace { @@ -108,12 +110,13 @@ TEST_F(CPRMessageSuite, StreamConnectMessage) { cras_fill_connect_message(&msg, CRAS_STREAM_OUTPUT, stream_id, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, 480, 240, /*flags=*/0, /*effects=*/0, fmt, - NO_DEVICE); + NO_DEVICE, /*client_shm_size=*/0); ASSERT_EQ(stream_id, msg.stream_id); fd_ = 100; rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); EXPECT_EQ(1, cras_make_fd_nonblocking_called); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); EXPECT_EQ(1, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); @@ -135,14 +138,16 @@ TEST_F(CPRMessageSuite, StreamConnectMessageInvalidDirection) { continue; cras_fill_connect_message(&msg, dir, stream_id, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, 480, 240, /*flags=*/0, - /*effects=*/0, fmt, NO_DEVICE); + /*effects=*/0, fmt, NO_DEVICE, + /*client_shm_size=*/0); ASSERT_EQ(stream_id, msg.stream_id); fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); EXPECT_EQ(0, cras_make_fd_nonblocking_called); + EXPECT_EQ(0, cras_rstream_config_init_with_message_called); EXPECT_EQ(0, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); @@ -162,14 +167,15 @@ TEST_F(CPRMessageSuite, StreamConnectMessageInvalidClientId) { cras_fill_connect_message(&msg, CRAS_STREAM_OUTPUT, stream_id, CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, 480, 240, /*flags=*/0, /*effects=*/0, fmt, - NO_DEVICE); + NO_DEVICE, /*client_shm_size=*/0); ASSERT_EQ(stream_id, msg.stream_id); fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); - EXPECT_EQ(0, rc); + EXPECT_EQ(-EINVAL, rc); EXPECT_EQ(0, cras_make_fd_nonblocking_called); + EXPECT_EQ(0, cras_rstream_config_init_with_message_called); EXPECT_EQ(0, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); @@ -179,31 +185,40 @@ TEST_F(CPRMessageSuite, StreamConnectMessageInvalidClientId) { EXPECT_EQ(stream_id, out_msg.stream_id); } -TEST_F(CPRMessageSuite, StreamConnectMessageInvalidAudioFormat) { +/* + * TODO(yuhsaun): Remove this test when there are no client uses the old + * craslib. (CRAS_PROTO_VER = 3) + */ +TEST_F(CPRMessageSuite, StreamConnectMessageOldProtocal) { struct cras_client_stream_connected out_msg; int rc; - struct cras_connect_message msg; + struct cras_connect_message_old msg; cras_stream_id_t stream_id = 0x10002; - cras_fill_connect_message(&msg, CRAS_STREAM_OUTPUT, stream_id, - CRAS_STREAM_TYPE_DEFAULT, CRAS_CLIENT_TYPE_UNKNOWN, - 480, 240, /*flags=*/0, /*effects=*/0, fmt, - NO_DEVICE); - ASSERT_EQ(stream_id, msg.stream_id); - audio_format_valid = false; // stubs out verification failure. + msg.proto_version = 3; + msg.direction = CRAS_STREAM_OUTPUT; + msg.stream_id = stream_id; + msg.stream_type = CRAS_STREAM_TYPE_DEFAULT; + msg.buffer_frames = 480; + msg.cb_threshold = 240; + msg.flags = 0; + msg.effects = 0; + pack_cras_audio_format(&msg.format, &fmt); + msg.dev_idx = NO_DEVICE; + msg.header.id = CRAS_SERVER_CONNECT_STREAM; + msg.header.length = sizeof(struct cras_connect_message_old); fd_ = 100; rc = rclient_->ops->handle_message_from_client(rclient_, &msg.header, &fd_, 1); - EXPECT_EQ(0, rc); - EXPECT_EQ(0, cras_make_fd_nonblocking_called); - EXPECT_EQ(0, stream_list_add_called); + EXPECT_EQ(1, cras_make_fd_nonblocking_called); + EXPECT_EQ(1, cras_rstream_config_init_with_message_called); + EXPECT_EQ(1, stream_list_add_called); EXPECT_EQ(0, stream_list_rm_called); rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); EXPECT_EQ(sizeof(out_msg), rc); - EXPECT_EQ(-EINVAL, out_msg.err); EXPECT_EQ(stream_id, out_msg.stream_id); } @@ -253,6 +268,11 @@ unsigned int cras_rstream_get_effects(const struct cras_rstream* stream) { return 0; } +int cras_server_metrics_stream_config(struct cras_rstream_config* config) { + cras_server_metrics_stream_config_called++; + return 0; +} + int cras_send_with_fds(int sockfd, const void* buf, size_t len, @@ -282,27 +302,30 @@ int stream_list_add(struct stream_list* list, struct cras_rstream** stream) { int ret; - *stream = &mock_rstream; + *stream = &dummy_rstream; stream_list_add_called++; ret = stream_list_add_return; if (ret) stream_list_add_return = -EINVAL; - mock_rstream.shm = &mock_shm; - mock_rstream.direction = config->direction; - mock_rstream.stream_id = config->stream_id; + dummy_rstream.shm = &dummy_shm; + dummy_rstream.direction = config->direction; + dummy_rstream.stream_id = config->stream_id; return ret; } -bool cras_audio_format_valid(const struct cras_audio_format* fmt) { - return audio_format_valid; +void cras_rstream_config_init_with_message( + struct cras_rclient* client, + const struct cras_connect_message* msg, + int* aud_fd, + int* client_shm_fd, + const struct cras_audio_format* remote_fmt, + struct cras_rstream_config* stream_config) { + cras_rstream_config_init_with_message_called++; } -void detect_rtc_stream_pair(struct stream_list* list, - struct cras_rstream* stream) { - return; -} +void cras_rstream_config_cleanup(struct cras_rstream_config* stream_config) {} } // extern "C" diff --git a/cras/src/tests/polled_interval_checker_unittest.cc b/cras/src/tests/polled_interval_checker_unittest.cc index a4aff09c..c18fdf7e 100644 --- a/cras/src/tests/polled_interval_checker_unittest.cc +++ b/cras/src/tests/polled_interval_checker_unittest.cc @@ -70,7 +70,7 @@ TEST(PolledIntervalCheckerTest, DoesNotResetAutomatically) { struct polled_interval* interval = create_interval(); - // Initial check. + // Sanity check. EXPECT_FALSE(pic_interval_elapsed(interval)); // Increment time so the interval elapses. @@ -100,7 +100,7 @@ TEST(PolledIntervalCheckerTest, Reset) { struct polled_interval* interval = create_interval(); - // Initial check. + // Sanity check. EXPECT_FALSE(pic_interval_elapsed(interval)); // Increment time so the interval elapses. diff --git a/cras/src/tests/ramp_unittest.cc b/cras/src/tests/ramp_unittest.cc index a661dffe..8d674799 100644 --- a/cras/src/tests/ramp_unittest.cc +++ b/cras/src/tests/ramp_unittest.cc @@ -315,22 +315,6 @@ TEST(RampTestSuite, RampDownWhileHalfWayRampUp) { cras_ramp_destroy(ramp); } -TEST(RampTestSuite, NullWontCrash) { - float from; - float to; - int duration_frames = 48000; - int rc = 0; - struct cras_ramp* ramp = NULL; - - ResetStubData(); - - from = 0.0; - to = 1.0; - rc = cras_mute_ramp_start(ramp, from, to, duration_frames, NULL, NULL); - - EXPECT_EQ(-EINVAL, rc); -} - TEST(RampTestSuite, RampDownWhileHalfWayRampDown) { float from = 1.0; float to = 0.0; @@ -370,28 +354,6 @@ TEST(RampTestSuite, RampDownWhileHalfWayRampDown) { cras_ramp_destroy(ramp); } -TEST(RampTestSuite, MuteRamp) { - float from = 0.0; - float to = 0.0; - int duration_frames = 48000; - struct cras_ramp* ramp; - struct cras_ramp_action action; - - ResetStubData(); - - ramp = cras_ramp_create(); - cras_mute_ramp_start(ramp, from, to, duration_frames, NULL, NULL); - - action = cras_ramp_get_current_action(ramp); - - EXPECT_EQ(CRAS_RAMP_ACTION_PARTIAL, action.type); - EXPECT_FLOAT_EQ(0.0, action.scaler); - EXPECT_FLOAT_EQ(0.0, action.increment); - EXPECT_FLOAT_EQ(0.0, action.target); - - cras_ramp_destroy(ramp); -} - TEST(RampTestSuite, PartialRamp) { float from_one = 0.75; float to_one = 0.4; diff --git a/cras/src/tests/rate_estimator_unittest.cc b/cras/src/tests/rate_estimator_unittest.cc index 778a3cda..66f7c586 100644 --- a/cras/src/tests/rate_estimator_unittest.cc +++ b/cras/src/tests/rate_estimator_unittest.cc @@ -95,10 +95,11 @@ TEST(RateEstimatorTest, EstimateRateSkewTooLarge) { TEST(RateEstimatorTest, EstimateOutputSmooth) { struct rate_estimator* re; - struct timespec t = {.tv_sec = 1, .tv_nsec = 0}; + struct timespec t; int rc; re = rate_estimator_create(10010, &window, 0.9f); + t.tv_sec = 1; rc = rate_estimator_check(re, 240, &t); EXPECT_EQ(0, rc); @@ -123,10 +124,11 @@ TEST(RateEstimatorTest, EstimateOutputSmooth) { TEST(RateEstimatorTest, EstimateInputLinear) { struct rate_estimator* re; - struct timespec t = {.tv_sec = 1, .tv_nsec = 0}; + struct timespec t; int i, rc, level, tmp; re = rate_estimator_create(10000, &window, 0.0f); + t.tv_sec = 1; level = 1200; for (i = 0; i < 20; i++) { rc = rate_estimator_check(re, level, &t); diff --git a/cras/src/tests/rstream_unittest.cc b/cras/src/tests/rstream_unittest.cc index d8dae24c..69523f5f 100644 --- a/cras/src/tests/rstream_unittest.cc +++ b/cras/src/tests/rstream_unittest.cc @@ -16,8 +16,6 @@ extern "C" { #include "cras_shm.h" } -#include "metrics_stub.h" - namespace { class RstreamTestSuite : public testing::Test { @@ -32,7 +30,6 @@ class RstreamTestSuite : public testing::Test { config_.stream_id = 555; config_.stream_type = CRAS_STREAM_TYPE_DEFAULT; - config_.client_type = CRAS_CLIENT_TYPE_UNKNOWN; config_.direction = CRAS_STREAM_OUTPUT; config_.dev_idx = NO_DEVICE; config_.flags = 0; @@ -379,7 +376,7 @@ unsigned int buffer_share_get_new_write_point(struct buffer_share* mix) { return 0; } -int buffer_share_add_id(struct buffer_share* mix, unsigned int id, void* data) { +int buffer_share_add_id(struct buffer_share* mix, unsigned int id) { return 0; } @@ -391,36 +388,14 @@ unsigned int buffer_share_id_offset(const struct buffer_share* mix, unsigned int id) { return 0; } -void ewma_power_init(struct ewma_power* ewma, unsigned int rate) {} - -void ewma_power_calculate(struct ewma_power* ewma, - const int16_t* buf, - unsigned int channels, - unsigned int size) {} -void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type) {} - -void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction, - enum CRAS_CLIENT_TYPE client_type) {} - -int cras_server_metrics_stream_create( - const struct cras_rstream_config* config) { - return 0; -} - -int cras_server_metrics_stream_destroy(const struct cras_rstream* stream) { - return 0; -} +void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction) {} +void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction) {} #ifdef HAVE_WEBRTC_APM -#define FAKE_CRAS_APM_PTR reinterpret_cast<struct cras_apm*>(0x99) struct cras_apm_list* cras_apm_list_create(void* stream_ptr, uint64_t effects) { return NULL; } -struct cras_apm* cras_apm_list_get_active_apm(void* stream_ptr, void* dev_ptr) { - return FAKE_CRAS_APM_PTR; -} int cras_apm_list_destroy(struct cras_apm_list* list) { return 0; } @@ -434,4 +409,8 @@ struct cras_audio_format* cras_apm_list_get_format(struct cras_apm* apm) { return NULL; } #endif + +int cras_server_metrics_missed_cb_frequency(const struct cras_rstream* stream) { + return 0; +} } diff --git a/cras/src/tests/server_metrics_unittest.cc b/cras/src/tests/server_metrics_unittest.cc index e23906ec..94a689c5 100644 --- a/cras/src/tests/server_metrics_unittest.cc +++ b/cras/src/tests/server_metrics_unittest.cc @@ -132,6 +132,20 @@ TEST(ServerMetricsTestSuite, SetMetricHighestHardwareLevel) { EXPECT_EQ(sent_msgs[0].data.value, hw_level); } +TEST(ServerMetricsTestSuite, SetMetricsLongestFetchDelay) { + ResetStubData(); + unsigned int delay = 100; + + cras_server_metrics_longest_fetch_delay(delay); + + EXPECT_EQ(sent_msgs.size(), 1); + EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS); + EXPECT_EQ(sent_msgs[0].header.length, + sizeof(struct cras_server_metrics_message)); + EXPECT_EQ(sent_msgs[0].metrics_type, LONGEST_FETCH_DELAY); + EXPECT_EQ(sent_msgs[0].data.value, delay); +} + TEST(ServerMetricsTestSuite, SetMetricsNumUnderruns) { ResetStubData(); unsigned int underrun = 10; @@ -146,6 +160,79 @@ TEST(ServerMetricsTestSuite, SetMetricsNumUnderruns) { EXPECT_EQ(sent_msgs[0].data.value, underrun); } +TEST(ServerMetricsTestSuite, SetMetricsMissedCallbackFrequencyInputStream) { + ResetStubData(); + struct cras_rstream stream; + struct timespec diff_ts; + + stream.flags = 0; + stream.start_ts.tv_sec = 0; + stream.start_ts.tv_nsec = 0; + clock_gettime_retspec.tv_sec = 1000; + clock_gettime_retspec.tv_nsec = 0; + stream.num_missed_cb = 5; + stream.first_missed_cb_ts.tv_sec = 100; + stream.first_missed_cb_ts.tv_nsec = 0; + + stream.direction = CRAS_STREAM_INPUT; + cras_server_metrics_missed_cb_frequency(&stream); + + subtract_timespecs(&clock_gettime_retspec, &stream.start_ts, &diff_ts); + EXPECT_EQ(sent_msgs.size(), 2); + EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS); + EXPECT_EQ(sent_msgs[0].header.length, + sizeof(struct cras_server_metrics_message)); + EXPECT_EQ(sent_msgs[0].metrics_type, MISSED_CB_FREQUENCY_INPUT); + EXPECT_EQ(sent_msgs[0].data.value, + stream.num_missed_cb * 86400 / diff_ts.tv_sec); + + subtract_timespecs(&clock_gettime_retspec, &stream.first_missed_cb_ts, + &diff_ts); + EXPECT_EQ(sent_msgs[1].header.type, CRAS_MAIN_METRICS); + EXPECT_EQ(sent_msgs[1].header.length, + sizeof(struct cras_server_metrics_message)); + EXPECT_EQ(sent_msgs[1].metrics_type, + MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_INPUT); + EXPECT_EQ(sent_msgs[1].data.value, + (stream.num_missed_cb - 1) * 86400 / diff_ts.tv_sec); +} + +TEST(ServerMetricsTestSuite, SetMetricsMissedCallbackFrequencyOutputStream) { + ResetStubData(); + struct cras_rstream stream; + struct timespec diff_ts; + + stream.flags = 0; + stream.start_ts.tv_sec = 0; + stream.start_ts.tv_nsec = 0; + clock_gettime_retspec.tv_sec = 1000; + clock_gettime_retspec.tv_nsec = 0; + stream.num_missed_cb = 5; + stream.first_missed_cb_ts.tv_sec = 100; + stream.first_missed_cb_ts.tv_nsec = 0; + stream.direction = CRAS_STREAM_OUTPUT; + cras_server_metrics_missed_cb_frequency(&stream); + + subtract_timespecs(&clock_gettime_retspec, &stream.start_ts, &diff_ts); + EXPECT_EQ(sent_msgs.size(), 2); + EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS); + EXPECT_EQ(sent_msgs[0].header.length, + sizeof(struct cras_server_metrics_message)); + EXPECT_EQ(sent_msgs[0].metrics_type, MISSED_CB_FREQUENCY_OUTPUT); + EXPECT_EQ(sent_msgs[0].data.value, + stream.num_missed_cb * 86400 / diff_ts.tv_sec); + + subtract_timespecs(&clock_gettime_retspec, &stream.first_missed_cb_ts, + &diff_ts); + EXPECT_EQ(sent_msgs[1].header.type, CRAS_MAIN_METRICS); + EXPECT_EQ(sent_msgs[1].header.length, + sizeof(struct cras_server_metrics_message)); + EXPECT_EQ(sent_msgs[1].metrics_type, + MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_OUTPUT); + EXPECT_EQ(sent_msgs[1].data.value, + (stream.num_missed_cb - 1) * 86400 / diff_ts.tv_sec); +} + TEST(ServerMetricsTestSuite, SetMetricsMissedCallbackEventInputStream) { ResetStubData(); struct cras_rstream stream; @@ -228,7 +315,7 @@ TEST(ServerMetricsTestSuite, SetMetricsMissedCallbackEventOutputStream) { EXPECT_EQ(stream.num_missed_cb, 2); } -TEST(ServerMetricsTestSuite, SetMetricsStreamCreate) { +TEST(ServerMetricsTestSuite, SetMetricsStreamConfig) { ResetStubData(); struct cras_rstream_config config; struct cras_audio_format format; @@ -239,10 +326,10 @@ TEST(ServerMetricsTestSuite, SetMetricsStreamCreate) { format.format = SND_PCM_FORMAT_S16_LE; format.frame_rate = 48000; config.client_type = CRAS_CLIENT_TYPE_TEST; + config.format = &format; - cras_server_metrics_stream_create(&config); + cras_server_metrics_stream_config(&config); - // Log stream config. EXPECT_EQ(sent_msgs.size(), 1); EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS); EXPECT_EQ(sent_msgs[0].header.length, @@ -256,75 +343,6 @@ TEST(ServerMetricsTestSuite, SetMetricsStreamCreate) { EXPECT_EQ(sent_msgs[0].data.stream_config.client_type, CRAS_CLIENT_TYPE_TEST); } -TEST(ServerMetricsTestSuite, SetMetricsStreamDestroy) { - ResetStubData(); - struct cras_rstream stream; - struct timespec diff_ts; - - stream.flags = 0; - stream.start_ts.tv_sec = 0; - stream.start_ts.tv_nsec = 0; - clock_gettime_retspec.tv_sec = 1000; - clock_gettime_retspec.tv_nsec = 0; - stream.num_missed_cb = 5; - stream.first_missed_cb_ts.tv_sec = 100; - stream.first_missed_cb_ts.tv_nsec = 0; - stream.longest_fetch_interval.tv_sec = 1; - stream.longest_fetch_interval.tv_nsec = 0; - stream.sleep_interval_ts.tv_sec = 0; - stream.sleep_interval_ts.tv_nsec = 5000000; - - stream.direction = CRAS_STREAM_INPUT; - stream.client_type = CRAS_CLIENT_TYPE_TEST; - stream.stream_type = CRAS_STREAM_TYPE_DEFAULT; - cras_server_metrics_stream_destroy(&stream); - - subtract_timespecs(&clock_gettime_retspec, &stream.start_ts, &diff_ts); - EXPECT_EQ(sent_msgs.size(), 4); - - // Log missed cb frequency. - EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS); - EXPECT_EQ(sent_msgs[0].header.length, - sizeof(struct cras_server_metrics_message)); - EXPECT_EQ(sent_msgs[0].metrics_type, MISSED_CB_FREQUENCY_INPUT); - EXPECT_EQ(sent_msgs[0].data.value, - stream.num_missed_cb * 86400 / diff_ts.tv_sec); - - // Log missed cb frequency after rescheduling. - subtract_timespecs(&clock_gettime_retspec, &stream.first_missed_cb_ts, - &diff_ts); - EXPECT_EQ(sent_msgs[1].header.type, CRAS_MAIN_METRICS); - EXPECT_EQ(sent_msgs[1].header.length, - sizeof(struct cras_server_metrics_message)); - EXPECT_EQ(sent_msgs[1].metrics_type, - MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_INPUT); - EXPECT_EQ(sent_msgs[1].data.value, - (stream.num_missed_cb - 1) * 86400 / diff_ts.tv_sec); - - // Log stream runtime. - EXPECT_EQ(sent_msgs[2].header.type, CRAS_MAIN_METRICS); - EXPECT_EQ(sent_msgs[2].header.length, - sizeof(struct cras_server_metrics_message)); - EXPECT_EQ(sent_msgs[2].metrics_type, STREAM_RUNTIME); - EXPECT_EQ(sent_msgs[2].data.stream_data.client_type, CRAS_CLIENT_TYPE_TEST); - EXPECT_EQ(sent_msgs[2].data.stream_data.stream_type, - CRAS_STREAM_TYPE_DEFAULT); - EXPECT_EQ(sent_msgs[2].data.stream_data.direction, CRAS_STREAM_INPUT); - EXPECT_EQ(sent_msgs[2].data.stream_data.runtime.tv_sec, 1000); - - // Log longest fetch delay. - EXPECT_EQ(sent_msgs[3].header.type, CRAS_MAIN_METRICS); - EXPECT_EQ(sent_msgs[3].header.length, - sizeof(struct cras_server_metrics_message)); - EXPECT_EQ(sent_msgs[3].metrics_type, LONGEST_FETCH_DELAY); - EXPECT_EQ(sent_msgs[3].data.stream_data.client_type, CRAS_CLIENT_TYPE_TEST); - EXPECT_EQ(sent_msgs[3].data.stream_data.stream_type, - CRAS_STREAM_TYPE_DEFAULT); - EXPECT_EQ(sent_msgs[3].data.stream_data.direction, CRAS_STREAM_INPUT); - EXPECT_EQ(sent_msgs[3].data.stream_data.runtime.tv_sec, 0); - EXPECT_EQ(sent_msgs[3].data.stream_data.runtime.tv_nsec, 995000000); -} - TEST(ServerMetricsTestSuite, SetMetricsBusyloop) { ResetStubData(); struct timespec time = {40, 0}; @@ -342,20 +360,6 @@ TEST(ServerMetricsTestSuite, SetMetricsBusyloop) { EXPECT_EQ(sent_msgs[0].data.timespec_data.count, 3); } -TEST(ServerMetricsTestSuite, SetMetricsBusyloopLength) { - ResetStubData(); - unsigned length = 5; - - cras_server_metrics_busyloop_length(length); - - EXPECT_EQ(sent_msgs.size(), 1); - EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS); - EXPECT_EQ(sent_msgs[0].header.length, - sizeof(struct cras_server_metrics_message)); - EXPECT_EQ(sent_msgs[0].metrics_type, BUSYLOOP_LENGTH); - EXPECT_EQ(sent_msgs[0].data.value, 5); -} - extern "C" { int cras_main_message_add_handler(enum CRAS_MAIN_MESSAGE_TYPE type, diff --git a/cras/src/tests/stream_list_unittest.cc b/cras/src/tests/stream_list_unittest.cc index 500774f1..8f3c2e3e 100644 --- a/cras/src/tests/stream_list_unittest.cc +++ b/cras/src/tests/stream_list_unittest.cc @@ -28,20 +28,13 @@ static int removed_cb(struct cras_rstream* rstream) { static unsigned int create_called; static struct cras_rstream_config* create_config; +static struct cras_rstream dummy_rstream; static int create_rstream_cb(struct cras_rstream_config* stream_config, struct cras_rstream** stream) { create_called++; create_config = stream_config; - *stream = (struct cras_rstream*)malloc(sizeof(struct cras_rstream)); - (*stream)->stream_id = stream_config->stream_id; - (*stream)->direction = stream_config->direction; - if (stream_config->format) - (*stream)->format = *(stream_config->format); - (*stream)->cb_threshold = stream_config->cb_threshold; - (*stream)->client_type = stream_config->client_type; - (*stream)->stream_type = stream_config->stream_type; - clock_gettime(CLOCK_MONOTONIC_RAW, &(*stream)->start_ts); - + *stream = &dummy_rstream; + dummy_rstream.stream_id = 0x3003; return 0; } @@ -50,7 +43,6 @@ static struct cras_rstream* destroyed_stream; static void destroy_rstream_cb(struct cras_rstream* rstream) { destroy_called++; destroyed_stream = rstream; - free(rstream); } static void reset_test_data() { @@ -65,10 +57,6 @@ TEST(StreamList, AddRemove) { struct cras_rstream* s1; struct cras_rstream_config s1_config; - s1_config.stream_id = 0x3003; - s1_config.direction = CRAS_STREAM_OUTPUT; - s1_config.format = NULL; - reset_test_data(); l = stream_list_create(added_cb, removed_cb, create_rstream_cb, destroy_rstream_cb, NULL); @@ -84,117 +72,6 @@ TEST(StreamList, AddRemove) { stream_list_destroy(l); } -TEST(StreamList, AddInDescendingOrderByChannels) { - struct stream_list* l; - struct cras_rstream* s1; - struct cras_rstream* s2; - struct cras_rstream* s3; - struct cras_audio_format s1_format, s2_format, s3_format; - struct cras_rstream_config s1_config, s2_config, s3_config; - - s1_config.stream_id = 0x4001; - s1_config.direction = CRAS_STREAM_INPUT; - s1_format.num_channels = 6; - s1_config.format = &s1_format; - - s2_config.stream_id = 0x4002; - s2_config.direction = CRAS_STREAM_OUTPUT; - s2_format.num_channels = 8; - s2_config.format = &s2_format; - - s3_config.stream_id = 0x4003; - s3_config.direction = CRAS_STREAM_OUTPUT; - s3_format.num_channels = 2; - s3_config.format = &s3_format; - - reset_test_data(); - l = stream_list_create(added_cb, removed_cb, create_rstream_cb, - destroy_rstream_cb, NULL); - stream_list_add(l, &s1_config, &s1); - EXPECT_EQ(1, add_called); - EXPECT_EQ(1, create_called); - EXPECT_EQ(6, stream_list_get(l)->format.num_channels); - - stream_list_add(l, &s2_config, &s2); - EXPECT_EQ(2, add_called); - EXPECT_EQ(2, create_called); - EXPECT_EQ(8, stream_list_get(l)->format.num_channels); - EXPECT_EQ(6, stream_list_get(l)->next->format.num_channels); - - stream_list_add(l, &s3_config, &s3); - EXPECT_EQ(3, add_called); - EXPECT_EQ(3, create_called); - EXPECT_EQ(8, stream_list_get(l)->format.num_channels); - EXPECT_EQ(6, stream_list_get(l)->next->format.num_channels); - EXPECT_EQ(2, stream_list_get(l)->next->next->format.num_channels); - EXPECT_EQ(0, stream_list_rm(l, 0x4001)); - EXPECT_EQ(0, stream_list_rm(l, 0x4002)); - EXPECT_EQ(0, stream_list_rm(l, 0x4003)); - stream_list_destroy(l); -} - -TEST(StreamList, DetectRtcStreamPair) { - struct stream_list* l; - struct cras_rstream *s1, *s2, *s3, *s4; - struct cras_rstream_config s1_config, s2_config, s3_config, s4_config; - - s1_config.stream_id = 0x5001; - s1_config.direction = CRAS_STREAM_OUTPUT; - s1_config.cb_threshold = 480; - s1_config.client_type = CRAS_CLIENT_TYPE_CHROME; - s1_config.stream_type = CRAS_STREAM_TYPE_DEFAULT; - s1_config.format = NULL; - - s2_config.stream_id = 0x5002; - s2_config.direction = CRAS_STREAM_INPUT; - s2_config.cb_threshold = 480; - s2_config.client_type = CRAS_CLIENT_TYPE_CHROME; - s2_config.stream_type = CRAS_STREAM_TYPE_DEFAULT; - s2_config.format = NULL; - - // s3 is not a RTC stream because the cb threshold is not 480. - s3_config.stream_id = 0x5003; - s3_config.direction = CRAS_STREAM_INPUT; - s3_config.cb_threshold = 500; - s3_config.client_type = CRAS_CLIENT_TYPE_CHROME; - s3_config.stream_type = CRAS_STREAM_TYPE_DEFAULT; - s3_config.format = NULL; - - // s4 is not a RTC stream because it is not from the same client with s1. - s4_config.stream_id = 0x5004; - s4_config.direction = CRAS_STREAM_INPUT; - s4_config.cb_threshold = 480; - s4_config.client_type = CRAS_CLIENT_TYPE_LACROS; - s4_config.stream_type = CRAS_STREAM_TYPE_DEFAULT; - s4_config.format = NULL; - - reset_test_data(); - l = stream_list_create(added_cb, removed_cb, create_rstream_cb, - destroy_rstream_cb, NULL); - stream_list_add(l, &s1_config, &s1); - EXPECT_EQ(1, add_called); - EXPECT_EQ(1, create_called); - EXPECT_EQ(&s1_config, create_config); - - stream_list_add(l, &s2_config, &s2); - detect_rtc_stream_pair(l, s2); - stream_list_add(l, &s3_config, &s3); - detect_rtc_stream_pair(l, s3); - stream_list_add(l, &s4_config, &s4); - detect_rtc_stream_pair(l, s4); - - EXPECT_EQ(CRAS_STREAM_TYPE_VOICE_COMMUNICATION, s1->stream_type); - EXPECT_EQ(CRAS_STREAM_TYPE_VOICE_COMMUNICATION, s2->stream_type); - EXPECT_EQ(CRAS_STREAM_TYPE_DEFAULT, s3->stream_type); - EXPECT_EQ(CRAS_STREAM_TYPE_DEFAULT, s4->stream_type); - - EXPECT_EQ(0, stream_list_rm(l, 0x5001)); - EXPECT_EQ(0, stream_list_rm(l, 0x5002)); - EXPECT_EQ(0, stream_list_rm(l, 0x5003)); - EXPECT_EQ(0, stream_list_rm(l, 0x5004)); - stream_list_destroy(l); -} - extern "C" { struct cras_timer* cras_tm_create_timer(struct cras_tm* tm, diff --git a/cras/src/tests/system_state_unittest.cc b/cras/src/tests/system_state_unittest.cc index 45224bc9..9e7ecc8b 100644 --- a/cras/src/tests/system_state_unittest.cc +++ b/cras/src/tests/system_state_unittest.cc @@ -4,11 +4,9 @@ #include <gtest/gtest.h> #include <stdio.h> -#include <string.h> extern "C" { #include "cras_alert.h" -#include "cras_board_config.h" #include "cras_shm.h" #include "cras_system_state.h" #include "cras_types.h" @@ -35,13 +33,10 @@ static char* device_config_dir; static const char* cras_alsa_card_config_dir; static size_t cras_observer_notify_output_volume_called; static size_t cras_observer_notify_output_mute_called; +static size_t cras_observer_notify_capture_gain_called; static size_t cras_observer_notify_capture_mute_called; static size_t cras_observer_notify_suspend_changed_called; static size_t cras_observer_notify_num_active_streams_called; -static size_t cras_observer_notify_input_streams_with_permission_called; -static size_t cras_iodev_list_reset_for_noise_cancellation_called; -static struct cras_board_config fake_board_config; -static size_t cras_alert_process_all_pending_alerts_called; static void ResetStubData() { cras_alsa_card_create_called = 0; @@ -58,19 +53,15 @@ static void ResetStubData() { cras_alsa_card_config_dir = NULL; cras_observer_notify_output_volume_called = 0; cras_observer_notify_output_mute_called = 0; + cras_observer_notify_capture_gain_called = 0; cras_observer_notify_capture_mute_called = 0; cras_observer_notify_suspend_changed_called = 0; cras_observer_notify_num_active_streams_called = 0; - cras_observer_notify_input_streams_with_permission_called = 0; - cras_alert_process_all_pending_alerts_called = 0; - cras_iodev_list_reset_for_noise_cancellation_called = 0; - memset(&fake_board_config, 0, sizeof(fake_board_config)); } static int add_stub(int fd, - void (*cb)(void* data, int revents), + void (*cb)(void* data), void* callback_data, - int events, void* select_data) { add_stub_called++; select_data_value = select_data; @@ -90,11 +81,7 @@ static int add_task_stub(void (*cb)(void* data), return 0; } -static void callback_stub(void* data, int revents) { - callback_stub_called++; -} - -static void task_stub(void* data) { +static void callback_stub(void* data) { callback_stub_called++; } @@ -116,6 +103,7 @@ static void do_sys_init() { TEST(SystemStateSuite, DefaultVolume) { do_sys_init(); EXPECT_EQ(100, cras_system_get_volume()); + EXPECT_EQ(2000, cras_system_get_capture_gain()); EXPECT_EQ(0, cras_system_get_mute()); EXPECT_EQ(0, cras_system_get_capture_mute()); cras_system_state_deinit(); @@ -143,6 +131,46 @@ TEST(SystemStateSuite, SetMinMaxVolume) { cras_system_state_deinit(); } +TEST(SystemStateSuite, SetCaptureVolume) { + do_sys_init(); + cras_system_set_capture_gain(0); + EXPECT_EQ(0, cras_system_get_capture_gain()); + cras_system_set_capture_gain(3000); + EXPECT_EQ(3000, cras_system_get_capture_gain()); + // Check that it is limited to the minimum allowed gain. + cras_system_set_capture_gain(-10000); + EXPECT_EQ(-5000, cras_system_get_capture_gain()); + cras_system_state_deinit(); + EXPECT_EQ(3, cras_observer_notify_capture_gain_called); +} + +TEST(SystemStateSuite, SetCaptureVolumeStoreTarget) { + do_sys_init(); + cras_system_set_capture_gain_limits(-2000, 2000); + cras_system_set_capture_gain(3000); + // Gain is within the limit. + EXPECT_EQ(2000, cras_system_get_capture_gain()); + + // Assume the range is changed. + cras_system_set_capture_gain_limits(-4000, 4000); + + // Gain is also changed because target gain is re-applied. + EXPECT_EQ(3000, cras_system_get_capture_gain()); + + cras_system_state_deinit(); +} + +TEST(SystemStateSuite, SetMinMaxCaptureGain) { + do_sys_init(); + cras_system_set_capture_gain(3000); + cras_system_set_capture_gain_limits(-2000, 2000); + EXPECT_EQ(-2000, cras_system_get_min_capture_gain()); + EXPECT_EQ(2000, cras_system_get_max_capture_gain()); + // Current gain is adjusted for range. + EXPECT_EQ(2000, cras_system_get_capture_gain()); + cras_system_state_deinit(); +} + TEST(SystemStateSuite, SetUserMute) { ResetStubData(); do_sys_init(); @@ -279,7 +307,6 @@ TEST(SystemStateSuite, Suspend) { cras_system_set_suspended(1); EXPECT_EQ(1, cras_observer_notify_suspend_changed_called); - EXPECT_EQ(1, cras_alert_process_all_pending_alerts_called); EXPECT_EQ(1, cras_system_get_suspended()); cras_system_set_suspended(0); @@ -330,7 +357,7 @@ TEST(SystemSettingsRegisterSelectDescriptor, AddSelectFd) { ResetStubData(); do_sys_init(); - rc = cras_system_add_select_fd(7, callback_stub, stub_data, POLLIN); + rc = cras_system_add_select_fd(7, callback_stub, stub_data); EXPECT_NE(0, rc); EXPECT_EQ(0, add_stub_called); EXPECT_EQ(0, rm_stub_called); @@ -342,7 +369,7 @@ TEST(SystemSettingsRegisterSelectDescriptor, AddSelectFd) { EXPECT_EQ(-EEXIST, rc); EXPECT_EQ(0, add_stub_called); EXPECT_EQ(0, rm_stub_called); - rc = cras_system_add_select_fd(7, callback_stub, stub_data, POLLIN); + rc = cras_system_add_select_fd(7, callback_stub, stub_data); EXPECT_EQ(0, rc); EXPECT_EQ(1, add_stub_called); EXPECT_EQ(select_data, select_data_value); @@ -359,13 +386,13 @@ TEST(SystemSettingsAddTask, AddTask) { int rc; do_sys_init(); - rc = cras_system_add_task(task_stub, stub_data); + rc = cras_system_add_task(callback_stub, stub_data); EXPECT_NE(0, rc); EXPECT_EQ(0, add_task_stub_called); rc = cras_system_set_add_task_handler(add_task_stub, task_data); EXPECT_EQ(0, rc); EXPECT_EQ(0, add_task_stub_called); - rc = cras_system_add_task(task_stub, stub_data); + rc = cras_system_add_task(callback_stub, stub_data); EXPECT_EQ(0, rc); EXPECT_EQ(1, add_task_stub_called); EXPECT_EQ(task_data, task_data_value); @@ -378,11 +405,11 @@ TEST(SystemSettingsStreamCount, StreamCount) { do_sys_init(); EXPECT_EQ(0, cras_system_state_get_active_streams()); - cras_system_state_stream_added(CRAS_STREAM_OUTPUT, CRAS_CLIENT_TYPE_CHROME); + cras_system_state_stream_added(CRAS_STREAM_OUTPUT); EXPECT_EQ(1, cras_system_state_get_active_streams()); struct cras_timespec ts1; cras_system_state_get_last_stream_active_time(&ts1); - cras_system_state_stream_removed(CRAS_STREAM_OUTPUT, CRAS_CLIENT_TYPE_CHROME); + cras_system_state_stream_removed(CRAS_STREAM_OUTPUT); EXPECT_EQ(0, cras_system_state_get_active_streams()); struct cras_timespec ts2; cras_system_state_get_last_stream_active_time(&ts2); @@ -395,11 +422,9 @@ TEST(SystemSettingsStreamCount, StreamCountByDirection) { do_sys_init(); EXPECT_EQ(0, cras_system_state_get_active_streams()); - cras_system_state_stream_added(CRAS_STREAM_OUTPUT, CRAS_CLIENT_TYPE_CHROME); - cras_system_state_stream_added(CRAS_STREAM_INPUT, CRAS_CLIENT_TYPE_CHROME); - cras_system_state_stream_added(CRAS_STREAM_POST_MIX_PRE_DSP, - CRAS_CLIENT_TYPE_CHROME); - EXPECT_EQ(1, cras_observer_notify_input_streams_with_permission_called); + cras_system_state_stream_added(CRAS_STREAM_OUTPUT); + cras_system_state_stream_added(CRAS_STREAM_INPUT); + cras_system_state_stream_added(CRAS_STREAM_POST_MIX_PRE_DSP); EXPECT_EQ( 1, cras_system_state_get_active_streams_by_direction(CRAS_STREAM_OUTPUT)); EXPECT_EQ( @@ -408,11 +433,9 @@ TEST(SystemSettingsStreamCount, StreamCountByDirection) { CRAS_STREAM_POST_MIX_PRE_DSP)); EXPECT_EQ(3, cras_system_state_get_active_streams()); EXPECT_EQ(3, cras_observer_notify_num_active_streams_called); - cras_system_state_stream_removed(CRAS_STREAM_OUTPUT, CRAS_CLIENT_TYPE_CHROME); - cras_system_state_stream_removed(CRAS_STREAM_INPUT, CRAS_CLIENT_TYPE_CHROME); - cras_system_state_stream_removed(CRAS_STREAM_POST_MIX_PRE_DSP, - CRAS_CLIENT_TYPE_CHROME); - EXPECT_EQ(2, cras_observer_notify_input_streams_with_permission_called); + cras_system_state_stream_removed(CRAS_STREAM_OUTPUT); + cras_system_state_stream_removed(CRAS_STREAM_INPUT); + cras_system_state_stream_removed(CRAS_STREAM_POST_MIX_PRE_DSP); EXPECT_EQ( 0, cras_system_state_get_active_streams_by_direction(CRAS_STREAM_OUTPUT)); EXPECT_EQ( @@ -425,50 +448,12 @@ TEST(SystemSettingsStreamCount, StreamCountByDirection) { cras_system_state_deinit(); } -TEST(SystemStateSuite, IgnoreUCMSuffix) { - fake_board_config.ucm_ignore_suffix = strdup("TEST1,TEST2,TEST3"); - do_sys_init(); - - EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix("TEST1")); - EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix("TEST2")); - EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix("TEST3")); - EXPECT_EQ(0, cras_system_check_ignore_ucm_suffix("TEST4")); - cras_system_state_deinit(); -} - -TEST(SystemStateSuite, SetNoiseCancellationEnabled) { - ResetStubData(); - do_sys_init(); - - EXPECT_EQ(0, cras_system_get_noise_cancellation_enabled()); - - cras_system_set_noise_cancellation_enabled(0); - EXPECT_EQ(0, cras_system_get_noise_cancellation_enabled()); - EXPECT_EQ(0, cras_iodev_list_reset_for_noise_cancellation_called); - - cras_system_set_noise_cancellation_enabled(1); - EXPECT_EQ(1, cras_system_get_noise_cancellation_enabled()); - EXPECT_EQ(1, cras_iodev_list_reset_for_noise_cancellation_called); - - cras_system_set_noise_cancellation_enabled(1); - EXPECT_EQ(1, cras_system_get_noise_cancellation_enabled()); - // cras_iodev_list_reset_for_noise_cancellation shouldn't be called if state - // is already enabled/disabled. - EXPECT_EQ(1, cras_iodev_list_reset_for_noise_cancellation_called); - - cras_system_set_noise_cancellation_enabled(0); - EXPECT_EQ(0, cras_system_get_noise_cancellation_enabled()); - EXPECT_EQ(2, cras_iodev_list_reset_for_noise_cancellation_called); - - cras_system_state_deinit(); -} - extern "C" { struct cras_alsa_card* cras_alsa_card_create( struct cras_alsa_card_info* info, const char* device_config_dir, - struct cras_device_blocklist* blocklist) { + struct cras_device_blacklist* blacklist) { cras_alsa_card_create_called++; cras_alsa_card_config_dir = device_config_dir; return kFakeAlsaCard; @@ -482,12 +467,12 @@ size_t cras_alsa_card_get_index(const struct cras_alsa_card* alsa_card) { return 0; } -struct cras_device_blocklist* cras_device_blocklist_create( +struct cras_device_blacklist* cras_device_blacklist_create( const char* config_path) { return NULL; } -void cras_device_blocklist_destroy(struct cras_device_blocklist* blocklist) {} +void cras_device_blacklist_destroy(struct cras_device_blacklist* blacklist) {} struct cras_alert* cras_alert_create(cras_alert_prepare prepare, unsigned int flags) { @@ -536,6 +521,10 @@ void cras_observer_notify_output_mute(int muted, cras_observer_notify_output_mute_called++; } +void cras_observer_notify_capture_gain(int32_t gain) { + cras_observer_notify_capture_gain_called++; +} + void cras_observer_notify_capture_mute(int muted, int mute_locked) { cras_observer_notify_capture_mute_called++; } @@ -549,24 +538,6 @@ void cras_observer_notify_num_active_streams(enum CRAS_STREAM_DIRECTION dir, cras_observer_notify_num_active_streams_called++; } -void cras_observer_notify_input_streams_with_permission( - uint32_t num_input_streams[CRAS_NUM_CLIENT_TYPE]) { - cras_observer_notify_input_streams_with_permission_called++; -} - -void cras_board_config_get(const char* config_path, - struct cras_board_config* board_config) { - *board_config = fake_board_config; -} - -void cras_alert_process_all_pending_alerts() { - cras_alert_process_all_pending_alerts_called++; -} - -void cras_iodev_list_reset_for_noise_cancellation() { - cras_iodev_list_reset_for_noise_cancellation_called++; -} - } // extern "C" } // namespace diff --git a/cras/src/tests/timing_unittest.cc b/cras/src/tests/timing_unittest.cc index 964f30c3..beba2f72 100644 --- a/cras/src/tests/timing_unittest.cc +++ b/cras/src/tests/timing_unittest.cc @@ -93,9 +93,10 @@ class TimingSuite : public testing::Test { // Set response for frames_queued. iodev_stub_frames_queued(dev->dev.get(), dev_level, *level_timestamp); - struct timespec dev_time; + struct timespec dev_time, now; dev_time.tv_sec = level_timestamp->tv_sec + 500; // Far in the future. - dev_io_next_output_wake(&dev_list_, &dev_time); + clock_gettime(CLOCK_MONOTONIC_RAW, &now); + dev_io_next_output_wake(&dev_list_, &dev_time, &now); return dev_time; } }; @@ -111,21 +112,20 @@ int clock_gettime(clockid_t clk_id, struct timespec* tp) { // Add a new input stream, make sure the initial next_cb_ts is 0. TEST_F(TimingSuite, NewInputStreamInit) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; + struct open_dev* dev_list_ = NULL; cras_audio_format format; fill_audio_format(&format, 48000); DevicePtr dev = create_device(CRAS_STREAM_INPUT, 1024, &format, CRAS_NODE_TYPE_MIC); - DL_APPEND(idev_list_, dev->odev.get()); + DL_APPEND(dev_list_, dev->odev.get()); struct cras_iodev* iodev = dev->odev->dev; ShmPtr shm = create_shm(480); RstreamPtr rstream = create_rstream(1, CRAS_STREAM_INPUT, 480, &format, shm.get()); - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); + dev_io_append_stream(&dev_list_, rstream.get(), &iodev, 1); EXPECT_EQ(0, rstream->next_cb_ts.tv_sec); EXPECT_EQ(0, rstream->next_cb_ts.tv_nsec); @@ -807,68 +807,23 @@ TEST_F(TimingSuite, HotwordStreamBulkDataIsNotPending) { // When a new output stream is added, there are two rules to determine the // initial next_cb_ts. -// 1. If there is a matched input stream, use the next_cb_ts and -// sleep_interval_ts from that input stream as the initial values. -// 2. If the device already has streams, the next_cb_ts will be the earliest +// 1. If the device already has streams, the next_cb_ts will be the earliest // next callback time from these streams. -// 3. If there are no other streams, the next_cb_ts will be set to the time +// 2. If there are no other streams, the next_cb_ts will be set to the time // when the valid frames in device is lower than cb_threshold. (If it is // already lower than cb_threshold, set next_cb_ts to now.) // Test rule 1. -// There is a matched input stream. The next_cb_ts of the newly added output -// stream will use the next_cb_ts from the input stream. -TEST_F(TimingSuite, NewOutputStreamInitExistMatchedStream) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; - - cras_audio_format format; - fill_audio_format(&format, 48000); - DevicePtr out_dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, - CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, out_dev->odev.get()); - struct cras_iodev* out_iodev = out_dev->odev->dev; - - DevicePtr in_dev = - create_device(CRAS_STREAM_INPUT, 1024, &format, CRAS_NODE_TYPE_MIC); - DL_APPEND(idev_list_, in_dev->odev.get()); - - StreamPtr in_stream = create_stream(1, 1, CRAS_STREAM_INPUT, 480, &format); - add_stream_to_dev(in_dev->dev, in_stream); - in_stream->rstream->next_cb_ts.tv_sec = 54321; - in_stream->rstream->next_cb_ts.tv_nsec = 12345; - in_stream->rstream->sleep_interval_ts.tv_sec = 321; - in_stream->rstream->sleep_interval_ts.tv_nsec = 123; - - ShmPtr shm = create_shm(480); - RstreamPtr rstream = - create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &out_iodev, 1); - - EXPECT_EQ(in_stream->rstream->next_cb_ts.tv_sec, rstream->next_cb_ts.tv_sec); - EXPECT_EQ(in_stream->rstream->next_cb_ts.tv_nsec, - rstream->next_cb_ts.tv_nsec); - EXPECT_EQ(in_stream->rstream->sleep_interval_ts.tv_sec, - rstream->sleep_interval_ts.tv_sec); - EXPECT_EQ(in_stream->rstream->sleep_interval_ts.tv_nsec, - rstream->sleep_interval_ts.tv_nsec); - - dev_stream_destroy(out_iodev->streams); -} - -// Test rule 2. // The device already has streams, the next_cb_ts will be the earliest // next_cb_ts from these streams. TEST_F(TimingSuite, NewOutputStreamInitStreamInDevice) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; + struct open_dev* dev_list_ = NULL; cras_audio_format format; fill_audio_format(&format, 48000); DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, dev->odev.get()); + DL_APPEND(dev_list_, dev->odev.get()); struct cras_iodev* iodev = dev->odev->dev; StreamPtr stream = create_stream(1, 1, CRAS_STREAM_OUTPUT, 480, &format); @@ -880,7 +835,7 @@ TEST_F(TimingSuite, NewOutputStreamInitStreamInDevice) { RstreamPtr rstream = create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); + dev_io_append_stream(&dev_list_, rstream.get(), &iodev, 1); EXPECT_EQ(stream->rstream->next_cb_ts.tv_sec, rstream->next_cb_ts.tv_sec); EXPECT_EQ(stream->rstream->next_cb_ts.tv_nsec, rstream->next_cb_ts.tv_nsec); @@ -888,18 +843,17 @@ TEST_F(TimingSuite, NewOutputStreamInitStreamInDevice) { dev_stream_destroy(iodev->streams->next); } -// Test rule 3. +// Test rule 2. // The there are no streams and no frames in device buffer. The next_cb_ts // will be set to now. TEST_F(TimingSuite, NewOutputStreamInitNoStreamNoFramesInDevice) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; + struct open_dev* dev_list_ = NULL; cras_audio_format format; fill_audio_format(&format, 48000); DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, dev->odev.get()); + DL_APPEND(dev_list_, dev->odev.get()); struct cras_iodev* iodev = dev->odev->dev; struct timespec start; @@ -909,7 +863,7 @@ TEST_F(TimingSuite, NewOutputStreamInitNoStreamNoFramesInDevice) { RstreamPtr rstream = create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); + dev_io_append_stream(&dev_list_, rstream.get(), &iodev, 1); EXPECT_EQ(start.tv_sec, rstream->next_cb_ts.tv_sec); EXPECT_EQ(start.tv_nsec, rstream->next_cb_ts.tv_nsec); @@ -922,14 +876,13 @@ TEST_F(TimingSuite, NewOutputStreamInitNoStreamNoFramesInDevice) { // next_cb_ts will be set to the time that valid frames in device is lower // than cb_threshold. TEST_F(TimingSuite, NewOutputStreamInitNoStreamSomeFramesInDevice) { - struct open_dev* odev_list_ = NULL; - struct open_dev* idev_list_ = NULL; + struct open_dev* dev_list_ = NULL; cras_audio_format format; fill_audio_format(&format, 48000); DevicePtr dev = create_device(CRAS_STREAM_OUTPUT, 1024, &format, CRAS_NODE_TYPE_HEADPHONE); - DL_APPEND(odev_list_, dev->odev.get()); + DL_APPEND(dev_list_, dev->odev.get()); struct cras_iodev* iodev = dev->odev->dev; struct timespec start; @@ -941,7 +894,7 @@ TEST_F(TimingSuite, NewOutputStreamInitNoStreamSomeFramesInDevice) { RstreamPtr rstream = create_rstream(1, CRAS_STREAM_OUTPUT, 480, &format, shm.get()); - dev_io_append_stream(&odev_list_, &idev_list_, rstream.get(), &iodev, 1); + dev_io_append_stream(&dev_list_, rstream.get(), &iodev, 1); // The next_cb_ts should be 10ms from now. At that time there are // only 480 valid frames in the device. @@ -1210,12 +1163,6 @@ int input_data_put_for_stream(struct input_data* data, return 0; } -float input_data_get_software_gain_scaler(struct input_data* data, - float idev_sw_gain_scaler, - struct cras_rstream* stream) { - return 1.0; -} - struct cras_audio_format* cras_rstream_post_processing_format( const struct cras_rstream* stream, void* dev_ptr) { @@ -1226,15 +1173,6 @@ int cras_audio_thread_event_drop_samples() { return 0; } -int cras_audio_thread_event_severe_underrun() { - return 0; -} - -void* buffer_share_get_data(const struct buffer_share* mix, unsigned int id) { - return NULL; -}; -void cras_apm_list_start_apm(struct cras_apm_list* list, void* dev_ptr){}; -void cras_apm_list_stop_apm(struct cras_apm_list* list, void* dev_ptr){}; } // extern "C" } // namespace diff --git a/cras/src/tools/cras_monitor/cras_monitor.c b/cras/src/tools/cras_monitor/cras_monitor.c index 19252773..d021669a 100644 --- a/cras/src/tools/cras_monitor/cras_monitor.c +++ b/cras/src/tools/cras_monitor/cras_monitor.c @@ -31,6 +31,11 @@ static void output_mute_changed(void *context, int muted, int user_muted, muted, user_muted, mute_locked); } +static void capture_gain_changed(void *context, int32_t gain) +{ + printf("capture gain: %d\n", gain); +} + static void capture_mute_changed(void *context, int muted, int mute_locked) { printf("capture mute: muted: %d, mute_locked: %d\n", muted, @@ -266,6 +271,8 @@ int main(int argc, char **argv) output_volume_changed); cras_client_set_output_mute_changed_callback(client, output_mute_changed); + cras_client_set_capture_gain_changed_callback(client, + capture_gain_changed); cras_client_set_capture_mute_changed_callback(client, capture_mute_changed); cras_client_set_nodes_changed_callback(client, nodes_changed); diff --git a/cras/src/tools/cras_test_client/cras_test_client.c b/cras/src/tools/cras_test_client/cras_test_client.c index 7a851852..a7845069 100644 --- a/cras/src/tools/cras_test_client/cras_test_client.c +++ b/cras/src/tools/cras_test_client/cras_test_client.c @@ -310,7 +310,7 @@ put_stdin_samples(struct cras_client *client, cras_stream_id_t stream_id, int rc = 0; uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format); - rc = read(0, playback_samples, (size_t)frames * (size_t)frame_bytes); + rc = read(0, playback_samples, frames * frame_bytes); if (rc <= 0) { terminate_stream_loop(); return -1; @@ -354,50 +354,30 @@ static void print_dev_info(const struct cras_iodev_info *devs, int num_devs) { unsigned i; - printf("\tID\tMaxCha\tName\n"); + printf("\tID\tName\n"); for (i = 0; i < num_devs; i++) - printf("\t%u\t%u\t%s\n", devs[i].idx, - devs[i].max_supported_channels, devs[i].name); + printf("\t%u\t%s\n", devs[i].idx, devs[i].name); } -static void print_node_info(struct cras_client *client, - const struct cras_ionode_info *nodes, int num_nodes, +static void print_node_info(const struct cras_ionode_info *nodes, int num_nodes, int is_input) { unsigned i; - printf("\tStable Id\t ID\t%4s UI Plugged\tL/R swapped\t " - "Time Hotword\tType\t\tMaxCha Name\n", + printf("\tStable Id\t ID\t%4s Plugged\tL/R swapped\t " + "Time Hotword\tType\t\t Name\n", is_input ? "Gain" : " Vol"); - for (i = 0; i < num_nodes; i++) { - char max_channels_str[7]; - if (is_input) { - // Print "X" as don't-care for input nodes because - // cras_client_get_max_supported_channels() is only valid for outputs. - strcpy(max_channels_str, " X"); - } else { - uint32_t max_channels; - int rc = cras_client_get_max_supported_channels( - client, - cras_make_node_id(nodes[i].iodev_idx, - nodes[i].ionode_idx), - &max_channels); - if (rc) - max_channels = 0; - sprintf(max_channels_str, "%6u", max_channels); - } - printf("\t(%08x)\t%u:%u\t%5g %f %7s\t%14s\t%10ld %-7s\t%-16s%-6s%c%s\n", + for (i = 0; i < num_nodes; i++) + printf("\t(%08x)\t%u:%u\t%5g %7s\t%14s\t%10ld %-7s\t%-16s%c%s\n", nodes[i].stable_id, nodes[i].iodev_idx, nodes[i].ionode_idx, is_input ? nodes[i].capture_gain / 100.0 : (double)nodes[i].volume, - nodes[i].ui_gain_scaler, nodes[i].plugged ? "yes" : "no", + nodes[i].plugged ? "yes" : "no", nodes[i].left_right_swapped ? "yes" : "no", (long)nodes[i].plugged_time.tv_sec, nodes[i].active_hotword_model, nodes[i].type, - max_channels_str, nodes[i].active ? '*' : ' ', - nodes[i].name); - } + nodes[i].active ? '*' : ' ', nodes[i].name); } static void print_device_lists(struct cras_client *client) @@ -416,7 +396,7 @@ static void print_device_lists(struct cras_client *client) printf("Output Devices:\n"); print_dev_info(devs, num_devs); printf("Output Nodes:\n"); - print_node_info(client, nodes, num_nodes, 0); + print_node_info(nodes, num_nodes, 0); num_devs = MAX_IODEVS; num_nodes = MAX_IONODES; @@ -425,7 +405,7 @@ static void print_device_lists(struct cras_client *client) printf("Input Devices:\n"); print_dev_info(devs, num_devs); printf("Input Nodes:\n"); - print_node_info(client, nodes, num_nodes, 1); + print_node_info(nodes, num_nodes, 1); } static void print_attached_client_list(struct cras_client *client) @@ -460,11 +440,13 @@ static void print_active_stream_info(struct cras_client *client) static void print_system_volumes(struct cras_client *client) { printf("System Volume (0-100): %zu %s\n" - "Capture Muted : %s\n", + "Capture Gain (%.2f - %.2f): %.2fdB %s\n", cras_client_get_system_volume(client), cras_client_get_system_muted(client) ? "(Muted)" : "", - cras_client_get_system_capture_muted(client) ? "Muted" : - "Not muted"); + cras_client_get_system_min_capture_gain(client) / 100.0, + cras_client_get_system_max_capture_gain(client) / 100.0, + cras_client_get_system_capture_gain(client) / 100.0, + cras_client_get_system_capture_muted(client) ? "(Muted)" : ""); } static void print_user_muted(struct cras_client *client) @@ -493,26 +475,6 @@ static void convert_time(unsigned int *sec, unsigned int *nsec, *nsec = nsec_offset; } -static float get_ewma_power_as_float(uint32_t data) -{ - float f = 0.0f; - - /* Convert from the uint32_t log type back to float. - * If data cannot be assigned to float, default value will - * be printed as -inf to hint the problem. - */ - if (sizeof(uint32_t) == sizeof(float)) - memcpy(&f, &data, sizeof(float)); - else - printf("%-30s float to uint32_t\n", "MEMORY_NOT_ALIGNED"); - - /* Convert to dBFS and set to zero if it's - * insignificantly low. Picking the same threshold - * 1.0e-10f as in Chrome. - */ - return (f < 1.0e-10f) ? -INFINITY : 10.0f * log10f(f); -} - static void show_alog_tag(const struct audio_thread_event_log *log, unsigned int tag_idx, int32_t sec_offset, int32_t nsec_offset) @@ -524,23 +486,22 @@ static void show_alog_tag(const struct audio_thread_event_log *log, unsigned int data2 = log->log[tag_idx].data2; unsigned int data3 = log->log[tag_idx].data3; time_t lt; - struct tm t; + struct tm *t; /* Skip unused log entries. */ if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0) return; - /* Convert from monotonic raw clock to realtime clock. */ + /* Convert from monotomic raw clock to realtime clock. */ convert_time(&sec, &nsec, sec_offset, nsec_offset); lt = sec; - localtime_r(<, &t); - strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t); + t = localtime(<); + strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", t); printf("%s.%09u cras atlog ", time_str, nsec); /* Prepare realtime string for arguments. */ switch (tag) { - case AUDIO_THREAD_A2DP_FLUSH: case AUDIO_THREAD_READ_AUDIO_TSTAMP: case AUDIO_THREAD_FILL_AUDIO_TSTAMP: case AUDIO_THREAD_STREAM_RESCHEDULE: @@ -553,16 +514,16 @@ static void show_alog_tag(const struct audio_thread_event_log *log, } convert_time(&sec, &nsec, sec_offset, nsec_offset); lt = sec; - localtime_r(<, &t); - strftime(time_str, 128, " %H:%M:%S", &t); + t = localtime(<); + strftime(time_str, 128, " %H:%M:%S", t); switch (tag) { case AUDIO_THREAD_WAKE: printf("%-30s num_fds:%d\n", "WAKE", (int)data1); break; case AUDIO_THREAD_SLEEP: - printf("%-30s sleep:%09d.%09d non_empty %u\n", "SLEEP", - (int)data1, (int)data2, (int)data3); + printf("%-30s sleep:%09d.%09d\n", "SLEEP", (int)data1, + (int)data2); break; case AUDIO_THREAD_READ_AUDIO: printf("%-30s dev:%u hw_level:%u read:%u\n", "READ_AUDIO", @@ -572,30 +533,25 @@ static void show_alog_tag(const struct audio_thread_event_log *log, printf("%-30s dev:%u tstamp:%s.%09u\n", "READ_AUDIO_TSTAMP", data1, time_str, nsec); break; - case AUDIO_THREAD_READ_AUDIO_DONE: { - float f = get_ewma_power_as_float(data2); - printf("%-30s read_remainder:%u power:%f dBFS\n", - "READ_AUDIO_DONE", data1, f); + case AUDIO_THREAD_READ_AUDIO_DONE: + printf("%-30s read_remainder:%u\n", "READ_AUDIO_DONE", data1); break; - } case AUDIO_THREAD_READ_OVERRUN: printf("%-30s dev:%u stream:%x num_overruns:%u\n", "READ_AUDIO_OVERRUN", data1, data2, data3); break; case AUDIO_THREAD_FILL_AUDIO: - printf("%-30s dev:%u hw_level:%u min_cb_level:%u\n", - "FILL_AUDIO", data1, data2, data3); + printf("%-30s dev:%u hw_level:%u\n", "FILL_AUDIO", data1, + data2); break; case AUDIO_THREAD_FILL_AUDIO_TSTAMP: printf("%-30s dev:%u tstamp:%s.%09u\n", "FILL_AUDIO_TSTAMP", data1, time_str, nsec); break; - case AUDIO_THREAD_FILL_AUDIO_DONE: { - float f = get_ewma_power_as_float(data3); - printf("%-30s hw_level:%u total_written:%u power:%f dBFS\n", - "FILL_AUDIO_DONE", data1, data2, f); + case AUDIO_THREAD_FILL_AUDIO_DONE: + printf("%-30s hw_level:%u total_written:%u min_cb_level:%u\n", + "FILL_AUDIO_DONE", data1, data2, data3); break; - } case AUDIO_THREAD_WRITE_STREAMS_WAIT: printf("%-30s stream:%x\n", "WRITE_STREAMS_WAIT", data1); break; @@ -613,26 +569,19 @@ static void show_alog_tag(const struct audio_thread_event_log *log, printf("%-30s id:%x shm_frames:%u cb_pending:%u\n", "WRITE_STREAMS_STREAM", data1, data2, data3); break; - case AUDIO_THREAD_FETCH_STREAM: { - float f = get_ewma_power_as_float(data3); - printf("%-30s id:%x cbth:%u power:%f dBFS\n", - "WRITE_STREAMS_FETCH_STREAM", data1, data2, f); + case AUDIO_THREAD_FETCH_STREAM: + printf("%-30s id:%x cbth:%u delay:%u\n", + "WRITE_STREAMS_FETCH_STREAM", data1, data2, data3); break; - } case AUDIO_THREAD_STREAM_ADDED: printf("%-30s id:%x dev:%u\n", "STREAM_ADDED", data1, data2); break; case AUDIO_THREAD_STREAM_REMOVED: printf("%-30s id:%x\n", "STREAM_REMOVED", data1); break; - break; - case AUDIO_THREAD_A2DP_FLUSH: - printf("%-30s state %u next flush time:%s.%09u\n", "A2DP_FLUSH", - data1, time_str, nsec); - break; - case AUDIO_THREAD_A2DP_THROTTLE_TIME: - printf("%-30s %u ms, queued:%u\n", "A2DP_THROTTLE_TIME", - data1 * 1000 + data2 / 1000000, data3); + case AUDIO_THREAD_A2DP_ENCODE: + printf("%-30s proc:%d queued:%u readable:%u\n", "A2DP_ENCODE", + data1, data2, data3); break; case AUDIO_THREAD_A2DP_WRITE: printf("%-30s written:%d queued:%u\n", "A2DP_WRITE", data1, @@ -688,8 +637,7 @@ static void show_alog_tag(const struct audio_thread_event_log *log, printf("%-30s dev:%u\n", "DEV_REMOVED", data1); break; case AUDIO_THREAD_IODEV_CB: - printf("%-30s revents:%u events:%u\n", "IODEV_CB", data1, - data2); + printf("%-30s is_write:%u\n", "IODEV_CB", data1); break; case AUDIO_THREAD_PB_MSG: printf("%-30s msg_id:%u\n", "PB_MSG", data1); @@ -727,21 +675,6 @@ static void show_alog_tag(const struct audio_thread_event_log *log, printf("%-30s dev:%u frames:%u\n", "DEV_DROP_FRAMES", data1, data2); break; - case AUDIO_THREAD_LOOPBACK_PUT: - printf("%-30s nframes_committed:%u\n", "LOOPBACK_PUT", data1); - break; - case AUDIO_THREAD_LOOPBACK_GET: - printf("%-30s nframes_requested:%u avail:%u\n", "LOOPBACK_GET", - data1, data2); - break; - case AUDIO_THREAD_LOOPBACK_SAMPLE_HOOK: - printf("%-30s frames_to_copy:%u frames_copied:%u\n", - "LOOPBACK_SAMPLE", data1, data2); - break; - case AUDIO_THREAD_DEV_OVERRUN: - printf("%-30s dev:%u hw_level:%u\n", "DEV_OVERRUN", data1, - data2); - break; default: printf("%-30s tag:%u\n", "UNKNOWN", tag); break; @@ -802,8 +735,8 @@ static void print_audio_debug_info(const struct audio_debug_info *info) for (i = 0; i < info->num_streams; i++) { int channel; - printf("stream: 0x%" PRIx64 " dev: %u\n", - info->streams[i].stream_id, + printf("stream: %llu dev: %u\n", + (unsigned long long)info->streams[i].stream_id, (unsigned int)info->streams[i].dev_idx); printf("direction: %s\n", (info->streams[i].direction == CRAS_STREAM_INPUT) ? @@ -875,92 +808,6 @@ static void audio_debug_info(struct cras_client *client) pthread_mutex_unlock(&done_mutex); } -static void show_mainlog_tag(const struct main_thread_event_log *log, - unsigned int tag_idx, int32_t sec_offset, - int32_t nsec_offset) -{ - unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff; - unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff; - unsigned int nsec = log->log[tag_idx].nsec; - unsigned int data1 = log->log[tag_idx].data1; - unsigned int data2 = log->log[tag_idx].data2; - unsigned int data3 = log->log[tag_idx].data3; - time_t lt; - struct tm t; - - /* Skip unused log entries. */ - if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0) - return; - - /* Convert from monotomic raw clock to realtime clock. */ - convert_time(&sec, &nsec, sec_offset, nsec_offset); - lt = sec; - localtime_r(<, &t); - strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t); - - printf("%s.%09u cras mainlog ", time_str, nsec); - - switch (tag) { - case MAIN_THREAD_DEV_CLOSE: - printf("%-30s dev %u\n", "DEV_CLOSE", data1); - break; - case MAIN_THREAD_DEV_DISABLE: - printf("%-30s dev %u force %u\n", "DEV_DISABLE", data1, data2); - break; - case MAIN_THREAD_DEV_INIT: - printf("%-30s dev %u ch %u rate %u\n", "DEV_INIT", data1, data2, - data3); - break; - case MAIN_THREAD_DEV_REOPEN: - printf("%-30s new ch %u old ch %u rate %u\n", "DEV_REOPEN", - data1, data2, data3); - break; - case MAIN_THREAD_ADD_ACTIVE_NODE: - printf("%-30s dev %u\n", "ADD_ACTIVE_NODE", data1); - break; - case MAIN_THREAD_SELECT_NODE: - printf("%-30s dev %u\n", "SELECT_NODE", data1); - break; - case MAIN_THREAD_ADD_TO_DEV_LIST: - printf("%-30s dev %u %s\n", "ADD_TO_DEV_LIST", data1, - (data2 == CRAS_STREAM_OUTPUT) ? "output" : "input"); - break; - case MAIN_THREAD_NODE_PLUGGED: - printf("%-30s dev %u %s\n", "NODE_PLUGGED", data1, - data2 ? "plugged" : "unplugged"); - break; - case MAIN_THREAD_INPUT_NODE_GAIN: - printf("%-30s dev %u gain %u\n", "INPUT_NODE_GAIN", data1, - data2); - break; - case MAIN_THREAD_OUTPUT_NODE_VOLUME: - printf("%-30s dev %u volume %u\n", "OUTPUT_NODE_VOLUME", data1, - data2); - break; - case MAIN_THREAD_SET_OUTPUT_USER_MUTE: - printf("%-30s mute %u\n", "SET_OUTPUT_USER_MUTE", data1); - break; - case MAIN_THREAD_RESUME_DEVS: - printf("RESUME_DEVS\n"); - break; - case MAIN_THREAD_SUSPEND_DEVS: - printf("SUSPEND_DEVS\n"); - break; - case MAIN_THREAD_STREAM_ADDED: - printf("%-30s %s stream 0x%x buffer frames %u\n", - "STREAM_ADDED", - (data2 == CRAS_STREAM_OUTPUT ? "output" : "input"), - data1, data3); - break; - case MAIN_THREAD_STREAM_REMOVED: - printf("%-30s stream 0x%x\n", "STREAM_REMOVED", data1); - break; - default: - printf("%-30s\n", "UNKNOWN"); - break; - } -} - static void show_btlog_tag(const struct cras_bt_event_log *log, unsigned int tag_idx, int32_t sec_offset, int32_t nsec_offset) @@ -971,17 +818,17 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, unsigned int data1 = log->log[tag_idx].data1; unsigned int data2 = log->log[tag_idx].data2; time_t lt; - struct tm t; + struct tm *t; /* Skip unused log entries. */ if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0) return; - /* Convert from monotonic raw clock to realtime clock. */ + /* Convert from monotomic raw clock to realtime clock. */ convert_time(&sec, &nsec, sec_offset, nsec_offset); lt = sec; - localtime_r(<, &t); - strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t); + t = localtime(<); + strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", t); printf("%s.%09u cras btlog ", time_str, nsec); @@ -993,7 +840,7 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, printf("%-30s\n", "ADAPTER_REMOVED"); break; case BT_A2DP_CONFIGURED: - printf("%-30s connected profiles 0x%.2x\n", "A2DP_CONFIGURED", + printf("%-30s connected profiles %u\n", "A2DP_CONFIGURED", data1); break; case BT_A2DP_START: @@ -1003,8 +850,8 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, printf("%-30s\n", "A2DP_SUSPENDED"); break; case BT_AUDIO_GATEWAY_INIT: - printf("%-30s supported profiles 0x%.2x\n", - "AUDIO_GATEWAY_INIT", data1); + printf("%-30s supported profiles %u\n", "AUDIO_GATEWAY_INIT", + data1); break; case BT_AUDIO_GATEWAY_START: printf("%-30s \n", "AUDIO_GATEWAY_START"); @@ -1017,34 +864,18 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, printf("%-30s dir %u codec id %u\n", "CODEC_SELECTION", data1, data2); break; - case BT_DEV_CONNECTED: - printf("%-30s supported profiles 0x%.2x stable_id 0x%08x\n", - "DEV_CONNECTED", data1, data2); - break; - case BT_DEV_DISCONNECTED: - printf("%-30s supported profiles 0x%.2x stable_id 0x%08x\n", - "DEV_DISCONNECTED", data1, data2); + case BT_DEV_CONNECTED_CHANGE: + printf("%-30s profiles %u now %u\n", "DEV_CONENCTED_CHANGE", + data1, data2); break; case BT_DEV_CONN_WATCH_CB: - printf("%-30s %u retries left, supported profiles 0x%.2x\n", + printf("%-30s %u retries left, supported profiles %u\n", "DEV_CONN_WATCH_CB", data1, data2); break; case BT_DEV_SUSPEND_CB: - printf("%-30s profiles supported %u, reason %u\n", + printf("%-30s profiles supported %u, connected %u\n", "DEV_SUSPEND_CB", data1, data2); break; - case BT_HFP_HF_INDICATOR: - printf("%-30s HF read AG %s indicator\n", "HFP_HF_INDICATOR", - data1 ? "enabled" : "supported"); - break; - case BT_HFP_SET_SPEAKER_GAIN: - printf("%-30s HF set speaker gain %u\n", "HFP_SET_SPEAKER_GAIN", - data1); - break; - case BT_HFP_UPDATE_SPEAKER_GAIN: - printf("%-30s HF update speaker gain %u\n", - "HFP_UPDATE_SPEAKER_GAIN", data1); - break; case BT_HFP_NEW_CONNECTION: printf("%-30s\n", "HFP_NEW_CONNECTION"); break; @@ -1052,8 +883,8 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, printf("%-30s\n", "HFP_REQUEST_DISCONNECT"); break; case BT_HFP_SUPPORTED_FEATURES: - printf("%-30s role %s features 0x%.4x\n", - "HFP_SUPPORTED_FEATURES", data1 ? "AG" : "HF", data2); + printf("%-30s role %s features %u\n", "HFP_SUPPORTED_FEATURES", + data1 ? "AG" : "HF", data2); break; case BT_HSP_NEW_CONNECTION: printf("%-30s\n", "HSP_NEW_CONNECTION"); @@ -1062,7 +893,7 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, printf("%-30s\n", "HSP_REQUEST_DISCONNECT"); break; case BT_NEW_AUDIO_PROFILE_AFTER_CONNECT: - printf("%-30s old 0x%.2x, new 0x%.2x\n", + printf("%-30s old %u, new %u\n", "NEW_AUDIO_PROFILE_AFTER_CONNECT", data1, data2); break; case BT_RESET: @@ -1079,42 +910,18 @@ static void show_btlog_tag(const struct cras_bt_event_log *log, case BT_TRANSPORT_RELEASE: printf("%-30s\n", "TRANSPORT_RELEASE"); break; - case BT_TRANSPORT_SET_VOLUME: - printf("%-30s %d\n", "TRANSPORT_SET_VOLUME", data1); - break; - case BT_TRANSPORT_UPDATE_VOLUME: - printf("%-30s %d\n", "TRANSPORT_UPDATE_VOLUME", data1); - break; default: printf("%-30s\n", "UNKNOWN"); break; } } -static void convert_to_time_str(const struct timespec *ts, time_t sec_offset, - int32_t nsec_offset) -{ - time_t lt = ts->tv_sec; - struct tm t; - unsigned int time_nsec; - - /* Assuming tv_nsec doesn't exceed 10^9 */ - time_nsec = ts->tv_nsec; - convert_time((unsigned int *)<, &time_nsec, sec_offset, nsec_offset); - localtime_r(<, &t); - strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t); - snprintf(time_str + strlen(time_str), 128 - strlen(time_str), ".%09u", - time_nsec); -} - static void cras_bt_debug_info(struct cras_client *client) { const struct cras_bt_debug_info *info; time_t sec_offset; int32_t nsec_offset; int i, j; - struct timespec ts; - struct packet_status_logger wbs_logger; info = cras_client_get_bt_debug_info(client); fill_time_offset(&sec_offset, &nsec_offset); @@ -1127,47 +934,6 @@ static void cras_bt_debug_info(struct cras_client *client) j %= info->bt_log.len; } - printf("-------------WBS packet loss------------\n"); - wbs_logger = info->wbs_logger; - - packet_status_logger_begin_ts(&wbs_logger, &ts); - convert_to_time_str(&ts, sec_offset, nsec_offset); - printf("%s [begin]\n", time_str); - - packet_status_logger_end_ts(&wbs_logger, &ts); - convert_to_time_str(&ts, sec_offset, nsec_offset); - printf("%s [end]\n", time_str); - - printf("In hex format:\n"); - packet_status_logger_dump_hex(&wbs_logger); - - printf("In binary format:\n"); - packet_status_logger_dump_binary(&wbs_logger); - - /* Signal main thread we are done after the last chunk. */ - pthread_mutex_lock(&done_mutex); - pthread_cond_signal(&done_cond); - pthread_mutex_unlock(&done_mutex); -} - -static void main_thread_debug_info(struct cras_client *client) -{ - const struct main_thread_debug_info *info; - time_t sec_offset; - int32_t nsec_offset; - int i, j; - - info = cras_client_get_main_thread_debug_info(client); - fill_time_offset(&sec_offset, &nsec_offset); - j = info->main_log.write_pos; - i = 0; - printf("Main debug log:\n"); - for (; i < info->main_log.len; i++) { - show_mainlog_tag(&info->main_log, j, sec_offset, nsec_offset); - j++; - j %= info->main_log.len; - } - /* Signal main thread we are done after the last chunk. */ pthread_mutex_lock(&done_mutex); pthread_cond_signal(&done_cond); @@ -1184,9 +950,6 @@ static void print_cras_audio_thread_snapshot( printf("Event type: "); switch (snapshot->event_type) { - case AUDIO_THREAD_EVENT_A2DP_THROTTLE: - printf("a2dp throttle\n"); - break; case AUDIO_THREAD_EVENT_BUSYLOOP: printf("busyloop\n"); break; @@ -1199,9 +962,6 @@ static void print_cras_audio_thread_snapshot( case AUDIO_THREAD_EVENT_DROP_SAMPLES: printf("drop samples\n"); break; - case AUDIO_THREAD_EVENT_DEV_OVERRUN: - printf("device overrun\n"); - break; case AUDIO_THREAD_EVENT_DEBUG: printf("debug\n"); break; @@ -1309,6 +1069,7 @@ static int run_file_io_stream(struct cras_client *client, int fd, struct timespec sleep_ts; float volume_scaler = 1.0; size_t sys_volume = 100; + long cap_gain = 0; int mute = 0; int8_t layout[CRAS_CH_MAX]; @@ -1457,6 +1218,14 @@ static int run_file_io_stream(struct cras_client *client, int fd, sys_volume = sys_volume == 0 ? 0 : sys_volume - 1; cras_client_set_system_volume(client, sys_volume); break; + case 'K': + cap_gain = MIN(cap_gain + 100, 5000); + cras_client_set_system_capture_gain(client, cap_gain); + break; + case 'J': + cap_gain = cap_gain == -5000 ? -5000 : cap_gain - 100; + cras_client_set_system_capture_gain(client, cap_gain); + break; case 'm': mute = !mute; cras_client_set_system_mute(client, mute); @@ -1469,16 +1238,19 @@ static int run_file_io_stream(struct cras_client *client, int fd, break; case 'v': printf("Volume: %zu%s Min dB: %ld Max dB: %ld\n" - "Capture: %s\n", + "Capture: %ld%s Min dB: %ld Max dB: %ld\n", cras_client_get_system_volume(client), cras_client_get_system_muted(client) ? "(Muted)" : "", cras_client_get_system_min_volume(client), cras_client_get_system_max_volume(client), + cras_client_get_system_capture_gain(client), cras_client_get_system_capture_muted(client) ? - "Muted" : - "Not muted"); + "(Muted)" : + "", + cras_client_get_system_min_capture_gain(client), + cras_client_get_system_max_capture_gain(client)); break; case '\'': play_short_sound_periods_left = @@ -1607,22 +1379,6 @@ static void show_cras_bt_debug_info(struct cras_client *client) pthread_mutex_unlock(&done_mutex); } -static void show_main_thread_debug_info(struct cras_client *client) -{ - struct timespec wait_time; - cras_client_run_thread(client); - cras_client_connected_wait(client); /* To synchronize data. */ - cras_client_update_main_thread_debug_info(client, - main_thread_debug_info); - - clock_gettime(CLOCK_REALTIME, &wait_time); - wait_time.tv_sec += 2; - - pthread_mutex_lock(&done_mutex); - pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time); - pthread_mutex_unlock(&done_mutex); -} - static void hotword_models_cb(struct cras_client *client, const char *hotword_models) { @@ -1653,7 +1409,7 @@ static void check_output_plugged(struct cras_client *client, const char *name) cras_client_output_dev_plugged(client, name) ? "Yes" : "No"); } -/* Repeatedly mute and un-mute the output until there is an error. */ +/* Repeatedly mute and unmute the output until there is an error. */ static void mute_loop_test(struct cras_client *client, int auto_reconnect) { int mute = 0; @@ -1718,9 +1474,6 @@ static void cras_show_continuous_atlog(struct cras_client *client) fill_time_offset(&sec_offset, &nsec_offset); - /* Set stdout buffer to line buffered mode. */ - setlinebuf(stdout); - while (1) { len = cras_client_read_atlog(client, &atlog_read_idx, &missing, &log); @@ -1794,7 +1547,6 @@ static struct option long_options[] = { {"connection_type", required_argument, 0, 'K'}, {"loopback_file", required_argument, 0, 'L'}, {"mute_loop_test", required_argument, 0, 'M'}, - {"dump_main", no_argument, 0, 'N'}, {"playback_file", required_argument, 0, 'P'}, {"stream_type", required_argument, 0, 'T'}, {0, 0, 0, 0} @@ -1818,7 +1570,7 @@ static void show_usage() printf("--capture_file <name> - " "Name of file to record to.\n"); printf("--capture_gain <dB> - " - "Set system capture gain in dB*100 (100 = 1dB).\n"); + "Set system caputre gain in dB*100 (100 = 1dB).\n"); printf("--capture_mute <0|1> - " "Set capture mute state.\n"); printf("--channel_layout <layout_str> - " @@ -1832,17 +1584,11 @@ static void show_usage() " " " 1 - For playback client.\n" " " - " 2 - For capture client.\n" - " " - " 3 - For legacy client in vms.\n" - " " - " 4 - For unified client in vms.\n"); + " 2 - For capture client.\n"); printf("--dump_audio_thread - " "Dumps audio thread info.\n"); printf("--dump_bt - " "Dumps debug info for bt audio\n"); - printf("--dump_main - " - "Dumps debug info from main thread\n"); printf("--dump_dsp - " "Print status of dsp to syslog.\n"); printf("--dump_server_info - " @@ -1867,7 +1613,7 @@ static void show_usage() printf("--mute <0|1> - " "Set system mute state.\n"); printf("--mute_loop_test <0|1> - " - "Continuously loop mute/un-mute.\n" + "Continuously loop mute/umute.\n" " " "Argument: 0 - stop on error.\n" " " @@ -1921,7 +1667,7 @@ static void show_usage() printf("--suspend <0|1> - " "Set audio suspend state.\n"); printf("--swap_left_right <N>:<M>:<0|1> - " - "Swap or un-swap (1 or 0) the left and right channel for the " + "Swap or unswap (1 or 0) the left and right channel for the " "ionode with the given index M on the device with index N\n"); printf("--stream_type <N> - " "Specify the type of the stream.\n"); @@ -2044,6 +1790,15 @@ int main(int argc, char **argv) } break; } + case 'g': { + long gain = atol(optarg); + rc = cras_client_set_system_capture_gain(client, gain); + if (rc < 0) { + fprintf(stderr, "problem setting capture\n"); + goto destroy_exit; + } + break; + } case 'h': show_usage(); break; @@ -2240,8 +1995,7 @@ int main(int argc, char **argv) s = strtok(optarg, ":"); nch = atoi(s); - coeff = (float *)calloc((size_t)nch * (size_t)nch, - sizeof(*coeff)); + coeff = (float *)calloc(nch * nch, sizeof(*coeff)); for (size = 0; size < nch * nch; size++) { s = strtok(NULL, ","); if (NULL == s) @@ -2362,9 +2116,6 @@ int main(int argc, char **argv) case 'M': mute_loop_test(client, atoi(optarg)); break; - case 'N': - show_main_thread_debug_info(client); - break; case 'P': playback_file = optarg; break; @@ -2377,15 +2128,6 @@ int main(int argc, char **argv) } } - if (optind < argc) { - printf("Warning: un-welcome arguments: "); - while (optind < argc) - printf("%s ", argv[optind++]); - printf("\n"); - rc = 1; - goto destroy_exit; - } - duration_frames = duration_seconds * rate; if (block_size == NOT_ASSIGNED) block_size = get_block_size(PLAYBACK_BUFFERED_TIME_IN_US, rate); diff --git a/cros_alsa/.gitignore b/cros_alsa/.gitignore deleted file mode 100644 index b659239f..00000000 --- a/cros_alsa/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target/ -.*.rustfmt -Cargo.lock diff --git a/cros_alsa/.rustfmt.toml b/cros_alsa/.rustfmt.toml deleted file mode 100644 index a2db3012..00000000 --- a/cros_alsa/.rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -use_field_init_shorthand = true -use_try_shorthand = true diff --git a/cros_alsa/Cargo.toml b/cros_alsa/Cargo.toml deleted file mode 100644 index 2e006e40..00000000 --- a/cros_alsa/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "cros_alsa" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" -description = "The Chromium OS alsa-lib wrapper" - -[dependencies] -alsa-sys = "0.2.0" -cros_alsa_derive = "*" -libc = "0.2.65" -remain = "0.2.1" - -[patch.crates-io] -cros_alsa_derive = { path = "cros_alsa_derive" } diff --git a/cros_alsa/cros_alsa_derive/Cargo.toml b/cros_alsa/cros_alsa_derive/Cargo.toml deleted file mode 100644 index 6a4da288..00000000 --- a/cros_alsa/cros_alsa_derive/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "cros_alsa_derive" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" -description = "Derive macros of cors_alsa." - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "^1" -quote = "^1" -syn = "^1" diff --git a/cros_alsa/cros_alsa_derive/src/common.rs b/cros_alsa/cros_alsa_derive/src/common.rs deleted file mode 100644 index 2daaa3be..00000000 --- a/cros_alsa/cros_alsa_derive/src/common.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! This mod provides common constants, structs and functions used across cros_alsa_derive. -use std::convert::TryFrom; - -use syn::{Lit, Meta, NestedMeta, Result}; - -/// Attribute name of cros_alsa. -const CROS_ALSA: &str = "cros_alsa"; - -/// const for `#[cros_alsa(path = "...")]` -const PATH: &str = "path"; - -/// Possible `#[cros_alsa("...")]` derive macro helper attributes. -pub enum CrosAlsaAttr { - /// Use `#[cros_alsa(path = "crate")]` to replace the crate path of cros_alsa in derive macros. - Path(syn::Path), -} - -impl CrosAlsaAttr { - /// Return true if the value is a `Path` variant. - pub fn is_path(&self) -> bool { - use CrosAlsaAttr::*; - match self { - Path(_) => true, - // suppress unreachable_patterns warning because there is only one CrosAlsaAttr variant. - #[allow(unreachable_patterns)] - _ => false, - } - } -} - -impl TryFrom<syn::NestedMeta> for CrosAlsaAttr { - type Error = syn::Error; - fn try_from(meta_item: NestedMeta) -> Result<CrosAlsaAttr> { - match meta_item { - // Parse `#[cros_alsa(path = "crate")]` - NestedMeta::Meta(Meta::NameValue(m)) if m.path.is_ident(PATH) => { - if let Lit::Str(lit_str) = &m.lit { - return Ok(CrosAlsaAttr::Path(lit_str.parse()?)); - } - Err(syn::Error::new_spanned( - &m.lit, - "expected a valid path for cros_alsa_derive::CrosAlsaAttr::Path", - )) - } - _ => Err(syn::Error::new_spanned( - meta_item, - "unrecognized cros_alsa_derive::CrosAlsaAttr", - )), - } - } -} - -/// Parses `#[cros_alsa(path = "...")]` into a list of `CrosAlsaAttr`. -/// It's used to replace the crate path of cros_alsa in derive macros. -pub fn parse_cros_alsa_attr(attrs: &[syn::Attribute]) -> Result<Vec<CrosAlsaAttr>> { - attrs - .iter() - .flat_map(|attr| get_cros_alsa_meta_items(attr)) - .flatten() - .map(CrosAlsaAttr::try_from) - .collect() -} - -/// Parses and collects `NestedMeta` under `cros_alsa` attribute. -fn get_cros_alsa_meta_items(attr: &syn::Attribute) -> Result<Vec<syn::NestedMeta>> { - if !attr.path.is_ident(CROS_ALSA) { - return Ok(Vec::new()); - } - match attr.parse_meta() { - Ok(Meta::List(meta)) => Ok(meta.nested.into_iter().collect()), - _ => Err(syn::Error::new_spanned(attr, "expected #[cros_alsa(...)]")), - } -} diff --git a/cros_alsa/cros_alsa_derive/src/control.rs b/cros_alsa/cros_alsa_derive/src/control.rs deleted file mode 100644 index 584a5418..00000000 --- a/cros_alsa/cros_alsa_derive/src/control.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! This mod provides derive macros for cros_alsa::control. - -use proc_macro::TokenStream; -use proc_macro2::Span; -use quote::quote; - -use crate::common::{parse_cros_alsa_attr, CrosAlsaAttr}; - -/// The provide default implementation for `ControlOps`. -/// Users could hold `Ctl` and `ElemID` as `handle` and `id` in their control structure and use -/// `#[derive(ControlOps)]` macro to generate default load / save implementations. -pub fn impl_control_ops(ast: &syn::DeriveInput) -> TokenStream { - let name = &ast.ident; - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - let attrs = match parse_cros_alsa_attr(&ast.attrs) { - Ok(attrs) => attrs, - Err(e) => return e.to_compile_error().into(), - }; - let path = match attrs.iter().find(|x| x.is_path()) { - Some(CrosAlsaAttr::Path(path)) => path.clone(), - None => syn::LitStr::new("cros_alsa", Span::call_site()) - .parse() - .expect("failed to create a default path for derive macro: ControlOps"), - }; - let gen = quote! { - impl #impl_generics #path::ControlOps #impl_generics for #name #ty_generics #where_clause { - fn load(&mut self) -> ::std::result::Result<<Self as #path::Control #impl_generics>::Item, #path::ControlError> { - Ok(<Self as #path::Control>::Item::load(self.handle, &self.id)?) - } - fn save(&mut self, val: <Self as #path::Control #impl_generics>::Item) -> ::std::result::Result<bool, #path::ControlError> { - Ok(<Self as #path::Control>::Item::save(self.handle, &self.id, val)?) - } - } - }; - gen.into() -} diff --git a/cros_alsa/cros_alsa_derive/src/lib.rs b/cros_alsa/cros_alsa_derive/src/lib.rs deleted file mode 100644 index 9970de78..00000000 --- a/cros_alsa/cros_alsa_derive/src/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! `cros_alsa_derive` crate provides derive macros for cros_alsa. -//! - -#![deny(missing_docs)] -extern crate proc_macro; - -use proc_macro::TokenStream; - -mod common; -mod control; -use self::control::impl_control_ops; - -#[proc_macro_derive(ControlOps, attributes(cros_alsa))] -/// Derive macro generating an impl of the trait ControlOps. -/// To use this derive macro, users should hold `Ctl` and `ElemID` as `handle` -/// and `id` in their control structure. -pub fn control_ops_derive(input: TokenStream) -> TokenStream { - match syn::parse(input) { - Ok(ast) => impl_control_ops(&ast), - Err(e) => e.to_compile_error().into(), - } -} diff --git a/cros_alsa/src/card.rs b/cros_alsa/src/card.rs deleted file mode 100644 index 42beef2c..00000000 --- a/cros_alsa/src/card.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::error; -use std::fmt; - -use remain::sorted; - -use crate::control::{self, Control}; -use crate::control_primitive; -use crate::control_primitive::{Ctl, ElemId, ElemIface}; -use crate::control_tlv::{self, ControlTLV}; - -pub type Result<T> = std::result::Result<T, Error>; - -#[sorted] -#[derive(Debug)] -/// Possible errors that can occur in cros-alsa::card. -pub enum Error { - /// Failed to call AlsaControlAPI. - AlsaControlAPI(control_primitive::Error), - /// Error occurs in Control. - Control(control::Error), - /// Error occurs in ControlTLV. - ControlTLV(control_tlv::Error), -} - -impl error::Error for Error {} - -impl From<control::Error> for Error { - fn from(err: control::Error) -> Error { - Error::Control(err) - } -} - -impl From<control_tlv::Error> for Error { - fn from(err: control_tlv::Error) -> Error { - Error::ControlTLV(err) - } -} - -impl From<control_primitive::Error> for Error { - fn from(err: control_primitive::Error) -> Error { - Error::AlsaControlAPI(err) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - AlsaControlAPI(e) => write!(f, "{}", e), - Control(e) => write!(f, "{}", e), - ControlTLV(e) => write!(f, "{}", e), - } - } -} - -/// `Card` represents a sound card. -#[derive(Debug)] -pub struct Card { - handle: Ctl, - name: String, -} - -impl Card { - /// Creates a `Card`. - /// - /// # Arguments - /// - /// * `card_name` - The sound card name, ex: sofcmlmax98390d. - /// - /// # Errors - /// - /// * If card_name is an invalid CString. - /// * If snd_ctl_open() fails. - pub fn new(card_name: &str) -> Result<Self> { - let handle = Ctl::new(&format!("hw:{}", card_name))?; - Ok(Card { - name: card_name.to_owned(), - handle, - }) - } - - /// Gets sound card name. - pub fn name(&self) -> &str { - &self.name - } - - /// Creates a `Control` from control name. - /// - /// # Errors - /// - /// * If control name is an invalid CString. - /// * If control does not exist. - /// * If `Control` elem_type() mismatches the type of underlying mixer control. - /// * If `Control` size() mismatches the number of value entries of underlying mixer control. - pub fn control_by_name<'a, T: 'a>(&'a mut self, control_name: &str) -> Result<T> - where - T: Control<'a>, - { - let id = ElemId::new(ElemIface::Mixer, control_name)?; - Ok(T::from(&mut self.handle, id)?) - } - - /// Creates a `ControlTLV` from control name. - /// - /// # Errors - /// - /// * If control name is an invalid CString. - /// * If control does not exist. - pub fn control_tlv_by_name<'a>(&'a mut self, control_name: &str) -> Result<ControlTLV<'a>> { - let id = ElemId::new(ElemIface::Mixer, control_name)?; - Ok(ControlTLV::new(&mut self.handle, id)?) - } -} diff --git a/cros_alsa/src/control.rs b/cros_alsa/src/control.rs deleted file mode 100644 index 2bc90256..00000000 --- a/cros_alsa/src/control.rs +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! `control` module is meant to provide easier to use and more type safe abstractions -//! for various alsa mixer controls. -//! -//! Each mixer control should implement the `Control` trait to allow itself to be created by `Card`. -//! Each mixer control could hold `Ctl` as handle and `ElemID` as id and use `#[derive(ControlOps)]` macro -//! to generate default load / save implementations of the `ControlOps` trait which allows itself to read and -//! write the underlying hardware. -//! -//! # Examples -//! This is an example of how to define a `SwitchControl`. -//! -//! ``` -//! use std::error::Error; -//! -//! use cros_alsa::{Ctl, ElemId, Control, ControlError, ControlOps}; -//! use cros_alsa::elem::Elem; -//! -//! type Result<T> = std::result::Result<T, ControlError>; -//! -//! #[derive(ControlOps)] -//! pub struct SwitchControl<'a> { -//! // Must hold `Ctl` as handle and `ElemID` as id to use `#[derive(ControlOps)]`. -//! handle: &'a mut Ctl, -//! id: ElemId, -//! } -//! -//! impl<'a> Control<'a> for SwitchControl <'a> { -//! type Item = [bool; 1]; -//! -//! fn new(handle: &'a mut Ctl, id: ElemId) -> Self { -//! Self { -//! handle, -//! id, -//! } -//! } -//! } -//! -//! impl<'a> SwitchControl<'a> { -//! /// Reads the state of a switch type mix control. -//! pub fn state(&mut self) -> Result<bool> { -//! // Uses ControlOps::load() to read the mixer control. -//! let v = self.load()?; -//! Ok(v[0]) -//! } -//! -//! /// Updates the control state to true. -//! pub fn on(&mut self) -> Result<()> { -//! // Uses ControlOps::save() to write the mixer control. -//! self.save([true])?; -//! Ok(()) -//! } -//! } -//! -//! ``` - -use std::error; -use std::fmt; - -use cros_alsa_derive::ControlOps; -use remain::sorted; - -use crate::control_primitive::{self, Ctl, ElemId, ElemInfo, ElemType}; -use crate::elem::{self, Elem}; - -/// The Result type of cros-alsa::control. -pub type Result<T> = std::result::Result<T, Error>; - -#[sorted] -#[derive(Debug)] -/// Possible errors that can occur in cros-alsa::control. -pub enum Error { - /// Failed to call AlsaControlAPI. - AlsaControlAPI(control_primitive::Error), - /// Error occurs in Elem. - Elem(elem::Error), - /// Elem::size() does not match the element count of the mixer control. - MismatchElemCount(String, usize, usize), - /// Elem::elem_type() does not match the data type of the mixer control. - MismatchElemType(String, ElemType, ElemType), -} - -impl error::Error for Error {} - -impl From<control_primitive::Error> for Error { - fn from(err: control_primitive::Error) -> Error { - Error::AlsaControlAPI(err) - } -} - -impl From<elem::Error> for Error { - fn from(err: elem::Error) -> Error { - Error::Elem(err) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - AlsaControlAPI(e) => write!(f, "{}", e), - Elem(e) => write!(f, "{}", e), - MismatchElemCount(name, count, elem_count) => write!( - f, - "invalid `Control::size()` of {}: expect: {}, get: {}", - name, count, elem_count - ), - MismatchElemType(name, t, elem_type) => write!( - f, - "invalid `Control::elem_type()` of {}: expect: {}, get: {}", - name, t, elem_type - ), - } - } -} - -/// Each mixer control should implement the `Control` trait to allow itself to be created by `Card`. -pub trait Control<'a>: Sized + 'a { - /// The data type of the mixer control. - /// Use `ElemType::load()` and `ElemType::save()` to read or write the mixer control. - type Item: Elem; - - /// Called by `Self::from(handle: &'a mut Ctl, id: ElemId)` to create a `Control`. - fn new(handle: &'a mut Ctl, id: ElemId) -> Self; - /// Called by `Card` to create a `Control`. - fn from(handle: &'a mut Ctl, id: ElemId) -> Result<Self> { - let info = ElemInfo::new(handle, &id)?; - if info.elem_type()? != Self::elem_type() { - return Err(Error::MismatchElemType( - id.name()?.to_owned(), - info.elem_type()?, - Self::elem_type(), - )); - } - - if info.count() != Self::size() { - return Err(Error::MismatchElemCount( - id.name()?.to_owned(), - info.count(), - Self::size(), - )); - } - - Ok(Self::new(handle, id)) - } - /// Called by `Self::from(handle: &'a mut Ctl, id: ElemId)` to validate the data type of a - /// `Control`. - fn elem_type() -> ElemType { - Self::Item::elem_type() - } - /// Called by `Self::from(handle: &'a mut Ctl, id: ElemId)` to validate the number of value - /// entries of a `Control`. - fn size() -> usize { - Self::Item::size() - } -} - -/// Each mixer control could implement the `ControlOps` trait to allow itself to read and -/// write the underlying hardware`. Users could hold `Ctl` and `ElemID` as `handle` and `id` -/// in their control structure and use `#[derive(ControlOps)]` macro to generate default -/// load / save implementations. -pub trait ControlOps<'a>: Control<'a> { - /// Reads the values of the mixer control. - fn load(&mut self) -> Result<<Self as Control<'a>>::Item>; - /// Saves the values to the mixer control. - fn save(&mut self, val: <Self as Control<'a>>::Item) -> Result<bool>; -} - -/// `Control` that reads and writes a single integer value entry. -/// Since this crate is the `cros_alsa` crate, we replace the `cros_alsa` -/// path to `crate` in derive macros by `cros_alsa` attribute. -#[derive(ControlOps)] -#[cros_alsa(path = "crate")] -pub struct IntControl<'a> { - handle: &'a mut Ctl, - id: ElemId, -} - -impl<'a> IntControl<'a> { - /// Gets an i32 value from the mixer control. - /// - /// # Errors - /// - /// * If it fails to read from the control. - pub fn get(&mut self) -> Result<i32> { - let val = self.load()?; - Ok(val[0]) - } - - /// Updates an i32 value to the mixer control. - /// - /// # Errors - /// - /// * If it fails to write to the control. - pub fn set(&mut self, val: i32) -> Result<()> { - self.save([val])?; - Ok(()) - } -} - -impl<'a> Control<'a> for IntControl<'a> { - type Item = [i32; 1]; - fn new(handle: &'a mut Ctl, id: ElemId) -> Self { - Self { handle, id } - } -} - -/// Stereo Volume Mixer Control -/// Since this crate is the `cros_alsa` crate, we replace the `cros_alsa` -/// path to `crate` in derive macros by `cros_alsa` attribute. -#[derive(ControlOps)] -#[cros_alsa(path = "crate")] -pub struct StereoVolumeControl<'a> { - handle: &'a mut Ctl, - id: ElemId, -} - -impl<'a> StereoVolumeControl<'a> { - /// Reads the left and right volume. - /// - /// # Errors - /// - /// * If it fails to read from the control. - pub fn volume(&mut self) -> Result<(i32, i32)> { - let val = self.load()?; - Ok((val[0], val[1])) - } - - /// Updates the left and right volume. - /// - /// # Errors - /// - /// * If it fails to write to the control. - pub fn set_volume(&mut self, left: i32, right: i32) -> Result<()> { - self.save([left, right])?; - Ok(()) - } -} - -impl<'a> Control<'a> for StereoVolumeControl<'a> { - type Item = [i32; 2]; - fn new(handle: &'a mut Ctl, id: ElemId) -> Self { - Self { handle, id } - } -} - -/// `Control` that reads and writes a single boolean value entry. -/// Since this crate is the `cros_alsa` crate, we replace the `cros_alsa` -/// path to `crate` in derive macros by `cros_alsa` attribute. -#[derive(ControlOps)] -#[cros_alsa(path = "crate")] -pub struct SwitchControl<'a> { - handle: &'a mut Ctl, - id: ElemId, -} - -impl<'a> SwitchControl<'a> { - /// Reads the state of a switch type mix control. - /// - /// # Errors - /// - /// * If it fails to read from the control. - pub fn state(&mut self) -> Result<bool> { - let v = self.load()?; - Ok(v[0]) - } - - /// Updates the control state to true. - /// - /// # Errors - /// - /// * If it fails to write to the control. - pub fn on(&mut self) -> Result<()> { - self.save([true])?; - Ok(()) - } - - /// Updates the control state to false. - /// - /// # Errors - /// - /// * If it fails to write to the control. - pub fn off(&mut self) -> Result<()> { - self.save([false])?; - Ok(()) - } -} - -impl<'a> Control<'a> for SwitchControl<'a> { - type Item = [bool; 1]; - fn new(handle: &'a mut Ctl, id: ElemId) -> Self { - Self { handle, id } - } -} diff --git a/cros_alsa/src/control_primitive.rs b/cros_alsa/src/control_primitive.rs deleted file mode 100644 index 227aef27..00000000 --- a/cros_alsa/src/control_primitive.rs +++ /dev/null @@ -1,406 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::convert::TryFrom; -use std::error; -use std::ffi::{CStr, CString, FromBytesWithNulError, NulError}; -use std::fmt; -use std::marker::PhantomData; -use std::ptr; -use std::slice; -use std::str; - -use alsa_sys::*; -use libc::strlen; -use remain::sorted; - -pub type Result<T> = std::result::Result<T, Error>; - -#[derive(Debug, PartialEq)] -/// Possible errors that can occur in FFI functions. -pub enum FFIError { - Rc(i32), - NullPtr, -} - -impl fmt::Display for FFIError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use FFIError::*; - match self { - Rc(rc) => write!(f, "{}", snd_strerror(*rc)?), - NullPtr => write!(f, "the return value is a null pointer"), - } - } -} - -#[sorted] -#[derive(Debug, PartialEq)] -/// Possible errors that can occur in cros-alsa::control_primitive. -pub enum Error { - /// Control with the given name does not exist. - ControlNotFound(String), - /// Failed to call snd_ctl_open(). - CtlOpenFailed(FFIError, String), - /// snd_ctl_elem_id_get_name() returns null. - ElemIdGetNameFailed, - /// Failed to call snd_ctl_elem_id_malloc(). - ElemIdMallocFailed(FFIError), - /// Failed to call snd_ctl_elem_info_malloc(). - ElemInfoMallocFailed(FFIError), - /// Failed to call snd_ctl_elem_value_malloc(). - ElemValueMallocFailed(FFIError), - /// The slice used to create a CStr does not have one and only one null - /// byte positioned at the end. - FromBytesWithNulError(FromBytesWithNulError), - /// Failed to convert to a valid ElemType. - InvalidElemType(u32), - /// An error indicating that an interior nul byte was found. - NulError(NulError), - /// Failed to call snd_strerror(). - SndStrErrorFailed(i32), - /// UTF-8 validation failed - Utf8Error(str::Utf8Error), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - ControlNotFound(name) => write!(f, "control: {} does not exist", name), - CtlOpenFailed(e, name) => write!(f, "{} snd_ctl_open failed: {}", name, e,), - ElemIdGetNameFailed => write!(f, "snd_ctl_elem_id_get_name failed"), - ElemIdMallocFailed(e) => write!(f, "snd_ctl_elem_id_malloc failed: {}", e), - ElemInfoMallocFailed(e) => write!(f, "snd_ctl_elem_info_malloc failed: {}", e), - ElemValueMallocFailed(e) => write!(f, "snd_ctl_elem_value_malloc failed: {}", e), - FromBytesWithNulError(e) => write!(f, "invalid CString: {}", e), - InvalidElemType(v) => write!(f, "invalid ElemType: {}", v), - NulError(e) => write!(f, "invalid CString: {}", e), - SndStrErrorFailed(e) => write!(f, "snd_strerror() failed: {}", e), - Utf8Error(e) => write!(f, "{}", e), - } - } -} - -impl From<Error> for fmt::Error { - fn from(_err: Error) -> fmt::Error { - fmt::Error - } -} - -impl From<str::Utf8Error> for Error { - fn from(err: str::Utf8Error) -> Error { - Error::Utf8Error(err) - } -} - -impl From<FromBytesWithNulError> for Error { - fn from(err: FromBytesWithNulError) -> Error { - Error::FromBytesWithNulError(err) - } -} - -impl From<NulError> for Error { - fn from(err: NulError) -> Error { - Error::NulError(err) - } -} - -/// [snd_ctl_elem_iface_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga14baa0febb91cc4c5d72dcc825acf518) wrapper. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum ElemIface { - Card = SND_CTL_ELEM_IFACE_CARD as isize, - Hwdep = SND_CTL_ELEM_IFACE_HWDEP as isize, - Mixer = SND_CTL_ELEM_IFACE_MIXER as isize, - PCM = SND_CTL_ELEM_IFACE_PCM as isize, - Rawmidi = SND_CTL_ELEM_IFACE_RAWMIDI as isize, - Timer = SND_CTL_ELEM_IFACE_TIMER as isize, - Sequencer = SND_CTL_ELEM_IFACE_SEQUENCER as isize, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -/// [snd_ctl_elem_type_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#gac42e0ed6713b62711af5e80b4b3bcfec) wrapper. -pub enum ElemType { - None = SND_CTL_ELEM_TYPE_NONE as isize, - Boolean = SND_CTL_ELEM_TYPE_BOOLEAN as isize, - Integer = SND_CTL_ELEM_TYPE_INTEGER as isize, - Enumerated = SND_CTL_ELEM_TYPE_ENUMERATED as isize, - Bytes = SND_CTL_ELEM_TYPE_BYTES as isize, - IEC958 = SND_CTL_ELEM_TYPE_IEC958 as isize, - Integer64 = SND_CTL_ELEM_TYPE_INTEGER64 as isize, -} - -impl fmt::Display for ElemType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ElemType::None => write!(f, "SND_CTL_ELEM_TYPE_NONE"), - ElemType::Boolean => write!(f, "SND_CTL_ELEM_TYPE_BOOLEAN"), - ElemType::Integer => write!(f, "SND_CTL_ELEM_TYPE_INTEGER"), - ElemType::Enumerated => write!(f, "SND_CTL_ELEM_TYPE_ENUMERATED"), - ElemType::Bytes => write!(f, "SND_CTL_ELEM_TYPE_BYTES"), - ElemType::IEC958 => write!(f, "SND_CTL_ELEM_TYPE_IEC958"), - ElemType::Integer64 => write!(f, "SND_CTL_ELEM_TYPE_INTEGER64"), - } - } -} - -impl TryFrom<u32> for ElemType { - type Error = Error; - fn try_from(elem_type: u32) -> Result<ElemType> { - match elem_type { - SND_CTL_ELEM_TYPE_NONE => Ok(ElemType::None), - SND_CTL_ELEM_TYPE_BOOLEAN => Ok(ElemType::Boolean), - SND_CTL_ELEM_TYPE_INTEGER => Ok(ElemType::Integer), - SND_CTL_ELEM_TYPE_ENUMERATED => Ok(ElemType::Enumerated), - SND_CTL_ELEM_TYPE_BYTES => Ok(ElemType::Bytes), - SND_CTL_ELEM_TYPE_IEC958 => Ok(ElemType::IEC958), - SND_CTL_ELEM_TYPE_INTEGER64 => Ok(ElemType::Integer64), - _ => Err(Error::InvalidElemType(elem_type)), - } - } -} - -/// [snd_ctl_elem_id_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#gad6c3746f1925bfec6a4fd0e913430e55) wrapper. -pub struct ElemId( - ptr::NonNull<snd_ctl_elem_id_t>, - PhantomData<snd_ctl_elem_id_t>, -); - -impl Drop for ElemId { - fn drop(&mut self) { - // Safe because self.0.as_ptr() is a valid snd_ctl_elem_id_t*. - unsafe { snd_ctl_elem_id_free(self.0.as_ptr()) }; - } -} - -impl ElemId { - /// Creates an `ElemId` object by `ElemIface` and name. - /// - /// # Errors - /// - /// * If memory allocation fails. - /// * If ctl_name is not a valid CString. - pub fn new(iface: ElemIface, ctl_name: &str) -> Result<ElemId> { - let mut id_ptr = ptr::null_mut(); - // Safe because we provide a valid id_ptr to be filled, - // and we validate the return code before using id_ptr. - let rc = unsafe { snd_ctl_elem_id_malloc(&mut id_ptr) }; - if rc < 0 { - return Err(Error::ElemIdMallocFailed(FFIError::Rc(rc))); - } - let id = ptr::NonNull::new(id_ptr).ok_or(Error::ElemIdMallocFailed(FFIError::NullPtr))?; - - // Safe because id.as_ptr() is a valid snd_ctl_elem_id_t*. - unsafe { snd_ctl_elem_id_set_interface(id.as_ptr(), iface as u32) }; - let name = CString::new(ctl_name)?; - // Safe because id.as_ptr() is a valid snd_ctl_elem_id_t* and name is a safe CString. - unsafe { snd_ctl_elem_id_set_name(id.as_ptr(), name.as_ptr()) }; - Ok(ElemId(id, PhantomData)) - } - - /// Borrows the const inner pointer. - pub fn as_ptr(&self) -> *const snd_ctl_elem_id_t { - self.0.as_ptr() - } - - /// Safe [snd_ctl_elem_id_get_name()] (https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#gaa6cfea3ac963bfdaeb8189e03e927a76) wrapper. - /// - /// # Errors - /// - /// * If snd_ctl_elem_id_get_name() fails. - /// * If control element name is not a valid CString. - /// * If control element name is not valid UTF-8 data. - pub fn name(&self) -> Result<&str> { - // Safe because self.as_ptr() is a valid snd_ctl_elem_id_t*. - let name = unsafe { snd_ctl_elem_id_get_name(self.as_ptr()) }; - if name.is_null() { - return Err(Error::ElemIdGetNameFailed); - } - // Safe because name is a valid *const i8, and its life time - // is the same as the passed reference of self. - let s = CStr::from_bytes_with_nul(unsafe { - slice::from_raw_parts(name as *const u8, strlen(name) + 1) - })?; - Ok(s.to_str()?) - } -} - -/// [snd_ctl_elem_value_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga266b478eb64f1cdd75e337df4b4b995e) wrapper. -pub struct ElemValue( - ptr::NonNull<snd_ctl_elem_value_t>, - PhantomData<snd_ctl_elem_value_t>, -); - -impl Drop for ElemValue { - // Safe because self.0.as_ptr() is valid. - fn drop(&mut self) { - unsafe { snd_ctl_elem_value_free(self.0.as_ptr()) }; - } -} - -impl ElemValue { - /// Creates an `ElemValue`. - /// - /// # Errors - /// - /// * If memory allocation fails. - pub fn new(id: &ElemId) -> Result<ElemValue> { - let mut v_ptr = ptr::null_mut(); - // Safe because we provide a valid v_ptr to be filled, - // and we validate the return code before using v_ptr. - let rc = unsafe { snd_ctl_elem_value_malloc(&mut v_ptr) }; - if rc < 0 { - return Err(Error::ElemValueMallocFailed(FFIError::Rc(rc))); - } - let value = - ptr::NonNull::new(v_ptr).ok_or(Error::ElemValueMallocFailed(FFIError::NullPtr))?; - // Safe because value.as_ptr() is a valid snd_ctl_elem_value_t* and id.as_ptr() is also valid. - unsafe { snd_ctl_elem_value_set_id(value.as_ptr(), id.as_ptr()) }; - Ok(ElemValue(value, PhantomData)) - } - - /// Borrows the mutable inner pointer. - pub fn as_mut_ptr(&mut self) -> *mut snd_ctl_elem_value_t { - self.0.as_ptr() - } - - /// Borrows the const inner pointer. - pub fn as_ptr(&self) -> *const snd_ctl_elem_value_t { - self.0.as_ptr() - } -} - -/// [snd_ctl_elem_info_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga2cae0bb76df919368e4ff9a7021dd3ab) wrapper. -pub struct ElemInfo( - ptr::NonNull<snd_ctl_elem_info_t>, - PhantomData<snd_ctl_elem_info_t>, -); - -impl Drop for ElemInfo { - fn drop(&mut self) { - // Safe because self.0.as_ptr() is a valid snd_ctl_elem_info_t*. - unsafe { snd_ctl_elem_info_free(self.0.as_ptr()) }; - } -} - -impl ElemInfo { - /// Creates an `ElemInfo`. - /// - /// # Errors - /// - /// * If memory allocation fails. - /// * If control does not exist. - pub fn new(handle: &mut Ctl, id: &ElemId) -> Result<ElemInfo> { - let mut info_ptr = ptr::null_mut(); - - // Safe because we provide a valid info_ptr to be filled, - // and we validate the return code before using info_ptr. - let rc = unsafe { snd_ctl_elem_info_malloc(&mut info_ptr) }; - if rc < 0 { - return Err(Error::ElemInfoMallocFailed(FFIError::Rc(rc))); - } - let info = - ptr::NonNull::new(info_ptr).ok_or(Error::ElemInfoMallocFailed(FFIError::NullPtr))?; - - // Safe because info.as_ptr() is a valid snd_ctl_elem_info_t* and id.as_ptr() is also valid. - unsafe { snd_ctl_elem_info_set_id(info.as_ptr(), id.as_ptr()) }; - - // Safe because handle.as_mut_ptr() is a valid snd_ctl_t* and info.as_ptr() is a valid - // snd_ctl_elem_info_t*. - let rc = unsafe { snd_ctl_elem_info(handle.as_mut_ptr(), info.as_ptr()) }; - if rc < 0 { - return Err(Error::ControlNotFound(id.name()?.to_owned())); - } - Ok(ElemInfo(info, PhantomData)) - } - - /// Safe [snd_ctl_elem_info_get_type](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga0fec5d22ee58d04f14b59f405adc595e) wrapper. - pub fn elem_type(&self) -> Result<ElemType> { - // Safe because self.0.as_ptr() is a valid snd_ctl_elem_info_t*. - unsafe { ElemType::try_from(snd_ctl_elem_info_get_type(self.0.as_ptr())) } - } - - /// Safe [snd_ctl_elem_info_get_count](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#gaa75a20d4190d324bcda5fd6659a4b377) wrapper. - pub fn count(&self) -> usize { - // Safe because self.0.as_ptr() is a valid snd_ctl_elem_info_t*. - unsafe { snd_ctl_elem_info_get_count(self.0.as_ptr()) as usize } - } - - /// Safe [snd_ctl_elem_info_is_tlv_readable](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#gaac6bb412e5a9fffb5509e98a10de45b5) wrapper. - pub fn tlv_readable(&self) -> bool { - // Safe because self.0.as_ptr() is a valid snd_ctl_elem_info_t*. - unsafe { snd_ctl_elem_info_is_tlv_readable(self.0.as_ptr()) as usize == 1 } - } - - /// Safe [snd_ctl_elem_info_is_tlv_writable](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#gacfbaae80d710b6feac682f8ba10a0341) wrapper. - pub fn tlv_writable(&self) -> bool { - // Safe because self.0.as_ptr() is a valid snd_ctl_elem_info_t*. - unsafe { snd_ctl_elem_info_is_tlv_writable(self.0.as_ptr()) as usize == 1 } - } -} - -/// [snd_ctl_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga06628f38def84a0fe3da74041db9d51f) wrapper. -#[derive(Debug)] -pub struct Ctl(ptr::NonNull<snd_ctl_t>, PhantomData<snd_ctl_t>); - -impl Drop for Ctl { - fn drop(&mut self) { - // Safe as we provide a valid snd_ctl_t*. - unsafe { snd_ctl_close(self.0.as_ptr()) }; - } -} - -impl Ctl { - /// Creates a `Ctl`. - /// Safe [snd_ctl_open](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga58537f5b74c9c1f51699f9908a0d7f56). - /// Does not support async mode. - /// - /// # Errors - /// - /// * If `card` is an invalid CString. - /// * If `snd_ctl_open()` fails. - pub fn new(card: &str) -> Result<Ctl> { - let name = CString::new(card)?; - let mut ctl_ptr = ptr::null_mut(); - // Safe because we provide a valid ctl_ptr to be filled, name is a safe CString - // and we validate the return code before using ctl_ptr. - let rc = unsafe { snd_ctl_open(&mut ctl_ptr, name.as_ptr(), 0) }; - if rc < 0 { - return Err(Error::CtlOpenFailed( - FFIError::Rc(rc), - name.to_str()?.to_owned(), - )); - } - let ctl = ptr::NonNull::new(ctl_ptr).ok_or(Error::CtlOpenFailed( - FFIError::NullPtr, - name.to_str()?.to_owned(), - ))?; - Ok(Ctl(ctl, PhantomData)) - } - - /// Borrows the mutable inner pointer - pub fn as_mut_ptr(&mut self) -> *mut snd_ctl_t { - self.0.as_ptr() - } -} - -/// Safe [snd_strerror](https://www.alsa-project.org/alsa-doc/alsa-lib/group___error.html#ga182bbadf2349e11602bc531e8cf22f7e) wrapper. -/// -/// # Errors -/// -/// * If `snd_strerror` returns invalid UTF-8 data. -pub fn snd_strerror(err_num: i32) -> Result<&'static str> { - // Safe because we validate the return pointer of snd_strerror() - // before using it. - let s_ptr = unsafe { alsa_sys::snd_strerror(err_num) }; - if s_ptr.is_null() { - return Err(Error::SndStrErrorFailed(err_num)); - } - // Safe because s_ptr is a non-null *const u8 and its lifetime is static. - let s = CStr::from_bytes_with_nul(unsafe { - slice::from_raw_parts(s_ptr as *const u8, strlen(s_ptr) + 1) - })?; - Ok(s.to_str()?) -} diff --git a/cros_alsa/src/control_tlv.rs b/cros_alsa/src/control_tlv.rs deleted file mode 100644 index e1f35510..00000000 --- a/cros_alsa/src/control_tlv.rs +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! `ControlTLV` supports read and write of the alsa TLV byte controls -//! Users can obtain a ControlTLV by Card::control_tlv_by_name(). -//! # Examples -//! This is an example of how to use a `TLV`. -//! -//! ``` -//! use std::assert_eq; -//! use std::convert::TryFrom; -//! use std::error::Error; -//! -//! use cros_alsa::{TLV, ControlTLVError}; -//! use cros_alsa::elem::Elem; -//! -//! type Result<T> = std::result::Result<T, ControlTLVError>; -//! -//! let mut tlv = TLV::new(0, vec![1,2,3,4]); -//! assert_eq!(4, tlv.len()); -//! assert_eq!(0, tlv.tlv_type()); -//! assert_eq!(2, tlv[1]); -//! tlv[1] = 8; -//! assert_eq!(vec![1,8,3,4], tlv.value().to_vec()); -//! assert_eq!(vec![0,16,1,8,3,4], Into::<Vec<u32>>::into(tlv)); -//! -//! ``` - -use std::{ - convert::TryFrom, - fmt, - ops::{Index, IndexMut}, - slice::SliceIndex, -}; -use std::{error, mem::size_of}; - -use remain::sorted; - -use crate::control_primitive::{self, Ctl, ElemId, ElemInfo, ElemType}; - -/// The Result type of cros-alsa::control. -pub type Result<T> = std::result::Result<T, Error>; - -#[sorted] -#[derive(Debug, PartialEq)] -/// Possible errors that can occur in cros-alsa::control. -pub enum Error { - /// Failed to call AlsaControlAPI. - AlsaControlAPI(control_primitive::Error), - /// Failed to convert buffer to TLV struct. - InvalidTLV, - /// ElemInfo::count() is not multiple of size_of::<u32>. - InvalidTLVSize(String, usize), - /// ElemInfo::elem_type() is not ElemType::Bytes. - InvalidTLVType(String, ElemType), - /// The control is not readable. - TLVNotReadable, - /// The control is not writeable. - TLVNotWritable, - /// Failed to call snd_ctl_elem_tlv_read. - TLVReadFailed(i32), - /// Failed to call snd_ctl_elem_tlv_write. - TVLWriteFailed(i32), -} - -impl error::Error for Error {} - -impl From<control_primitive::Error> for Error { - fn from(err: control_primitive::Error) -> Error { - Error::AlsaControlAPI(err) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - AlsaControlAPI(e) => write!(f, "{}", e), - InvalidTLV => write!(f, "failed to convert to TLV"), - InvalidTLVSize(name, elem_size) => write!( - f, - "ElemInfo::size() of {} should be multiple of size_of::<u32>, get: {}", - name, elem_size - ), - InvalidTLVType(name, elem_type) => write!( - f, - "invalid ElemInfo::elem_type() of {}: expect: {}, get: {}", - name, - ElemType::Bytes, - elem_type - ), - TLVNotReadable => write!(f, "the control is not readable."), - TLVNotWritable => write!(f, "the control is not writable."), - TLVReadFailed(rc) => write!(f, "snd_ctl_elem_tlv_read failed: {}", rc), - TVLWriteFailed(rc) => write!(f, "snd_ctl_elem_tlv_write failed: {}", rc), - } - } -} - -/// TLV struct represents the TLV data to be read from -/// or write to an alsa TLV byte control. -#[derive(Debug)] -pub struct TLV { - /// data[Self::TYPE_OFFSET] contains the tlv type. - /// data[Self::LEN_OFFSET] contains the length of the value in bytes. - /// data[Self::VALUE_OFFSET..] contains the data. - data: Vec<u32>, -} - -impl TLV { - const TYPE_OFFSET: usize = 0; - const LEN_OFFSET: usize = 1; - const VALUE_OFFSET: usize = 2; - const TLV_HEADER_SIZE_BYTES: usize = Self::VALUE_OFFSET * size_of::<u32>(); - - /// Initializes a `TLV` by giving the tlv type and tlv value. - pub fn new(tlv_type: u32, tlv_value: Vec<u32>) -> Self { - let mut data = vec![0; 2]; - data[Self::TYPE_OFFSET] = tlv_type; - data[Self::LEN_OFFSET] = (tlv_value.len() * size_of::<u32>()) as u32; - data.extend(tlv_value.iter()); - Self { data } - } - - /// Returns the type of the tlv. - pub fn tlv_type(&self) -> u32 { - self.data[Self::TYPE_OFFSET] - } - - /// Returns the length of the tlv value in dword. - pub fn len(&self) -> usize { - self.data[Self::LEN_OFFSET] as usize / size_of::<u32>() - } - - /// Returns whether the tlv value is empty. - pub fn is_empty(&self) -> bool { - self.data[Self::LEN_OFFSET] == 0 - } - - /// Returns the tlv value in slice. - pub fn value(&self) -> &[u32] { - &self.data[Self::VALUE_OFFSET..] - } -} - -impl<I: SliceIndex<[u32]>> Index<I> for TLV { - type Output = I::Output; - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.data[Self::VALUE_OFFSET..][index] - } -} - -impl<I: SliceIndex<[u32]>> IndexMut<I> for TLV { - #[inline] - fn index_mut(&mut self, index: I) -> &mut Self::Output { - &mut self.data[Self::VALUE_OFFSET..][index] - } -} - -impl TryFrom<Vec<u32>> for TLV { - type Error = Error; - - /// Constructs a TLV from a vector with the following alsa tlv header validation: - /// 1 . tlv_buf[Self::LEN_OFFSET] should be multiple of size_of::<u32> - /// 2 . tlv_buf[Self::LEN_OFFSET] is the length of tlv value in byte and - /// should be less than the buffer length * size_of::<u32>. - fn try_from(data: Vec<u32>) -> Result<Self> { - if data.len() < 2 { - return Err(Error::InvalidTLV); - } - - if data[Self::LEN_OFFSET] % size_of::<u32>() as u32 != 0 { - return Err(Error::InvalidTLV); - } - - if data[Self::LEN_OFFSET] / size_of::<u32>() as u32 - > data[Self::VALUE_OFFSET..].len() as u32 - { - return Err(Error::InvalidTLV); - } - - Ok(Self { data }) - } -} - -impl Into<Vec<u32>> for TLV { - /// Returns the raw tlv data buffer (including the tlv header). - fn into(self) -> Vec<u32> { - self.data - } -} - -/// `ControlTLV` supports read and write of the alsa TLV byte controls. -pub struct ControlTLV<'a> { - handle: &'a mut Ctl, - id: ElemId, -} - -impl<'a> ControlTLV<'a> { - /// Called by `Card` to create a `ControlTLV`. - pub fn new(handle: &'a mut Ctl, id: ElemId) -> Result<Self> { - let info = ElemInfo::new(handle, &id)?; - if info.count() % size_of::<u32>() != 0 { - return Err(Error::InvalidTLVSize(id.name()?.to_owned(), info.count())); - } - match info.elem_type()? { - ElemType::Bytes => Ok(Self { handle, id }), - _ => Err(Error::InvalidTLVType( - id.name()?.to_owned(), - info.elem_type()?, - )), - } - } - - /// Reads data from the byte control by `snd_ctl_elem_tlv_read` - /// - /// # - /// # Errors - /// - /// * If it fails to read from the control. - pub fn load(&mut self) -> Result<TLV> { - if !ElemInfo::new(self.handle, &self.id)?.tlv_readable() { - return Err(Error::TLVNotReadable); - } - - let tlv_size = ElemInfo::new(self.handle, &self.id)?.count() + TLV::TLV_HEADER_SIZE_BYTES; - - let mut tlv_buf = vec![0; tlv_size / size_of::<u32>()]; - // Safe because handle.as_mut_ptr() is a valid *mut snd_ctl_t, id_as_ptr is valid and - // tlv_buf.as_mut_ptr() is also valid. - let rc = unsafe { - alsa_sys::snd_ctl_elem_tlv_read( - self.handle.as_mut_ptr(), - self.id.as_ptr(), - tlv_buf.as_mut_ptr(), - tlv_size as u32, - ) - }; - if rc < 0 { - return Err(Error::TLVReadFailed(rc)); - } - Ok(TLV::try_from(tlv_buf)?) - } - - /// Writes to the byte control by `snd_ctl_elem_tlv_write` - /// - /// # Results - /// - /// * `changed` - false on success. - /// - true on success when value was changed. - /// # - /// # Errors - /// - /// * If it fails to write to the control. - pub fn save(&mut self, tlv: TLV) -> Result<bool> { - if !ElemInfo::new(self.handle, &self.id)?.tlv_writable() { - return Err(Error::TLVNotReadable); - } - // Safe because handle.as_mut_ptr() is a valid *mut snd_ctl_t, id_as_ptr is valid and - // tlv.as_mut_ptr() is also valid. - let rc = unsafe { - alsa_sys::snd_ctl_elem_tlv_write( - self.handle.as_mut_ptr(), - self.id.as_ptr(), - Into::<Vec<u32>>::into(tlv).as_mut_ptr(), - ) - }; - if rc < 0 { - return Err(Error::TVLWriteFailed(rc)); - } - Ok(rc > 0) - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_tlv_try_from_raw_vec() { - let tlv_buf = vec![0, 12, 2, 3, 4]; - assert!(TLV::try_from(tlv_buf).is_ok()); - } - - #[test] - fn test_tlv_length_is_not_multiple_of_sizeof_int() { - // Invalid tlv length in data[Self::LEN_OFFSET]. - let tlv_buf = vec![0, 1, 2, 3, 4]; - assert_eq!(TLV::try_from(tlv_buf).unwrap_err(), Error::InvalidTLV); - } - - #[test] - fn test_tlv_length_larger_than_buff_size() { - // Invalid tlv length in data[Self::LEN_OFFSET]. - let tlv_buf = vec![0, 16, 2, 3, 4]; - assert_eq!(TLV::try_from(tlv_buf).unwrap_err(), Error::InvalidTLV); - } - - #[test] - fn test_tlv_length_less_than_two() { - // tlv buffer length < 2 - let tlv_buf = vec![0]; - assert_eq!(TLV::try_from(tlv_buf).unwrap_err(), Error::InvalidTLV); - } - - #[test] - fn test_tlv_length_equal_two() { - // tlv buffer size = 2. - let tlv_buf = vec![0, 0]; - assert!(TLV::try_from(tlv_buf).is_ok()); - } -} diff --git a/cros_alsa/src/elem.rs b/cros_alsa/src/elem.rs deleted file mode 100644 index 08fe8b62..00000000 --- a/cros_alsa/src/elem.rs +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! This module provides different implementations of `Elem` that use the alsa-lib control interface -//! API to read and write alsa control elements. -//! -//! The `Elem::type()` returns the type of value that a control element can interact with, -//! and it is one of integer, integer64, boolean, enumerators, bytes or IEC958 structure. -//! The `Elem::size()` returns the number of values it reads from or writes to the hardware -//! at a time. -//! The `Elem::load(..)` and `Elem::save(..)` are used by `ControlOps` trait to read and write -//! the underlying mixer control. -//! -//! Users should use the provided implementations of `Elem` to define the associated type in -//! their owner encapsulation of `Control`. - -use std::default::Default; -use std::error; -use std::fmt; - -use libc::{c_long, c_uint}; -use remain::sorted; - -use crate::control_primitive::{self, snd_strerror, Ctl, ElemId, ElemType, ElemValue}; - -/// The Result type of cros-alsa::elem. -pub type Result<T> = std::result::Result<T, Error>; - -#[sorted] -#[derive(Debug)] -/// Possible errors that can occur in cros-alsa::elem. -pub enum Error { - /// Failed to call AlsaControlAPI. - AlsaControlAPI(control_primitive::Error), - /// Failed to call `snd_ctl_elem_read()`. - ElemReadFailed(i32), - /// Failed to call `snd_ctl_elem_write()`. - ElemWriteFailed(i32), -} - -impl error::Error for Error {} - -impl From<control_primitive::Error> for Error { - fn from(err: control_primitive::Error) -> Error { - Error::AlsaControlAPI(err) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - AlsaControlAPI(e) => write!(f, "{}", e), - ElemReadFailed(e) => write!(f, "snd_ctl_elem_read failed: {}", snd_strerror(*e)?), - ElemWriteFailed(e) => write!(f, "snd_ctl_elem_write failed: {}", snd_strerror(*e)?), - } - } -} - -// Uses a recursive macro to generate implementation for [bool; n] and [i32; n], n = 1 to 128. -// The `$t:ident $($ts:ident)*` part matches and removes one token at a time. It's used for -// counting recursive steps. -macro_rules! impl_for_array { - {$n:expr, $type:ty, $t:ident $($ts:ident)*} => { - impl Elem for [$type; $n] { - type T = Self; - /// Reads [$type; $n] data from the mixer control. - /// - /// # Errors - /// - /// * If it fails to call `snd_ctl_elem_read()`. - fn load(handle: &mut Ctl, id: &ElemId) -> Result<Self::T> - { - let mut elem = ElemValue::new(id)?; - // Safe because self.handle.as_mut_ptr() is a valid *mut snd_ctl_t and - // elem.as_mut_ptr() is also a valid *mut snd_ctl_elem_value_t. - let rc = unsafe { alsa_sys::snd_ctl_elem_read(handle.as_mut_ptr(), elem.as_mut_ptr()) }; - if rc < 0 { - return Err(Error::ElemReadFailed(rc)); - } - let mut ret = [Default::default(); $n]; - for i in 0..$n { - // Safe because elem.as_ptr() is a valid snd_ctl_elem_value_t* and i is guaranteed to be - // within a valid range. - ret[i] = unsafe { <$type>::elem_value_get(&elem, i) }; - } - Ok(ret) - } - - /// Updates [$type; $n] data to the mixer control. - /// - /// # Results - /// - /// * `changed` - false on success. - /// - true on success when value was changed. - /// - /// # Errors - /// - /// * If it fails to call `snd_ctl_elem_write()`. - fn save(handle: &mut Ctl, id: &ElemId, val: Self::T) -> Result<bool> { - let mut elem = ElemValue::new(id)?; - for i in 0..$n { - // Safe because elem.as_mut_ptr() is a valid snd_ctl_elem_value_t* and i is guaranteed to be - // within a valid range. - unsafe { <$type>::elem_value_set(&mut elem, i, val[i]) }; - } - // Safe because self.handle.as_mut_ptr() is a valid *mut snd_ctl_t and - // elem.as_mut_ptr() is also a valid *mut snd_ctl_elem_value_t. - let rc = unsafe { alsa_sys::snd_ctl_elem_write(handle.as_mut_ptr(), elem.as_mut_ptr()) }; - if rc < 0 { - return Err(Error::ElemWriteFailed(rc)); - } - Ok(rc > 0) - } - - /// Gets the data type itself can read and write. - fn elem_type() -> ElemType { - <$type>::elem_type() - } - - /// Gets the number of value entries itself can read and write. - fn size() -> usize { - $n - } - } - impl_for_array!{($n - 1), $type, $($ts)*} - }; - {$n:expr, $type:ty,} => {}; -} - -// Implements `Elem` for [i32; n] where n = 1 to 128. -impl_for_array! {128, i32, -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -} - -// Implements `Elem` for [bool; n] where n = 1 to 128. -impl_for_array! {128, bool, -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T -} - -impl CtlElemValue for bool { - type T = bool; - /// Gets a bool from the ElemValue. - unsafe fn elem_value_get(elem: &ElemValue, idx: usize) -> bool { - alsa_sys::snd_ctl_elem_value_get_boolean(elem.as_ptr(), idx as c_uint) != 0 - } - /// Sets a bool to the ElemValue. - unsafe fn elem_value_set(elem: &mut ElemValue, idx: usize, val: bool) { - alsa_sys::snd_ctl_elem_value_set_boolean(elem.as_mut_ptr(), idx as c_uint, val as c_long); - } - /// Returns ElemType::Boolean. - fn elem_type() -> ElemType { - ElemType::Boolean - } -} - -impl CtlElemValue for i32 { - type T = i32; - /// Gets an i32 from the ElemValue. - unsafe fn elem_value_get(elem: &ElemValue, idx: usize) -> i32 { - alsa_sys::snd_ctl_elem_value_get_integer(elem.as_ptr(), idx as c_uint) as i32 - } - /// Sets an i32 to the ElemValue. - unsafe fn elem_value_set(elem: &mut ElemValue, idx: usize, val: i32) { - alsa_sys::snd_ctl_elem_value_set_integer(elem.as_mut_ptr(), idx as c_uint, val as c_long); - } - /// Returns ElemType::Integer. - fn elem_type() -> ElemType { - ElemType::Integer - } -} - -/// All primitive types of a control element should implement `CtlElemValue` trait. -trait CtlElemValue { - /// The primitive type of a control element. - type T; - /// Gets the value from the ElemValue. - unsafe fn elem_value_get(value: &ElemValue, idx: usize) -> Self::T; - /// Sets the value to the ElemValue. - unsafe fn elem_value_set(value: &mut ElemValue, id: usize, val: Self::T); - /// Gets the data type itself can read and write. - fn elem_type() -> ElemType; -} - -/// Use `Elem` trait to access the underlying control element through the given `Ctl` and `ElemId`. -pub trait Elem: Sized { - /// The data type of a control element. - type T; - /// Reads the value from the mixer control. - fn load(handle: &mut Ctl, id: &ElemId) -> Result<Self::T>; - /// Saves the value to the mixer control. - fn save(handle: &mut Ctl, id: &ElemId, val: Self::T) -> Result<bool>; - /// Gets the data type itself can read and write. - fn elem_type() -> ElemType; - /// Gets the number of value entries itself can read and write. - fn size() -> usize; -} diff --git a/cros_alsa/src/lib.rs b/cros_alsa/src/lib.rs deleted file mode 100644 index 070d221a..00000000 --- a/cros_alsa/src/lib.rs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! `cros_alsa` crate currently supports interacting with alsa -//! controls by using the control interface API of alsa-lib. -//! -//! # Examples -//! This is an example of how to use the provided `Control` objects. -//! -//! ``` no_run -//! use std::error::Error; -//! use std::result::Result; -//! -//! use cros_alsa::{Card, SwitchControl, IntControl, StereoVolumeControl}; -//! -//! fn main() -> Result<(), Box<dyn Error>> { -//! -//! let mut card = Card::new("sofmax98390d")?; -//! -//! // Uses a SwitchControl to turn on and off a mixer control that has a single boolean state. -//! let mut calib_ctrl:SwitchControl = card.control_by_name("Left DSM Calibration")?; -//! calib_ctrl.on()?; -//! assert_eq!(calib_ctrl.state()?, true); -//! calib_ctrl.off()?; -//! -//! // Uses an IntControl to read and write a mixer control that has a single integer value. -//! let mut rdc_ctrl:IntControl = card.control_by_name("Left Rdc")?; -//! let _rdc = rdc_ctrl.get()?; -//! rdc_ctrl.set(13000)?; -//! -//! // Uses a StereoVolumeControl to manipulate stereo volume related functionality. -//! let mut volume_ctrl:StereoVolumeControl = card.control_by_name("Master Playback Volume")?; -//! volume_ctrl.set_volume(184, 184)?; -//! -//! Ok(()) -//! } -//! ``` - -// Allow the maximum recursive depth = 256 for macro expansion. -#![recursion_limit = "256"] -#![deny(missing_docs)] - -mod card; -mod control; -mod control_primitive; -pub mod control_tlv; -pub mod elem; - -pub use self::card::Card; -pub use self::control::{Control, ControlOps, IntControl, StereoVolumeControl, SwitchControl}; -pub use self::control_primitive::{Ctl, ElemId}; -pub use self::control_tlv::{ControlTLV, TLV}; - -pub use self::card::Error as CardError; -pub use self::control::Error as ControlError; -pub use self::control_tlv::Error as ControlTLVError; -pub use self::elem::Error as ElemError; - -#[allow(unused_imports)] -pub use cros_alsa_derive::*; diff --git a/init/cras.conf b/init/cras.conf index 20847494..e7df7991 100644 --- a/init/cras.conf +++ b/init/cras.conf @@ -9,9 +9,6 @@ description "Chrome OS audio server" author "chromium-os-dev@chromium.org" env CRAS_SOCKET_DIR=/run/cras -env CRAS_VMS_SOCKET_DIR=/run/cras/vms -env CRAS_PLUGIN_DIR=/run/cras/vms/plugin -env CRAS_ARGS= start on starting system-services stop on stopping system-services @@ -23,20 +20,6 @@ limit rtprio 12 12 pre-start script mkdir -p -m 1770 "${CRAS_SOCKET_DIR}" chown -R cras:cras "${CRAS_SOCKET_DIR}" - mkdir -p -m 1770 "${CRAS_VMS_SOCKET_DIR}" - chown -R cras:cras "${CRAS_VMS_SOCKET_DIR}" - for socket_dir in playback unified; do - mkdir -p -m 1770 "${CRAS_PLUGIN_DIR}/${socket_dir}" - chown -R cras:cras "${CRAS_PLUGIN_DIR}/${socket_dir}" - done - mkdir -m 0755 -p /var/lib/cras - chown -R cras:cras /var/lib/cras end script exec /bin/sh /usr/share/cros/init/cras.sh - -# sound_card_init uses CRAS stop timestamp as a criterion to skip boot time -# calibration for DSM. -post-stop script - echo "$(date +---%\nsecs:\ %s%\nnanos:\ %N)" > /var/lib/cras/stop -end script diff --git a/init/cras.sh b/init/cras.sh index 91114c00..a1a21db2 100644 --- a/init/cras.sh +++ b/init/cras.sh @@ -6,11 +6,6 @@ device_config_dir="$(cros_config /audio/main cras-config-dir)" internal_ucm_suffix="$(cros_config /audio/main ucm-suffix)" -# Deprecate HSP since it's just too old. -# TODO(hychao): Clean up all CRAS codes that are related to HSP once we're -# sure no headset breaks because of that. -DISABLE_PROFILE="--disable_profile=hsp" - # Handle legacy config. if [ -z "${device_config_dir}" ]; then # Disable HSP/HFP on Google WiFi (Gale) with UART-HCI Bluetooth @@ -48,6 +43,7 @@ exec minijail0 -u cras -g cras -G --uts -v -l \ -k 'tmpfs,/run,tmpfs,MS_NODEV|MS_NOEXEC|MS_NOSUID,mode=755,size=10M' \ -b /run/cras,/run/cras,1 \ -b /run/dbus,/run/dbus,1 \ + -b /run/systemd/journal \ -b /run/udev,/run/udev \ -b /dev,/dev \ -b /dev/shm,/dev/shm,1 \ @@ -61,4 +57,4 @@ exec minijail0 -u cras -g cras -G --uts -v -l \ -- \ /usr/bin/cras \ ${DSP_CONFIG} ${DEVICE_CONFIG_DIR} ${DISABLE_PROFILE} \ - ${INTERNAL_UCM_SUFFIX} ${CRAS_ARGS} + ${INTERNAL_UCM_SUFFIX} diff --git a/scripts/asoc_dapm_graph b/scripts/asoc_dapm_graph index fd43736d..f02c60c5 100755 --- a/scripts/asoc_dapm_graph +++ b/scripts/asoc_dapm_graph @@ -42,7 +42,7 @@ def handle_widgets(path): for l in lines[1:]: l = l.rstrip() # The string format is (in/out) "switch" "widget". - edge = list(filter(None, re.split(r' (in|out) "(.+)" "(.+)"', l))) + edge = filter(None, re.split(r' (in|out) "(.+)" "(.+)"', l)) if len(edge) != 3: continue diff --git a/scripts/audio_diagnostics b/scripts/audio_diagnostics index b754c07c..c3fe4f8d 100755 --- a/scripts/audio_diagnostics +++ b/scripts/audio_diagnostics @@ -7,37 +7,21 @@ # Collect information about the audio system from top to bottom. dump_cards() { - # shellcheck disable=SC2068 for card in ${@} do - echo "=== amixer -c ${card} scontents ===" - amixer -c "${card}" scontents - echo "=== amixer -c ${card} contents ===" - amixer -c "${card}" contents + echo '=== amixer -c' $card scontents '===' + amixer -c $card scontents + echo '=== amixer -c' $card contents '===' + amixer -c $card contents done } -# Helper function: in_the_list $1 $2 -# Returns 0 if str $1 is included in delimited str $2; otherwise 1 -in_the_list() { - for item in $2 - do - if [ "$1" = "${item}" ]; then - return 0 - fi - done - return 1 -} - echo '=== cras_test_client --dump_server_info ===' cras_test_client --dump_server_info echo '=== cras_test_client --dump_audio_thread ===' cras_test_client --dump_audio_thread -echo '=== cras_test_client --dump_main ===' -cras_test_client --dump_main - echo '=== cras_test_client --dump_bt ===' cras_test_client --dump_bt @@ -49,81 +33,28 @@ aplay -l echo '=== arecord -l ===' arecord -l -output_cards=$( - aplay -l | grep -E ^card | sed 's/card \([0-9]\+\).*/\1/' | sort -u) -dump_cards "${output_cards}" +output_cards=$(aplay -l | egrep ^card | sed 's/card \([0-9]\+\).*/\1/' | sort -u) +dump_cards $output_cards -input_cards=$( - arecord -l | grep -E ^card | sed 's/card \([0-9]\+\).*/\1/' | sort -u) -dump_cards "${input_cards}" +input_cards=$(arecord -l | egrep ^card | sed 's/card \([0-9]\+\).*/\1/' | sort -u) +dump_cards $input_cards # HDA codec for codecs on x86. codecs=$(find /proc/asound -mindepth 2 -maxdepth 2 -path '*card*/codec#*') -for codec in ${codecs} +for codec in $codecs do - echo "=== codec: ${codec} ===" - cat "${codec}" + echo '=== codec:' $codec '===' + cat $codec done # I2C dump for codecs on arm. # Find lines like "max98088.7-0010" and extract "7 0x0010" from it. if [ -e /sys/kernel/debug/asoc/codecs ]; then sed_expr='s/^\([^.-]\+\)\.\([0-9]\+\)-\([0-9]\+\)$/\2 0x\3/p' - sed -n "${sed_expr}" /sys/kernel/debug/asoc/codecs | - while read -r i2c_addr + sed -n "$sed_expr" /sys/kernel/debug/asoc/codecs | + while read i2c_addr do - echo "=== i2cdump -f -y ${i2c_addr} ===" - i2cdump -f -y "${i2c_addr}" + echo '===' i2cdump -f -y $i2c_addr '===' + i2cdump -f -y $i2c_addr done fi - -# Dump registers from regmaps - -# List of audio components -# For kernel>=4.14, it is in /sys/kernel/debug/asoc/components -# For kernel<4.14, it is in /sys/kernel/debug/asoc/codecs -if [ -f /sys/kernel/debug/asoc/components ]; then - audio_comps=$(cat /sys/kernel/debug/asoc/components) -else - audio_comps=$(cat /sys/kernel/debug/asoc/codecs) -fi - -# Blocklist regmap name of dumping registers (tracked by b/154177454) -# Use the blank space as delimiter, e.g. 'name_a name_b name_c' -name_blocklist='snd_hda_codec_hdmi' - -for file_path in /sys/kernel/debug/regmap/* -do - [ -e "${file_path}" ] || break # handle the case of no files - component=$(basename "${file_path}") - - # Skip dumping registers if component is not listed in audio_comps - if ! in_the_list "${component}" "${audio_comps}"; then - continue - fi - - if [ ! -f "${file_path}/name" ]; then - echo "Failed at dump registers: ${file_path}" - continue - fi - - name=$(cat "${file_path}/name") - echo "=== dump registers component: ${component} name: ${name} ===" - - # Skip dumping registers if regmap's name is in name_blocklist - if in_the_list "${name}" "${name_blocklist}"; then - echo 'skipped dumping due to b/154177454' - continue - fi - - # Store back the original value - # Note: $(cat cache_bypass) returns 'Y' if flag is on; otherwise 'N' - cache_bypass=$(cat "${file_path}/cache_bypass") - if [ "${cache_bypass}" = "N" ]; then - echo 1 > "${file_path}/cache_bypass" - fi - cat "${file_path}/registers" - if [ "${cache_bypass}" = "N" ]; then - echo 0 > "${file_path}/cache_bypass" - fi -done diff --git a/scripts/audio_tuning/frontend/audio.js b/scripts/audio_tuning/frontend/audio.js index 98870cdd..2476f1a9 100644 --- a/scripts/audio_tuning/frontend/audio.js +++ b/scripts/audio_tuning/frontend/audio.js @@ -1105,7 +1105,7 @@ function check_button(div, handler) { this.update = update; } -function empty() { +function dummy() { } /* Changes the opacity of a div. */ @@ -1185,7 +1185,7 @@ function drc_card(parent, index, lower_freq, freq_label) { var f_slider; if (lower_freq == 0) { /* Special case for the lowest band */ f_slider = new slider_input_log(table, freq_label, lower_freq, 0, 1, - 'Hz', 0, empty); + 'Hz', 0, dummy); f_slider.hide(true); } else { f_slider = new slider_input_log(table, freq_label, lower_freq, 1, @@ -1570,7 +1570,7 @@ function DrcDrawer(canvas) { var kneeThresholdDb; var kneeThreshold; var ykneeThresholdDb; - var mainLinearGain; + var masterLinearGain; var maxOutputDb = 6; var minOutputDb = -36; @@ -1662,10 +1662,10 @@ function DrcDrawer(canvas) { kneeThreshold = dBToLinear(kneeThresholdDb); ykneeThresholdDb = linearToDb(kneeCurve(kneeThreshold, curve_k)); - /* Calculate mainLinearGain */ + /* Calculate masterLinearGain */ var fullRangeGain = saturate(1, curve_k); var fullRangeMakeupGain = Math.pow(1 / fullRangeGain, 0.6); - mainLinearGain = dBToLinear(boost) * fullRangeMakeupGain; + masterLinearGain = dBToLinear(boost) * fullRangeMakeupGain; /* Clear canvas */ var width = canvas.width; @@ -1725,7 +1725,7 @@ function DrcDrawer(canvas) { var inputDb = xpixelToDb(x); var inputLinear = dBToLinear(inputDb); var outputLinear = saturate(inputLinear, curve_k); - outputLinear *= mainLinearGain; + outputLinear *= masterLinearGain; var outputDb = linearToDb(outputLinear); var y = dBToYPixel(outputDb); diff --git a/scripts/volume_tuning/volume.js b/scripts/volume_tuning/volume.js index 88f39984..c5f05266 100644 --- a/scripts/volume_tuning/volume.js +++ b/scripts/volume_tuning/volume.js @@ -116,7 +116,7 @@ function redraw() { var max = parseFloat(minmax_boxes[1].value); var step = parseFloat(minmax_boxes[2].value); - // Soundness checks + // Sanity checks if (isNaN(min) || isNaN(max) || isNaN(step)) return; if (min >= max || step <= 0 || (max - min) / step > 10000) return; diff --git a/seccomp/cras-seccomp-amd64.policy b/seccomp/cras-seccomp-amd64.policy index afa6ace6..06dc2243 100644 --- a/seccomp/cras-seccomp-amd64.policy +++ b/seccomp/cras-seccomp-amd64.policy @@ -11,7 +11,6 @@ poll: 1 ppoll: 1 fstat: 1 write: 1 -writev: 1 open: 1 openat: 1 close: 1 @@ -20,7 +19,6 @@ getrandom: 1 access: 1 fcntl: 1 getdents: 1 -getdents64: 1 sendmsg: 1 stat: 1 statfs: 1 @@ -36,13 +34,10 @@ futex: 1 lseek: 1 rt_sigaction: 1 socket: arg0 == AF_UNIX || arg0 == AF_BLUETOOTH || arg0 == AF_NETLINK -socketpair: 1 unlink: 1 nanosleep: 1 -clock_nanosleep: 1 pipe: 1 ftruncate: 1 -fallocate: 1 mprotect: 1 connect: 1 getsockname: 1 @@ -64,7 +59,6 @@ setrlimit: 1 listen: 1 clone: 1 set_robust_list: 1 -setpriority: 1 getresuid: 1 getresgid: 1 sched_setscheduler: 1 @@ -92,4 +86,3 @@ prlimit64: 1 tgkill: 1 mremap: 1 dup: 1 -gettimeofday: 1 diff --git a/seccomp/cras-seccomp-arm.policy b/seccomp/cras-seccomp-arm.policy index cbaa622b..f917036f 100644 --- a/seccomp/cras-seccomp-arm.policy +++ b/seccomp/cras-seccomp-arm.policy @@ -3,13 +3,10 @@ # found in the LICENSE file. clock_gettime: 1 -clock_gettime64: 1 poll: 1 read: 1 ppoll: 1 -ppoll_time64: 1 write: 1 -writev: 1 recv: 1 send: 1 recvmsg: 1 @@ -41,13 +38,10 @@ unlink: 1 lsetxattr: 1 rt_sigprocmask: 1 ftruncate: 1 -fallocate: 1 futex: 1 -futex_time64: 1 execve: 1 set_robust_list: 1 socket: arg0 == AF_UNIX || arg0 == AF_BLUETOOTH || arg0 == AF_NETLINK -socketpair: 1 clone: 1 setsockopt: 1 geteuid32: 1 @@ -67,8 +61,6 @@ exit_group: 1 getsockname: 1 getdents: 1 nanosleep: 1 -clock_nanosleep: 1 -clock_nanosleep_time64: 1 epoll_ctl: 1 sched_setscheduler: 1 restart_syscall: 1 @@ -77,10 +69,8 @@ getresuid32: 1 exit: 1 prctl: arg0 == PR_SET_NAME clock_getres: 1 -clock_getres_time64: 1 epoll_create1: 1 fchmod: 1 -setpriority: 1 setrlimit: 1 listen: 1 gettid: 1 @@ -91,6 +81,7 @@ getresgid32: 1 pipe2: 1 sched_get_priority_max: 1 sysinfo: 1 +flock: 1 # Allow ioctl command of type 'A' and 'U' for SNDRV_PCM_IOCTL_* and # SNDRV_CTL_IOCTL_*, and EVIOCGSW(8), EVIOCGNAME(256), EVIOCGBIT(0x05, 8), @@ -101,4 +92,3 @@ prlimit64: 1 tgkill: 1 mremap: 1 dup: 1 -_newselect: 1 diff --git a/seccomp/cras-seccomp-arm64.policy b/seccomp/cras-seccomp-arm64.policy index 4b523552..64f32440 100644 --- a/seccomp/cras-seccomp-arm64.policy +++ b/seccomp/cras-seccomp-arm64.policy @@ -10,7 +10,6 @@ ioctl: arg1 in 0xffff41ff && arg1 & 0x00004100 || arg1 in 0xffff55ff && arg1 & 0 ppoll: 1 read: 1 write: 1 -writev: 1 newfstatat: 1 fstat: 1 openat: 1 @@ -31,7 +30,6 @@ sendto: 1 brk: 1 munmap: 1 socket: arg0 == AF_UNIX || arg0 == AF_BLUETOOTH || arg0 == AF_NETLINK -socketpair: 1 statfs: 1 getsockopt: 1 accept: 1 @@ -39,7 +37,6 @@ pipe2: 1 prctl: arg0 == PR_SET_NAME futex: 1 ftruncate: 1 -fallocate: 1 connect: 1 bind: 1 clock_getres: 1 @@ -53,6 +50,7 @@ exit_group: 1 fchmod: 1 fchmodat: 1 flock: 1 +flock: 1 getegid: 1 geteuid: 1 getgid: 1 @@ -68,7 +66,6 @@ listen: 1 lsetxattr: 1 madvise: 1 nanosleep: 1 -clock_nanosleep: 1 restart_syscall: 1 rt_sigprocmask: 1 rt_sigreturn: 1 @@ -77,7 +74,6 @@ sched_get_priority_min: 1 sched_setscheduler: 1 setrlimit: 1 set_robust_list: 1 -setpriority: 1 setsockopt: 1 set_tid_address: 1 sysinfo: 1 diff --git a/sof_sys/.gitignore b/sof_sys/.gitignore deleted file mode 100644 index fa8d85ac..00000000 --- a/sof_sys/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Cargo.lock -target diff --git a/sof_sys/.rustfmt.toml b/sof_sys/.rustfmt.toml deleted file mode 100644 index a2db3012..00000000 --- a/sof_sys/.rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -use_field_init_shorthand = true -use_try_shorthand = true diff --git a/sof_sys/Cargo.toml b/sof_sys/Cargo.toml deleted file mode 100644 index 21934ee1..00000000 --- a/sof_sys/Cargo.toml +++ /dev/null @@ -1,4 +0,0 @@ -[package] -name = "sof_sys" -version = "0.1.0" -authors = ["The Chromium OS Authors"] diff --git a/sof_sys/generator/.gitignore b/sof_sys/generator/.gitignore deleted file mode 100644 index 03314f77..00000000 --- a/sof_sys/generator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Cargo.lock diff --git a/sof_sys/generator/Cargo.toml b/sof_sys/generator/Cargo.toml deleted file mode 100644 index 672d41da..00000000 --- a/sof_sys/generator/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "generator" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -[dependencies] -bindgen = "0.43.0" diff --git a/sof_sys/generator/README.md b/sof_sys/generator/README.md deleted file mode 100644 index 3e2ca771..00000000 --- a/sof_sys/generator/README.md +++ /dev/null @@ -1 +0,0 @@ -Use `cargo run` to generate rust bindings at sof_sys/src/bindings.rs diff --git a/sof_sys/generator/src/main.rs b/sof_sys/generator/src/main.rs deleted file mode 100644 index 60f0102d..00000000 --- a/sof_sys/generator/src/main.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -extern crate bindgen; - -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; - -fn main() { - let bindings = bindgen::Builder::default() - .header("wrapper.h") - .derive_debug(false) - .clang_arg("-I../../../sound-open-firmware-private/src/include") - .whitelist_type("sof_abi_hdr") - .whitelist_type("sof_ipc_ctrl_cmd") - .generate() - .expect("Unable to generate bindings"); - - let header = b"// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/* - * generated from files in sound-open-firmware-private/src/include: - * kernel/header.h - * ipc/control.h - */ - -"; - - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from("../src").join("bindings.rs"); - - let mut output_file = - File::create(&out_path).expect(&format!("Couldn't create {:?}", out_path)); - output_file - .write_all(header) - .expect("Couldn't write header"); - output_file - .write_all(bindings.to_string().as_bytes()) - .expect("Couldn't write bindings"); -} diff --git a/sof_sys/generator/wrapper.h b/sof_sys/generator/wrapper.h deleted file mode 100644 index 5bac0f57..00000000 --- a/sof_sys/generator/wrapper.h +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2021 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#include <kernel/header.h> -#include <ipc/control.h> diff --git a/sof_sys/src/bindings.rs b/sof_sys/src/bindings.rs deleted file mode 100644 index 7bed0dcf..00000000 --- a/sof_sys/src/bindings.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/* - * generated from files in sound-open-firmware-private/src/include: - * kernel/header.h - * ipc/control.h - */ - -/* automatically generated by rust-bindgen */ - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>); -impl<T> __IncompleteArrayField<T> { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl<T> ::std::clone::Clone for __IncompleteArrayField<T> { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {} -pub type __uint32_t = ::std::os::raw::c_uint; -/// \brief Header for all non IPC ABI data. -/// -/// Identifies data type, size and ABI. -/// Data header used for all component data structures and binary blobs sent to -/// firmware as runtime data. This data is typically sent by userspace -/// applications and tunnelled through any OS kernel (via binary kcontrol on -/// Linux) to the firmware. -#[repr(C, packed)] -pub struct sof_abi_hdr { - ///< 'S', 'O', 'F', '\0' - pub magic: u32, - ///< component specific type - pub type_: u32, - ///< size in bytes of data excl. this struct - pub size: u32, - ///< SOF ABI version - pub abi: u32, - ///< reserved for future use - pub reserved: [u32; 4usize], - ///< Component data - opaque to core - pub data: __IncompleteArrayField<u32>, -} -#[test] -fn bindgen_test_layout_sof_abi_hdr() { - assert_eq!( - ::std::mem::size_of::<sof_abi_hdr>(), - 32usize, - concat!("Size of: ", stringify!(sof_abi_hdr)) - ); - assert_eq!( - ::std::mem::align_of::<sof_abi_hdr>(), - 1usize, - concat!("Alignment of ", stringify!(sof_abi_hdr)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<sof_abi_hdr>())).magic as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(sof_abi_hdr), - "::", - stringify!(magic) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<sof_abi_hdr>())).type_ as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(sof_abi_hdr), - "::", - stringify!(type_) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<sof_abi_hdr>())).size as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(sof_abi_hdr), - "::", - stringify!(size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<sof_abi_hdr>())).abi as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(sof_abi_hdr), - "::", - stringify!(abi) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<sof_abi_hdr>())).reserved as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(sof_abi_hdr), - "::", - stringify!(reserved) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<sof_abi_hdr>())).data as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(sof_abi_hdr), - "::", - stringify!(data) - ) - ); -} -///< maps to ALSA volume style controls -pub const sof_ipc_ctrl_cmd_SOF_CTRL_CMD_VOLUME: sof_ipc_ctrl_cmd = 0; -///< maps to ALSA enum style controls -pub const sof_ipc_ctrl_cmd_SOF_CTRL_CMD_ENUM: sof_ipc_ctrl_cmd = 1; -///< maps to ALSA switch style controls -pub const sof_ipc_ctrl_cmd_SOF_CTRL_CMD_SWITCH: sof_ipc_ctrl_cmd = 2; -///< maps to ALSA binary style controls -pub const sof_ipc_ctrl_cmd_SOF_CTRL_CMD_BINARY: sof_ipc_ctrl_cmd = 3; -/// Control command type. -pub type sof_ipc_ctrl_cmd = u32; diff --git a/sof_sys/src/lib.rs b/sof_sys/src/lib.rs deleted file mode 100644 index 57119cfa..00000000 --- a/sof_sys/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#![allow(clippy::unreadable_literal)] -#![allow(clippy::cognitive_complexity)] -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -pub mod bindings; -#[allow(unused_imports)] -pub use bindings::sof_abi_hdr; diff --git a/sound_card_init/.gitignore b/sound_card_init/.gitignore deleted file mode 100644 index b6e87008..00000000 --- a/sound_card_init/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -**/target/ - -# These are backup files generated by rustfmt -**/*.rs.bk diff --git a/sound_card_init/99-sound_card_init.rules b/sound_card_init/99-sound_card_init.rules deleted file mode 100644 index 82a3aec8..00000000 --- a/sound_card_init/99-sound_card_init.rules +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -SUBSYSTEM!="sound", GOTO="sci_end" -ACTION!="change", GOTO="sci_end" -KERNEL!="card*", GOTO="sci_end" - -GOTO="sci_action" - -LABEL="sci_action" -RUN+="/sbin/initctl start sound_card_init SOUND_CARD_ID=$attr{id}" -LABEL="sci_end" diff --git a/sound_card_init/Cargo.lock b/sound_card_init/Cargo.lock deleted file mode 100644 index c89ad1ec..00000000 --- a/sound_card_init/Cargo.lock +++ /dev/null @@ -1,286 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "alsa-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644d308f5822c2b39fba5a6d850f74c208bf73c61d1d2dfad62505d6960e4977" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "amp" -version = "0.1.0" -dependencies = [ - "cros_alsa", - "dsm", - "libcras", - "remain", - "serde", - "serde_yaml", - "sof_sys", - "sys_util", -] - -[[package]] -name = "android_log-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" - -[[package]] -name = "assertions" -version = "0.1.0" - -[[package]] -name = "audio_streams" -version = "0.1.0" -dependencies = [ - "sync", - "sys_util", -] - -[[package]] -name = "cras-sys" -version = "0.1.0" -dependencies = [ - "audio_streams", - "data_model", -] - -[[package]] -name = "cros_alsa" -version = "0.1.0" -dependencies = [ - "alsa-sys", - "cros_alsa_derive", - "libc", - "remain", -] - -[[package]] -name = "cros_alsa_derive" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "data_model" -version = "0.1.0" -dependencies = [ - "assertions", - "libc", -] - -[[package]] -name = "dsm" -version = "0.1.0" -dependencies = [ - "audio_streams", - "cros_alsa", - "libcras", - "remain", - "serde", - "serde_yaml", - "sys_util", -] - -[[package]] -name = "dtoa" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "libc" -version = "0.2.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" - -[[package]] -name = "libcras" -version = "0.1.0" -dependencies = [ - "audio_streams", - "cras-sys", - "data_model", - "libc", - "sys_util", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "pkg-config" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" - -[[package]] -name = "poll_token_derive" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "remain" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ba1e78fa68412cb93ef642fd4d20b9a941be49ee9333875ebaf13112673ea7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde" -version = "1.0.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_yaml" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "971be8f6e4d4a47163b405a3df70d14359186f9ab0f3a3ec37df144ca1ce089f" -dependencies = [ - "dtoa", - "linked-hash-map", - "serde", - "yaml-rust", -] - -[[package]] -name = "sof_sys" -version = "0.1.0" - -[[package]] -name = "sound_card_init" -version = "0.1.0" -dependencies = [ - "amp", - "audio_streams", - "cros_alsa", - "dsm", - "getopts", - "libcras", - "remain", - "serde", - "serde_yaml", - "sof_sys", - "sys_util", -] - -[[package]] -name = "syn" -version = "1.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "sync" -version = "0.1.0" - -[[package]] -name = "sys_util" -version = "0.1.0" -dependencies = [ - "android_log-sys", - "data_model", - "libc", - "poll_token_derive", - "sync", - "syscall_defines", - "tempfile", -] - -[[package]] -name = "syscall_defines" -version = "0.1.0" - -[[package]] -name = "tempfile" -version = "3.0.7" -dependencies = [ - "libc", -] - -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/sound_card_init/Cargo.toml b/sound_card_init/Cargo.toml deleted file mode 100644 index 9d5a107e..00000000 --- a/sound_card_init/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "sound_card_init" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" -description = "Sound Card Initializer" - -[workspace] -members = [ - "amp", - "dsm" -] - -[dependencies] -amp = { path = "amp" } -audio_streams = "*" -cros_alsa = "*" -dsm = { path = "dsm" } -getopts = "0.2" -libcras = "*" -remain = "0.2.1" -serde = { version = "1.0", features = ["derive"] } -serde_yaml = "0.8.11" -sof_sys = "*" -sys_util = "*" - -[patch.crates-io] -audio_streams = { path = "../audio_streams" } # ignored by ebuild -cros_alsa = { path = "../cros_alsa" } # ignored by ebuild -cros_alsa_derive = { path = "../cros_alsa/cros_alsa_derive" } # ignored by ebuild -libcras = { path = "../cras/client/libcras" } # ignored by ebuild -sof_sys = { path = "../sof_sys" } # ignored by ebuild -sys_util = { path = "../../../platform/crosvm/sys_util" } # ignored by ebuild diff --git a/sound_card_init/amp/Cargo.lock b/sound_card_init/amp/Cargo.lock deleted file mode 100644 index 679e60cd..00000000 --- a/sound_card_init/amp/Cargo.lock +++ /dev/null @@ -1,254 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "alsa-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644d308f5822c2b39fba5a6d850f74c208bf73c61d1d2dfad62505d6960e4977" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "amp" -version = "0.1.0" -dependencies = [ - "cros_alsa", - "dsm", - "libcras", - "remain", - "serde", - "serde_yaml", - "sof_sys", - "sys_util", -] - -[[package]] -name = "android_log-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" - -[[package]] -name = "assertions" -version = "0.1.0" - -[[package]] -name = "audio_streams" -version = "0.1.0" -dependencies = [ - "sync", - "sys_util", -] - -[[package]] -name = "cras-sys" -version = "0.1.0" -dependencies = [ - "audio_streams", - "data_model", -] - -[[package]] -name = "cros_alsa" -version = "0.1.0" -dependencies = [ - "alsa-sys", - "cros_alsa_derive", - "libc", - "remain", -] - -[[package]] -name = "cros_alsa_derive" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "data_model" -version = "0.1.0" -dependencies = [ - "assertions", - "libc", -] - -[[package]] -name = "dsm" -version = "0.1.0" -dependencies = [ - "audio_streams", - "cros_alsa", - "libcras", - "remain", - "serde", - "serde_yaml", - "sys_util", -] - -[[package]] -name = "dtoa" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" - -[[package]] -name = "libc" -version = "0.2.84" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" - -[[package]] -name = "libcras" -version = "0.1.0" -dependencies = [ - "audio_streams", - "cras-sys", - "data_model", - "libc", - "sys_util", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "pkg-config" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" - -[[package]] -name = "poll_token_derive" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "remain" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ba1e78fa68412cb93ef642fd4d20b9a941be49ee9333875ebaf13112673ea7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde" -version = "1.0.123" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.123" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_yaml" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "971be8f6e4d4a47163b405a3df70d14359186f9ab0f3a3ec37df144ca1ce089f" -dependencies = [ - "dtoa", - "linked-hash-map", - "serde", - "yaml-rust", -] - -[[package]] -name = "sof_sys" -version = "0.1.0" - -[[package]] -name = "syn" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "sync" -version = "0.1.0" - -[[package]] -name = "sys_util" -version = "0.1.0" -dependencies = [ - "android_log-sys", - "data_model", - "libc", - "poll_token_derive", - "sync", - "syscall_defines", - "tempfile", -] - -[[package]] -name = "syscall_defines" -version = "0.1.0" - -[[package]] -name = "tempfile" -version = "3.0.7" -dependencies = [ - "libc", -] - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/sound_card_init/amp/Cargo.toml b/sound_card_init/amp/Cargo.toml deleted file mode 100644 index 62e63db7..00000000 --- a/sound_card_init/amp/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "amp" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" -description = "The boot time calibration logic for smart amp" - -[dependencies] -cros_alsa = "*" -libcras = "*" -dsm = { path = "../dsm" } -remain = "0.2.1" -serde = { version = "1.0", features = ["derive"]} -serde_yaml = "0.8.11" -sof_sys = "*" -sys_util = "*" diff --git a/sound_card_init/amp/src/lib.rs b/sound_card_init/amp/src/lib.rs deleted file mode 100644 index 7114233d..00000000 --- a/sound_card_init/amp/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2021 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -//! `amp` crate provides `Amp` trait for amplifier initializations and `AmpBuilder` -//! to create `Amp` objects. -#![deny(missing_docs)] - -mod max98373d; -mod max98390d; -use std::path::PathBuf; - -use dsm::Error; - -use max98373d::Max98373; -use max98390d::Max98390; - -type Result<T> = std::result::Result<T, Error>; -const CONF_DIR: &str = "/etc/sound_card_init"; - -/// It creates `Amp` object based on the sound card name. -pub struct AmpBuilder<'a> { - sound_card_id: &'a str, - config_path: PathBuf, -} - -impl<'a> AmpBuilder<'a> { - /// Creates an `AmpBuilder`. - /// # Arguments - /// - /// * `card_name` - card name. - /// * `conf_file` - config file name. - pub fn new(sound_card_id: &'a str, conf_file: &'a str) -> Self { - let config_path = PathBuf::from(CONF_DIR).join(conf_file); - AmpBuilder { - sound_card_id, - config_path, - } - } - - /// Creates an `Amp` based on the sound card name. - pub fn build(&self) -> Result<Box<dyn Amp>> { - match self.sound_card_id { - "sofcmlmax98390d" => { - Ok(Box::new(Max98390::new(self.sound_card_id, &self.config_path)?) as Box<dyn Amp>) - } - "sofrt5682" => { - Ok(Box::new(Max98373::new(self.sound_card_id, &self.config_path)?) as Box<dyn Amp>) - } - _ => Err(Error::UnsupportedSoundCard(self.sound_card_id.to_owned())), - } - } -} - -/// It defines the required functions of amplifier objects. -pub trait Amp { - /// The amplifier boot time calibration flow. - fn boot_time_calibration(&mut self) -> Result<()>; -} diff --git a/sound_card_init/amp/src/max98373d/dsm_param.rs b/sound_card_init/amp/src/max98373d/dsm_param.rs deleted file mode 100644 index d9257522..00000000 --- a/sound_card_init/amp/src/max98373d/dsm_param.rs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::mem; - -use cros_alsa::{Card, TLV}; -use sof_sys::sof_abi_hdr; - -use dsm::{self, Error, Result}; - -/// Amp volume mode enumeration used by set_volume(). -#[derive(Copy, Clone, PartialEq)] -pub enum VolumeMode { - /// Low mode protects the speaker by limiting its output volume if the - /// calibration has not been completed successfully. - Low = 0x1009B9CF, - /// High mode removes the speaker output volume limitation after - /// having successfully completed the calibration. - High = 0x20000000, -} - -#[derive(Copy, Clone)] -/// Calibration mode enumeration. -pub enum CalibMode { - ON = 0x4, - OFF = 0x1, -} - -#[derive(Copy, Clone)] -/// Smart pilot signal mode mode enumeration. -pub enum SPTMode { - ON = 0x1, - OFF = 0x0, -} - -#[derive(Copy, Clone)] -/// DSM Parem field enumeration. -enum DsmAPI { - ParamCount = 0x0, - CalibMode = 0x1, - MakeupGain = 0x5, - DsmRdc = 0x6, - DsmAmbientTemp = 0x8, - AdaptiveRdc = 0x12, - SPTMode = 0x68, -} - -#[derive(Debug)] -/// It implements functions to access the `DSMParam` fields. -pub struct DSMParam { - param_count: usize, - num_channels: usize, - tlv: TLV, -} - -impl DSMParam { - const DWORD_PER_PARAM: usize = 2; - const VALUE_OFFSET: usize = 1; - const SOF_HEADER_SIZE: usize = mem::size_of::<sof_abi_hdr>() / mem::size_of::<i32>(); - - /// Creates an `DSMParam`. - /// # Arguments - /// - /// * `card` - `&Card`. - /// * `num_channels` - number of channels. - /// * `ctl_name` - the mixer control name to access the DSM param. - /// - /// # Results - /// - /// * `DSMParam` - It is initialized by the content of the given byte control . - /// - /// # Errors - /// - /// * If `Card` creation from sound card name fails. - pub fn new(card: &mut Card, num_channels: usize, ctl_name: &str) -> Result<Self> { - let tlv = card.control_tlv_by_name(ctl_name)?.load()?; - Self::try_from_tlv(tlv, num_channels) - } - - /// Sets DSMParam to the given calibration mode. - pub fn set_calibration_mode(&mut self, mode: CalibMode) { - for channel in 0..self.num_channels { - self.set(channel, DsmAPI::CalibMode, mode as i32); - } - } - - /// Sets DSMParam to the given smart pilot signal mode. - pub fn set_spt_mode(&mut self, mode: SPTMode) { - for channel in 0..self.num_channels { - self.set(channel, DsmAPI::SPTMode, mode as i32); - } - } - - /// Sets DSMParam to the given VolumeMode. - pub fn set_volume_mode(&mut self, mode: VolumeMode) { - for channel in 0..self.num_channels { - self.set(channel, DsmAPI::MakeupGain, mode as i32); - } - } - - /// Reads the calibrated rdc from DSMParam. - pub fn get_adaptive_rdc(&self) -> Vec<i32> { - self.get(DsmAPI::AdaptiveRdc) - } - - /// Sets DSMParam to the given the calibrated rdc. - pub fn set_rdc(&mut self, ch: usize, rdc: i32) { - self.set(ch, DsmAPI::DsmRdc, rdc); - } - - /// Sets DSMParam to the given calibrated temp. - pub fn set_ambient_temp(&mut self, ch: usize, temp: i32) { - self.set(ch, DsmAPI::DsmAmbientTemp, temp); - } - - /// Sets the `id` field to the given `val`. - fn set(&mut self, channel: usize, id: DsmAPI, val: i32) { - let pos = Self::value_pos(self.param_count, channel, id); - self.tlv[pos] = val as u32; - } - - /// Gets the val from the `id` field from all the channels. - fn get(&self, id: DsmAPI) -> Vec<i32> { - (0..self.num_channels) - .map(|channel| { - let pos = Self::value_pos(self.param_count, channel, id); - self.tlv[pos] as i32 - }) - .collect() - } - - fn try_from_tlv(tlv: TLV, num_channels: usize) -> Result<Self> { - let param_count_pos = Self::value_pos(0, 0, DsmAPI::ParamCount); - - if tlv.len() < param_count_pos { - return Err(Error::InvalidDSMParam); - } - - let param_count = tlv[param_count_pos] as usize; - - if tlv.len() != Self::SOF_HEADER_SIZE + param_count * num_channels * Self::DWORD_PER_PARAM { - return Err(Error::InvalidDSMParam); - } - - Ok(Self { - param_count, - num_channels, - tlv, - }) - } - - #[inline] - fn value_pos(param_count: usize, channel: usize, id: DsmAPI) -> usize { - Self::SOF_HEADER_SIZE - + (channel * param_count + id as usize) * Self::DWORD_PER_PARAM - + Self::VALUE_OFFSET - } -} - -impl Into<TLV> for DSMParam { - fn into(self) -> TLV { - self.tlv - } -} - -#[cfg(test)] -mod tests { - use super::*; - const PARAM_COUNT: usize = 138; - const CHANNEL_COUNT: usize = 2; - - #[test] - fn test_dsmparam_try_from_tlv_ok() { - let mut data = vec![ - 0u32; - DSMParam::SOF_HEADER_SIZE - + CHANNEL_COUNT * PARAM_COUNT * DSMParam::DWORD_PER_PARAM - ]; - data[DSMParam::value_pos(PARAM_COUNT, 0, DsmAPI::ParamCount)] = PARAM_COUNT as u32; - data[DSMParam::value_pos(PARAM_COUNT, 1, DsmAPI::ParamCount)] = PARAM_COUNT as u32; - - let tlv = TLV::new(0, data); - assert!(DSMParam::try_from_tlv(tlv, CHANNEL_COUNT).is_ok()); - } - - #[test] - fn test_dsmparam_try_from_invalid_len() { - let data = vec![0u32; DSMParam::SOF_HEADER_SIZE]; - - let tlv = TLV::new(0, data); - assert_eq!( - DSMParam::try_from_tlv(tlv, CHANNEL_COUNT).unwrap_err(), - Error::InvalidDSMParam - ); - } - - #[test] - fn test_dsmparam_try_from_param_count() { - let data = vec![ - 0u32; - DSMParam::SOF_HEADER_SIZE - + CHANNEL_COUNT * PARAM_COUNT * DSMParam::DWORD_PER_PARAM - ]; - - let tlv = TLV::new(0, data); - assert_eq!( - DSMParam::try_from_tlv(tlv, CHANNEL_COUNT).unwrap_err(), - Error::InvalidDSMParam - ); - } -} diff --git a/sound_card_init/amp/src/max98373d/mod.rs b/sound_card_init/amp/src/max98373d/mod.rs deleted file mode 100644 index 1ee29ceb..00000000 --- a/sound_card_init/amp/src/max98373d/mod.rs +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -//! `max98373d` module implements the required initialization workflows for sound -//! cards that use max98373d smart amp. -//! It currently supports boot time calibration for max98373d. -#![deny(missing_docs)] -mod dsm_param; -mod settings; - -use std::path::Path; -use std::time::Duration; -use std::{fs, thread}; - -use cros_alsa::{Card, IntControl}; -use dsm::{CalibData, Error, Result, SpeakerStatus, ZeroPlayer, DSM}; -use sys_util::info; - -use crate::Amp; -use dsm_param::*; -use settings::{AmpCalibSettings, DeviceSettings}; - -/// It implements the amplifier boot time calibration flow. -pub struct Max98373 { - card: Card, - setting: AmpCalibSettings, -} - -impl Amp for Max98373 { - /// Performs max98373d boot time calibration. - /// - /// # Errors - /// - /// If any amplifiers fail to complete the calibration. - fn boot_time_calibration(&mut self) -> Result<()> { - if !Path::new(&self.setting.dsm_param).exists() { - return Err(Error::MissingDSMParam); - } - - let num_channels = self.setting.num_channels(); - let dsm = DSM::new( - &self.card.name(), - num_channels, - Self::rdc_to_ohm, - Self::TEMP_UPPER_LIMIT_CELSIUS, - Self::TEMP_LOWER_LIMIT_CELSIUS, - ); - self.set_volume(VolumeMode::Low)?; - - let calib = if !self.setting.boot_time_calibration_enabled { - info!("skip boot time calibration and use vpd values"); - // Needs Rdc updates to be done after internal speaker is ready otherwise - // it would be overwritten by the DSM blob update. - dsm.wait_for_speakers_ready()?; - dsm.get_all_vpd_calibration_value()? - } else { - match dsm.check_speaker_over_heated_workflow()? { - SpeakerStatus::Hot(previous_calib) => previous_calib, - SpeakerStatus::Cold => { - let all_temp = self.get_ambient_temp()?; - let all_rdc = self.do_rdc_calibration()?; - all_rdc - .iter() - .zip(all_temp) - .enumerate() - .map(|(ch, (&rdc, temp))| { - dsm.decide_calibration_value_workflow(ch, CalibData { rdc, temp }) - }) - .collect::<Result<Vec<_>>>()? - } - } - }; - self.apply_calibration_value(&calib)?; - self.set_volume(VolumeMode::High)?; - Ok(()) - } -} - -impl Max98373 { - const TEMP_CALIB_WARM_UP_TIME: Duration = Duration::from_millis(10); - const RDC_CALIB_WARM_UP_TIME: Duration = Duration::from_millis(500); - const RDC_CALIB_INTERVAL: Duration = Duration::from_millis(200); - const CALIB_REPEAT_TIMES: usize = 5; - - const TEMP_UPPER_LIMIT_CELSIUS: f32 = 40.0; - const TEMP_LOWER_LIMIT_CELSIUS: f32 = 0.0; - - /// Creates an `Max98373`. - /// # Arguments - /// - /// * `card_name` - card_name. - /// * `config_path` - config file path. - /// - /// # Results - /// - /// * `Max98373` - It implements the Max98373 functions of boot time calibration. - /// - /// # Errors - /// - /// * If `Card` creation from sound card name fails. - pub fn new(card_name: &str, config_path: &Path) -> Result<Self> { - let conf = fs::read_to_string(config_path) - .map_err(|e| Error::FileIOFailed(config_path.to_path_buf(), e))?; - let settings = DeviceSettings::from_yaml_str(&conf)?; - Ok(Self { - card: Card::new(card_name)?, - setting: settings.amp_calibrations, - }) - } - - /// Triggers the amplifier calibration and reads the calibrated rdc. - /// To get accurate calibration results, the main thread calibrates the amplifier while - /// the `zero_player` starts another thread to play zeros to the speakers. - fn do_rdc_calibration(&mut self) -> Result<Vec<i32>> { - let mut zero_player: ZeroPlayer = Default::default(); - zero_player.start(Self::RDC_CALIB_WARM_UP_TIME)?; - // Playback of zeros is started for Self::RDC_CALIB_WARM_UP_TIME, and the main thread - // can start the calibration. - self.set_spt_mode(SPTMode::OFF)?; - self.set_calibration_mode(CalibMode::ON)?; - // Playback of zeros is started, and the main thread can start the calibration. - let mut avg_rdc = vec![0; self.setting.num_channels()]; - for _ in 0..Self::CALIB_REPEAT_TIMES { - let rdc = self.get_adaptive_rdc()?; - for i in 0..self.setting.num_channels() { - avg_rdc[i] += rdc[i]; - } - thread::sleep(Self::RDC_CALIB_INTERVAL); - } - self.set_spt_mode(SPTMode::ON)?; - self.set_calibration_mode(CalibMode::OFF)?; - zero_player.stop()?; - - avg_rdc = avg_rdc - .iter() - .map(|val| val / Self::CALIB_REPEAT_TIMES as i32) - .collect(); - Ok(avg_rdc) - } - - /// Sets the card volume control to the given VolumeMode. - fn set_volume(&mut self, mode: VolumeMode) -> Result<()> { - let mut dsm_param = DSMParam::new( - &mut self.card, - self.setting.num_channels(), - &self.setting.dsm_param_read_ctrl, - )?; - - dsm_param.set_volume_mode(mode); - - self.card - .control_tlv_by_name(&self.setting.dsm_param_write_ctrl)? - .save(dsm_param.into()) - .map_err(Error::DSMParamUpdateFailed)?; - Ok(()) - } - - /// Applies the calibration value to the amp. - fn apply_calibration_value(&mut self, calib: &[CalibData]) -> Result<()> { - let mut dsm_param = DSMParam::new( - &mut self.card, - self.setting.num_channels(), - &self.setting.dsm_param_read_ctrl, - )?; - for ch in 0..self.setting.num_channels() { - dsm_param.set_rdc(ch, calib[ch].rdc); - dsm_param.set_ambient_temp(ch, Self::celsius_to_dsm_unit(calib[ch].temp)); - } - self.card - .control_tlv_by_name(&self.setting.dsm_param_write_ctrl)? - .save(dsm_param.into()) - .map_err(Error::DSMParamUpdateFailed)?; - Ok(()) - } - - /// Rdc (ohm) = [ID:0x12] * 3.66 / 2^27 - #[inline] - fn rdc_to_ohm(x: i32) -> f32 { - (3.66 * x as f32) / (1 << 27) as f32 - } - - /// Returns the ambient temperature in celsius degree. - fn get_ambient_temp(&mut self) -> Result<Vec<f32>> { - let mut zero_player: ZeroPlayer = Default::default(); - zero_player.start(Self::TEMP_CALIB_WARM_UP_TIME)?; - let mut temps = Vec::new(); - for x in 0..self.setting.num_channels() as usize { - let temp = self - .card - .control_by_name::<IntControl>(&self.setting.temp_ctrl[x])? - .get()?; - let celsius = Self::measured_temp_to_celsius(temp); - temps.push(celsius); - } - zero_player.stop()?; - - Ok(temps) - } - - /// Converts the measured ambient temperature to celsius unit. - #[inline] - fn measured_temp_to_celsius(temp: i32) -> f32 { - // Measured Temperature (°C) = ([Mixer Val] * 1.28) - 29 - (temp as f32 * 1.28) - 29.0 - } - - /// Converts the ambient temperature from celsius to the DsmSetAPI::DsmAmbientTemp unit. - #[inline] - fn celsius_to_dsm_unit(celsius: f32) -> i32 { - // Temperature (℃) = [ID:0x12] / 2^19 - (celsius * (1 << 19) as f32) as i32 - } - - /// Sets the amp to the given smart pilot signal mode. - fn set_spt_mode(&mut self, mode: SPTMode) -> Result<()> { - let mut dsm_param = DSMParam::new( - &mut self.card, - self.setting.num_channels(), - &self.setting.dsm_param_read_ctrl, - )?; - dsm_param.set_spt_mode(mode); - self.card - .control_tlv_by_name(&self.setting.dsm_param_write_ctrl)? - .save(dsm_param.into()) - .map_err(Error::DSMParamUpdateFailed)?; - Ok(()) - } - - /// Sets the amp to the given the calibration mode. - fn set_calibration_mode(&mut self, mode: CalibMode) -> Result<()> { - let mut dsm_param = DSMParam::new( - &mut self.card, - self.setting.num_channels(), - &self.setting.dsm_param_read_ctrl, - )?; - dsm_param.set_calibration_mode(mode); - self.card - .control_tlv_by_name(&self.setting.dsm_param_write_ctrl)? - .save(dsm_param.into()) - .map_err(Error::DSMParamUpdateFailed)?; - Ok(()) - } - - /// Reads the calibrated rdc. - /// Must be called when the calibration mode in on. - fn get_adaptive_rdc(&mut self) -> Result<Vec<i32>> { - let dsm_param = DSMParam::new( - &mut self.card, - self.setting.num_channels(), - &self.setting.dsm_param_read_ctrl, - )?; - Ok(dsm_param.get_adaptive_rdc()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn celsius_to_dsm_unit() { - assert_eq!(Max98373::celsius_to_dsm_unit(37.0), 0x01280000); - assert_eq!(Max98373::celsius_to_dsm_unit(50.0), 0x01900000); - } - - #[test] - fn rdc_to_ohm() { - assert_eq!(Max98373::rdc_to_ohm(0x05cea0c7), 2.656767); - } - - #[test] - fn measured_temp_to_celsius() { - assert_eq!(Max98373::measured_temp_to_celsius(56), 42.68); - } -} diff --git a/sound_card_init/amp/src/max98373d/settings.rs b/sound_card_init/amp/src/max98373d/settings.rs deleted file mode 100644 index 1d6e64e5..00000000 --- a/sound_card_init/amp/src/max98373d/settings.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::string::String; - -use dsm::{self, Error, Result}; -use serde::Deserialize; -/// `DeviceSettings` includes the settings of max98373. It currently includes: -/// * the settings of amplifier calibration. -/// * the path of dsm_param. -#[derive(Debug, Default, PartialEq, Deserialize, Clone)] -pub struct DeviceSettings { - pub amp_calibrations: AmpCalibSettings, -} - -/// `AmpCalibSettings` includes the settings needed for amplifier calibration. -#[derive(Debug, Default, PartialEq, Deserialize, Clone)] -pub struct AmpCalibSettings { - pub dsm_param_read_ctrl: String, - pub dsm_param_write_ctrl: String, - pub temp_ctrl: Vec<String>, - // Path of the dsm_param.bin file. - pub dsm_param: String, - pub boot_time_calibration_enabled: bool, -} - -impl AmpCalibSettings { - /// Returns the number of channels. - pub fn num_channels(&self) -> usize { - self.temp_ctrl.len() - } -} - -impl DeviceSettings { - /// Creates a `DeviceSettings` from a yaml str. - pub fn from_yaml_str(conf: &str) -> Result<DeviceSettings> { - let settings: DeviceSettings = serde_yaml::from_str(conf) - .map_err(|e| Error::DeserializationFailed("DeviceSettings".to_owned(), e))?; - Ok(settings) - } -} diff --git a/sound_card_init/amp/src/max98390d/mod.rs b/sound_card_init/amp/src/max98390d/mod.rs deleted file mode 100644 index 601165ec..00000000 --- a/sound_card_init/amp/src/max98390d/mod.rs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -//! `max98390d` module implements the required initialization workflows for sound -//! cards that use max98390d smart amp. -//! It currently supports boot time calibration for max98390d. -#![deny(missing_docs)] -mod settings; - -use std::time::Duration; -use std::{fs, path::Path}; - -use cros_alsa::{Card, IntControl, SwitchControl}; -use dsm::{CalibData, Error, Result, SpeakerStatus, TempConverter, ZeroPlayer, DSM}; - -use crate::Amp; -use settings::{AmpCalibSettings, DeviceSettings}; - -/// Amp volume mode emulation used by set_volume(). -#[derive(PartialEq, Clone, Copy)] -enum VolumeMode { - /// Low mode protects the speaker by limiting its output volume if the - /// calibration has not been completed successfully. - Low = 138, - /// High mode removes the speaker output volume limitation after - /// having successfully completed the calibration. - High = 148, -} - -/// It implements the Max98390 functions of boot time calibration. -#[derive(Debug)] -pub struct Max98390 { - card: Card, - setting: AmpCalibSettings, -} - -impl Amp for Max98390 { - /// Performs max98390d boot time calibration. - /// - /// # Errors - /// - /// If the amplifier fails to complete the calibration. - fn boot_time_calibration(&mut self) -> Result<()> { - if !Path::new(&self.setting.dsm_param).exists() { - return Err(Error::MissingDSMParam); - } - - let mut dsm = DSM::new( - &self.card.name(), - self.setting.num_channels(), - Self::rdc_to_ohm, - Self::TEMP_UPPER_LIMIT_CELSIUS, - Self::TEMP_LOWER_LIMIT_CELSIUS, - ); - dsm.set_temp_converter(TempConverter::new( - Self::dsm_unit_to_celsius, - Self::celsius_to_dsm_unit, - )); - - self.set_volume(VolumeMode::Low)?; - let calib = match dsm.check_speaker_over_heated_workflow()? { - SpeakerStatus::Hot(previous_calib) => previous_calib, - SpeakerStatus::Cold => self - .do_calibration()? - .iter() - .enumerate() - .map(|(ch, calib_data)| dsm.decide_calibration_value_workflow(ch, *calib_data)) - .collect::<Result<Vec<_>>>()?, - }; - self.apply_calibration_value(calib)?; - self.set_volume(VolumeMode::High)?; - Ok(()) - } -} - -impl Max98390 { - const TEMP_UPPER_LIMIT_CELSIUS: f32 = 40.0; - const TEMP_LOWER_LIMIT_CELSIUS: f32 = 0.0; - const RDC_CALIB_WARM_UP_TIME: Duration = Duration::from_millis(300); - - /// Creates an `Max98390`. - /// # Arguments - /// - /// * `card_name` - card name. - /// * `config_path` - config file path. - /// - /// # Results - /// - /// * `Max98390` - It implements the Max98390 functions of boot time calibration. - /// - /// # Errors - /// - /// * If `Card` creation from sound card name fails. - pub fn new(card_name: &str, config_path: &Path) -> Result<Self> { - let conf = fs::read_to_string(config_path) - .map_err(|e| Error::FileIOFailed(config_path.to_path_buf(), e))?; - let settings = DeviceSettings::from_yaml_str(&conf)?; - Ok(Self { - card: Card::new(card_name)?, - setting: settings.amp_calibrations, - }) - } - - /// Sets the card volume control to given VolumeMode. - fn set_volume(&mut self, mode: VolumeMode) -> Result<()> { - for control in &self.setting.controls { - self.card - .control_by_name::<IntControl>(&control.volume_ctrl)? - .set(mode as i32)?; - } - Ok(()) - } - - /// Applies the calibration value to the amp. - fn apply_calibration_value(&mut self, calib: Vec<CalibData>) -> Result<()> { - for (ch, &CalibData { rdc, temp }) in calib.iter().enumerate() { - self.card - .control_by_name::<IntControl>(&self.setting.controls[ch].rdc_ctrl)? - .set(rdc)?; - self.card - .control_by_name::<IntControl>(&self.setting.controls[ch].temp_ctrl)? - .set(Self::celsius_to_dsm_unit(temp))?; - } - Ok(()) - } - - /// Triggers the amplifier calibration and reads the calibrated rdc and ambient_temp value - /// from the mixer control. - /// To get accurate calibration results, the main thread calibrates the amplifier while - /// the `zero_player` starts another thread to play zeros to the speakers. - fn do_calibration(&mut self) -> Result<Vec<CalibData>> { - let mut zero_player: ZeroPlayer = Default::default(); - zero_player.start(Self::RDC_CALIB_WARM_UP_TIME)?; - // Playback of zeros is started for Self::RDC_CALIB_WARM_UP_TIME, and the main thread - // can start the calibration. - let setting = &self.setting; - let card = &mut self.card; - let calib = setting - .controls - .iter() - .map(|control| { - card.control_by_name::<SwitchControl>(&control.calib_ctrl)? - .on()?; - let rdc = card - .control_by_name::<IntControl>(&control.rdc_ctrl)? - .get()?; - let temp = card - .control_by_name::<IntControl>(&control.temp_ctrl)? - .get()?; - card.control_by_name::<SwitchControl>(&control.calib_ctrl)? - .off()?; - Ok(CalibData { - rdc, - temp: Self::dsm_unit_to_celsius(temp), - }) - }) - .collect::<Result<Vec<CalibData>>>()?; - zero_player.stop()?; - Ok(calib) - } - - /// Converts the ambient temperature from celsius to the DSM unit. - #[inline] - fn celsius_to_dsm_unit(celsius: f32) -> i32 { - (celsius * ((1 << 12) as f32) / 100.0) as i32 - } - - /// Converts the ambient temperature from DSM unit to celsius. - #[inline] - fn dsm_unit_to_celsius(temp: i32) -> f32 { - temp as f32 * 100.0 / (1 << 12) as f32 - } - - /// Converts the calibrated value to real DC resistance in ohm unit. - #[inline] - fn rdc_to_ohm(x: i32) -> f32 { - 3.66 * (1 << 20) as f32 / x as f32 - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn celsius_to_dsm_unit() { - assert_eq!( - Max98390::celsius_to_dsm_unit(Max98390::TEMP_UPPER_LIMIT_CELSIUS), - 1638 - ); - assert_eq!( - Max98390::celsius_to_dsm_unit(Max98390::TEMP_LOWER_LIMIT_CELSIUS), - 0 - ); - } - - #[test] - fn dsm_unit_to_celsius() { - assert_eq!( - Max98390::dsm_unit_to_celsius(1638).round(), - Max98390::TEMP_UPPER_LIMIT_CELSIUS - ); - assert_eq!( - Max98390::dsm_unit_to_celsius(0), - Max98390::TEMP_LOWER_LIMIT_CELSIUS - ); - } - - #[test] - fn rdc_to_ohm() { - assert_eq!(Max98390::rdc_to_ohm(1123160), 3.416956); - assert_eq!(Max98390::rdc_to_ohm(1157049), 3.3168762); - } -} diff --git a/sound_card_init/amp/src/max98390d/settings.rs b/sound_card_init/amp/src/max98390d/settings.rs deleted file mode 100644 index 316f25be..00000000 --- a/sound_card_init/amp/src/max98390d/settings.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::string::String; - -use dsm::{self, Error, Result}; -use serde::Deserialize; - -/// `DeviceSettings` includes the settings of max98390. It currently includes: -/// * the settings of amplifier calibration. -/// * the path of dsm_param. -#[derive(Debug, Default, PartialEq, Deserialize, Clone)] -pub struct DeviceSettings { - pub amp_calibrations: AmpCalibSettings, -} -#[derive(Debug, Default, PartialEq, Deserialize, Clone)] -pub struct AmpCalibCtrl { - // Mixer control to get/set rdc value. - pub rdc_ctrl: String, - // Mixer control to get/set ambient temperature value. - pub temp_ctrl: String, - // Mixer control to trigger calibration. - pub calib_ctrl: String, - // Mixer control to adjust volume. - pub volume_ctrl: String, -} - -/// `AmpCalibSettings` includes the settings needed for amplifier calibration. -#[derive(Debug, Default, PartialEq, Deserialize, Clone)] -pub struct AmpCalibSettings { - // Mixer control to get/set rdc value. - pub controls: Vec<AmpCalibCtrl>, - // Path of the dsm_param.bin file. - pub dsm_param: String, -} - -impl AmpCalibSettings { - /// Returns the number of channels. - pub fn num_channels(&self) -> usize { - self.controls.len() - } -} - -impl DeviceSettings { - /// Creates a `DeviceSettings` from a yaml str. - pub fn from_yaml_str(conf: &str) -> Result<DeviceSettings> { - let settings: DeviceSettings = serde_yaml::from_str(conf) - .map_err(|e| Error::DeserializationFailed("DeviceSettings".to_owned(), e))?; - Ok(settings) - } -} diff --git a/sound_card_init/dsm/Cargo.lock b/sound_card_init/dsm/Cargo.lock deleted file mode 100644 index 411c7527..00000000 --- a/sound_card_init/dsm/Cargo.lock +++ /dev/null @@ -1,229 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "alsa-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644d308f5822c2b39fba5a6d850f74c208bf73c61d1d2dfad62505d6960e4977" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "assertions" -version = "0.1.0" - -[[package]] -name = "audio_streams" -version = "0.1.0" -dependencies = [ - "sync", - "sys_util", -] - -[[package]] -name = "cras-sys" -version = "0.1.0" -dependencies = [ - "audio_streams", - "data_model", -] - -[[package]] -name = "cros_alsa" -version = "0.1.0" -dependencies = [ - "alsa-sys", - "libc", - "remain", - "sys_util", -] - -[[package]] -name = "data_model" -version = "0.1.0" -dependencies = [ - "assertions", -] - -[[package]] -name = "dtoa" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" - -[[package]] -name = "libc" -version = "0.2.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" - -[[package]] -name = "libcras" -version = "0.1.0" -dependencies = [ - "audio_streams", - "cras-sys", - "data_model", - "libc", - "sys_util", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" - -[[package]] -name = "max98390d" -version = "0.1.0" -dependencies = [ - "audio_streams", - "cros_alsa", - "libcras", - "remain", - "serde", - "serde_yaml", - "sound_card_util", - "sys_util", -] - -[[package]] -name = "pkg-config" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" - -[[package]] -name = "poll_token_derive" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "remain" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c861227fc40c8da6fdaa3d58144ac84c0537080a43eb1d7d45c28f88dcb888" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_yaml" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" -dependencies = [ - "dtoa", - "linked-hash-map", - "serde", - "yaml-rust", -] - -[[package]] -name = "sound_card_util" -version = "0.1.0" -dependencies = [ - "cros_alsa", - "remain", - "sys_util", -] - -[[package]] -name = "syn" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "sync" -version = "0.1.0" - -[[package]] -name = "sys_util" -version = "0.1.0" -dependencies = [ - "data_model", - "libc", - "poll_token_derive", - "sync", - "syscall_defines", - "tempfile", -] - -[[package]] -name = "syscall_defines" -version = "0.1.0" - -[[package]] -name = "tempfile" -version = "3.0.7" -dependencies = [ - "libc", -] - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" - -[[package]] -name = "yaml-rust" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" -dependencies = [ - "linked-hash-map", -] diff --git a/sound_card_init/dsm/Cargo.toml b/sound_card_init/dsm/Cargo.toml deleted file mode 100644 index 280896d2..00000000 --- a/sound_card_init/dsm/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "dsm" -version = "0.1.0" -authors = ["The Chromium OS Authors"] -edition = "2018" -description = "The boot time calibration logic for smart amp" - -[dependencies] -cros_alsa = "*" -audio_streams = "*" -libcras = "*" -remain = "0.2.1" -serde = { version = "1.0", features = ["derive"]} -serde_yaml = "0.8.11" -sys_util = "*"
\ No newline at end of file diff --git a/sound_card_init/dsm/src/datastore.rs b/sound_card_init/dsm/src/datastore.rs deleted file mode 100644 index f0180cc2..00000000 --- a/sound_card_init/dsm/src/datastore.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::fs::{remove_file, File}; -use std::io::{prelude::*, BufReader, BufWriter}; -use std::path::PathBuf; - -use serde::{Deserialize, Serialize}; -use sys_util::info; - -use crate::error::{Error, Result}; - -/// `Datastore`, which stores and reads calibration values in yaml format. -#[derive(Debug, Deserialize, Serialize, Copy, Clone)] -pub enum Datastore { - /// Indicates using values in VPD. - UseVPD, - DSM { - rdc: i32, - temp: i32, - }, -} - -impl Datastore { - /// The dir of datastore. - pub const DATASTORE_DIR: &'static str = "/var/lib/sound_card_init"; - - /// Creates a `Datastore` and initializes its fields from the datastore file. - pub fn from_file(snd_card: &str, channel: usize) -> Result<Datastore> { - let path = Self::path(snd_card, channel); - let reader = - BufReader::new(File::open(&path).map_err(|e| Error::FileIOFailed(path.to_owned(), e))?); - let datastore: Datastore = - serde_yaml::from_reader(reader).map_err(|e| Error::SerdeError(path.to_owned(), e))?; - Ok(datastore) - } - - /// Saves a `Datastore` to file. - pub fn save(&self, snd_card: &str, channel: usize) -> Result<()> { - let path = Self::path(snd_card, channel); - - let mut writer = BufWriter::new( - File::create(&path).map_err(|e| Error::FileIOFailed(path.to_owned(), e))?, - ); - writer - .write( - serde_yaml::to_string(self) - .map_err(|e| Error::SerdeError(path.to_owned(), e))? - .as_bytes(), - ) - .map_err(|e| Error::FileIOFailed(path.to_owned(), e))?; - writer - .flush() - .map_err(|e| Error::FileIOFailed(path.to_owned(), e))?; - info!("update Datastore {}: {:?}", path.to_string_lossy(), self); - Ok(()) - } - - /// Deletes the datastore file. - pub fn delete(snd_card: &str, channel: usize) -> Result<()> { - let path = Self::path(snd_card, channel); - remove_file(&path).map_err(|e| Error::FileIOFailed(path.to_owned(), e))?; - info!("datastore: {:#?} is deleted.", path); - Ok(()) - } - - fn path(snd_card: &str, channel: usize) -> PathBuf { - PathBuf::from(Self::DATASTORE_DIR) - .join(snd_card) - .join(format!("calib_{}", channel)) - } -} diff --git a/sound_card_init/dsm/src/error.rs b/sound_card_init/dsm/src/error.rs deleted file mode 100644 index 4b6e8dc2..00000000 --- a/sound_card_init/dsm/src/error.rs +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::any::Any; -use std::error; -use std::fmt; -use std::io; -use std::num::ParseIntError; -use std::path::PathBuf; -use std::sync::PoisonError; -use std::time; - -use remain::sorted; - -use crate::CalibData; - -pub type Result<T> = std::result::Result<T, Error>; - -#[sorted] -#[derive(Debug)] -pub enum Error { - AlsaCardError(cros_alsa::CardError), - AlsaControlError(cros_alsa::ControlError), - AlsaControlTLVError(cros_alsa::ControlTLVError), - CalibrationTimeout, - CrasClientFailed(libcras::Error), - DeserializationFailed(String, serde_yaml::Error), - DSMParamUpdateFailed(cros_alsa::ControlTLVError), - FileIOFailed(PathBuf, io::Error), - InternalSpeakerNotFound, - InvalidDatastore, - InvalidDSMParam, - InvalidShutDownTime, - InvalidTemperature(f32), - LargeCalibrationDiff(CalibData), - MissingDSMParam, - MutexPoisonError, - NewPlayStreamFailed(libcras::BoxError), - NextPlaybackBufferFailed(libcras::BoxError), - PlaybackFailed(io::Error), - SerdeError(PathBuf, serde_yaml::Error), - StartPlaybackTimeout, - SystemTimeError(time::SystemTimeError), - UnsupportedSoundCard(String), - VPDParseFailed(String, ParseIntError), - WorkerPanics(Box<dyn Any + Send + 'static>), - ZeroPlayerIsNotRunning, - ZeroPlayerIsRunning, -} - -impl PartialEq for Error { - // Implement eq for more Error when needed. - fn eq(&self, other: &Error) -> bool { - match (self, other) { - (Error::InvalidDSMParam, Error::InvalidDSMParam) => true, - _ => false, - } - } -} - -impl From<cros_alsa::CardError> for Error { - fn from(err: cros_alsa::CardError) -> Error { - Error::AlsaCardError(err) - } -} - -impl From<cros_alsa::ControlError> for Error { - fn from(err: cros_alsa::ControlError) -> Error { - Error::AlsaControlError(err) - } -} - -impl From<cros_alsa::ControlTLVError> for Error { - fn from(err: cros_alsa::ControlTLVError) -> Error { - Error::AlsaControlTLVError(err) - } -} - -impl<T> From<PoisonError<T>> for Error { - fn from(_: PoisonError<T>) -> Error { - Error::MutexPoisonError - } -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - AlsaCardError(e) => write!(f, "AlsaCardError: {}", e), - AlsaControlError(e) => write!(f, "AlsaControlError: {}", e), - AlsaControlTLVError(e) => write!(f, "AlsaControlTLVError: {}", e), - CalibrationTimeout => write!(f, "calibration is not finished in time"), - DSMParamUpdateFailed(e) => write!(f, "failed to update DsmParam, err: {}", e), - CrasClientFailed(e) => write!(f, "failed to create cras client: {}", e), - DeserializationFailed(file_path, e) => { - write!(f, "failed to parse {}: {}", file_path, e) - } - FileIOFailed(file_path, e) => write!(f, "{:#?}: {}", file_path, e), - InvalidShutDownTime => write!(f, "invalid shutdown time"), - InternalSpeakerNotFound => write!(f, "internal speaker is not found in cras"), - InvalidTemperature(temp) => write!( - f, - "invalid calibration temperature: {}, and there is no datastore", - temp - ), - InvalidDatastore => write!(f, "invalid datastore format"), - InvalidDSMParam => write!(f, "invalid dsm param from kcontrol"), - LargeCalibrationDiff(calib) => { - write!(f, "calibration difference is too large, calib: {:?}", calib) - } - MissingDSMParam => write!(f, "missing dsm_param.bin"), - MutexPoisonError => write!(f, "mutex is poisoned"), - NewPlayStreamFailed(e) => write!(f, "{}", e), - NextPlaybackBufferFailed(e) => write!(f, "{}", e), - PlaybackFailed(e) => write!(f, "{}", e), - SerdeError(file_path, e) => write!(f, "{:?}: {}", file_path, e), - StartPlaybackTimeout => write!(f, "playback is not started in time"), - SystemTimeError(e) => write!(f, "{}", e), - UnsupportedSoundCard(name) => write!(f, "unsupported sound card: {}", name), - VPDParseFailed(file_path, e) => write!(f, "failed to parse vpd {}: {}", file_path, e), - WorkerPanics(e) => write!(f, "run_play_zero_worker panics: {:#?}", e), - ZeroPlayerIsNotRunning => write!(f, "zero player is not running"), - ZeroPlayerIsRunning => write!(f, "zero player is running"), - } - } -} diff --git a/sound_card_init/dsm/src/lib.rs b/sound_card_init/dsm/src/lib.rs deleted file mode 100644 index 0b3ec64c..00000000 --- a/sound_card_init/dsm/src/lib.rs +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -//! `dsm` crate implements the required initialization workflows for smart amps. - -mod datastore; -mod error; -pub mod utils; -mod vpd; -mod zero_player; - -use std::{ - thread, - time::{Duration, SystemTime, UNIX_EPOCH}, -}; - -use libcras::{CrasClient, CrasNodeType}; -use sys_util::{error, info}; - -use crate::datastore::Datastore; -pub use crate::error::{Error, Result}; -use crate::utils::{run_time, shutdown_time}; -use crate::vpd::VPD; -pub use crate::zero_player::ZeroPlayer; - -#[derive(Debug, Clone, Copy)] -/// `CalibData` represents the calibration data. -pub struct CalibData { - /// The DC resistance of the speaker is DSM unit. - pub rdc: i32, - /// The ambient temperature in celsius unit at which the rdc is measured. - pub temp: f32, -} - -/// `TempConverter` converts the temperature value between celsius and unit in VPD::dsm_calib_temp. -pub struct TempConverter { - vpd_to_celsius: fn(i32) -> f32, - celsius_to_vpd: fn(f32) -> i32, -} - -impl Default for TempConverter { - fn default() -> Self { - let vpd_to_celsius = |x: i32| x as f32; - let celsius_to_vpd = |x: f32| x.round() as i32; - Self { - vpd_to_celsius, - celsius_to_vpd, - } - } -} - -impl TempConverter { - /// Creates a `TempConverter` - /// - /// # Arguments - /// - /// * `vpd_to_celsius` - function to convert VPD::dsm_calib_temp to celsius unit` - /// * `celsius_to_vpd` - function to convert celsius unit to VPD::dsm_calib_temp` - /// # Results - /// - /// * `TempConverter` - it converts the temperature value between celsius and unit in VPD::dsm_calib_temp. - pub fn new(vpd_to_celsius: fn(i32) -> f32, celsius_to_vpd: fn(f32) -> i32) -> Self { - Self { - vpd_to_celsius, - celsius_to_vpd, - } - } -} - -/// `SpeakerStatus` are the possible return results of -/// DSM::check_speaker_over_heated_workflow. -pub enum SpeakerStatus { - ///`SpeakerStatus::Cold` means the speakers are not overheated and the Amp can - /// trigger the boot time calibration. - Cold, - /// `SpeakerStatus::Hot(Vec<CalibData>)` means the speakers may be too hot for calibration. - /// The boot time calibration should be skipped and the Amp should use the previous - /// calibration values returned by the enum. - Hot(Vec<CalibData>), -} - -/// `DSM`, which implements the required initialization workflows for smart amps. -pub struct DSM { - snd_card: String, - num_channels: usize, - temp_converter: TempConverter, - rdc_to_ohm: fn(i32) -> f32, - temp_upper_limit: f32, - temp_lower_limit: f32, -} - -impl DSM { - const SPEAKER_COOL_DOWN_TIME: Duration = Duration::from_secs(180); - const CALI_ERROR_UPPER_LIMIT: f32 = 0.3; - const CALI_ERROR_LOWER_LIMIT: f32 = 0.03; - - /// Creates a `DSM` - /// - /// # Arguments - /// - /// * `snd_card` - `sound card name`. - /// * `num_channels` - `number of channels`. - /// * `rdc_to_ohm` - `fn(rdc: i32) -> f32 to convert the CalibData::rdc to ohm unit`. - /// * `temp_upper_limit` - the high limit of the valid ambient temperature in dsm unit. - /// * `temp_lower_limit` - the low limit of the valid ambient temperature in dsm unit. - /// - /// # Results - /// - /// * `DSM` - It implements the required initialization workflows for smart amps. - pub fn new( - snd_card: &str, - num_channels: usize, - rdc_to_ohm: fn(i32) -> f32, - temp_upper_limit: f32, - temp_lower_limit: f32, - ) -> Self { - Self { - snd_card: snd_card.to_owned(), - num_channels, - rdc_to_ohm, - temp_converter: TempConverter::default(), - temp_upper_limit, - temp_lower_limit, - } - } - - /// Sets self.temp_converter to the given temp_converter. - /// - /// # Arguments - /// - /// * `temp_converter` - the convert function to use. - pub fn set_temp_converter(&mut self, temp_converter: TempConverter) { - self.temp_converter = temp_converter; - } - - /// Checks whether the speakers are overheated or not according to the previous shutdown time. - /// The boot time calibration should be skipped when the speakers may be too hot - /// and the Amp should use the previous calibration value returned by the - /// SpeakerStatus::Hot(Vec<CalibData>). - /// - /// # Results - /// - /// * `SpeakerStatus::Cold` - which means the speakers are not overheated and the Amp can - /// trigger the boot time calibration. - /// * `SpeakerStatus::Hot(Vec<CalibData>)` - when the speakers may be too hot. The boot - /// time calibration should be skipped and the Amp should use the previous calibration values - /// returned by the enum. - /// - /// # Errors - /// - /// * The speakers are overheated and there are no previous calibration values stored. - /// * Cannot determine whether the speakers are overheated as previous shutdown time record is - /// invalid. - pub fn check_speaker_over_heated_workflow(&self) -> Result<SpeakerStatus> { - if self.is_first_boot() { - return Ok(SpeakerStatus::Cold); - } - match self.is_speaker_over_heated() { - Ok(overheated) => { - if overheated { - let calib: Vec<CalibData> = (0..self.num_channels) - .map(|ch| -> Result<CalibData> { self.get_previous_calibration_value(ch) }) - .collect::<Result<Vec<CalibData>>>()?; - info!("the speakers are hot, the boot time calibration should be skipped"); - return Ok(SpeakerStatus::Hot(calib)); - } - Ok(SpeakerStatus::Cold) - } - Err(err) => { - // We cannot assume the speakers are not replaced or not overheated - // when the shutdown time file is invalid; therefore we can not use the datastore - // value anymore and we can not trigger boot time calibration. - for ch in 0..self.num_channels { - if let Err(e) = Datastore::delete(&self.snd_card, ch) { - error!("error delete datastore: {}", e); - } - } - Err(err) - } - } - } - - /// Decides a good calibration value and updates the stored value according to the following - /// logic: - /// * Returns the previous value if the ambient temperature is not within a valid range. - /// * Returns Error::LargeCalibrationDiff if rdc difference is larger than - /// `CALI_ERROR_UPPER_LIMIT`. - /// * Returns the previous value if the rdc difference is smaller than `CALI_ERROR_LOWER_LIMIT`. - /// * Returns the boot time calibration value and updates the datastore value if the rdc. - /// difference is between `CALI_ERROR_UPPER_LIMIT` and `CALI_ERROR_LOWER_LIMIT`. - /// - /// # Arguments - /// - /// * `card` - `&Card`. - /// * `channel` - `channel number`. - /// * `calib_data` - `boot time calibrated data`. - /// - /// # Results - /// - /// * `CalibData` - the calibration data to be applied according to the deciding logic. - /// - /// # Errors - /// - /// * VPD does not exist. - /// * rdc difference is larger than `CALI_ERROR_UPPER_LIMIT`. - /// * Failed to update Datastore. - pub fn decide_calibration_value_workflow( - &self, - channel: usize, - calib_data: CalibData, - ) -> Result<CalibData> { - if calib_data.temp < self.temp_lower_limit || calib_data.temp > self.temp_upper_limit { - info!("invalid temperature: {}.", calib_data.temp); - return self - .get_previous_calibration_value(channel) - .map_err(|_| Error::InvalidTemperature(calib_data.temp)); - } - let (datastore_exist, previous_calib) = match self.get_previous_calibration_value(channel) { - Ok(previous_calib) => (true, previous_calib), - Err(e) => { - info!("{}, use vpd as previous calibration value", e); - (false, self.get_vpd_calibration_value(channel)?) - } - }; - - let diff = { - let calib_rdc_ohm = (self.rdc_to_ohm)(calib_data.rdc); - let previous_rdc_ohm = (self.rdc_to_ohm)(previous_calib.rdc); - (calib_rdc_ohm - previous_rdc_ohm) / previous_rdc_ohm - }; - if diff > Self::CALI_ERROR_UPPER_LIMIT { - Err(Error::LargeCalibrationDiff(calib_data)) - } else if diff < Self::CALI_ERROR_LOWER_LIMIT { - if !datastore_exist { - Datastore::UseVPD.save(&self.snd_card, channel)?; - } - Ok(previous_calib) - } else { - Datastore::DSM { - rdc: calib_data.rdc, - temp: (self.temp_converter.celsius_to_vpd)(calib_data.temp), - } - .save(&self.snd_card, channel)?; - Ok(calib_data) - } - } - - /// Gets the calibration values from vpd. - /// - /// # Results - /// - /// * `Vec<CalibData>` - the calibration values in vpd. - /// - /// # Errors - /// - /// * Failed to read vpd. - pub fn get_all_vpd_calibration_value(&self) -> Result<Vec<CalibData>> { - (0..self.num_channels) - .map(|ch| self.get_vpd_calibration_value(ch)) - .collect::<Result<Vec<_>>>() - } - - /// Blocks until the internal speakers are ready. - /// - /// # Errors - /// - /// * Failed to wait the internal speakers to be ready. - pub fn wait_for_speakers_ready(&self) -> Result<()> { - let find_speaker = || -> Result<()> { - let cras_client = CrasClient::new().map_err(Error::CrasClientFailed)?; - let _node = cras_client - .output_nodes() - .find(|node| node.node_type == CrasNodeType::CRAS_NODE_TYPE_INTERNAL_SPEAKER) - .ok_or(Error::InternalSpeakerNotFound)?; - Ok(()) - }; - // TODO(b/155007305): Implement cras_client.wait_node_change and use it here. - const RETRY: usize = 3; - const RETRY_INTERVAL: Duration = Duration::from_millis(500); - for _ in 0..RETRY { - match find_speaker() { - Ok(_) => return Ok(()), - Err(e) => error!("retry on finding speaker: {}", e), - }; - thread::sleep(RETRY_INTERVAL); - } - Err(Error::InternalSpeakerNotFound) - } - - fn is_first_boot(&self) -> bool { - !run_time::exists(&self.snd_card) - } - - // If (Current time - the latest CRAS shutdown time) < cool_down_time, we assume that - // the speakers may be overheated. - fn is_speaker_over_heated(&self) -> Result<bool> { - let last_run = run_time::from_file(&self.snd_card)?; - let last_shutdown = shutdown_time::from_file()?; - if last_shutdown < last_run { - return Err(Error::InvalidShutDownTime); - } - - let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map_err(Error::SystemTimeError)?; - - let elapsed = now - .checked_sub(last_shutdown) - .ok_or(Error::InvalidShutDownTime)?; - - if elapsed < Self::SPEAKER_COOL_DOWN_TIME { - return Ok(true); - } - Ok(false) - } - - fn get_previous_calibration_value(&self, ch: usize) -> Result<CalibData> { - let sci_calib = Datastore::from_file(&self.snd_card, ch)?; - match sci_calib { - Datastore::UseVPD => self.get_vpd_calibration_value(ch), - Datastore::DSM { rdc, temp } => Ok(CalibData { - rdc, - temp: (self.temp_converter.vpd_to_celsius)(temp), - }), - } - } - - fn get_vpd_calibration_value(&self, channel: usize) -> Result<CalibData> { - let vpd = VPD::new(channel)?; - Ok(CalibData { - rdc: vpd.dsm_calib_r0, - temp: (self.temp_converter.vpd_to_celsius)(vpd.dsm_calib_temp), - }) - } -} diff --git a/sound_card_init/dsm/src/utils.rs b/sound_card_init/dsm/src/utils.rs deleted file mode 100644 index 64f6c972..00000000 --- a/sound_card_init/dsm/src/utils.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -//! It contains common utils shared within sound_card_init. -#![deny(missing_docs)] - -use std::fs::File; -use std::io::{prelude::*, BufReader, BufWriter}; -use std::path::PathBuf; -use std::time::Duration; - -use crate::datastore::Datastore; -use crate::error::{Error, Result}; - -fn duration_from_file(path: &PathBuf) -> Result<Duration> { - let reader = - BufReader::new(File::open(&path).map_err(|e| Error::FileIOFailed(path.clone(), e))?); - serde_yaml::from_reader(reader).map_err(|e| Error::SerdeError(path.clone(), e)) -} - -/// The utils to parse CRAS shutdown time file. -pub mod shutdown_time { - use super::*; - // The path of CRAS shutdown time file. - const SHUTDOWN_TIME_FILE: &str = "/var/lib/cras/stop"; - - /// Reads the unix time from CRAS shutdown time file. - pub fn from_file() -> Result<Duration> { - duration_from_file(&PathBuf::from(SHUTDOWN_TIME_FILE)) - } -} - -/// The utils to create and parse sound_card_init run time file. -pub mod run_time { - use std::time::SystemTime; - - use super::*; - // The filename of sound_card_init run time file. - const RUN_TIME_FILE: &str = "run"; - - /// Returns the sound_card_init run time file existence. - pub fn exists(snd_card: &str) -> bool { - run_time_file(snd_card).exists() - } - - /// Reads the unix time from sound_card_init run time file. - pub fn from_file(snd_card: &str) -> Result<Duration> { - duration_from_file(&run_time_file(snd_card)) - } - - /// Saves the current unix time to sound_card_init run time file. - pub fn now_to_file(snd_card: &str) -> Result<()> { - match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { - Ok(t) => to_file(snd_card, t), - Err(e) => Err(Error::SystemTimeError(e)), - } - } - - /// Saves the unix time to sound_card_init run time file. - pub fn to_file(snd_card: &str, duration: Duration) -> Result<()> { - let path = run_time_file(snd_card); - let mut writer = - BufWriter::new(File::create(&path).map_err(|e| Error::FileIOFailed(path.clone(), e))?); - writer - .write_all( - serde_yaml::to_string(&duration) - .map_err(|e| Error::SerdeError(path.clone(), e))? - .as_bytes(), - ) - .map_err(|e| Error::FileIOFailed(path.clone(), e))?; - writer - .flush() - .map_err(|e| Error::FileIOFailed(path.clone(), e))?; - Ok(()) - } - - fn run_time_file(snd_card: &str) -> PathBuf { - PathBuf::from(Datastore::DATASTORE_DIR) - .join(snd_card) - .join(RUN_TIME_FILE) - } -} diff --git a/sound_card_init/dsm/src/vpd.rs b/sound_card_init/dsm/src/vpd.rs deleted file mode 100644 index b00864cc..00000000 --- a/sound_card_init/dsm/src/vpd.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::fs::File; -use std::io::prelude::*; -use std::io::BufReader; -use std::path::PathBuf; - -use crate::error::{Error, Result}; - -const VPD_DIR: &str = "/sys/firmware/vpd/ro/vpdfile"; - -/// `VPD`, which represents the amplifier factory calibration values. -#[derive(Default, Debug)] -pub struct VPD { - pub dsm_calib_r0: i32, - pub dsm_calib_temp: i32, -} - -impl VPD { - /// Creates a `VPD` and initializes its fields from VPD_DIR/dsm_calib_r0_{channel}. - /// # Arguments - /// - /// * `channel` - channel number. - pub fn new(channel: usize) -> Result<VPD> { - let mut vpd: VPD = Default::default(); - vpd.dsm_calib_r0 = read_vpd_files(&format!("dsm_calib_r0_{}", channel))?; - vpd.dsm_calib_temp = read_vpd_files(&format!("dsm_calib_temp_{}", channel))?; - Ok(vpd) - } -} - -fn read_vpd_files(file: &str) -> Result<i32> { - let path = PathBuf::from(VPD_DIR).with_file_name(file); - let io_err = |e| Error::FileIOFailed(path.to_owned(), e); - let mut reader = BufReader::new(File::open(&path).map_err(io_err)?); - let mut line = String::new(); - reader.read_line(&mut line).map_err(io_err)?; - line.parse::<i32>() - .map_err(|e| Error::VPDParseFailed(path.to_string_lossy().to_string(), e)) -} diff --git a/sound_card_init/dsm/src/zero_player.rs b/sound_card_init/dsm/src/zero_player.rs deleted file mode 100644 index 441f7ffa..00000000 --- a/sound_card_init/dsm/src/zero_player.rs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2020 The Chromium OS 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 std::io::Write; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Condvar, Mutex}; -use std::thread; -use std::thread::JoinHandle; -use std::time::Duration; - -use audio_streams::SampleFormat; -use libcras::{CrasClient, CrasNodeType}; -use sys_util::error; - -use crate::error::{Error, Result}; - -/// `ZeroPlayer` provides the functionality to play zeros sample in the background thread. -#[derive(Default)] -pub struct ZeroPlayer { - thread_info: Option<PlayZeroWorkerInfo>, -} - -impl Drop for ZeroPlayer { - fn drop(&mut self) { - if self.thread_info.is_some() { - if let Err(e) = self.stop() { - error!("{}", e); - } - } - } -} - -impl ZeroPlayer { - /// It takes about 400 ms to get CRAS_NODE_TYPE_INTERNAL_SPEAKER during the boot time. - const TIMEOUT: Duration = Duration::from_millis(1000); - - /// Returns whether the ZeroPlayer is running. - pub fn running(&self) -> bool { - self.thread_info.is_some() - } - - /// Starts to play zeros for at most `max_playback_time`. - /// This function blocks and returns until playback has started for `min_playback_time`. - /// This function must be called when self.running() returns false. - /// - /// # Arguments - /// - /// * `min_playback_time` - It blocks and returns until playback has started for - /// `min_playback_time`. - /// - /// # Errors - /// - /// * If it's called when the `ZeroPlayer` is already running. - /// * Failed to find internal speakers. - /// * Failed to start the background thread. - pub fn start(&mut self, min_playback_time: Duration) -> Result<()> { - if self.running() { - return Err(Error::ZeroPlayerIsRunning); - } - self.thread_info = Some(PlayZeroWorkerInfo::new(min_playback_time)); - if let Some(thread_info) = &mut self.thread_info { - // Block until playback of zeros has started for min_playback_time or timeout. - let (lock, cvar) = &*(thread_info.ready); - let result = cvar.wait_timeout_while( - lock.lock()?, - min_playback_time + ZeroPlayer::TIMEOUT, - |&mut is_ready| !is_ready, - )?; - if result.1.timed_out() { - return Err(Error::StartPlaybackTimeout); - } - } - Ok(()) - } - - /// Stops playing zeros in the background thread. - /// This function must be called when self.running() returns true. - /// - /// # Errors - /// - /// * If it's called again when the `ZeroPlayer` is not running. - /// * Failed to play zeros to internal speakers via CRAS client. - /// * Failed to join the background thread. - pub fn stop(&mut self) -> Result<()> { - match self.thread_info.take() { - Some(mut thread_info) => Ok(thread_info.destroy()?), - None => Err(Error::ZeroPlayerIsNotRunning), - } - } -} - -// Audio thread book-keeping data -struct PlayZeroWorkerInfo { - thread: Option<JoinHandle<Result<()>>>, - // Uses `thread_run` to notify the background thread to stop. - thread_run: Arc<AtomicBool>, - // The background thread uses `ready` to notify the main thread that playback - // of zeros has started for min_playback_time. - ready: Arc<(Mutex<bool>, Condvar)>, -} - -impl Drop for PlayZeroWorkerInfo { - fn drop(&mut self) { - if let Err(e) = self.destroy() { - error!("{}", e); - } - } -} - -impl PlayZeroWorkerInfo { - // Spawns the PlayZeroWorker. - fn new(min_playback_time: Duration) -> Self { - let thread_run = Arc::new(AtomicBool::new(false)); - let ready = Arc::new((Mutex::new(false), Condvar::new())); - let mut worker = PlayZeroWorker::new(min_playback_time, thread_run.clone(), ready.clone()); - Self { - thread: Some(thread::spawn(move || -> Result<()> { - worker.run()?; - Ok(()) - })), - thread_run, - ready, - } - } - - // Joins the PlayZeroWorker. - fn destroy(&mut self) -> Result<()> { - self.thread_run.store(false, Ordering::Relaxed); - if let Some(handle) = self.thread.take() { - let res = handle.join().map_err(Error::WorkerPanics)?; - return match res { - Err(e) => Err(e), - Ok(_) => Ok(()), - }; - } - Ok(()) - } -} - -struct PlayZeroWorker { - min_playback_time: Duration, - // Uses `thread_run` to notify the background thread to stop. - thread_run: Arc<AtomicBool>, - // The background thread uses `ready` to notify the main thread that playback - // of zeros has started for min_playback_time. - ready: Arc<(Mutex<bool>, Condvar)>, -} - -impl PlayZeroWorker { - const FRAMES_PER_BUFFER: usize = 256; - const FRAME_RATE: u32 = 48000; - const NUM_CHANNELS: usize = 2; - const FORMAT: SampleFormat = SampleFormat::S16LE; - - fn new( - min_playback_time: Duration, - thread_run: Arc<AtomicBool>, - ready: Arc<(Mutex<bool>, Condvar)>, - ) -> Self { - Self { - min_playback_time, - thread_run, - ready, - } - } - - fn run(&mut self) -> Result<()> { - let mut cras_client = CrasClient::new().map_err(Error::CrasClientFailed)?; - // TODO(b/155007305): Implement cras_client.wait_node_change and use it here. - let node = cras_client - .output_nodes() - .find(|node| node.node_type == CrasNodeType::CRAS_NODE_TYPE_INTERNAL_SPEAKER) - .ok_or(Error::InternalSpeakerNotFound)?; - let local_buffer = - vec![0u8; Self::FRAMES_PER_BUFFER * Self::NUM_CHANNELS * Self::FORMAT.sample_bytes()]; - let min_playback_iterations = (Self::FRAME_RATE - * self.min_playback_time.as_millis() as u32) - / Self::FRAMES_PER_BUFFER as u32 - / 1000; - let (_control, mut stream) = cras_client - .new_pinned_playback_stream( - node.iodev_index, - Self::NUM_CHANNELS, - Self::FORMAT, - Self::FRAME_RATE, - Self::FRAMES_PER_BUFFER, - ) - .map_err(|e| Error::NewPlayStreamFailed(e))?; - - let mut iter = 0; - self.thread_run.store(true, Ordering::Relaxed); - while self.thread_run.load(Ordering::Relaxed) { - let mut buffer = stream - .next_playback_buffer() - .map_err(|e| Error::NextPlaybackBufferFailed(e))?; - let _write_frames = buffer.write(&local_buffer).map_err(Error::PlaybackFailed)?; - - // Notifies the main thread that playback of zeros has started for min_playback_time. - if iter == min_playback_iterations { - let (lock, cvar) = &*self.ready; - let mut is_ready = lock.lock()?; - *is_ready = true; - cvar.notify_one(); - } - iter += 1; - } - Ok(()) - } -} diff --git a/sound_card_init/seccomp/sound_card_init-seccomp-amd64.policy b/sound_card_init/seccomp/sound_card_init-seccomp-amd64.policy deleted file mode 100644 index d06f225e..00000000 --- a/sound_card_init/seccomp/sound_card_init-seccomp-amd64.policy +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -access: 1 -arch_prctl: 1 -bind: 1 -brk: 1 -clone: 1 -close: 1 -connect: 1 -dup2: 1 -dup: 1 -epoll_create1: 1 -epoll_ctl: 1 -epoll_wait: 1 -execve: 1 -exit: 1 -exit_group: 1 -fcntl: 1 -fstat: 1 -futex: 1 -getcwd: 1 -getdents: 1 -getdents64: 1 -getegid: 1 -geteuid: 1 -getgid: 1 -getgroups: 1 -getpgid: 1 -getpgrp: 1 -getpid: 1 -getppid: 1 -getpriority: 1 -getrandom: 1 -getresgid: 1 -getresuid: 1 -getsid: 1 -getsockname: 1 -getuid: 1 -ioctl: arg1 == 0x5401 || arg1 == 0xc4c85512 || arg1 == 0x540f || arg1 == 0x80045500 || arg1 == 0xc4c85513 || arg1 == 0x81785501 || arg1 == 0x5413 || arg1 == 0xc1105511 || arg1 == 0x81785501 || arg1 == 0x80045500 || arg1 == 0xc008551a || arg1 == 0xc4c85512 || arg1 == 0xc008551b || arg1 == 0xc1105511 -lseek: 1 -madvise: 1 -mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE -mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE -munmap: 1 -nanosleep: 1 -clock_nanosleep: 1 -openat: 1 -pipe2: 1 -ppoll: 1 -prctl: arg0 == 0x3 || arg0 == 0x4 -prlimit64: 1 -read: 1 -recvfrom: 1 -recvmsg: 1 -restart_syscall: 1 -rt_sigaction: 1 -rt_sigprocmask: 1 -rt_sigreturn: 1 -sched_getaffinity: 1 -sched_yield: 1 -sendmsg: 1 -sendto: 1 -set_robust_list: 1 -set_tid_address: 1 -setgid: 1 -setgroups: 1 -setpriority: 1 -setresgid: 1 -setresuid: 1 -setuid: 1 -sigaltstack: 1 -socket: arg0 == 0x10 || arg0 == 0x1 -socketpair: 1 -stat: 1 -statx: 1 -umask: 1 -uname: 1 -unlink: 1 -wait4: 1 -write: 1 diff --git a/sound_card_init/sound_card_init.conf b/sound_card_init/sound_card_init.conf deleted file mode 100644 index 40bc88f8..00000000 --- a/sound_card_init/sound_card_init.conf +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Installed by sound_card_init package. -# sound_card_init upstart job. -# sound_card_init is started by /lib/udev/rules.d/99-sound_card_init.rules - -description "Chrome OS sound card initializer" -author "chromium-os-dev@chromium.org" - -# sound_card_init is a short-running process, but we don't start it as -# a task job, because sound_card_init needs the sound card to be ready in -# CRAS therefore we do not want to block the udev rule processing. - -# Make the task killable, because if it has a leak it's better to -# restart it than to OOM-panic. -oom score 0 - -# SOUND_CARD_ID is provided by /lib/udev/rules.d/99-sound_card_init.rules. -import SOUND_CARD_ID - -pre-start script - if ! echo "${SOUND_CARD_ID}" | grep -Eq "^[a-zA-Z0-9]+$"; then - logger -t "${UPSTART_JOB}" \ - "Invalid SOUND_CARD_ID supplied" - exit 1 - else - mkdir -m 0755 -p /var/lib/sound_card_init/"${SOUND_CARD_ID}" - chown -R sound_card_init:sound_card_init /var/lib/sound_card_init - fi -end script - - -script - CONFIG="$(cros_config /audio/main sound-card-init-conf)" - if [ -f /etc/sound_card_init/"${CONFIG}" ]; then - # Here (in order) are a list of the args added: - # --uts: Create and enter new UTS namespace (hostname/NIS domain name). - # -e: doesn't need network access. - # -l: process doesn't use SysV shared memory or IPC. - # -N: doesn't need to modify control groups settings. - # -v: run inside a new VFS namespace. - # -p -r: process doesn't need to access other processes in the system. - # -n: process doesn't need new privileges. - # -P: set /mnt/empty as the root fs. - # -b: bind / - # -k: Get a writeable and empty /run tmpfs path. - # -b: need /run/cras to connect cras. - # -b: need /dev to send ioctls to the system's block devices. - # -k: empty /sys tmpfs path. - # -b: need /sys/firmware/vpd/ro/ access to read the default calibration - # value in vpd. - # -k: get a writeable and empty /var tmpfs path. - # -b: need /var/lib/sound_card_init/$SOUND_CARD_ID writable access for - # datastore update. - # -b: need /var/lib/cras readable - exec minijail0 \ - --uts \ - -e \ - -l \ - -N \ - -v \ - -p -r \ - -n \ - -P /mnt/empty \ - -b / \ - -k 'tmpfs,/run,tmpfs,MS_NODEV|MS_NOEXEC|MS_NOSUID,mode=755,size=10M' \ - -b /run/cras \ - -b /dev \ - -k 'tmpfs,/sys,tmpfs,MS_NODEV|MS_NOEXEC|MS_NOSUID,mode=755,size=10M' \ - -b /sys/firmware/vpd/ro/ \ - -k 'tmpfs,/var,tmpfs,MS_NODEV|MS_NOEXEC|MS_NOSUID,mode=755,size=10M' \ - -b /var/lib/sound_card_init/"${SOUND_CARD_ID}"/,,1 \ - -b /var/lib/cras/ \ - -u sound_card_init -g sound_card_init -G \ - -S /usr/share/policy/sound_card_init-seccomp.policy \ - /usr/bin/sound_card_init "--id=${SOUND_CARD_ID}" "--conf=${CONFIG}" - fi -end script
\ No newline at end of file diff --git a/sound_card_init/src/main.rs b/sound_card_init/src/main.rs deleted file mode 100644 index 806b7d53..00000000 --- a/sound_card_init/src/main.rs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2020 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -//! `sound_card_init` is an user space binary to perform sound card initialization during boot time. -//! -//! -//! # Arguments -//! -//! * `sound_card_id` - The sound card name, ex: sofcmlmax98390d. -//! -//! Given the `sound_card_id`, this binary parses the CONF_DIR/<sound_card_id>.yaml to perform per sound card initialization. -//! The upstart job of `sound_card_init` is started by the udev event specified in /lib/udev/rules.d/99-sound_card_init.rules. -#![deny(missing_docs)] -use std::env; -use std::error; -use std::fmt; -use std::process; -use std::string::String; - -use getopts::Options; -use remain::sorted; -use sys_util::{error, info, syslog}; - -use amp::AmpBuilder; -use dsm::utils::run_time; - -type Result<T> = std::result::Result<T, Error>; - -#[derive(Default)] -struct Args { - pub sound_card_id: String, - pub conf: String, -} - -#[sorted] -#[derive(Debug)] -enum Error { - MissingOption(String), - ParseArgsFailed(getopts::Fail), -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - match self { - MissingOption(option) => write!(f, "missing required option: {}", option), - ParseArgsFailed(e) => write!(f, "parse_args failed: {}", e), - } - } -} - -fn print_usage(opts: &Options) { - let brief = "Usage: sound_card_init [options]".to_owned(); - print!("{}", opts.usage(&brief)); -} - -fn parse_args() -> Result<Args> { - let mut opts = Options::new(); - opts.optopt("", "id", "sound card id", "ID"); - opts.optopt( - "", - "conf", - "the config file name. It should be $(cros_config /audio/main sound-card-init-conf)", - "CONFIG_NAME", - ); - opts.optflag("h", "help", "print help menu"); - let matches = opts - .parse(&env::args().collect::<Vec<_>>()[1..]) - .map_err(|e| { - print_usage(&opts); - Error::ParseArgsFailed(e) - })?; - - if matches.opt_present("h") { - print_usage(&opts); - process::exit(0); - } - - let sound_card_id = matches - .opt_str("id") - .ok_or_else(|| Error::MissingOption("id".to_owned())) - .map_err(|e| { - print_usage(&opts); - e - })?; - - let conf = matches - .opt_str("conf") - .ok_or_else(|| Error::MissingOption("conf".to_owned())) - .map_err(|e| { - print_usage(&opts); - e - })?; - - Ok(Args { - sound_card_id, - conf, - }) -} - -/// Parses the CONF_DIR/${args.conf}.yaml and starts the boot time calibration. -fn sound_card_init(args: &Args) -> std::result::Result<(), Box<dyn error::Error>> { - info!("sound_card_id: {}, conf:{}", args.sound_card_id, args.conf); - AmpBuilder::new(&args.sound_card_id, &args.conf) - .build()? - .boot_time_calibration()?; - - Ok(()) -} - -fn main() { - syslog::init().expect("failed to initialize syslog"); - let args = match parse_args() { - Ok(args) => args, - Err(e) => { - error!("failed to parse arguments: {}", e); - return; - } - }; - - match sound_card_init(&args) { - Ok(_) => info!("sound_card_init finished successfully."), - Err(e) => error!("sound_card_init: {}", e), - } - - if let Err(e) = run_time::now_to_file(&args.sound_card_id) { - error!("failed to create sound_card_init run time file: {}", e); - } -} diff --git a/ucm-config/for_all_boards/Pixel USB-C earbuds/Pixel USB-C earbuds.conf b/ucm-config/bolt/HDA Intel PCH/HDA Intel PCH.conf index 4166632c..1cd5b42a 100644 --- a/ucm-config/for_all_boards/Pixel USB-C earbuds/Pixel USB-C earbuds.conf +++ b/ucm-config/bolt/HDA Intel PCH/HDA Intel PCH.conf @@ -1,4 +1,4 @@ -Comment "Pixel USB-C earbuds" +Comment "Bolt internal card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/bolt/HDA Intel PCH/HiFi.conf b/ucm-config/bolt/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..2ab99c55 --- /dev/null +++ b/ucm-config/bolt/HDA Intel PCH/HiFi.conf @@ -0,0 +1,67 @@ +SectionVerb { + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='HP/Speaker Playback Switch' off" + cset "name='HP/Speaker Auto Detect Playback Switch' off" + cset "name='PlayEnhancement Playback Switch' on" + cset "name='Surround Playback Switch' on" + cset "name='Crystalizer Playback Switch' off" + cset "name='Dialog Plus Playback Switch' off" + cset "name='Smart Volume Playback Switch' on" + cset "name='X-Bass Playback Switch' on" + cset "name='Equalizer Playback Switch' off" + cset "name='Echo Cancellation Capture Switch' on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 99" + cset "name='CrystalVoice Capture Switch' off" + cset "name='Analog-Mic2 Capture Volume' 90" + cset "name='Analog-Mic2 Capture Switch' on" + cset "name='Mic1-Boost (30dB) Capture Switch' on" + cset "name='AMic1/DMic Capture Switch' off" + cset "name='AMic1/DMic Auto Detect Capture Switch' off" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Front Headphone Jack" + } + + EnableSequence [ + cdev "hw:PCH" + + cset "name='PlayEnhancement Playback Switch' off" + cset "name='HP/Speaker Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='PlayEnhancement Playback Switch' on" + cset "name='HP/Speaker Playback Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + + EnableSequence [ + cdev "hw:PCH" + + cset "name='CrystalVoice Capture Switch' off" + cset "name='AMic1/DMic Capture Switch' on" + ] + + DisableSequence [ + cdev "hw:PCH" + + cset "name='CrystalVoice Capture Switch' off" + cset "name='AMic1/DMic Capture Switch' off" + ] +} diff --git a/ucm-config/chell b/ucm-config/chell new file mode 120000 index 00000000..1ec1f47c --- /dev/null +++ b/ucm-config/chell @@ -0,0 +1 @@ +glados/
\ No newline at end of file diff --git a/ucm-config/cid/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/cid/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..63485af9 --- /dev/null +++ b/ucm-config/cid/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Cid internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/cid/HDA Intel PCH/HiFi.conf b/ucm-config/cid/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..6174c0b9 --- /dev/null +++ b/ucm-config/cid/HDA Intel PCH/HiFi.conf @@ -0,0 +1,55 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Mic Boost Volume' 2" + cset "name='Internal Mic Boost Volume' 1" + cset "name='Capture Source' 0" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + DspName "" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Speaker Playback Switch' off" + cset "name='Headphone Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 1" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 0" + ] +} diff --git a/ucm-config/for_all_boards/Dell AC511 USB SoundBar/Dell AC511 USB SoundBar.conf b/ucm-config/daisy/DAISY-I2S-98090/DAISY-I2S-98090.conf index 54913786..3ca0ff05 100644 --- a/ucm-config/for_all_boards/Dell AC511 USB SoundBar/Dell AC511 USB SoundBar.conf +++ b/ucm-config/daisy/DAISY-I2S-98090/DAISY-I2S-98090.conf @@ -1,4 +1,4 @@ -Comment "Dell AC511 USB SoundBar" +Comment "Daisy internal card (Maxim 98090)" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/daisy/DAISY-I2S-98090/HiFi.conf b/ucm-config/daisy/DAISY-I2S-98090/HiFi.conf new file mode 100644 index 00000000..54e92b3c --- /dev/null +++ b/ucm-config/daisy/DAISY-I2S-98090/HiFi.conf @@ -0,0 +1,107 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:DAISYI2S98090" + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='MIC2 Mux' IN34" + cset "name='DMIC Mux' DMIC" + cset "name='Right ADC Mixer MIC2 Switch' off" + cset "name='Left ADC Mixer MIC2 Switch' off" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + ] + DisableSequence [ + ] +} + +SectionDevice."HDMI".0 { + Value { + JackName "DAISY-I2S-98090 HDMI Jack" + DspName "" + EDIDFile "/sys/devices/platform/exynos-drm/drm/card1/card1-HDMI-A-1/edid" + } + EnableSequence [ + cdev "hw:DAISYI2S98090" + cset "name='Left Speaker Mixer Left DAC Switch' off" + cset "name='Right Speaker Mixer Right DAC Switch' off" + ] + DisableSequence [ + cdev "hw:DAISYI2S98090" + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "DAISY-I2S-98090 Headphone Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:DAISYI2S98090" + cset "name='Left Speaker Mixer Left DAC Switch' off" + cset "name='Right Speaker Mixer Right DAC Switch' off" + cset "name='HP Left Out Switch' on" + cset "name='HP Right Out Switch' on" + ] + DisableSequence [ + cdev "hw:DAISYI2S98090" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "DAISY-I2S-98090 Mic Jack" + CaptureControl "MIC2" + DefaultNodeGain "-500" + } + + EnableSequence [ + cdev "hw:DAISYI2S98090" + + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='DMIC Mux' ADC" + cset "name='MIC2 Volume' 20" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:DAISYI2S98090" + + cset "name='DMIC Mux' DMIC" + cset "name='Right ADC Mixer MIC2 Switch' off" + cset "name='Left ADC Mixer MIC2 Switch' off" + cset "name='MIC2 Volume' 0" + cset "name='Record Path DC Blocking' off" + ] +} diff --git a/ucm-config/for_all_boards/PCP-USB/PCP-USB.conf b/ucm-config/daisy/DAISY-I2S/DAISY-I2S.conf index b4689272..0f4b5fcc 100644 --- a/ucm-config/for_all_boards/PCP-USB/PCP-USB.conf +++ b/ucm-config/daisy/DAISY-I2S/DAISY-I2S.conf @@ -1,4 +1,4 @@ -Comment "PCP USB Stethoscope" +Comment "Daisy internal card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/daisy/DAISY-I2S/HiFi.conf b/ucm-config/daisy/DAISY-I2S/HiFi.conf new file mode 100644 index 00000000..90318169 --- /dev/null +++ b/ucm-config/daisy/DAISY-I2S/HiFi.conf @@ -0,0 +1,142 @@ +SectionVerb { + EnableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Headphone Volume' 13" + cset "name='Speaker Volume' 16" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + cset "name='Receiver Switch' on" + cset "name='Lineout Switch' on" + cset "name='MIC1 Volume' 20" + cset "name='MIC2 Volume' 20" + cset "name='MIC1 Boost Volume' 0" + cset "name='MIC2 Boost Volume' 1" + cset "name='Linein Volume' 5" + cset "name='ADCL Volume' 15" + cset "name='ADCR Volume' 15" + cset "name='ADCL Boost Volume' 0" + cset "name='ADCR Boost Volume' 0" + cset "name='EQ1 Mode' Default" + cset "name='EQ1 Switch' on" + cset "name='EQ2 Switch' off" + cset "name='Biquad1 Switch' off" + cset "name='Biquad2 Switch' off" + cset "name='DMIC1 Left Capture Switch' on" + cset "name='DMIC1 Right Capture Switch' on" + cset "name='MIC1 External Mic Switch' off" + cset "name='MIC2 External Mic Switch' on" + cset "name='DAI2 Filter Mode' Voice" + cset "name='DAI1 DAC Filter' Off" + cset "name='DAI1 Filter Mode' Music" + cset "name='DAI2 DAC Filter' Off" + cset "name='DAI3 DAC Filter' Off" + cset "name='Linein Mode' Stereo" + cset "name='Lineout Mode' Stereo" + cset "name='Right ADC Mixer MIC1 Switch' off" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Right ADC Mixer IN1 Switch' off" + cset "name='Right ADC Mixer IN2 Switch' off" + cset "name='Left ADC Mixer MIC1 Switch' off" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer IN1 Switch' off" + cset "name='Left ADC Mixer IN2 Switch' off" + cset "name='Right Lineout Mixer Left DAC1 Switch' off" + cset "name='Right Lineout Mixer Right DAC1 Switch' off" + cset "name='Right Lineout Mixer MIC1 Switch' off" + cset "name='Right Lineout Mixer MIC2 Switch' off" + cset "name='Right Lineout Mixer IN1 Switch' off" + cset "name='Right Lineout Mixer IN2 Switch' off" + cset "name='Left Lineout Mixer Left DAC1 Switch' off" + cset "name='Left Lineout Mixer Right DAC1 Switch' off" + cset "name='Left Lineout Mixer MIC1 Switch' off" + cset "name='Left Lineout Mixer MIC2 Switch' off" + cset "name='Left Lineout Mixer IN1 Switch' off" + cset "name='Left Lineout Mixer IN2 Switch' off" + cset "name='Receiver Mixer Left DAC1 Switch' off" + cset "name='Receiver Mixer Right DAC1 Switch' off" + cset "name='Receiver Mixer MIC1 Switch' off" + cset "name='Receiver Mixer MIC2 Switch' off" + cset "name='Receiver Mixer IN1 Switch' off" + cset "name='Receiver Mixer IN2 Switch' off" + cset "name='Right Speaker Mixer Left DAC1 Switch' off" + cset "name='Right Speaker Mixer Right DAC1 Switch' on" + cset "name='Right Speaker Mixer Mono DAC2 Switch' off" + cset "name='Right Speaker Mixer Mono DAC3 Switch' off" + cset "name='Left Speaker Mixer Left DAC1 Switch' on" + cset "name='Left Speaker Mixer Right DAC1 Switch' off" + cset "name='Left Speaker Mixer Mono DAC2 Switch' off" + cset "name='Left Speaker Mixer Mono DAC3 Switch' off" + cset "name='Right Headphone Mixer Left DAC1 Switch' off" + cset "name='Right Headphone Mixer Right DAC1 Switch' on" + cset "name='Right Headphone Mixer MIC1 Switch' off" + cset "name='Right Headphone Mixer MIC2 Switch' off" + cset "name='Right Headphone Mixer IN1 Switch' off" + cset "name='Right Headphone Mixer IN2 Switch' off" + cset "name='Left Headphone Mixer Left DAC1 Switch' on" + cset "name='Left Headphone Mixer Right DAC1 Switch' off" + cset "name='Left Headphone Mixer MIC1 Switch' off" + cset "name='Left Headphone Mixer MIC2 Switch' off" + cset "name='Left Headphone Mixer IN1 Switch' off" + cset "name='Left Headphone Mixer IN2 Switch' off" + cset "name='Linein Mux' INA" + cset "name='External MIC' MIC2" + cset "name='HDMI Playback Switch' off" + ] + DisableSequence [ + ] +} + +SectionDevice."HDMI".0 { + Value { + JackName "DAISY-I2S HDMI Jack" + EDIDFile "/sys/devices/platform/exynos-drm/drm/card1/card1-HDMI-A-1/edid" + } +} + +SectionDevice."Headphone".0 { + Value { + JackName "DAISY-I2S Headphone Jack" + } + + EnableSequence [ + cdev "hw:DAISYI2S" + cset "name='EQ1 Switch' off" + cset "name='Speaker Switch' off" + cset "name='Left Headphone Mixer Left DAC1 Switch' on" + cset "name='Right Headphone Mixer Right DAC1 Switch' on" + ] + DisableSequence [ + cdev "hw:DAISYI2S" + cset "name='EQ1 Mode' Default" + cset "name='EQ1 Switch' on" + cset "name='Left Speaker Mixer Left DAC1 Switch' on" + cset "name='Right Speaker Mixer Right DAC1 Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "DAISY-I2S Mic Jack" + CaptureControl "MIC2" + DefaultNodeGain "-500" + } + + EnableSequence [ + cdev "hw:DAISYI2S" + + cset "name='DMIC1 Left Capture Switch' off" + cset "name='DMIC1 Right Capture Switch' off" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='Right ADC Mixer MIC2 Switch' on" + ] + + DisableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Left ADC Mixer MIC2 Switch' off" + cset "name='Right ADC Mixer MIC2 Switch' off" + cset "name='DMIC1 Left Capture Switch' on" + cset "name='DMIC1 Right Capture Switch' on" + ] +} diff --git a/ucm-config/daisy_skate/DAISY-I2S/DAISY-I2S.conf b/ucm-config/daisy_skate/DAISY-I2S/DAISY-I2S.conf new file mode 100644 index 00000000..bca7d631 --- /dev/null +++ b/ucm-config/daisy_skate/DAISY-I2S/DAISY-I2S.conf @@ -0,0 +1,6 @@ +Comment "Skate internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/daisy_skate/DAISY-I2S/HiFi.conf b/ucm-config/daisy_skate/DAISY-I2S/HiFi.conf new file mode 100644 index 00000000..d2a913b8 --- /dev/null +++ b/ucm-config/daisy_skate/DAISY-I2S/HiFi.conf @@ -0,0 +1,70 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:DAISYI2S" + cset "name='Left SPK Mixer Left DAC1 Switch' on" + cset "name='Right SPK Mixer Right DAC1 Switch' on" + cset "name='Left HP Mixer Left DAC1 Switch' on" + cset "name='Right HP Mixer Right DAC1 Switch' on" + cset "name='External MIC' MIC2" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='DAI1 Filter Mode' Music" + cset "name='DIGMICL Switch' on" + cset "name='DIGMICR Switch' on" + ] + DisableSequence [ + ] +} + +SectionDevice."HDMI".0 { + Value { + JackName "DAISY-I2S HDMI Jack" + DspName "" + EDIDFile "/sys/devices/platform/exynos-drm/drm/card1/card1-HDMI-A-1/edid" + } +} + +SectionDevice."Headphone".0 { + Value { + JackName "DAISY-I2S Headphone Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:DAISYI2S" + cset "name='EQ1 Switch' off" + ] + DisableSequence [ + cdev "hw:DAISYI2S" + cset "name='EQ1 Mode' Default" + cset "name='EQ1 Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "DAISY-I2S Mic Jack" + CaptureControl "MIC2" + } + + EnableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='DIGMICL Switch' off" + cset "name='DIGMICR Switch' off" + ] + + DisableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Left ADC Mixer MIC2 Switch' off" + cset "name='Right ADC Mixer MIC2 Switch' off" + cset "name='DIGMICL Switch' on" + cset "name='DIGMICR Switch' on" + ] +} diff --git a/ucm-config/for_all_boards/HUAWEI USB-C HEADSET/HUAWEI USB-C HEADSET.conf b/ucm-config/daisy_spring/DAISY-I2S/DAISY-I2S.conf index c1db5193..05389ee0 100644 --- a/ucm-config/for_all_boards/HUAWEI USB-C HEADSET/HUAWEI USB-C HEADSET.conf +++ b/ucm-config/daisy_spring/DAISY-I2S/DAISY-I2S.conf @@ -1,4 +1,4 @@ -Comment "HUAWEI USB-C HEADSET" +Comment "Spring internal card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/daisy_spring/DAISY-I2S/HiFi.conf b/ucm-config/daisy_spring/DAISY-I2S/HiFi.conf new file mode 100644 index 00000000..af49a05f --- /dev/null +++ b/ucm-config/daisy_spring/DAISY-I2S/HiFi.conf @@ -0,0 +1,90 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Headphone Volume' 0" + cset "name='Speaker Volume' 0" + cset "name='Receiver Volume' 0" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + cset "name='Receiver Switch' on" + cset "name='MIC1 Volume' 31" + cset "name='MIC2 Volume' 32" + cset "name='MIC1 Boost Volume' 0" + cset "name='MIC2 Boost Volume' 0" + cset "name='INA Volume' 7" + cset "name='INB Volume' 7" + cset "name='ADCL Volume' 0" + cset "name='ADCR Volume' 0" + cset "name='ADCL Boost Volume' 0" + cset "name='ADCR Boost Volume' 0" + cset "name='DIGMICR Switch' on" + cset "name='DIGMICL Switch' on" + cset "name='EQ1 Switch' off" + cset "name='EQ2 Switch' off" + cset "name='EX Limiter Mode' off" + cset "name='EX Limiter Threshold' '0.6'" + cset "name='DAI1 Filter Mode' Music" + cset "name='DAI1 DAC Filter' off" + cset "name='DAI1 ADC Filter' 1" + cset "name='DAI2 DC Block Switch' off" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='Right SPK Mixer Right DAC1 Switch' on" + cset "name='Left SPK Mixer Left DAC1 Switch' on" + cset "name='Right HP Mixer Right DAC1 Switch' on" + cset "name='Left HP Mixer Left DAC1 Switch' on" + cset "name='External MIC' MIC2" + cset "name='HDMI Playback Switch' off" + ] + DisableSequence [ + ] +} + +SectionDevice."HDMI".0 { + Value { + JackName "DAISY-I2S HDMI Jack" + DspName "" + EDIDFile "/sys/devices/platform/exynos-drm/drm/card1/card1-HDMI-A-1/edid" + } +} + +SectionDevice."Headphone".0 { + Value { + JackName "DAISY-I2S Headphone Jack" + DspName "" + } + + EnableSequence [ + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "DAISY-I2S Mic Jack" + CaptureControl "MIC2" + } + + EnableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='DIGMICL Switch' off" + cset "name='DIGMICR Switch' off" + ] + + DisableSequence [ + cdev "hw:DAISYI2S" + + cset "name='Left ADC Mixer MIC2 Switch' off" + cset "name='Right ADC Mixer MIC2 Switch' off" + cset "name='DIGMICL Switch' on" + cset "name='DIGMICR Switch' on" + ] +} diff --git a/ucm-config/falco/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/falco/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..45c29837 --- /dev/null +++ b/ucm-config/falco/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Falco internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/falco/HDA Intel PCH/HiFi.conf b/ucm-config/falco/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..03f431e5 --- /dev/null +++ b/ucm-config/falco/HDA Intel PCH/HiFi.conf @@ -0,0 +1,55 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Mic Boost Volume' 2" + cset "name='Internal Mic Boost Volume' 0" + cset "name='Capture Source' 0" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + DspName "" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Speaker Playback Switch' off" + cset "name='Headphone Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 1" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 0" + ] +} diff --git a/ucm-config/for_all_boards/C505 HD Webcam/HiFi.conf b/ucm-config/for_all_boards/C505 HD Webcam/HiFi.conf deleted file mode 100644 index c7e13426..00000000 --- a/ucm-config/for_all_boards/C505 HD Webcam/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:Webcam" - cset "name='Mic Capture Volume' 0" - ] - - DisableSequence [ - ] -} - -SectionDevice."Webcam" { - Value { - CapturePCM "hw:Webcam,0" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} diff --git a/ucm-config/for_all_boards/Chat 150 C/HiFi.conf b/ucm-config/for_all_boards/Chat 150 C/HiFi.conf index 368796d7..5a73702c 100644 --- a/ucm-config/for_all_boards/Chat 150 C/HiFi.conf +++ b/ucm-config/for_all_boards/Chat 150 C/HiFi.conf @@ -10,7 +10,7 @@ SectionVerb { ] } -SectionDevice."Chat 150 C".0 { +SectionDevice."Dummy".0 { EnableSequence [ ] diff --git a/ucm-config/for_all_boards/DELL PROFESSIONAL SOUND BAR AE5/DELL PROFESSIONAL SOUND BAR AE5.conf b/ucm-config/for_all_boards/DELL PROFESSIONAL SOUND BAR AE5/DELL PROFESSIONAL SOUND BAR AE5.conf deleted file mode 100644 index e34c8135..00000000 --- a/ucm-config/for_all_boards/DELL PROFESSIONAL SOUND BAR AE5/DELL PROFESSIONAL SOUND BAR AE5.conf +++ /dev/null @@ -1,6 +0,0 @@ -Comment "DELL PROFESSIONAL SOUND BAR AE5" - -SectionUseCase."HiFi" { - File "HiFi.conf" - Comment "Default" -} diff --git a/ucm-config/for_all_boards/DELL PROFESSIONAL SOUND BAR AE5/HiFi.conf b/ucm-config/for_all_boards/DELL PROFESSIONAL SOUND BAR AE5/HiFi.conf deleted file mode 100644 index 67bd2d52..00000000 --- a/ucm-config/for_all_boards/DELL PROFESSIONAL SOUND BAR AE5/HiFi.conf +++ /dev/null @@ -1,27 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} - -SectionDevice."Dell AE515 USB SoundBar Output".0 { - Comment "SoundBar Output" - - Value { - PlaybackPCM "hw:AE5,0" - } -} - -SectionDevice."Dell AE515 USB SoundBar Input".0 { - Comment "SoundBar Input" - - Value { - CapturePCM "hw:AE5,0" - } -} diff --git a/ucm-config/for_all_boards/Dell AC511 USB SoundBar/HiFi.conf b/ucm-config/for_all_boards/Dell AC511 USB SoundBar/HiFi.conf deleted file mode 100644 index e920e3c2..00000000 --- a/ucm-config/for_all_boards/Dell AC511 USB SoundBar/HiFi.conf +++ /dev/null @@ -1,30 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:SoundBar" - - cset "name='PCM Playback Volume' 51" - ] - - DisableSequence [ - ] -} - -SectionDevice."Dell AC511 USB SoundBar Output".0 { - Comment "SoundBar Output" - - Value { - PlaybackPCM "hw:SoundBar,0" - } -} - -SectionDevice."Dell AC511 USB SoundBar Input".0 { - Comment "SoundBar Input" - - Value { - CapturePCM "hw:SoundBar,0" - } -} diff --git a/ucm-config/for_all_boards/Dell-WD15-Dock/Dell-WD15-Dock.conf b/ucm-config/for_all_boards/Dell-WD15-Dock/Dell-WD15-Dock.conf deleted file mode 100644 index 290758a3..00000000 --- a/ucm-config/for_all_boards/Dell-WD15-Dock/Dell-WD15-Dock.conf +++ /dev/null @@ -1,5 +0,0 @@ -Comment "USB-audio on Dell docking station" -SectionUseCase."HiFi" { - File "HiFi.conf" - Comment "Default" -} diff --git a/ucm-config/for_all_boards/Dell-WD15-Dock/HiFi.conf b/ucm-config/for_all_boards/Dell-WD15-Dock/HiFi.conf deleted file mode 100644 index c522540f..00000000 --- a/ucm-config/for_all_boards/Dell-WD15-Dock/HiFi.conf +++ /dev/null @@ -1,40 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - EnableSequence [ - cdev "hw:Dock" - ] - DisableSequence [ - ] -} - -SectionDevice."Dock Headphone".0 { - Comment "Headphone" - - Value { - PlaybackPCM "hw:Dock,0" - } -} - -SectionDevice."Dock Line Out".0 { - Value { - PlaybackPCM "hw:Dock,1" - } - EnableSequence [ - cdev "hw:Dock" - cset "name='Line Playback Switch' on" - ] - DisableSequence [ - cdev "hw:Dock" - cset "name='Line Playback Switch' off" - ] -} - -SectionDevice."Dock Microphone".0 { - Comment "Microphone" - - Value { - CapturePCM "hw:Dock,0" - } -} diff --git a/ucm-config/for_all_boards/HD Pro Webcam C920/HD Pro Webcam C920.conf b/ucm-config/for_all_boards/HD Pro Webcam C920/HD Pro Webcam C920.conf new file mode 100644 index 00000000..e7394ba8 --- /dev/null +++ b/ucm-config/for_all_boards/HD Pro Webcam C920/HD Pro Webcam C920.conf @@ -0,0 +1,6 @@ +Comment "HD Pro Webcam C920" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/for_all_boards/HD Pro Webcam C920/HiFi.conf b/ucm-config/for_all_boards/HD Pro Webcam C920/HiFi.conf new file mode 100644 index 00000000..e7d37232 --- /dev/null +++ b/ucm-config/for_all_boards/HD Pro Webcam C920/HiFi.conf @@ -0,0 +1,28 @@ +SectionVerb { + Value { + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:C920" + + cset "name='Mic Capture Volume' 5" + ] + + DisableSequence [ + ] +} + +SectionDevice."Mic" { + Value { + CapturePCM "hw:HD Pro Webcam C920,0" + MaxSoftwareGain "2000" + JackType "always" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} diff --git a/ucm-config/for_all_boards/HUAWEI USB-C HEADSET/HiFi.conf b/ucm-config/for_all_boards/HUAWEI USB-C HEADSET/HiFi.conf deleted file mode 100644 index d48942bf..00000000 --- a/ucm-config/for_all_boards/HUAWEI USB-C HEADSET/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:HEADSET" - cset "name='PCM Playback Volume' 45" - ] - - DisableSequence [ - ] -} - -SectionDevice."HUAWEI USB-C HEADSET Output".0 { - Value { - PlaybackPCM "hw:HEADSET,0" - } -} - -SectionDevice."HUAWEI USB-C HEADSET Input".0 { - Value { - CapturePCM "hw:HEADSET,0" - } -} diff --git a/ucm-config/for_all_boards/ICUSBAUDIO7D/HiFi.conf b/ucm-config/for_all_boards/ICUSBAUDIO7D/HiFi.conf deleted file mode 100644 index c44de8dd..00000000 --- a/ucm-config/for_all_boards/ICUSBAUDIO7D/HiFi.conf +++ /dev/null @@ -1,132 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:ICUSBAUDIO7D" - - cset "name='Line Capture Switch', off" - cset "name='Mic Capture Switch', off" - cset "name='IEC958 In Capture Switch', off" - cset "name='PCM Capture Switch', off" - cset "name='Speaker Playback Switch', off" - cset "name='Mic Playback Switch', off" - ] - - DisableSequence [ - ] -} - -SectionDevice."Speaker-Headset".0 { - Comment "Speaker out" - - Value { - PlaybackPCM "hw:ICUSBAUDIO7D,0" - PlaybackMixerElem "Speaker" - } - - EnableSequence [ - cset "name='Speaker Playback Switch', on" - ] - - DisableSequence [ - cset "name='Speaker Playback Switch', off" - ] -} - -SectionDevice."Line In".0 { - Comment "Line In" - - Value { - CapturePCM "hw:ICUSBAUDIO7D,0" - CaptureMixerElem "Line" - } - - ConflictingDevice [ - "Mic" - "SPDIF In" - "PCM" - ] - - EnableSequence [ - cset "name='Line Capture Switch', on" - cset "name='PCM Capture Source', Line" - ] - - DisableSequence [ - cset "name='Line Capture Switch', off" - ] -} - -SectionDevice."Mic".0 { - Comment "Mic Input" - - Value { - CapturePCM "hw:ICUSBAUDIO7D,0" - CaptureMixerElem "Mic" - } - - ConflictingDevice [ - "Line In" - "SPDIF In" - "PCM" - ] - - EnableSequence [ - cset "name='Mic Capture Switch', on" - cset "name='PCM Capture Source', Mic" - ] - - DisableSequence [ - cset "name='Mic Capture Switch', off" - ] -} - -SectionDevice."SPDIF In".0 { - Comment "S/PDIF In" - - Value { - CapturePCM "hw:ICUSBAUDIO7D,0" - CaptureMixerElem "IEC958 In" - } - - ConflictingDevice [ - "Line In" - "Mic" - "PCM" - ] - - EnableSequence [ - cset "name='IEC958 In Capture Switch', on" - cset "name='PCM Capture Source', IEC958 In" - ] - - DisableSequence [ - cset "name='IEC958 In Capture Switch', off" - ] -} - -SectionDevice."PCM".0 { - Comment "PCM Capture" - - Value { - CapturePCM "hw:ICUSBAUDIO7D,0" - CaptureMixerElem "PCM" - } - - ConflictingDevice [ - "Line In" - "Mic" - "SPDIF In" - ] - - EnableSequence [ - cset "name='PCM Capture Switch', on" - cset "name='PCM Capture Source', Mixer" - ] - - DisableSequence [ - cset "name='PCM Capture Switch', off" - ] -} diff --git a/ucm-config/for_all_boards/Jabra SPEAK 810/HiFi.conf b/ucm-config/for_all_boards/Jabra SPEAK 810/HiFi.conf index 313bffef..5a73702c 100644 --- a/ucm-config/for_all_boards/Jabra SPEAK 810/HiFi.conf +++ b/ucm-config/for_all_boards/Jabra SPEAK 810/HiFi.conf @@ -10,7 +10,7 @@ SectionVerb { ] } -SectionDevice."Jabra Speak 810".0 { +SectionDevice."Dummy".0 { EnableSequence [ ] diff --git a/ucm-config/for_all_boards/Logitech BRIO/HiFi.conf b/ucm-config/for_all_boards/Logitech BRIO/HiFi.conf deleted file mode 100644 index eb20ee2d..00000000 --- a/ucm-config/for_all_boards/Logitech BRIO/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:BRIO" - cset "name='Mic Capture Volume' 24" - ] - - DisableSequence [ - ] -} - -SectionDevice."BRIO" { - Value { - CapturePCM "hw:BRIO,0" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} diff --git a/ucm-config/for_all_boards/Logitech Webcam C930e/HiFi.conf b/ucm-config/for_all_boards/Logitech Webcam C930e/HiFi.conf deleted file mode 100644 index 95f2fcf8..00000000 --- a/ucm-config/for_all_boards/Logitech Webcam C930e/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:C930e" - cset "name='Mic Capture Volume' 30" - ] - - DisableSequence [ - ] -} - -SectionDevice."C930e" { - Value { - CapturePCM "hw:C930e,0" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} diff --git a/ucm-config/for_all_boards/Logitech Webcam C930e/Logitech Webcam C930e.conf b/ucm-config/for_all_boards/Logitech Webcam C930e/Logitech Webcam C930e.conf deleted file mode 100644 index f6760e2d..00000000 --- a/ucm-config/for_all_boards/Logitech Webcam C930e/Logitech Webcam C930e.conf +++ /dev/null @@ -1,6 +0,0 @@ -Comment "Logitech Webcam C930e" - -SectionUseCase."HiFi" { - File "HiFi.conf" - Comment "Default" -} diff --git a/ucm-config/for_all_boards/Loopback/HiFi.conf b/ucm-config/for_all_boards/Loopback/HiFi.conf deleted file mode 100644 index 254c9956..00000000 --- a/ucm-config/for_all_boards/Loopback/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} - -SectionDevice."Loopback Playback".0 { - Value { - PlaybackPCM "hw:Loopback,0" - PlaybackChannels "8" - } -} - -SectionDevice."Loopback Capture".0 { - Value { - CapturePCM "hw:Loopback,1" - CaptureChannels "8" - } -} diff --git a/ucm-config/for_all_boards/Mi Dual Driver Earphones Type-C/HiFi.conf b/ucm-config/for_all_boards/Mi Dual Driver Earphones Type-C/HiFi.conf deleted file mode 100644 index 9d63e16e..00000000 --- a/ucm-config/for_all_boards/Mi Dual Driver Earphones Type-C/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:TypeC" - cset "name='PCM Playback Volume' 45" - ] - - DisableSequence [ - ] -} - -SectionDevice."Mi Earphones Output".0 { - Value { - PlaybackPCM "hw:TypeC,0" - } -} - -SectionDevice."Mi Earphones Input".0 { - Value { - CapturePCM "hw:TypeC,0" - } -} diff --git a/ucm-config/for_all_boards/Mi Dual Driver Earphones Type-C/Mi Dual Driver Earphones Type-C.conf b/ucm-config/for_all_boards/Mi Dual Driver Earphones Type-C/Mi Dual Driver Earphones Type-C.conf deleted file mode 100644 index df19b47b..00000000 --- a/ucm-config/for_all_boards/Mi Dual Driver Earphones Type-C/Mi Dual Driver Earphones Type-C.conf +++ /dev/null @@ -1,6 +0,0 @@ -Comment "Mi Dual Driver Earphones Type-C" - -SectionUseCase."HiFi" { - File "HiFi.conf" - Comment "Default" -} diff --git a/ucm-config/for_all_boards/PCP-USB/HiFi.conf b/ucm-config/for_all_boards/PCP-USB/HiFi.conf deleted file mode 100644 index ac5c7ed7..00000000 --- a/ucm-config/for_all_boards/PCP-USB/HiFi.conf +++ /dev/null @@ -1,20 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:PCPUSB" - - cset "name='Mic Capture Volume' 19" - ] - - DisableSequence [ - ] -} - -SectionDevice."PCP USB Input".0 { - Value { - CapturePCM "hw:PCPUSB,0" - } -} diff --git a/ucm-config/for_all_boards/Pixel USB-C earbuds/HiFi.conf b/ucm-config/for_all_boards/Pixel USB-C earbuds/HiFi.conf deleted file mode 100644 index 7a607456..00000000 --- a/ucm-config/for_all_boards/Pixel USB-C earbuds/HiFi.conf +++ /dev/null @@ -1,24 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} - -SectionDevice."Google Pixel earbuds Output".0 { - Value { - PlaybackPCM "hw:earbuds,0" - } -} - -SectionDevice."Google Pixel earbuds Input".0 { - Value { - CapturePCM "hw:earbuds,0" - IntrinsicSensitivity "-3100" - } -} diff --git a/ucm-config/for_all_boards/Plankton Captured HDMI Audio/HiFi.conf b/ucm-config/for_all_boards/Plankton Captured HDMI Audio/HiFi.conf new file mode 100644 index 00000000..1a1f4a29 --- /dev/null +++ b/ucm-config/for_all_boards/Plankton Captured HDMI Audio/HiFi.conf @@ -0,0 +1,24 @@ +SectionVerb { + Value { + FullySpecifiedUCM "1" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} + +SectionDevice."Plankton Captured HDMI Audio".0 { + Value { + CapturePCM "hw:Plankton Captured HDMI Audio,0" + JackType "always" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} diff --git a/ucm-config/for_all_boards/Plankton Captured HDMI Audio/Plankton Captured HDMI Audio.conf b/ucm-config/for_all_boards/Plankton Captured HDMI Audio/Plankton Captured HDMI Audio.conf new file mode 100644 index 00000000..6514aa1c --- /dev/null +++ b/ucm-config/for_all_boards/Plankton Captured HDMI Audio/Plankton Captured HDMI Audio.conf @@ -0,0 +1,6 @@ +Comment "Plankton Captured HDMI Audio" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/for_all_boards/Plantronics DA70/HiFi.conf b/ucm-config/for_all_boards/Plantronics DA70/HiFi.conf deleted file mode 100644 index 0840b5d1..00000000 --- a/ucm-config/for_all_boards/Plantronics DA70/HiFi.conf +++ /dev/null @@ -1,28 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:SoundBar" - ] - - DisableSequence [ - ] -} - -SectionDevice."Plantronics DA70 Output".0 { - Comment "DA70 Output" - - Value { - PlaybackPCM "hw:DA70,0" - } -} - -SectionDevice."Plantronics DA70 Input".0 { - Comment "DA70 Input" - - Value { - CapturePCM "hw:DA70,0" - } -} diff --git a/ucm-config/for_all_boards/README b/ucm-config/for_all_boards/README new file mode 100644 index 00000000..b5384358 --- /dev/null +++ b/ucm-config/for_all_boards/README @@ -0,0 +1,8 @@ +Regarding the two dead sym links WD15 Dock and WD19 Dock + +ALSA has added a ucm for the ucm the sym links they point to and the ucm +has been patched in the chromiumos overlay. Unfortunately the alsa-lib +installs via Makefile and make HATES files with spaces, so we are keeping +the sym links here (even though they appear dead) they are NOT. Once +deployed with alsa-lib 1.1.8 they will have a proper target on a dut. + diff --git a/ucm-config/for_all_boards/Scarlett 2i2 USB/HiFi.conf b/ucm-config/for_all_boards/Scarlett 2i2 USB/HiFi.conf deleted file mode 100644 index f49d6816..00000000 --- a/ucm-config/for_all_boards/Scarlett 2i2 USB/HiFi.conf +++ /dev/null @@ -1,27 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - EnableSequence [ - cdev "hw:USB,0" - ] - DisableSequence [ - ] -} - -SectionDevice."Scarlett 2i2 USB Output".0 { - Comment "Scarlett 2i2 Output" - - Value { - PlaybackPCM "hw:USB,0" - PlaybackRate "48000" - } -} - -SectionDevice."Scarlett 2i2 USB Input".0 { - Comment "Scarlett 2i2 Input" - Value { - CapturePCM "hw:USB,0" - CaptureRate "48000" - } -} diff --git a/ucm-config/for_all_boards/Scarlett 2i4 USB/HiFi.conf b/ucm-config/for_all_boards/Scarlett 2i4 USB/HiFi.conf deleted file mode 100644 index 894683cd..00000000 --- a/ucm-config/for_all_boards/Scarlett 2i4 USB/HiFi.conf +++ /dev/null @@ -1,27 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - EnableSequence [ - cdev "hw:USB,0" - ] - DisableSequence [ - ] -} - -SectionDevice."Scarlett 2i4 USB Output".0 { - Comment "Scarlett 2i4 Output" - - Value { - PlaybackPCM "hw:USB,0" - PlaybackRate "48000" - } -} - -SectionDevice."Scarlett 2i4 USB Input".0 { - Comment "Scarlett 2i4 Input" - Value { - CapturePCM "hw:USB,0" - CaptureRate "48000" - } -} diff --git a/ucm-config/for_all_boards/Scarlett 2i4 USB/Scarlett 2i4 USB.conf b/ucm-config/for_all_boards/Scarlett 2i4 USB/Scarlett 2i4 USB.conf deleted file mode 100644 index 71ea1696..00000000 --- a/ucm-config/for_all_boards/Scarlett 2i4 USB/Scarlett 2i4 USB.conf +++ /dev/null @@ -1,5 +0,0 @@ -Comment "Scarlett 2i4 USB" -SectionUseCase."HiFi" { - File "HiFi.conf" - Comment "Default" -} diff --git a/ucm-config/for_all_boards/USB 2.0 Camera/HiFi.conf b/ucm-config/for_all_boards/USB 2.0 Camera/HiFi.conf deleted file mode 100644 index e4121da1..00000000 --- a/ucm-config/for_all_boards/USB 2.0 Camera/HiFi.conf +++ /dev/null @@ -1,25 +0,0 @@ -SectionVerb { - Value { - FullySpecifiedUCM "1" - } - - EnableSequence [ - cdev "hw:Camera" - cset "name='Mic Capture Volume' 200" - ] - - DisableSequence [ - ] -} - -SectionDevice."Camera" { - Value { - CapturePCM "hw:Camera,0" - } - - EnableSequence [ - ] - - DisableSequence [ - ] -} diff --git a/ucm-config/for_all_boards/USB 2.0 Camera/USB 2.0 Camera b/ucm-config/for_all_boards/USB 2.0 Camera/USB 2.0 Camera deleted file mode 100644 index 52bd294a..00000000 --- a/ucm-config/for_all_boards/USB 2.0 Camera/USB 2.0 Camera +++ /dev/null @@ -1,6 +0,0 @@ -Comment "ZIQIAN N21 1080P Webcam" - -SectionUseCase."HiFi" { - File "HiFi.conf" - Comment "Default" -} diff --git a/ucm-config/glados/sklnau8825adi/HiFi.conf b/ucm-config/glados/sklnau8825adi/HiFi.conf new file mode 100644 index 00000000..c10104dc --- /dev/null +++ b/ucm-config/glados/sklnau8825adi/HiFi.conf @@ -0,0 +1,512 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + InputDspName "extmic_eq" + } + + EnableSequence [ + cdev "hw:sklnau8825adi" + cset "name='codec1_out mo media0_in mi Switch' off" + cset "name='codec0_out mo media0_in mi Switch' on" + cset "name='DAC Oversampling Rate' 64" + cset "name='Headset Mic Switch' off" + cset "name='BIQ Path Select' ADC" + cset "name='BIQ Coefficients' 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + cset "name='codec0_iv_in Switch' 0" + cset "name='media0_out mo codec0_in mi Switch' off" + cset "name='media0_out mo dmic01_hifi_in mi Switch' on" + cset "name='Pin 5 Mux' cvt 2" + cset "name='Pin 6 Mux' cvt 3" + cset "name='Pin 7 Mux' cvt 4" + cset "name='Mic Volume' 255" + ] + + DisableSequence [ + ] +} + +SectionDevice."Internal Mic".0 { + Value { + MaxSoftwareGain "2400" + InputDspName "" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + CoupledMixers "Left Master,Right Master" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} + +SectionDevice."HDMI1".0 { + Value { + JackName "HDMI/DP, pcm=4 Jack" + DspName "" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} + +SectionDevice."HDMI2".0 { + Value { + JackName "HDMI/DP, pcm=5 Jack" + DspName "" + } + + EnableSequence [ + ] + + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "sklnau8825adi Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:sklnau8825adi" + cset "name='codec0_out mo media0_in mi Switch' off" + cset "name='codec1_out mo media0_in mi Switch' on" + cset "name='Headphone Jack Switch' on" + ] + + DisableSequence [ + cdev "hw:sklnau8825adi" + cset "name='codec0_out mo media0_in mi Switch' on" + cset "name='codec1_out mo media0_in mi Switch' off" + cset "name='Headphone Jack Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "sklnau8825adi Headset Jack" + CaptureControl "Mic" + DefaultNodeGain "800" + } + + EnableSequence [ + cdev "hw:sklnau8825adi" + cset "name='Headset Mic Switch' on" + cset "name='BIQ Coefficients' 0,155,0,6,255,102,0,0,255,179,0,0,0,154,0,6,255,179,128,0" + cset "name='media0_out mo codec0_in mi Switch' on" + cset "name='media0_out mo dmic01_hifi_in mi Switch' off" + ] + + DisableSequence [ + cdev "hw:sklnau8825adi" + cset "name='Headset Mic Switch' off" + cset "name='BIQ Coefficients' 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + cset "name='media0_out mo codec0_in mi Switch' off" + cset "name='media0_out mo dmic01_hifi_in mi Switch' on" + ] +} + +SectionModifier."Hotword Model ar_eg".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/ar_eg.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model cmn_cn".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/cmn_hans_cn.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model cmn_tw".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/cmn_hant_tw.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model cs_cz".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/cs_cz.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model da_dk".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/da_dk.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model de_de".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/de_de.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model en_au".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/en_au.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model en_gb".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/en_gb.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model en_ie".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/en_ie.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model en_in".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/en_in.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model en_ph".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/en_ph.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model en_us".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/en_us.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model es_419".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/es_419.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model es_ar".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/es_ar.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model es_es".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/es_es.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model es_mx".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/es_mx.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model es_us".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/es_us.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model fa_ir".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/fa_ir.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model fi_fi".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/fi_fi.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model fil_ph".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/fil_ph.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model fr_fr".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/fr_fr.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model hi_in".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/hi_in.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model hr_hr".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/hr_hr.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model id_id".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/id_id.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model it_it".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/it_it.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model ja_jp".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/ja_jp.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model ko_kr".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/ko_kr.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model ms_my".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/ms_my.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model nb_no".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/nb_no.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model nl_nl".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/nl_nl.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model pl_pl".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/pl_pl.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model pt_br".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/pt_br.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model ro_ro".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/ro_ro.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model ru_ru".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/ru_ru.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model sv_se".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/sv_se.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model th_th".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/th_th.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model tr_tr".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/tr_tr.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model vi_vn".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/vi_vn.hwd-blob" + ] + + DisableSequence [ + ] +} + +SectionModifier."Hotword Model yue_hk".0 { + EnableSequence [ + cdev "hw:sklnau8825adi" + cset-tlv "name='hwd_in hwd 0 mdl params' /opt/google/skl-hotword-support/yue_hant_hk.hwd-blob" + ] + + DisableSequence [ + ] +} diff --git a/ucm-config/for_all_boards/C505 HD Webcam/C505 HD Webcam.conf b/ucm-config/glados/sklnau8825adi/sklnau8825adi.conf index 126ac331..e1b2a278 100644 --- a/ucm-config/for_all_boards/C505 HD Webcam/C505 HD Webcam.conf +++ b/ucm-config/glados/sklnau8825adi/sklnau8825adi.conf @@ -1,4 +1,4 @@ -Comment "Logitech Webcam C505" +Comment "Glados internal card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/jecht/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/jecht/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..17e4cb15 --- /dev/null +++ b/ucm-config/jecht/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Jecht internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/jecht/HDA Intel PCH/HiFi.conf b/ucm-config/jecht/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/jecht/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/ucm-config/leon/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/leon/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..f6608a08 --- /dev/null +++ b/ucm-config/leon/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Leon internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/leon/HDA Intel PCH/HiFi.conf b/ucm-config/leon/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..03f431e5 --- /dev/null +++ b/ucm-config/leon/HDA Intel PCH/HiFi.conf @@ -0,0 +1,55 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Mic Boost Volume' 2" + cset "name='Internal Mic Boost Volume' 0" + cset "name='Capture Source' 0" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + DspName "" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Speaker Playback Switch' off" + cset "name='Headphone Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 1" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 0" + ] +} diff --git a/ucm-config/link/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/link/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..44e29321 --- /dev/null +++ b/ucm-config/link/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Link internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/link/HDA Intel PCH/HiFi.conf b/ucm-config/link/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..6c78a275 --- /dev/null +++ b/ucm-config/link/HDA Intel PCH/HiFi.conf @@ -0,0 +1,70 @@ +SectionVerb { + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='HP/Speaker Playback Switch' off" + cset "name='HP/Speaker Auto Detect Playback Switch' off" + cset "name='PlayEnhancement Playback Switch' on" + cset "name='Surround Playback Switch' on" + cset "name='Crystalizer Playback Switch' off" + cset "name='Dialog Plus Playback Switch' off" + cset "name='Smart Volume Playback Switch' on" + cset "name='X-Bass Playback Switch' on" + cset "name='Equalizer Playback Switch' off" + cset "name='Echo Cancellation Capture Switch' on" + cset "name='IEC958 Playback Switch' on" + cset "name='IEC958 Playback Switch',index=1 on" + cset "name='IEC958 Playback Switch',index=2 on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 99" + cset "name='CrystalVoice Capture Switch' off" + cset "name='Analog-Mic2 Capture Volume' 90" + cset "name='Analog-Mic2 Capture Switch' on" + cset "name='Mic1-Boost (30dB) Capture Switch' on" + cset "name='AMic1/DMic Capture Switch' off" + cset "name='AMic1/DMic Auto Detect Capture Switch' off" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + } + + EnableSequence [ + cdev "hw:PCH" + + cset "name='PlayEnhancement Playback Switch' off" + cset "name='HP/Speaker Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='PlayEnhancement Playback Switch' on" + cset "name='HP/Speaker Playback Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + + EnableSequence [ + cdev "hw:PCH" + + cset "name='CrystalVoice Capture Switch' off" + cset "name='AMic1/DMic Capture Switch' on" + ] + + DisableSequence [ + cdev "hw:PCH" + + cset "name='CrystalVoice Capture Switch' off" + cset "name='AMic1/DMic Capture Switch' off" + ] +} diff --git a/ucm-config/for_all_boards/ICUSBAUDIO7D/ICUSBAUDIO7D.conf b/ucm-config/mccloud/HDA Intel PCH/HDA Intel PCH.conf index 3dc10fa7..a10a4cd9 100644 --- a/ucm-config/for_all_boards/ICUSBAUDIO7D/ICUSBAUDIO7D.conf +++ b/ucm-config/mccloud/HDA Intel PCH/HDA Intel PCH.conf @@ -1,4 +1,4 @@ -Comment "Startech USB 7D Audio" +Comment "Mccloud internal card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/mccloud/HDA Intel PCH/HiFi.conf b/ucm-config/mccloud/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/mccloud/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/ucm-config/for_all_boards/Plantronics DA70/Plantronics DA70.conf b/ucm-config/monroe/HDA Intel MID/HDA Intel MID.conf index 7857d470..d3bf843f 100644 --- a/ucm-config/for_all_boards/Plantronics DA70/Plantronics DA70.conf +++ b/ucm-config/monroe/HDA Intel MID/HDA Intel MID.conf @@ -1,4 +1,4 @@ -Comment "Plantronics DA70" +Comment "Monroe HDMI card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/monroe/HDA Intel MID/HiFi.conf b/ucm-config/monroe/HDA Intel MID/HiFi.conf new file mode 100644 index 00000000..10cc8528 --- /dev/null +++ b/ucm-config/monroe/HDA Intel MID/HiFi.conf @@ -0,0 +1,15 @@ +SectionVerb { + Value { + } + EnableSequence [ + ] + DisableSequence [ + ] +} + +SectionDevice."OUTPUT".0 { + Value { + JackName "HDMI/DP,pcm=3 Jack" + OverrideNodeType "Internal Speaker" + } +} diff --git a/ucm-config/monroe/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/monroe/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..cbd74d48 --- /dev/null +++ b/ucm-config/monroe/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Monroe internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/monroe/HDA Intel PCH/HiFi.conf b/ucm-config/monroe/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..54dd5a96 --- /dev/null +++ b/ucm-config/monroe/HDA Intel PCH/HiFi.conf @@ -0,0 +1,37 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Mic Boost Volume' 2" + cset "name='Internal Mic Boost Volume' 1" + cset "name='Capture Source' 0" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + } +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 1" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 0" + ] +} diff --git a/ucm-config/panther/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/panther/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..813d96e2 --- /dev/null +++ b/ucm-config/panther/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Panther internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/panther/HDA Intel PCH/HiFi.conf b/ucm-config/panther/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/panther/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/ucm-config/peppy/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/peppy/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..819f8265 --- /dev/null +++ b/ucm-config/peppy/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Peppy internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/peppy/HDA Intel PCH/HiFi.conf b/ucm-config/peppy/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..c33144d1 --- /dev/null +++ b/ucm-config/peppy/HDA Intel PCH/HiFi.conf @@ -0,0 +1,55 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Mic Boost Volume' 2" + cset "name='Internal Mic Boost Volume' 1" + cset "name='Input Source' 1" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + DspName "" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Speaker Playback Switch' off" + cset "name='Headphone Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Input Source' 0" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Input Source' 1" + ] +} diff --git a/ucm-config/rikku/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/rikku/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..d9365ccc --- /dev/null +++ b/ucm-config/rikku/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Rikku internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/rikku/HDA Intel PCH/HiFi.conf b/ucm-config/rikku/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/rikku/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/ucm-config/stout/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/stout/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..2751b940 --- /dev/null +++ b/ucm-config/stout/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Stout internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/stout/HDA Intel PCH/HiFi.conf b/ucm-config/stout/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..20c809a9 --- /dev/null +++ b/ucm-config/stout/HDA Intel PCH/HiFi.conf @@ -0,0 +1,62 @@ +SectionVerb { + Value { + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Headphone Playback Volume' 87" + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Volume' 87" + cset "name='Speaker Playback Switch' on" + cset "name='Mic Playback Volume' 0" + cset "name='Mic Playback Switch' off" + cset "name='Internal Mic Boost Volume' 0" + cset "name='Mic Boost Volume' 0" + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Master Playback Volume' 79" + cset "name='Master Playback Switch' on" + cset "name='IEC958 Playback Switch' on" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Speaker Pin Playback Switch' off" + cset "name='HP Pin Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='HP Pin Playback Switch' off" + cset "name='Speaker Pin Playback Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 1" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 0" + ] +} + +SectionDevice."HDMI".0 { + Value { + } +} diff --git a/ucm-config/strago/chtrt5645/HiFi.conf b/ucm-config/strago/chtrt5645/HiFi.conf new file mode 100644 index 00000000..e51c9472 --- /dev/null +++ b/ucm-config/strago/chtrt5645/HiFi.conf @@ -0,0 +1,121 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + + EnableSequence [ + cdev "hw:chtrt5645" + + cset "name='codec_out1 mix 0 pcm0_in Switch' on" + cset "name='media0_out mix 0 media1_in Switch' on" + + cset "name='media1_in Gain 0 Ramp Delay' 50" + cset "name='media1_in Gain 0 Switch' off" + cset "name='media1_in Gain 0 Volume' 80% 80%" + + cset "name='pcm0_in Gain 0 Ramp Delay' 50" + cset "name='pcm0_in Gain 0 Switch' off" + cset "name='pcm0_in Gain 0 Volume' 80% 80%" + + cset "name='codec_out1 Gain 0 Ramp Delay' 50" + cset "name='codec_out1 Gain 0 Switch' off" + cset "name='codec_out1 Gain 0 Volume' 70% 70%" + + cset "name='Ext Spk Switch' on" + cset "name='Speaker Channel Switch' on" + cset "name='Ext HP Switch' off" + + cset "name='DAC R2 Mux' 'IF1 DAC'" + cset "name='DAC L2 Mux' 'IF1 DAC'" + cset "name='Mono DAC MIXL DAC L2 Switch' on" + cset "name='Mono DAC MIXR DAC R2 Switch' on" + cset "name='DAC2 Playback Switch' on" + + cset "name='HPOVOL MIXL DAC2 Switch' on" + cset "name='HPOVOL MIXR DAC2 Switch' on" + cset "name='HPO MIX HPVOL Switch' on" + cset "name='HPOVOL L Switch' on" + cset "name='HPOVOL R Switch' on" + + cset "name='SPK MIXL DAC L2 Switch' on" + cset "name='SPK MIXR DAC R2 Switch' on" + cset "name='SPOL MIX SPKVOL L Switch' on" + cset "name='SPOR MIX SPKVOL R Switch' on" + cset "name='SPKVOL L Switch' on" + cset "name='SPKVOL R Switch' on" + + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + cset "name='ADC Capture Switch' on" + cset "name='Stereo1 DMIC Mux' 0" + cset "name='Stereo1 ADC2 Mux' 1" + cset "name='I2S2 Func Switch' 0" + cset "name='pcm1_out mix 0 media_loop2_in Switch' 1" + cset "name='media_loop2_out mix 0 codec_in0 Switch' 1" + cset "name='codec_in0 Gain 0 Ramp Delay' 50" + cset "name='codec_in0 Gain 0 Switch' off" + cset "name='codec_in0 Gain 0 Volume' 80% 80%" + cset "name='media_loop2_out Gain 0 Ramp Delay' 50" + cset "name='media_loop2_out Gain 0 Switch' off" + cset "name='media_loop2_out Gain 0 Volume' 80% 80%" + cset "name='pcm1_out Gain 0 Ramp Delay' 50" + cset "name='pcm1_out Gain 0 Switch' off" + cset "name='pcm1_out Gain 0 Volume' 80% 80%" + ] + + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "chtrt5645 Headphone Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:chtrt5645" + cset "name='Ext Spk Switch' off" + cset "name='Speaker Channel Switch' off" + cset "name='Ext HP Switch' on" + cset "name='HP Channel Switch' on" + ] + + DisableSequence [ + cdev "hw:chtrt5645" + cset "name='Ext Spk Switch' on" + cset "name='Speaker Channel Switch' on" + cset "name='Ext HP Switch' off" + cset "name='HP Channel Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "chtrt5645 Mic Jack" + } + + EnableSequence [ + cdev "hw:chtrt5645" + cset "name='Headset Mic Switch' on" + cset "name='Int Mic Switch' off" + cset "name='Sto1 ADC MIXL ADC2 Switch' 0" + cset "name='Sto1 ADC MIXR ADC2 Switch' 0" + cset "name='RECMIXL BST1 Switch' 1" + cset "name='RECMIXR BST1 Switch' 1" + cset "name='Sto1 ADC MIXL ADC1 Switch' 1" + cset "name='Sto1 ADC MIXR ADC1 Switch' 1" + ] + + DisableSequence [ + cdev "hw:chtrt5645" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + cset "name='RECMIXL BST1 Switch' 0" + cset "name='RECMIXR BST1 Switch' 0" + cset "name='Sto1 ADC MIXL ADC1 Switch' 0" + cset "name='Sto1 ADC MIXR ADC1 Switch' 0" + cset "name='Sto1 ADC MIXL ADC2 Switch' 1" + cset "name='Sto1 ADC MIXR ADC2 Switch' 1" + ] +} diff --git a/ucm-config/strago/chtrt5645/chtrt5645.conf b/ucm-config/strago/chtrt5645/chtrt5645.conf new file mode 100644 index 00000000..14b8450f --- /dev/null +++ b/ucm-config/strago/chtrt5645/chtrt5645.conf @@ -0,0 +1,6 @@ +Comment "Strago internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/strago/chtrt5650/HiFi.conf b/ucm-config/strago/chtrt5650/HiFi.conf new file mode 100644 index 00000000..4cdc9009 --- /dev/null +++ b/ucm-config/strago/chtrt5650/HiFi.conf @@ -0,0 +1,129 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + + EnableSequence [ + cdev "hw:chtrt5650" + + cset "name='codec_out0 mix 0 pcm0_in Switch' on" + cset "name='media0_out mix 0 media1_in Switch' on" + + cset "name='media1_in Gain 0 Ramp Delay' 50" + cset "name='media1_in Gain 0 Switch' off" + cset "name='media1_in Gain 0 Volume' 80% 80%" + + cset "name='pcm0_in Gain 0 Ramp Delay' 50" + cset "name='pcm0_in Gain 0 Switch' off" + cset "name='pcm0_in Gain 0 Volume' 80% 80%" + + cset "name='codec_out0 Gain 0 Ramp Delay' 50" + cset "name='codec_out0 Gain 0 Switch' off" + cset "name='codec_out0 Gain 0 Volume' 80% 80%" + + cset "name='Ext Spk Switch' on" + cset "name='Speaker Channel Switch' on" + cset "name='Ext HP Switch' off" + + cset "name='Stereo DAC MIXL DAC L1 Switch' on" + cset "name='Stereo DAC MIXR DAC R1 Switch' on" + cset "name='DAC1 MIXL DAC1 Switch' on" + cset "name='DAC1 MIXR DAC1 Switch' on" + + cset "name='SPK MIXL DAC L1 Switch' on" + cset "name='SPK MIXR DAC R1 Switch' on" + cset "name='SPOL MIX SPKVOL L Switch' on" + cset "name='SPOR MIX SPKVOL R Switch' on" + cset "name='SPKVOL L Switch' on" + cset "name='SPKVOL R Switch' on" + cset "name='Speaker Channel Switch' on" + + cset "name='HPOVOL MIXL DAC1 Switch' on" + cset "name='HPOVOL MIXR DAC1 Switch' on" + cset "name='HPO MIX HPVOL Switch' on" + cset "name='HPOVOL L Switch' on" + cset "name='HPOVOL R Switch' on" + cset "name='Headphone Channel Switch' on" + + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + cset "name='ADC Capture Switch' on" + cset "name='Stereo1 DMIC Mux' 1" + cset "name='Stereo1 ADC2 Mux' 1" + cset "name='I2S2 Func Switch' 0" + cset "name='RT5650 IF1 ADC Mux' 0" + cset "name='ADC Capture Volume' 74" + + cset "name='Sto1 ADC MIXL ADC1 Switch' 0" + cset "name='Sto1 ADC MIXR ADC1 Switch' 0" + cset "name='Sto1 ADC MIXL ADC2 Switch' 1" + cset "name='Sto1 ADC MIXR ADC2 Switch' 1" + + cset "name='pcm1_out mix 0 media_loop2_in Switch' 1" + cset "name='media_loop2_out mix 0 codec_in0 Switch' 1" + cset "name='codec_in0 Gain 0 Ramp Delay' 50" + cset "name='codec_in0 Gain 0 Switch' off" + cset "name='codec_in0 Gain 0 Volume' 80% 80%" + cset "name='media_loop2_out Gain 0 Ramp Delay' 50" + cset "name='media_loop2_out Gain 0 Switch' off" + cset "name='media_loop2_out Gain 0 Volume' 80% 80%" + cset "name='pcm1_out Gain 0 Ramp Delay' 50" + cset "name='pcm1_out Gain 0 Switch' off" + cset "name='pcm1_out Gain 0 Volume' 80% 80%" + + + ] + + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "chtrt5650 Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:chtrt5650" + cset "name='Ext Spk Switch' off" + cset "name='Ext HP Switch' on" + ] + DisableSequence [ + cdev "hw:chtrt5650" + cset "name='Ext Spk Switch' on" + cset "name='Ext HP Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "chtrt5650 Headset Jack" + } + + EnableSequence [ + cdev "hw:chtrt5650" + cset "name='Headset Mic Switch' on" + cset "name='Int Mic Switch' off" + cset "name='Sto1 ADC MIXL ADC2 Switch' 0" + cset "name='Sto1 ADC MIXR ADC2 Switch' 0" + cset "name='RECMIXL BST1 Switch' 1" + cset "name='RECMIXR BST1 Switch' 1" + cset "name='Sto1 ADC MIXL ADC1 Switch' 1" + cset "name='Sto1 ADC MIXR ADC1 Switch' 1" + cset "name='IN1 Boost' 1" + ] + + DisableSequence [ + cdev "hw:chtrt5650" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + cset "name='RECMIXL BST1 Switch' 0" + cset "name='RECMIXR BST1 Switch' 0" + cset "name='Sto1 ADC MIXL ADC1 Switch' 0" + cset "name='Sto1 ADC MIXR ADC1 Switch' 0" + cset "name='Sto1 ADC MIXL ADC2 Switch' 1" + cset "name='Sto1 ADC MIXR ADC2 Switch' 1" + cset "name='IN1 Boost' 0" + ] +} diff --git a/ucm-config/strago/chtrt5650/chtrt5650.conf b/ucm-config/strago/chtrt5650/chtrt5650.conf new file mode 100644 index 00000000..14b8450f --- /dev/null +++ b/ucm-config/strago/chtrt5650/chtrt5650.conf @@ -0,0 +1,6 @@ +Comment "Strago internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/strago/chtrt5676/HiFi.conf b/ucm-config/strago/chtrt5676/HiFi.conf new file mode 100644 index 00000000..dd2354fd --- /dev/null +++ b/ucm-config/strago/chtrt5676/HiFi.conf @@ -0,0 +1,106 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + + EnableSequence [ + cdev "hw:chtrt5676" + + cset "name='codec_out0 mix 0 pcm0_in Switch' on" + cset "name='media0_out mix 0 media1_in Switch' on" + + cset "name='media1_in Gain 0 Ramp Delay' 50" + cset "name='media1_in Gain 0 Switch' off" + cset "name='media1_in Gain 0 Volume' 80% 80%" + + cset "name='pcm0_in Gain 0 Ramp Delay' 50" + cset "name='pcm0_in Gain 0 Switch' off" + cset "name='pcm0_in Gain 0 Volume' 80% 80%" + + cset "name='codec_out0 Gain 0 Ramp Delay' 50" + cset "name='codec_out0 Gain 0 Switch' off" + cset "name='codec_out0 Gain 0 Volume' 70% 70%" + + cset "name='Ext Spk Switch' on" + cset "name='Ext HP Switch' off" + + cset "name='DAC1 MIXL DAC1 Switch' on" + cset "name='DAC1 MIXR DAC1 Switch' on" + cset "name='Stereo DAC MIXL DAC1 L Switch' on" + cset "name='Stereo DAC MIXR DAC1 R Switch' on" + cset "name='PDM1 L Mux' 0" + cset "name='PDM1 R Mux' 0" + + cset "name='DAC1 Mux' 0" + cset "name='DAC12 SRC Mux' 0" + cset "name='OUT1 Playback Switch' on" + cset "name='OUT2 Playback Switch' on" + + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='Stereo1 DMIC Mux' 0" + cset "name='Stereo1 ADC2 Mux' 1" + cset "name='Sto1 ADC MIXL ADC2 Switch' on" + cset "name='Sto1 ADC MIXR ADC2 Switch' on" + cset "name='IF1 ADC1 Mux' 0" + + cset "name='Stereo1 ADC1 Mux' 1" + cset "name='Sto1 ADC MIXL ADC1 Switch' on" + cset "name='Sto1 ADC MIXR ADC1 Switch' on" + cset "name='IN1 Boost' 1" + cset "name='IF1 ADC1 Swap Mux' 2" + + cset "name='pcm1_out mix 0 media_loop2_in Switch' 1" + cset "name='media_loop2_out mix 0 codec_in0 Switch' 1" + cset "name='codec_in0 Gain 0 Ramp Delay' 50" + cset "name='codec_in0 Gain 0 Switch' off" + cset "name='codec_in0 Gain 0 Volume' 80% 80%" + cset "name='media_loop2_out Gain 0 Ramp Delay' 50" + cset "name='media_loop2_out Gain 0 Switch' off" + cset "name='media_loop2_out Gain 0 Volume' 80% 80%" + cset "name='pcm1_out Gain 0 Ramp Delay' 50" + cset "name='pcm1_out Gain 0 Switch' off" + cset "name='pcm1_out Gain 0 Volume' 80% 80%" + ] + + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "chtrt5676 Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:chtrt5676" + cset "name='Ext Spk Switch' off" + cset "name='Ext HP Switch' on" + ] + + DisableSequence [ + cdev "hw:chtrt5676" + cset "name='Ext Spk Switch' on" + cset "name='Ext HP Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "chtrt5676 Headset Jack" + } + + EnableSequence [ + cdev "hw:chtrt5676" + cset "name='Headset Mic Switch' on" + cset "name='Int Mic Switch' off" + ] + + DisableSequence [ + cdev "hw:chtrt5676" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + ] +} diff --git a/ucm-config/strago/chtrt5676/chtrt5676.conf b/ucm-config/strago/chtrt5676/chtrt5676.conf new file mode 100644 index 00000000..14b8450f --- /dev/null +++ b/ucm-config/strago/chtrt5676/chtrt5676.conf @@ -0,0 +1,6 @@ +Comment "Strago internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/tidus/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/tidus/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..ad8ba1af --- /dev/null +++ b/ucm-config/tidus/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Tidus internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/tidus/HDA Intel PCH/HiFi.conf b/ucm-config/tidus/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/tidus/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/ucm-config/tricky/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/tricky/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..f9b1aece --- /dev/null +++ b/ucm-config/tricky/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Tricky internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/tricky/HDA Intel PCH/HiFi.conf b/ucm-config/tricky/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/tricky/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/ucm-config/veyron/ROCKCHIP-I2S/HiFi.conf b/ucm-config/veyron/ROCKCHIP-I2S/HiFi.conf new file mode 100644 index 00000000..a7d8020d --- /dev/null +++ b/ucm-config/veyron/ROCKCHIP-I2S/HiFi.conf @@ -0,0 +1,137 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + cset "name='Headphone Switch' on" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} diff --git a/ucm-config/for_all_boards/Logitech BRIO/Logitech BRIO.conf b/ucm-config/veyron/ROCKCHIP-I2S/ROCKCHIP-I2S.conf index 7059edac..0c399b0d 100644 --- a/ucm-config/for_all_boards/Logitech BRIO/Logitech BRIO.conf +++ b/ucm-config/veyron/ROCKCHIP-I2S/ROCKCHIP-I2S.conf @@ -1,4 +1,4 @@ -Comment "Logitech BRIO" +Comment "Rockchip card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/veyron/RockchipHDMI/HiFi.conf b/ucm-config/veyron/RockchipHDMI/HiFi.conf new file mode 100644 index 00000000..bf76d6a6 --- /dev/null +++ b/ucm-config/veyron/RockchipHDMI/HiFi.conf @@ -0,0 +1,12 @@ +SectionVerb { + Value { + MinBufferLevel "512" + } +} + +SectionDevice."HDMI".0 { + Value { + JackName "RockchipHDMI HDMI Jack" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } +} diff --git a/ucm-config/veyron/RockchipHDMI/RockchipHDMI.conf b/ucm-config/veyron/RockchipHDMI/RockchipHDMI.conf new file mode 100644 index 00000000..a167d741 --- /dev/null +++ b/ucm-config/veyron/RockchipHDMI/RockchipHDMI.conf @@ -0,0 +1,6 @@ +Comment "Rockchip HDMI card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron/VEYRON-I2S/HiFi.conf b/ucm-config/veyron/VEYRON-I2S/HiFi.conf new file mode 100644 index 00000000..2698529d --- /dev/null +++ b/ucm-config/veyron/VEYRON-I2S/HiFi.conf @@ -0,0 +1,158 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + cset "name='Speaker Switch' off" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Switch' off" + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + OutputDspName "" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='HP Left Out Switch' on" + cset "name='HP Right Out Switch' on" + cset "name='Headphone Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} + +SectionDevice."HDMI".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,1" + JackName "VEYRON-I2S HDMI Jack" + JackType "gpio" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + ] +} diff --git a/ucm-config/for_all_boards/Loopback/Loopback.conf b/ucm-config/veyron/VEYRON-I2S/VEYRON-I2S.conf index 44abedda..0c399b0d 100644 --- a/ucm-config/for_all_boards/Loopback/Loopback.conf +++ b/ucm-config/veyron/VEYRON-I2S/VEYRON-I2S.conf @@ -1,4 +1,4 @@ -Comment "Loopback" +Comment "Rockchip card" SectionUseCase."HiFi" { File "HiFi.conf" diff --git a/ucm-config/veyron_fievel/ROCKCHIP-I2S/HiFi.conf b/ucm-config/veyron_fievel/ROCKCHIP-I2S/HiFi.conf new file mode 100644 index 00000000..c9e570ac --- /dev/null +++ b/ucm-config/veyron_fievel/ROCKCHIP-I2S/HiFi.conf @@ -0,0 +1,103 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + cset "name='Headphone Switch' on" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} diff --git a/ucm-config/for_all_boards/Scarlett 2i2 USB/Scarlett 2i2 USB.conf b/ucm-config/veyron_fievel/ROCKCHIP-I2S/ROCKCHIP-I2S.conf index 88bac6ba..0c399b0d 100644 --- a/ucm-config/for_all_boards/Scarlett 2i2 USB/Scarlett 2i2 USB.conf +++ b/ucm-config/veyron_fievel/ROCKCHIP-I2S/ROCKCHIP-I2S.conf @@ -1,4 +1,5 @@ -Comment "Scarlett 2i2 USB" +Comment "Rockchip card" + SectionUseCase."HiFi" { File "HiFi.conf" Comment "Default" diff --git a/ucm-config/veyron_fievel/RockchipHDMI/HiFi.conf b/ucm-config/veyron_fievel/RockchipHDMI/HiFi.conf new file mode 100644 index 00000000..bf76d6a6 --- /dev/null +++ b/ucm-config/veyron_fievel/RockchipHDMI/HiFi.conf @@ -0,0 +1,12 @@ +SectionVerb { + Value { + MinBufferLevel "512" + } +} + +SectionDevice."HDMI".0 { + Value { + JackName "RockchipHDMI HDMI Jack" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } +} diff --git a/ucm-config/veyron_fievel/RockchipHDMI/RockchipHDMI.conf b/ucm-config/veyron_fievel/RockchipHDMI/RockchipHDMI.conf new file mode 100644 index 00000000..a167d741 --- /dev/null +++ b/ucm-config/veyron_fievel/RockchipHDMI/RockchipHDMI.conf @@ -0,0 +1,6 @@ +Comment "Rockchip HDMI card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_fievel/VEYRON-I2S/HiFi.conf b/ucm-config/veyron_fievel/VEYRON-I2S/HiFi.conf new file mode 100644 index 00000000..f23f3bc4 --- /dev/null +++ b/ucm-config/veyron_fievel/VEYRON-I2S/HiFi.conf @@ -0,0 +1,120 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + cset "name='Speaker Switch' off" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + OutputDspName "" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='HP Left Out Switch' on" + cset "name='HP Right Out Switch' on" + cset "name='Headphone Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} + +SectionDevice."HDMI".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,1" + JackName "VEYRON-I2S HDMI Jack" + JackType "gpio" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + ] +} diff --git a/ucm-config/veyron_fievel/VEYRON-I2S/VEYRON-I2S.conf b/ucm-config/veyron_fievel/VEYRON-I2S/VEYRON-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_fievel/VEYRON-I2S/VEYRON-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_jaq/ROCKCHIP-I2S/HiFi.conf b/ucm-config/veyron_jaq/ROCKCHIP-I2S/HiFi.conf new file mode 100644 index 00000000..8523a815 --- /dev/null +++ b/ucm-config/veyron_jaq/ROCKCHIP-I2S/HiFi.conf @@ -0,0 +1,142 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + + cset "name='Left Speaker Mixer Left DAC Switch' off" + cset "name='Right Speaker Mixer Right DAC Switch' off" + cset "name='Left Speaker Mixer Right DAC Switch' on" + cset "name='Right Speaker Mixer Left DAC Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + cset "name='Headphone Switch' on" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} diff --git a/ucm-config/veyron_jaq/ROCKCHIP-I2S/ROCKCHIP-I2S.conf b/ucm-config/veyron_jaq/ROCKCHIP-I2S/ROCKCHIP-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_jaq/ROCKCHIP-I2S/ROCKCHIP-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_jaq/RockchipHDMI/HiFi.conf b/ucm-config/veyron_jaq/RockchipHDMI/HiFi.conf new file mode 100644 index 00000000..bf76d6a6 --- /dev/null +++ b/ucm-config/veyron_jaq/RockchipHDMI/HiFi.conf @@ -0,0 +1,12 @@ +SectionVerb { + Value { + MinBufferLevel "512" + } +} + +SectionDevice."HDMI".0 { + Value { + JackName "RockchipHDMI HDMI Jack" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } +} diff --git a/ucm-config/veyron_jaq/RockchipHDMI/RockchipHDMI.conf b/ucm-config/veyron_jaq/RockchipHDMI/RockchipHDMI.conf new file mode 100644 index 00000000..a167d741 --- /dev/null +++ b/ucm-config/veyron_jaq/RockchipHDMI/RockchipHDMI.conf @@ -0,0 +1,6 @@ +Comment "Rockchip HDMI card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_jaq/VEYRON-I2S/HiFi.conf b/ucm-config/veyron_jaq/VEYRON-I2S/HiFi.conf new file mode 100644 index 00000000..2698529d --- /dev/null +++ b/ucm-config/veyron_jaq/VEYRON-I2S/HiFi.conf @@ -0,0 +1,158 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 11" + cset "name='ADCL Volume' 11" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + cset "name='Speaker Switch' off" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Switch' off" + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + OutputDspName "" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='HP Left Out Switch' on" + cset "name='HP Right Out Switch' on" + cset "name='Headphone Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} + +SectionDevice."HDMI".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,1" + JackName "VEYRON-I2S HDMI Jack" + JackType "gpio" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + ] +} diff --git a/ucm-config/veyron_jaq/VEYRON-I2S/VEYRON-I2S.conf b/ucm-config/veyron_jaq/VEYRON-I2S/VEYRON-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_jaq/VEYRON-I2S/VEYRON-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_minnie-kernelnext b/ucm-config/veyron_minnie-kernelnext new file mode 120000 index 00000000..5fea6bb7 --- /dev/null +++ b/ucm-config/veyron_minnie-kernelnext @@ -0,0 +1 @@ +veyron_minnie
\ No newline at end of file diff --git a/ucm-config/veyron_minnie/ROCKCHIP-I2S/HiFi.conf b/ucm-config/veyron_minnie/ROCKCHIP-I2S/HiFi.conf new file mode 100644 index 00000000..bcfe9157 --- /dev/null +++ b/ucm-config/veyron_minnie/ROCKCHIP-I2S/HiFi.conf @@ -0,0 +1,137 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 8" + cset "name='ADCL Volume' 8" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + cset "name='Headphone Switch' on" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} diff --git a/ucm-config/veyron_minnie/ROCKCHIP-I2S/ROCKCHIP-I2S.conf b/ucm-config/veyron_minnie/ROCKCHIP-I2S/ROCKCHIP-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_minnie/ROCKCHIP-I2S/ROCKCHIP-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_minnie/RockchipHDMI/HiFi.conf b/ucm-config/veyron_minnie/RockchipHDMI/HiFi.conf new file mode 100644 index 00000000..bf76d6a6 --- /dev/null +++ b/ucm-config/veyron_minnie/RockchipHDMI/HiFi.conf @@ -0,0 +1,12 @@ +SectionVerb { + Value { + MinBufferLevel "512" + } +} + +SectionDevice."HDMI".0 { + Value { + JackName "RockchipHDMI HDMI Jack" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } +} diff --git a/ucm-config/veyron_minnie/RockchipHDMI/RockchipHDMI.conf b/ucm-config/veyron_minnie/RockchipHDMI/RockchipHDMI.conf new file mode 100644 index 00000000..a167d741 --- /dev/null +++ b/ucm-config/veyron_minnie/RockchipHDMI/RockchipHDMI.conf @@ -0,0 +1,6 @@ +Comment "Rockchip HDMI card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_minnie/VEYRON-I2S/HiFi.conf b/ucm-config/veyron_minnie/VEYRON-I2S/HiFi.conf new file mode 100644 index 00000000..fd4e6a84 --- /dev/null +++ b/ucm-config/veyron_minnie/VEYRON-I2S/HiFi.conf @@ -0,0 +1,158 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 8" + cset "name='ADCL Volume' 8" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + cset "name='Speaker Switch' off" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Switch' off" + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + OutputDspName "" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='HP Left Out Switch' on" + cset "name='HP Right Out Switch' on" + cset "name='Headphone Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} + +SectionDevice."HDMI".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,1" + JackName "VEYRON-I2S HDMI Jack" + JackType "gpio" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + ] +} diff --git a/ucm-config/veyron_minnie/VEYRON-I2S/VEYRON-I2S.conf b/ucm-config/veyron_minnie/VEYRON-I2S/VEYRON-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_minnie/VEYRON-I2S/VEYRON-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_speedy/ROCKCHIP-I2S/HiFi.conf b/ucm-config/veyron_speedy/ROCKCHIP-I2S/HiFi.conf new file mode 100644 index 00000000..bcfe9157 --- /dev/null +++ b/ucm-config/veyron_speedy/ROCKCHIP-I2S/HiFi.conf @@ -0,0 +1,137 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 8" + cset "name='ADCL Volume' 8" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:ROCKCHIPI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + DspName "" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Speaker Switch' off" + cset "name='Headphone Switch' on" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headphone Left Switch' off" + cset "name='Headphone Right Switch' off" + cset "name='Headphone Switch' off" + cset "name='Speaker Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:ROCKCHIPI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "ROCKCHIP-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:ROCKCHIPI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} diff --git a/ucm-config/veyron_speedy/ROCKCHIP-I2S/ROCKCHIP-I2S.conf b/ucm-config/veyron_speedy/ROCKCHIP-I2S/ROCKCHIP-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_speedy/ROCKCHIP-I2S/ROCKCHIP-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_speedy/RockchipHDMI/HiFi.conf b/ucm-config/veyron_speedy/RockchipHDMI/HiFi.conf new file mode 100644 index 00000000..bf76d6a6 --- /dev/null +++ b/ucm-config/veyron_speedy/RockchipHDMI/HiFi.conf @@ -0,0 +1,12 @@ +SectionVerb { + Value { + MinBufferLevel "512" + } +} + +SectionDevice."HDMI".0 { + Value { + JackName "RockchipHDMI HDMI Jack" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } +} diff --git a/ucm-config/veyron_speedy/RockchipHDMI/RockchipHDMI.conf b/ucm-config/veyron_speedy/RockchipHDMI/RockchipHDMI.conf new file mode 100644 index 00000000..a167d741 --- /dev/null +++ b/ucm-config/veyron_speedy/RockchipHDMI/RockchipHDMI.conf @@ -0,0 +1,6 @@ +Comment "Rockchip HDMI card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/veyron_speedy/VEYRON-I2S/HiFi.conf b/ucm-config/veyron_speedy/VEYRON-I2S/HiFi.conf new file mode 100644 index 00000000..fd4e6a84 --- /dev/null +++ b/ucm-config/veyron_speedy/VEYRON-I2S/HiFi.conf @@ -0,0 +1,158 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + MinBufferLevel "512" + FullySpecifiedUCM "1" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Digital EQ 3 Band Switch' off" + cset "name='Digital EQ 5 Band Switch' off" + cset "name='Digital EQ 7 Band Switch' off" + cset "name='Biquad Switch' off" + cset "name='Filter Mode' Music" + cset "name='ADC Oversampling Rate' 0" + + cset "name='DMIC Mux' DMIC" + cset "name='MIC2 Mux' IN34" + cset "name='Right ADC Mixer MIC2 Switch' on" + cset "name='Left ADC Mixer MIC2 Switch' on" + cset "name='MIC2 Volume' 20" + cset "name='Headset Mic Switch' off" + cset "name='Int Mic Switch' on" + + cset "name='ADCR Boost Volume' 4" + cset "name='ADCL Boost Volume' 4" + cset "name='ADCR Volume' 8" + cset "name='ADCL Volume' 8" + + cset "name='Left Speaker Mixer Left DAC Switch' on" + cset "name='Right Speaker Mixer Right DAC Switch' on" + cset "name='Speaker Left Mixer Volume' 2" + cset "name='Speaker Right Mixer Volume' 2" + cset "name='Record Path DC Blocking' on" + cset "name='Playback Path DC Blocking' on" + + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + cset "name='Speaker Switch' off" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + cset "name='Headphone Left Switch' on" + cset "name='Headphone Right Switch' on" + ] + + DisableSequence [ + ] +} + +SectionDevice."Speaker".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Speaker" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Left Switch' on" + cset "name='Speaker Right Switch' on" + cset "name='Speaker Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Speaker Switch' off" + cset "name='Speaker Left Switch' off" + cset "name='Speaker Right Switch' off" + ] +} + +SectionDevice."Internal Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Int Mic" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + ] +} + +SectionDevice."Headphone".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,0" + MixerName "Headphone" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + OutputDspName "" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='HP Left Out Switch' on" + cset "name='HP Right Out Switch' on" + cset "name='Headphone Switch' on" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headphone Switch' off" + cset "name='HP Left Out Switch' off" + cset "name='HP Right Out Switch' off" + ] +} + +SectionDevice."Mic".0 { + Value { + CapturePCM "hw:VEYRONI2S,0" + MixerName "Headset Mic" + JackType "gpio" + JackName "VEYRON-I2S Headset Jack" + } + + EnableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Int Mic Switch' off" + cset "name='DMIC Mux' ADC" + cset "name='Headset Mic Switch' on" + cset "name='Record Path DC Blocking' on" + ] + + DisableSequence [ + cdev "hw:VEYRONI2S" + + cset "name='Headset Mic Switch' off" + cset "name='DMIC Mux' DMIC" + cset "name='Int Mic Switch' on" + cset "name='Record Path DC Blocking' off" + ] +} + +SectionDevice."HDMI".0 { + Value { + PlaybackPCM "hw:VEYRONI2S,1" + JackName "VEYRON-I2S HDMI Jack" + JackType "gpio" + EDIDFile "/sys/class/drm/card1-HDMI-A-1/edid" + } + EnableSequence [ + cdev "hw:VEYRONI2S" + ] + DisableSequence [ + cdev "hw:VEYRONI2S" + ] +} diff --git a/ucm-config/veyron_speedy/VEYRON-I2S/VEYRON-I2S.conf b/ucm-config/veyron_speedy/VEYRON-I2S/VEYRON-I2S.conf new file mode 100644 index 00000000..0c399b0d --- /dev/null +++ b/ucm-config/veyron_speedy/VEYRON-I2S/VEYRON-I2S.conf @@ -0,0 +1,6 @@ +Comment "Rockchip card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/wolf/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/wolf/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..8c8d57ed --- /dev/null +++ b/ucm-config/wolf/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Wolf internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/wolf/HDA Intel PCH/HiFi.conf b/ucm-config/wolf/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..03f431e5 --- /dev/null +++ b/ucm-config/wolf/HDA Intel PCH/HiFi.conf @@ -0,0 +1,55 @@ +SectionVerb { + Value { + OutputDspName "speaker_eq" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Master Playback Switch' on" + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + + cset "name='Capture Switch' on" + cset "name='Capture Volume' 39" + cset "name='Mic Boost Volume' 2" + cset "name='Internal Mic Boost Volume' 0" + cset "name='Capture Source' 0" + ] + DisableSequence [ + ] +} + +SectionDevice."Headphone".0 { + Value { + JackName "Headphone Jack" + DspName "" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Speaker Playback Switch' off" + cset "name='Headphone Playback Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Headphone Playback Switch' off" + cset "name='Speaker Playback Switch' on" + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 1" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Source' 0" + ] +} diff --git a/ucm-config/zako/HDA Intel PCH/HDA Intel PCH.conf b/ucm-config/zako/HDA Intel PCH/HDA Intel PCH.conf new file mode 100644 index 00000000..81234e11 --- /dev/null +++ b/ucm-config/zako/HDA Intel PCH/HDA Intel PCH.conf @@ -0,0 +1,6 @@ +Comment "Zako internal card" + +SectionUseCase."HiFi" { + File "HiFi.conf" + Comment "Default" +} diff --git a/ucm-config/zako/HDA Intel PCH/HiFi.conf b/ucm-config/zako/HDA Intel PCH/HiFi.conf new file mode 100644 index 00000000..5e280c25 --- /dev/null +++ b/ucm-config/zako/HDA Intel PCH/HiFi.conf @@ -0,0 +1,32 @@ +SectionVerb { + Value { + NoCreateDefaultOutputNode "1" + NoCreateDefaultInputNode "1" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + cset "name='Capture Volume' 23" + cset "name='Master Playback Switch' on" + cset "name='Master Playback Volume' 87" + ] + DisableSequence [ + ] +} + +SectionDevice."Mic".0 { + Value { + JackName "Mic Jack" + } + EnableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' on" + ] + DisableSequence [ + cdev "hw:PCH" + + cset "name='Capture Switch' off" + ] +} diff --git a/unblocked_terms.txt b/unblocked_terms.txt deleted file mode 100644 index cba7545a..00000000 --- a/unblocked_terms.txt +++ /dev/null @@ -1,10 +0,0 @@ -# KEEP THIS COMMENT IN YOUR COPY. -# -# Don't delete this file if you want to keep keyword_check enabled even if it's -# empty. -# -# See repohooks/README.md for more details. - -master -\bnative -white.?list |