You are not logged in.

#1 2006-08-28 17:47:37

Neuro
Member
From: Poland
Registered: 2005-10-12
Posts: 352

Hotkey handling through acpi_fake.c program [kind of SOLVED]

Hi,

Got an Asus A6JC laptop here. asus_acpi is working perfectly, i can handle ACPI hotkey events through special scripts, no problem in that.

However, I'd like to make the ACPI hotkeys act like normal keyboard keys (like XF86AudioMute or XF86AudioVolumeRaise). Much like this guy here, and these guys.
The program acpi_keyfake.c can be found in this Ubuntu source acpi-support

It's all a simple program written in C, that outputs the desired key code to /dev/input/event*. It definately works since doing

./acpi_fakekey 18

it returns a nice letter "e" to Xorg (prints it in konsole and returns as an event in xev).

However, nothing happens if i do

./acpi_fakekey 160

which is a XF86AudioMute key. Despite declaring the keyboard in xorg.conf as:

Section "InputDevice"
    Identifier  "Keyboard1"
    Driver      "kbd"
    Option "AutoRepeat" "500 30"
    Option "XkbRules" "xorg"
    Option "XkbModel" "hp5185"
    Option "XkbLayout" "pl"
EndSection

. Please note that 160 is specified in hp5185 modemap.
I even went as far as declaring my own mode changes using xmodmap. This resulted in completly nothing. xev didn't report it.

Anyone has any tips on what to do, why it doesn't work? Any suggestions on what I might be doing wrong? Its a nice script, and it works in ubuntu (my friend checked it) and (appearently) it works in gentoo. So why doesn't it work in Arch?

Offline

#2 2006-08-29 12:14:13

Neuro
Member
From: Poland
Registered: 2005-10-12
Posts: 352

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Alright, so I've kind of solved the problem.

It appears that X keycodes are something way different than linux keycodes.
For example doing ./acpi_fakekey 32 shows up in xev as

KeyPress event, serial 31, synthetic NO, window 0x2800001,
    root 0x135, subw 0x0, time 1506877459, (-874,613), root:(176,638),
    state 0x0, keycode 40 (keysym 0x64, d), same_screen YES,
    XLookupString gives 1 bytes: (64) "d"
    XmbLookupString gives 1 bytes: (64) "d"
    XFilterEvent returns: False

So basically when you provide a value to acpi_fakekey, it's a linux keycode (see dumpkeys). In the 'd' example, the linux keycodce is 32 and Xorg keycode is 40 (see xmodmap -pke).

So basically what you need to do, is find out the mapping. As I knew that I'm looking for XF86AudioMute, XF86AudioPlay etc. Xorg keys I thought that it's better to just "press" all linux keycodes and see what happens smile

I wrote a little script (needs to run as root):

#!/bin/bash
xev  &
for i in `seq $1 $2`; do
    if (($i == 99)); then continue; fi # printscreen key, causes xev to unfocus
    echo "!!! key $i" >&2
    /etc/acpi/acpi_fakekey $i
    sleep 1
done;
killall xev

This will print out the currently "presseys ked" key and the resulting (if it works) Xorg event. I don't really know why linux keycode to xorg keycode mapping can't be straight, but hey, it works! wink

And finally I am able to turn the acpi events I get from pressing the keyboard keys into proper Xorg keys.  smile

(I don't know if it would help somebody, but I fought with it for a long time now and I thought I'd let you guys know)

Offline

#3 2006-09-05 03:37:32

lefallen
Member
From: Melbourne, Australia
Registered: 2006-07-06
Posts: 36
Website

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Well, just to let you know it is helpful to someone!

Until reading your post I didn't realise how to use the "function" and "special" buttons on my Asus A6U laptop.  I didn't realise they used ACPI.

I then started following your footsteps and got to the same point as you.  I actually then discovered that it was working and that it was just that the keycodes didn't match the X keycodes. I was on a train at the time however and forgot to post a reply - sorry about that.  I didn't realise they were just the linux keycodes though so thanks for that info too.

Now I can get these keys working also!  Bringing my laptop's COMPLETE Linux compatibility to something like 96%!


JABBER: krayon -A-T- chat.qdnx.org
E-MAIL: archlinuxforums -A-T- quadronyx.org
WEB: http://www.qdnx.org/krayon/
~o~

Offline

#4 2006-09-05 11:53:48

Neuro
Member
From: Poland
Registered: 2005-10-12
Posts: 352

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

lefallen wrote:

Well, just to let you know it is helpful to someone!

Glad I could help smile

Now I can get these keys working also!  Bringing my laptop's COMPLETE Linux compatibility to something like 96%!

Yea, same here. What I'm missing is support for the built-in usb bus camera and everything would work just fine smile

Offline

#5 2008-04-10 12:09:13

mik
Member
Registered: 2008-04-07
Posts: 7

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Neuro wrote:

Alright, so I've kind of solved the problem.

It appears that X keycodes are something way different than linux keycodes.
For example doing ./acpi_fakekey 32 shows up in xev as

KeyPress event, serial 31, synthetic NO, window 0x2800001,
    root 0x135, subw 0x0, time 1506877459, (-874,613), root:(176,638),
    state 0x0, keycode 40 (keysym 0x64, d), same_screen YES,
    XLookupString gives 1 bytes: (64) "d"
    XmbLookupString gives 1 bytes: (64) "d"
    XFilterEvent returns: False

So basically when you provide a value to acpi_fakekey, it's a linux keycode (see dumpkeys). In the 'd' example, the linux keycodce is 32 and Xorg keycode is 40 (see xmodmap -pke).

So basically what you need to do, is find out the mapping. As I knew that I'm looking for XF86AudioMute, XF86AudioPlay etc. Xorg keys I thought that it's better to just "press" all linux keycodes and see what happens smile

I wrote a little script (needs to run as root):

#!/bin/bash
xev  &
for i in `seq $1 $2`; do
    if (($i == 99)); then continue; fi # printscreen key, causes xev to unfocus
    echo "!!! key $i" >&2
    /etc/acpi/acpi_fakekey $i
    sleep 1
done;
killall xev

This will print out the currently "presseys ked" key and the resulting (if it works) Xorg event. I don't really know why linux keycode to xorg keycode mapping can't be straight, but hey, it works! wink

And finally I am able to turn the acpi events I get from pressing the keyboard keys into proper Xorg keys.  smile

(I don't know if it would help somebody, but I fought with it for a long time now and I thought I'd let you guys know)

I dont know why i cant use acpi_fakekey 152 to take my computer to "lock-screen".
If i use script from Neuro, xev give result as keycode 36 (Return) for my acpi_fakekey 152

KeyRelease event, serial 24, synthetic NO, window 0x2a00001,
    root 0x87, subw 0x0, time 321615, (814,482), root:(818,533),
    state 0x0, keycode 36 (keysym 0xff0d, Return), same_screen YES,
"   XLookupString gives 1 bytes: (0d) "
    XFilterEvent returns: False

Which key do u use to lock your screen ?
@tastatur

Offline

#6 2008-04-10 13:57:50

imrehg
Member
From: London, UK
Registered: 2008-04-10
Posts: 108
Website

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Neuro wrote:

Yea, same here. What I'm missing is support for the built-in usb bus camera and everything would work just fine smile

How about using linux_uvc? Can find the very latest version  here on AUR. It works fine on my Asus EeePC.

Offline

#7 2008-04-16 19:02:58

Neuro
Member
From: Poland
Registered: 2005-10-12
Posts: 352

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Since I've been getting a lot of mails recently regarding this acpi_fake key thingy here's how I got it to work:

1. The acpi handling script

acpid whenever a acpi event occurres, such as pressing one of the special buttons on ASUS notebooks, runs the /etc/acpi/handler.sh script (as root), which tells it what to do. By default, unknown events, and ASUS hotkeys are unknown until we script them, are logged to /var/log/messages (or somewhere there, I don't remember now) using the logger command. If you play with the buttons and watch them using tail -f on the said log file, you'll see that each key causes a different event. Since we would like to map certain commands to these keys, all we need to do is script these events.

It's better to put the ASUS specific events in a separate file (my case /etc/acpi/asus_hotkey.sh). However, we still need to hook it up, for example by adding the following case to the switch statement in handler.sh:

    hotkey)
        /etc/acpi/asus-hotkey.sh $1 $2 $3 $4
        ;;

2. The ASUS hotkeys

You can use the script to call various system commands, like for example, turning on/off the touchpad. In _my_ script file (your event command can be different) it looks like this:

case "$3" in
    0000006b) # Synaptic touchpad on/off
        ticks=$((16#$4));
        if [ $((ticks % 2)) == 0 ]; then
            logger "ACPI Turning Synaptic touchpad off $ticks"
            /usr/bin/synclient TouchpadOff=1
        else
            logger "ACPI Turning Synaptic touchpad on $ticks"
            /usr/bin/synclient TouchpadOff=0
        fi;
        ;;

In this case, the event code for my (yours can be different) touchpad key is 0000006b. The code as an unknown acpi event is logged (in this case an unknown button press), so you can check your own code this way.

However, keys like stop, play, forward, rewind aren't usefull for root-level commands. I'd like them to act like normal keys on a multimedia keyboard to, for example, control amaroK. Thanks to the acpi_fakekey.c program it is possible. For example (from my configuration):

    00000043) # Media - Stop / generate XF86AudioStop
        /etc/acpi/acpi_fakekey 166    
        ;;

In this example, the press of the stop button generates a linux key code 166 which is interpreted by Xorg as a key press event of XF86AudioStop. In amaroK i just reassigned XF86AudioStop as a shortcut for playback stop (the button now acts as a normal key). Of course, I could map it to, for example, the 'k' event, but who on earth would like the stop button to produce a letter k on screen? tongue

3. The key code to key press
However, key code to Xorg key press event matching is tricky and AFAIK varies greatly from system to system. I couldn't really make head or tails from the manuals, and never found a comprehensive explanation  why things work the way they do. So because I really really badly needed to know which numbers given to acpi_fakekey generate which X events, I went for the brute force solution: generate all key codes from 0 to 255 and see what X makes of them.

I made a little script to do this:

#/bin/sh
xev &
FROM=10
TO=240
sleep 1;
for i in $(seq $FROM $TO); do
        /etc/acpi/acpi_fakekey $i;
        sleep 1;
done

First, as the logged in user you need to execute xhost + to allow root to use your Xorg screen. Then, run the given script as root and watch carefully. Don't use the mouse since it generates a lot of Xorg events and it'll spoil everything! You will see something like:

...
key said to be pressed: 160
key said to be pressed: 161
key said to be pressed: 162
key said to be pressed: 163

FocusOut event, serial 31, synthetic NO, window 0x2c00001,
    mode NotifyGrab, detail NotifyAncestor

FocusIn event, serial 31, synthetic NO, window 0x2c00001,
    mode NotifyUngrab, detail NotifyAncestor

KeymapNotify event, serial 31, synthetic NO, window 0x0,
    keys:  68  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
           0   0   0   2   0   0   0   0   0   0   0   0   0   0   0   0

KeyRelease event, serial 31, synthetic NO, window 0x2c00001,
    root 0x1a6, subw 0x0, time 1373647, (529,562), root:(532,610),
    state 0x0, keycode 153 (keysym 0x1008ff17, XF86AudioNext), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False
key said to be pressed: 164
key said to be pressed: 165
....

Which basically says: 160, 161, 162, 164 aren't recognized as X events. However, key code 163 generates a XF86AudioNext event. Thus you may use key code 163 in acpi_fakekey to generate a XF86AudioNext key stroke. Note: you might need a big buffer for the console you'll be running this code in and, once again, _don't move the mouse_! wink

I uploaded the acpi_fakekey.c : http://continuity.intelink.pl/~neuro/acpi_fakekey.c and my asus_hotkey script:
http://continuity.intelink.pl/~neuro/asus-hotkey.sh

I hope this helps anyone. I would wikify it if I knew the wiki syntax and had a little time on my hands.

Cheers,
Michal

Offline

#8 2008-04-16 20:13:55

Nathan P
Member
Registered: 2008-01-30
Posts: 93

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

I ran that script and got a huge mess

Testing bit 134
Testing bit 135
Testing bit 136

and on and on every time it does a key.  What's up with this?

Also, I pasted the entire output into writer and searched it and it had "Pause" and "Next" as keys but not "XF86AudioNext."  It only had the "XF86AudioNext" type stuff for mute, volume raise, and volume lower.

Also, how do you change which volume slider XF86AudioLowerVolume controls?  As it stands it controls the "PC Speaker" Output which from what I can tell is useless.  The Front output is what it needs to control.

Offline

#9 2008-04-16 20:14:04

uastasi
Member
From: Salento - Italy
Registered: 2007-11-27
Posts: 247

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Hi Neuro, thank you for your explanation. There's a thing I don't understand yet, and it's about acpi_fakekey.c. What should I do with that? It's not a bin so I can't run it, should I compile it or what else?


Till the last battle, till the last bottle.
aur - twitter

Offline

#10 2008-04-16 20:17:44

Nathan P
Member
Registered: 2008-01-30
Posts: 93

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Alright, so those "Next" inputs correspond to the PgUp and PgDn buttons...

Offline

#11 2008-04-16 22:16:59

Neuro
Member
From: Poland
Registered: 2005-10-12
Posts: 352

Re: Hotkey handling through acpi_fake.c program [kind of SOLVED]

Nathan P wrote:

I ran that script and got a huge mess

Testing bit 134
Testing bit 135
Testing bit 136

and on and on every time it does a key.  What's up with this?

Ah,yes. I forgot. Please download the acpi_fakekey.c from my post. These are debugging messages which I put there because the program stopped working ~2.6.19 and I had to fix it. With the source from the link you'll get only "key pressed" messages.

i Neuro, thank you for your explanation. There's a thing I don't understand yet, and it's about acpi_fakekey.c. What should I do with that? It's not a bin so I can't run it, should I compile it or what else?

Just compile it.

gcc -o acpi_fakekey acpi_fakekey.c

or just make acpi_fakekey. The program accepts one argument and it's the key code it'll "generate".

Also, I pasted the entire output into writer and searched it and it had "Pause" and "Next" as keys but not "XF86AudioNext."  It only had the "XF86AudioNext" type stuff for mute, volume raise, and volume lower.

Ah yes, I forgot. You probably have your keyboard configured as a standard pc 104-key keyboard, which obviously, doesn't have the multimedia mappings. Try switching the keyboard type in /etc/X11/xorg.conf to:

    Option         "XkbModel" "hp5185" #"pc104"

There obviously is a better way to find the correct mapping than trying out everything, but I don't know what it is. If anyone could point me to a man page or sth that would explain it, I'd be most grateful.

Also, how do you change which volume slider XF86AudioLowerVolume controls?  As it stands it controls the "PC Speaker" Output which from what I can tell is useless.  The Front output is what it needs to control.

I don't really know what you mean. Are you talking about my script? Because if you correctly map the volume keys and they generate XF86AudioLowerVolume, XF86AudioUpperVolume it most probably gets captured somewhere along the way by your gnome volume applet thingy (or whatever its called) or kmix (in KDE).

Offline

Board footer

Powered by FluxBB