Closed kiwistrongis closed 10 years ago
Not all key codes available for Windows seem to work for Linux.
SteelSeries don't seem to publish their protocol, so we are reverse engineering it. For instance, I witnessed the packets listed below, but don't know what they do. We might have to send some of these to fix the key bindings to match those seen on Windows.
09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
22 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
How are you doing it? A vm with windows and listening with wireshark? usbmon? Also, I don't suppose anyone's tried just asking steelseries for help? XD
Hey KiwiStrongis, you can already change color zones programmatically with ApexCtl. All you need to do is to change/uncomment the relevant line: --apexSetColorProfile devHndl cp0 to apexSetColorProfile devHndl cp0
The cp0 'variable' describes color profile which is defined towards the top of the file: cp0 = SetColorProfile colorRed colorRed colorRed colorRed colorRed
colorRed is defined using 4 components: red, green, blue and intensity, which can change from 0 (off) to 8 (max intensity): colorRed = Color 0xFF 0x00 0x00 0x08
A few example colors and color profiles are already defined.
Now for key codes, these can be changed using external tools. The way (more or less) USB input works is:
So basically all you need to do, is to create a custom ~/.Xmodmap file, which rebinds custom scancodes to something more meaningful, like F13, F14, ..., F35.
I just googled a bit and it seems that the problem is in keyboard-specific scancode to keycode mappings, which only later get pet passed to evdev and to X server.
Here is a bit more info on the subject: https://wiki.archlinux.org/index.php/Map_scancodes_to_keycodes Later I'll try to create a custom udev mappings file, which should fix the problem Zimmux was mentioning (that several keys translate to the same keycode).
Do the M8 - M12 keys work for you? They did not show any keypresses through showkey if I remember correctly, I haven't tried with xev. Can you share your ~/.Xmodmap file?
I am using custom utility that takes events directly from evdev and executes commands when necessary, so I bypass the X11 layer entirely and therefore do not have (yet) an appropriate Xmodmap file. So M9-M12 keys do work for me, but only in this low level setting.
Ok, I've added a few things to get everything working properly: 1) config/90-apex.hwdb file, which adds necessary scancode to keycode bindings 2) config/Xmodmap (which should be placed to ~/.Xmodmap), which adds keycode to keysym bindings Now:
3) config/90-apexctl.rules file, which provides udev rule that automatically invokes /usr/local/bin/apexctl when Apex or Apex Raw keyboard is plugged in.
Cool, I'll give it a try when I get home tonight (my apex is at home). Maybe I'll work on a script for setting the colour/brightness for the zones. I was thinking something like command [-c|--colour north|south|east|west|logo|n|s|e|w|l #ffffff] [-b|--brightness (0..8)]
. Idk what to call the command. Can I just tack it on to apexctl?
Also, I think you made a mistake. M1-M12 is 12 keys, but F13-F23 is 11. Also MX1-10 is 10 keys, but F25-35 plus XF86Launch5 is 12.
How you apply the udev rule? Like this?:
cp config/90-apexctl.rules /etc/udev/rules.d/
udevadm control --reload-rules
Yes, you are right. Two keys were unnecessary. And color management should be included directly into apexctl, but I was just too lazy to implement it at the time. As for reloading udev rules, after copying both files (.hwdb and .rules), i just: 1) sudo udevadm hwdb --update 2) sudo udevadm control --reload
Mkay, I'll write the colour management into apexctl tonight, if you're cool with that. :)
Does running apexctl repeatedly cause problems? It just resets the keys, right? Also, should we be storing profile data in a config file? At least for the colours, having a config file would be good, right? And would an install script be a good idea? Just being able to to `make && sudo make install`` would be nice.
I'm working on command line args right now, so you won't need to code it.
Running apexctl does not seem to cause any problems. However when I was developing the utility, if I changed colors really quickly (with no delay, like 1000 times per second or something), from time to time the keyboard would crash and would take the whole hub down with it. So in order to get back everything working, I had to reset the hub.
As for install script - I'm not sure whether make is the best way to do things, because Haskell uses cabal as it's build system and it is capable of installing binaries (by default it installs everything to ~/.cabal/bin; I haven't tried running 'cabal install' with root though).
Okidoke, aha. I was looking forward to some haskell practice. XD Maybe I'll write a gui for apexctl :).
I'm just thinking of packaging problems, when you install an rpm or dep, it would install to /usr/bin, not ~/.cabal/bin. You might not even have cabal installed, right?
Sorry from robbing you of opportunity for practice. I saw your comment when I was already working on it.
Anyway, I've just pushed a restructured version of apexctl with a bit nicer code and command line options.
A gui might be nice for this, but I don't think that Haskell has any nice GUI libraries. Most of them have more or less 'raw' bindings of C libraries. Though there exist some more Haskelly (and more exotic) abstractions for those libraries, but I don't think that Haskell community has come up with anything that is practically usable.
Cabal is necessary only for building apexctl. If you want to package it to rpm or deb, when you could package the apexctl just like a regular binary, since it has no external haskell dependencies (Haskell programs tend to be compiled statically). Though it will still depend on libusb.
I'd love a deb package for this though. I've never done anything packaging related, so I'm noob on that subject.
Oh, that's okay :). I'm completely new to haskell, I'm sure your work is better.
Re: gui - I was planning on doing it with gtk3/c++, and just use system calls to apexctl.
Re: packaging - I'm a packaging noob too, just I really wanna learn it. I'm thinking that just a standard ./configure && make && sudo make install
is probably more appropriate for this project, aha.
Also, were you planning user profiles of some sort?
Nope. I hadn't thought about user profiles. If you want, you can implement those :)
Mkay, I'll take crack at it tonight or tomorrow night. I'm just about to leave work, so it'll be soon. What time zone are you in? I just wanna know if you'll be available for help tonight. I'm in EDT (UTC - 4).
I live in GMT +2, so 6 hour difference. I usually stay up till 4:00 AM GMT +2.
This seems a bit off topic so I'll use this as a discussion thread.
Sorry about the many branches, didn't know github created a new one when clicking edit through the browser interface.
No problem.
so how does this makefile look to you? I think I got everything.
I also got to try your changes. The keys don't map to what you said they did - and a number of keys are duplicated. I'll write down what each key is currently mapped to tonight. Also the colour stuff was nice, with a bit of experimenting, I managed to get very close to the colours I like. The brightness is a bit bugged though, you can only set the brightness for the south zone - all the others are at maximum.
One other thing, mind if I markdown-ify the readme? :) I wanna make it prettier and stuff, aha.
Makefile looks great.
Brightness control is mainly intended for Apex [RAW] keyboards, where exists only one 'color' zone. If you want to adjust brightness on Apex keyboard, you should use this color notation: RRGGBB:A, where A is brightness. Or: RGB:A (a shorter version of the same thing). It's not documented, but it should be.
Also I would really accept all the help regarding proper version of README.
Today I also noticed another problem regarding 90-apexctl.rules file, which calls apexctl whenever you plug in the keyboard or on startup. Apparently, when apexctl is invoked, it counts as a short keyboard unplug/plug, which causes another invocation of apexctl and so it begins to recursively loop and spam a lot of apexctl invocations. I'm not sure whether this can be fixed by tweaking the rules file further. So probably additional apexctl mode is required (like apexctl boot or something), which before running should check when was the last apexctl invocation. If it was less than 3-5 seconds ago, apexctl should just quit without doing anything, thus preventing the loop.
What's the range for the values? The RRGGBB is obviously hex like ffffff:A. The range for A is 0..8, inclusive, right? What's the RGB:A format? 000:0 to fff:8 or 999:8?
One other thing, I think it's better to install to /usr/bin than /usr/local/bin. Have a look at this rant for the reasons, or just try:
sudo -s
echo $PATH
Maybe /usr/local/sbin would work?
Re: readme - I'll do that tonight, after work. It'll probably end up looking something like this, but with a few different sections. Also, have you thought about licenses? The MIT license is probably appropriate.
Re: makefile - Thanks :).
RGB:A format is 0-F inclusive for R, G and B. And 0-8 inclusive for A.
For installations I think we should use /usr/local/sbin then, because everything in /usr/bin is usually managed by a package manager.
I usually slap LGPL on everything I create. Though MIT might be suitable too. Not sure which one is better.
Unfortunately /usr/local/sbin won't work :(. It has to be one of the following to work with sudo:
[kiwistrongis@blackbox ^_^ opt]$ sudo -s
[sudo] password for kiwistrongis:
[root@blackbox ^_^ opt]$ echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin
and
[kiwistrongis@blackbox >_< ~]$ ls /usr/local/sbin
apexctl
[kiwistrongis@blackbox ^_^ ~]$ sudo apexctl
sudo: apexctl: command not found
/usr/sbin is probably best? This is kinda a distro-specific problem though, a solution could be to add /usr/local/sbin to the secure_path in /etc/sudoers, if the distro requires it. I don't think this should be done by the install script though.
I just added LGPL 3 to my fork :). Feel free to pull. I was looking at choosealicense.com/licenses, and I think I like LGPL more. I think I'll use it for my projects in the future.
Another alternative is
sudo -i apexctl
I'm using (L)Ubuntu, so pretty much everything you can think of ends up in $PATH.
Also, would you mind sending me a pull request for the changes you've made?
You also previously mentioned that some key bindings are duplicated. Could you elaborate a bit more on that?
Pull request sent. Just FYI, you can always do:
git remote add kiwi https://github.com/KiwiStrongis/ApexCtl.git
git fetch kiwi
git merge kiwi/master
The L keys and M9 through M12 all give 0x0f with xev (i dont remember the key code). Some of the media keys (the right-most column) are duplicated on some of the MX keys, but i don't remember the specifics - I'll have to check when i get home. I think it was like this MX1 - Play MX2 - Stop MX6 - Volume Up MX7 - Volume Down MX8 - Mute I probably need to customize my ~/.Xmodmap
It seems that you haven't applied your Xmodmap at all. All extra keys should translate either to F* keys or to XLaunch1-XLaunch4. I have a script that (among other things) on startup calls "xmodmap ~/.Xmodmap". I know that some environments/DEs used to do or still do this automatically.
I'm pretty sure I did. Give me a couple (4) hours to get home and double check :).
For Apex RAW, I still can't get L1, L2, M9-M12 to send anything useful. The MX1, MX3 and MX4 keys overlap with media keys. The other codes seem arbitrary, but are at least distinct:
MX1 172 = Play/Pause
MX2 174
MX3 173 = AudioPrev
MX4 171 = AudioNext
MX5 169
M1 144
M2 185
M3 186
M4 184
M5 150
M6 160
M7 181
M8 148
M9 248
M10 248
M11 248
M12 248
L1 248
L2 248
I made a whole bunch of changes. The only change i thought you might object to is that i renamed reset-usb to apexctl-reset. Lemme know if you want me to put it back or if you have a better idea for a name.
Also I mapped out what all my keys are currently bound to with xev: keys.txt
M1 144 = Find
M2 185 = F31
M3 186 = F32
M4 184 = F30
M5 xxx = Sleep
M6 xxx = Lock
M7 181 = F27
M8 148 = XF86Calculator
M9 248 = NoSymbol
M10 248 = NoSymbol
M11 248 = NoSymbol
M12 248 = NoSymbol
MX1 172 = XF86AudioPlay
MX2 174 = XF86AudioStop
MX3 173 = XF86AudioPrev
MX4 171 = XF86AudioNext
MX5 169 = XF86Eject
MX6 123 = XF86AudioRaiseVolume
MX7 122 = XF86AudioLowerVolume
MX8 121 = XF86AudioMute
MX9 158 = XF86WWW
MX10 166 = XF86Back
L1 248 = NoSymbol
L2 248 = NoSymbol
L3 248 = NoSymbol
L4 248 = NoSymbol
V+ 123 = XF86AudioRaiseVolume
V- 122 = XF86AudioLowerVolume
Vmute 121 = XF86AudioMute
Mprev 173 = XF86AudioPrev
Mnext 171 = XF86AudioNext
Mpaus 172 = XF86AudioPlay
A few notes: reset-usb script is/was used to reset a specific hub in my machine. There is no guarantee that it will work on any other machine. So it should be either removed or parameterized with a variable that allows specification of target hub.
Regarding wrong key mappings: It seems that 90-apex.hwdb has failed to remap keys on your machine. Make sure that your distro allows placing hwdb files in /etc/udev/hwdb.d. Also check what is your udev version (hwdb file contract may change between different udev/systemd versions). Also try using evtest utility to see which scancodes translate to what keycodes. Test just M9-M12 keys and paste the results here.
Also try using: sudo udevadm test /sys/class/input/inputXX, where XX should correspond to your Apex keyboard input id. It should show whether hwdb mappings have been attached to XX input device.
Hmm, things have started working. :D
I probably forgot to reboot after changing the Xmodmap or hwdb.
How does this look?: https://github.com/KiwiStrongis/ApexCtl/blob/master/apexctl-reset What was the reason for the sleep between the unbind/rebind?
Fedora supposedly does support the hwdb.d folder. I couldn't figure out how to check the udev version, though.
The evtest log: github.com/KiwiStrongis/ApexCtl/blob/master/log.txt Weirdly enough there's two entries, one just for the media keys.
With evtest I was able to figure out the scancodes. I guess I just need to change my hwdb file to match them?
Zimmux: that's good to hear that you have everything working.
KiwiStrongis: The script looks awesome. As for sleep, I don't really remember why I put it there. In general, a 'normal' user shouldn't ever need to reset an USB hub. It's more of a measure of the last resort when you want your USB ports operational without rebooting the whole OS.
And you don't need to change anything, because we have the same model and our scancodes match. All you need to to is to figure how fedora handles hwdb files/where to place them/how to activate them (the log you posted proves that your udev currently does not 'see' the hwdb file; there should be an entry for each 700xx key there). Check /lib/udev/hwdb.d folder, that's where Ubuntu puts hwdb files that are managed by package manager.
Yeah /lib/udev/hwdb.d has a number of hwdb files, and I'm sure that'd work, but shouldn't non-package-manager-managed files stay out of there? (I'll try it tonight.)
I'll rename it to apexctl-resethubs? or reset-usbhub? Maybe it should be removed :S.
I was thinking - I'll add a user confirmation and warning to the script.
The script still could be useful for those who would like to add extra commands/functionality.
I've tried both /lib/udev/hwdb.d and /etc/udev/hwdb.d. man udevadm
(and this forum post says they're both read from. I'm going to try rebooting with both, I guess.
I tried the udevadm test thing: https://gist.github.com/KiwiStrongis/9569981
Also, pull request. I made the readme pretty. Lemme know if you have any suggestions :).
Can you find 60-keyboard.hwdb file in your installation and upload it to gist? It could be that hwdb file contract is different in your machine.
There isn't one O_o maybe I accidentally deleted it? I'll see if i can grab it off a livecd.
Can you try then to find ANY *.hwdb file and upload some of them?
Here's all of them, but they just seem to be vendor identification stuff.
And does your installation anywhere contain 60-keyboard.rules file?
No, but I found one 95-keymap.rules that looks like it adds the mappings for some other special keyboards.
So that means that your udev (or systemd) is simply outdated and you need to upgrade.
I don't suppose you know which version of systemd adds the necessary support, or how new is the required features are? I was thinking i could just write a .rules file based on the keymap.rules for myself.
Unfortunately I don't think you can write your own .rules file, because keymap support is integrated directly into udev and depends on udev built-in commands. The minimum required systemd version is v206 which was released 8 months ago.
Mine (on fedora 19) is 204 :(. I guess I'll check if fedora 20 has it, and upgrade if it does.
So fedora 20 has 208, and i've been lusting for korora for a while now. I'm planning to upgrade this weekend. I'll let you know how it goes :).
Hey, thanks for working this out :)
So what are the keys supposed to be bound to? For me, a bunch of the MX keys are bound to media keys and stuff (even though the apex already had media keys). Also, the colour profile buttons aren't supposed to work, right? I'm glad they're disabled at least XD . I used to keep accidentally hit them instead of Esc.
Also idk haskell, and I'm open to learning it. How (programmatically) easy would it be (for me) to make a tool that can set key codes for the macro keys and colour zones, etc?
Sorry for the wall of text, I'm just excited to finally get my awesome keyboard working on my favorite OS :).