March 5, 2015

Patch Linux kernel to support Esterline Medigenic keyboard

The Esterline Medigenic keyboard does not work under stock Linux kernel (as of kernel version 4.0RC). This is because the HID Report Descriptor of the keyboard is wrong for Linux (and Mac OS). Under Linux kernel tree driver/hid there are a bunch of "special" drivers for different hid devices, and we can create one for the medigenic keyboard to fix up the HID report descriptor so that it works under Linux.

1. Create a file under driver/hid called hid-medigenic.c with the following content:
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 */

#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>

#include "hid-ids.h"

/* the fixups that need to be done:
 *   - change keyboard Usage Mininum from 1 to 0
 */
static __u8 *medigenic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
{
        if (*rsize >= 59 &&
                rdesc[24] == 0x19 && rdesc[25] == 0x01 &&
                rdesc[26] == 0x29 && rdesc[27] == 0x65 ) {
                dev_info(&hdev->dev, "fixing up medigenic keyboard report descriptor\n");
                rdesc[25] = 0x00;
        }
        return rdesc;
}

static const struct hid_device_id medigenic_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ESTERLINE, USB_DEVICE_ID_MEDIGENIC) },
        { }
};
MODULE_DEVICE_TABLE(hid, medigenic_devices);

static struct hid_driver medigenic_driver = {
        .name = "medigenic",
        .id_table = medigenic_devices,
        .report_fixup = medigenic_report_fixup,
};

static int __init medigenic_init(void)
{
        return hid_register_driver(&medigenic_driver);
}

static void __exit medigenic_exit(void)
{
        hid_unregister_driver(&medigenic_driver);
}

module_init(medigenic_init);
module_exit(medigenic_exit);
MODULE_LICENSE("GPL");

2. Edit file driver/hid/hid-ids.h to add the following two lines:
#define USB_VENDOR_ID_ESTERLINE 0x059d
#define USB_DEVICE_ID_MEDIGENIC 0x0708


3. Edit file driver/hid/Kconfig to add the following lines:
config HID_MEDIGENIC
    tristate "Medigenic Keyboard Support" if EMBEDDED
    depends on USB_HID
    default !EMBEDDED
    ---help---
    Support for Medigenic keyboard.

4. Edit file driver/hid/Makefile to add the following line:
obj-$(CONFIG_HID_MEDIGENIC)     += hid-medigenic.o

Then in top directory of kernel, do make menuconfig, and exit, and save (somehow medigenic is automatically set to Y when you do this). Check .config to make sure you have the following line:
CONFIG_HID_MEDIGENIC=y

The build your kernel and the keyboard should work now.

No comments:

Post a Comment