UPDATE:
As of recent versions of Chrome OS, the procedure detailed below (using jscal) no longer works to remap keys for Android apps. The original post should now be considered deprecated and no longer applicable.
In some cases, Android apps will suffice to remap keys, and in other cases it may be possible to remap events in CrOS via evdev.
I wanted to play the game "War Robots" but when I opened it up I discovered that, while I could move and aim, the buttons to fire were incorrectly mapped.
First of all, I tried creating /system/usr/keylayout/Vendor_045e_Product_0719.kl on the Android filesystem, as this was what had worked for me to configure this gamepad on my Nexus 9. However, editing the Android keylayout didn't seem to do anything on the Chromebook. I had a look around the device and found that in the list of CrOS installable packages at /etc/portage/make.profile/package.installable, the following was included: games-util/joystick-1.4.2.
Accordingly, I emerged joystick-1.4.2 and played around with jstest and jscal.
The set of commands to emerge these binaries:
shell
Turned out I that with this I was able to easily swap gamepad button mappings around.
First of all I dumped the current mapping with
jscal -q /dev/input/js0
which gave the following output
jscal -u 6,0,1,2,3,4,5,15,304,305,307,308,310,311,314,315,316,317,318,704,705,706,707 /dev/input/js0
In order to determine which number corresponded to which button, I tried
jstest /dev/input/js0
However, when I pressed some buttons on the gamepad, numbers for the buttons were displayed which did not correspond with the set above. So I tried evtest
emerge evtest
Output:
No device specified, trying to scan all of /dev/input/event*
6
Hooray! Pressing the buttons on the gamepad gives useful output, such as
code 311 (BTN_TR), value 1
and so on
Armed with this information I was easily able to fix the mapping in War Robots, which had one "Fire" button mapped to "Start" and another "Fire" button mapped to "Back". I found a number of reports online suggesting that this is a current issue with (lack of) controller support in the game itself, rather than any quirk of running Android on Chrome OS.
jscal -u 6,0,1,2,3,4,5,15,304,305,307,308,310,311,314,315,316,317,318,704,705,706,707 /dev/input/js0
jscal -u 6,0,1,2,3,4,5,15,304,305,307,308,314,315,310,311,316,317,318,704,705,706,707 /dev/input/js0
Saved the config. to a file with:
jscal -q /dev/input/js0 > /usr/local/WR_gamepad.sh
Unfortunately I also had another issue to fix. There is a fair amount of play in both the analog axis of my controller, the right one particularly, meaning that with the controller at rest, it's sometimes still pointing to the right slightly. In order to stop the annoying 'camera moving to the right without me moving it' issue, I needed to calibrate the dead zones.
Back to jscal:
jscal -c
(went through the calibration, which involves pressing each button/moving each axis once)
Output:
Calibrated axis:
Setting correction to:
Dumped the above corrections with
jscal -p /dev/input/js0 which gave the following output:
jscal -s 6,1,0,-338,-338,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-64,-64,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0
jscal -p /dev/input/js0 > /usr/local/jscal.sh
First attempt at editing dead zones.
vi/usr/local/jscal.sh
Original file contents (as above):
jscal -s 6,1,0,-338,-338,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-64,-64,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0
Changed the 4th and 5th values (axis 0) and the 22nd and 23rd values (axis 3) from -338,-338 and -64, -64 respectively to +/- ~3000 (Axis 0 and 3 are L-< >+R on the two analogs).
New file contents:
jscal -s 6,1,0,-3038,3038,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-3064,3064,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0
Opened up the game. Still some drift in the right-hand analog. Let's have a look at what's going on with jstest:
jstest /dev/input/js0
Moving the analogs different ways, dropping them to center, and watching the values change in jstest confirms that while there is play in both sticks, the right hand side of the right hand stick is particularly loose.
Second attempt at modifying the calibration
vi /usr/local/jscal.sh
Tried -3064,10064 on axis 3.
:wq!
Opened up the game. This one works quite well! I probably set it a little too high, but at least there's no right hand drift at all, now.
Final file contents:
#!/bin/bash
jscal -s 6,1,0,-3038,3038,16555,16217,1,0,-8,-8,16388,16380,1,0,126,126,4260750,4161663,1,0,-3064,10064,16416,16352,1,0,55,55,16357,-16357,1,0,111,128,4836527,4227201 /dev/input/js0
The following config seems to work well in MC5 to eliminate camera drift while still passing maximum values reasonably close to the original. It still doesn't quite give the proper maximum range, but seems close enough to work well for this game.
#!/bin/bash
jscal -s 6,1,0,237,237,16266,16503,1,0,797,797,16153,16792,1,0,126,126,4260750,4161663,1,0,-3908,3908,18086,18694,1,0,-6989,6989,19894,19904,1,0,122,125,4400447,4129650 /dev/input/js0
TL;DR version:
hey nolirium can you help me? the controller i have controls the keyboard on my chromebook not the games :/ how do i fix?
ReplyDeletecould we do a hangouts chat maybe?
DeleteI don't have much time for extended Hangouts chats or anything like that really, tbh
DeleteDoes it show up correctly (as a gamepad) on html5gamepad.com?
ReplyDeleteno it does nothing :/ is that bad? im assuming it is :/
Deleteno gamepad it doesnt react at all
DeleteWhich controller? You might be out of luck right now, I think they're in the middle of a rewrite of some of the underlying code dealing with gamepads. I saw a post from one of the Google devs recently suggesting that people get their Bluetooth controllers from somewhere with a decent return policy...
DeleteYou could do dev_install & emerge evtest or joystick/jstest as per my post above, and see if anything shows up there
its a obecome t3 bluetooth controller i was messing arond with jscal/jstest and emerging random things that looked like they could help me could we please do a hangout call it would make this thing so much easier it doesnt have to be long either and im seeing people do the games im trying to play like mc5 heres the output from evtest
Deletenvm cant send it too big
Deletebruh u there?
Deleteyeah, sorry, been a bit busy. Did you have any success? If not, if you install the Android app 'Game Controller Keymapper', does it also show up there as a keyboard?
Deleteno it didnt work
Deletethe app says "Chromeoskeyboard"
Saw something that reminded me of this. If you still have this problem you could try adding a rule in udev, similar to the 8bitdo rules listed here:
Deletehttp://g00se.org/2016/07/8bitdo-udev.html
Just one of the lines, saved as something like 99-gamepad-rules in /etc/udev/rules.d/ might do the trick. (change ATTRS{name} to whatever shows up in evtest or lsusb as the name of your controller).
e.g.
SUBSYSTEM=="input", ATTRS{name}=="whateverthenameis", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1"
could we plz do a hangout chat though?
ReplyDeleteI am trying to configure a wired xbox 360 controller to map buttons for PUBG Mobile. Its been a difficult task. Even with SuperSu running on my Chomebook, I haven't had any luck allowed new .ki files to be used for keymapping via Tincore Keymapping or Game Controller KeyMapper. Something about the Kernal not supporting UINPUT. Any thoughts?
ReplyDeleteYou should be able to use http://appmirror.net/app/tools/gamekeyboard/ for this. I just tested it out with my wireless Xbox 360 pad and after setting it up it works well with PUBG Mobile.
DeleteI may make another post laying out the steps in a bit more detail but briefly:
I downloaded GameKeyboard+ from the link above, opened it, tapped "Settings", under "General Usage Settings" unchecked Standalone Mode, then reopened the app - it showed three prompts for setup/first time running under IME mode.
Step 1 (enable GameKeyboard+ IME) would normally open Android's screen to enable IMEs, on CrOS this setting routes to Chrome's Language Settings screen, so as per my blog post regarding IMEs I had to enable the IME manually in the shell.
After enabling the IME "com.locnet.gamekeyboard2/.SoftKeyboard" in a root Android shell, and setting it as default (Step 2), I was able to select the four right hand soft buttons on GameKeyboard+'s touchscreen overlay to bind to A, B, X and Y on my 360 controller, bind them, remove the other soft buttons, open PUBG, in PUBG's settings move the right hand buttons (Fire etc.) slightly so they were well aligned with the GameKeyboard+ overlay, then start the game.
Hi! I'm also trying to configure my Shield TV controller for PUBG Mobile, but I have problems with the keymapping. Basically both triggers are recognized as axis and also control the right stick. Since the chromebook thinks that the axis is centered when the trigger is half pressed, this results in camera spin, even when the triggers are not pressed at all.
ReplyDeleteI was trying to change the keymap with your guide, but couldn't figure out the specifics.
This problem appears only on chrome os, Android recognizes the controller correctly, windows recognizes it as an Xbox 360 controller, but the mapping is correct (the Shield controller is basically an Xbox controller).
Any ideas how I could unbind the triggers form the axis and map it correctly?
Although you may be able to fix the bindings with e.g. jscal, I think it might be more straightforward to try adding in a keylayout file for your controller to the Android /system/usr/keylayout dir.
DeleteIf you haven't got a R/W Android system in CrOS (per the rooting scripts), you could, in the CrOS shell, copy the Android keylayouts directory to e.g. /usr/local, add your .kl file, bind mount keylayouts back across to its original location, and then reboot (just) the Android container (with printf reboot | android-sh, again in the CrOS shell, as root).
You can check the Vendor and Product ID for your controller with lsusb, then maybe find the relevant .kl online, or rename a copy of a similar .kl to correspond with the Vendor and Product ID of your controller. Perhaps you already have the relevant .kl in your other Android device's keylayout directory (though not necessarily)...
From looking at the stock CrOS keylayout file, the listing for the axes of generic gamepads is
axis 0x00 X
axis 0x01 Y
axis 0x02 Z
axis 0x03 RX
axis 0x04 RY
axis 0x05 RZ
while the x360 (Vendor_045e_Product_028e.kl) controller axes have this mapping:
axis 0x00 X flat 4096
axis 0x01 Y flat 4096
axis 0x03 Z flat 4096
axis 0x04 RZ flat 4096
# Triggers.
axis 0x02 LTRIGGER
axis 0x05 RTRIGGER
So yeah, it looks like 0x02 and 0x05 axes events are sent by the controller, and mapped to Z and RZ (right stick) in the CrOS Android container's stock keylayout for generic/unspecified controllers.
I found an old NVidia Shield controller's .kl online
axis 0x00 invert X flat 2
axis 0x01 Y flat 2
axis 0x02 invert LTRIGGER flat 2
axis 0x03 invert Z flat 2
axis 0x04 RZ flat 2
axis 0x05 invert RTRIGGER flat 2
More or less the same mappings as x360, but different deadzones etc. So, if you can't find the .kl that exactly matches your controller's Vendor/Device ID, the Nvidia may be better to use as a base, I guess.
The latter mappings are from a .kl for the original Shield controller, downloaded from this xda thread:
https://forum.xda-developers.com/showthread.php?t=2754866
If the .kl method doesn't work, or you would prefer to try doing it another way, feel free to post back.
you can use https://play.google.com/store/apps/details?id=com.Evag.UACL to find out the info to the controller
DeleteThanks! I can't seem to find the the .kl file for the Shield Controller 2017 anywhere online. But If I have paired my phone with the controller, I should be able to find the corresponding .kl file on it? Because I'm not able to find the file with the corresponding vendor ID. Is there a way to bluetooth vendor IDs (or it should be the same)?
ReplyDeleteRight now i'm trying to rename Xbox .kl file, just to see what happens, but I don't fully understand how to bind the file (I have root access with your script).
Ok, disregard (parts of) my previous comment. I was able to get the correct nvidia .kl files off my Shield TV (small miracle, since i'm not home). How can I get them into the Chome OS keylayout folder?
DeleteOh, if you have root access (su in Android) from the rooting script, then you shouldn't need to bind mount anything since you should already have a writeable Android rootfs. Your .kl should go into the directory /opt/google/containers/android/rootfs/root/system/usr/keylayout/
DeleteThe following part may not be necessary at all, but it's possible that the permissions, ownership, context of the file you add may need to match those of the existing files in the directory. To rule out any potential issue with this, what I would do is make a duplicate copy of an existing file in the destination directory (with cp -a), then copy (overwrite) the contents of my file into the duplicate.
In case the above paragraph is a little unclear, here's an example of what I mean: http://pasted.co/52ccc1cf
Hm. Did what you described and it still doesn't work.
DeleteIs Chrome OS even using these as standard? Because I use html5gamepad.com to troubleshoot and I don't think that accesses the android layouts. I also use the Game Controller KeyMapper app and there the gamepad shows up as "ChromeOS Gamepad", not the correct name.
Having looked into it some, it seems like Chrome OS gamepad support has changed quite a bit since I made my original post. The .kl idea came to mind as I'd recently been using keymaps to remap my CB's hardware keyboard in Android, which worked well, but as far as gamepads, it appears that not only are these vendor_product keymap files not being used now, but additionally, there appears to have been quite a bit of work on moving over to a new system of gamepad support in the past year, which seems to be ongoing.
DeleteAs a result of the changeover, the calibration/remapping via joydev per my original post appears to no longer work, so my post needs updating.
***
All the stuff at
https://cs.chromium.org/chromium/src/ui/events/ozone/gamepad/
seems new. To quote a bit from there:
"There is a group of gamepads designed for joydev interface but will require a mapping for evdev. There was no existing mapping in current code base but if we move on to use evdev gamepad in arc++, user will notice their gamepad does not work anymore.
The purpose of this patch is to generate a mapping as close to joydev as possible while being compatible with xbox and adt gamnepads.
When gamepad vendor id and product id are unknown, we will use generic
mapping. A static generic mapping can only be compatible with one class
of gamepad. This commit implements a dynamic generic gamepad mapping. It
is both compatible with XInput style and ADT style gamepad. And it trys
it best to be compatible with joydev compatible gamepad."
"This patch add gamepad event and gamepad support to Ozone.
gamepad_event_converter_evdev will map evdev gamepad events to w3c
standard gamepad events. Then the events will be dispatched."
***
I noticed in the old code at
https://cs.chromium.org/chromium/src/device/gamepad/gamepad_standard_mappings_linux.cc?l=544
there's only one reference to a Nvidia controller, Vendor 0955", product "7210". I guess that's not your exact one...
Oh, and yeah, sorry, lsusb wouldn't show devices connected via bluetooth. I guess cat /proc/bus/input/devices may do?.
So anyway, yeah, it looks like unfortunately not only the .kl approach won't work but also the jscal approach, as joydev is being deprecated.
Another way of key remapping, that works in theory but seemed unreliable when I tried something similar lately is to use python-evdev. Not sure why using python-evdev was unreliable unfortunately, maybe have been some race condition or something blocking, possibly fixable. I was hoping to do some troubleshooting on this when I got a chance. Making the script for python-evdev is somewhat more involved, though (and this method may also stop working through the container).
If anything else comes to mind, I'll post back.
Bad news, but you were very insightful, thank you!
DeleteNo, that's not the right controller, mine is Vendor 0955", product "7214".
DeleteI'll share some data that I collected, maybe it's of some help. I used html5gampad.com to troubleshoot the buttons.
First up is Chrome OS:
http://i1201.photobucket.com/albums/bb348/piendem/html5gamepad_chromeos_zpshlu6kv7l.png
What's interesting, that vendor and product IDs and even the firmware version are recognized correctly. Triggers are recognized as Axis 3,4, and 7. It's the same on bluetooth and USB.
Next is Android with bluetooth:
http://i1201.photobucket.com/albums/bb348/piendem/html5gamepad_android_zpsptoustzm.png
As to be expected it works correctly. Only four axis and the triggers are recognized as buttons.
Finally windows with USB:
http://i1201.photobucket.com/albums/bb348/piendem/html5gamepad_windows_zps8c5hfsyq.png
Recognized as an Xbox 360 controller, but works as it should.
I also used the Game Controller Keymapper android app to see how android apps recognize the controller:
http://i1201.photobucket.com/albums/bb348/piendem/IMG_20180401_091208_zpsmfjjbc3g.jpg
http://i1201.photobucket.com/albums/bb348/piendem/2b4eb1a2-aa01-4644-8703-f1b6cfae0574_zpsnelmc0f3.jpg
Recognized as "ChromeOS Gamepad". It's hard to see in the picture, but the right stick moves to the right on both triggers. But they don't just show up as AXIS_Z, but also as L/R trigger, like they should.
Yeah, product 7214 is in the newer OS code, at
Deletehttps://cs.chromium.org/chromium/src/ui/events/ozone/gamepad/static_gamepad_mapping.cc?rcl=d7843a4769214114c1fa55069976918b6d751b54&l=485
It looks like they still have a few bugs/tweaks to iron out in the new implementation. I've seen a couple of other posts here and there like yours, where people are still having issues with wrong mappings. If you haven't already done so, I might suggest sending in an issue report (with Alt+Shift+I) with a brief precis of the issue.
I noticed that it's possible to forward the uinput character device into the Android container, by adding appropriate details into /opt/google/containers/android/config.json. Some Android keyboard mapping apps require uinput to create virtual input devices.I haven't looked into it any further though, and such an approach would be rather involved, and may not be worth messing around with. Just posting the info anyway, in case you (or anyone) might be curious about (the lack of) uinput in Android.
I'll have a look into evdev when I get a chance, and if I come up with anything on that side of things, I'll post back.
Thanks! I already reported this problem, but I though there is a way I could fix this myself.
DeleteHey guys can anyone help me out, im trying to use a 360 controller on my Chromebook to use ppsspp and shadow gun legends. The controller registers and works except the mapping are incorrect. it has my bumpers labeled as the select and start buttons, and some other buttons just dont respond at all.
ReplyDeleteMy name is Chris btw, i dont know why it defaulted to "Unknown"
DeleteI have a tab E from Samsung and I'm trying to use an Xbox One controller Bluetooth to the Samsung Tab e for robot war robots and no one has been of any help period. Is this possible
ReplyDeleteIs it rooted? If so, do you have the right keylayout in your /system/usr/keylayout folder?
DeleteAs per e.g. this guide:
https://www.howtogeek.com/329647/how-to-get-the-xbox-one-s-controller-working-properly-with-android/
I also have just about every Controller made for mainstream systems is there something that would work better I just don't know how to map buttons or anything like that and when I open it up I'm having the same problem that's crossed out above from the old school 360 controllers where I can walk but none of the buttons fire
ReplyDeleteI promise I read everything above lol.
ReplyDeletewhen i look up my aim button come up this is on chromebook just to say
ReplyDeletemy chromebook does not see the pad how can i cofigure it
ReplyDelete