Skip to content

Commit 447b613

Browse files
committed
Add a kernel module to sync S/PDIF volume
1 parent 1e998ea commit 447b613

File tree

7 files changed

+2502
-0
lines changed

7 files changed

+2502
-0
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
[submodule "third_party/procyon"]
1111
path = third_party/procyon
1212
url = https://github.com/yath/procyon-mirror.git
13+
[submodule "third_party/linux"]
14+
path = third_party/linux
15+
url = https://github.com/yath/mediatek-linux-3.10

Kbuild

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ccflags-y := -std=gnu99 -Wno-declaration-after-statement
2+
obj-m := audiosync.o

Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ TARGET_CFLAGS = $(CFLAGS) -mcpu=cortex-a17 -mfpu=neon
1717

1818
CROSS := arm-none-eabi-
1919

20+
# https://launchpad.net/linaro-toolchain-binaries/trunk/2013.10/+download/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
21+
LINUX_CROSS := $$PWD/third_party/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-
22+
2023
INSTALL_DIR := /data/local/tmp
2124
INSTALL_TARGETS := loader patcher patcher-payload.so cli decrap
2225

@@ -54,6 +57,14 @@ kernelutil: kernelutil.go
5457
decrypt: decrypt.c
5558
$(CC) $(CFLAGS) -o $@ $< -lcrypto
5659

60+
## kernel modules
61+
third_party/linux.stamp:
62+
+$(MAKE) -C third_party LINUX_CROSS=$(LINUX_CROSS) linux.stamp
63+
64+
.PHONY: *.ko
65+
*.ko: third_party/linux.stamp
66+
$(MAKE) -C third_party/linux ARCH=arm CROSS_COMPILE=$(LINUX_CROSS) M=$$PWD $@
67+
5768
## debugging stuff
5869

5970
# _Cust_dump_all_thread (b.da)

audiosync.c

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <linux/module.h>
2+
#include <linux/kernel.h>
3+
#include <linux/slab.h>
4+
#include <linux/kallsyms.h>
5+
6+
#define DEBUG(fmt, args...) printk(KERN_INFO KBUILD_MODNAME ": "fmt"\n", ##args)
7+
8+
#define ASSERT(condition) do { \
9+
if (!(condition)) { \
10+
WARN(true, "Assertion \""#condition"\" failed"); \
11+
return -EINVAL; \
12+
} \
13+
} while(0)
14+
15+
typedef unsigned long word;
16+
17+
#define FAR_JMP 0xe51ff004 // ldr pc, [pc, #-4]
18+
19+
enum {
20+
TI_BRANCH_HOOK_1 = 0, // FAR_JMP
21+
TI_BRANCH_HOOK_2, // addr of hook
22+
TI_ORIG_INSN_1, // overwritten first word of f
23+
TI_ORIG_INSN_2, // overwritten second word of f
24+
TI_CALL_ORIG_1, // FAR_JMP
25+
TI_CALL_ORIG_2, // addr of f+8
26+
TI_CALL_MAX,
27+
} trampoline_instruction_t;
28+
29+
static void hook_fun(word *f, void *hook, word **orig_fun) {
30+
word *trampoline = kcalloc(TI_CALL_MAX, sizeof(word), GFP_KERNEL);
31+
32+
trampoline[TI_BRANCH_HOOK_1] = FAR_JMP;
33+
trampoline[TI_BRANCH_HOOK_2] = (word)hook;
34+
trampoline[TI_ORIG_INSN_1] = f[0];
35+
trampoline[TI_ORIG_INSN_2] = f[1];
36+
trampoline[TI_CALL_ORIG_1] = FAR_JMP;
37+
trampoline[TI_CALL_ORIG_2] = (word)&f[2];
38+
39+
*orig_fun = &trampoline[TI_ORIG_INSN_1];
40+
41+
f[0] = FAR_JMP;
42+
f[1] = (word)trampoline;
43+
44+
DEBUG("hook_fun(f=%pS (%px), hook=%pS (%px)), trampoline is at %px", f, f, hook, hook, trampoline);
45+
46+
for (int i = 0; i < TI_CALL_MAX; i++)
47+
DEBUG(" trampoline[%d] = %lx", i, trampoline[i]);
48+
for (int i = 0; i < 2; i++)
49+
DEBUG(" set f[%d]: %lx", i, f[i]);
50+
}
51+
52+
static int restore_fun(word **orig_fun) {
53+
word *trampoline = *orig_fun - TI_ORIG_INSN_1;
54+
ASSERT(trampoline[TI_BRANCH_HOOK_1] == FAR_JMP);
55+
ASSERT(trampoline[TI_CALL_ORIG_1] == FAR_JMP);
56+
57+
word *f = ((word **)trampoline)[TI_CALL_ORIG_2] - 2;
58+
DEBUG("restore_fun(orig_fun=%pS (%px)), trampoline is at %px, f=%pS (%px)", orig_fun, orig_fun, trampoline, f, f);
59+
60+
ASSERT(f[0] == FAR_JMP);
61+
ASSERT(f[1] == (word)trampoline);
62+
63+
f[0] = trampoline[TI_ORIG_INSN_1];
64+
f[1] = trampoline[TI_ORIG_INSN_2];
65+
66+
for (int i = 0; i < 2; i++)
67+
DEBUG(" reset f[%d]: %lx", i, f[i]);
68+
69+
kfree(trampoline);
70+
*orig_fun = NULL;
71+
72+
return 0;
73+
}
74+
75+
int (*orig_MTAUD_SetChannelVolume)(int, int, int) = NULL;
76+
77+
int my_MTAUD_SetChannelVolume(int decoder, int channel, int value) {
78+
DEBUG("my_MTAUD_SetChannelVolume(%d, %d, %d)", decoder, channel, value);
79+
80+
if (channel == 0 || channel == 21) {
81+
int ret = orig_MTAUD_SetChannelVolume(0, 6, value);
82+
DEBUG(" also set channel 6, rc=%d", ret);
83+
} else if (channel == 1 || channel == 22) {
84+
int ret = orig_MTAUD_SetChannelVolume(0, 7, value);
85+
DEBUG(" also set channel 7, rc=%d", ret);
86+
}
87+
88+
return orig_MTAUD_SetChannelVolume(decoder, channel, value);
89+
}
90+
91+
int init_module(void) {
92+
word *p = (word *)kallsyms_lookup_name("_MTAUD_SetChannelVolume");
93+
if (!p) {
94+
printk(KERN_ERR "can't find symbol\n");
95+
return -ENOENT;
96+
}
97+
98+
hook_fun((word *)p, my_MTAUD_SetChannelVolume, (word **)&orig_MTAUD_SetChannelVolume);
99+
DEBUG("loaded.");
100+
return 0;
101+
}
102+
103+
void cleanup_module(void) {
104+
restore_fun((word **)&orig_MTAUD_SetChannelVolume);
105+
DEBUG("unloaded.");
106+
}
107+
108+
MODULE_LICENSE("GPL");

third_party/Makefile

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ clean:
1515
cd dex2jar && rm -f *.sh && rm -rf out && $(GRADLE4) clean && rm -rf .gradle
1616
cd procyon && rm -f procyon-decompiler.jar && $(GRADLE4) clean && rm -rf .gradle
1717
cd vdexExtractor && ./make.sh clean
18+
rm -f linux.stamp && cd linux && make distclean
1819

1920
apktool/apktool.jar:
2021
cd apktool && \
@@ -35,3 +36,12 @@ procyon/procyon-decompiler.jar:
3536

3637
vdexExtractor/bin/vdexExtractor:
3738
cd vdexExtractor && ./make.sh
39+
40+
linux.stamp:
41+
ifndef LINUX_CROSS
42+
$(error set LINUX_CROSS to cross compiler prefix)
43+
endif
44+
sed -i -e 's/^ *YYLTYPE yylloc;/extern &/' linux/scripts/dtc/dtc-lexer.*
45+
cp config-linux-3.10.79 linux/.config
46+
+cd linux && $(MAKE) ARCH=arm CROSS_COMPILE=$(LINUX_CROSS) oldconfig modules
47+
touch linux.stamp

0 commit comments

Comments
 (0)