linux/drivers/hid/hid-speedlink.c
<<
>>
Prefs
   1/*
   2 *  HID driver for Speedlink Vicious and Divine Cezanne (USB mouse).
   3 *  Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from
   4 *  the HID descriptor.
   5 *
   6 *  Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.de>
   7 */
   8
   9/*
  10 * This program is free software; you can redistribute it and/or modify it
  11 * under the terms of the GNU General Public License as published by the Free
  12 * Software Foundation; either version 2 of the License, or (at your option)
  13 * any later version.
  14 */
  15
  16#include <linux/device.h>
  17#include <linux/hid.h>
  18#include <linux/module.h>
  19#include <linux/usb.h>
  20
  21#include "hid-ids.h"
  22#include "usbhid/usbhid.h"
  23
  24static const struct hid_device_id speedlink_devices[] = {
  25        { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)},
  26        { }
  27};
  28
  29static int speedlink_input_mapping(struct hid_device *hdev,
  30                struct hid_input *hi,
  31                struct hid_field *field, struct hid_usage *usage,
  32                unsigned long **bit, int *max)
  33{
  34        /*
  35         * The Cezanne mouse has a second "keyboard" USB endpoint for it is
  36         * able to map keyboard events to the button presses.
  37         * It sends a standard keyboard report descriptor, though, whose
  38         * LEDs we ignore.
  39         */
  40        switch (usage->hid & HID_USAGE_PAGE) {
  41        case HID_UP_LED:
  42                return -1;
  43        }
  44        return 0;
  45}
  46
  47static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
  48                struct hid_usage *usage, __s32 value)
  49{
  50        /* No other conditions due to usage_table. */
  51        /* Fix "jumpy" cursor (invalid events sent by device). */
  52        if (value == 256)
  53                return 1;
  54        /* Drop useless distance 0 events (on button clicks etc.) as well */
  55        if (value == 0)
  56                return 1;
  57
  58        return 0;
  59}
  60
  61MODULE_DEVICE_TABLE(hid, speedlink_devices);
  62
  63static const struct hid_usage_id speedlink_grabbed_usages[] = {
  64        { HID_GD_X, EV_REL, 0 },
  65        { HID_GD_Y, EV_REL, 1 },
  66        { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
  67};
  68
  69static struct hid_driver speedlink_driver = {
  70        .name = "speedlink",
  71        .id_table = speedlink_devices,
  72        .usage_table = speedlink_grabbed_usages,
  73        .input_mapping = speedlink_input_mapping,
  74        .event = speedlink_event,
  75};
  76
  77static int __init speedlink_init(void)
  78{
  79        return hid_register_driver(&speedlink_driver);
  80}
  81
  82static void __exit speedlink_exit(void)
  83{
  84        hid_unregister_driver(&speedlink_driver);
  85}
  86
  87module_init(speedlink_init);
  88module_exit(speedlink_exit);
  89MODULE_LICENSE("GPL");
  90