#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "hid-ids.h"
#include "usbhid/usbhid.h"
static __u8 holtek_kbd_rdesc_fixed[] = {
0x05, 0x01,
0x09, 0x80,
0xA1, 0x01,
0x85, 0x01,
0x19, 0x81,
0x29, 0x83,
0x15, 0x00,
0x25, 0x01,
0x95, 0x03,
0x75, 0x01,
0x81, 0x02,
0x95, 0x01,
0x75, 0x05,
0x81, 0x01,
0xC0,
0x05, 0x0C,
0x09, 0x01,
0xA1, 0x01,
0x85, 0x02,
0x19, 0x00,
0x2A, 0xFF, 0x2F,
0x15, 0x00,
0x26, 0xFF, 0x2F,
0x95, 0x01,
0x75, 0x10,
0x81, 0x00,
0xC0,
0x05, 0x01,
0x09, 0x06,
0xA1, 0x01,
0x85, 0x03,
0x95, 0x38,
0x75, 0x01,
0x15, 0x00,
0x25, 0x01,
0x05, 0x07,
0x19, 0xE0,
0x29, 0xE7,
0x19, 0x00,
0x29, 0x2F,
0x81, 0x02,
0xC0,
0x05, 0x01,
0x09, 0x06,
0xA1, 0x01,
0x85, 0x04,
0x95, 0x38,
0x75, 0x01,
0x15, 0x00,
0x25, 0x01,
0x05, 0x07,
0x19, 0x30,
0x29, 0x67,
0x81, 0x02,
0xC0,
0x05, 0x01,
0x09, 0x06,
0xA1, 0x01,
0x05, 0x08,
0x19, 0x01,
0x29, 0x03,
0x15, 0x00,
0x25, 0x01,
0x75, 0x01,
0x95, 0x03,
0x91, 0x02,
0x95, 0x05,
0x91, 0x01,
0xC0,
};
static __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
rdesc = holtek_kbd_rdesc_fixed;
*rsize = sizeof(holtek_kbd_rdesc_fixed);
}
return rdesc;
}
static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
unsigned int code,
int value)
{
struct hid_device *hid = input_get_drvdata(dev);
struct usb_device *usb_dev = hid_to_usb_dev(hid);
struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0);
struct hid_device *boot_hid;
struct hid_input *boot_hid_input;
if (unlikely(boot_interface == NULL))
return -ENODEV;
boot_hid = usb_get_intfdata(boot_interface);
if (list_empty(&boot_hid->inputs)) {
hid_err(hid, "no inputs found\n");
return -ENODEV;
}
boot_hid_input = list_first_entry(&boot_hid->inputs,
struct hid_input, list);
return boot_hid_input->input->event(boot_hid_input->input, type, code,
value);
}
static int holtek_kbd_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
struct usb_interface *intf;
int ret;
if (!hid_is_usb(hdev))
return -EINVAL;
ret = hid_parse(hdev);
if (!ret)
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
intf = to_usb_interface(hdev->dev.parent);
if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) {
struct hid_input *hidinput;
list_for_each_entry(hidinput, &hdev->inputs, list) {
hidinput->input->event = holtek_kbd_input_event;
}
}
return ret;
}
static const struct hid_device_id holtek_kbd_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
{ }
};
MODULE_DEVICE_TABLE(hid, holtek_kbd_devices);
static struct hid_driver holtek_kbd_driver = {
.name = "holtek_kbd",
.id_table = holtek_kbd_devices,
.report_fixup = holtek_kbd_report_fixup,
.probe = holtek_kbd_probe
};
module_hid_driver(holtek_kbd_driver);
MODULE_LICENSE("GPL"