요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
============================
ALSA Jack Software Injection
============================
Simple Introduction On Jack Injection
=====================================
Here jack injection means users could inject plugin or plugout events
to the audio jacks through debugfs interface, it is helpful to
validate ALSA userspace changes. For example, we change the audio
profile switching code in the pulseaudio, and we want to verify if the
change works as expected and if the change introduce the regression,
in this case, we could inject plugin or plugout events to an audio
jack or to some audio jacks, we don't need to physically access the
machine and plug/unplug physical devices to the audio jack.
In this design, an audio jack doesn't equal to a physical audio jack.
Sometimes a physical audio jack contains multi functions, and the
ALSA driver creates multi ``jack_kctl`` for a ``snd_jack``, here the
``snd_jack`` represents a physical audio jack and the ``jack_kctl``
represents a function, for example a physical jack has two functions:
headphone and mic_in, the ALSA ASoC driver will build 2 ``jack_kctl``
for this jack. The jack injection is implemented based on the
``jack_kctl`` instead of ``snd_jack``.
To inject events to audio jacks, we need to enable the jack injection
via ``sw_inject_enable`` first, once it is enabled, this jack will not
change the state by hardware events anymore, we could inject plugin or
plugout events via ``jackin_inject`` and check the jack state via
``status``, after we finish our test, we need to disable the jack
injection via ``sw_inject_enable`` too, once it is disabled, the jack
state will be restored according to the last reported hardware events
and will change by future hardware events.
The Layout of Jack Injection Interface
======================================
If users enable the SND_JACK_INJECTION_DEBUG in the kernel, the audio
jack injection interface will be created as below:
::
$debugfs_mount_dir/sound
|-- card0
|-- |-- HDMI_DP_pcm_10_Jack
|-- |-- |-- jackin_inject
|-- |-- |-- kctl_id
|-- |-- |-- mask_bits
|-- |-- |-- status
|-- |-- |-- sw_inject_enable
|-- |-- |-- type
...
|-- |-- HDMI_DP_pcm_9_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
|-- card1
|-- HDMI_DP_pcm_5_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
...
|-- Headphone_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
|-- Headset_Mic_Jack
|-- jackin_inject
|-- kctl_id
|-- mask_bits
|-- status
|-- sw_inject_enable
|-- type
The Explanation Of The Nodes
======================================
kctl_id
read-only, get jack_kctl->kctl's id
::
sound/card1/Headphone_Jack# cat kctl_id
Headphone Jack
mask_bits
read-only, get jack_kctl's supported events mask_bits
::
sound/card1/Headphone_Jack# cat mask_bits
0x0001 HEADPHONE(0x0001)
status
read-only, get jack_kctl's current status
- headphone unplugged:
::
sound/card1/Headphone_Jack# cat status
Unplugged
- headphone plugged:
::
sound/card1/Headphone_Jack# cat status
Plugged
type
read-only, get snd_jack's supported events from type (all supported events on the physical audio jack)
::
sound/card1/Headphone_Jack# cat type
0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
sw_inject_enable
read-write, enable or disable injection
- injection disabled:
::
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 0
- injection enabled:
::
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 1
- to enable jack injection:
::
sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
- to disable jack injection:
::
sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
jackin_inject
write-only, inject plugin or plugout
- to inject plugin:
::
sound/card1/Headphone_Jack# echo 1 > jackin_inject
- to inject plugout:
::
sound/card1/Headphone_Jack# echo 0 > jackin_inject
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Software jack event 주입
1-34Jack injection은 사용자가 debugfs interface를 통해 audio jack에 plug-in 또는 plug-out event를 주입하는 기능이다. PulseAudio의 audio profile 전환 code 변경을 검증하거나 regression을 확인할 때 장치에 물리적으로 접근해 실제 plug를 꽂고 뺄 필요가 없다. 하나 또는 여러 audio jack에 event를 주입할 수 있다.
여기서 audio jack은 반드시 물리 jack 하나와 같지 않다. 하나의 물리 jack이 headphone과 `mic_in`처럼 여러 기능을 가지면 ALSA ASoC driver는 하나의 `snd_jack`에 여러 `jack_kctl`을 만든다. `snd_jack`은 물리 jack, 각 `jack_kctl`은 개별 기능을 나타내며 injection은 `snd_jack`이 아니라 `jack_kctl`을 기준으로 구현한다.
Event를 주입하려면 먼저 `sw_inject_enable`로 injection을 켠다. 켜진 동안 해당 jack 상태는 hardware event로 바뀌지 않고 `jackin_inject`로 plug-in/plug-out을 주입하며 `status`로 확인한다. 시험 후 `sw_inject_enable`을 끄면 마지막 hardware event에 따라 상태를 복원하고 이후 hardware event를 다시 따른다.
Software override를 켠 동안 hardware event 대신 debugfs 값을 사용한다.
============================
ALSA Jack Software Injection
============================
Simple Introduction On Jack Injection
=====================================
Here jack injection means users could inject plugin or plugout events
to the audio jacks through debugfs interface, it is helpful to
validate ALSA userspace changes. For example, we change the audio
profile switching code in the pulseaudio, and we want to verify if the
change works as expected and if the change introduce the regression,
in this case, we could inject plugin or plugout events to an audio
jack or to some audio jacks, we don't need to physically access the
machine and plug/unplug physical devices to the audio jack.
In this design, an audio jack doesn't equal to a physical audio jack.
Sometimes a physical audio jack contains multi functions, and the
ALSA driver creates multi ``jack_kctl`` for a ``snd_jack``, here the
``snd_jack`` represents a physical audio jack and the ``jack_kctl``
represents a function, for example a physical jack has two functions:
headphone and mic_in, the ALSA ASoC driver will build 2 ``jack_kctl``
for this jack. The jack injection is implemented based on the
``jack_kctl`` instead of ``snd_jack``.
To inject events to audio jacks, we need to enable the jack injection
via ``sw_inject_enable`` first, once it is enabled, this jack will not
change the state by hardware events anymore, we could inject plugin or
plugout events via ``jackin_inject`` and check the jack state via
``status``, after we finish our test, we need to disable the jack
injection via ``sw_inject_enable`` too, once it is disabled, the jack
state will be restored according to the last reported hardware events
and will change by future hardware events.
Debugfs interface 계층
35-82Kernel에서 `SND_JACK_INJECTION_DEBUG`를 켜면 `$debugfs_mount_dir/sound` 아래 card별·jack별 directory가 생긴다. 각 jack directory에는 `jackin_inject`, `kctl_id`, `mask_bits`, `status`, `sw_inject_enable`, `type` 여섯 node가 있다.
원문의 ASCII directory tree를 card→jack→node 계층으로 재구성했다.
The Layout of Jack Injection Interface
======================================
If users enable the SND_JACK_INJECTION_DEBUG in the kernel, the audio
jack injection interface will be created as below:
::
$debugfs_mount_dir/sound
|-- card0
|-- |-- HDMI_DP_pcm_10_Jack
|-- |-- |-- jackin_inject
|-- |-- |-- kctl_id
|-- |-- |-- mask_bits
|-- |-- |-- status
|-- |-- |-- sw_inject_enable
|-- |-- |-- type
...
|-- |-- HDMI_DP_pcm_9_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
|-- card1
|-- HDMI_DP_pcm_5_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
...
|-- Headphone_Jack
|-- |-- jackin_inject
|-- |-- kctl_id
|-- |-- mask_bits
|-- |-- status
|-- |-- sw_inject_enable
|-- |-- type
|-- Headset_Mic_Jack
|-- jackin_inject
|-- kctl_id
|-- mask_bits
|-- status
|-- sw_inject_enable
|-- type
kctl_id·mask_bits·status·type
83-123`kctl_id`는 read-only이며 `jack_kctl->kctl`의 ID를 반환한다. `mask_bits`도 read-only이며 `jack_kctl`이 지원하는 event mask를 반환한다. 예에서는 headphone event bit `0x0001`을 보여준다.
sound/card1/Headphone_Jack# cat kctl_id
Headphone Jack
sound/card1/Headphone_Jack# cat mask_bits
0x0001 HEADPHONE(0x0001)
`status`는 read-only current state로 unplugged면 `Unplugged`, plugged면 `Plugged`를 반환한다.
sound/card1/Headphone_Jack# cat status
Unplugged
sound/card1/Headphone_Jack# cat status
Plugged
`type`은 물리 audio jack 전체에서 `snd_jack`이 지원하는 모든 event를 read-only로 반환한다. 예에는 HEADPHONE, MICROPHONE과 BTN_0~BTN_3 bit가 포함된다.
sound/card1/Headphone_Jack# cat type
0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
기능별 kcontrol과 물리 jack 전체 정보를 구분한다.
The Explanation Of The Nodes
======================================
kctl_id
read-only, get jack_kctl->kctl's id
::
sound/card1/Headphone_Jack# cat kctl_id
Headphone Jack
mask_bits
read-only, get jack_kctl's supported events mask_bits
::
sound/card1/Headphone_Jack# cat mask_bits
0x0001 HEADPHONE(0x0001)
status
read-only, get jack_kctl's current status
- headphone unplugged:
::
sound/card1/Headphone_Jack# cat status
Unplugged
- headphone plugged:
::
sound/card1/Headphone_Jack# cat status
Plugged
type
read-only, get snd_jack's supported events from type (all supported events on the physical audio jack)
::
sound/card1/Headphone_Jack# cat type
0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
sw_inject_enable
124-152`sw_inject_enable`은 injection을 enable/disable하는 read-write node다. 읽으면 jack 이름과 `Inject Enabled: 0` 또는 `1`을 반환한다. `1`을 쓰면 software injection을 켜고 `0`을 쓰면 끈다.
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 0
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 1
sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
쓰기 값과 jack 상태 source의 관계다.
sw_inject_enable
read-write, enable or disable injection
- injection disabled:
::
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 0
- injection enabled:
::
sound/card1/Headphone_Jack# cat sw_inject_enable
Jack: Headphone Jack Inject Enabled: 1
- to enable jack injection:
::
sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
- to disable jack injection:
::
sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
jackin_inject
153-166`jackin_inject`는 plug-in 또는 plug-out을 주입하는 write-only node다. 값 `1`은 plug-in, `0`은 plug-out event를 뜻한다. 먼저 `sw_inject_enable`을 켠 상태에서 사용해야 한다.
sound/card1/Headphone_Jack# echo 1 > jackin_inject
sound/card1/Headphone_Jack# echo 0 > jackin_inject
Write-only 값이 생성하는 jack event다.
jackin_inject
write-only, inject plugin or plugout
- to inject plugin:
::
sound/card1/Headphone_Jack# echo 1 > jackin_inject
- to inject plugout:
::
sound/card1/Headphone_Jack# echo 0 > jackin_inject
요약·해설
jack-injection.rst:1-166SND_JACK_INJECTION_DEBUG의 debugfs 계층과 sw_inject_enable·jackin_inject를 이용해 plug event를 시험하는 방법을 설명합니다.