GPIOは誰の手に?
G-clusterでは、Linux側でボタンはGPIO9に、LEDはGPIO2にマウントされています。
しかし、
code: root shell
DSM232:/proc # cat /dev/gpio2
cat: can't open '/dev/gpio2': Device or resource busy
DSM232:/proc # cat /dev/gpio9
cat: can't open '/dev/gpio9': Device or resource busy
こんな感じで、リソースが使えません。。
procで調べても、こんな感じ。。
code: root shell
DSM232:/proc # cat /proc/gpio
==> GPIOa 0 is free.
==> GPIOa 1 is free.
==> GPIOa 2 is held by other component.
==> GPIOa 3 is free.
==> GPIOa 4 is free.
==> GPIOa 5 is free.
==> GPIOa 6 is free.
==> GPIOa 7 is free.
==> GPIOa 8 is free.
==> GPIOa 9 is held by other component.
==> GPIOa 10 is free.
==> GPIOa 11 is free.
==> GPIOa 12 is free.
==> GPIOa 13 is free.
リソースを誰が持っているのか見ていきましょう!
lsofなどの便利コマンドは当然用意されていないので、procfsを覗いていきます
code: root shell
DSM232:/etc # ls -la /proc/*/fd | grep -C 10 'gpio9'
lr-x------ 1 root root 64 Jan 1 09:05 10 -> /dlink/remote/remote.sh
lrwx------ 1 root root 64 Jan 1 09:05 2 -> /dev/console
/proc/238/fd:
total 0
dr-x------ 2 root root 0 Jan 1 09:05 .
dr-xr-xr-x 6 root root 0 Jan 1 09:00 ..
lr-x------ 1 root root 64 Jan 1 09:05 0 -> /dev/null
lrwx------ 1 root root 64 Jan 1 09:05 1 -> /dev/console
lrwx------ 1 root root 64 Jan 1 09:05 10 -> /dev/gpio2
lrwx------ 1 root root 64 Jan 1 09:05 11 -> /dev/gpio9
lrwx------ 1 root root 64 Jan 1 09:05 12 -> socket:1639 lr-x------ 1 root root 64 Jan 1 09:05 13 -> /dlink/remote/mp3/10_medium.mp3
lrwx------ 1 root root 64 Jan 1 09:05 14 -> /dev/fb0
lr-x------ 1 root root 64 Jan 1 09:05 15 -> /dev/tty0
lrwx------ 1 root root 64 Jan 1 09:05 16 -> /dev/tty2
lr-x------ 1 root root 64 Jan 1 09:05 17 -> pipe:1646 l-wx------ 1 root root 64 Jan 1 09:05 18 -> pipe:1646 lrwx------ 1 root root 64 Jan 1 09:05 2 -> /dev/console
lrwx------ 1 root root 64 Jan 1 09:05 21 -> socket:1647 lrwx------ 1 root root 64 Jan 1 09:05 3 -> socket:1632 ということで、238番のプロセスが持っているようなので(プロセスIDは毎回変わります)
code: root shell
DSM232:/proc/238 # echo $(cat /proc/238/cmdline)
/dlink/remote/dsm232 wlan0 sta 0
ということで、どうやらdsm232が使っているようです。
dsm232はソースコードが公開されてないbinary blobなのでそのまま、とりあえずkill -9してみると、勝手に再起動してしまうようです。。
どうやらこいつが勝手に立ち上げてるっぽい
code: root shell
DSM232:/dlink/remote # cat remote.sh
PARAM="0"
while true
do
/dlink/remote/dsm232 wlan0 sta $PARAM
rm -f /var/run/dsm232.pid
killall http_caller;killall caller.sh;killall gcclient;killall hls_client
PARAM="1"
done
すると、うまく殺せました。
これで、gpio9を正しく見ることができるようになりました。
code: root shell
DSM232:/dlink/remote # echo $(cat /dev/gpio9 | head -c 1)
0
DSM232:/dlink/remote # echo $(cat /dev/gpio9 | head -c 1)
1
これで、ボタンのステートを取ってこれるようになりました。
0で押している、1で押していないを表しています。
code: root shell
DSM232:/dlink/remote # echo -n 1 > /dev/gpio2
DSM232:/dlink/remote # echo -n 0 > /dev/gpio2
また、これで基板のLEDを制御できます。
1で点灯、0で消灯です。
ちなみに、この状態だとremotectl_pipeが死んでいるので、これらの方法でのLED情報取得が不可能になります
code:root shell
DSM232:/root $ echo "led 0" > /cavium/remotectl_pipe # led消灯
DSM232:/root $ echo "led 1" > /cavium/remotectl_pipe # led点灯
DSM232:/root $ echo "led 200" > /cavium/remotectl_pipe # 0.2秒間隔(?)でled点滅
DSM232:/root $ echo "gc_warning hogehoge\naaaaaaaaa" > /cavium/remotectl_pipe # TV画面にメッセージを表示
remotectlは、自分の解析の結果こんな感じです。
なんか起動処理も全てこれでしているっぽいので、切り離すにはちゃんとバイナリ解析する必要がありそう。。
code:remotectl_main.c
undefined4 main(int argc,int argv)
{
int run_mode;
undefined4 uVar1;
if (argc < 2) {
puts("para1 eth? needed ");
/* WARNING: Subroutine does not return */
exit(0);
}
save_and_print_gcluster_pid();
puts("##########################################################");
printf(" %s , GUI Build Date :%s ,%s\n","v1.02.09","Aug 12 2013","18:59:20");
puts("##########################################################");
read_tv_resolution();
FUN_0000ac30();
if ((2 < argc) && (run_mode = strcmp(*(char **)(argv + 8),"sta"), run_mode == 0)) {
puts(" [] avoid auto recover to softap !!");
DAT_0006f89c = 1;
}
uVar1 = get_version_string();
printf("~ver %s\n",uVar1);
puts("~dsm232 start");
strcpy(PTR_s_wlan0_0006b418,*(char **)(argv + 4));
FUN_0002b8d0();
FUN_0002be70();
init_env();
FUN_0000a8ec();
create_event_queue();
open_remote_control_pipe();
FUN_0002d2d4();
send_param_to_remote_control_pipe(&LAB_0001fecc);
send_param_to_remote_control_pipe(FUN_000205b0);
send_param_to_remote_control_pipe(&LAB_0002c304);
send_param_to_remote_control_pipe(FUN_000267e0);
send_param_to_remote_control_pipe(FUN_00026b90);
set_dsm_mode();
init_direct_fb(0,0);
draw_fastboot_screen();
if ((3 < argc) && (run_mode = strcmp(*(char **)(argv + 0xc),"1"), run_mode == 0)) {
FUN_000279f0("FIRST_BOOT",local_1c);
exec_shell("echo http_caller > /cavium/remotectl_pipe");
}
else {
exec_shell("echo firstboot 10 > /cavium/remotectl_pipe");
}
}
FUN_0003be14();
FUN_0003bdbc();
FUN_0000b404(*(undefined4 *)(DAT_0006e738 + 0x198));
FUN_0000b178(DAT_0006e738);
DAT_0006e738 = 0;
FUN_0000b2f0();
FUN_0002faf0();
puts("~dsm232 end");
return 0;
}