$ input keyevent 21
I made a conf file with some keys I needed:
$ cat androidKeys.sh KEY_LEFT=21 KEY_RIGHT=22 KEY_UP=19 KEY_DOWN=20 KEY_BACK=4 KEY_ENTER=66 KEY_MENU=3 KEY_VOLUME_UP=24 KEY_VOLUME_DOWN=25 KEY_VOLUME_MUTE=164
And created a script to easily send commands:
$ cat send.sh #!/usr/bin/env bash source ./androidKeys.sh HOST_IP=$1 EVENT_KEY=$2 KEY_CODE=$(eval "echo \$${EVENT_KEY}") ssh $HOST_IP "input keyevent ${KEY_CODE}"
Noticed the eval "echo \$${EVENT_KEY}"? It lets you obtain a variable's value by using the content of another variable to indicate the name of the first variable. So, the $EVENT_KEY may contain 'KEY_LEFT', which when passed to eval is evaluated as "echo $KEY_LEFT" , giving us the value of $KEY_LEFT.
Then I did:
$ ./send.sh 10.0.0.123 KEY_LEFT
And the cursor moved to the left. This is better, I thought, but it could be even better. I could be using the directional keys on my keyboard.
But it is not a simple task, the following has to possible:
1) obtain the key pressed
2) convert into a numerical representation
3) translate that representation into our KEY_* codes
4) invoke send.sh, passing the host IP and the key code
For the first task, an stty/dd combo comes to rescue. We use stty in raw mode, and capture three bytes of input with dd (bs=3). This will allow us to capture single and multi byte keys.
Then we parse this string (ord function below), by iterating over it and converting each character to a number by printfing it as integer.
Finally, we pass the numerical sequence returned by ord to another charCodeTokey function which translates to our known KEY_* codes.
$ cat auto.sh #!/usr/bin/env bash HOST_IP=$1 function charCodeToKey () { CHAR_CODE=($@) CHAR_STRING="${CHAR_CODE[@]}" [ "$CHAR_STRING" = "27 91 68" ] && echo 'KEY_LEFT' [ "$CHAR_STRING" = "27 91 67" ] && echo 'KEY_RIGHT' [ "$CHAR_STRING" = "27 91 65" ] && echo 'KEY_UP' [ "$CHAR_STRING" = "27 91 66" ] && echo 'KEY_DOWN' [ "$CHAR_STRING" = "127" ] && echo 'KEY_BACK' [ "$CHAR_STRING" = "13" ] && echo 'KEY_ENTER' [ "$CHAR_STRING" = "27 79 72" ] && echo 'KEY_MENU' [ "$CHAR_STRING" = "43" ] && echo 'KEY_VOLUME_UP' [ "$CHAR_STRING" = "45" ] && echo 'KEY_VOLUME_DOWN' } function ord() { str="$@" strLen=${#str} for i in $(seq 0 $(($strLen - 1))) do c=${str:$i:1} printf '%d ' "'$c" done } while : do old_tty_settings=$(stty -g) stty raw -echo DATA=$(dd bs=3 count=1 2>/dev/null) stty "$old_tty_settings" CHARS=$(ord $DATA) if [ "${CHARS}" = "3 " ] then exit fi KEY_EVENT=$(charCodeToKey "$CHARS") if [ "$KEY_EVENT" != "" ] then echo $KEY_EVENT ./send.sh $HOST_IP $KEY_EVENT else echo "Unsupported key" fi done
One caveat of using stty's this way is that after starting the infinite while loop, it is impossible to stop. This is because stty captures the ^C command, and translates it too. So we need to check for it (the if [ "${CHARS}" = "3 " ].. exit above), and exit the script. Also, we must save the terminal settings ( old_tty_settings=$(stty -g) ) and put it back ( stty "$old_tty_settings" ), otherwise the terminal will be unusable after we exit the script.
So now I can control all my applications on the TV through my shell, no more remotes :)
Well, maybe not all applications yet. These scripts will need more key codes... and mouse support.
No comments:
Post a Comment