Keyboard Driver Linux

0 views
Skip to first unread message

Frauke Vilandre

unread,
Aug 3, 2024, 5:42:32 PM8/3/24
to pislimicomp

Here comes a very simple example of an input device driver. The device hasjust one button and the button is accessible at i/o port BUTTON_PORT. Whenpressed or released a BUTTON_IRQ happens. The driver could look like:

Then it allocates a new input device structure with input_allocate_device()and sets up input bitfields. This way the device driver tells the otherparts of the input systems what it is - what events can be generated oraccepted by this input device. Our example device can only generate EV_KEYtype events, and from those only BTN_0 event code. Thus we only set thesetwo bits. We could have used:

This adds the button_dev structure to linked lists of the input driver andcalls device handler modules _connect functions to tell them a new inputdevice has appeared. input_register_device() may sleep and therefore mustnot be called from an interrupt or with a spinlock held.

Note that input core keeps track of number of users for the device andmakes sure that dev->open() is called only when the first user connectsto the device and that dev->close() is called when the very last userdisconnects. Calls to both callbacks are serialized.

See uapi/linux/input-event-codes.h for the allowable values of code (from 0 toKEY_MAX). Value is interpreted as a truth value, ie any nonzero value means keypressed, zero value means key released. The input code generates events onlyin case the value is different from before.

However EV_ABS requires a little special care. Before callinginput_register_device, you have to fill additional fields in the input_devstruct for each absolute axis your device has. If our button device had alsothe ABS_X axis:

This setting would be appropriate for a joystick X axis, with the minimum of0, maximum of 255 (which the joystick must be able to reach, no problem ifit sometimes reports more, but it must be able to always reach the min andmax values), with noise in the data up to +- 4, and with a center flatposition of size 8.

The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device IDof the device. The bus IDs are defined in input.h. The vendor and device idsare defined in pci_ids.h, usb_ids.h and similar include files. These fieldsshould be set by the input device driver before registering it.

These three fields should be used by input devices that have dense keymaps.The keycode is an array used to map from scancodes to input system keycodes.The keycode max should contain the size of the array and keycodesize thesize of each entry in it (in bytes).

They are very similar to for example key events, but they go in the otherdirection - from the system to the input device driver. If your input devicedriver can handle these events, it has to set the respective bits in evbit,and also the callback routine:

I recently bought a new keyboard, it was cheap and of an unknown brand but i wasn't particularly worried. I found out that on linux pressing shift, super, left-ctrl or left-alt with this keyboard made no difference, it always take it as shift. I made some researches and it turns out the problem is the chipset used by the keyboard. I read that the only way to solve the problem is to write a driver for the keyboard, but, while working on it i found out that running sudo modprobe usbmon and then opening wireshark as sudo, unexpectedly fixes the problem... someone knows why this happen? and if there is a simpler way to trigger this change?

Treating all modifier keys as shift keys might be caused by the system initially using the simplified boot keyboard protocol (the usbkbd module) instead of the main HID protocol, combined with the fact that the boot keyboard protocol support might be poorly implemented in that particular keyboard. But this is just a wild guess.

Apparently you might see a message like USB HIDBP Keyboard 14cf:0056 in dmesg output if the boot protocol is getting used. What does sudo dmesg grep HID tell you? (Please add the results into your original question.)

Wireshark can also monitor USB traffic, and starting Wireshark with sudo might in fact trigger the loading of the usbmon module. But the fact that the usbmon module causes the problem to be fixed is intriguing... perhaps it causes a re-detection of USB devices so the full-featured usbhid driver module will get the keyboard for itself, or changes the timing of USB traffic just enough that whatever causes the "all modifiers are Shift" dumbness of this keyboard gets avoided.

I'm building a driver for the RGB keyboards so that us Linux users don't miss out on the cool features. Many thanks to CalcProgrammer1 and others (link to his thread here) for decoding the LED messages - wouldn't have gotten this far without them. I really liked the music visualizer and wanted to restructure it into more of a generic driver, so here's my attempt. :biggrin:

It's very incomplete at the moment, needs more fine-tuning and it's still missing major features like key rebinding or the use of the G-keys, but if anyone else out there uses one of these keyboards with Linux I'd love some testing/feedback. It *should* work with the K70 as well as the K95, although I only have a K95 so I can't test the former. Might be possible to run it under OSX as well. I'll keep the GitHub posted as I make progress.

Yep! You can see this in action in the animation demo - it basically just builds up a string of key/color combinations and sends that to the device. You should be able to implement the visualizer in the same way.

Interesting...that's been happening to me sometimes, but so far I've been able to fix it by unplugging the keyboard and plugging it back in. Have you tried using a different USB port? If you're able, can you test it on Windows just to make sure it's working correctly there?

Seems others indicate this might be a power supply issue to the device, or possibly a faulty device. Im hesitant to think its a problem with the USB ports given i have tested a range of other spare USB keyboards at home and all work instantly with no issues or errors.

The firmware is definitely flakey, but I think it's the driver's fault in this case. I managed to reproduce your problem in a VM (same dmesg output as well). I just pushed a commit that, at least in my case, allows it to connect the device anyway. Unfortunately the LED controller still doesn't work when this happens. I'll keep working on it.

Edit: It seems the keyboard really hates the linux HID driver. I think the best route is to disable it entirely and implement all key binding in the custom driver, even when keys aren't reassigned.

Well, pulled down the latest commit, managed to get a little further this time in the log output, but unfortunately the keyboard died again. All the lights are on, but it just doesn't accept any key presses.

Nope. I'm in the process of rewriting the program to detach the stock HID driver entirely and handle all key input through the ckb daemon. It's a less elegant solution than I was hoping for, but I don't feel like debugging the USB keyboard module to figure out what's wrong with it.

It seems to be necessary (most of the time) to issue a USB reset to the device when activating it, and in fact the Windows driver appears to do 2 or 3 of them. But the device breaks again as soon as I try to reactivate the Linux driver. I have a SLIGHT suspicion this keyboard didn't get much compatibility testing... :rolleyes:

I've pushed an update that disables the kernel driver and uses a custom input device. It seems to fix the keyboard not responding, but I don't know if you'll be as lucky. I don't think there's much else I can do if it still fails, so fingers crossed.

Nice! I tried pressing Alt+Left in a terminal and I get a capital D as well, but all of my other keyboards do the same thing. Do you have a non-US layout or any alternate key bindings? I'm working on key rebinding now, so once it's done you should be able to solve the problem that way if nothing else. After that I'll get started on a better control utility so that you can edit the colors/bindings easily.

Unfortunately CUE currently won't write hardware profiles (Corsair says they've disabled it due to firmware issues) so I won't be able to do anything with them until that functionality is added back. Once it is I'll certainly try to implement it.

I took a quick look at the hardware save commands and they don't look too complicated (in fact, the RGB commands are exactly the same as the regular ones). I need to code the concept of profiles into the daemon first, but I should be able to implement this soon.

One other thing i have noticed, and i really need to get more examples to explain it better, but it seems if i plug the keyboard in, start the driver everything works fine, all key mappings are correct.

I'd be happy forever if Corsair officially endorsed this (nudge nudge ;). It's still not nearly complete, but I definitely think I'll be able to provide all of the same functionality as the Windows driver once I'm finished.

I just spent an entire day hitting my head against the wall trying to figure out why the keyboard was reporting all three hardware profiles as having the same RGB settings, only to import them into CUE again and realize that the Windows driver has the exact same problem. Now I see why this was disabled. The save works fine, though, so there's at least that.

By the way, can anybody with a K70 test this (specifically the hwload and hwsave commands)? I know the K70 lacks the mode buttons, so I assume it's the same thing except with only one hardware mode, but I don't have a K70 so I can't confirm it.

I'm nearly done writing the daemon now, so after a few more revisions I'll move on to writing the user utility and you shouldn't have to recompile/restart it every time I make an update. I'll start testing out an OSX version in the next few days as well.

Hey everyone! Sorry for the double post, but I just added OSX support. You have to install libusb separately since OSX doesn't have it by default, but other than that it's just as easy as building the Linux driver.

c80f0f1006
Reply all
Reply to author
Forward
0 new messages