diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/hid')
87 files changed, 0 insertions, 36707 deletions
diff --git a/ANDROID_3.4.5/drivers/hid/Kconfig b/ANDROID_3.4.5/drivers/hid/Kconfig deleted file mode 100644 index 1283fa3b..00000000 --- a/ANDROID_3.4.5/drivers/hid/Kconfig +++ /dev/null @@ -1,670 +0,0 @@ -# -# HID driver configuration -# -menuconfig HID_SUPPORT - bool "HID Devices" - depends on INPUT - default y - ---help--- - Say Y here to get to see options for various computer-human interface - device drivers. This option alone does not add any kernel code. - - If you say N, all options in this submenu will be skipped and disabled. - -if HID_SUPPORT - -config HID - tristate "Generic HID support" - depends on INPUT - default y - ---help--- - A human interface device (HID) is a type of computer device that - interacts directly with and takes input from humans. The term "HID" - most commonly used to refer to the USB-HID specification, but other - devices (such as, but not strictly limited to, Bluetooth) are - designed using HID specification (this involves certain keyboards, - mice, tablets, etc). This option compiles into kernel the generic - HID layer code (parser, usages, etc.), which can then be used by - transport-specific HID implementation (like USB or Bluetooth). - - For docs and specs, see http://www.usb.org/developers/hidpage/ - - If unsure, say Y. - -config HID_BATTERY_STRENGTH - bool - depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY - default n - -config HIDRAW - bool "/dev/hidraw raw HID device support" - depends on HID - ---help--- - Say Y here if you want to support HID devices (from the USB - specification standpoint) that aren't strictly user interface - devices, like monitor controls and Uninterruptable Power Supplies. - - This module supports these devices separately using a separate - event interface on /dev/hidraw. - - There is also a /dev/hiddev configuration option in the USB HID - configuration menu. In comparison to hiddev, this device does not process - the hid events at all (no parsing, no lookups). This lets applications - to work on raw hid events when they want to, and avoid using transport-specific - userspace libhid/libusb libraries. - - If unsure, say Y. - -config UHID - tristate "User-space I/O driver support for HID subsystem" - depends on HID - default n - ---help--- - Say Y here if you want to provide HID I/O Drivers from user-space. - This allows to write I/O drivers in user-space and feed the data from - the device into the kernel. The kernel parses the HID reports, loads the - corresponding HID Device Driver or provides input devices on top of your - user-space device. - - This driver cannot be used to parse HID-reports in user-space and write - special HID-drivers. You should use hidraw for that. - Instead, this driver allows to write the transport-layer driver in - user-space like USB-HID and Bluetooth-HID do in kernel-space. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called uhid. - -source "drivers/hid/usbhid/Kconfig" - -menu "Special HID drivers" - depends on HID - -config HID_A4TECH - tristate "A4 tech mice" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for A4 tech X5 and WOP-35 / Trust 450L mice. - -config HID_ACRUX - tristate "ACRUX game controller support" - depends on USB_HID - ---help--- - Say Y here if you want to enable support for ACRUX game controllers. - -config HID_ACRUX_FF - bool "ACRUX force feedback support" - depends on HID_ACRUX - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you want to enable force feedback support for ACRUX - game controllers. - -config HID_APPLE - tristate "Apple {i,Power,Mac}Books" if EXPERT - depends on (USB_HID || BT_HIDP) - default !EXPERT - ---help--- - Support for some Apple devices which less or more break - HID specification. - - Say Y here if you want support for keyboards of Apple iBooks, PowerBooks, - MacBooks, MacBook Pros and Apple Aluminum. - -config HID_BELKIN - tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Belkin Flip KVM and Wireless keyboard. - -config HID_CHERRY - tristate "Cherry Cymotion keyboard" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Cherry Cymotion keyboard. - -config HID_CHICONY - tristate "Chicony Tactical pad" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Chicony Tactical pad. - -config HID_PRODIKEYS - tristate "Prodikeys PC-MIDI Keyboard support" - depends on USB_HID && SND - select SND_RAWMIDI - ---help--- - Support for Prodikeys PC-MIDI Keyboard device support. - Say Y here to enable support for this device. - - Prodikeys PC-MIDI keyboard. - The Prodikeys PC-MIDI acts as a USB Audio device, with one MIDI - input and one MIDI output. These MIDI jacks appear as - a sound "card" in the ALSA sound system. - Note: if you say N here, this device will still function as a basic - multimedia keyboard, but will lack support for the musical keyboard - and some additional multimedia keys. - -config HID_CYPRESS - tristate "Cypress mouse and barcode readers" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for cypress mouse and barcode readers. - -config HID_DRAGONRISE - tristate "DragonRise Inc. game controller" - depends on USB_HID - ---help--- - Say Y here if you have DragonRise Inc. game controllers. - These might be branded as: - - Tesun USB-703 - - Media-tech MT1504 "Rogue" - - DVTech JS19 "Gear" - - Defender Game Master - -config DRAGONRISE_FF - bool "DragonRise Inc. force feedback" - depends on HID_DRAGONRISE - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you want to enable force feedback support for DragonRise Inc. - game controllers. - -config HID_EMS_FF - tristate "EMS Production Inc. force feedback support" - depends on USB_HID - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you want to enable force feedback support for devices by - EMS Production Ltd. - Currently the following devices are known to be supported: - - Trio Linker Plus II - -config HID_ELECOM - tristate "ELECOM BM084 bluetooth mouse" - depends on BT_HIDP - ---help--- - Support for the ELECOM BM084 (bluetooth mouse). - -config HID_EZKEY - tristate "Ezkey BTC 8193 keyboard" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Ezkey BTC 8193 keyboard. - -config HID_HOLTEK - tristate "Holtek On Line Grip based game controller support" - depends on USB_HID - ---help--- - Say Y here if you have a Holtek On Line Grip based game controller. - -config HOLTEK_FF - bool "Holtek On Line Grip force feedback support" - depends on HID_HOLTEK - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you have a Holtek On Line Grip based game controller - and want to have force feedback support for it. - -config HID_KEYTOUCH - tristate "Keytouch HID devices" - depends on USB_HID - ---help--- - Support for Keytouch HID devices not fully compliant with - the specification. Currently supported: - - Keytouch IEC 60945 - -config HID_KYE - tristate "KYE/Genius devices" - depends on USB_HID - ---help--- - Support for KYE/Genius devices not fully compliant with HID standard: - - Ergo Mouse - - EasyPen i405X tablet - - MousePen i608X tablet - - EasyPen M610X tablet - -config HID_UCLOGIC - tristate "UC-Logic" - depends on USB_HID - ---help--- - Support for UC-Logic tablets. - -config HID_WALTOP - tristate "Waltop" - depends on USB_HID - ---help--- - Support for Waltop tablets. - -config HID_GYRATION - tristate "Gyration remote control" - depends on USB_HID - ---help--- - Support for Gyration remote control. - -config HID_TWINHAN - tristate "Twinhan IR remote control" - depends on USB_HID - ---help--- - Support for Twinhan IR remote control. - -config HID_KENSINGTON - tristate "Kensington Slimblade Trackball" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Kensington Slimblade Trackball. - -config HID_LCPOWER - tristate "LC-Power" - depends on USB_HID - ---help--- - Support for LC-Power RC1000MCE RF remote control. - -config HID_LOGITECH - tristate "Logitech devices" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Logitech devices that are not fully compliant with HID standard. - -config HID_LOGITECH_DJ - tristate "Logitech Unifying receivers full support" - depends on HID_LOGITECH - default m - ---help--- - Say Y if you want support for Logitech Unifying receivers and devices. - Unifying receivers are capable of pairing up to 6 Logitech compliant - devices to the same receiver. Without this driver it will be handled by - generic USB_HID driver and all incomming events will be multiplexed - into a single mouse and a single keyboard device. - -config LOGITECH_FF - bool "Logitech force feedback support" - depends on HID_LOGITECH - select INPUT_FF_MEMLESS - help - Say Y here if you have one of these devices: - - Logitech WingMan Cordless RumblePad - - Logitech WingMan Cordless RumblePad 2 - - Logitech WingMan Force 3D - - Logitech Formula Force EX - - Logitech WingMan Formula Force GP - - Logitech MOMO Force wheel - - and if you want to enable force feedback for them. - Note: if you say N here, this device will still be supported, but without - force feedback. - -config LOGIRUMBLEPAD2_FF - bool "Logitech RumblePad/Rumblepad 2 force feedback support" - depends on HID_LOGITECH - select INPUT_FF_MEMLESS - help - Say Y here if you want to enable force feedback support for Logitech - RumblePad and Rumblepad 2 devices. - -config LOGIG940_FF - bool "Logitech Flight System G940 force feedback support" - depends on HID_LOGITECH - select INPUT_FF_MEMLESS - help - Say Y here if you want to enable force feedback support for Logitech - Flight System G940 devices. - -config LOGIWHEELS_FF - bool "Logitech wheels configuration and force feedback support" - depends on HID_LOGITECH - select INPUT_FF_MEMLESS - default LOGITECH_FF - help - Say Y here if you want to enable force feedback and range setting - support for following Logitech wheels: - - Logitech Driving Force - - Logitech Driving Force Pro - - Logitech Driving Force GT - - Logitech G25 - - Logitech G27 - - Logitech MOMO/MOMO 2 - - Logitech Formula Force EX - -config HID_MAGICMOUSE - tristate "Apple MagicMouse multi-touch support" - depends on BT_HIDP - ---help--- - Support for the Apple Magic Mouse multi-touch. - - Say Y here if you want support for the multi-touch features of the - Apple Wireless "Magic" Mouse. - -config HID_MICROSOFT - tristate "Microsoft non-fully HID-compliant devices" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Microsoft devices that are not fully compliant with HID standard. - -config HID_MONTEREY - tristate "Monterey Genius KB29E keyboard" if EXPERT - depends on USB_HID - default !EXPERT - ---help--- - Support for Monterey Genius KB29E. - -config HID_MULTITOUCH - tristate "HID Multitouch panels" - depends on USB_HID - ---help--- - Generic support for HID multitouch panels. - - Say Y here if you have one of the following devices: - - 3M PCT touch screens - - ActionStar dual touch panels - - Atmel panels - - Cando dual touch panels - - Chunghwa panels - - CVTouch panels - - Cypress TrueTouch panels - - Elo TouchSystems IntelliTouch Plus panels - - GeneralTouch 'Sensing Win7-TwoFinger' panels - - GoodTouch panels - - Hanvon dual touch panels - - Ilitek dual touch panels - - IrTouch Infrared USB panels - - LG Display panels (Dell ST2220Tc) - - Lumio CrystalTouch panels - - MosArt dual-touch panels - - Panasonic multitouch panels - - PenMount dual touch panels - - Perixx Peripad 701 touchpad - - PixArt optical touch screen - - Pixcir dual touch panels - - Quanta panels - - eGalax dual-touch panels, including the Joojoo and Wetab tablets - - Stantum multitouch panels - - Touch International Panels - - Unitec Panels - - XAT optical touch panels - - Xiroku optical touch panels - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called hid-multitouch. - -config HID_NTRIG - tristate "N-Trig touch screen" - depends on USB_HID - ---help--- - Support for N-Trig touch screen. - -config HID_ORTEK - tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" - depends on USB_HID - ---help--- - There are certain devices which have LogicalMaximum wrong in the keyboard - usage page of their report descriptor. The most prevailing ones so far - are manufactured by Ortek, thus the name of the driver. Currently - supported devices by this driver are - - - Ortek PKB-1700 - - Ortek WKB-2000 - - Skycable wireless presenter - -config HID_PANTHERLORD - tristate "Pantherlord/GreenAsia game controller" - depends on USB_HID - ---help--- - Say Y here if you have a PantherLord/GreenAsia based game controller - or adapter. - -config PANTHERLORD_FF - bool "Pantherlord force feedback support" - depends on HID_PANTHERLORD - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you have a PantherLord/GreenAsia based game controller - or adapter and want to enable force feedback support for it. - -config HID_PETALYNX - tristate "Petalynx Maxter remote control" - depends on USB_HID - ---help--- - Support for Petalynx Maxter remote control. - -config HID_PICOLCD - tristate "PicoLCD (graphic version)" - depends on USB_HID - ---help--- - This provides support for Minibox PicoLCD devices, currently - only the graphical ones are supported. - - This includes support for the following device features: - - Keypad - - Switching between Firmware and Flash mode - - EEProm / Flash access (via debugfs) - Features selectively enabled: - - Framebuffer for monochrome 256x64 display - - Backlight control - - Contrast control - - General purpose outputs - Features that are not (yet) supported: - - IR - -config HID_PICOLCD_FB - bool "Framebuffer support" if EXPERT - default !EXPERT - depends on HID_PICOLCD - depends on HID_PICOLCD=FB || FB=y - select FB_DEFERRED_IO - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - ---help--- - Provide access to PicoLCD's 256x64 monochrome display via a - frambuffer device. - -config HID_PICOLCD_BACKLIGHT - bool "Backlight control" if EXPERT - default !EXPERT - depends on HID_PICOLCD - depends on HID_PICOLCD=BACKLIGHT_CLASS_DEVICE || BACKLIGHT_CLASS_DEVICE=y - ---help--- - Provide access to PicoLCD's backlight control via backlight - class. - -config HID_PICOLCD_LCD - bool "Contrast control" if EXPERT - default !EXPERT - depends on HID_PICOLCD - depends on HID_PICOLCD=LCD_CLASS_DEVICE || LCD_CLASS_DEVICE=y - ---help--- - Provide access to PicoLCD's LCD contrast via lcd class. - -config HID_PICOLCD_LEDS - bool "GPO via leds class" if EXPERT - default !EXPERT - depends on HID_PICOLCD - depends on HID_PICOLCD=LEDS_CLASS || LEDS_CLASS=y - ---help--- - Provide access to PicoLCD's GPO pins via leds class. - -config HID_PRIMAX - tristate "Primax non-fully HID-compliant devices" - depends on USB_HID - ---help--- - Support for Primax devices that are not fully compliant with the - HID standard. - -config HID_ROCCAT - tristate "Roccat device support" - depends on USB_HID - ---help--- - Support for Roccat devices. - Say Y here if you have a Roccat mouse or keyboard and want - support for its special functionalities. - -config HID_SAITEK - tristate "Saitek non-fully HID-compliant devices" - depends on USB_HID - ---help--- - Support for Saitek devices that are not fully compliant with the - HID standard. - - Currently only supports the PS1000 controller. - -config HID_SAMSUNG - tristate "Samsung InfraRed remote control or keyboards" - depends on USB_HID - ---help--- - Support for Samsung InfraRed remote control or keyboards. - -config HID_SONY - tristate "Sony PS3 controller" - depends on USB_HID - ---help--- - Support for Sony PS3 controller. - -config HID_SPEEDLINK - tristate "Speedlink VAD Cezanne mouse support" - depends on USB_HID - ---help--- - Support for Speedlink Vicious and Divine Cezanne mouse. - -config HID_SUNPLUS - tristate "Sunplus wireless desktop" - depends on USB_HID - ---help--- - Support for Sunplus wireless desktop. - -config HID_GREENASIA - tristate "GreenAsia (Product ID 0x12) game controller support" - depends on USB_HID - ---help--- - Say Y here if you have a GreenAsia (Product ID 0x12) based game - controller or adapter. - -config GREENASIA_FF - bool "GreenAsia (Product ID 0x12) force feedback support" - depends on HID_GREENASIA - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you have a GreenAsia (Product ID 0x12) based game controller - (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter - and want to enable force feedback support for it. - -config HID_HYPERV_MOUSE - tristate "Microsoft Hyper-V mouse driver" - depends on HYPERV - ---help--- - Select this option to enable the Hyper-V mouse driver. - -config HID_SMARTJOYPLUS - tristate "SmartJoy PLUS PS2/USB adapter support" - depends on USB_HID - ---help--- - Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box, - Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro. - - Note that DDR (Dance Dance Revolution) mode is not supported, nor - is pressure sensitive buttons on the pro models. - -config SMARTJOYPLUS_FF - bool "SmartJoy PLUS PS2/USB adapter force feedback support" - depends on HID_SMARTJOYPLUS - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to - enable force feedback support for it. - -config HID_TIVO - tristate "TiVo Slide Bluetooth remote control support" - depends on (USB_HID || BT_HIDP) - ---help--- - Say Y if you have a TiVo Slide Bluetooth remote control. - -config HID_TOPSEED - tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" - depends on USB_HID - ---help--- - Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic - CLLRCMCE remote control. - -config HID_THRUSTMASTER - tristate "ThrustMaster devices support" - depends on USB_HID - ---help--- - Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or - a THRUSTMASTER Ferrari GT Rumble Wheel. - -config THRUSTMASTER_FF - bool "ThrustMaster devices force feedback support" - depends on HID_THRUSTMASTER - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or 3, - a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT - Rumble Force or Force Feedback Wheel. - -config HID_WACOM - tristate "Wacom Bluetooth devices support" - depends on BT_HIDP - ---help--- - Support for Wacom Graphire Bluetooth tablet. - -config HID_WACOM_POWER_SUPPLY - bool "Wacom Bluetooth devices power supply status support" - depends on HID_WACOM - select POWER_SUPPLY - ---help--- - Say Y here if you want to enable power supply status monitoring for - Wacom Bluetooth devices. - -config HID_WIIMOTE - tristate "Nintendo Wii Remote support" - depends on BT_HIDP - depends on LEDS_CLASS - select POWER_SUPPLY - select INPUT_FF_MEMLESS - ---help--- - Support for the Nintendo Wii Remote bluetooth device. - -config HID_WIIMOTE_EXT - bool "Nintendo Wii Remote Extension support" - depends on HID_WIIMOTE - default HID_WIIMOTE - ---help--- - Support for extension controllers of the Nintendo Wii Remote. Say yes - here if you want to use the Nintendo Motion+, Nunchuck or Classic - extension controllers with your Wii Remote. - -config HID_ZEROPLUS - tristate "Zeroplus based game controller support" - depends on USB_HID - ---help--- - Say Y here if you have a Zeroplus based game controller. - -config ZEROPLUS_FF - bool "Zeroplus based game controller force feedback support" - depends on HID_ZEROPLUS - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you have a Zeroplus based game controller and want - to have force feedback support for it. - -config HID_ZYDACRON - tristate "Zydacron remote control support" - depends on USB_HID - ---help--- - Support for Zydacron remote control. - -endmenu - -endif # HID_SUPPORT diff --git a/ANDROID_3.4.5/drivers/hid/Makefile b/ANDROID_3.4.5/drivers/hid/Makefile deleted file mode 100644 index 9dca8459..00000000 --- a/ANDROID_3.4.5/drivers/hid/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -# -# Makefile for the HID driver -# -hid-y := hid-core.o hid-input.o - -ifdef CONFIG_DEBUG_FS - hid-objs += hid-debug.o -endif - -obj-$(CONFIG_HID) += hid.o -obj-$(CONFIG_UHID) += uhid.o - -hid-$(CONFIG_HIDRAW) += hidraw.o - -hid-logitech-y := hid-lg.o -ifdef CONFIG_LOGITECH_FF - hid-logitech-y += hid-lgff.o -endif -ifdef CONFIG_LOGIRUMBLEPAD2_FF - hid-logitech-y += hid-lg2ff.o -endif -ifdef CONFIG_LOGIG940_FF - hid-logitech-y += hid-lg3ff.o -endif -ifdef CONFIG_LOGIWHEELS_FF - hid-logitech-y += hid-lg4ff.o -endif - -hid-wiimote-y := hid-wiimote-core.o -ifdef CONFIG_HID_WIIMOTE_EXT - hid-wiimote-y += hid-wiimote-ext.o -endif -ifdef CONFIG_DEBUG_FS - hid-wiimote-y += hid-wiimote-debug.o -endif - -obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o -obj-$(CONFIG_HID_ACRUX) += hid-axff.o -obj-$(CONFIG_HID_APPLE) += hid-apple.o -obj-$(CONFIG_HID_BELKIN) += hid-belkin.o -obj-$(CONFIG_HID_CHERRY) += hid-cherry.o -obj-$(CONFIG_HID_CHICONY) += hid-chicony.o -obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o -obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o -obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o -obj-$(CONFIG_HID_ELECOM) += hid-elecom.o -obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o -obj-$(CONFIG_HID_GYRATION) += hid-gyration.o -obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o -obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o -obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o -obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o -obj-$(CONFIG_HID_KYE) += hid-kye.o -obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o -obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o -obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o -obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o -obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o -obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o -obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o -obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o -obj-$(CONFIG_HID_ORTEK) += hid-ortek.o -obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o -obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o -obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o -obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o -obj-$(CONFIG_HID_PRIMAX) += hid-primax.o -obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ - hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ - hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o -obj-$(CONFIG_HID_SAITEK) += hid-saitek.o -obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o -obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o -obj-$(CONFIG_HID_SONY) += hid-sony.o -obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o -obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o -obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o -obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o -obj-$(CONFIG_HID_TIVO) += hid-tivo.o -obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o -obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o -obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o -obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o -obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o -obj-$(CONFIG_HID_WACOM) += hid-wacom.o -obj-$(CONFIG_HID_WALTOP) += hid-waltop.o -obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o - -obj-$(CONFIG_USB_HID) += usbhid/ -obj-$(CONFIG_USB_MOUSE) += usbhid/ -obj-$(CONFIG_USB_KBD) += usbhid/ - diff --git a/ANDROID_3.4.5/drivers/hid/hid-a4tech.c b/ANDROID_3.4.5/drivers/hid/hid-a4tech.c deleted file mode 100644 index 902d1dfe..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-a4tech.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * HID driver for some a4tech "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> - -#include "hid-ids.h" - -#define A4_2WHEEL_MOUSE_HACK_7 0x01 -#define A4_2WHEEL_MOUSE_HACK_B8 0x02 - -struct a4tech_sc { - unsigned long quirks; - unsigned int hw_wheel; - __s32 delayed_value; -}; - -static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct a4tech_sc *a4 = hid_get_drvdata(hdev); - - if (usage->type == EV_REL && usage->code == REL_WHEEL) - set_bit(REL_HWHEEL, *bit); - - if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) - return -1; - - return 0; -} - -static int a4_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct a4tech_sc *a4 = hid_get_drvdata(hdev); - struct input_dev *input; - - if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || - !usage->type) - return 0; - - input = field->hidinput->input; - - if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) { - if (usage->type == EV_REL && usage->code == REL_WHEEL) { - a4->delayed_value = value; - return 1; - } - - if (usage->hid == 0x000100b8) { - input_event(input, EV_REL, value ? REL_HWHEEL : - REL_WHEEL, a4->delayed_value); - return 1; - } - } - - if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) { - a4->hw_wheel = !!value; - return 1; - } - - if (usage->code == REL_WHEEL && a4->hw_wheel) { - input_event(input, usage->type, REL_HWHEEL, value); - return 1; - } - - return 0; -} - -static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - struct a4tech_sc *a4; - int ret; - - a4 = kzalloc(sizeof(*a4), GFP_KERNEL); - if (a4 == NULL) { - hid_err(hdev, "can't alloc device descriptor\n"); - ret = -ENOMEM; - goto err_free; - } - - a4->quirks = id->driver_data; - - hid_set_drvdata(hdev, a4); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - kfree(a4); - return ret; -} - -static void a4_remove(struct hid_device *hdev) -{ - struct a4tech_sc *a4 = hid_get_drvdata(hdev); - - hid_hw_stop(hdev); - kfree(a4); -} - -static const struct hid_device_id a4_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU), - .driver_data = A4_2WHEEL_MOUSE_HACK_7 }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D), - .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649), - .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, - { } -}; -MODULE_DEVICE_TABLE(hid, a4_devices); - -static struct hid_driver a4_driver = { - .name = "a4tech", - .id_table = a4_devices, - .input_mapped = a4_input_mapped, - .event = a4_event, - .probe = a4_probe, - .remove = a4_remove, -}; - -static int __init a4_init(void) -{ - return hid_register_driver(&a4_driver); -} - -static void __exit a4_exit(void) -{ - hid_unregister_driver(&a4_driver); -} - -module_init(a4_init); -module_exit(a4_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-apple.c b/ANDROID_3.4.5/drivers/hid/hid-apple.c deleted file mode 100644 index 299d2387..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-apple.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * USB HID quirks support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> - */ - -/* - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/device.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "hid-ids.h" - -#define APPLE_RDESC_JIS 0x0001 -#define APPLE_IGNORE_MOUSE 0x0002 -#define APPLE_HAS_FN 0x0004 -#define APPLE_HIDDEV 0x0008 -#define APPLE_ISO_KEYBOARD 0x0010 -#define APPLE_MIGHTYMOUSE 0x0020 -#define APPLE_INVERT_HWHEEL 0x0040 -#define APPLE_IGNORE_HIDINPUT 0x0080 -#define APPLE_NUMLOCK_EMULATION 0x0100 - -#define APPLE_FLAG_FKEY 0x01 - -static unsigned int fnmode = 1; -module_param(fnmode, uint, 0644); -MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, " - "[1] = fkeyslast, 2 = fkeysfirst)"); - -static unsigned int iso_layout = 1; -module_param(iso_layout, uint, 0644); -MODULE_PARM_DESC(iso_layout, "Enable/Disable hardcoded ISO-layout of the keyboard. " - "(0 = disabled, [1] = enabled)"); - -struct apple_sc { - unsigned long quirks; - unsigned int fn_on; - DECLARE_BITMAP(pressed_fn, KEY_CNT); - DECLARE_BITMAP(pressed_numlock, KEY_CNT); -}; - -struct apple_key_translation { - u16 from; - u16 to; - u8 flags; -}; - -static const struct apple_key_translation macbookair_fn_keys[] = { - { KEY_BACKSPACE, KEY_DELETE }, - { KEY_ENTER, KEY_INSERT }, - { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, - { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, - { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, - { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, - { KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, - { KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, - { KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY }, - { KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY }, - { KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, - { KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, - { KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY }, - { KEY_UP, KEY_PAGEUP }, - { KEY_DOWN, KEY_PAGEDOWN }, - { KEY_LEFT, KEY_HOME }, - { KEY_RIGHT, KEY_END }, - { } -}; - -static const struct apple_key_translation apple_fn_keys[] = { - { KEY_BACKSPACE, KEY_DELETE }, - { KEY_ENTER, KEY_INSERT }, - { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, - { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, - { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, - { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, - { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, - { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, - { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, - { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, - { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY }, - { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY }, - { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, - { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, - { KEY_UP, KEY_PAGEUP }, - { KEY_DOWN, KEY_PAGEDOWN }, - { KEY_LEFT, KEY_HOME }, - { KEY_RIGHT, KEY_END }, - { } -}; - -static const struct apple_key_translation powerbook_fn_keys[] = { - { KEY_BACKSPACE, KEY_DELETE }, - { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, - { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, - { KEY_F3, KEY_MUTE, APPLE_FLAG_FKEY }, - { KEY_F4, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, - { KEY_F5, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, - { KEY_F6, KEY_NUMLOCK, APPLE_FLAG_FKEY }, - { KEY_F7, KEY_SWITCHVIDEOMODE, APPLE_FLAG_FKEY }, - { KEY_F8, KEY_KBDILLUMTOGGLE, APPLE_FLAG_FKEY }, - { KEY_F9, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, - { KEY_F10, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, - { KEY_UP, KEY_PAGEUP }, - { KEY_DOWN, KEY_PAGEDOWN }, - { KEY_LEFT, KEY_HOME }, - { KEY_RIGHT, KEY_END }, - { } -}; - -static const struct apple_key_translation powerbook_numlock_keys[] = { - { KEY_J, KEY_KP1 }, - { KEY_K, KEY_KP2 }, - { KEY_L, KEY_KP3 }, - { KEY_U, KEY_KP4 }, - { KEY_I, KEY_KP5 }, - { KEY_O, KEY_KP6 }, - { KEY_7, KEY_KP7 }, - { KEY_8, KEY_KP8 }, - { KEY_9, KEY_KP9 }, - { KEY_M, KEY_KP0 }, - { KEY_DOT, KEY_KPDOT }, - { KEY_SLASH, KEY_KPPLUS }, - { KEY_SEMICOLON, KEY_KPMINUS }, - { KEY_P, KEY_KPASTERISK }, - { KEY_MINUS, KEY_KPEQUAL }, - { KEY_0, KEY_KPSLASH }, - { KEY_F6, KEY_NUMLOCK }, - { KEY_KPENTER, KEY_KPENTER }, - { KEY_BACKSPACE, KEY_BACKSPACE }, - { } -}; - -static const struct apple_key_translation apple_iso_keyboard[] = { - { KEY_GRAVE, KEY_102ND }, - { KEY_102ND, KEY_GRAVE }, - { } -}; - -static const struct apple_key_translation *apple_find_translation( - const struct apple_key_translation *table, u16 from) -{ - const struct apple_key_translation *trans; - - /* Look for the translation */ - for (trans = table; trans->from; trans++) - if (trans->from == from) - return trans; - - return NULL; -} - -static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, - struct hid_usage *usage, __s32 value) -{ - struct apple_sc *asc = hid_get_drvdata(hid); - const struct apple_key_translation *trans, *table; - - if (usage->code == KEY_FN) { - asc->fn_on = !!value; - input_event(input, usage->type, usage->code, value); - return 1; - } - - if (fnmode) { - int do_translate; - - if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && - hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) - table = macbookair_fn_keys; - else if (hid->product < 0x21d || hid->product >= 0x300) - table = powerbook_fn_keys; - else - table = apple_fn_keys; - - trans = apple_find_translation (table, usage->code); - - if (trans) { - if (test_bit(usage->code, asc->pressed_fn)) - do_translate = 1; - else if (trans->flags & APPLE_FLAG_FKEY) - do_translate = (fnmode == 2 && asc->fn_on) || - (fnmode == 1 && !asc->fn_on); - else - do_translate = asc->fn_on; - - if (do_translate) { - if (value) - set_bit(usage->code, asc->pressed_fn); - else - clear_bit(usage->code, asc->pressed_fn); - - input_event(input, usage->type, trans->to, - value); - - return 1; - } - } - - if (asc->quirks & APPLE_NUMLOCK_EMULATION && - (test_bit(usage->code, asc->pressed_numlock) || - test_bit(LED_NUML, input->led))) { - trans = apple_find_translation(powerbook_numlock_keys, - usage->code); - - if (trans) { - if (value) - set_bit(usage->code, - asc->pressed_numlock); - else - clear_bit(usage->code, - asc->pressed_numlock); - - input_event(input, usage->type, trans->to, - value); - } - - return 1; - } - } - - if (iso_layout) { - if (asc->quirks & APPLE_ISO_KEYBOARD) { - trans = apple_find_translation(apple_iso_keyboard, usage->code); - if (trans) { - input_event(input, usage->type, trans->to, value); - return 1; - } - } - } - - return 0; -} - -static int apple_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct apple_sc *asc = hid_get_drvdata(hdev); - - if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || - !usage->type) - return 0; - - if ((asc->quirks & APPLE_INVERT_HWHEEL) && - usage->code == REL_HWHEEL) { - input_event(field->hidinput->input, usage->type, usage->code, - -value); - return 1; - } - - if ((asc->quirks & APPLE_HAS_FN) && - hidinput_apple_event(hdev, field->hidinput->input, - usage, value)) - return 1; - - - return 0; -} - -/* - * MacBook JIS keyboard has wrong logical maximum - */ -static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - struct apple_sc *asc = hid_get_drvdata(hdev); - - if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && - rdesc[53] == 0x65 && rdesc[59] == 0x65) { - hid_info(hdev, - "fixing up MacBook JIS keyboard report descriptor\n"); - rdesc[53] = rdesc[59] = 0xe7; - } - return rdesc; -} - -static void apple_setup_input(struct input_dev *input) -{ - const struct apple_key_translation *trans; - - set_bit(KEY_NUMLOCK, input->keybit); - - /* Enable all needed keys */ - for (trans = apple_fn_keys; trans->from; trans++) - set_bit(trans->to, input->keybit); - - for (trans = powerbook_fn_keys; trans->from; trans++) - set_bit(trans->to, input->keybit); - - for (trans = powerbook_numlock_keys; trans->from; trans++) - set_bit(trans->to, input->keybit); - - for (trans = apple_iso_keyboard; trans->from; trans++) - set_bit(trans->to, input->keybit); -} - -static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->hid == (HID_UP_CUSTOM | 0x0003)) { - /* The fn key on Apple USB keyboards */ - set_bit(EV_REP, hi->input->evbit); - hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN); - apple_setup_input(hi->input); - return 1; - } - - /* we want the hid layer to go through standard path (set and ignore) */ - return 0; -} - -static int apple_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct apple_sc *asc = hid_get_drvdata(hdev); - - if (asc->quirks & APPLE_MIGHTYMOUSE) { - if (usage->hid == HID_GD_Z) - hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL); - else if (usage->code == BTN_1) - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_2); - else if (usage->code == BTN_2) - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_1); - } - - return 0; -} - -static int apple_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - unsigned long quirks = id->driver_data; - struct apple_sc *asc; - unsigned int connect_mask = HID_CONNECT_DEFAULT; - int ret; - - asc = kzalloc(sizeof(*asc), GFP_KERNEL); - if (asc == NULL) { - hid_err(hdev, "can't alloc apple descriptor\n"); - return -ENOMEM; - } - - asc->quirks = quirks; - - hid_set_drvdata(hdev, asc); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - if (quirks & APPLE_HIDDEV) - connect_mask |= HID_CONNECT_HIDDEV_FORCE; - if (quirks & APPLE_IGNORE_HIDINPUT) - connect_mask &= ~HID_CONNECT_HIDINPUT; - - ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - kfree(asc); - return ret; -} - -static void apple_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); -} - -static const struct hid_device_id apple_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL), - .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4), - .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE), - .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, - - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS), - .driver_data = APPLE_HAS_FN }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_ISO_KEYBOARD }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_ISO_KEYBOARD }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI), - .driver_data = APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO), - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | - APPLE_ISO_KEYBOARD }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - - { } -}; -MODULE_DEVICE_TABLE(hid, apple_devices); - -static struct hid_driver apple_driver = { - .name = "apple", - .id_table = apple_devices, - .report_fixup = apple_report_fixup, - .probe = apple_probe, - .remove = apple_remove, - .event = apple_event, - .input_mapping = apple_input_mapping, - .input_mapped = apple_input_mapped, -}; - -static int __init apple_init(void) -{ - int ret; - - ret = hid_register_driver(&apple_driver); - if (ret) - pr_err("can't register apple driver\n"); - - return ret; -} - -static void __exit apple_exit(void) -{ - hid_unregister_driver(&apple_driver); -} - -module_init(apple_init); -module_exit(apple_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-axff.c b/ANDROID_3.4.5/drivers/hid/hid-axff.c deleted file mode 100644 index 5be858dd..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-axff.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Force feedback support for ACRUX game controllers - * - * From what I have gathered, these devices are mass produced in China - * by several vendors. They often share the same design as the original - * Xbox 360 controller. - * - * 1a34:0802 "ACRUX USB GAMEPAD 8116" - * - tested with an EXEQ EQ-PCU-02090 game controller. - * - * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#ifdef CONFIG_HID_ACRUX_FF -#include "usbhid/usbhid.h" - -struct axff_device { - struct hid_report *report; -}; - -static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct axff_device *axff = data; - struct hid_report *report = axff->report; - int field_count = 0; - int left, right; - int i, j; - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - - dbg_hid("called with 0x%04x 0x%04x", left, right); - - left = left * 0xff / 0xffff; - right = right * 0xff / 0xffff; - - for (i = 0; i < report->maxfield; i++) { - for (j = 0; j < report->field[i]->report_count; j++) { - report->field[i]->value[j] = - field_count % 2 ? right : left; - field_count++; - } - } - - dbg_hid("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, axff->report, USB_DIR_OUT); - - return 0; -} - -static int axff_init(struct hid_device *hid) -{ - struct axff_device *axff; - struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); - struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int field_count = 0; - int i, j; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output reports found\n"); - return -ENODEV; - } - - report = list_first_entry(report_list, struct hid_report, list); - for (i = 0; i < report->maxfield; i++) { - for (j = 0; j < report->field[i]->report_count; j++) { - report->field[i]->value[j] = 0x00; - field_count++; - } - } - - if (field_count < 4) { - hid_err(hid, "not enough fields in the report: %d\n", - field_count); - return -ENODEV; - } - - axff = kzalloc(sizeof(struct axff_device), GFP_KERNEL); - if (!axff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, axff, axff_play); - if (error) - goto err_free_mem; - - axff->report = report; - usbhid_submit_report(hid, axff->report, USB_DIR_OUT); - - hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n"); - - return 0; - -err_free_mem: - kfree(axff); - return error; -} -#else -static inline int axff_init(struct hid_device *hid) -{ - return 0; -} -#endif - -static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int error; - - dev_dbg(&hdev->dev, "ACRUX HID hardware probe...\n"); - - error = hid_parse(hdev); - if (error) { - hid_err(hdev, "parse failed\n"); - return error; - } - - error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (error) { - hid_err(hdev, "hw start failed\n"); - return error; - } - - error = axff_init(hdev); - if (error) { - /* - * Do not fail device initialization completely as device - * may still be partially operable, just warn. - */ - hid_warn(hdev, - "Failed to enable force feedback support, error: %d\n", - error); - } - - /* - * We need to start polling device right away, otherwise - * it will go into a coma. - */ - error = hid_hw_open(hdev); - if (error) { - dev_err(&hdev->dev, "hw open failed\n"); - hid_hw_stop(hdev); - return error; - } - - return 0; -} - -static void ax_remove(struct hid_device *hdev) -{ - hid_hw_close(hdev); - hid_hw_stop(hdev); -} - -static const struct hid_device_id ax_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, - { } -}; -MODULE_DEVICE_TABLE(hid, ax_devices); - -static struct hid_driver ax_driver = { - .name = "acrux", - .id_table = ax_devices, - .probe = ax_probe, - .remove = ax_remove, -}; - -static int __init ax_init(void) -{ - return hid_register_driver(&ax_driver); -} - -static void __exit ax_exit(void) -{ - hid_unregister_driver(&ax_driver); -} - -module_init(ax_init); -module_exit(ax_exit); - -MODULE_AUTHOR("Sergei Kolzun"); -MODULE_DESCRIPTION("Force feedback support for ACRUX game controllers"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-belkin.c b/ANDROID_3.4.5/drivers/hid/hid-belkin.c deleted file mode 100644 index a1a765a5..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-belkin.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * HID driver for some belkin "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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" - -#define BELKIN_HIDDEV 0x01 -#define BELKIN_WKBD 0x02 - -#define belkin_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int belkin_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER || - !(quirks & BELKIN_WKBD)) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x03a: belkin_map_key_clear(KEY_SOUND); break; - case 0x03b: belkin_map_key_clear(KEY_CAMERA); break; - case 0x03c: belkin_map_key_clear(KEY_DOCUMENTS); break; - default: - return 0; - } - return 1; -} - -static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - unsigned long quirks = id->driver_data; - int ret; - - hid_set_drvdata(hdev, (void *)quirks); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | - ((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0)); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - return ret; -} - -static const struct hid_device_id belkin_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM), - .driver_data = BELKIN_HIDDEV }, - { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD), - .driver_data = BELKIN_WKBD }, - { } -}; -MODULE_DEVICE_TABLE(hid, belkin_devices); - -static struct hid_driver belkin_driver = { - .name = "belkin", - .id_table = belkin_devices, - .input_mapping = belkin_input_mapping, - .probe = belkin_probe, -}; - -static int __init belkin_init(void) -{ - return hid_register_driver(&belkin_driver); -} - -static void __exit belkin_exit(void) -{ - hid_unregister_driver(&belkin_driver); -} - -module_init(belkin_init); -module_exit(belkin_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-cherry.c b/ANDROID_3.4.5/drivers/hid/hid-cherry.c deleted file mode 100644 index 888ece68..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-cherry.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * HID driver for some cherry "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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" - -/* - * Cherry Cymotion keyboard have an invalid HID report descriptor, - * that needs fixing before we can parse it. - */ -static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { - hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); - rdesc[11] = rdesc[16] = 0xff; - rdesc[12] = rdesc[17] = 0x03; - } - return rdesc; -} - -#define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x301: ch_map_key_clear(KEY_PROG1); break; - case 0x302: ch_map_key_clear(KEY_PROG2); break; - case 0x303: ch_map_key_clear(KEY_PROG3); break; - default: - return 0; - } - - return 1; -} - -static const struct hid_device_id ch_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ch_devices); - -static struct hid_driver ch_driver = { - .name = "cherry", - .id_table = ch_devices, - .report_fixup = ch_report_fixup, - .input_mapping = ch_input_mapping, -}; - -static int __init ch_init(void) -{ - return hid_register_driver(&ch_driver); -} - -static void __exit ch_exit(void) -{ - hid_unregister_driver(&ch_driver); -} - -module_init(ch_init); -module_exit(ch_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-chicony.c b/ANDROID_3.4.5/drivers/hid/hid-chicony.c deleted file mode 100644 index b99af346..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-chicony.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * HID driver for some chicony "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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/input.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) - return 0; - - set_bit(EV_REP, hi->input->evbit); - switch (usage->hid & HID_USAGE) { - case 0xff01: ch_map_key_clear(BTN_1); break; - case 0xff02: ch_map_key_clear(BTN_2); break; - case 0xff03: ch_map_key_clear(BTN_3); break; - case 0xff04: ch_map_key_clear(BTN_4); break; - case 0xff05: ch_map_key_clear(BTN_5); break; - case 0xff06: ch_map_key_clear(BTN_6); break; - case 0xff07: ch_map_key_clear(BTN_7); break; - case 0xff08: ch_map_key_clear(BTN_8); break; - case 0xff09: ch_map_key_clear(BTN_9); break; - case 0xff0a: ch_map_key_clear(BTN_A); break; - case 0xff0b: ch_map_key_clear(BTN_B); break; - case 0x00f1: ch_map_key_clear(KEY_WLAN); break; - case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN); break; - case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP); break; - case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF); break; - case 0x00f7: ch_map_key_clear(KEY_CAMERA); break; - case 0x00f8: ch_map_key_clear(KEY_PROG1); break; - default: - return 0; - } - return 1; -} - -static const struct hid_device_id ch_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ch_devices); - -static struct hid_driver ch_driver = { - .name = "chicony", - .id_table = ch_devices, - .input_mapping = ch_input_mapping, -}; - -static int __init ch_init(void) -{ - return hid_register_driver(&ch_driver); -} - -static void __exit ch_exit(void) -{ - hid_unregister_driver(&ch_driver); -} - -module_init(ch_init); -module_exit(ch_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-core.c b/ANDROID_3.4.5/drivers/hid/hid-core.c deleted file mode 100644 index 4da66b4b..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-core.c +++ /dev/null @@ -1,2254 +0,0 @@ -/* - * HID support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2012 Jiri Kosina - */ - -/* - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/mm.h> -#include <linux/spinlock.h> -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/input.h> -#include <linux/wait.h> -#include <linux/vmalloc.h> -#include <linux/sched.h> -#include <linux/semaphore.h> - -#include <linux/hid.h> -#include <linux/hiddev.h> -#include <linux/hid-debug.h> -#include <linux/hidraw.h> - -#include "hid-ids.h" - -/* - * Version Information - */ - -#define DRIVER_DESC "HID core driver" -#define DRIVER_LICENSE "GPL" - -int hid_debug = 0; -module_param_named(debug, hid_debug, int, 0600); -MODULE_PARM_DESC(debug, "toggle HID debugging messages"); -EXPORT_SYMBOL_GPL(hid_debug); - -static int hid_ignore_special_drivers = 0; -module_param_named(ignore_special_drivers, hid_ignore_special_drivers, int, 0600); -MODULE_PARM_DESC(debug, "Ignore any special drivers and handle all devices by generic driver"); - -/* - * Register a new report for a device. - */ - -struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) -{ - struct hid_report_enum *report_enum = device->report_enum + type; - struct hid_report *report; - - if (report_enum->report_id_hash[id]) - return report_enum->report_id_hash[id]; - - report = kzalloc(sizeof(struct hid_report), GFP_KERNEL); - if (!report) - return NULL; - - if (id != 0) - report_enum->numbered = 1; - - report->id = id; - report->type = type; - report->size = 0; - report->device = device; - report_enum->report_id_hash[id] = report; - - list_add_tail(&report->list, &report_enum->report_list); - - return report; -} -EXPORT_SYMBOL_GPL(hid_register_report); - -/* - * Register a new field for this report. - */ - -static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) -{ - struct hid_field *field; - - if (report->maxfield == HID_MAX_FIELDS) { - hid_err(report->device, "too many fields in report\n"); - return NULL; - } - - field = kzalloc((sizeof(struct hid_field) + - usages * sizeof(struct hid_usage) + - values * sizeof(unsigned)), GFP_KERNEL); - if (!field) - return NULL; - - field->index = report->maxfield++; - report->field[field->index] = field; - field->usage = (struct hid_usage *)(field + 1); - field->value = (s32 *)(field->usage + usages); - field->report = report; - - return field; -} - -/* - * Open a collection. The type/usage is pushed on the stack. - */ - -static int open_collection(struct hid_parser *parser, unsigned type) -{ - struct hid_collection *collection; - unsigned usage; - - usage = parser->local.usage[0]; - - if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { - hid_err(parser->device, "collection stack overflow\n"); - return -1; - } - - if (parser->device->maxcollection == parser->device->collection_size) { - collection = kmalloc(sizeof(struct hid_collection) * - parser->device->collection_size * 2, GFP_KERNEL); - if (collection == NULL) { - hid_err(parser->device, "failed to reallocate collection array\n"); - return -1; - } - memcpy(collection, parser->device->collection, - sizeof(struct hid_collection) * - parser->device->collection_size); - memset(collection + parser->device->collection_size, 0, - sizeof(struct hid_collection) * - parser->device->collection_size); - kfree(parser->device->collection); - parser->device->collection = collection; - parser->device->collection_size *= 2; - } - - parser->collection_stack[parser->collection_stack_ptr++] = - parser->device->maxcollection; - - collection = parser->device->collection + - parser->device->maxcollection++; - collection->type = type; - collection->usage = usage; - collection->level = parser->collection_stack_ptr - 1; - - if (type == HID_COLLECTION_APPLICATION) - parser->device->maxapplication++; - - return 0; -} - -/* - * Close a collection. - */ - -static int close_collection(struct hid_parser *parser) -{ - if (!parser->collection_stack_ptr) { - hid_err(parser->device, "collection stack underflow\n"); - return -1; - } - parser->collection_stack_ptr--; - return 0; -} - -/* - * Climb up the stack, search for the specified collection type - * and return the usage. - */ - -static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) -{ - struct hid_collection *collection = parser->device->collection; - int n; - - for (n = parser->collection_stack_ptr - 1; n >= 0; n--) { - unsigned index = parser->collection_stack[n]; - if (collection[index].type == type) - return collection[index].usage; - } - return 0; /* we know nothing about this usage type */ -} - -/* - * Add a usage to the temporary parser table. - */ - -static int hid_add_usage(struct hid_parser *parser, unsigned usage) -{ - if (parser->local.usage_index >= HID_MAX_USAGES) { - hid_err(parser->device, "usage index exceeded\n"); - return -1; - } - parser->local.usage[parser->local.usage_index] = usage; - parser->local.collection_index[parser->local.usage_index] = - parser->collection_stack_ptr ? - parser->collection_stack[parser->collection_stack_ptr - 1] : 0; - parser->local.usage_index++; - return 0; -} - -/* - * Register a new field for this report. - */ - -static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) -{ - struct hid_report *report; - struct hid_field *field; - int usages; - unsigned offset; - int i; - - report = hid_register_report(parser->device, report_type, parser->global.report_id); - if (!report) { - hid_err(parser->device, "hid_register_report failed\n"); - return -1; - } - - if (parser->global.logical_maximum < parser->global.logical_minimum) { - hid_err(parser->device, "logical range invalid %d %d\n", - parser->global.logical_minimum, parser->global.logical_maximum); - return -1; - } - - offset = report->size; - report->size += parser->global.report_size * parser->global.report_count; - - if (!parser->local.usage_index) /* Ignore padding fields */ - return 0; - - usages = max_t(int, parser->local.usage_index, parser->global.report_count); - - field = hid_register_field(report, usages, parser->global.report_count); - if (!field) - return 0; - - field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); - field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); - field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); - - for (i = 0; i < usages; i++) { - int j = i; - /* Duplicate the last usage we parsed if we have excess values */ - if (i >= parser->local.usage_index) - j = parser->local.usage_index - 1; - field->usage[i].hid = parser->local.usage[j]; - field->usage[i].collection_index = - parser->local.collection_index[j]; - } - - field->maxusage = usages; - field->flags = flags; - field->report_offset = offset; - field->report_type = report_type; - field->report_size = parser->global.report_size; - field->report_count = parser->global.report_count; - field->logical_minimum = parser->global.logical_minimum; - field->logical_maximum = parser->global.logical_maximum; - field->physical_minimum = parser->global.physical_minimum; - field->physical_maximum = parser->global.physical_maximum; - field->unit_exponent = parser->global.unit_exponent; - field->unit = parser->global.unit; - - return 0; -} - -/* - * Read data value from item. - */ - -static u32 item_udata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.u8; - case 2: return item->data.u16; - case 4: return item->data.u32; - } - return 0; -} - -static s32 item_sdata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.s8; - case 2: return item->data.s16; - case 4: return item->data.s32; - } - return 0; -} - -/* - * Process a global item. - */ - -static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) -{ - switch (item->tag) { - case HID_GLOBAL_ITEM_TAG_PUSH: - - if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { - hid_err(parser->device, "global environment stack overflow\n"); - return -1; - } - - memcpy(parser->global_stack + parser->global_stack_ptr++, - &parser->global, sizeof(struct hid_global)); - return 0; - - case HID_GLOBAL_ITEM_TAG_POP: - - if (!parser->global_stack_ptr) { - hid_err(parser->device, "global environment stack underflow\n"); - return -1; - } - - memcpy(&parser->global, parser->global_stack + - --parser->global_stack_ptr, sizeof(struct hid_global)); - return 0; - - case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: - parser->global.usage_page = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: - parser->global.logical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: - if (parser->global.logical_minimum < 0) - parser->global.logical_maximum = item_sdata(item); - else - parser->global.logical_maximum = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: - parser->global.physical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: - if (parser->global.physical_minimum < 0) - parser->global.physical_maximum = item_sdata(item); - else - parser->global.physical_maximum = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: - parser->global.unit_exponent = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT: - parser->global.unit = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: - parser->global.report_size = item_udata(item); - if (parser->global.report_size > 96) { - hid_err(parser->device, "invalid report_size %d\n", - parser->global.report_size); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: - parser->global.report_count = item_udata(item); - if (parser->global.report_count > HID_MAX_USAGES) { - hid_err(parser->device, "invalid report_count %d\n", - parser->global.report_count); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_ID: - parser->global.report_id = item_udata(item); - if (parser->global.report_id == 0) { - hid_err(parser->device, "report_id 0 is invalid\n"); - return -1; - } - return 0; - - default: - hid_err(parser->device, "unknown global tag 0x%x\n", item->tag); - return -1; - } -} - -/* - * Process a local item. - */ - -static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - unsigned n; - - data = item_udata(item); - - switch (item->tag) { - case HID_LOCAL_ITEM_TAG_DELIMITER: - - if (data) { - /* - * We treat items before the first delimiter - * as global to all usage sets (branch 0). - * In the moment we process only these global - * items and the first delimiter set. - */ - if (parser->local.delimiter_depth != 0) { - hid_err(parser->device, "nested delimiters\n"); - return -1; - } - parser->local.delimiter_depth++; - parser->local.delimiter_branch++; - } else { - if (parser->local.delimiter_depth < 1) { - hid_err(parser->device, "bogus close delimiter\n"); - return -1; - } - parser->local.delimiter_depth--; - } - return 1; - - case HID_LOCAL_ITEM_TAG_USAGE: - - if (parser->local.delimiter_branch > 1) { - dbg_hid("alternative usage ignored\n"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - return hid_add_usage(parser, data); - - case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: - - if (parser->local.delimiter_branch > 1) { - dbg_hid("alternative usage ignored\n"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - parser->local.usage_minimum = data; - return 0; - - case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: - - if (parser->local.delimiter_branch > 1) { - dbg_hid("alternative usage ignored\n"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { - dbg_hid("hid_add_usage failed\n"); - return -1; - } - return 0; - - default: - - dbg_hid("unknown local item tag 0x%x\n", item->tag); - return 0; - } - return 0; -} - -/* - * Process a main item. - */ - -static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - int ret; - - data = item_udata(item); - - switch (item->tag) { - case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: - ret = open_collection(parser, data & 0xff); - break; - case HID_MAIN_ITEM_TAG_END_COLLECTION: - ret = close_collection(parser); - break; - case HID_MAIN_ITEM_TAG_INPUT: - ret = hid_add_field(parser, HID_INPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_OUTPUT: - ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_FEATURE: - ret = hid_add_field(parser, HID_FEATURE_REPORT, data); - break; - default: - hid_err(parser->device, "unknown main item tag 0x%x\n", item->tag); - ret = 0; - } - - memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ - - return ret; -} - -/* - * Process a reserved item. - */ - -static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) -{ - dbg_hid("reserved item type, tag 0x%x\n", item->tag); - return 0; -} - -/* - * Free a report and all registered fields. The field->usage and - * field->value table's are allocated behind the field, so we need - * only to free(field) itself. - */ - -static void hid_free_report(struct hid_report *report) -{ - unsigned n; - - for (n = 0; n < report->maxfield; n++) - kfree(report->field[n]); - kfree(report); -} - -/* - * Free a device structure, all reports, and all fields. - */ - -static void hid_device_release(struct device *dev) -{ - struct hid_device *device = container_of(dev, struct hid_device, dev); - unsigned i, j; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - struct hid_report_enum *report_enum = device->report_enum + i; - - for (j = 0; j < 256; j++) { - struct hid_report *report = report_enum->report_id_hash[j]; - if (report) - hid_free_report(report); - } - } - - kfree(device->rdesc); - kfree(device->collection); - kfree(device); -} - -/* - * Fetch a report description item from the data stream. We support long - * items, though they are not used yet. - */ - -static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) -{ - u8 b; - - if ((end - start) <= 0) - return NULL; - - b = *start++; - - item->type = (b >> 2) & 3; - item->tag = (b >> 4) & 15; - - if (item->tag == HID_ITEM_TAG_LONG) { - - item->format = HID_ITEM_FORMAT_LONG; - - if ((end - start) < 2) - return NULL; - - item->size = *start++; - item->tag = *start++; - - if ((end - start) < item->size) - return NULL; - - item->data.longdata = start; - start += item->size; - return start; - } - - item->format = HID_ITEM_FORMAT_SHORT; - item->size = b & 3; - - switch (item->size) { - case 0: - return start; - - case 1: - if ((end - start) < 1) - return NULL; - item->data.u8 = *start++; - return start; - - case 2: - if ((end - start) < 2) - return NULL; - item->data.u16 = get_unaligned_le16(start); - start = (__u8 *)((__le16 *)start + 1); - return start; - - case 3: - item->size++; - if ((end - start) < 4) - return NULL; - item->data.u32 = get_unaligned_le32(start); - start = (__u8 *)((__le32 *)start + 1); - return start; - } - - return NULL; -} - -/** - * hid_parse_report - parse device report - * - * @device: hid device - * @start: report start - * @size: report size - * - * Parse a report description into a hid_device structure. Reports are - * enumerated, fields are attached to these reports. - * 0 returned on success, otherwise nonzero error value. - */ -int hid_parse_report(struct hid_device *device, __u8 *start, - unsigned size) -{ - struct hid_parser *parser; - struct hid_item item; - __u8 *end; - int ret; - static int (*dispatch_type[])(struct hid_parser *parser, - struct hid_item *item) = { - hid_parser_main, - hid_parser_global, - hid_parser_local, - hid_parser_reserved - }; - - if (device->driver->report_fixup) - start = device->driver->report_fixup(device, start, &size); - - device->rdesc = kmemdup(start, size, GFP_KERNEL); - if (device->rdesc == NULL) - return -ENOMEM; - device->rsize = size; - - parser = vzalloc(sizeof(struct hid_parser)); - if (!parser) { - ret = -ENOMEM; - goto err; - } - - parser->device = device; - - end = start + size; - ret = -EINVAL; - while ((start = fetch_item(start, end, &item)) != NULL) { - - if (item.format != HID_ITEM_FORMAT_SHORT) { - hid_err(device, "unexpected long global item\n"); - goto err; - } - - if (dispatch_type[item.type](parser, &item)) { - hid_err(device, "item %u %u %u %u parsing failed\n", - item.format, (unsigned)item.size, - (unsigned)item.type, (unsigned)item.tag); - goto err; - } - - if (start == end) { - if (parser->collection_stack_ptr) { - hid_err(device, "unbalanced collection at end of report description\n"); - goto err; - } - if (parser->local.delimiter_depth) { - hid_err(device, "unbalanced delimiter at end of report description\n"); - goto err; - } - vfree(parser); - return 0; - } - } - - hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); -err: - vfree(parser); - return ret; -} -EXPORT_SYMBOL_GPL(hid_parse_report); - -/* - * Convert a signed n-bit integer to signed 32-bit integer. Common - * cases are done through the compiler, the screwed things has to be - * done by hand. - */ - -static s32 snto32(__u32 value, unsigned n) -{ - switch (n) { - case 8: return ((__s8)value); - case 16: return ((__s16)value); - case 32: return ((__s32)value); - } - return value & (1 << (n - 1)) ? value | (-1 << n) : value; -} - -/* - * Convert a signed 32-bit integer to a signed n-bit integer. - */ - -static u32 s32ton(__s32 value, unsigned n) -{ - s32 a = value >> (n - 1); - if (a && a != -1) - return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; - return value & ((1 << n) - 1); -} - -/* - * Extract/implement a data field from/to a little endian report (bit array). - * - * Code sort-of follows HID spec: - * http://www.usb.org/developers/devclass_docs/HID1_11.pdf - * - * While the USB HID spec allows unlimited length bit fields in "report - * descriptors", most devices never use more than 16 bits. - * One model of UPS is claimed to report "LINEV" as a 32-bit field. - * Search linux-kernel and linux-usb-devel archives for "hid-core extract". - */ - -static __u32 extract(const struct hid_device *hid, __u8 *report, - unsigned offset, unsigned n) -{ - u64 x; - - if (n > 32) - hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n", - n, current->comm); - - report += offset >> 3; /* adjust byte index */ - offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned_le64(report); - x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ - return (u32) x; -} - -/* - * "implement" : set bits in a little endian bit stream. - * Same concepts as "extract" (see comments above). - * The data mangled in the bit stream remains in little endian - * order the whole time. It make more sense to talk about - * endianness of register values by considering a register - * a "cached" copy of the little endiad bit stream. - */ -static void implement(const struct hid_device *hid, __u8 *report, - unsigned offset, unsigned n, __u32 value) -{ - u64 x; - u64 m = (1ULL << n) - 1; - - if (n > 32) - hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", - __func__, n, current->comm); - - if (value > m) - hid_warn(hid, "%s() called with too large value %d! (%s)\n", - __func__, value, current->comm); - WARN_ON(value > m); - value &= m; - - report += offset >> 3; - offset &= 7; - - x = get_unaligned_le64(report); - x &= ~(m << offset); - x |= ((u64)value) << offset; - put_unaligned_le64(x, report); -} - -/* - * Search an array for a value. - */ - -static int search(__s32 *array, __s32 value, unsigned n) -{ - while (n--) { - if (*array++ == value) - return 0; - } - return -1; -} - -/** - * hid_match_report - check if driver's raw_event should be called - * - * @hid: hid device - * @report_type: type to match against - * - * compare hid->driver->report_table->report_type to report->type - */ -static int hid_match_report(struct hid_device *hid, struct hid_report *report) -{ - const struct hid_report_id *id = hid->driver->report_table; - - if (!id) /* NULL means all */ - return 1; - - for (; id->report_type != HID_TERMINATOR; id++) - if (id->report_type == HID_ANY_ID || - id->report_type == report->type) - return 1; - return 0; -} - -/** - * hid_match_usage - check if driver's event should be called - * - * @hid: hid device - * @usage: usage to match against - * - * compare hid->driver->usage_table->usage_{type,code} to - * usage->usage_{type,code} - */ -static int hid_match_usage(struct hid_device *hid, struct hid_usage *usage) -{ - const struct hid_usage_id *id = hid->driver->usage_table; - - if (!id) /* NULL means all */ - return 1; - - for (; id->usage_type != HID_ANY_ID - 1; id++) - if ((id->usage_hid == HID_ANY_ID || - id->usage_hid == usage->hid) && - (id->usage_type == HID_ANY_ID || - id->usage_type == usage->type) && - (id->usage_code == HID_ANY_ID || - id->usage_code == usage->code)) - return 1; - return 0; -} - -static void hid_process_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, int interrupt) -{ - struct hid_driver *hdrv = hid->driver; - int ret; - - hid_dump_input(hid, usage, value); - - if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { - ret = hdrv->event(hid, field, usage, value); - if (ret != 0) { - if (ret < 0) - hid_err(hid, "%s's event failed with %d\n", - hdrv->name, ret); - return; - } - } - - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_hid_event(hid, field, usage, value); - if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); -} - -/* - * Analyse a received field, and fetch the data from it. The field - * content is stored for next report processing (we do differential - * reporting to the layer). - */ - -static void hid_input_field(struct hid_device *hid, struct hid_field *field, - __u8 *data, int interrupt) -{ - unsigned n; - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - __s32 min = field->logical_minimum; - __s32 max = field->logical_maximum; - __s32 *value; - - value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC); - if (!value) - return; - - for (n = 0; n < count; n++) { - - value[n] = min < 0 ? - snto32(extract(hid, data, offset + n * size, size), - size) : - extract(hid, data, offset + n * size, size); - - /* Ignore report if ErrorRollOver */ - if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && - value[n] >= min && value[n] <= max && - field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) - goto exit; - } - - for (n = 0; n < count; n++) { - - if (HID_MAIN_ITEM_VARIABLE & field->flags) { - hid_process_event(hid, field, &field->usage[n], value[n], interrupt); - continue; - } - - if (field->value[n] >= min && field->value[n] <= max - && field->usage[field->value[n] - min].hid - && search(value, field->value[n], count)) - hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); - - if (value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid - && search(field->value, value[n], count)) - hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); - } - - memcpy(field->value, value, count * sizeof(__s32)); -exit: - kfree(value); -} - -/* - * Output the field into the report. - */ - -static void hid_output_field(const struct hid_device *hid, - struct hid_field *field, __u8 *data) -{ - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - unsigned n; - - for (n = 0; n < count; n++) { - if (field->logical_minimum < 0) /* signed values */ - implement(hid, data, offset + n * size, size, - s32ton(field->value[n], size)); - else /* unsigned values */ - implement(hid, data, offset + n * size, size, - field->value[n]); - } -} - -/* - * Create a report. - */ - -void hid_output_report(struct hid_report *report, __u8 *data) -{ - unsigned n; - - if (report->id > 0) - *data++ = report->id; - - memset(data, 0, ((report->size - 1) >> 3) + 1); - for (n = 0; n < report->maxfield; n++) - hid_output_field(report->device, report->field[n], data); -} -EXPORT_SYMBOL_GPL(hid_output_report); - -/* - * Set a field value. The report this field belongs to has to be - * created and transferred to the device, to set this value in the - * device. - */ - -int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) -{ - unsigned size = field->report_size; - - hid_dump_input(field->report->device, field->usage + offset, value); - - if (offset >= field->report_count) { - hid_err(field->report->device, "offset (%d) exceeds report_count (%d)\n", - offset, field->report_count); - return -1; - } - if (field->logical_minimum < 0) { - if (value != snto32(s32ton(value, size), size)) { - hid_err(field->report->device, "value %d is out of range\n", value); - return -1; - } - } - field->value[offset] = value; - return 0; -} -EXPORT_SYMBOL_GPL(hid_set_field); - -static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, - const u8 *data) -{ - struct hid_report *report; - unsigned int n = 0; /* Normally report number is 0 */ - - /* Device uses numbered reports, data[0] is report number */ - if (report_enum->numbered) - n = *data; - - report = report_enum->report_id_hash[n]; - if (report == NULL) - dbg_hid("undefined report_id %u received\n", n); - - return report; -} - -void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, - int interrupt) -{ - struct hid_report_enum *report_enum = hid->report_enum + type; - struct hid_report *report; - unsigned int a; - int rsize, csize = size; - u8 *cdata = data; - - report = hid_get_report(report_enum, data); - if (!report) - return; - - if (report_enum->numbered) { - cdata++; - csize--; - } - - rsize = ((report->size - 1) >> 3) + 1; - - if (rsize > HID_MAX_BUFFER_SIZE) - rsize = HID_MAX_BUFFER_SIZE; - - if (csize < rsize) { - dbg_hid("report %d is too short, (%d < %d)\n", report->id, - csize, rsize); - memset(cdata + csize, 0, rsize - csize); - } - - if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) - hid->hiddev_report_event(hid, report); - if (hid->claimed & HID_CLAIMED_HIDRAW) - hidraw_report_event(hid, data, size); - - for (a = 0; a < report->maxfield; a++) - hid_input_field(hid, report->field[a], cdata, interrupt); - - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_report_event(hid, report); -} -EXPORT_SYMBOL_GPL(hid_report_raw_event); - -/** - * hid_input_report - report data from lower layer (usb, bt...) - * - * @hid: hid device - * @type: HID report type (HID_*_REPORT) - * @data: report contents - * @size: size of data parameter - * @interrupt: distinguish between interrupt and control transfers - * - * This is data entry for lower layers. - */ -int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) -{ - struct hid_report_enum *report_enum; - struct hid_driver *hdrv; - struct hid_report *report; - char *buf; - unsigned int i; - int ret = 0; - - if (!hid) - return -ENODEV; - - if (down_trylock(&hid->driver_lock)) - return -EBUSY; - - if (!hid->driver) { - ret = -ENODEV; - goto unlock; - } - report_enum = hid->report_enum + type; - hdrv = hid->driver; - - if (!size) { - dbg_hid("empty report\n"); - ret = -1; - goto unlock; - } - - buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); - - if (!buf) - goto nomem; - - /* dump the report */ - snprintf(buf, HID_DEBUG_BUFSIZE - 1, - "\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un"); - hid_debug_event(hid, buf); - - for (i = 0; i < size; i++) { - snprintf(buf, HID_DEBUG_BUFSIZE - 1, - " %02x", data[i]); - hid_debug_event(hid, buf); - } - hid_debug_event(hid, "\n"); - kfree(buf); - -nomem: - report = hid_get_report(report_enum, data); - - if (!report) { - ret = -1; - goto unlock; - } - - if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { - ret = hdrv->raw_event(hid, report, data, size); - if (ret != 0) { - ret = ret < 0 ? ret : 0; - goto unlock; - } - } - - hid_report_raw_event(hid, type, data, size, interrupt); - -unlock: - up(&hid->driver_lock); - return ret; -} -EXPORT_SYMBOL_GPL(hid_input_report); - -static bool hid_match_one_id(struct hid_device *hdev, - const struct hid_device_id *id) -{ - return id->bus == hdev->bus && - (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && - (id->product == HID_ANY_ID || id->product == hdev->product); -} - -const struct hid_device_id *hid_match_id(struct hid_device *hdev, - const struct hid_device_id *id) -{ - for (; id->bus; id++) - if (hid_match_one_id(hdev, id)) - return id; - - return NULL; -} - -static const struct hid_device_id hid_hiddev_list[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1) }, - { } -}; - -static bool hid_hiddev(struct hid_device *hdev) -{ - return !!hid_match_id(hdev, hid_hiddev_list); -} - - -static ssize_t -read_report_descriptor(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - - if (off >= hdev->rsize) - return 0; - - if (off + count > hdev->rsize) - count = hdev->rsize - off; - - memcpy(buf, hdev->rdesc + off, count); - - return count; -} - -static struct bin_attribute dev_bin_attr_report_desc = { - .attr = { .name = "report_descriptor", .mode = 0444 }, - .read = read_report_descriptor, - .size = HID_MAX_DESCRIPTOR_SIZE, -}; - -int hid_connect(struct hid_device *hdev, unsigned int connect_mask) -{ - static const char *types[] = { "Device", "Pointer", "Mouse", "Device", - "Joystick", "Gamepad", "Keyboard", "Keypad", - "Multi-Axis Controller" - }; - const char *type, *bus; - char buf[64]; - unsigned int i; - int len; - int ret; - - if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) - connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); - if (hdev->quirks & HID_QUIRK_HIDINPUT_FORCE) - connect_mask |= HID_CONNECT_HIDINPUT_FORCE; - if (hdev->bus != BUS_USB) - connect_mask &= ~HID_CONNECT_HIDDEV; - if (hid_hiddev(hdev)) - connect_mask |= HID_CONNECT_HIDDEV_FORCE; - - if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev, - connect_mask & HID_CONNECT_HIDINPUT_FORCE)) - hdev->claimed |= HID_CLAIMED_INPUT; - if (hdev->quirks & HID_QUIRK_MULTITOUCH) { - /* this device should be handled by hid-multitouch, skip it */ - return -ENODEV; - } - - if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect && - !hdev->hiddev_connect(hdev, - connect_mask & HID_CONNECT_HIDDEV_FORCE)) - hdev->claimed |= HID_CLAIMED_HIDDEV; - if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev)) - hdev->claimed |= HID_CLAIMED_HIDRAW; - - if (!hdev->claimed) { - hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n"); - return -ENODEV; - } - - if ((hdev->claimed & HID_CLAIMED_INPUT) && - (connect_mask & HID_CONNECT_FF) && hdev->ff_init) - hdev->ff_init(hdev); - - len = 0; - if (hdev->claimed & HID_CLAIMED_INPUT) - len += sprintf(buf + len, "input"); - if (hdev->claimed & HID_CLAIMED_HIDDEV) - len += sprintf(buf + len, "%shiddev%d", len ? "," : "", - hdev->minor); - if (hdev->claimed & HID_CLAIMED_HIDRAW) - len += sprintf(buf + len, "%shidraw%d", len ? "," : "", - ((struct hidraw *)hdev->hidraw)->minor); - - type = "Device"; - for (i = 0; i < hdev->maxcollection; i++) { - struct hid_collection *col = &hdev->collection[i]; - if (col->type == HID_COLLECTION_APPLICATION && - (col->usage & HID_USAGE_PAGE) == HID_UP_GENDESK && - (col->usage & 0xffff) < ARRAY_SIZE(types)) { - type = types[col->usage & 0xffff]; - break; - } - } - - switch (hdev->bus) { - case BUS_USB: - bus = "USB"; - break; - case BUS_BLUETOOTH: - bus = "BLUETOOTH"; - break; - default: - bus = "<UNKNOWN>"; - } - - ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc); - if (ret) - hid_warn(hdev, - "can't create sysfs report descriptor attribute err: %d\n", ret); - - hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n", - buf, bus, hdev->version >> 8, hdev->version & 0xff, - type, hdev->name, hdev->phys); - - return 0; -} -EXPORT_SYMBOL_GPL(hid_connect); - -void hid_disconnect(struct hid_device *hdev) -{ - device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc); - if (hdev->claimed & HID_CLAIMED_INPUT) - hidinput_disconnect(hdev); - if (hdev->claimed & HID_CLAIMED_HIDDEV) - hdev->hiddev_disconnect(hdev); - if (hdev->claimed & HID_CLAIMED_HIDRAW) - hidraw_disconnect(hdev); -} -EXPORT_SYMBOL_GPL(hid_disconnect); - -/* a list of devices for which there is a specialized driver on HID bus */ -static const struct hid_device_id hid_have_special_driver[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, - { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, - { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_FRUCTEL, USB_DEVICE_ID_GAMETEL_MT_MODE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, -#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ) - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) }, -#endif - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT780) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT880) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, - - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, - { } -}; - -struct hid_dynid { - struct list_head list; - struct hid_device_id id; -}; - -/** - * store_new_id - add a new HID device ID to this driver and re-probe devices - * @driver: target device driver - * @buf: buffer for scanning device ID data - * @count: input size - * - * Adds a new dynamic hid device ID to this driver, - * and causes the driver to probe for all devices again. - */ -static ssize_t store_new_id(struct device_driver *drv, const char *buf, - size_t count) -{ - struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); - struct hid_dynid *dynid; - __u32 bus, vendor, product; - unsigned long driver_data = 0; - int ret; - - ret = sscanf(buf, "%x %x %x %lx", - &bus, &vendor, &product, &driver_data); - if (ret < 3) - return -EINVAL; - - dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); - if (!dynid) - return -ENOMEM; - - dynid->id.bus = bus; - dynid->id.vendor = vendor; - dynid->id.product = product; - dynid->id.driver_data = driver_data; - - spin_lock(&hdrv->dyn_lock); - list_add_tail(&dynid->list, &hdrv->dyn_list); - spin_unlock(&hdrv->dyn_lock); - - ret = driver_attach(&hdrv->driver); - - return ret ? : count; -} -static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); - -static void hid_free_dynids(struct hid_driver *hdrv) -{ - struct hid_dynid *dynid, *n; - - spin_lock(&hdrv->dyn_lock); - list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) { - list_del(&dynid->list); - kfree(dynid); - } - spin_unlock(&hdrv->dyn_lock); -} - -static const struct hid_device_id *hid_match_device(struct hid_device *hdev, - struct hid_driver *hdrv) -{ - struct hid_dynid *dynid; - - spin_lock(&hdrv->dyn_lock); - list_for_each_entry(dynid, &hdrv->dyn_list, list) { - if (hid_match_one_id(hdev, &dynid->id)) { - spin_unlock(&hdrv->dyn_lock); - return &dynid->id; - } - } - spin_unlock(&hdrv->dyn_lock); - - return hid_match_id(hdev, hdrv->id_table); -} - -static int hid_bus_match(struct device *dev, struct device_driver *drv) -{ - struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - - if ((hdev->quirks & HID_QUIRK_MULTITOUCH) && - !strncmp(hdrv->name, "hid-multitouch", 14)) - return 1; - - if (!hid_match_device(hdev, hdrv)) - return 0; - - /* generic wants all that don't have specialized driver */ - if (!strncmp(hdrv->name, "generic-", 8) && !hid_ignore_special_drivers) - return !hid_match_id(hdev, hid_have_special_driver); - - return 1; -} - -static int hid_device_probe(struct device *dev) -{ - struct hid_driver *hdrv = container_of(dev->driver, - struct hid_driver, driver); - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - const struct hid_device_id *id; - int ret = 0; - - if (down_interruptible(&hdev->driver_lock)) - return -EINTR; - - if (!hdev->driver) { - id = hid_match_device(hdev, hdrv); - if (id == NULL) { - if (!((hdev->quirks & HID_QUIRK_MULTITOUCH) && - !strncmp(hdrv->name, "hid-multitouch", 14))) { - ret = -ENODEV; - goto unlock; - } - } - - hdev->driver = hdrv; - if (hdrv->probe) { - ret = hdrv->probe(hdev, id); - } else { /* default probe */ - ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - } - if (ret) - hdev->driver = NULL; - } -unlock: - up(&hdev->driver_lock); - return ret; -} - -static int hid_device_remove(struct device *dev) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct hid_driver *hdrv; - - if (down_interruptible(&hdev->driver_lock)) - return -EINTR; - - hdrv = hdev->driver; - if (hdrv) { - if (hdrv->remove) - hdrv->remove(hdev); - else /* default remove */ - hid_hw_stop(hdev); - hdev->driver = NULL; - } - - up(&hdev->driver_lock); - return 0; -} - -static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - - if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X", - hdev->bus, hdev->vendor, hdev->product)) - return -ENOMEM; - - if (add_uevent_var(env, "HID_NAME=%s", hdev->name)) - return -ENOMEM; - - if (add_uevent_var(env, "HID_PHYS=%s", hdev->phys)) - return -ENOMEM; - - if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq)) - return -ENOMEM; - - if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X", - hdev->bus, hdev->vendor, hdev->product)) - return -ENOMEM; - - return 0; -} - -static struct bus_type hid_bus_type = { - .name = "hid", - .match = hid_bus_match, - .probe = hid_device_probe, - .remove = hid_device_remove, - .uevent = hid_uevent, -}; - -/* a list of devices that shouldn't be handled by HID core at all */ -static const struct hid_device_id hid_ignore_list[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, - { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, - { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYVOLTAGE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYCURRENT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOTOR) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_ABSESP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_AUTODATABUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0001) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, -#if defined(CONFIG_MOUSE_SYNAPTICS_USB) || defined(CONFIG_MOUSE_SYNAPTICS_USB_MODULE) - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_CPAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_STICK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_COMP_TP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WTP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, -#endif - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, - { } -}; - -/** - * hid_mouse_ignore_list - mouse devices which should not be handled by the hid layer - * - * There are composite devices for which we want to ignore only a certain - * interface. This is a list of devices for which only the mouse interface will - * be ignored. This allows a dedicated driver to take care of the interface. - */ -static const struct hid_device_id hid_mouse_ignore_list[] = { - /* appletouch driver */ - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { } -}; - -static bool hid_ignore(struct hid_device *hdev) -{ - switch (hdev->vendor) { - case USB_VENDOR_ID_CODEMERCS: - /* ignore all Code Mercenaries IOWarrior devices */ - if (hdev->product >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST && - hdev->product <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) - return true; - break; - case USB_VENDOR_ID_LOGITECH: - if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST && - hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST) - return true; - /* - * The Keene FM transmitter USB device has the same USB ID as - * the Logitech AudioHub Speaker, but it should ignore the hid. - * Check if the name is that of the Keene device. - * For reference: the name of the AudioHub is - * "HOLTEK AudioHub Speaker". - */ - if (hdev->product == USB_DEVICE_ID_LOGITECH_AUDIOHUB && - !strcmp(hdev->name, "HOLTEK B-LINK USB Audio ")) - return true; - break; - case USB_VENDOR_ID_SOUNDGRAPH: - if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST && - hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) - return true; - break; - case USB_VENDOR_ID_HANWANG: - if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST && - hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST) - return true; - break; - case USB_VENDOR_ID_JESS: - if (hdev->product == USB_DEVICE_ID_JESS_YUREX && - hdev->type == HID_TYPE_USBNONE) - return true; - break; - } - - if (hdev->type == HID_TYPE_USBMOUSE && - hid_match_id(hdev, hid_mouse_ignore_list)) - return true; - - return !!hid_match_id(hdev, hid_ignore_list); -} - -int hid_add_device(struct hid_device *hdev) -{ - static atomic_t id = ATOMIC_INIT(0); - int ret; - - if (WARN_ON(hdev->status & HID_STAT_ADDED)) - return -EBUSY; - - /* we need to kill them here, otherwise they will stay allocated to - * wait for coming driver */ - if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) - && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE))) - return -ENODEV; - - /* XXX hack, any other cleaner solution after the driver core - * is converted to allow more than 20 bytes as the device name? */ - dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, - hdev->vendor, hdev->product, atomic_inc_return(&id)); - - hid_debug_register(hdev, dev_name(&hdev->dev)); - ret = device_add(&hdev->dev); - if (!ret) - hdev->status |= HID_STAT_ADDED; - else - hid_debug_unregister(hdev); - - return ret; -} -EXPORT_SYMBOL_GPL(hid_add_device); - -/** - * hid_allocate_device - allocate new hid device descriptor - * - * Allocate and initialize hid device, so that hid_destroy_device might be - * used to free it. - * - * New hid_device pointer is returned on success, otherwise ERR_PTR encoded - * error value. - */ -struct hid_device *hid_allocate_device(void) -{ - struct hid_device *hdev; - unsigned int i; - int ret = -ENOMEM; - - hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); - if (hdev == NULL) - return ERR_PTR(ret); - - device_initialize(&hdev->dev); - hdev->dev.release = hid_device_release; - hdev->dev.bus = &hid_bus_type; - - hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS, - sizeof(struct hid_collection), GFP_KERNEL); - if (hdev->collection == NULL) - goto err; - hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS; - - for (i = 0; i < HID_REPORT_TYPES; i++) - INIT_LIST_HEAD(&hdev->report_enum[i].report_list); - - init_waitqueue_head(&hdev->debug_wait); - INIT_LIST_HEAD(&hdev->debug_list); - sema_init(&hdev->driver_lock, 1); - - return hdev; -err: - put_device(&hdev->dev); - return ERR_PTR(ret); -} -EXPORT_SYMBOL_GPL(hid_allocate_device); - -static void hid_remove_device(struct hid_device *hdev) -{ - if (hdev->status & HID_STAT_ADDED) { - device_del(&hdev->dev); - hid_debug_unregister(hdev); - hdev->status &= ~HID_STAT_ADDED; - } -} - -/** - * hid_destroy_device - free previously allocated device - * - * @hdev: hid device - * - * If you allocate hid_device through hid_allocate_device, you should ever - * free by this function. - */ -void hid_destroy_device(struct hid_device *hdev) -{ - hid_remove_device(hdev); - put_device(&hdev->dev); -} -EXPORT_SYMBOL_GPL(hid_destroy_device); - -int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, - const char *mod_name) -{ - int ret; - - hdrv->driver.name = hdrv->name; - hdrv->driver.bus = &hid_bus_type; - hdrv->driver.owner = owner; - hdrv->driver.mod_name = mod_name; - - INIT_LIST_HEAD(&hdrv->dyn_list); - spin_lock_init(&hdrv->dyn_lock); - - ret = driver_register(&hdrv->driver); - if (ret) - return ret; - - ret = driver_create_file(&hdrv->driver, &driver_attr_new_id); - if (ret) - driver_unregister(&hdrv->driver); - - return ret; -} -EXPORT_SYMBOL_GPL(__hid_register_driver); - -void hid_unregister_driver(struct hid_driver *hdrv) -{ - driver_remove_file(&hdrv->driver, &driver_attr_new_id); - driver_unregister(&hdrv->driver); - hid_free_dynids(hdrv); -} -EXPORT_SYMBOL_GPL(hid_unregister_driver); - -int hid_check_keys_pressed(struct hid_device *hid) -{ - struct hid_input *hidinput; - int i; - - if (!(hid->claimed & HID_CLAIMED_INPUT)) - return 0; - - list_for_each_entry(hidinput, &hid->inputs, list) { - for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++) - if (hidinput->input->key[i]) - return 1; - } - - return 0; -} - -EXPORT_SYMBOL_GPL(hid_check_keys_pressed); - -static int __init hid_init(void) -{ - int ret; - - if (hid_debug) - pr_warn("hid_debug is now used solely for parser and driver debugging.\n" - "debugfs is now used for inspecting the device (report descriptor, reports)\n"); - - ret = bus_register(&hid_bus_type); - if (ret) { - pr_err("can't register hid bus\n"); - goto err; - } - - ret = hidraw_init(); - if (ret) - goto err_bus; - - hid_debug_init(); - - return 0; -err_bus: - bus_unregister(&hid_bus_type); -err: - return ret; -} - -static void __exit hid_exit(void) -{ - hid_debug_exit(); - hidraw_exit(); - bus_unregister(&hid_bus_type); -} - -module_init(hid_init); -module_exit(hid_exit); - -MODULE_AUTHOR("Andreas Gal"); -MODULE_AUTHOR("Vojtech Pavlik"); -MODULE_AUTHOR("Jiri Kosina"); -MODULE_LICENSE(DRIVER_LICENSE); - diff --git a/ANDROID_3.4.5/drivers/hid/hid-cypress.c b/ANDROID_3.4.5/drivers/hid/hid-cypress.c deleted file mode 100644 index 2f0be4c6..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-cypress.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * HID driver for some cypress "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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/input.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#define CP_RDESC_SWAPPED_MIN_MAX 0x01 -#define CP_2WHEEL_MOUSE_HACK 0x02 -#define CP_2WHEEL_MOUSE_HACK_ON 0x04 - -/* - * Some USB barcode readers from cypress have usage min and usage max in - * the wrong order - */ -static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - unsigned int i; - - if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) - return rdesc; - - for (i = 0; i < *rsize - 4; i++) - if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { - __u8 tmp; - - rdesc[i] = 0x19; - rdesc[i + 2] = 0x29; - tmp = rdesc[i + 3]; - rdesc[i + 3] = rdesc[i + 1]; - rdesc[i + 1] = tmp; - } - return rdesc; -} - -static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if (!(quirks & CP_2WHEEL_MOUSE_HACK)) - return 0; - - if (usage->type == EV_REL && usage->code == REL_WHEEL) - set_bit(REL_HWHEEL, *bit); - if (usage->hid == 0x00090005) - return -1; - - return 0; -} - -static int cp_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || - !usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK)) - return 0; - - if (usage->hid == 0x00090005) { - if (value) - quirks |= CP_2WHEEL_MOUSE_HACK_ON; - else - quirks &= ~CP_2WHEEL_MOUSE_HACK_ON; - hid_set_drvdata(hdev, (void *)quirks); - return 1; - } - - if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) { - struct input_dev *input = field->hidinput->input; - - input_event(input, usage->type, REL_HWHEEL, value); - return 1; - } - - return 0; -} - -static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - unsigned long quirks = id->driver_data; - int ret; - - hid_set_drvdata(hdev, (void *)quirks); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - return ret; -} - -static const struct hid_device_id cp_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1), - .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2), - .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3), - .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), - .driver_data = CP_2WHEEL_MOUSE_HACK }, - { } -}; -MODULE_DEVICE_TABLE(hid, cp_devices); - -static struct hid_driver cp_driver = { - .name = "cypress", - .id_table = cp_devices, - .report_fixup = cp_report_fixup, - .input_mapped = cp_input_mapped, - .event = cp_event, - .probe = cp_probe, -}; - -static int __init cp_init(void) -{ - return hid_register_driver(&cp_driver); -} - -static void __exit cp_exit(void) -{ - hid_unregister_driver(&cp_driver); -} - -module_init(cp_init); -module_exit(cp_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-debug.c b/ANDROID_3.4.5/drivers/hid/hid-debug.c deleted file mode 100644 index 01dd9a7d..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-debug.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> - * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> - * (c) 2007-2009 Jiri Kosina - * - * HID debugging support - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/sched.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/poll.h> - -#include <linux/hid.h> -#include <linux/hid-debug.h> - -static struct dentry *hid_debug_root; - -struct hid_usage_entry { - unsigned page; - unsigned usage; - const char *description; -}; - -static const struct hid_usage_entry hid_usage_table[] = { - { 0, 0, "Undefined" }, - { 1, 0, "GenericDesktop" }, - {0, 0x01, "Pointer"}, - {0, 0x02, "Mouse"}, - {0, 0x04, "Joystick"}, - {0, 0x05, "GamePad"}, - {0, 0x06, "Keyboard"}, - {0, 0x07, "Keypad"}, - {0, 0x08, "MultiAxis"}, - {0, 0x30, "X"}, - {0, 0x31, "Y"}, - {0, 0x32, "Z"}, - {0, 0x33, "Rx"}, - {0, 0x34, "Ry"}, - {0, 0x35, "Rz"}, - {0, 0x36, "Slider"}, - {0, 0x37, "Dial"}, - {0, 0x38, "Wheel"}, - {0, 0x39, "HatSwitch"}, - {0, 0x3a, "CountedBuffer"}, - {0, 0x3b, "ByteCount"}, - {0, 0x3c, "MotionWakeup"}, - {0, 0x3d, "Start"}, - {0, 0x3e, "Select"}, - {0, 0x40, "Vx"}, - {0, 0x41, "Vy"}, - {0, 0x42, "Vz"}, - {0, 0x43, "Vbrx"}, - {0, 0x44, "Vbry"}, - {0, 0x45, "Vbrz"}, - {0, 0x46, "Vno"}, - {0, 0x80, "SystemControl"}, - {0, 0x81, "SystemPowerDown"}, - {0, 0x82, "SystemSleep"}, - {0, 0x83, "SystemWakeUp"}, - {0, 0x84, "SystemContextMenu"}, - {0, 0x85, "SystemMainMenu"}, - {0, 0x86, "SystemAppMenu"}, - {0, 0x87, "SystemMenuHelp"}, - {0, 0x88, "SystemMenuExit"}, - {0, 0x89, "SystemMenuSelect"}, - {0, 0x8a, "SystemMenuRight"}, - {0, 0x8b, "SystemMenuLeft"}, - {0, 0x8c, "SystemMenuUp"}, - {0, 0x8d, "SystemMenuDown"}, - {0, 0x90, "D-PadUp"}, - {0, 0x91, "D-PadDown"}, - {0, 0x92, "D-PadRight"}, - {0, 0x93, "D-PadLeft"}, - { 2, 0, "Simulation" }, - {0, 0xb0, "Aileron"}, - {0, 0xb1, "AileronTrim"}, - {0, 0xb2, "Anti-Torque"}, - {0, 0xb3, "Autopilot"}, - {0, 0xb4, "Chaff"}, - {0, 0xb5, "Collective"}, - {0, 0xb6, "DiveBrake"}, - {0, 0xb7, "ElectronicCountermeasures"}, - {0, 0xb8, "Elevator"}, - {0, 0xb9, "ElevatorTrim"}, - {0, 0xba, "Rudder"}, - {0, 0xbb, "Throttle"}, - {0, 0xbc, "FlightCommunications"}, - {0, 0xbd, "FlareRelease"}, - {0, 0xbe, "LandingGear"}, - {0, 0xbf, "ToeBrake"}, - { 6, 0, "GenericDeviceControls" }, - {0, 0x20, "BatteryStrength" }, - {0, 0x21, "WirelessChannel" }, - {0, 0x22, "WirelessID" }, - {0, 0x23, "DiscoverWirelessControl" }, - {0, 0x24, "SecurityCodeCharacterEntered" }, - {0, 0x25, "SecurityCodeCharactedErased" }, - {0, 0x26, "SecurityCodeCleared" }, - { 7, 0, "Keyboard" }, - { 8, 0, "LED" }, - {0, 0x01, "NumLock"}, - {0, 0x02, "CapsLock"}, - {0, 0x03, "ScrollLock"}, - {0, 0x04, "Compose"}, - {0, 0x05, "Kana"}, - {0, 0x4b, "GenericIndicator"}, - { 9, 0, "Button" }, - { 10, 0, "Ordinal" }, - { 12, 0, "Consumer" }, - {0, 0x238, "HorizontalWheel"}, - { 13, 0, "Digitizers" }, - {0, 0x01, "Digitizer"}, - {0, 0x02, "Pen"}, - {0, 0x03, "LightPen"}, - {0, 0x04, "TouchScreen"}, - {0, 0x05, "TouchPad"}, - {0, 0x20, "Stylus"}, - {0, 0x21, "Puck"}, - {0, 0x22, "Finger"}, - {0, 0x30, "TipPressure"}, - {0, 0x31, "BarrelPressure"}, - {0, 0x32, "InRange"}, - {0, 0x33, "Touch"}, - {0, 0x34, "UnTouch"}, - {0, 0x35, "Tap"}, - {0, 0x39, "TabletFunctionKey"}, - {0, 0x3a, "ProgramChangeKey"}, - {0, 0x3c, "Invert"}, - {0, 0x42, "TipSwitch"}, - {0, 0x43, "SecondaryTipSwitch"}, - {0, 0x44, "BarrelSwitch"}, - {0, 0x45, "Eraser"}, - {0, 0x46, "TabletPick"}, - {0, 0x47, "Confidence"}, - {0, 0x48, "Width"}, - {0, 0x49, "Height"}, - {0, 0x51, "ContactID"}, - {0, 0x52, "InputMode"}, - {0, 0x53, "DeviceIndex"}, - {0, 0x54, "ContactCount"}, - {0, 0x55, "ContactMaximumNumber"}, - { 15, 0, "PhysicalInterfaceDevice" }, - {0, 0x00, "Undefined"}, - {0, 0x01, "Physical_Interface_Device"}, - {0, 0x20, "Normal"}, - {0, 0x21, "Set_Effect_Report"}, - {0, 0x22, "Effect_Block_Index"}, - {0, 0x23, "Parameter_Block_Offset"}, - {0, 0x24, "ROM_Flag"}, - {0, 0x25, "Effect_Type"}, - {0, 0x26, "ET_Constant_Force"}, - {0, 0x27, "ET_Ramp"}, - {0, 0x28, "ET_Custom_Force_Data"}, - {0, 0x30, "ET_Square"}, - {0, 0x31, "ET_Sine"}, - {0, 0x32, "ET_Triangle"}, - {0, 0x33, "ET_Sawtooth_Up"}, - {0, 0x34, "ET_Sawtooth_Down"}, - {0, 0x40, "ET_Spring"}, - {0, 0x41, "ET_Damper"}, - {0, 0x42, "ET_Inertia"}, - {0, 0x43, "ET_Friction"}, - {0, 0x50, "Duration"}, - {0, 0x51, "Sample_Period"}, - {0, 0x52, "Gain"}, - {0, 0x53, "Trigger_Button"}, - {0, 0x54, "Trigger_Repeat_Interval"}, - {0, 0x55, "Axes_Enable"}, - {0, 0x56, "Direction_Enable"}, - {0, 0x57, "Direction"}, - {0, 0x58, "Type_Specific_Block_Offset"}, - {0, 0x59, "Block_Type"}, - {0, 0x5A, "Set_Envelope_Report"}, - {0, 0x5B, "Attack_Level"}, - {0, 0x5C, "Attack_Time"}, - {0, 0x5D, "Fade_Level"}, - {0, 0x5E, "Fade_Time"}, - {0, 0x5F, "Set_Condition_Report"}, - {0, 0x60, "CP_Offset"}, - {0, 0x61, "Positive_Coefficient"}, - {0, 0x62, "Negative_Coefficient"}, - {0, 0x63, "Positive_Saturation"}, - {0, 0x64, "Negative_Saturation"}, - {0, 0x65, "Dead_Band"}, - {0, 0x66, "Download_Force_Sample"}, - {0, 0x67, "Isoch_Custom_Force_Enable"}, - {0, 0x68, "Custom_Force_Data_Report"}, - {0, 0x69, "Custom_Force_Data"}, - {0, 0x6A, "Custom_Force_Vendor_Defined_Data"}, - {0, 0x6B, "Set_Custom_Force_Report"}, - {0, 0x6C, "Custom_Force_Data_Offset"}, - {0, 0x6D, "Sample_Count"}, - {0, 0x6E, "Set_Periodic_Report"}, - {0, 0x6F, "Offset"}, - {0, 0x70, "Magnitude"}, - {0, 0x71, "Phase"}, - {0, 0x72, "Period"}, - {0, 0x73, "Set_Constant_Force_Report"}, - {0, 0x74, "Set_Ramp_Force_Report"}, - {0, 0x75, "Ramp_Start"}, - {0, 0x76, "Ramp_End"}, - {0, 0x77, "Effect_Operation_Report"}, - {0, 0x78, "Effect_Operation"}, - {0, 0x79, "Op_Effect_Start"}, - {0, 0x7A, "Op_Effect_Start_Solo"}, - {0, 0x7B, "Op_Effect_Stop"}, - {0, 0x7C, "Loop_Count"}, - {0, 0x7D, "Device_Gain_Report"}, - {0, 0x7E, "Device_Gain"}, - {0, 0x7F, "PID_Pool_Report"}, - {0, 0x80, "RAM_Pool_Size"}, - {0, 0x81, "ROM_Pool_Size"}, - {0, 0x82, "ROM_Effect_Block_Count"}, - {0, 0x83, "Simultaneous_Effects_Max"}, - {0, 0x84, "Pool_Alignment"}, - {0, 0x85, "PID_Pool_Move_Report"}, - {0, 0x86, "Move_Source"}, - {0, 0x87, "Move_Destination"}, - {0, 0x88, "Move_Length"}, - {0, 0x89, "PID_Block_Load_Report"}, - {0, 0x8B, "Block_Load_Status"}, - {0, 0x8C, "Block_Load_Success"}, - {0, 0x8D, "Block_Load_Full"}, - {0, 0x8E, "Block_Load_Error"}, - {0, 0x8F, "Block_Handle"}, - {0, 0x90, "PID_Block_Free_Report"}, - {0, 0x91, "Type_Specific_Block_Handle"}, - {0, 0x92, "PID_State_Report"}, - {0, 0x94, "Effect_Playing"}, - {0, 0x95, "PID_Device_Control_Report"}, - {0, 0x96, "PID_Device_Control"}, - {0, 0x97, "DC_Enable_Actuators"}, - {0, 0x98, "DC_Disable_Actuators"}, - {0, 0x99, "DC_Stop_All_Effects"}, - {0, 0x9A, "DC_Device_Reset"}, - {0, 0x9B, "DC_Device_Pause"}, - {0, 0x9C, "DC_Device_Continue"}, - {0, 0x9F, "Device_Paused"}, - {0, 0xA0, "Actuators_Enabled"}, - {0, 0xA4, "Safety_Switch"}, - {0, 0xA5, "Actuator_Override_Switch"}, - {0, 0xA6, "Actuator_Power"}, - {0, 0xA7, "Start_Delay"}, - {0, 0xA8, "Parameter_Block_Size"}, - {0, 0xA9, "Device_Managed_Pool"}, - {0, 0xAA, "Shared_Parameter_Blocks"}, - {0, 0xAB, "Create_New_Effect_Report"}, - {0, 0xAC, "RAM_Pool_Available"}, - { 0x84, 0, "Power Device" }, - { 0x84, 0x02, "PresentStatus" }, - { 0x84, 0x03, "ChangeStatus" }, - { 0x84, 0x04, "UPS" }, - { 0x84, 0x05, "PowerSupply" }, - { 0x84, 0x10, "BatterySystem" }, - { 0x84, 0x11, "BatterySystemID" }, - { 0x84, 0x12, "Battery" }, - { 0x84, 0x13, "BatteryID" }, - { 0x84, 0x14, "Charger" }, - { 0x84, 0x15, "ChargerID" }, - { 0x84, 0x16, "PowerConverter" }, - { 0x84, 0x17, "PowerConverterID" }, - { 0x84, 0x18, "OutletSystem" }, - { 0x84, 0x19, "OutletSystemID" }, - { 0x84, 0x1a, "Input" }, - { 0x84, 0x1b, "InputID" }, - { 0x84, 0x1c, "Output" }, - { 0x84, 0x1d, "OutputID" }, - { 0x84, 0x1e, "Flow" }, - { 0x84, 0x1f, "FlowID" }, - { 0x84, 0x20, "Outlet" }, - { 0x84, 0x21, "OutletID" }, - { 0x84, 0x22, "Gang" }, - { 0x84, 0x24, "PowerSummary" }, - { 0x84, 0x25, "PowerSummaryID" }, - { 0x84, 0x30, "Voltage" }, - { 0x84, 0x31, "Current" }, - { 0x84, 0x32, "Frequency" }, - { 0x84, 0x33, "ApparentPower" }, - { 0x84, 0x35, "PercentLoad" }, - { 0x84, 0x40, "ConfigVoltage" }, - { 0x84, 0x41, "ConfigCurrent" }, - { 0x84, 0x43, "ConfigApparentPower" }, - { 0x84, 0x53, "LowVoltageTransfer" }, - { 0x84, 0x54, "HighVoltageTransfer" }, - { 0x84, 0x56, "DelayBeforeStartup" }, - { 0x84, 0x57, "DelayBeforeShutdown" }, - { 0x84, 0x58, "Test" }, - { 0x84, 0x5a, "AudibleAlarmControl" }, - { 0x84, 0x60, "Present" }, - { 0x84, 0x61, "Good" }, - { 0x84, 0x62, "InternalFailure" }, - { 0x84, 0x65, "Overload" }, - { 0x84, 0x66, "OverCharged" }, - { 0x84, 0x67, "OverTemperature" }, - { 0x84, 0x68, "ShutdownRequested" }, - { 0x84, 0x69, "ShutdownImminent" }, - { 0x84, 0x6b, "SwitchOn/Off" }, - { 0x84, 0x6c, "Switchable" }, - { 0x84, 0x6d, "Used" }, - { 0x84, 0x6e, "Boost" }, - { 0x84, 0x73, "CommunicationLost" }, - { 0x84, 0xfd, "iManufacturer" }, - { 0x84, 0xfe, "iProduct" }, - { 0x84, 0xff, "iSerialNumber" }, - { 0x85, 0, "Battery System" }, - { 0x85, 0x01, "SMBBatteryMode" }, - { 0x85, 0x02, "SMBBatteryStatus" }, - { 0x85, 0x03, "SMBAlarmWarning" }, - { 0x85, 0x04, "SMBChargerMode" }, - { 0x85, 0x05, "SMBChargerStatus" }, - { 0x85, 0x06, "SMBChargerSpecInfo" }, - { 0x85, 0x07, "SMBSelectorState" }, - { 0x85, 0x08, "SMBSelectorPresets" }, - { 0x85, 0x09, "SMBSelectorInfo" }, - { 0x85, 0x29, "RemainingCapacityLimit" }, - { 0x85, 0x2c, "CapacityMode" }, - { 0x85, 0x42, "BelowRemainingCapacityLimit" }, - { 0x85, 0x44, "Charging" }, - { 0x85, 0x45, "Discharging" }, - { 0x85, 0x4b, "NeedReplacement" }, - { 0x85, 0x66, "RemainingCapacity" }, - { 0x85, 0x68, "RunTimeToEmpty" }, - { 0x85, 0x6a, "AverageTimeToFull" }, - { 0x85, 0x83, "DesignCapacity" }, - { 0x85, 0x85, "ManufacturerDate" }, - { 0x85, 0x89, "iDeviceChemistry" }, - { 0x85, 0x8b, "Rechargeable" }, - { 0x85, 0x8f, "iOEMInformation" }, - { 0x85, 0x8d, "CapacityGranularity1" }, - { 0x85, 0xd0, "ACPresent" }, - /* pages 0xff00 to 0xffff are vendor-specific */ - { 0xffff, 0, "Vendor-specific-FF" }, - { 0, 0, NULL } -}; - -/* Either output directly into simple seq_file, or (if f == NULL) - * allocate a separate buffer that will then be passed to the 'events' - * ringbuffer. - * - * This is because these functions can be called both for "one-shot" - * "rdesc" while resolving, or for blocking "events". - * - * This holds both for resolv_usage_page() and hid_resolv_usage(). - */ -static char *resolv_usage_page(unsigned page, struct seq_file *f) { - const struct hid_usage_entry *p; - char *buf = NULL; - - if (!f) { - buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); - if (!buf) - return ERR_PTR(-ENOMEM); - } - - for (p = hid_usage_table; p->description; p++) - if (p->page == page) { - if (!f) { - snprintf(buf, HID_DEBUG_BUFSIZE, "%s", - p->description); - return buf; - } - else { - seq_printf(f, "%s", p->description); - return NULL; - } - } - if (!f) - snprintf(buf, HID_DEBUG_BUFSIZE, "%04x", page); - else - seq_printf(f, "%04x", page); - return buf; -} - -char *hid_resolv_usage(unsigned usage, struct seq_file *f) { - const struct hid_usage_entry *p; - char *buf = NULL; - int len = 0; - - buf = resolv_usage_page(usage >> 16, f); - if (IS_ERR(buf)) { - pr_err("error allocating HID debug buffer\n"); - return NULL; - } - - - if (!f) { - len = strlen(buf); - snprintf(buf+len, max(0, HID_DEBUG_BUFSIZE - len), "."); - len++; - } - else { - seq_printf(f, "."); - } - for (p = hid_usage_table; p->description; p++) - if (p->page == (usage >> 16)) { - for(++p; p->description && p->usage != 0; p++) - if (p->usage == (usage & 0xffff)) { - if (!f) - snprintf(buf + len, - max(0,HID_DEBUG_BUFSIZE - len - 1), - "%s", p->description); - else - seq_printf(f, - "%s", - p->description); - return buf; - } - break; - } - if (!f) - snprintf(buf + len, max(0, HID_DEBUG_BUFSIZE - len - 1), - "%04x", usage & 0xffff); - else - seq_printf(f, "%04x", usage & 0xffff); - return buf; -} -EXPORT_SYMBOL_GPL(hid_resolv_usage); - -static void tab(int n, struct seq_file *f) { - seq_printf(f, "%*s", n, ""); -} - -void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) { - int j; - - if (field->physical) { - tab(n, f); - seq_printf(f, "Physical("); - hid_resolv_usage(field->physical, f); seq_printf(f, ")\n"); - } - if (field->logical) { - tab(n, f); - seq_printf(f, "Logical("); - hid_resolv_usage(field->logical, f); seq_printf(f, ")\n"); - } - if (field->application) { - tab(n, f); - seq_printf(f, "Application("); - hid_resolv_usage(field->application, f); seq_printf(f, ")\n"); - } - tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage); - for (j = 0; j < field->maxusage; j++) { - tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n"); - } - if (field->logical_minimum != field->logical_maximum) { - tab(n, f); seq_printf(f, "Logical Minimum(%d)\n", field->logical_minimum); - tab(n, f); seq_printf(f, "Logical Maximum(%d)\n", field->logical_maximum); - } - if (field->physical_minimum != field->physical_maximum) { - tab(n, f); seq_printf(f, "Physical Minimum(%d)\n", field->physical_minimum); - tab(n, f); seq_printf(f, "Physical Maximum(%d)\n", field->physical_maximum); - } - if (field->unit_exponent) { - tab(n, f); seq_printf(f, "Unit Exponent(%d)\n", field->unit_exponent); - } - if (field->unit) { - static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; - static const char *units[5][8] = { - { "None", "None", "None", "None", "None", "None", "None", "None" }, - { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, - { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, - { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }, - { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" } - }; - - int i; - int sys; - __u32 data = field->unit; - - /* First nibble tells us which system we're in. */ - sys = data & 0xf; - data >>= 4; - - if(sys > 4) { - tab(n, f); seq_printf(f, "Unit(Invalid)\n"); - } - else { - int earlier_unit = 0; - - tab(n, f); seq_printf(f, "Unit(%s : ", systems[sys]); - - for (i=1 ; i<sizeof(__u32)*2 ; i++) { - char nibble = data & 0xf; - data >>= 4; - if (nibble != 0) { - if(earlier_unit++ > 0) - seq_printf(f, "*"); - seq_printf(f, "%s", units[sys][i]); - if(nibble != 1) { - /* This is a _signed_ nibble(!) */ - - int val = nibble & 0x7; - if(nibble & 0x08) - val = -((0x7 & ~val) +1); - seq_printf(f, "^%d", val); - } - } - } - seq_printf(f, ")\n"); - } - } - tab(n, f); seq_printf(f, "Report Size(%u)\n", field->report_size); - tab(n, f); seq_printf(f, "Report Count(%u)\n", field->report_count); - tab(n, f); seq_printf(f, "Report Offset(%u)\n", field->report_offset); - - tab(n, f); seq_printf(f, "Flags( "); - j = field->flags; - seq_printf(f, "%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); - seq_printf(f, "%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); - seq_printf(f, "%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); - seq_printf(f, "%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); - seq_printf(f, ")\n"); -} -EXPORT_SYMBOL_GPL(hid_dump_field); - -void hid_dump_device(struct hid_device *device, struct seq_file *f) -{ - struct hid_report_enum *report_enum; - struct hid_report *report; - struct list_head *list; - unsigned i,k; - static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - report_enum = device->report_enum + i; - list = report_enum->report_list.next; - while (list != &report_enum->report_list) { - report = (struct hid_report *) list; - tab(2, f); - seq_printf(f, "%s", table[i]); - if (report->id) - seq_printf(f, "(%d)", report->id); - seq_printf(f, "[%s]", table[report->type]); - seq_printf(f, "\n"); - for (k = 0; k < report->maxfield; k++) { - tab(4, f); - seq_printf(f, "Field(%d)\n", k); - hid_dump_field(report->field[k], 6, f); - } - list = list->next; - } - } -} -EXPORT_SYMBOL_GPL(hid_dump_device); - -/* enqueue string to 'events' ring buffer */ -void hid_debug_event(struct hid_device *hdev, char *buf) -{ - int i; - struct hid_debug_list *list; - - list_for_each_entry(list, &hdev->debug_list, node) { - for (i = 0; i < strlen(buf); i++) - list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = - buf[i]; - list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; - } - - wake_up_interruptible(&hdev->debug_wait); -} -EXPORT_SYMBOL_GPL(hid_debug_event); - -void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value) -{ - char *buf; - int len; - - buf = hid_resolv_usage(usage->hid, NULL); - if (!buf) - return; - len = strlen(buf); - snprintf(buf + len, HID_DEBUG_BUFSIZE - len - 1, " = %d\n", value); - - hid_debug_event(hdev, buf); - - kfree(buf); - wake_up_interruptible(&hdev->debug_wait); - -} -EXPORT_SYMBOL_GPL(hid_dump_input); - -static const char *events[EV_MAX + 1] = { - [EV_SYN] = "Sync", [EV_KEY] = "Key", - [EV_REL] = "Relative", [EV_ABS] = "Absolute", - [EV_MSC] = "Misc", [EV_LED] = "LED", - [EV_SND] = "Sound", [EV_REP] = "Repeat", - [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", - [EV_FF_STATUS] = "ForceFeedbackStatus", -}; - -static const char *syncs[3] = { - [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", - [SYN_MT_REPORT] = "MT Report", -}; - -static const char *keys[KEY_MAX + 1] = { - [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", - [KEY_1] = "1", [KEY_2] = "2", - [KEY_3] = "3", [KEY_4] = "4", - [KEY_5] = "5", [KEY_6] = "6", - [KEY_7] = "7", [KEY_8] = "8", - [KEY_9] = "9", [KEY_0] = "0", - [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", - [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", - [KEY_Q] = "Q", [KEY_W] = "W", - [KEY_E] = "E", [KEY_R] = "R", - [KEY_T] = "T", [KEY_Y] = "Y", - [KEY_U] = "U", [KEY_I] = "I", - [KEY_O] = "O", [KEY_P] = "P", - [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", - [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", - [KEY_A] = "A", [KEY_S] = "S", - [KEY_D] = "D", [KEY_F] = "F", - [KEY_G] = "G", [KEY_H] = "H", - [KEY_J] = "J", [KEY_K] = "K", - [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", - [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", - [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", - [KEY_Z] = "Z", [KEY_X] = "X", - [KEY_C] = "C", [KEY_V] = "V", - [KEY_B] = "B", [KEY_N] = "N", - [KEY_M] = "M", [KEY_COMMA] = "Comma", - [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", - [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", - [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", - [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", - [KEY_F2] = "F2", [KEY_F3] = "F3", - [KEY_F4] = "F4", [KEY_F5] = "F5", - [KEY_F6] = "F6", [KEY_F7] = "F7", - [KEY_F8] = "F8", [KEY_F9] = "F9", - [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", - [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", - [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", - [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", - [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", - [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", - [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", - [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", - [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", - [KEY_F11] = "F11", [KEY_F12] = "F12", - [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", - [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", - [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", - [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", - [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", - [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", - [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", - [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", - [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", - [KEY_END] = "End", [KEY_DOWN] = "Down", - [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", - [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", - [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", - [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", - [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", - [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", - [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja", - [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", - [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", - [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", - [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", - [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", - [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", - [KEY_FIND] = "Find", [KEY_CUT] = "Cut", - [KEY_HELP] = "Help", [KEY_MENU] = "Menu", - [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", - [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", - [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", - [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", - [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", - [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", - [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", - [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", - [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", - [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", - [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", - [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", - [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", - [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", - [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", - [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", - [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", - [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", - [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", - [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", - [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New", - [KEY_REDO] = "Redo", [KEY_F13] = "F13", - [KEY_F14] = "F14", [KEY_F15] = "F15", - [KEY_F16] = "F16", [KEY_F17] = "F17", - [KEY_F18] = "F18", [KEY_F19] = "F19", - [KEY_F20] = "F20", [KEY_F21] = "F21", - [KEY_F22] = "F22", [KEY_F23] = "F23", - [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", - [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", - [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", - [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", - [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost", - [KEY_PRINT] = "Print", [KEY_HP] = "HP", - [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", - [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", - [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", - [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", - [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", - [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", - [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", - [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", - [BTN_0] = "Btn0", [BTN_1] = "Btn1", - [BTN_2] = "Btn2", [BTN_3] = "Btn3", - [BTN_4] = "Btn4", [BTN_5] = "Btn5", - [BTN_6] = "Btn6", [BTN_7] = "Btn7", - [BTN_8] = "Btn8", [BTN_9] = "Btn9", - [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", - [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", - [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", - [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", - [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", - [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", - [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", - [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", - [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", - [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", - [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", - [BTN_B] = "BtnB", [BTN_C] = "BtnC", - [BTN_X] = "BtnX", [BTN_Y] = "BtnY", - [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", - [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", - [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", - [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", - [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", - [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", - [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", - [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", - [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", - [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", - [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", - [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", - [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", - [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", - [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", - [KEY_OPTION] = "Option", [KEY_INFO] = "Info", - [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", - [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", - [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", - [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", - [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", - [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", - [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", - [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", - [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", - [KEY_TV] = "TV", [KEY_TV2] = "TV2", - [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", - [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", - [KEY_CD] = "CD", [KEY_TAPE] = "Tape", - [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", - [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", - [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", - [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", - [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", - [KEY_LIST] = "List", [KEY_MEMO] = "Memo", - [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", - [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", - [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", - [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", - [KEY_LAST] = "Last", [KEY_AB] = "AB", - [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", - [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", - [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", - [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", - [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", - [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", - [KEY_DEL_LINE] = "DeleteLine", - [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", - [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", - [KEY_DOCUMENTS] = "Documents", [KEY_SPELLCHECK] = "SpellCheck", - [KEY_LOGOFF] = "Logoff", - [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", - [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", - [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", - [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F", - [KEY_FN_S] = "Fn+S", - [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2", - [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4", - [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6", - [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8", - [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10", - [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12", - [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle", - [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", - [KEY_KBDILLUMUP] = "KbdIlluminationUp", - [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", -}; - -static const char *relatives[REL_MAX + 1] = { - [REL_X] = "X", [REL_Y] = "Y", - [REL_Z] = "Z", [REL_RX] = "Rx", - [REL_RY] = "Ry", [REL_RZ] = "Rz", - [REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial", - [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", -}; - -static const char *absolutes[ABS_CNT] = { - [ABS_X] = "X", [ABS_Y] = "Y", - [ABS_Z] = "Z", [ABS_RX] = "Rx", - [ABS_RY] = "Ry", [ABS_RZ] = "Rz", - [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", - [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", - [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", - [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", - [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", - [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", - [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", - [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", - [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth", - [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", - [ABS_MT_TOUCH_MAJOR] = "MTMajor", - [ABS_MT_TOUCH_MINOR] = "MTMinor", - [ABS_MT_WIDTH_MAJOR] = "MTMajorW", - [ABS_MT_WIDTH_MINOR] = "MTMinorW", - [ABS_MT_ORIENTATION] = "MTOrientation", - [ABS_MT_POSITION_X] = "MTPositionX", - [ABS_MT_POSITION_Y] = "MTPositionY", - [ABS_MT_TOOL_TYPE] = "MTToolType", - [ABS_MT_BLOB_ID] = "MTBlobID", -}; - -static const char *misc[MSC_MAX + 1] = { - [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", - [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" -}; - -static const char *leds[LED_MAX + 1] = { - [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", - [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", - [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", - [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", - [LED_MISC] = "Misc", -}; - -static const char *repeats[REP_MAX + 1] = { - [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" -}; - -static const char *sounds[SND_MAX + 1] = { - [SND_CLICK] = "Click", [SND_BELL] = "Bell", - [SND_TONE] = "Tone" -}; - -static const char **names[EV_MAX + 1] = { - [EV_SYN] = syncs, [EV_KEY] = keys, - [EV_REL] = relatives, [EV_ABS] = absolutes, - [EV_MSC] = misc, [EV_LED] = leds, - [EV_SND] = sounds, [EV_REP] = repeats, -}; - -static void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) -{ - seq_printf(f, "%s.%s", events[type] ? events[type] : "?", - names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); -} - -static void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f) -{ - int i, j, k; - struct hid_report *report; - struct hid_usage *usage; - - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { - list_for_each_entry(report, &hid->report_enum[k].report_list, list) { - for (i = 0; i < report->maxfield; i++) { - for ( j = 0; j < report->field[i]->maxusage; j++) { - usage = report->field[i]->usage + j; - hid_resolv_usage(usage->hid, f); - seq_printf(f, " ---> "); - hid_resolv_event(usage->type, usage->code, f); - seq_printf(f, "\n"); - } - } - } - } - -} - - -static int hid_debug_rdesc_show(struct seq_file *f, void *p) -{ - struct hid_device *hdev = f->private; - int i; - - /* dump HID report descriptor */ - for (i = 0; i < hdev->rsize; i++) - seq_printf(f, "%02x ", hdev->rdesc[i]); - seq_printf(f, "\n\n"); - - /* dump parsed data and input mappings */ - hid_dump_device(hdev, f); - seq_printf(f, "\n"); - hid_dump_input_mapping(hdev, f); - - return 0; -} - -static int hid_debug_rdesc_open(struct inode *inode, struct file *file) -{ - return single_open(file, hid_debug_rdesc_show, inode->i_private); -} - -static int hid_debug_events_open(struct inode *inode, struct file *file) -{ - int err = 0; - struct hid_debug_list *list; - - if (!(list = kzalloc(sizeof(struct hid_debug_list), GFP_KERNEL))) { - err = -ENOMEM; - goto out; - } - - if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) { - err = -ENOMEM; - kfree(list); - goto out; - } - list->hdev = (struct hid_device *) inode->i_private; - file->private_data = list; - mutex_init(&list->read_mutex); - - list_add_tail(&list->node, &list->hdev->debug_list); - -out: - return err; -} - -static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct hid_debug_list *list = file->private_data; - int ret = 0, len; - DECLARE_WAITQUEUE(wait, current); - - mutex_lock(&list->read_mutex); - while (ret == 0) { - if (list->head == list->tail) { - add_wait_queue(&list->hdev->debug_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (list->head == list->tail) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - if (!list->hdev || !list->hdev->debug) { - ret = -EIO; - break; - } - - /* allow O_NONBLOCK from other threads */ - mutex_unlock(&list->read_mutex); - schedule(); - mutex_lock(&list->read_mutex); - set_current_state(TASK_INTERRUPTIBLE); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&list->hdev->debug_wait, &wait); - } - - if (ret) - goto out; - - /* pass the ringbuffer contents to userspace */ -copy_rest: - if (list->tail == list->head) - goto out; - if (list->tail > list->head) { - len = list->tail - list->head; - - if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { - ret = -EFAULT; - goto out; - } - ret += len; - list->head += len; - } else { - len = HID_DEBUG_BUFSIZE - list->head; - - if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { - ret = -EFAULT; - goto out; - } - list->head = 0; - ret += len; - goto copy_rest; - } - - } -out: - mutex_unlock(&list->read_mutex); - return ret; -} - -static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait) -{ - struct hid_debug_list *list = file->private_data; - - poll_wait(file, &list->hdev->debug_wait, wait); - if (list->head != list->tail) - return POLLIN | POLLRDNORM; - if (!list->hdev->debug) - return POLLERR | POLLHUP; - return 0; -} - -static int hid_debug_events_release(struct inode *inode, struct file *file) -{ - struct hid_debug_list *list = file->private_data; - - list_del(&list->node); - kfree(list->hid_debug_buf); - kfree(list); - - return 0; -} - -static const struct file_operations hid_debug_rdesc_fops = { - .open = hid_debug_rdesc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations hid_debug_events_fops = { - .owner = THIS_MODULE, - .open = hid_debug_events_open, - .read = hid_debug_events_read, - .poll = hid_debug_events_poll, - .release = hid_debug_events_release, - .llseek = noop_llseek, -}; - - -void hid_debug_register(struct hid_device *hdev, const char *name) -{ - hdev->debug_dir = debugfs_create_dir(name, hid_debug_root); - hdev->debug_rdesc = debugfs_create_file("rdesc", 0400, - hdev->debug_dir, hdev, &hid_debug_rdesc_fops); - hdev->debug_events = debugfs_create_file("events", 0400, - hdev->debug_dir, hdev, &hid_debug_events_fops); - hdev->debug = 1; -} - -void hid_debug_unregister(struct hid_device *hdev) -{ - hdev->debug = 0; - wake_up_interruptible(&hdev->debug_wait); - debugfs_remove(hdev->debug_rdesc); - debugfs_remove(hdev->debug_events); - debugfs_remove(hdev->debug_dir); -} - -void hid_debug_init(void) -{ - hid_debug_root = debugfs_create_dir("hid", NULL); -} - -void hid_debug_exit(void) -{ - debugfs_remove_recursive(hid_debug_root); -} - diff --git a/ANDROID_3.4.5/drivers/hid/hid-dr.c b/ANDROID_3.4.5/drivers/hid/hid-dr.c deleted file mode 100644 index e832f44a..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-dr.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Force feedback support for DragonRise Inc. game controllers - * - * From what I have gathered, these devices are mass produced in China and are - * distributed under several vendors. They often share the same design as - * the original PlayStation DualShock controller. - * - * 0079:0006 "DragonRise Inc. Generic USB Joystick " - * - tested with a Tesun USB-703 game controller. - * - * Copyright (c) 2009 Richard Walmsley <richwalm@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#ifdef CONFIG_DRAGONRISE_FF -#include "usbhid/usbhid.h" - -struct drff_device { - struct hid_report *report; -}; - -static int drff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct drff_device *drff = data; - int strong, weak; - - strong = effect->u.rumble.strong_magnitude; - weak = effect->u.rumble.weak_magnitude; - - dbg_hid("called with 0x%04x 0x%04x", strong, weak); - - if (strong || weak) { - strong = strong * 0xff / 0xffff; - weak = weak * 0xff / 0xffff; - - /* While reverse engineering this device, I found that when - this value is set, it causes the strong rumble to function - at a near maximum speed, so we'll bypass it. */ - if (weak == 0x0a) - weak = 0x0b; - - drff->report->field[0]->value[0] = 0x51; - drff->report->field[0]->value[1] = 0x00; - drff->report->field[0]->value[2] = weak; - drff->report->field[0]->value[4] = strong; - usbhid_submit_report(hid, drff->report, USB_DIR_OUT); - - drff->report->field[0]->value[0] = 0xfa; - drff->report->field[0]->value[1] = 0xfe; - } else { - drff->report->field[0]->value[0] = 0xf3; - drff->report->field[0]->value[1] = 0x00; - } - - drff->report->field[0]->value[2] = 0x00; - drff->report->field[0]->value[4] = 0x00; - dbg_hid("running with 0x%02x 0x%02x", strong, weak); - usbhid_submit_report(hid, drff->report, USB_DIR_OUT); - - return 0; -} - -static int drff_init(struct hid_device *hid) -{ - struct drff_device *drff; - struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output reports found\n"); - return -ENODEV; - } - - report = list_first_entry(report_list, struct hid_report, list); - if (report->maxfield < 1) { - hid_err(hid, "no fields in the report\n"); - return -ENODEV; - } - - if (report->field[0]->report_count < 7) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } - - drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL); - if (!drff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, drff, drff_play); - if (error) { - kfree(drff); - return error; - } - - drff->report = report; - drff->report->field[0]->value[0] = 0xf3; - drff->report->field[0]->value[1] = 0x00; - drff->report->field[0]->value[2] = 0x00; - drff->report->field[0]->value[3] = 0x00; - drff->report->field[0]->value[4] = 0x00; - drff->report->field[0]->value[5] = 0x00; - drff->report->field[0]->value[6] = 0x00; - usbhid_submit_report(hid, drff->report, USB_DIR_OUT); - - hid_info(hid, "Force Feedback for DragonRise Inc. " - "game controllers by Richard Walmsley <richwalm@gmail.com>\n"); - - return 0; -} -#else -static inline int drff_init(struct hid_device *hid) -{ - return 0; -} -#endif - -/* - * The original descriptor of joystick with PID 0x0011, represented by DVTech PC - * JS19. It seems both copied from another device and a result of confusion - * either about the specification or about the program used to create the - * descriptor. In any case, it's a wonder it works on Windows. - * - * Usage Page (Desktop), ; Generic desktop controls (01h) - * Usage (Joystik), ; Joystik (04h, application collection) - * Collection (Application), - * Collection (Logical), - * Report Size (8), - * Report Count (5), - * Logical Minimum (0), - * Logical Maximum (255), - * Physical Minimum (0), - * Physical Maximum (255), - * Usage (X), ; X (30h, dynamic value) - * Usage (X), ; X (30h, dynamic value) - * Usage (X), ; X (30h, dynamic value) - * Usage (X), ; X (30h, dynamic value) - * Usage (Y), ; Y (31h, dynamic value) - * Input (Variable), - * Report Size (4), - * Report Count (1), - * Logical Maximum (7), - * Physical Maximum (315), - * Unit (Degrees), - * Usage (00h), - * Input (Variable, Null State), - * Unit, - * Report Size (1), - * Report Count (10), - * Logical Maximum (1), - * Physical Maximum (1), - * Usage Page (Button), ; Button (09h) - * Usage Minimum (01h), - * Usage Maximum (0Ah), - * Input (Variable), - * Usage Page (FF00h), ; FF00h, vendor-defined - * Report Size (1), - * Report Count (10), - * Logical Maximum (1), - * Physical Maximum (1), - * Usage (01h), - * Input (Variable), - * End Collection, - * Collection (Logical), - * Report Size (8), - * Report Count (4), - * Physical Maximum (255), - * Logical Maximum (255), - * Usage (02h), - * Output (Variable), - * End Collection, - * End Collection - */ - -/* Size of the original descriptor of the PID 0x0011 joystick */ -#define PID0011_RDESC_ORIG_SIZE 101 - -/* Fixed report descriptor for PID 0x011 joystick */ -static __u8 pid0011_rdesc_fixed[] = { - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x04, /* Usage (Joystik), */ - 0xA1, 0x01, /* Collection (Application), */ - 0xA1, 0x02, /* Collection (Logical), */ - 0x14, /* Logical Minimum (0), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x01, /* Input (Constant), */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ - 0x95, 0x02, /* Report Count (2), */ - 0x09, 0x30, /* Usage (X), */ - 0x09, 0x31, /* Usage (Y), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x04, /* Report Count (4), */ - 0x81, 0x01, /* Input (Constant), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x0A, /* Report Count (10), */ - 0x05, 0x09, /* Usage Page (Button), */ - 0x19, 0x01, /* Usage Minimum (01h), */ - 0x29, 0x0A, /* Usage Maximum (0Ah), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x0A, /* Report Count (10), */ - 0x81, 0x01, /* Input (Constant), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - switch (hdev->product) { - case 0x0011: - if (*rsize == PID0011_RDESC_ORIG_SIZE) { - rdesc = pid0011_rdesc_fixed; - *rsize = sizeof(pid0011_rdesc_fixed); - } - break; - } - return rdesc; -} - -static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe..."); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - switch (hdev->product) { - case 0x0006: - ret = drff_init(hdev); - if (ret) { - dev_err(&hdev->dev, "force feedback init failed\n"); - hid_hw_stop(hdev); - goto err; - } - break; - } - - return 0; -err: - return ret; -} - -static const struct hid_device_id dr_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, - { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011), }, - { } -}; -MODULE_DEVICE_TABLE(hid, dr_devices); - -static struct hid_driver dr_driver = { - .name = "dragonrise", - .id_table = dr_devices, - .report_fixup = dr_report_fixup, - .probe = dr_probe, -}; - -static int __init dr_init(void) -{ - return hid_register_driver(&dr_driver); -} - -static void __exit dr_exit(void) -{ - hid_unregister_driver(&dr_driver); -} - -module_init(dr_init); -module_exit(dr_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-elecom.c b/ANDROID_3.4.5/drivers/hid/hid-elecom.c deleted file mode 100644 index 79d0c61e..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-elecom.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * HID driver for Elecom BM084 (bluetooth mouse). - * Removes a non-existing horizontal wheel from - * the HID descriptor. - * (This module is based on "hid-ortek".) - * - * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> - */ - -/* - * 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" - -static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { - hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); - rdesc[47] = 0x00; - } - return rdesc; -} - -static const struct hid_device_id elecom_devices[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084)}, - { } -}; -MODULE_DEVICE_TABLE(hid, elecom_devices); - -static struct hid_driver elecom_driver = { - .name = "elecom", - .id_table = elecom_devices, - .report_fixup = elecom_report_fixup -}; - -static int __init elecom_init(void) -{ - return hid_register_driver(&elecom_driver); -} - -static void __exit elecom_exit(void) -{ - hid_unregister_driver(&elecom_driver); -} - -module_init(elecom_init); -module_exit(elecom_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-emsff.c b/ANDROID_3.4.5/drivers/hid/hid-emsff.c deleted file mode 100644 index 2630d483..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-emsff.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Force feedback support for EMS Trio Linker Plus II - * - * Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.de> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/usb.h> -#include <linux/module.h> - -#include "hid-ids.h" -#include "usbhid/usbhid.h" - -struct emsff_device { - struct hid_report *report; -}; - -static int emsff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct emsff_device *emsff = data; - int weak, strong; - - weak = effect->u.rumble.weak_magnitude; - strong = effect->u.rumble.strong_magnitude; - - dbg_hid("called with 0x%04x 0x%04x\n", strong, weak); - - weak = weak * 0xff / 0xffff; - strong = strong * 0xff / 0xffff; - - emsff->report->field[0]->value[1] = weak; - emsff->report->field[0]->value[2] = strong; - - dbg_hid("running with 0x%02x 0x%02x\n", strong, weak); - usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); - - return 0; -} - -static int emsff_init(struct hid_device *hid) -{ - struct emsff_device *emsff; - struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output reports found\n"); - return -ENODEV; - } - - report = list_first_entry(report_list, struct hid_report, list); - if (report->maxfield < 1) { - hid_err(hid, "no fields in the report\n"); - return -ENODEV; - } - - if (report->field[0]->report_count < 7) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } - - emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL); - if (!emsff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, emsff, emsff_play); - if (error) { - kfree(emsff); - return error; - } - - emsff->report = report; - emsff->report->field[0]->value[0] = 0x01; - emsff->report->field[0]->value[1] = 0x00; - emsff->report->field[0]->value[2] = 0x00; - emsff->report->field[0]->value[3] = 0x00; - emsff->report->field[0]->value[4] = 0x00; - emsff->report->field[0]->value[5] = 0x00; - emsff->report->field[0]->value[6] = 0x00; - usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); - - hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n"); - - return 0; -} - -static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - ret = emsff_init(hdev); - if (ret) { - dev_err(&hdev->dev, "force feedback init failed\n"); - hid_hw_stop(hdev); - goto err; - } - - return 0; -err: - return ret; -} - -static const struct hid_device_id ems_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ems_devices); - -static struct hid_driver ems_driver = { - .name = "hkems", - .id_table = ems_devices, - .probe = ems_probe, -}; - -static int ems_init(void) -{ - return hid_register_driver(&ems_driver); -} - -static void ems_exit(void) -{ - hid_unregister_driver(&ems_driver); -} - -module_init(ems_init); -module_exit(ems_exit); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/drivers/hid/hid-ezkey.c b/ANDROID_3.4.5/drivers/hid/hid-ezkey.c deleted file mode 100644 index ca1163e9..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-ezkey.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * HID driver for some ezkey "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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/input.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#define ez_map_rel(c) hid_map_usage(hi, usage, bit, max, EV_REL, (c)) -#define ez_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c)) - -static int ez_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x230: ez_map_key(BTN_MOUSE); break; - case 0x231: ez_map_rel(REL_WHEEL); break; - /* - * this keyboard has a scrollwheel implemented in - * totally broken way. We map this usage temporarily - * to HWHEEL and handle it in the event quirk handler - */ - case 0x232: ez_map_rel(REL_HWHEEL); break; - default: - return 0; - } - return 1; -} - -static int ez_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || - !usage->type) - return 0; - - /* handle the temporary quirky mapping to HWHEEL */ - if (usage->type == EV_REL && usage->code == REL_HWHEEL) { - struct input_dev *input = field->hidinput->input; - input_event(input, usage->type, REL_WHEEL, -value); - return 1; - } - - return 0; -} - -static const struct hid_device_id ez_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ez_devices); - -static struct hid_driver ez_driver = { - .name = "ezkey", - .id_table = ez_devices, - .input_mapping = ez_input_mapping, - .event = ez_event, -}; - -static int __init ez_init(void) -{ - return hid_register_driver(&ez_driver); -} - -static void __exit ez_exit(void) -{ - hid_unregister_driver(&ez_driver); -} - -module_init(ez_init); -module_exit(ez_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-gaff.c b/ANDROID_3.4.5/drivers/hid/hid-gaff.c deleted file mode 100644 index f1e1bcf6..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-gaff.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Force feedback support for GreenAsia (Product ID 0x12) based devices - * - * The devices are distributed under various names and the same USB device ID - * can be used in many game controllers. - * - * - * 0e8f:0012 "GreenAsia Inc. USB Joystick " - * - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635. - * - * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/hid.h> -#include <linux/module.h> -#include "hid-ids.h" - -#ifdef CONFIG_GREENASIA_FF -#include "usbhid/usbhid.h" - -struct gaff_device { - struct hid_report *report; -}; - -static int hid_gaff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct gaff_device *gaff = data; - int left, right; - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - - dbg_hid("called with 0x%04x 0x%04x", left, right); - - left = left * 0xfe / 0xffff; - right = right * 0xfe / 0xffff; - - gaff->report->field[0]->value[0] = 0x51; - gaff->report->field[0]->value[1] = 0x0; - gaff->report->field[0]->value[2] = right; - gaff->report->field[0]->value[3] = 0; - gaff->report->field[0]->value[4] = left; - gaff->report->field[0]->value[5] = 0; - dbg_hid("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); - - gaff->report->field[0]->value[0] = 0xfa; - gaff->report->field[0]->value[1] = 0xfe; - gaff->report->field[0]->value[2] = 0x0; - gaff->report->field[0]->value[4] = 0x0; - - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); - - return 0; -} - -static int gaff_init(struct hid_device *hid) -{ - struct gaff_device *gaff; - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct list_head *report_ptr = report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output reports found\n"); - return -ENODEV; - } - - report_ptr = report_ptr->next; - - report = list_entry(report_ptr, struct hid_report, list); - if (report->maxfield < 1) { - hid_err(hid, "no fields in the report\n"); - return -ENODEV; - } - - if (report->field[0]->report_count < 6) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } - - gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL); - if (!gaff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, gaff, hid_gaff_play); - if (error) { - kfree(gaff); - return error; - } - - gaff->report = report; - gaff->report->field[0]->value[0] = 0x51; - gaff->report->field[0]->value[1] = 0x00; - gaff->report->field[0]->value[2] = 0x00; - gaff->report->field[0]->value[3] = 0x00; - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); - - gaff->report->field[0]->value[0] = 0xfa; - gaff->report->field[0]->value[1] = 0xfe; - - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); - - hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); - - return 0; -} -#else -static inline int gaff_init(struct hid_device *hdev) -{ - return 0; -} -#endif - -static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - dev_dbg(&hdev->dev, "Greenasia HID hardware probe..."); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - gaff_init(hdev); - - return 0; -err: - return ret; -} - -static const struct hid_device_id ga_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), }, - { } -}; -MODULE_DEVICE_TABLE(hid, ga_devices); - -static struct hid_driver ga_driver = { - .name = "greenasia", - .id_table = ga_devices, - .probe = ga_probe, -}; - -static int __init ga_init(void) -{ - return hid_register_driver(&ga_driver); -} - -static void __exit ga_exit(void) -{ - hid_unregister_driver(&ga_driver); -} - -module_init(ga_init); -module_exit(ga_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-gyration.c b/ANDROID_3.4.5/drivers/hid/hid-gyration.c deleted file mode 100644 index e88b951c..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-gyration.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * HID driver for some gyration "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - * Copyright (c) 2006-2008 Jiri Kosina - */ - -/* - * 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/input.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#define gy_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) - return 0; - - set_bit(EV_REP, hi->input->evbit); - switch (usage->hid & HID_USAGE) { - /* Reported on Gyration MCE Remote */ - case 0x00d: gy_map_key_clear(KEY_HOME); break; - case 0x024: gy_map_key_clear(KEY_DVD); break; - case 0x025: gy_map_key_clear(KEY_PVR); break; - case 0x046: gy_map_key_clear(KEY_MEDIA); break; - case 0x047: gy_map_key_clear(KEY_MP3); break; - case 0x048: gy_map_key_clear(KEY_MEDIA); break; - case 0x049: gy_map_key_clear(KEY_CAMERA); break; - case 0x04a: gy_map_key_clear(KEY_VIDEO); break; - case 0x05a: gy_map_key_clear(KEY_TEXT); break; - case 0x05b: gy_map_key_clear(KEY_RED); break; - case 0x05c: gy_map_key_clear(KEY_GREEN); break; - case 0x05d: gy_map_key_clear(KEY_YELLOW); break; - case 0x05e: gy_map_key_clear(KEY_BLUE); break; - - default: - return 0; - } - return 1; -} - -static int gyration_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - - if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput) - return 0; - - if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK && - (usage->hid & 0xff) == 0x82) { - struct input_dev *input = field->hidinput->input; - input_event(input, usage->type, usage->code, 1); - input_sync(input); - input_event(input, usage->type, usage->code, 0); - input_sync(input); - return 1; - } - - return 0; -} - -static const struct hid_device_id gyration_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, - { } -}; -MODULE_DEVICE_TABLE(hid, gyration_devices); - -static struct hid_driver gyration_driver = { - .name = "gyration", - .id_table = gyration_devices, - .input_mapping = gyration_input_mapping, - .event = gyration_event, -}; - -static int __init gyration_init(void) -{ - return hid_register_driver(&gyration_driver); -} - -static void __exit gyration_exit(void) -{ - hid_unregister_driver(&gyration_driver); -} - -module_init(gyration_init); -module_exit(gyration_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-holtekff.c b/ANDROID_3.4.5/drivers/hid/hid-holtekff.c deleted file mode 100644 index 4e754215..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-holtekff.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Force feedback support for Holtek On Line Grip based gamepads - * - * These include at least a Brazilian "Clone Joypad Super Power Fire" - * which uses vendor ID 0x1241 and identifies as "HOLTEK On Line Grip". - * - * Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "hid-ids.h" - -#ifdef CONFIG_HOLTEK_FF -#include "usbhid/usbhid.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>"); -MODULE_DESCRIPTION("Force feedback support for Holtek On Line Grip based devices"); - -/* - * These commands and parameters are currently known: - * - * byte 0: command id: - * 01 set effect parameters - * 02 play specified effect - * 03 stop specified effect - * 04 stop all effects - * 06 stop all effects - * (the difference between 04 and 06 isn't known; win driver - * sends 06,04 on application init, and 06 otherwise) - * - * Commands 01 and 02 need to be sent as pairs, i.e. you need to send 01 - * before each 02. - * - * The rest of the bytes are parameters. Command 01 takes all of them, and - * commands 02,03 take only the effect id. - * - * byte 1: - * bits 0-3: effect id: - * 1: very strong rumble - * 2: periodic rumble, short intervals - * 3: very strong rumble - * 4: periodic rumble, long intervals - * 5: weak periodic rumble, long intervals - * 6: weak periodic rumble, short intervals - * 7: periodic rumble, short intervals - * 8: strong periodic rumble, short intervals - * 9: very strong rumble - * a: causes an error - * b: very strong periodic rumble, very short intervals - * c-f: nothing - * bit 6: right (weak) motor enabled - * bit 7: left (strong) motor enabled - * - * bytes 2-3: time in milliseconds, big-endian - * bytes 5-6: unknown (win driver seems to use at least 10e0 with effect 1 - * and 0014 with effect 6) - * byte 7: - * bits 0-3: effect magnitude - */ - -#define HOLTEKFF_MSG_LENGTH 7 - -static const u8 start_effect_1[] = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const u8 stop_all4[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const u8 stop_all6[] = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -struct holtekff_device { - struct hid_field *field; -}; - -static void holtekff_send(struct holtekff_device *holtekff, - struct hid_device *hid, - const u8 data[HOLTEKFF_MSG_LENGTH]) -{ - int i; - - for (i = 0; i < HOLTEKFF_MSG_LENGTH; i++) { - holtekff->field->value[i] = data[i]; - } - - dbg_hid("sending %02x %02x %02x %02x %02x %02x %02x\n", data[0], - data[1], data[2], data[3], data[4], data[5], data[6]); - - usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT); -} - -static int holtekff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct holtekff_device *holtekff = data; - int left, right; - /* effect type 1, length 65535 msec */ - u8 buf[HOLTEKFF_MSG_LENGTH] = - { 0x01, 0x01, 0xff, 0xff, 0x10, 0xe0, 0x00 }; - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - dbg_hid("called with 0x%04x 0x%04x\n", left, right); - - if (!left && !right) { - holtekff_send(holtekff, hid, stop_all6); - return 0; - } - - if (left) - buf[1] |= 0x80; - if (right) - buf[1] |= 0x40; - - /* The device takes a single magnitude, so we just sum them up. */ - buf[6] = min(0xf, (left >> 12) + (right >> 12)); - - holtekff_send(holtekff, hid, buf); - holtekff_send(holtekff, hid, start_effect_1); - - return 0; -} - -static int holtekff_init(struct hid_device *hid) -{ - struct holtekff_device *holtekff; - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); - return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 1 || report->field[0]->report_count != 7) { - hid_err(hid, "unexpected output report layout\n"); - return -ENODEV; - } - - holtekff = kzalloc(sizeof(*holtekff), GFP_KERNEL); - if (!holtekff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - holtekff->field = report->field[0]; - - /* initialize the same way as win driver does */ - holtekff_send(holtekff, hid, stop_all4); - holtekff_send(holtekff, hid, stop_all6); - - error = input_ff_create_memless(dev, holtekff, holtekff_play); - if (error) { - kfree(holtekff); - return error; - } - - hid_info(hid, "Force feedback for Holtek On Line Grip based devices by Anssi Hannula <anssi.hannula@iki.fi>\n"); - - return 0; -} -#else -static inline int holtekff_init(struct hid_device *hid) -{ - return 0; -} -#endif - -static int holtek_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - holtekff_init(hdev); - - return 0; -err: - return ret; -} - -static const struct hid_device_id holtek_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, - { } -}; -MODULE_DEVICE_TABLE(hid, holtek_devices); - -static struct hid_driver holtek_driver = { - .name = "holtek", - .id_table = holtek_devices, - .probe = holtek_probe, -}; - -static int __init holtek_init(void) -{ - return hid_register_driver(&holtek_driver); -} - -static void __exit holtek_exit(void) -{ - hid_unregister_driver(&holtek_driver); -} - -module_init(holtek_init); -module_exit(holtek_exit); - diff --git a/ANDROID_3.4.5/drivers/hid/hid-hyperv.c b/ANDROID_3.4.5/drivers/hid/hid-hyperv.c deleted file mode 100644 index 40663247..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-hyperv.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Copyright (c) 2009, Citrix Systems, Inc. - * Copyright (c) 2010, Microsoft Corporation. - * Copyright (c) 2011, Novell Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/completion.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/hiddev.h> -#include <linux/hyperv.h> - - -struct hv_input_dev_info { - unsigned int size; - unsigned short vendor; - unsigned short product; - unsigned short version; - unsigned short reserved[11]; -}; - -/* The maximum size of a synthetic input message. */ -#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16 - -/* - * Current version - * - * History: - * Beta, RC < 2008/1/22 1,0 - * RC > 2008/1/22 2,0 - */ -#define SYNTHHID_INPUT_VERSION_MAJOR 2 -#define SYNTHHID_INPUT_VERSION_MINOR 0 -#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \ - (SYNTHHID_INPUT_VERSION_MAJOR << 16)) - - -#pragma pack(push, 1) -/* - * Message types in the synthetic input protocol - */ -enum synthhid_msg_type { - SYNTH_HID_PROTOCOL_REQUEST, - SYNTH_HID_PROTOCOL_RESPONSE, - SYNTH_HID_INITIAL_DEVICE_INFO, - SYNTH_HID_INITIAL_DEVICE_INFO_ACK, - SYNTH_HID_INPUT_REPORT, - SYNTH_HID_MAX -}; - -/* - * Basic message structures. - */ -struct synthhid_msg_hdr { - enum synthhid_msg_type type; - u32 size; -}; - -struct synthhid_msg { - struct synthhid_msg_hdr header; - char data[1]; /* Enclosed message */ -}; - -union synthhid_version { - struct { - u16 minor_version; - u16 major_version; - }; - u32 version; -}; - -/* - * Protocol messages - */ -struct synthhid_protocol_request { - struct synthhid_msg_hdr header; - union synthhid_version version_requested; -}; - -struct synthhid_protocol_response { - struct synthhid_msg_hdr header; - union synthhid_version version_requested; - unsigned char approved; -}; - -struct synthhid_device_info { - struct synthhid_msg_hdr header; - struct hv_input_dev_info hid_dev_info; - struct hid_descriptor hid_descriptor; -}; - -struct synthhid_device_info_ack { - struct synthhid_msg_hdr header; - unsigned char reserved; -}; - -struct synthhid_input_report { - struct synthhid_msg_hdr header; - char buffer[1]; -}; - -#pragma pack(pop) - -#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) -#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) - - -enum pipe_prot_msg_type { - PIPE_MESSAGE_INVALID, - PIPE_MESSAGE_DATA, - PIPE_MESSAGE_MAXIMUM -}; - - -struct pipe_prt_msg { - enum pipe_prot_msg_type type; - u32 size; - char data[1]; -}; - -struct mousevsc_prt_msg { - enum pipe_prot_msg_type type; - u32 size; - union { - struct synthhid_protocol_request request; - struct synthhid_protocol_response response; - struct synthhid_device_info_ack ack; - }; -}; - -/* - * Represents an mousevsc device - */ -struct mousevsc_dev { - struct hv_device *device; - bool init_complete; - bool connected; - struct mousevsc_prt_msg protocol_req; - struct mousevsc_prt_msg protocol_resp; - /* Synchronize the request/response if needed */ - struct completion wait_event; - int dev_info_status; - - struct hid_descriptor *hid_desc; - unsigned char *report_desc; - u32 report_desc_size; - struct hv_input_dev_info hid_dev_info; - struct hid_device *hid_device; -}; - - -static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device) -{ - struct mousevsc_dev *input_dev; - - input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL); - - if (!input_dev) - return NULL; - - input_dev->device = device; - hv_set_drvdata(device, input_dev); - init_completion(&input_dev->wait_event); - input_dev->init_complete = false; - - return input_dev; -} - -static void mousevsc_free_device(struct mousevsc_dev *device) -{ - kfree(device->hid_desc); - kfree(device->report_desc); - hv_set_drvdata(device->device, NULL); - kfree(device); -} - -static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, - struct synthhid_device_info *device_info) -{ - int ret = 0; - struct hid_descriptor *desc; - struct mousevsc_prt_msg ack; - - input_device->dev_info_status = -ENOMEM; - - input_device->hid_dev_info = device_info->hid_dev_info; - desc = &device_info->hid_descriptor; - if (desc->bLength == 0) - goto cleanup; - - input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); - - if (!input_device->hid_desc) - goto cleanup; - - memcpy(input_device->hid_desc, desc, desc->bLength); - - input_device->report_desc_size = desc->desc[0].wDescriptorLength; - if (input_device->report_desc_size == 0) { - input_device->dev_info_status = -EINVAL; - goto cleanup; - } - - input_device->report_desc = kzalloc(input_device->report_desc_size, - GFP_ATOMIC); - - if (!input_device->report_desc) { - input_device->dev_info_status = -ENOMEM; - goto cleanup; - } - - memcpy(input_device->report_desc, - ((unsigned char *)desc) + desc->bLength, - desc->desc[0].wDescriptorLength); - - /* Send the ack */ - memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); - - ack.type = PIPE_MESSAGE_DATA; - ack.size = sizeof(struct synthhid_device_info_ack); - - ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; - ack.ack.header.size = 1; - ack.ack.reserved = 0; - - ret = vmbus_sendpacket(input_device->device->channel, - &ack, - sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + - sizeof(struct synthhid_device_info_ack), - (unsigned long)&ack, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - - if (!ret) - input_device->dev_info_status = 0; - -cleanup: - complete(&input_device->wait_event); - - return; -} - -static void mousevsc_on_receive(struct hv_device *device, - struct vmpacket_descriptor *packet) -{ - struct pipe_prt_msg *pipe_msg; - struct synthhid_msg *hid_msg; - struct mousevsc_dev *input_dev = hv_get_drvdata(device); - struct synthhid_input_report *input_report; - - pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + - (packet->offset8 << 3)); - - if (pipe_msg->type != PIPE_MESSAGE_DATA) - return; - - hid_msg = (struct synthhid_msg *)pipe_msg->data; - - switch (hid_msg->header.type) { - case SYNTH_HID_PROTOCOL_RESPONSE: - /* - * While it will be impossible for us to protect against - * malicious/buggy hypervisor/host, add a check here to - * ensure we don't corrupt memory. - */ - if ((pipe_msg->size + sizeof(struct pipe_prt_msg) - - sizeof(unsigned char)) - > sizeof(struct mousevsc_prt_msg)) { - WARN_ON(1); - break; - } - - memcpy(&input_dev->protocol_resp, pipe_msg, - pipe_msg->size + sizeof(struct pipe_prt_msg) - - sizeof(unsigned char)); - complete(&input_dev->wait_event); - break; - - case SYNTH_HID_INITIAL_DEVICE_INFO: - WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); - - /* - * Parse out the device info into device attr, - * hid desc and report desc - */ - mousevsc_on_receive_device_info(input_dev, - (struct synthhid_device_info *)pipe_msg->data); - break; - case SYNTH_HID_INPUT_REPORT: - input_report = - (struct synthhid_input_report *)pipe_msg->data; - if (!input_dev->init_complete) - break; - hid_input_report(input_dev->hid_device, - HID_INPUT_REPORT, input_report->buffer, - input_report->header.size, 1); - break; - default: - pr_err("unsupported hid msg type - type %d len %d", - hid_msg->header.type, hid_msg->header.size); - break; - } - -} - -static void mousevsc_on_channel_callback(void *context) -{ - const int packet_size = 0x100; - int ret; - struct hv_device *device = context; - u32 bytes_recvd; - u64 req_id; - struct vmpacket_descriptor *desc; - unsigned char *buffer; - int bufferlen = packet_size; - - buffer = kmalloc(bufferlen, GFP_ATOMIC); - if (!buffer) - return; - - do { - ret = vmbus_recvpacket_raw(device->channel, buffer, - bufferlen, &bytes_recvd, &req_id); - - switch (ret) { - case 0: - if (bytes_recvd <= 0) { - kfree(buffer); - return; - } - desc = (struct vmpacket_descriptor *)buffer; - - switch (desc->type) { - case VM_PKT_COMP: - break; - - case VM_PKT_DATA_INBAND: - mousevsc_on_receive(device, desc); - break; - - default: - pr_err("unhandled packet type %d, tid %llx len %d\n", - desc->type, req_id, bytes_recvd); - break; - } - - break; - - case -ENOBUFS: - kfree(buffer); - /* Handle large packet */ - bufferlen = bytes_recvd; - buffer = kmalloc(bytes_recvd, GFP_ATOMIC); - - if (!buffer) - return; - - break; - } - } while (1); - -} - -static int mousevsc_connect_to_vsp(struct hv_device *device) -{ - int ret = 0; - int t; - struct mousevsc_dev *input_dev = hv_get_drvdata(device); - struct mousevsc_prt_msg *request; - struct mousevsc_prt_msg *response; - - request = &input_dev->protocol_req; - memset(request, 0, sizeof(struct mousevsc_prt_msg)); - - request->type = PIPE_MESSAGE_DATA; - request->size = sizeof(struct synthhid_protocol_request); - request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; - request->request.header.size = sizeof(unsigned int); - request->request.version_requested.version = SYNTHHID_INPUT_VERSION; - - ret = vmbus_sendpacket(device->channel, request, - sizeof(struct pipe_prt_msg) - - sizeof(unsigned char) + - sizeof(struct synthhid_protocol_request), - (unsigned long)request, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret) - goto cleanup; - - t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); - if (!t) { - ret = -ETIMEDOUT; - goto cleanup; - } - - response = &input_dev->protocol_resp; - - if (!response->response.approved) { - pr_err("synthhid protocol request failed (version %d)\n", - SYNTHHID_INPUT_VERSION); - ret = -ENODEV; - goto cleanup; - } - - t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); - if (!t) { - ret = -ETIMEDOUT; - goto cleanup; - } - - /* - * We should have gotten the device attr, hid desc and report - * desc at this point - */ - ret = input_dev->dev_info_status; - -cleanup: - return ret; -} - -static int mousevsc_hid_open(struct hid_device *hid) -{ - return 0; -} - -static int mousevsc_hid_start(struct hid_device *hid) -{ - return 0; -} - -static void mousevsc_hid_close(struct hid_device *hid) -{ -} - -static void mousevsc_hid_stop(struct hid_device *hid) -{ -} - -static struct hid_ll_driver mousevsc_ll_driver = { - .open = mousevsc_hid_open, - .close = mousevsc_hid_close, - .start = mousevsc_hid_start, - .stop = mousevsc_hid_stop, -}; - -static struct hid_driver mousevsc_hid_driver; - -static int mousevsc_probe(struct hv_device *device, - const struct hv_vmbus_device_id *dev_id) -{ - int ret; - struct mousevsc_dev *input_dev; - struct hid_device *hid_dev; - - input_dev = mousevsc_alloc_device(device); - - if (!input_dev) - return -ENOMEM; - - ret = vmbus_open(device->channel, - INPUTVSC_SEND_RING_BUFFER_SIZE, - INPUTVSC_RECV_RING_BUFFER_SIZE, - NULL, - 0, - mousevsc_on_channel_callback, - device - ); - - if (ret) - goto probe_err0; - - ret = mousevsc_connect_to_vsp(device); - - if (ret) - goto probe_err1; - - /* workaround SA-167 */ - if (input_dev->report_desc[14] == 0x25) - input_dev->report_desc[14] = 0x29; - - hid_dev = hid_allocate_device(); - if (IS_ERR(hid_dev)) { - ret = PTR_ERR(hid_dev); - goto probe_err1; - } - - hid_dev->ll_driver = &mousevsc_ll_driver; - hid_dev->driver = &mousevsc_hid_driver; - hid_dev->bus = BUS_VIRTUAL; - hid_dev->vendor = input_dev->hid_dev_info.vendor; - hid_dev->product = input_dev->hid_dev_info.product; - hid_dev->version = input_dev->hid_dev_info.version; - input_dev->hid_device = hid_dev; - - sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); - - ret = hid_add_device(hid_dev); - if (ret) - goto probe_err1; - - ret = hid_parse_report(hid_dev, input_dev->report_desc, - input_dev->report_desc_size); - - if (ret) { - hid_err(hid_dev, "parse failed\n"); - goto probe_err2; - } - - ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); - - if (ret) { - hid_err(hid_dev, "hw start failed\n"); - goto probe_err2; - } - - input_dev->connected = true; - input_dev->init_complete = true; - - return ret; - -probe_err2: - hid_destroy_device(hid_dev); - -probe_err1: - vmbus_close(device->channel); - -probe_err0: - mousevsc_free_device(input_dev); - - return ret; -} - - -static int mousevsc_remove(struct hv_device *dev) -{ - struct mousevsc_dev *input_dev = hv_get_drvdata(dev); - - vmbus_close(dev->channel); - hid_hw_stop(input_dev->hid_device); - hid_destroy_device(input_dev->hid_device); - mousevsc_free_device(input_dev); - - return 0; -} - -static const struct hv_vmbus_device_id id_table[] = { - /* Mouse guid */ - { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, - 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, - { }, -}; - -MODULE_DEVICE_TABLE(vmbus, id_table); - -static struct hv_driver mousevsc_drv = { - .name = KBUILD_MODNAME, - .id_table = id_table, - .probe = mousevsc_probe, - .remove = mousevsc_remove, -}; - -static int __init mousevsc_init(void) -{ - return vmbus_driver_register(&mousevsc_drv); -} - -static void __exit mousevsc_exit(void) -{ - vmbus_driver_unregister(&mousevsc_drv); -} - -MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); -module_init(mousevsc_init); -module_exit(mousevsc_exit); diff --git a/ANDROID_3.4.5/drivers/hid/hid-ids.h b/ANDROID_3.4.5/drivers/hid/hid-ids.h deleted file mode 100644 index e39aecb1..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-ids.h +++ /dev/null @@ -1,797 +0,0 @@ -/* - * USB HID quirks support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - */ - -/* - * 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. - */ - -#ifndef HID_IDS_H_FILE -#define HID_IDS_H_FILE - -#define USB_VENDOR_ID_3M 0x0596 -#define USB_DEVICE_ID_3M1968 0x0500 -#define USB_DEVICE_ID_3M2256 0x0502 -#define USB_DEVICE_ID_3M3266 0x0506 - -#define USB_VENDOR_ID_A4TECH 0x09da -#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 -#define USB_DEVICE_ID_A4TECH_X5_005D 0x000a -#define USB_DEVICE_ID_A4TECH_RP_649 0x001a - -#define USB_VENDOR_ID_AASHIMA 0x06d6 -#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 -#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026 - -#define USB_VENDOR_ID_ACECAD 0x0460 -#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 -#define USB_DEVICE_ID_ACECAD_302 0x0008 - -#define USB_VENDOR_ID_ACRUX 0x1a34 - -#define USB_VENDOR_ID_ACTIONSTAR 0x2101 -#define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011 - -#define USB_VENDOR_ID_ADS_TECH 0x06e1 -#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 - -#define USB_VENDOR_ID_AFATECH 0x15a4 -#define USB_DEVICE_ID_AFATECH_AF9016 0x9016 - -#define USB_VENDOR_ID_AIPTEK 0x08ca -#define USB_DEVICE_ID_AIPTEK_01 0x0001 -#define USB_DEVICE_ID_AIPTEK_10 0x0010 -#define USB_DEVICE_ID_AIPTEK_20 0x0020 -#define USB_DEVICE_ID_AIPTEK_21 0x0021 -#define USB_DEVICE_ID_AIPTEK_22 0x0022 -#define USB_DEVICE_ID_AIPTEK_23 0x0023 -#define USB_DEVICE_ID_AIPTEK_24 0x0024 - -#define USB_VENDOR_ID_AIRCABLE 0x16CA -#define USB_DEVICE_ID_AIRCABLE1 0x1502 - -#define USB_VENDOR_ID_AIREN 0x1a2c -#define USB_DEVICE_ID_AIREN_SLIMPLUS 0x0002 - -#define USB_VENDOR_ID_ALCOR 0x058f -#define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 - -#define USB_VENDOR_ID_ALPS 0x0433 -#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 - -#define USB_VENDOR_ID_APPLE 0x05ac -#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 -#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d -#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e -#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e -#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f -#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 -#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215 -#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216 -#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217 -#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218 -#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219 -#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a -#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b -#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c -#define USB_DEVICE_ID_APPLE_ALU_MINI_ANSI 0x021d -#define USB_DEVICE_ID_APPLE_ALU_MINI_ISO 0x021e -#define USB_DEVICE_ID_APPLE_ALU_MINI_JIS 0x021f -#define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220 -#define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221 -#define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222 -#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 -#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 -#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 -#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229 -#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a -#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e -#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 -#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 -#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 -#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 -#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 -#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 -#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f -#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 -#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 -#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 -#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 -#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 -#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 -#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 -#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 -#define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f -#define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 -#define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 -#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 -#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 -#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 -#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 -#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a -#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b -#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c -#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d -#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 -#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 -#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a -#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b -#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 -#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 - -#define USB_VENDOR_ID_ASUS 0x0486 -#define USB_DEVICE_ID_ASUS_T91MT 0x0185 -#define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 - -#define USB_VENDOR_ID_ASUSTEK 0x0b05 -#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 -#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b - -#define USB_VENDOR_ID_ATEN 0x0557 -#define USB_DEVICE_ID_ATEN_UC100KM 0x2004 -#define USB_DEVICE_ID_ATEN_CS124U 0x2202 -#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 -#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 -#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 - -#define USB_VENDOR_ID_ATMEL 0x03eb -#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c -#define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER 0x2118 - -#define USB_VENDOR_ID_AVERMEDIA 0x07ca -#define USB_DEVICE_ID_AVER_FM_MR800 0xb800 - -#define USB_VENDOR_ID_BELKIN 0x050d -#define USB_DEVICE_ID_FLIP_KVM 0x3201 - -#define USB_VENDOR_ID_BERKSHIRE 0x0c98 -#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 - -#define USB_VENDOR_ID_BTC 0x046e -#define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 -#define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 - -#define USB_VENDOR_ID_CANDO 0x2087 -#define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703 -#define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 -#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02 -#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 -#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 - -#define USB_VENDOR_ID_CH 0x068e -#define USB_DEVICE_ID_CH_PRO_THROTTLE 0x00f1 -#define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 -#define USB_DEVICE_ID_CH_FIGHTERSTICK 0x00f3 -#define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4 -#define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051 -#define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff -#define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK 0x00d3 -#define USB_DEVICE_ID_CH_AXIS_295 0x001c - -#define USB_VENDOR_ID_CHERRY 0x046a -#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 -#define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027 - -#define USB_VENDOR_ID_CHIC 0x05fe -#define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 - -#define USB_VENDOR_ID_CHICONY 0x04f2 -#define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 -#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d -#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 -#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 - -#define USB_VENDOR_ID_CHUNGHWAT 0x2247 -#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 - -#define USB_VENDOR_ID_CIDC 0x1677 - -#define USB_VENDOR_ID_CMEDIA 0x0d8c -#define USB_DEVICE_ID_CM109 0x000e - -#define USB_VENDOR_ID_CODEMERCS 0x07c0 -#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 -#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff - -#define USB_VENDOR_ID_CREATIVELABS 0x041e -#define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 - -#define USB_VENDOR_ID_CVTOUCH 0x1ff7 -#define USB_DEVICE_ID_CVTOUCH_SCREEN 0x0013 - -#define USB_VENDOR_ID_CYGNAL 0x10c4 -#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a - -#define USB_VENDOR_ID_CYPRESS 0x04b4 -#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 -#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 -#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 -#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 -#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 -#define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 -#define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 - -#define USB_VENDOR_ID_DEALEXTREAME 0x10c5 -#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a - -#define USB_VENDOR_ID_DELORME 0x1163 -#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 -#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 - -#define USB_VENDOR_ID_DMI 0x0c0b -#define USB_DEVICE_ID_DMI_ENC 0x5fab - -#define USB_VENDOR_ID_DRAGONRISE 0x0079 - -#define USB_VENDOR_ID_DWAV 0x0eef -#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207 0x7207 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C 0x720c -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224 0x7224 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A 0x722A -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E 0x725e -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262 0x7262 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B 0x726b -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA 0x72aa -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1 0x72a1 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA 0x72fa -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 0x7302 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349 -#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 - -#define USB_VENDOR_ID_ELECOM 0x056e -#define USB_DEVICE_ID_ELECOM_BM084 0x0061 - -#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 - -#define USB_VENDOR_ID_ELO 0x04E7 -#define USB_DEVICE_ID_ELO_TS2515 0x0022 -#define USB_DEVICE_ID_ELO_TS2700 0x0020 - -#define USB_VENDOR_ID_EMS 0x2006 -#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118 - -#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f -#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 - -#define USB_VENDOR_ID_ETT 0x0664 -#define USB_DEVICE_ID_TC5UH 0x0309 -#define USB_DEVICE_ID_TC4UM 0x0306 - -#define USB_VENDOR_ID_ETURBOTOUCH 0x22b9 -#define USB_DEVICE_ID_ETURBOTOUCH 0x0006 - -#define USB_VENDOR_ID_EZKEY 0x0518 -#define USB_DEVICE_ID_BTC_8193 0x0002 - -#define USB_VENDOR_ID_FRUCTEL 0x25B6 -#define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002 - -#define USB_VENDOR_ID_GAMERON 0x0810 -#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 -#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 - -#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc -#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 -#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 -#define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 -#define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 -#define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 -#define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 -#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 -#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 - -#define USB_VENDOR_ID_GOODTOUCH 0x1aad -#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f - -#define USB_VENDOR_ID_GOTOP 0x08f2 -#define USB_DEVICE_ID_SUPER_Q2 0x007f -#define USB_DEVICE_ID_GOGOPEN 0x00ce -#define USB_DEVICE_ID_PENPOWER 0x00f4 - -#define USB_VENDOR_ID_GREENASIA 0x0e8f -#define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013 - -#define USB_VENDOR_ID_GRETAGMACBETH 0x0971 -#define USB_DEVICE_ID_GRETAGMACBETH_HUEY 0x2005 - -#define USB_VENDOR_ID_GRIFFIN 0x077d -#define USB_DEVICE_ID_POWERMATE 0x0410 -#define USB_DEVICE_ID_SOUNDKNOB 0x04AA - -#define USB_VENDOR_ID_GTCO 0x078c -#define USB_DEVICE_ID_GTCO_90 0x0090 -#define USB_DEVICE_ID_GTCO_100 0x0100 -#define USB_DEVICE_ID_GTCO_101 0x0101 -#define USB_DEVICE_ID_GTCO_103 0x0103 -#define USB_DEVICE_ID_GTCO_104 0x0104 -#define USB_DEVICE_ID_GTCO_105 0x0105 -#define USB_DEVICE_ID_GTCO_106 0x0106 -#define USB_DEVICE_ID_GTCO_107 0x0107 -#define USB_DEVICE_ID_GTCO_108 0x0108 -#define USB_DEVICE_ID_GTCO_200 0x0200 -#define USB_DEVICE_ID_GTCO_201 0x0201 -#define USB_DEVICE_ID_GTCO_202 0x0202 -#define USB_DEVICE_ID_GTCO_203 0x0203 -#define USB_DEVICE_ID_GTCO_204 0x0204 -#define USB_DEVICE_ID_GTCO_205 0x0205 -#define USB_DEVICE_ID_GTCO_206 0x0206 -#define USB_DEVICE_ID_GTCO_207 0x0207 -#define USB_DEVICE_ID_GTCO_300 0x0300 -#define USB_DEVICE_ID_GTCO_301 0x0301 -#define USB_DEVICE_ID_GTCO_302 0x0302 -#define USB_DEVICE_ID_GTCO_303 0x0303 -#define USB_DEVICE_ID_GTCO_304 0x0304 -#define USB_DEVICE_ID_GTCO_305 0x0305 -#define USB_DEVICE_ID_GTCO_306 0x0306 -#define USB_DEVICE_ID_GTCO_307 0x0307 -#define USB_DEVICE_ID_GTCO_308 0x0308 -#define USB_DEVICE_ID_GTCO_309 0x0309 -#define USB_DEVICE_ID_GTCO_400 0x0400 -#define USB_DEVICE_ID_GTCO_401 0x0401 -#define USB_DEVICE_ID_GTCO_402 0x0402 -#define USB_DEVICE_ID_GTCO_403 0x0403 -#define USB_DEVICE_ID_GTCO_404 0x0404 -#define USB_DEVICE_ID_GTCO_405 0x0405 -#define USB_DEVICE_ID_GTCO_500 0x0500 -#define USB_DEVICE_ID_GTCO_501 0x0501 -#define USB_DEVICE_ID_GTCO_502 0x0502 -#define USB_DEVICE_ID_GTCO_503 0x0503 -#define USB_DEVICE_ID_GTCO_504 0x0504 -#define USB_DEVICE_ID_GTCO_1000 0x1000 -#define USB_DEVICE_ID_GTCO_1001 0x1001 -#define USB_DEVICE_ID_GTCO_1002 0x1002 -#define USB_DEVICE_ID_GTCO_1003 0x1003 -#define USB_DEVICE_ID_GTCO_1004 0x1004 -#define USB_DEVICE_ID_GTCO_1005 0x1005 -#define USB_DEVICE_ID_GTCO_1006 0x1006 -#define USB_DEVICE_ID_GTCO_1007 0x1007 - -#define USB_VENDOR_ID_GYRATION 0x0c16 -#define USB_DEVICE_ID_GYRATION_REMOTE 0x0002 -#define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 -#define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008 - -#define USB_VENDOR_ID_HANWANG 0x0b57 -#define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 -#define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff - -#define USB_VENDOR_ID_HANVON 0x20b3 -#define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 - -#define USB_VENDOR_ID_HANVON_ALT 0x22ed -#define USB_DEVICE_ID_HANVON_ALT_MULTITOUCH 0x1010 - -#define USB_VENDOR_ID_HAPP 0x078b -#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 -#define USB_DEVICE_ID_UGCI_FLYING 0x0020 -#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 - -#define USB_VENDOR_ID_IDEACOM 0x1cb6 -#define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650 -#define USB_DEVICE_ID_IDEACOM_IDC6651 0x6651 - -#define USB_VENDOR_ID_ILITEK 0x222a -#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 - -#define USB_VENDOR_ID_HOLTEK 0x1241 -#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 - -#define USB_VENDOR_ID_IMATION 0x0718 -#define USB_DEVICE_ID_DISC_STAKKA 0xd000 - -#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 -#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 - -#define USB_VENDOR_ID_JESS 0x0c45 -#define USB_DEVICE_ID_JESS_YUREX 0x1010 - -#define USB_VENDOR_ID_KBGEAR 0x084e -#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 - -#define USB_VENDOR_ID_KENSINGTON 0x047d -#define USB_DEVICE_ID_KS_SLIMBLADE 0x2041 - -#define USB_VENDOR_ID_KWORLD 0x1b80 -#define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 - -#define USB_VENDOR_ID_KEYTOUCH 0x0926 -#define USB_DEVICE_ID_KEYTOUCH_IEC 0x3333 - -#define USB_VENDOR_ID_KYE 0x0458 -#define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 -#define USB_DEVICE_ID_KYE_GPEN_560 0x5003 -#define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 -#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 -#define USB_DEVICE_ID_KYE_EASYPEN_M610X 0x5013 - -#define USB_VENDOR_ID_LABTEC 0x1020 -#define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 - -#define USB_VENDOR_ID_LCPOWER 0x1241 -#define USB_DEVICE_ID_LCPOWER_LC1000 0xf767 - -#define USB_VENDOR_ID_LD 0x0f11 -#define USB_DEVICE_ID_LD_CASSY 0x1000 -#define USB_DEVICE_ID_LD_CASSY2 0x1001 -#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 -#define USB_DEVICE_ID_LD_POCKETCASSY2 0x1011 -#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 -#define USB_DEVICE_ID_LD_MOBILECASSY2 0x1021 -#define USB_DEVICE_ID_LD_MICROCASSYVOLTAGE 0x1031 -#define USB_DEVICE_ID_LD_MICROCASSYCURRENT 0x1032 -#define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033 -#define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035 -#define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038 -#define USB_DEVICE_ID_LD_JWM 0x1080 -#define USB_DEVICE_ID_LD_DMMP 0x1081 -#define USB_DEVICE_ID_LD_UMIP 0x1090 -#define USB_DEVICE_ID_LD_UMIC 0x10A0 -#define USB_DEVICE_ID_LD_UMIB 0x10B0 -#define USB_DEVICE_ID_LD_XRAY 0x1100 -#define USB_DEVICE_ID_LD_XRAY2 0x1101 -#define USB_DEVICE_ID_LD_XRAYCT 0x1110 -#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 -#define USB_DEVICE_ID_LD_MOTOR 0x1210 -#define USB_DEVICE_ID_LD_COM3LAB 0x2000 -#define USB_DEVICE_ID_LD_TELEPORT 0x2010 -#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 -#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 -#define USB_DEVICE_ID_LD_MACHINETEST 0x2040 -#define USB_DEVICE_ID_LD_MOSTANALYSER 0x2050 -#define USB_DEVICE_ID_LD_MOSTANALYSER2 0x2051 -#define USB_DEVICE_ID_LD_ABSESP 0x2060 -#define USB_DEVICE_ID_LD_AUTODATABUS 0x2070 -#define USB_DEVICE_ID_LD_MCT 0x2080 -#define USB_DEVICE_ID_LD_HYBRID 0x2090 -#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 - -#define USB_VENDOR_ID_LG 0x1fd2 -#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 - -#define USB_VENDOR_ID_LOGITECH 0x046d -#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e -#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 -#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 -#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f -#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a -#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 -#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 -#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 -#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 -#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 -#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 -#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287 -#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 -#define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 -#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 -#define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298 -#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 -#define USB_DEVICE_ID_LOGITECH_DFGT_WHEEL 0xc29a -#define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b -#define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c -#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a -#define USB_DEVICE_ID_S510_RECEIVER 0xc50c -#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 -#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 -#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 -#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b -#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532 -#define USB_DEVICE_ID_SPACETRAVELLER 0xc623 -#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 -#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704 -#define USB_DEVICE_ID_DINOVO_EDGE 0xc714 -#define USB_DEVICE_ID_DINOVO_MINI 0xc71f -#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 - -#define USB_VENDOR_ID_LUMIO 0x202e -#define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 -#define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 - -#define USB_VENDOR_ID_MCC 0x09db -#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 -#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a - -#define USB_VENDOR_ID_MGE 0x0463 -#define USB_DEVICE_ID_MGE_UPS 0xffff -#define USB_DEVICE_ID_MGE_UPS1 0x0001 - -#define USB_VENDOR_ID_MICROCHIP 0x04d8 -#define USB_DEVICE_ID_PICKIT1 0x0032 -#define USB_DEVICE_ID_PICKIT2 0x0033 -#define USB_DEVICE_ID_PICOLCD 0xc002 -#define USB_DEVICE_ID_PICOLCD_BOOTLOADER 0xf002 - -#define USB_VENDOR_ID_MICROSOFT 0x045e -#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b -#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d -#define USB_DEVICE_ID_MS_NE4K 0x00db -#define USB_DEVICE_ID_MS_LK6K 0x00f9 -#define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701 -#define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 -#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 -#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c - -#define USB_VENDOR_ID_MOJO 0x8282 -#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 - -#define USB_VENDOR_ID_MONTEREY 0x0566 -#define USB_DEVICE_ID_GENIUS_KB29E 0x3004 - -#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 -#define USB_DEVICE_ID_N_S_HARMONY 0xc359 - -#define USB_VENDOR_ID_NATSU 0x08b7 -#define USB_DEVICE_ID_NATSU_GAMEPAD 0x0001 - -#define USB_VENDOR_ID_NCR 0x0404 -#define USB_DEVICE_ID_NCR_FIRST 0x0300 -#define USB_DEVICE_ID_NCR_LAST 0x03ff - -#define USB_VENDOR_ID_NEC 0x073e -#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 - -#define USB_VENDOR_ID_NEXTWINDOW 0x1926 -#define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 - -#define USB_VENDOR_ID_NINTENDO 0x057e -#define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 - -#define USB_VENDOR_ID_NTRIG 0x1b96 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2 0x0004 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3 0x0005 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4 0x0006 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5 0x0007 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6 0x0008 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7 0x0009 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8 0x000A -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9 0x000B -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10 0x000C -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11 0x000D -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12 0x000E -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13 0x000F -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14 0x0010 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15 0x0011 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16 0x0012 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17 0x0013 -#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014 - -#define USB_VENDOR_ID_ONTRAK 0x0a07 -#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 - -#define USB_VENDOR_ID_ORTEK 0x05a4 -#define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 -#define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 - -#define USB_VENDOR_ID_PANASONIC 0x04da -#define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 -#define USB_DEVICE_ID_PANABOARD_UBT880 0x104d - -#define USB_VENDOR_ID_PANJIT 0x134c - -#define USB_VENDOR_ID_PANTHERLORD 0x0810 -#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 - -#define USB_VENDOR_ID_PENMOUNT 0x14e1 -#define USB_DEVICE_ID_PENMOUNT_PCI 0x3500 - -#define USB_VENDOR_ID_PETALYNX 0x18b1 -#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 - -#define USB_VENDOR_ID_PHILIPS 0x0471 -#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 - -#define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 -#define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff - -#define USB_VENDOR_ID_PIXART 0x093a -#define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN 0x8001 -#define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1 0x8002 -#define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2 0x8003 - -#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 -#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 - -#define USB_VENDOR_ID_POWERCOM 0x0d9f -#define USB_DEVICE_ID_POWERCOM_UPS 0x0002 - -#define USB_VENDOR_ID_PRODIGE 0x05af -#define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 - -#define USB_VENDOR_ID_QUANTA 0x0408 -#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 -#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 -#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 -#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 - -#define USB_VENDOR_ID_ROCCAT 0x1e7d -#define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 -#define USB_DEVICE_ID_ROCCAT_ISKU 0x319c -#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced -#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 -#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 -#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 -#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 - -#define USB_VENDOR_ID_SAITEK 0x06a3 -#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 -#define USB_DEVICE_ID_SAITEK_PS1000 0x0621 - -#define USB_VENDOR_ID_SAMSUNG 0x0419 -#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 -#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 - -#define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f -#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 - -#define USB_VENDOR_ID_SKYCABLE 0x1223 -#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 - -#define USB_VENDOR_ID_SONY 0x054c -#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b -#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 -#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f - -#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 -#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 -#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 - -#define USB_VENDOR_ID_STANTUM 0x1f87 -#define USB_DEVICE_ID_MTP 0x0002 - -#define USB_VENDOR_ID_STANTUM_STM 0x0483 -#define USB_DEVICE_ID_MTP_STM 0x3261 - -#define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403 -#define USB_DEVICE_ID_MTP_SITRONIX 0x5001 - -#define USB_VENDOR_ID_SUN 0x0430 -#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab - -#define USB_VENDOR_ID_SUNPLUS 0x04fc -#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 - -#define USB_VENDOR_ID_SYMBOL 0x05e0 -#define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800 -#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300 - -#define USB_VENDOR_ID_SYNAPTICS 0x06cb -#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 -#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 -#define USB_DEVICE_ID_SYNAPTICS_CPAD 0x0003 -#define USB_DEVICE_ID_SYNAPTICS_TS 0x0006 -#define USB_DEVICE_ID_SYNAPTICS_STICK 0x0007 -#define USB_DEVICE_ID_SYNAPTICS_WP 0x0008 -#define USB_DEVICE_ID_SYNAPTICS_COMP_TP 0x0009 -#define USB_DEVICE_ID_SYNAPTICS_WTP 0x0010 -#define USB_DEVICE_ID_SYNAPTICS_DPAD 0x0013 - -#define USB_VENDOR_ID_THRUSTMASTER 0x044f - -#define USB_VENDOR_ID_TIVO 0x150a -#define USB_DEVICE_ID_TIVO_SLIDE_BT 0x1200 -#define USB_DEVICE_ID_TIVO_SLIDE 0x1201 - -#define USB_VENDOR_ID_TOPSEED 0x0766 -#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 - -#define USB_VENDOR_ID_TOPSEED2 0x1784 -#define USB_DEVICE_ID_TOPSEED2_RF_COMBO 0x0004 -#define USB_DEVICE_ID_TOPSEED2_PERIPAD_701 0x0016 - -#define USB_VENDOR_ID_TOPMAX 0x0663 -#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 - -#define USB_VENDOR_ID_TOUCH_INTL 0x1e5e -#define USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH 0x0313 - -#define USB_VENDOR_ID_TOUCHPACK 0x1bfd -#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 - -#define USB_VENDOR_ID_TURBOX 0x062a -#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 -#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 - -#define USB_VENDOR_ID_TWINHAN 0x6253 -#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 - -#define USB_VENDOR_ID_UCLOGIC 0x5543 -#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 -#define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 -#define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60 0x0064 -#define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 -#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 -#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 -#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 - -#define USB_VENDOR_ID_UNITEC 0x227d -#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 -#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19 0x0a19 - -#define USB_VENDOR_ID_VERNIER 0x08f7 -#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 -#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 -#define USB_DEVICE_ID_VERNIER_SKIP 0x0003 -#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 -#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 - -#define USB_VENDOR_ID_WACOM 0x056a -#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 -#define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0x00BD - -#define USB_VENDOR_ID_WALTOP 0x172f -#define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 -#define USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH 0x0034 -#define USB_DEVICE_ID_WALTOP_Q_PAD 0x0037 -#define USB_DEVICE_ID_WALTOP_PID_0038 0x0038 -#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH 0x0501 -#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500 - -#define USB_VENDOR_ID_WISEGROUP 0x0925 -#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 -#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 -#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 -#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 -#define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888 -#define USB_DEVICE_ID_QUAD_USB_JOYPAD 0x8800 -#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 - -#define USB_VENDOR_ID_WISEGROUP_LTD 0x6666 -#define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677 -#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 -#define USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO 0x8801 -#define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802 -#define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804 - -#define USB_VENDOR_ID_X_TENSIONS 0x1ae7 -#define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 - -#define USB_VENDOR_ID_XAT 0x2505 -#define USB_DEVICE_ID_XAT_CSR 0x0220 - -#define USB_VENDOR_ID_XIROKU 0x1477 -#define USB_DEVICE_ID_XIROKU_SPX 0x1006 -#define USB_DEVICE_ID_XIROKU_MPX 0x1007 -#define USB_DEVICE_ID_XIROKU_CSR 0x100e -#define USB_DEVICE_ID_XIROKU_SPX1 0x1021 -#define USB_DEVICE_ID_XIROKU_CSR1 0x1022 -#define USB_DEVICE_ID_XIROKU_MPX1 0x1023 -#define USB_DEVICE_ID_XIROKU_SPX2 0x1024 -#define USB_DEVICE_ID_XIROKU_CSR2 0x1025 -#define USB_DEVICE_ID_XIROKU_MPX2 0x1026 - -#define USB_VENDOR_ID_YEALINK 0x6993 -#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 - -#define USB_VENDOR_ID_ZEROPLUS 0x0c12 - -#define USB_VENDOR_ID_ZYDACRON 0x13EC -#define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006 - -#define USB_VENDOR_ID_PRIMAX 0x0461 -#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-input.c b/ANDROID_3.4.5/drivers/hid/hid-input.c deleted file mode 100644 index c19bff70..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-input.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Copyright (c) 2000-2001 Vojtech Pavlik - * Copyright (c) 2006-2010 Jiri Kosina - * - * HID to Linux Input mapping - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/kernel.h> - -#include <linux/hid.h> -#include <linux/hid-debug.h> - -#include "hid-ids.h" - -#define unk KEY_UNKNOWN - -static const unsigned char hid_keyboard[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, - 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk -}; - -static const struct { - __s32 x; - __s32 y; -} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; - -#define map_abs(c) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c)) -#define map_rel(c) hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c)) -#define map_key(c) hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c)) -#define map_led(c) hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c)) - -#define map_abs_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ - &max, EV_ABS, (c)) -#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ - &max, EV_KEY, (c)) - -static bool match_scancode(struct hid_usage *usage, - unsigned int cur_idx, unsigned int scancode) -{ - return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode; -} - -static bool match_keycode(struct hid_usage *usage, - unsigned int cur_idx, unsigned int keycode) -{ - /* - * We should exclude unmapped usages when doing lookup by keycode. - */ - return (usage->type == EV_KEY && usage->code == keycode); -} - -static bool match_index(struct hid_usage *usage, - unsigned int cur_idx, unsigned int idx) -{ - return cur_idx == idx; -} - -typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage, - unsigned int cur_idx, unsigned int val); - -static struct hid_usage *hidinput_find_key(struct hid_device *hid, - hid_usage_cmp_t match, - unsigned int value, - unsigned int *usage_idx) -{ - unsigned int i, j, k, cur_idx = 0; - struct hid_report *report; - struct hid_usage *usage; - - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { - list_for_each_entry(report, &hid->report_enum[k].report_list, list) { - for (i = 0; i < report->maxfield; i++) { - for (j = 0; j < report->field[i]->maxusage; j++) { - usage = report->field[i]->usage + j; - if (usage->type == EV_KEY || usage->type == 0) { - if (match(usage, cur_idx, value)) { - if (usage_idx) - *usage_idx = cur_idx; - return usage; - } - cur_idx++; - } - } - } - } - } - return NULL; -} - -static struct hid_usage *hidinput_locate_usage(struct hid_device *hid, - const struct input_keymap_entry *ke, - unsigned int *index) -{ - struct hid_usage *usage; - unsigned int scancode; - - if (ke->flags & INPUT_KEYMAP_BY_INDEX) - usage = hidinput_find_key(hid, match_index, ke->index, index); - else if (input_scancode_to_scalar(ke, &scancode) == 0) - usage = hidinput_find_key(hid, match_scancode, scancode, index); - else - usage = NULL; - - return usage; -} - -static int hidinput_getkeycode(struct input_dev *dev, - struct input_keymap_entry *ke) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct hid_usage *usage; - unsigned int scancode, index; - - usage = hidinput_locate_usage(hid, ke, &index); - if (usage) { - ke->keycode = usage->type == EV_KEY ? - usage->code : KEY_RESERVED; - ke->index = index; - scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE); - ke->len = sizeof(scancode); - memcpy(ke->scancode, &scancode, sizeof(scancode)); - return 0; - } - - return -EINVAL; -} - -static int hidinput_setkeycode(struct input_dev *dev, - const struct input_keymap_entry *ke, - unsigned int *old_keycode) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct hid_usage *usage; - - usage = hidinput_locate_usage(hid, ke, NULL); - if (usage) { - *old_keycode = usage->type == EV_KEY ? - usage->code : KEY_RESERVED; - usage->code = ke->keycode; - - clear_bit(*old_keycode, dev->keybit); - set_bit(usage->code, dev->keybit); - dbg_hid("Assigned keycode %d to HID usage code %x\n", - usage->code, usage->hid); - - /* - * Set the keybit for the old keycode if the old keycode is used - * by another key - */ - if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL)) - set_bit(*old_keycode, dev->keybit); - - return 0; - } - - return -EINVAL; -} - - -/** - * hidinput_calc_abs_res - calculate an absolute axis resolution - * @field: the HID report field to calculate resolution for - * @code: axis code - * - * The formula is: - * (logical_maximum - logical_minimum) - * resolution = ---------------------------------------------------------- - * (physical_maximum - physical_minimum) * 10 ^ unit_exponent - * - * as seen in the HID specification v1.11 6.2.2.7 Global Items. - * - * Only exponent 1 length units are processed. Centimeters and inches are - * converted to millimeters. Degrees are converted to radians. - */ -static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) -{ - __s32 unit_exponent = field->unit_exponent; - __s32 logical_extents = field->logical_maximum - - field->logical_minimum; - __s32 physical_extents = field->physical_maximum - - field->physical_minimum; - __s32 prev; - - /* Check if the extents are sane */ - if (logical_extents <= 0 || physical_extents <= 0) - return 0; - - /* - * Verify and convert units. - * See HID specification v1.11 6.2.2.7 Global Items for unit decoding - */ - if (code == ABS_X || code == ABS_Y || code == ABS_Z) { - if (field->unit == 0x11) { /* If centimeters */ - /* Convert to millimeters */ - unit_exponent += 1; - } else if (field->unit == 0x13) { /* If inches */ - /* Convert to millimeters */ - prev = physical_extents; - physical_extents *= 254; - if (physical_extents < prev) - return 0; - unit_exponent -= 1; - } else { - return 0; - } - } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) { - if (field->unit == 0x14) { /* If degrees */ - /* Convert to radians */ - prev = logical_extents; - logical_extents *= 573; - if (logical_extents < prev) - return 0; - unit_exponent += 1; - } else if (field->unit != 0x12) { /* If not radians */ - return 0; - } - } else { - return 0; - } - - /* Apply negative unit exponent */ - for (; unit_exponent < 0; unit_exponent++) { - prev = logical_extents; - logical_extents *= 10; - if (logical_extents < prev) - return 0; - } - /* Apply positive unit exponent */ - for (; unit_exponent > 0; unit_exponent--) { - prev = physical_extents; - physical_extents *= 10; - if (physical_extents < prev) - return 0; - } - - /* Calculate resolution */ - return logical_extents / physical_extents; -} - -#ifdef CONFIG_HID_BATTERY_STRENGTH -static enum power_supply_property hidinput_battery_props[] = { - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_MODEL_NAME, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_SCOPE, -}; - -#define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */ -#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ - -static const struct hid_device_id hid_battery_quirks[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, - USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), - HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, - {} -}; - -static unsigned find_battery_quirk(struct hid_device *hdev) -{ - unsigned quirks = 0; - const struct hid_device_id *match; - - match = hid_match_id(hdev, hid_battery_quirks); - if (match != NULL) - quirks = match->driver_data; - - return quirks; -} - -static int hidinput_get_battery_property(struct power_supply *psy, - enum power_supply_property prop, - union power_supply_propval *val) -{ - struct hid_device *dev = container_of(psy, struct hid_device, battery); - int ret = 0; - __u8 buf[2] = {}; - - switch (prop) { - case POWER_SUPPLY_PROP_PRESENT: - case POWER_SUPPLY_PROP_ONLINE: - val->intval = 1; - break; - - case POWER_SUPPLY_PROP_CAPACITY: - ret = dev->hid_get_raw_report(dev, dev->battery_report_id, - buf, sizeof(buf), - dev->battery_report_type); - - if (ret != 2) { - if (ret >= 0) - ret = -EINVAL; - break; - } - - if (dev->battery_min < dev->battery_max && - buf[1] >= dev->battery_min && - buf[1] <= dev->battery_max) - val->intval = (100 * (buf[1] - dev->battery_min)) / - (dev->battery_max - dev->battery_min); - break; - - case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = dev->name; - break; - - case POWER_SUPPLY_PROP_STATUS: - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - break; - - case POWER_SUPPLY_PROP_SCOPE: - val->intval = POWER_SUPPLY_SCOPE_DEVICE; - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field) -{ - struct power_supply *battery = &dev->battery; - int ret; - unsigned quirks; - s32 min, max; - - if (field->usage->hid != HID_DC_BATTERYSTRENGTH) - return false; /* no match */ - - if (battery->name != NULL) - goto out; /* already initialized? */ - - battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq); - if (battery->name == NULL) - goto out; - - battery->type = POWER_SUPPLY_TYPE_BATTERY; - battery->properties = hidinput_battery_props; - battery->num_properties = ARRAY_SIZE(hidinput_battery_props); - battery->use_for_apm = 0; - battery->get_property = hidinput_get_battery_property; - - quirks = find_battery_quirk(dev); - - hid_dbg(dev, "device %x:%x:%x %d quirks %d\n", - dev->bus, dev->vendor, dev->product, dev->version, quirks); - - min = field->logical_minimum; - max = field->logical_maximum; - - if (quirks & HID_BATTERY_QUIRK_PERCENT) { - min = 0; - max = 100; - } - - if (quirks & HID_BATTERY_QUIRK_FEATURE) - report_type = HID_FEATURE_REPORT; - - dev->battery_min = min; - dev->battery_max = max; - dev->battery_report_type = report_type; - dev->battery_report_id = field->report->id; - - ret = power_supply_register(&dev->dev, battery); - if (ret != 0) { - hid_warn(dev, "can't register power supply: %d\n", ret); - kfree(battery->name); - battery->name = NULL; - } - - power_supply_powers(battery, &dev->dev); - -out: - return true; -} - -static void hidinput_cleanup_battery(struct hid_device *dev) -{ - if (!dev->battery.name) - return; - - power_supply_unregister(&dev->battery); - kfree(dev->battery.name); - dev->battery.name = NULL; -} -#else /* !CONFIG_HID_BATTERY_STRENGTH */ -static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, - struct hid_field *field) -{ - return false; -} - -static void hidinput_cleanup_battery(struct hid_device *dev) -{ -} -#endif /* CONFIG_HID_BATTERY_STRENGTH */ - -static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, - struct hid_usage *usage) -{ - struct input_dev *input = hidinput->input; - struct hid_device *device = input_get_drvdata(input); - int max = 0, code; - unsigned long *bit = NULL; - - field->hidinput = hidinput; - - if (field->flags & HID_MAIN_ITEM_CONSTANT) - goto ignore; - - /* only LED usages are supported in output fields */ - if (field->report_type == HID_OUTPUT_REPORT && - (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { - goto ignore; - } - - if (device->driver->input_mapping) { - int ret = device->driver->input_mapping(device, hidinput, field, - usage, &bit, &max); - if (ret > 0) - goto mapped; - if (ret < 0) - goto ignore; - } - - switch (usage->hid & HID_USAGE_PAGE) { - case HID_UP_UNDEFINED: - goto ignore; - - case HID_UP_KEYBOARD: - set_bit(EV_REP, input->evbit); - - if ((usage->hid & HID_USAGE) < 256) { - if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore; - map_key_clear(hid_keyboard[usage->hid & HID_USAGE]); - } else - map_key(KEY_UNKNOWN); - - break; - - case HID_UP_BUTTON: - code = ((usage->hid - 1) & HID_USAGE); - - switch (field->application) { - case HID_GD_MOUSE: - case HID_GD_POINTER: code += BTN_MOUSE; break; - case HID_GD_JOYSTICK: - if (code <= 0xf) - code += BTN_JOYSTICK; - else - code += BTN_TRIGGER_HAPPY; - break; - case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break; - default: - switch (field->physical) { - case HID_GD_MOUSE: - case HID_GD_POINTER: code += BTN_MOUSE; break; - case HID_GD_JOYSTICK: code += BTN_JOYSTICK; break; - case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break; - default: code += BTN_MISC; - } - } - - map_key(code); - break; - - case HID_UP_SIMULATION: - switch (usage->hid & 0xffff) { - case 0xba: map_abs(ABS_RUDDER); break; - case 0xbb: map_abs(ABS_THROTTLE); break; - case 0xc4: map_abs(ABS_GAS); break; - case 0xc5: map_abs(ABS_BRAKE); break; - case 0xc8: map_abs(ABS_WHEEL); break; - default: goto ignore; - } - break; - - case HID_UP_GENDESK: - if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ - switch (usage->hid & 0xf) { - case 0x1: map_key_clear(KEY_POWER); break; - case 0x2: map_key_clear(KEY_SLEEP); break; - case 0x3: map_key_clear(KEY_WAKEUP); break; - case 0x4: map_key_clear(KEY_CONTEXT_MENU); break; - case 0x5: map_key_clear(KEY_MENU); break; - case 0x6: map_key_clear(KEY_PROG1); break; - case 0x7: map_key_clear(KEY_HELP); break; - case 0x8: map_key_clear(KEY_EXIT); break; - case 0x9: map_key_clear(KEY_SELECT); break; - case 0xa: map_key_clear(KEY_RIGHT); break; - case 0xb: map_key_clear(KEY_LEFT); break; - case 0xc: map_key_clear(KEY_UP); break; - case 0xd: map_key_clear(KEY_DOWN); break; - case 0xe: map_key_clear(KEY_POWER2); break; - case 0xf: map_key_clear(KEY_RESTART); break; - default: goto unknown; - } - break; - } - - if ((usage->hid & 0xf0) == 0x90) { /* D-pad */ - switch (usage->hid) { - case HID_GD_UP: usage->hat_dir = 1; break; - case HID_GD_DOWN: usage->hat_dir = 5; break; - case HID_GD_RIGHT: usage->hat_dir = 3; break; - case HID_GD_LEFT: usage->hat_dir = 7; break; - default: goto unknown; - } - if (field->dpad) { - map_abs(field->dpad); - goto ignore; - } - map_abs(ABS_HAT0X); - break; - } - - switch (usage->hid) { - /* These usage IDs map directly to the usage codes. */ - case HID_GD_X: case HID_GD_Y: case HID_GD_Z: - case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: - case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: - if (field->flags & HID_MAIN_ITEM_RELATIVE) - map_rel(usage->hid & 0xf); - else - map_abs(usage->hid & 0xf); - break; - - case HID_GD_HATSWITCH: - usage->hat_min = field->logical_minimum; - usage->hat_max = field->logical_maximum; - map_abs(ABS_HAT0X); - break; - - case HID_GD_START: map_key_clear(BTN_START); break; - case HID_GD_SELECT: map_key_clear(BTN_SELECT); break; - - default: goto unknown; - } - - break; - - case HID_UP_LED: - switch (usage->hid & 0xffff) { /* HID-Value: */ - case 0x01: map_led (LED_NUML); break; /* "Num Lock" */ - case 0x02: map_led (LED_CAPSL); break; /* "Caps Lock" */ - case 0x03: map_led (LED_SCROLLL); break; /* "Scroll Lock" */ - case 0x04: map_led (LED_COMPOSE); break; /* "Compose" */ - case 0x05: map_led (LED_KANA); break; /* "Kana" */ - case 0x27: map_led (LED_SLEEP); break; /* "Stand-By" */ - case 0x4c: map_led (LED_SUSPEND); break; /* "System Suspend" */ - case 0x09: map_led (LED_MUTE); break; /* "Mute" */ - case 0x4b: map_led (LED_MISC); break; /* "Generic Indicator" */ - case 0x19: map_led (LED_MAIL); break; /* "Message Waiting" */ - case 0x4d: map_led (LED_CHARGING); break; /* "External Power Connected" */ - - default: goto ignore; - } - break; - - case HID_UP_DIGITIZER: - switch (usage->hid & 0xff) { - case 0x00: /* Undefined */ - goto ignore; - - case 0x30: /* TipPressure */ - if (!test_bit(BTN_TOUCH, input->keybit)) { - device->quirks |= HID_QUIRK_NOTOUCH; - set_bit(EV_KEY, input->evbit); - set_bit(BTN_TOUCH, input->keybit); - } - map_abs_clear(ABS_PRESSURE); - break; - - case 0x32: /* InRange */ - switch (field->physical & 0xff) { - case 0x21: map_key(BTN_TOOL_MOUSE); break; - case 0x22: map_key(BTN_TOOL_FINGER); break; - default: map_key(BTN_TOOL_PEN); break; - } - break; - - case 0x3c: /* Invert */ - map_key_clear(BTN_TOOL_RUBBER); - break; - - case 0x33: /* Touch */ - case 0x42: /* TipSwitch */ - case 0x43: /* TipSwitch2 */ - device->quirks &= ~HID_QUIRK_NOTOUCH; - map_key_clear(BTN_TOUCH); - break; - - case 0x44: /* BarrelSwitch */ - map_key_clear(BTN_STYLUS); - break; - - case 0x46: /* TabletPick */ - map_key_clear(BTN_STYLUS2); - break; - - case 0x51: /* ContactID */ - device->quirks |= HID_QUIRK_MULTITOUCH; - goto unknown; - - default: goto unknown; - } - break; - - case HID_UP_CONSUMER: /* USB HUT v1.12, pages 75-84 */ - switch (usage->hid & HID_USAGE) { - case 0x000: goto ignore; - case 0x030: map_key_clear(KEY_POWER); break; - case 0x031: map_key_clear(KEY_RESTART); break; - case 0x032: map_key_clear(KEY_SLEEP); break; - case 0x034: map_key_clear(KEY_SLEEP); break; - case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE); break; - case 0x036: map_key_clear(BTN_MISC); break; - - case 0x040: map_key_clear(KEY_MENU); break; /* Menu */ - case 0x041: map_key_clear(KEY_SELECT); break; /* Menu Pick */ - case 0x042: map_key_clear(KEY_UP); break; /* Menu Up */ - case 0x043: map_key_clear(KEY_DOWN); break; /* Menu Down */ - case 0x044: map_key_clear(KEY_LEFT); break; /* Menu Left */ - case 0x045: map_key_clear(KEY_RIGHT); break; /* Menu Right */ - case 0x046: map_key_clear(KEY_ESC); break; /* Menu Escape */ - case 0x047: map_key_clear(KEY_KPPLUS); break; /* Menu Value Increase */ - case 0x048: map_key_clear(KEY_KPMINUS); break; /* Menu Value Decrease */ - - case 0x060: map_key_clear(KEY_INFO); break; /* Data On Screen */ - case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */ - case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */ - case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */ - case 0x069: map_key_clear(KEY_RED); break; - case 0x06a: map_key_clear(KEY_GREEN); break; - case 0x06b: map_key_clear(KEY_BLUE); break; - case 0x06c: map_key_clear(KEY_YELLOW); break; - case 0x06d: map_key_clear(KEY_ZOOM); break; - - case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; - case 0x083: map_key_clear(KEY_LAST); break; - case 0x084: map_key_clear(KEY_ENTER); break; - case 0x088: map_key_clear(KEY_PC); break; - case 0x089: map_key_clear(KEY_TV); break; - case 0x08a: map_key_clear(KEY_WWW); break; - case 0x08b: map_key_clear(KEY_DVD); break; - case 0x08c: map_key_clear(KEY_PHONE); break; - case 0x08d: map_key_clear(KEY_PROGRAM); break; - case 0x08e: map_key_clear(KEY_VIDEOPHONE); break; - case 0x08f: map_key_clear(KEY_GAMES); break; - case 0x090: map_key_clear(KEY_MEMO); break; - case 0x091: map_key_clear(KEY_CD); break; - case 0x092: map_key_clear(KEY_VCR); break; - case 0x093: map_key_clear(KEY_TUNER); break; - case 0x094: map_key_clear(KEY_EXIT); break; - case 0x095: map_key_clear(KEY_HELP); break; - case 0x096: map_key_clear(KEY_TAPE); break; - case 0x097: map_key_clear(KEY_TV2); break; - case 0x098: map_key_clear(KEY_SAT); break; - case 0x09a: map_key_clear(KEY_PVR); break; - - case 0x09c: map_key_clear(KEY_CHANNELUP); break; - case 0x09d: map_key_clear(KEY_CHANNELDOWN); break; - case 0x0a0: map_key_clear(KEY_VCR2); break; - - case 0x0b0: map_key_clear(KEY_PLAY); break; - case 0x0b1: map_key_clear(KEY_PAUSE); break; - case 0x0b2: map_key_clear(KEY_RECORD); break; - case 0x0b3: map_key_clear(KEY_FASTFORWARD); break; - case 0x0b4: map_key_clear(KEY_REWIND); break; - case 0x0b5: map_key_clear(KEY_NEXTSONG); break; - case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break; - case 0x0b7: map_key_clear(KEY_STOPCD); break; - case 0x0b8: map_key_clear(KEY_EJECTCD); break; - case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break; - case 0x0b9: map_key_clear(KEY_SHUFFLE); break; - case 0x0bf: map_key_clear(KEY_SLOW); break; - - case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; - case 0x0e0: map_abs_clear(ABS_VOLUME); break; - case 0x0e2: map_key_clear(KEY_MUTE); break; - case 0x0e5: map_key_clear(KEY_BASSBOOST); break; - case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; - case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; - case 0x0f5: map_key_clear(KEY_SLOW); break; - - case 0x182: map_key_clear(KEY_BOOKMARKS); break; - case 0x183: map_key_clear(KEY_CONFIG); break; - case 0x184: map_key_clear(KEY_WORDPROCESSOR); break; - case 0x185: map_key_clear(KEY_EDITOR); break; - case 0x186: map_key_clear(KEY_SPREADSHEET); break; - case 0x187: map_key_clear(KEY_GRAPHICSEDITOR); break; - case 0x188: map_key_clear(KEY_PRESENTATION); break; - case 0x189: map_key_clear(KEY_DATABASE); break; - case 0x18a: map_key_clear(KEY_MAIL); break; - case 0x18b: map_key_clear(KEY_NEWS); break; - case 0x18c: map_key_clear(KEY_VOICEMAIL); break; - case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break; - case 0x18e: map_key_clear(KEY_CALENDAR); break; - case 0x191: map_key_clear(KEY_FINANCE); break; - case 0x192: map_key_clear(KEY_CALC); break; - case 0x193: map_key_clear(KEY_PLAYER); break; - case 0x194: map_key_clear(KEY_FILE); break; - case 0x196: map_key_clear(KEY_WWW); break; - case 0x199: map_key_clear(KEY_CHAT); break; - case 0x19c: map_key_clear(KEY_LOGOFF); break; - case 0x19e: map_key_clear(KEY_COFFEE); break; - case 0x1a6: map_key_clear(KEY_HELP); break; - case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; - case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; - case 0x1ae: map_key_clear(KEY_KEYBOARD); break; - case 0x1b6: map_key_clear(KEY_IMAGES); break; - case 0x1b7: map_key_clear(KEY_AUDIO); break; - case 0x1b8: map_key_clear(KEY_VIDEO); break; - case 0x1bc: map_key_clear(KEY_MESSENGER); break; - case 0x1bd: map_key_clear(KEY_INFO); break; - case 0x201: map_key_clear(KEY_NEW); break; - case 0x202: map_key_clear(KEY_OPEN); break; - case 0x203: map_key_clear(KEY_CLOSE); break; - case 0x204: map_key_clear(KEY_EXIT); break; - case 0x207: map_key_clear(KEY_SAVE); break; - case 0x208: map_key_clear(KEY_PRINT); break; - case 0x209: map_key_clear(KEY_PROPS); break; - case 0x21a: map_key_clear(KEY_UNDO); break; - case 0x21b: map_key_clear(KEY_COPY); break; - case 0x21c: map_key_clear(KEY_CUT); break; - case 0x21d: map_key_clear(KEY_PASTE); break; - case 0x21f: map_key_clear(KEY_FIND); break; - case 0x221: map_key_clear(KEY_SEARCH); break; - case 0x222: map_key_clear(KEY_GOTO); break; - case 0x223: map_key_clear(KEY_HOMEPAGE); break; - case 0x224: map_key_clear(KEY_BACK); break; - case 0x225: map_key_clear(KEY_FORWARD); break; - case 0x226: map_key_clear(KEY_STOP); break; - case 0x227: map_key_clear(KEY_REFRESH); break; - case 0x22a: map_key_clear(KEY_BOOKMARKS); break; - case 0x22d: map_key_clear(KEY_ZOOMIN); break; - case 0x22e: map_key_clear(KEY_ZOOMOUT); break; - case 0x22f: map_key_clear(KEY_ZOOMRESET); break; - case 0x233: map_key_clear(KEY_SCROLLUP); break; - case 0x234: map_key_clear(KEY_SCROLLDOWN); break; - case 0x238: map_rel(REL_HWHEEL); break; - case 0x23d: map_key_clear(KEY_EDIT); break; - case 0x25f: map_key_clear(KEY_CANCEL); break; - case 0x269: map_key_clear(KEY_INSERT); break; - case 0x26a: map_key_clear(KEY_DELETE); break; - case 0x279: map_key_clear(KEY_REDO); break; - - case 0x289: map_key_clear(KEY_REPLY); break; - case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; - case 0x28c: map_key_clear(KEY_SEND); break; - - default: goto ignore; - } - break; - - case HID_UP_GENDEVCTRLS: - if (hidinput_setup_battery(device, HID_INPUT_REPORT, field)) - goto ignore; - else - goto unknown; - break; - - case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ - set_bit(EV_REP, input->evbit); - switch (usage->hid & HID_USAGE) { - case 0x021: map_key_clear(KEY_PRINT); break; - case 0x070: map_key_clear(KEY_HP); break; - case 0x071: map_key_clear(KEY_CAMERA); break; - case 0x072: map_key_clear(KEY_SOUND); break; - case 0x073: map_key_clear(KEY_QUESTION); break; - case 0x080: map_key_clear(KEY_EMAIL); break; - case 0x081: map_key_clear(KEY_CHAT); break; - case 0x082: map_key_clear(KEY_SEARCH); break; - case 0x083: map_key_clear(KEY_CONNECT); break; - case 0x084: map_key_clear(KEY_FINANCE); break; - case 0x085: map_key_clear(KEY_SPORT); break; - case 0x086: map_key_clear(KEY_SHOP); break; - default: goto ignore; - } - break; - - case HID_UP_MSVENDOR: - goto ignore; - - case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */ - set_bit(EV_REP, input->evbit); - goto ignore; - - case HID_UP_LOGIVENDOR: - goto ignore; - - case HID_UP_PID: - switch (usage->hid & HID_USAGE) { - case 0xa4: map_key_clear(BTN_DEAD); break; - default: goto ignore; - } - break; - - default: - unknown: - if (field->report_size == 1) { - if (field->report->type == HID_OUTPUT_REPORT) { - map_led(LED_MISC); - break; - } - map_key(BTN_MISC); - break; - } - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - map_rel(REL_MISC); - break; - } - map_abs(ABS_MISC); - break; - } - -mapped: - if (device->driver->input_mapped && device->driver->input_mapped(device, - hidinput, field, usage, &bit, &max) < 0) - goto ignore; - - set_bit(usage->type, input->evbit); - - while (usage->code <= max && test_and_set_bit(usage->code, bit)) - usage->code = find_next_zero_bit(bit, max + 1, usage->code); - - if (usage->code > max) - goto ignore; - - - if (usage->type == EV_ABS) { - - int a = field->logical_minimum; - int b = field->logical_maximum; - - if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) { - a = field->logical_minimum = 0; - b = field->logical_maximum = 255; - } - - if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) - input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); - else input_set_abs_params(input, usage->code, a, b, 0, 0); - - input_abs_set_res(input, usage->code, - hidinput_calc_abs_res(field, usage->code)); - - /* use a larger default input buffer for MT devices */ - if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0) - input_set_events_per_packet(input, 60); - } - - if (usage->type == EV_ABS && - (usage->hat_min < usage->hat_max || usage->hat_dir)) { - int i; - for (i = usage->code; i < usage->code + 2 && i <= max; i++) { - input_set_abs_params(input, i, -1, 1, 0, 0); - set_bit(i, input->absbit); - } - if (usage->hat_dir && !field->dpad) - field->dpad = usage->code; - } - - /* for those devices which produce Consumer volume usage as relative, - * we emulate pressing volumeup/volumedown appropriate number of times - * in hidinput_hid_event() - */ - if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) && - (usage->code == ABS_VOLUME)) { - set_bit(KEY_VOLUMEUP, input->keybit); - set_bit(KEY_VOLUMEDOWN, input->keybit); - } - - if (usage->type == EV_KEY) { - set_bit(EV_MSC, input->evbit); - set_bit(MSC_SCAN, input->mscbit); - } - -ignore: - return; - -} - -void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) -{ - struct input_dev *input; - unsigned *quirks = &hid->quirks; - - if (!field->hidinput) - return; - - input = field->hidinput->input; - - if (!usage->type) - return; - - if (usage->hat_min < usage->hat_max || usage->hat_dir) { - int hat_dir = usage->hat_dir; - if (!hat_dir) - hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; - if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; - input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); - input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ - *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */ - if (value) { - input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1); - return; - } - input_event(input, usage->type, usage->code, 0); - input_event(input, usage->type, BTN_TOOL_RUBBER, 0); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */ - int a = field->logical_minimum; - int b = field->logical_maximum; - input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); - } - - if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */ - dbg_hid("Maximum Effects - %d\n",value); - return; - } - - if (usage->hid == (HID_UP_PID | 0x7fUL)) { - dbg_hid("PID Pool Report\n"); - return; - } - - if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ - return; - - if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) && - (usage->code == ABS_VOLUME)) { - int count = abs(value); - int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN; - int i; - - for (i = 0; i < count; i++) { - input_event(input, EV_KEY, direction, 1); - input_sync(input); - input_event(input, EV_KEY, direction, 0); - input_sync(input); - } - return; - } - - /* - * Ignore out-of-range values as per HID specification, - * section 5.10 and 6.2.25 - */ - if ((field->flags & HID_MAIN_ITEM_VARIABLE) && - (value < field->logical_minimum || - value > field->logical_maximum)) { - dbg_hid("Ignoring out-of-range value %x\n", value); - return; - } - - /* report the usage code as scancode if the key status has changed */ - if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) - input_event(input, EV_MSC, MSC_SCAN, usage->hid); - - input_event(input, usage->type, usage->code, value); - - if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) - input_event(input, usage->type, usage->code, 0); -} - -void hidinput_report_event(struct hid_device *hid, struct hid_report *report) -{ - struct hid_input *hidinput; - - if (hid->quirks & HID_QUIRK_NO_INPUT_SYNC) - return; - - list_for_each_entry(hidinput, &hid->inputs, list) - input_sync(hidinput->input); -} -EXPORT_SYMBOL_GPL(hidinput_report_event); - -int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) -{ - struct hid_report *report; - int i, j; - - list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { - for (i = 0; i < report->maxfield; i++) { - *field = report->field[i]; - for (j = 0; j < (*field)->maxusage; j++) - if ((*field)->usage[j].type == type && (*field)->usage[j].code == code) - return j; - } - } - return -1; -} -EXPORT_SYMBOL_GPL(hidinput_find_field); - -struct hid_field *hidinput_get_led_field(struct hid_device *hid) -{ - struct hid_report *report; - struct hid_field *field; - int i, j; - - list_for_each_entry(report, - &hid->report_enum[HID_OUTPUT_REPORT].report_list, - list) { - for (i = 0; i < report->maxfield; i++) { - field = report->field[i]; - for (j = 0; j < field->maxusage; j++) - if (field->usage[j].type == EV_LED) - return field; - } - } - return NULL; -} -EXPORT_SYMBOL_GPL(hidinput_get_led_field); - -unsigned int hidinput_count_leds(struct hid_device *hid) -{ - struct hid_report *report; - struct hid_field *field; - int i, j; - unsigned int count = 0; - - list_for_each_entry(report, - &hid->report_enum[HID_OUTPUT_REPORT].report_list, - list) { - for (i = 0; i < report->maxfield; i++) { - field = report->field[i]; - for (j = 0; j < field->maxusage; j++) - if (field->usage[j].type == EV_LED && - field->value[j]) - count += 1; - } - } - return count; -} -EXPORT_SYMBOL_GPL(hidinput_count_leds); - -static int hidinput_open(struct input_dev *dev) -{ - struct hid_device *hid = input_get_drvdata(dev); - - return hid_hw_open(hid); -} - -static void hidinput_close(struct input_dev *dev) -{ - struct hid_device *hid = input_get_drvdata(dev); - - hid_hw_close(hid); -} - -static void report_features(struct hid_device *hid) -{ - struct hid_driver *drv = hid->driver; - struct hid_report_enum *rep_enum; - struct hid_report *rep; - int i, j; - - rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; - list_for_each_entry(rep, &rep_enum->report_list, list) - for (i = 0; i < rep->maxfield; i++) - for (j = 0; j < rep->field[i]->maxusage; j++) { - /* Verify if Battery Strength feature is available */ - hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); - - if (drv->feature_mapping) - drv->feature_mapping(hid, rep->field[i], - rep->field[i]->usage + j); - } -} - -/* - * Register the input device; print a message. - * Configure the input layer interface - * Read all reports and initialize the absolute field values. - */ - -int hidinput_connect(struct hid_device *hid, unsigned int force) -{ - struct hid_report *report; - struct hid_input *hidinput = NULL; - struct input_dev *input_dev; - int i, j, k; - - INIT_LIST_HEAD(&hid->inputs); - - if (!force) { - for (i = 0; i < hid->maxcollection; i++) { - struct hid_collection *col = &hid->collection[i]; - if (col->type == HID_COLLECTION_APPLICATION || - col->type == HID_COLLECTION_PHYSICAL) - if (IS_INPUT_APPLICATION(col->usage)) - break; - } - - if (i == hid->maxcollection) - return -1; - } - - report_features(hid); - - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { - if (k == HID_OUTPUT_REPORT && - hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) - continue; - - list_for_each_entry(report, &hid->report_enum[k].report_list, list) { - - if (!report->maxfield) - continue; - - if (!hidinput) { - hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!hidinput || !input_dev) { - kfree(hidinput); - input_free_device(input_dev); - hid_err(hid, "Out of memory during hid input probe\n"); - goto out_unwind; - } - - input_set_drvdata(input_dev, hid); - input_dev->event = - hid->ll_driver->hidinput_input_event; - input_dev->open = hidinput_open; - input_dev->close = hidinput_close; - input_dev->setkeycode = hidinput_setkeycode; - input_dev->getkeycode = hidinput_getkeycode; - - input_dev->name = hid->name; - input_dev->phys = hid->phys; - input_dev->uniq = hid->uniq; - input_dev->id.bustype = hid->bus; - input_dev->id.vendor = hid->vendor; - input_dev->id.product = hid->product; - input_dev->id.version = hid->version; - input_dev->dev.parent = hid->dev.parent; - hidinput->input = input_dev; - list_add_tail(&hidinput->list, &hid->inputs); - } - - for (i = 0; i < report->maxfield; i++) - for (j = 0; j < report->field[i]->maxusage; j++) - hidinput_configure_usage(hidinput, report->field[i], - report->field[i]->usage + j); - - if (hid->quirks & HID_QUIRK_MULTI_INPUT) { - /* This will leave hidinput NULL, so that it - * allocates another one if we have more inputs on - * the same interface. Some devices (e.g. Happ's - * UGCI) cram a lot of unrelated inputs into the - * same interface. */ - hidinput->report = report; - if (hid->driver->input_register && - hid->driver->input_register(hid, hidinput)) - goto out_cleanup; - if (input_register_device(hidinput->input)) - goto out_cleanup; - hidinput = NULL; - } - } - } - - if (hid->quirks & HID_QUIRK_MULTITOUCH) { - /* generic hid does not know how to handle multitouch devices */ - if (hidinput) - goto out_cleanup; - goto out_unwind; - } - - if (hidinput && hid->driver->input_register && - hid->driver->input_register(hid, hidinput)) - goto out_cleanup; - - if (hidinput && input_register_device(hidinput->input)) - goto out_cleanup; - - return 0; - -out_cleanup: - list_del(&hidinput->list); - input_free_device(hidinput->input); - kfree(hidinput); -out_unwind: - /* unwind the ones we already registered */ - hidinput_disconnect(hid); - - return -1; -} -EXPORT_SYMBOL_GPL(hidinput_connect); - -void hidinput_disconnect(struct hid_device *hid) -{ - struct hid_input *hidinput, *next; - - hidinput_cleanup_battery(hid); - - list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { - list_del(&hidinput->list); - input_unregister_device(hidinput->input); - kfree(hidinput); - } -} -EXPORT_SYMBOL_GPL(hidinput_disconnect); - diff --git a/ANDROID_3.4.5/drivers/hid/hid-kensington.c b/ANDROID_3.4.5/drivers/hid/hid-kensington.c deleted file mode 100644 index a5b4016e..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-kensington.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * HID driver for Kensigton Slimblade Trackball - * - * Copyright (c) 2009 Jiri Kosina - */ - -/* - * 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/input.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#define ks_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c)) - -static int ks_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x01: ks_map_key(BTN_MIDDLE); break; - case 0x02: ks_map_key(BTN_SIDE); break; - default: - return 0; - } - return 1; -} - -static const struct hid_device_id ks_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ks_devices); - -static struct hid_driver ks_driver = { - .name = "kensington", - .id_table = ks_devices, - .input_mapping = ks_input_mapping, -}; - -static int __init ks_init(void) -{ - return hid_register_driver(&ks_driver); -} - -static void __exit ks_exit(void) -{ - hid_unregister_driver(&ks_driver); -} - -module_init(ks_init); -module_exit(ks_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-keytouch.c b/ANDROID_3.4.5/drivers/hid/hid-keytouch.c deleted file mode 100644 index 07cd825f..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-keytouch.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * HID driver for Keytouch devices not fully compliant with HID standard - * - * Copyright (c) 2011 Jiri Kosina - */ - -/* - * 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" - -/* Replace the broken report descriptor of this device with rather - * a default one */ -static __u8 keytouch_fixed_rdesc[] = { -0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, -0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, -0x81, 0x01, 0x95, 0x03, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, -0x02, 0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, -0x26, 0xff, 0x00, 0x05, 0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00, 0xc0 -}; - -static __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - hid_info(hdev, "fixing up Keytouch IEC report descriptor\n"); - - rdesc = keytouch_fixed_rdesc; - *rsize = sizeof(keytouch_fixed_rdesc); - - return rdesc; -} - -static const struct hid_device_id keytouch_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, - { } -}; -MODULE_DEVICE_TABLE(hid, keytouch_devices); - -static struct hid_driver keytouch_driver = { - .name = "keytouch", - .id_table = keytouch_devices, - .report_fixup = keytouch_report_fixup, -}; - -static int __init keytouch_init(void) -{ - return hid_register_driver(&keytouch_driver); -} - -static void __exit keytouch_exit(void) -{ - hid_unregister_driver(&keytouch_driver); -} - -module_init(keytouch_init); -module_exit(keytouch_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jiri Kosina"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-kye.c b/ANDROID_3.4.5/drivers/hid/hid-kye.c deleted file mode 100644 index b4f0d821..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-kye.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * HID driver for Kye/Genius devices not fully compliant with HID standard - * - * Copyright (c) 2009 Jiri Kosina - * Copyright (c) 2009 Tomas Hanak - * Copyright (c) 2012 Nikolai Kondrashov - */ - -/* - * 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 <linux/usb.h> -#include "usbhid/usbhid.h" - -#include "hid-ids.h" - -/* - * See EasyPen i405X description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=KYE_EasyPen_i405X - */ - -/* Original EasyPen i405X report descriptor size */ -#define EASYPEN_I405X_RDESC_ORIG_SIZE 476 - -/* Fixed EasyPen i405X report descriptor */ -static __u8 easypen_i405x_rdesc_fixed[] = { - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ - 0x09, 0x01, /* Usage (01h), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x05, /* Report ID (5), */ - 0x09, 0x01, /* Usage (01h), */ - 0x15, 0x80, /* Logical Minimum (-128), */ - 0x25, 0x7F, /* Logical Maximum (127), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x07, /* Report Count (7), */ - 0xB1, 0x02, /* Feature (Variable), */ - 0xC0, /* End Collection, */ - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x04, /* Report Count (4), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ - 0x26, 0x00, 0x37, /* Logical Maximum (14080), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ - 0x26, 0x00, 0x28, /* Logical Maximum (10240), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See MousePen i608X description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=KYE_MousePen_i608X - */ - -/* Original MousePen i608X report descriptor size */ -#define MOUSEPEN_I608X_RDESC_ORIG_SIZE 476 - -/* Fixed MousePen i608X report descriptor */ -static __u8 mousepen_i608x_rdesc_fixed[] = { - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ - 0x09, 0x01, /* Usage (01h), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x05, /* Report ID (5), */ - 0x09, 0x01, /* Usage (01h), */ - 0x15, 0x80, /* Logical Minimum (-128), */ - 0x25, 0x7F, /* Logical Maximum (127), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x07, /* Report Count (7), */ - 0xB1, 0x02, /* Feature (Variable), */ - 0xC0, /* End Collection, */ - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x04, /* Report Count (4), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ - 0x26, 0x00, 0x50, /* Logical Maximum (20480), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ - 0x26, 0x00, 0x3C, /* Logical Maximum (15360), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x02, /* Usage (Mouse), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x11, /* Report ID (17), */ - 0x09, 0x01, /* Usage (Pointer), */ - 0xA0, /* Collection (Physical), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x09, /* Usage Page (Button), */ - 0x75, 0x01, /* Report Size (1), */ - 0x19, 0x01, /* Usage Minimum (01h), */ - 0x29, 0x03, /* Usage Maximum (03h), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0xB4, /* Pop, */ - 0x95, 0x01, /* Report Count (1), */ - 0xA4, /* Push, */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x75, 0x10, /* Report Size (16), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ - 0x26, 0x00, 0x50, /* Logical Maximum (20480), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ - 0x26, 0x00, 0x3C, /* Logical Maximum (15360), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x75, 0x08, /* Report Size (8), */ - 0x09, 0x38, /* Usage (Wheel), */ - 0x15, 0xFF, /* Logical Minimum (-1), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x81, 0x01, /* Input (Constant), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See EasyPen M610X description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=KYE_EasyPen_M610X - */ - -/* Original EasyPen M610X report descriptor size */ -#define EASYPEN_M610X_RDESC_ORIG_SIZE 476 - -/* Fixed EasyPen M610X report descriptor */ -static __u8 easypen_m610x_rdesc_fixed[] = { - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ - 0x09, 0x01, /* Usage (01h), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x05, /* Report ID (5), */ - 0x09, 0x01, /* Usage (01h), */ - 0x15, 0x80, /* Logical Minimum (-128), */ - 0x25, 0x7F, /* Logical Maximum (127), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x07, /* Report Count (7), */ - 0xB1, 0x02, /* Feature (Variable), */ - 0xC0, /* End Collection, */ - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x04, /* Report Count (4), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ - 0x27, 0x00, 0xA0, 0x00, 0x00, /* Logical Maximum (40960), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ - 0x26, 0x00, 0x64, /* Logical Maximum (25600), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x0C, /* Usage Page (Consumer), */ - 0x09, 0x01, /* Usage (Consumer Control), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x12, /* Report ID (18), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x04, /* Report Count (4), */ - 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ - 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */ - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x01, /* Report Count (1), */ - 0x75, 0x14, /* Report Size (20), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x20, /* Report Size (32), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0xC0 /* End Collection */ -}; - -static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - switch (hdev->product) { - case USB_DEVICE_ID_KYE_ERGO_525V: - /* the fixups that need to be done: - * - change led usage page to button for extra buttons - * - report size 8 count 1 must be size 1 count 8 for button - * bitfield - * - change the button usage range to 4-7 for the extra - * buttons - */ - if (*rsize >= 74 && - rdesc[61] == 0x05 && rdesc[62] == 0x08 && - rdesc[63] == 0x19 && rdesc[64] == 0x08 && - rdesc[65] == 0x29 && rdesc[66] == 0x0f && - rdesc[71] == 0x75 && rdesc[72] == 0x08 && - rdesc[73] == 0x95 && rdesc[74] == 0x01) { - hid_info(hdev, - "fixing up Kye/Genius Ergo Mouse " - "report descriptor\n"); - rdesc[62] = 0x09; - rdesc[64] = 0x04; - rdesc[66] = 0x07; - rdesc[72] = 0x01; - rdesc[74] = 0x08; - } - break; - case USB_DEVICE_ID_KYE_EASYPEN_I405X: - if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) { - rdesc = easypen_i405x_rdesc_fixed; - *rsize = sizeof(easypen_i405x_rdesc_fixed); - } - break; - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: - if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) { - rdesc = mousepen_i608x_rdesc_fixed; - *rsize = sizeof(mousepen_i608x_rdesc_fixed); - } - break; - case USB_DEVICE_ID_KYE_EASYPEN_M610X: - if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) { - rdesc = easypen_m610x_rdesc_fixed; - *rsize = sizeof(easypen_m610x_rdesc_fixed); - } - break; - } - return rdesc; -} - -/** - * Enable fully-functional tablet mode by setting a special feature report. - * - * @hdev: HID device - * - * The specific report ID and data were discovered by sniffing the - * Windows driver traffic. - */ -static int kye_tablet_enable(struct hid_device *hdev) -{ - struct list_head *list; - struct list_head *head; - struct hid_report *report; - __s32 *value; - - list = &hdev->report_enum[HID_FEATURE_REPORT].report_list; - list_for_each(head, list) { - report = list_entry(head, struct hid_report, list); - if (report->id == 5) - break; - } - - if (head == list) { - hid_err(hdev, "tablet-enabling feature report not found\n"); - return -ENODEV; - } - - if (report->maxfield < 1 || report->field[0]->report_count < 7) { - hid_err(hdev, "invalid tablet-enabling feature report\n"); - return -ENODEV; - } - - value = report->field[0]->value; - - value[0] = 0x12; - value[1] = 0x10; - value[2] = 0x11; - value[3] = 0x12; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; - usbhid_submit_report(hdev, report, USB_DIR_OUT); - - return 0; -} - -static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - switch (id->product) { - case USB_DEVICE_ID_KYE_EASYPEN_I405X: - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: - case USB_DEVICE_ID_KYE_EASYPEN_M610X: - ret = kye_tablet_enable(hdev); - if (ret) { - hid_err(hdev, "tablet enabling failed\n"); - goto enabling_err; - } - break; - } - - return 0; -enabling_err: - hid_hw_stop(hdev); -err: - return ret; -} - -static const struct hid_device_id kye_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, - USB_DEVICE_ID_KYE_EASYPEN_I405X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, - USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, - USB_DEVICE_ID_KYE_EASYPEN_M610X) }, - { } -}; -MODULE_DEVICE_TABLE(hid, kye_devices); - -static struct hid_driver kye_driver = { - .name = "kye", - .id_table = kye_devices, - .probe = kye_probe, - .report_fixup = kye_report_fixup, -}; - -static int __init kye_init(void) -{ - return hid_register_driver(&kye_driver); -} - -static void __exit kye_exit(void) -{ - hid_unregister_driver(&kye_driver); -} - -module_init(kye_init); -module_exit(kye_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-lcpower.c b/ANDROID_3.4.5/drivers/hid/hid-lcpower.c deleted file mode 100644 index c4fe9bd0..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lcpower.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * HID driver for LC Power Model RC1000MCE - * - * Copyright (c) 2011 Chris Schlund - * based on hid-topseed module - */ - -/* - * 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" - -#define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x046: ts_map_key_clear(KEY_YELLOW); break; - case 0x047: ts_map_key_clear(KEY_GREEN); break; - case 0x049: ts_map_key_clear(KEY_BLUE); break; - case 0x04a: ts_map_key_clear(KEY_RED); break; - case 0x00d: ts_map_key_clear(KEY_HOME); break; - case 0x025: ts_map_key_clear(KEY_TV); break; - case 0x048: ts_map_key_clear(KEY_VCR); break; - case 0x024: ts_map_key_clear(KEY_MENU); break; - default: - return 0; - } - - return 1; -} - -static const struct hid_device_id ts_devices[] = { - { HID_USB_DEVICE( USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ts_devices); - -static struct hid_driver ts_driver = { - .name = "LC RC1000MCE", - .id_table = ts_devices, - .input_mapping = ts_input_mapping, -}; - -static int __init ts_init(void) -{ - return hid_register_driver(&ts_driver); -} - -static void __exit ts_exit(void) -{ - hid_unregister_driver(&ts_driver); -} - -module_init(ts_init); -module_exit(ts_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-lg.c b/ANDROID_3.4.5/drivers/hid/hid-lg.c deleted file mode 100644 index e7a7bd1e..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lg.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * HID driver for some logitech "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - * Copyright (c) 2010 Hendrik Iben - */ - -/* - * 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 <linux/random.h> -#include <linux/sched.h> -#include <linux/wait.h> - -#include "hid-ids.h" -#include "hid-lg.h" - -#define LG_RDESC 0x001 -#define LG_BAD_RELATIVE_KEYS 0x002 -#define LG_DUPLICATE_USAGES 0x004 -#define LG_EXPANDED_KEYMAP 0x010 -#define LG_IGNORE_DOUBLED_WHEEL 0x020 -#define LG_WIRELESS 0x040 -#define LG_INVERT_HWHEEL 0x080 -#define LG_NOGET 0x100 -#define LG_FF 0x200 -#define LG_FF2 0x400 -#define LG_RDESC_REL_ABS 0x800 -#define LG_FF3 0x1000 -#define LG_FF4 0x2000 - -/* Size of the original descriptor of the Driving Force Pro wheel */ -#define DFP_RDESC_ORIG_SIZE 97 - -/* Fixed report descriptor for Logitech Driving Force Pro wheel controller - * - * The original descriptor hides the separate throttle and brake axes in - * a custom vendor usage page, providing only a combined value as - * GenericDesktop.Y. - * This descriptor removes the combined Y axis and instead reports - * separate throttle (Y) and brake (RZ). - */ -static __u8 dfp_rdesc_fixed[] = { -0x05, 0x01, /* Usage Page (Desktop), */ -0x09, 0x04, /* Usage (Joystik), */ -0xA1, 0x01, /* Collection (Application), */ -0xA1, 0x02, /* Collection (Logical), */ -0x95, 0x01, /* Report Count (1), */ -0x75, 0x0E, /* Report Size (14), */ -0x14, /* Logical Minimum (0), */ -0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ -0x34, /* Physical Minimum (0), */ -0x46, 0xFF, 0x3F, /* Physical Maximum (16383), */ -0x09, 0x30, /* Usage (X), */ -0x81, 0x02, /* Input (Variable), */ -0x95, 0x0E, /* Report Count (14), */ -0x75, 0x01, /* Report Size (1), */ -0x25, 0x01, /* Logical Maximum (1), */ -0x45, 0x01, /* Physical Maximum (1), */ -0x05, 0x09, /* Usage Page (Button), */ -0x19, 0x01, /* Usage Minimum (01h), */ -0x29, 0x0E, /* Usage Maximum (0Eh), */ -0x81, 0x02, /* Input (Variable), */ -0x05, 0x01, /* Usage Page (Desktop), */ -0x95, 0x01, /* Report Count (1), */ -0x75, 0x04, /* Report Size (4), */ -0x25, 0x07, /* Logical Maximum (7), */ -0x46, 0x3B, 0x01, /* Physical Maximum (315), */ -0x65, 0x14, /* Unit (Degrees), */ -0x09, 0x39, /* Usage (Hat Switch), */ -0x81, 0x42, /* Input (Variable, Nullstate), */ -0x65, 0x00, /* Unit, */ -0x26, 0xFF, 0x00, /* Logical Maximum (255), */ -0x46, 0xFF, 0x00, /* Physical Maximum (255), */ -0x75, 0x08, /* Report Size (8), */ -0x81, 0x01, /* Input (Constant), */ -0x09, 0x31, /* Usage (Y), */ -0x81, 0x02, /* Input (Variable), */ -0x09, 0x35, /* Usage (Rz), */ -0x81, 0x02, /* Input (Variable), */ -0x81, 0x01, /* Input (Constant), */ -0xC0, /* End Collection, */ -0xA1, 0x02, /* Collection (Logical), */ -0x09, 0x02, /* Usage (02h), */ -0x95, 0x07, /* Report Count (7), */ -0x91, 0x02, /* Output (Variable), */ -0xC0, /* End Collection, */ -0xC0 /* End Collection */ -}; - - -/* - * Certain Logitech keyboards send in report #3 keys which are far - * above the logical maximum described in descriptor. This extends - * the original value of 0x28c of logical maximum to 0x104d - */ -static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && - rdesc[84] == 0x8c && rdesc[85] == 0x02) { - hid_info(hdev, - "fixing up Logitech keyboard report descriptor\n"); - rdesc[84] = rdesc[89] = 0x4d; - rdesc[85] = rdesc[90] = 0x10; - } - if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && - rdesc[32] == 0x81 && rdesc[33] == 0x06 && - rdesc[49] == 0x81 && rdesc[50] == 0x06) { - hid_info(hdev, - "fixing up rel/abs in Logitech report descriptor\n"); - rdesc[33] = rdesc[50] = 0x02; - } - if ((quirks & LG_FF4) && *rsize >= 101 && - rdesc[41] == 0x95 && rdesc[42] == 0x0B && - rdesc[47] == 0x05 && rdesc[48] == 0x09) { - hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n"); - rdesc[41] = 0x05; - rdesc[42] = 0x09; - rdesc[47] = 0x95; - rdesc[48] = 0x0B; - } - - switch (hdev->product) { - case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: - if (*rsize == DFP_RDESC_ORIG_SIZE) { - hid_info(hdev, - "fixing up Logitech Driving Force Pro report descriptor\n"); - rdesc = dfp_rdesc_fixed; - *rsize = sizeof(dfp_rdesc_fixed); - } - break; - } - - return rdesc; -} - -#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) - -static int lg_ultrax_remote_mapping(struct hid_input *hi, - struct hid_usage *usage, unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) - return 0; - - set_bit(EV_REP, hi->input->evbit); - switch (usage->hid & HID_USAGE) { - /* Reported on Logitech Ultra X Media Remote */ - case 0x004: lg_map_key_clear(KEY_AGAIN); break; - case 0x00d: lg_map_key_clear(KEY_HOME); break; - case 0x024: lg_map_key_clear(KEY_SHUFFLE); break; - case 0x025: lg_map_key_clear(KEY_TV); break; - case 0x026: lg_map_key_clear(KEY_MENU); break; - case 0x031: lg_map_key_clear(KEY_AUDIO); break; - case 0x032: lg_map_key_clear(KEY_TEXT); break; - case 0x033: lg_map_key_clear(KEY_LAST); break; - case 0x047: lg_map_key_clear(KEY_MP3); break; - case 0x048: lg_map_key_clear(KEY_DVD); break; - case 0x049: lg_map_key_clear(KEY_MEDIA); break; - case 0x04a: lg_map_key_clear(KEY_VIDEO); break; - case 0x04b: lg_map_key_clear(KEY_ANGLE); break; - case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break; - case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break; - case 0x051: lg_map_key_clear(KEY_RED); break; - case 0x052: lg_map_key_clear(KEY_CLOSE); break; - - default: - return 0; - } - return 1; -} - -static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) - return 0; - - switch (usage->hid & HID_USAGE) { - - case 0x00d: lg_map_key_clear(KEY_MEDIA); break; - default: - return 0; - - } - return 1; -} - -static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x1001: lg_map_key_clear(KEY_MESSENGER); break; - case 0x1003: lg_map_key_clear(KEY_SOUND); break; - case 0x1004: lg_map_key_clear(KEY_VIDEO); break; - case 0x1005: lg_map_key_clear(KEY_AUDIO); break; - case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break; - /* The following two entries are Playlist 1 and 2 on the MX3200 */ - case 0x100f: lg_map_key_clear(KEY_FN_1); break; - case 0x1010: lg_map_key_clear(KEY_FN_2); break; - case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break; - case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break; - case 0x1013: lg_map_key_clear(KEY_CAMERA); break; - case 0x1014: lg_map_key_clear(KEY_MESSENGER); break; - case 0x1015: lg_map_key_clear(KEY_RECORD); break; - case 0x1016: lg_map_key_clear(KEY_PLAYER); break; - case 0x1017: lg_map_key_clear(KEY_EJECTCD); break; - case 0x1018: lg_map_key_clear(KEY_MEDIA); break; - case 0x1019: lg_map_key_clear(KEY_PROG1); break; - case 0x101a: lg_map_key_clear(KEY_PROG2); break; - case 0x101b: lg_map_key_clear(KEY_PROG3); break; - case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS); break; - case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break; - case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break; - case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break; - case 0x1023: lg_map_key_clear(KEY_CLOSE); break; - case 0x1027: lg_map_key_clear(KEY_MENU); break; - /* this one is marked as 'Rotate' */ - case 0x1028: lg_map_key_clear(KEY_ANGLE); break; - case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break; - case 0x102a: lg_map_key_clear(KEY_BACK); break; - case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break; - case 0x102d: lg_map_key_clear(KEY_WWW); break; - /* The following two are 'Start/answer call' and 'End/reject call' - on the MX3200 */ - case 0x1031: lg_map_key_clear(KEY_OK); break; - case 0x1032: lg_map_key_clear(KEY_CANCEL); break; - case 0x1041: lg_map_key_clear(KEY_BATTERY); break; - case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break; - case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break; - case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break; - case 0x1045: lg_map_key_clear(KEY_UNDO); break; - case 0x1046: lg_map_key_clear(KEY_REDO); break; - case 0x1047: lg_map_key_clear(KEY_PRINT); break; - case 0x1048: lg_map_key_clear(KEY_SAVE); break; - case 0x1049: lg_map_key_clear(KEY_PROG1); break; - case 0x104a: lg_map_key_clear(KEY_PROG2); break; - case 0x104b: lg_map_key_clear(KEY_PROG3); break; - case 0x104c: lg_map_key_clear(KEY_PROG4); break; - - default: - return 0; - } - return 1; -} - -static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - /* extended mapping for certain Logitech hardware (Logitech cordless - desktop LX500) */ - static const u8 e_keymap[] = { - 0,216, 0,213,175,156, 0, 0, 0, 0, - 144, 0, 0, 0, 0, 0, 0, 0, 0,212, - 174,167,152,161,112, 0, 0, 0,154, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,183,184,185,186,187, - 188,189,190,191,192,193,194, 0, 0, 0 - }; - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - unsigned int hid = usage->hid; - - if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && - lg_ultrax_remote_mapping(hi, usage, bit, max)) - return 1; - - if (hdev->product == USB_DEVICE_ID_DINOVO_MINI && - lg_dinovo_mapping(hi, usage, bit, max)) - return 1; - - if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) - return 1; - - if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON) - return 0; - - hid &= HID_USAGE; - - /* Special handling for Logitech Cordless Desktop */ - if (field->application == HID_GD_MOUSE) { - if ((quirks & LG_IGNORE_DOUBLED_WHEEL) && - (hid == 7 || hid == 8)) - return -1; - } else { - if ((quirks & LG_EXPANDED_KEYMAP) && - hid < ARRAY_SIZE(e_keymap) && - e_keymap[hid] != 0) { - hid_map_usage(hi, usage, bit, max, EV_KEY, - e_keymap[hid]); - return 1; - } - } - - return 0; -} - -static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && - (field->flags & HID_MAIN_ITEM_RELATIVE)) - field->flags &= ~HID_MAIN_ITEM_RELATIVE; - - if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY || - usage->type == EV_REL || usage->type == EV_ABS)) - clear_bit(usage->code, *bit); - - return 0; -} - -static int lg_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) { - input_event(field->hidinput->input, usage->type, usage->code, - -value); - return 1; - } - - return 0; -} - -static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - unsigned long quirks = id->driver_data; - unsigned int connect_mask = HID_CONNECT_DEFAULT; - int ret; - - hid_set_drvdata(hdev, (void *)quirks); - - if (quirks & LG_NOGET) - hdev->quirks |= HID_QUIRK_NOGET; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) - connect_mask &= ~HID_CONNECT_FF; - - ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - /* Setup wireless link with Logitech Wii wheel */ - if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { - unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); - - if (ret >= 0) { - /* insert a little delay of 10 jiffies ~ 40ms */ - wait_queue_head_t wait; - init_waitqueue_head (&wait); - wait_event_interruptible_timeout(wait, 0, 10); - - /* Select random Address */ - buf[1] = 0xB2; - get_random_bytes(&buf[2], 2); - - ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); - } - } - - if (quirks & LG_FF) - lgff_init(hdev); - if (quirks & LG_FF2) - lg2ff_init(hdev); - if (quirks & LG_FF3) - lg3ff_init(hdev); - if (quirks & LG_FF4) - lg4ff_init(hdev); - - return 0; -err_free: - return ret; -} - -static void lg_remove(struct hid_device *hdev) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - if(quirks & LG_FF4) - lg4ff_deinit(hdev); - - hid_hw_stop(hdev); -} - -static const struct hid_device_id lg_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), - .driver_data = LG_RDESC | LG_WIRELESS }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER), - .driver_data = LG_RDESC | LG_WIRELESS }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2), - .driver_data = LG_RDESC | LG_WIRELESS }, - - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER), - .driver_data = LG_BAD_RELATIVE_KEYS }, - - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP), - .driver_data = LG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE), - .driver_data = LG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), - .driver_data = LG_DUPLICATE_USAGES }, - - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), - .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), - .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, - - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), - .driver_data = LG_NOGET }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), - .driver_data = LG_NOGET | LG_FF4 }, - - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), - .driver_data = LG_FF2 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), - .driver_data = LG_FF }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), - .driver_data = LG_FF }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D), - .driver_data = LG_FF }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO), - .driver_data = LG_FF }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL), - .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), - .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), - .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL), - .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), - .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), - .driver_data = LG_NOGET | LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), - .driver_data = LG_FF4 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), - .driver_data = LG_FF }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), - .driver_data = LG_FF2 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940), - .driver_data = LG_FF3 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR), - .driver_data = LG_RDESC_REL_ABS }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER), - .driver_data = LG_RDESC_REL_ABS }, - { } -}; - -MODULE_DEVICE_TABLE(hid, lg_devices); - -static struct hid_driver lg_driver = { - .name = "logitech", - .id_table = lg_devices, - .report_fixup = lg_report_fixup, - .input_mapping = lg_input_mapping, - .input_mapped = lg_input_mapped, - .event = lg_event, - .probe = lg_probe, - .remove = lg_remove, -}; - -static int __init lg_init(void) -{ - return hid_register_driver(&lg_driver); -} - -static void __exit lg_exit(void) -{ - hid_unregister_driver(&lg_driver); -} - -module_init(lg_init); -module_exit(lg_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-lg.h b/ANDROID_3.4.5/drivers/hid/hid-lg.h deleted file mode 100644 index 4b097286..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lg.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __HID_LG_H -#define __HID_LG_H - -#ifdef CONFIG_LOGITECH_FF -int lgff_init(struct hid_device *hdev); -#else -static inline int lgff_init(struct hid_device *hdev) { return -1; } -#endif - -#ifdef CONFIG_LOGIRUMBLEPAD2_FF -int lg2ff_init(struct hid_device *hdev); -#else -static inline int lg2ff_init(struct hid_device *hdev) { return -1; } -#endif - -#ifdef CONFIG_LOGIG940_FF -int lg3ff_init(struct hid_device *hdev); -#else -static inline int lg3ff_init(struct hid_device *hdev) { return -1; } -#endif - -#ifdef CONFIG_LOGIWHEELS_FF -int lg4ff_init(struct hid_device *hdev); -int lg4ff_deinit(struct hid_device *hdev); -#else -static inline int lg4ff_init(struct hid_device *hdev) { return -1; } -static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; } -#endif - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-lg2ff.c b/ANDROID_3.4.5/drivers/hid/hid-lg2ff.c deleted file mode 100644 index 3c31bc65..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lg2ff.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Force feedback support for Logitech RumblePad and Rumblepad 2 - * - * Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/hid.h> - -#include "usbhid/usbhid.h" -#include "hid-lg.h" - -struct lg2ff_device { - struct hid_report *report; -}; - -static int play_effect(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct lg2ff_device *lg2ff = data; - int weak, strong; - - strong = effect->u.rumble.strong_magnitude; - weak = effect->u.rumble.weak_magnitude; - - if (weak || strong) { - weak = weak * 0xff / 0xffff; - strong = strong * 0xff / 0xffff; - - lg2ff->report->field[0]->value[0] = 0x51; - lg2ff->report->field[0]->value[2] = weak; - lg2ff->report->field[0]->value[4] = strong; - } else { - lg2ff->report->field[0]->value[0] = 0xf3; - lg2ff->report->field[0]->value[2] = 0x00; - lg2ff->report->field[0]->value[4] = 0x00; - } - - usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT); - return 0; -} - -int lg2ff_init(struct hid_device *hid) -{ - struct lg2ff_device *lg2ff; - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); - return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 1) { - hid_err(hid, "output report is empty\n"); - return -ENODEV; - } - if (report->field[0]->report_count < 7) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } - - lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); - if (!lg2ff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, lg2ff, play_effect); - if (error) { - kfree(lg2ff); - return error; - } - - lg2ff->report = report; - report->field[0]->value[0] = 0xf3; - report->field[0]->value[1] = 0x00; - report->field[0]->value[2] = 0x00; - report->field[0]->value[3] = 0x00; - report->field[0]->value[4] = 0x00; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - usbhid_submit_report(hid, report, USB_DIR_OUT); - - hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n"); - - return 0; -} diff --git a/ANDROID_3.4.5/drivers/hid/hid-lg3ff.c b/ANDROID_3.4.5/drivers/hid/hid-lg3ff.c deleted file mode 100644 index f98644c2..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lg3ff.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Force feedback support for Logitech Flight System G940 - * - * Copyright (c) 2009 Gary Stein <LordCnidarian@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/input.h> -#include <linux/usb.h> -#include <linux/hid.h> - -#include "usbhid/usbhid.h" -#include "hid-lg.h" - -/* - * G940 Theory of Operation (from experimentation) - * - * There are 63 fields (only 3 of them currently used) - * 0 - seems to be command field - * 1 - 30 deal with the x axis - * 31 -60 deal with the y axis - * - * Field 1 is x axis constant force - * Field 31 is y axis constant force - * - * other interesting fields 1,2,3,4 on x axis - * (same for 31,32,33,34 on y axis) - * - * 0 0 127 127 makes the joystick autocenter hard - * - * 127 0 127 127 makes the joystick loose on the right, - * but stops all movemnt left - * - * -127 0 -127 -127 makes the joystick loose on the left, - * but stops all movement right - * - * 0 0 -127 -127 makes the joystick rattle very hard - * - * I'm sure these are effects that I don't know enough about them - */ - -struct lg3ff_device { - struct hid_report *report; -}; - -static int hid_lg3ff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int x, y; - -/* - * Maxusage should always be 63 (maximum fields) - * likely a better way to ensure this data is clean - */ - memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); - - switch (effect->type) { - case FF_CONSTANT: -/* - * Already clamped in ff_memless - * 0 is center (different then other logitech) - */ - x = effect->u.ramp.start_level; - y = effect->u.ramp.end_level; - - /* send command byte */ - report->field[0]->value[0] = 0x51; - -/* - * Sign backwards from other Force3d pro - * which get recast here in two's complement 8 bits - */ - report->field[0]->value[1] = (unsigned char)(-x); - report->field[0]->value[31] = (unsigned char)(-y); - - usbhid_submit_report(hid, report, USB_DIR_OUT); - break; - } - return 0; -} -static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - -/* - * Auto Centering probed from device - * NOTE: deadman's switch on G940 must be covered - * for effects to work - */ - report->field[0]->value[0] = 0x51; - report->field[0]->value[1] = 0x00; - report->field[0]->value[2] = 0x00; - report->field[0]->value[3] = 0x7F; - report->field[0]->value[4] = 0x7F; - report->field[0]->value[31] = 0x00; - report->field[0]->value[32] = 0x00; - report->field[0]->value[33] = 0x7F; - report->field[0]->value[34] = 0x7F; - - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - - -static const signed short ff3_joystick_ac[] = { - FF_CONSTANT, - FF_AUTOCENTER, - -1 -}; - -int lg3ff_init(struct hid_device *hid) -{ - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; - const signed short *ff_bits = ff3_joystick_ac; - int error; - int i; - - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); - return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } - - /* Assume single fixed device G940 */ - for (i = 0; ff_bits[i] >= 0; i++) - set_bit(ff_bits[i], dev->ffbit); - - error = input_ff_create_memless(dev, NULL, hid_lg3ff_play); - if (error) - return error; - - if (test_bit(FF_AUTOCENTER, dev->ffbit)) - dev->ff->set_autocenter = hid_lg3ff_set_autocenter; - - hid_info(hid, "Force feedback for Logitech Flight System G940 by Gary Stein <LordCnidarian@gmail.com>\n"); - return 0; -} - diff --git a/ANDROID_3.4.5/drivers/hid/hid-lg4ff.c b/ANDROID_3.4.5/drivers/hid/hid-lg4ff.c deleted file mode 100644 index 6ecc9e22..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lg4ff.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Force feedback support for Logitech Speed Force Wireless - * - * http://wiibrew.org/wiki/Logitech_USB_steering_wheel - * - * Copyright (c) 2010 Simon Wood <simon@mungewell.org> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/input.h> -#include <linux/usb.h> -#include <linux/hid.h> - -#include "usbhid/usbhid.h" -#include "hid-lg.h" -#include "hid-ids.h" - -#define DFGT_REV_MAJ 0x13 -#define DFGT_REV_MIN 0x22 -#define DFP_REV_MAJ 0x11 -#define DFP_REV_MIN 0x06 -#define FFEX_REV_MAJ 0x21 -#define FFEX_REV_MIN 0x00 -#define G25_REV_MAJ 0x12 -#define G25_REV_MIN 0x22 -#define G27_REV_MAJ 0x12 -#define G27_REV_MIN 0x38 - -#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev) - -static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range); -static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range); -static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); - -static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store); - -static bool list_inited; - -struct lg4ff_device_entry { - char *device_id; /* Use name in respective kobject structure's address as the ID */ - __u16 range; - __u16 min_range; - __u16 max_range; - __u8 leds; - struct list_head list; - void (*set_range)(struct hid_device *hid, u16 range); -}; - -static struct lg4ff_device_entry device_list; - -static const signed short lg4ff_wheel_effects[] = { - FF_CONSTANT, - FF_AUTOCENTER, - -1 -}; - -struct lg4ff_wheel { - const __u32 product_id; - const signed short *ff_effects; - const __u16 min_range; - const __u16 max_range; - void (*set_range)(struct hid_device *hid, u16 range); -}; - -static const struct lg4ff_wheel lg4ff_devices[] = { - {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, - {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, - {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp}, - {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, - {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, - {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, - {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, - {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} -}; - -struct lg4ff_native_cmd { - const __u8 cmd_num; /* Number of commands to send */ - const __u8 cmd[]; -}; - -struct lg4ff_usb_revision { - const __u16 rev_maj; - const __u16 rev_min; - const struct lg4ff_native_cmd *command; -}; - -static const struct lg4ff_native_cmd native_dfp = { - 1, - {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -static const struct lg4ff_native_cmd native_dfgt = { - 2, - {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */ - 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00} /* 2nd command */ -}; - -static const struct lg4ff_native_cmd native_g25 = { - 1, - {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -static const struct lg4ff_native_cmd native_g27 = { - 2, - {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */ - 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* 2nd command */ -}; - -static const struct lg4ff_usb_revision lg4ff_revs[] = { - {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */ - {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */ - {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */ - {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */ -}; - -static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int x; - -#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff - - switch (effect->type) { - case FF_CONSTANT: - x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ - CLAMP(x); - report->field[0]->value[0] = 0x11; /* Slot 1 */ - report->field[0]->value[1] = 0x08; - report->field[0]->value[2] = x; - report->field[0]->value[3] = 0x80; - report->field[0]->value[4] = 0x00; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - usbhid_submit_report(hid, report, USB_DIR_OUT); - break; - } - return 0; -} - -/* Sends default autocentering command compatible with - * all wheels except Formula Force EX */ -static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - - report->field[0]->value[0] = 0xfe; - report->field[0]->value[1] = 0x0d; - report->field[0]->value[2] = magnitude >> 13; - report->field[0]->value[3] = magnitude >> 13; - report->field[0]->value[4] = magnitude >> 8; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - -/* Sends autocentering command compatible with Formula Force EX */ -static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - magnitude = magnitude * 90 / 65535; - - - report->field[0]->value[0] = 0xfe; - report->field[0]->value[1] = 0x03; - report->field[0]->value[2] = magnitude >> 14; - report->field[0]->value[3] = magnitude >> 14; - report->field[0]->value[4] = magnitude; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - -/* Sends command to set range compatible with G25/G27/Driving Force GT */ -static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) -{ - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - dbg_hid("G25/G27/DFGT: setting range to %u\n", range); - - report->field[0]->value[0] = 0xf8; - report->field[0]->value[1] = 0x81; - report->field[0]->value[2] = range & 0x00ff; - report->field[0]->value[3] = (range & 0xff00) >> 8; - report->field[0]->value[4] = 0x00; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - -/* Sends commands to set range compatible with Driving Force Pro wheel */ -static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) -{ - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int start_left, start_right, full_range; - dbg_hid("Driving Force Pro: setting range to %u\n", range); - - /* Prepare "coarse" limit command */ - report->field[0]->value[0] = 0xf8; - report->field[0]->value[1] = 0x00; /* Set later */ - report->field[0]->value[2] = 0x00; - report->field[0]->value[3] = 0x00; - report->field[0]->value[4] = 0x00; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - if (range > 200) { - report->field[0]->value[1] = 0x03; - full_range = 900; - } else { - report->field[0]->value[1] = 0x02; - full_range = 200; - } - usbhid_submit_report(hid, report, USB_DIR_OUT); - - /* Prepare "fine" limit command */ - report->field[0]->value[0] = 0x81; - report->field[0]->value[1] = 0x0b; - report->field[0]->value[2] = 0x00; - report->field[0]->value[3] = 0x00; - report->field[0]->value[4] = 0x00; - report->field[0]->value[5] = 0x00; - report->field[0]->value[6] = 0x00; - - if (range == 200 || range == 900) { /* Do not apply any fine limit */ - usbhid_submit_report(hid, report, USB_DIR_OUT); - return; - } - - /* Construct fine limit command */ - start_left = (((full_range - range + 1) * 2047) / full_range); - start_right = 0xfff - start_left; - - report->field[0]->value[2] = start_left >> 4; - report->field[0]->value[3] = start_right >> 4; - report->field[0]->value[4] = 0xff; - report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); - report->field[0]->value[6] = 0xff; - - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - -static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd) -{ - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __u8 i, j; - - j = 0; - while (j < 7*cmd->cmd_num) { - for (i = 0; i < 7; i++) - report->field[0]->value[i] = cmd->cmd[j++]; - - usbhid_submit_report(hid, report, USB_DIR_OUT); - } -} - -/* Read current range and display it in terminal */ -static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct lg4ff_device_entry *uninitialized_var(entry); - struct list_head *h; - struct hid_device *hid = to_hid_device(dev); - size_t count; - - list_for_each(h, &device_list.list) { - entry = list_entry(h, struct lg4ff_device_entry, list); - if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) - break; - } - if (h == &device_list.list) { - dbg_hid("Device not found!"); - return 0; - } - - count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range); - return count; -} - -/* Set range to user specified value, call appropriate function - * according to the type of the wheel */ -static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct lg4ff_device_entry *uninitialized_var(entry); - struct list_head *h; - struct hid_device *hid = to_hid_device(dev); - __u16 range = simple_strtoul(buf, NULL, 10); - - list_for_each(h, &device_list.list) { - entry = list_entry(h, struct lg4ff_device_entry, list); - if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) - break; - } - if (h == &device_list.list) { - dbg_hid("Device not found!"); - return count; - } - - if (range == 0) - range = entry->max_range; - - /* Check if the wheel supports range setting - * and that the range is within limits for the wheel */ - if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) { - entry->set_range(hid, range); - entry->range = range; - } - - return count; -} - -int lg4ff_init(struct hid_device *hid) -{ - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; - struct lg4ff_device_entry *entry; - struct usb_device_descriptor *udesc; - int error, i, j; - __u16 bcdDevice, rev_maj, rev_min; - - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); - return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } - - /* Check what wheel has been connected */ - for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { - if (hid->product == lg4ff_devices[i].product_id) { - dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id); - break; - } - } - - if (i == ARRAY_SIZE(lg4ff_devices)) { - hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to" - "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n"); - return -1; - } - - /* Attempt to switch wheel to native mode when applicable */ - udesc = &(hid_to_usb_dev(hid)->descriptor); - if (!udesc) { - hid_err(hid, "NULL USB device descriptor\n"); - return -1; - } - bcdDevice = le16_to_cpu(udesc->bcdDevice); - rev_maj = bcdDevice >> 8; - rev_min = bcdDevice & 0xff; - - if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) { - dbg_hid("Generic wheel detected, can it do native?\n"); - dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min); - - for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) { - if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) { - hid_lg4ff_switch_native(hid, lg4ff_revs[j].command); - hid_info(hid, "Switched to native mode\n"); - } - } - } - - /* Set supported force feedback capabilities */ - for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++) - set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit); - - error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); - - if (error) - return error; - - /* Check if autocentering is available and - * set the centering force to zero by default */ - if (test_bit(FF_AUTOCENTER, dev->ffbit)) { - if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; - else - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; - - dev->ff->set_autocenter(dev, 0); - } - - /* Initialize device_list if this is the first device to handle by lg4ff */ - if (!list_inited) { - INIT_LIST_HEAD(&device_list.list); - list_inited = 1; - } - - /* Add the device to device_list */ - entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); - if (!entry) { - hid_err(hid, "Cannot add device, insufficient memory.\n"); - return -ENOMEM; - } - entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL); - if (!entry->device_id) { - hid_err(hid, "Cannot set device_id, insufficient memory.\n"); - kfree(entry); - return -ENOMEM; - } - entry->min_range = lg4ff_devices[i].min_range; - entry->max_range = lg4ff_devices[i].max_range; - entry->set_range = lg4ff_devices[i].set_range; - list_add(&entry->list, &device_list.list); - - /* Create sysfs interface */ - error = device_create_file(&hid->dev, &dev_attr_range); - if (error) - return error; - dbg_hid("sysfs interface created\n"); - - /* Set the maximum range to start with */ - entry->range = entry->max_range; - if (entry->set_range != NULL) - entry->set_range(hid, entry->range); - - hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n"); - return 0; -} - -int lg4ff_deinit(struct hid_device *hid) -{ - bool found = 0; - struct lg4ff_device_entry *entry; - struct list_head *h, *g; - list_for_each_safe(h, g, &device_list.list) { - entry = list_entry(h, struct lg4ff_device_entry, list); - if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) { - list_del(h); - kfree(entry->device_id); - kfree(entry); - found = 1; - break; - } - } - - if (!found) { - dbg_hid("Device entry not found!\n"); - return -1; - } - - device_remove_file(&hid->dev, &dev_attr_range); - dbg_hid("Device successfully unregistered\n"); - return 0; -} diff --git a/ANDROID_3.4.5/drivers/hid/hid-lgff.c b/ANDROID_3.4.5/drivers/hid/hid-lgff.c deleted file mode 100644 index 27bc54f9..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-lgff.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Force feedback support for hid-compliant for some of the devices from - * Logitech, namely: - * - WingMan Cordless RumblePad - * - WingMan Force 3D - * - * Copyright (c) 2002-2004 Johann Deneux - * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <johann.deneux@it.uu.se> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/input.h> -#include <linux/usb.h> -#include <linux/hid.h> - -#include "usbhid/usbhid.h" -#include "hid-lg.h" - -struct dev_type { - u16 idVendor; - u16 idProduct; - const signed short *ff; -}; - -static const signed short ff_rumble[] = { - FF_RUMBLE, - -1 -}; - -static const signed short ff_joystick[] = { - FF_CONSTANT, - -1 -}; - -static const signed short ff_joystick_ac[] = { - FF_CONSTANT, - FF_AUTOCENTER, - -1 -}; - -static const struct dev_type devices[] = { - { 0x046d, 0xc211, ff_rumble }, - { 0x046d, 0xc219, ff_rumble }, - { 0x046d, 0xc283, ff_joystick }, - { 0x046d, 0xc286, ff_joystick_ac }, - { 0x046d, 0xc287, ff_joystick_ac }, - { 0x046d, 0xc293, ff_joystick }, - { 0x046d, 0xc295, ff_joystick }, -}; - -static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int x, y; - unsigned int left, right; - -#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff - - switch (effect->type) { - case FF_CONSTANT: - x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */ - y = effect->u.ramp.end_level + 0x7f; - CLAMP(x); - CLAMP(y); - report->field[0]->value[0] = 0x51; - report->field[0]->value[1] = 0x08; - report->field[0]->value[2] = x; - report->field[0]->value[3] = y; - dbg_hid("(x, y)=(%04x, %04x)\n", x, y); - usbhid_submit_report(hid, report, USB_DIR_OUT); - break; - - case FF_RUMBLE: - right = effect->u.rumble.strong_magnitude; - left = effect->u.rumble.weak_magnitude; - right = right * 0xff / 0xffff; - left = left * 0xff / 0xffff; - CLAMP(left); - CLAMP(right); - report->field[0]->value[0] = 0x42; - report->field[0]->value[1] = 0x00; - report->field[0]->value[2] = left; - report->field[0]->value[3] = right; - dbg_hid("(left, right)=(%04x, %04x)\n", left, right); - usbhid_submit_report(hid, report, USB_DIR_OUT); - break; - } - return 0; -} - -static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; - magnitude = (magnitude >> 12) & 0xf; - *value++ = 0xfe; - *value++ = 0x0d; - *value++ = magnitude; /* clockwise strength */ - *value++ = magnitude; /* counter-clockwise strength */ - *value++ = 0x80; - *value++ = 0x00; - *value = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - -int lgff_init(struct hid_device* hid) -{ - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; - const signed short *ff_bits = ff_joystick; - int error; - int i; - - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } - - for (i = 0; i < ARRAY_SIZE(devices); i++) { - if (dev->id.vendor == devices[i].idVendor && - dev->id.product == devices[i].idProduct) { - ff_bits = devices[i].ff; - break; - } - } - - for (i = 0; ff_bits[i] >= 0; i++) - set_bit(ff_bits[i], dev->ffbit); - - error = input_ff_create_memless(dev, NULL, hid_lgff_play); - if (error) - return error; - - if ( test_bit(FF_AUTOCENTER, dev->ffbit) ) - dev->ff->set_autocenter = hid_lgff_set_autocenter; - - pr_info("Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); - - return 0; -} diff --git a/ANDROID_3.4.5/drivers/hid/hid-magicmouse.c b/ANDROID_3.4.5/drivers/hid/hid-magicmouse.c deleted file mode 100644 index 8427463b..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-magicmouse.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Apple "Magic" Wireless Mouse driver - * - * Copyright (c) 2010 Michael Poole <mdpoole@troilus.org> - * Copyright (c) 2010 Chase Douglas <chase.douglas@canonical.com> - */ - -/* - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/device.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "hid-ids.h" - -static bool emulate_3button = true; -module_param(emulate_3button, bool, 0644); -MODULE_PARM_DESC(emulate_3button, "Emulate a middle button"); - -static int middle_button_start = -350; -static int middle_button_stop = +350; - -static bool emulate_scroll_wheel = true; -module_param(emulate_scroll_wheel, bool, 0644); -MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); - -static unsigned int scroll_speed = 32; -static int param_set_scroll_speed(const char *val, struct kernel_param *kp) { - unsigned long speed; - if (!val || strict_strtoul(val, 0, &speed) || speed > 63) - return -EINVAL; - scroll_speed = speed; - return 0; -} -module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644); -MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)"); - -static bool scroll_acceleration = false; -module_param(scroll_acceleration, bool, 0644); -MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); - -static bool report_touches = true; -module_param(report_touches, bool, 0644); -MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); - -static bool report_undeciphered; -module_param(report_undeciphered, bool, 0644); -MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); - -#define TRACKPAD_REPORT_ID 0x28 -#define MOUSE_REPORT_ID 0x29 -#define DOUBLE_REPORT_ID 0xf7 -/* These definitions are not precise, but they're close enough. (Bits - * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem - * to be some kind of bit mask -- 0x20 may be a near-field reading, - * and 0x40 is actual contact, and 0x10 may be a start/stop or change - * indication.) - */ -#define TOUCH_STATE_MASK 0xf0 -#define TOUCH_STATE_NONE 0x00 -#define TOUCH_STATE_START 0x30 -#define TOUCH_STATE_DRAG 0x40 - -#define SCROLL_ACCEL_DEFAULT 7 - -/* Single touch emulation should only begin when no touches are currently down. - * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches - * are down and the touch providing for single touch emulation is lifted, - * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is - * occurring, single_touch_id corresponds with the tracking id of the touch used. - */ -#define NO_TOUCHES -1 -#define SINGLE_TOUCH_UP -2 - -/* Touch surface information. Dimension is in hundredths of a mm, min and max - * are in units. */ -#define MOUSE_DIMENSION_X (float)9056 -#define MOUSE_MIN_X -1100 -#define MOUSE_MAX_X 1258 -#define MOUSE_RES_X ((MOUSE_MAX_X - MOUSE_MIN_X) / (MOUSE_DIMENSION_X / 100)) -#define MOUSE_DIMENSION_Y (float)5152 -#define MOUSE_MIN_Y -1589 -#define MOUSE_MAX_Y 2047 -#define MOUSE_RES_Y ((MOUSE_MAX_Y - MOUSE_MIN_Y) / (MOUSE_DIMENSION_Y / 100)) - -#define TRACKPAD_DIMENSION_X (float)13000 -#define TRACKPAD_MIN_X -2909 -#define TRACKPAD_MAX_X 3167 -#define TRACKPAD_RES_X \ - ((TRACKPAD_MAX_X - TRACKPAD_MIN_X) / (TRACKPAD_DIMENSION_X / 100)) -#define TRACKPAD_DIMENSION_Y (float)11000 -#define TRACKPAD_MIN_Y -2456 -#define TRACKPAD_MAX_Y 2565 -#define TRACKPAD_RES_Y \ - ((TRACKPAD_MAX_Y - TRACKPAD_MIN_Y) / (TRACKPAD_DIMENSION_Y / 100)) - -/** - * struct magicmouse_sc - Tracks Magic Mouse-specific data. - * @input: Input device through which we report events. - * @quirks: Currently unused. - * @ntouches: Number of touches in most recent touch report. - * @scroll_accel: Number of consecutive scroll motions. - * @scroll_jiffies: Time of last scroll motion. - * @touches: Most recent data for a touch, indexed by tracking ID. - * @tracking_ids: Mapping of current touch input data to @touches. - */ -struct magicmouse_sc { - struct input_dev *input; - unsigned long quirks; - - int ntouches; - int scroll_accel; - unsigned long scroll_jiffies; - - struct { - short x; - short y; - short scroll_x; - short scroll_y; - u8 size; - } touches[16]; - int tracking_ids[16]; - int single_touch_id; -}; - -static int magicmouse_firm_touch(struct magicmouse_sc *msc) -{ - int touch = -1; - int ii; - - /* If there is only one "firm" touch, set touch to its - * tracking ID. - */ - for (ii = 0; ii < msc->ntouches; ii++) { - int idx = msc->tracking_ids[ii]; - if (msc->touches[idx].size < 8) { - /* Ignore this touch. */ - } else if (touch >= 0) { - touch = -1; - break; - } else { - touch = idx; - } - } - - return touch; -} - -static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) -{ - int last_state = test_bit(BTN_LEFT, msc->input->key) << 0 | - test_bit(BTN_RIGHT, msc->input->key) << 1 | - test_bit(BTN_MIDDLE, msc->input->key) << 2; - - if (emulate_3button) { - int id; - - /* If some button was pressed before, keep it held - * down. Otherwise, if there's exactly one firm - * touch, use that to override the mouse's guess. - */ - if (state == 0) { - /* The button was released. */ - } else if (last_state != 0) { - state = last_state; - } else if ((id = magicmouse_firm_touch(msc)) >= 0) { - int x = msc->touches[id].x; - if (x < middle_button_start) - state = 1; - else if (x > middle_button_stop) - state = 2; - else - state = 4; - } /* else: we keep the mouse's guess */ - - input_report_key(msc->input, BTN_MIDDLE, state & 4); - } - - input_report_key(msc->input, BTN_LEFT, state & 1); - input_report_key(msc->input, BTN_RIGHT, state & 2); - - if (state != last_state) - msc->scroll_accel = SCROLL_ACCEL_DEFAULT; -} - -static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) -{ - struct input_dev *input = msc->input; - int id, x, y, size, orientation, touch_major, touch_minor, state, down; - - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { - id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf; - x = (tdata[1] << 28 | tdata[0] << 20) >> 20; - y = -((tdata[2] << 24 | tdata[1] << 16) >> 20); - size = tdata[5] & 0x3f; - orientation = (tdata[6] >> 2) - 32; - touch_major = tdata[3]; - touch_minor = tdata[4]; - state = tdata[7] & TOUCH_STATE_MASK; - down = state != TOUCH_STATE_NONE; - } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ - id = (tdata[7] << 2 | tdata[6] >> 6) & 0xf; - x = (tdata[1] << 27 | tdata[0] << 19) >> 19; - y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19); - size = tdata[6] & 0x3f; - orientation = (tdata[7] >> 2) - 32; - touch_major = tdata[4]; - touch_minor = tdata[5]; - state = tdata[8] & TOUCH_STATE_MASK; - down = state != TOUCH_STATE_NONE; - } - - /* Store tracking ID and other fields. */ - msc->tracking_ids[raw_id] = id; - msc->touches[id].x = x; - msc->touches[id].y = y; - msc->touches[id].size = size; - - /* If requested, emulate a scroll wheel by detecting small - * vertical touch motions. - */ - if (emulate_scroll_wheel) { - unsigned long now = jiffies; - int step_x = msc->touches[id].scroll_x - x; - int step_y = msc->touches[id].scroll_y - y; - - /* Calculate and apply the scroll motion. */ - switch (state) { - case TOUCH_STATE_START: - msc->touches[id].scroll_x = x; - msc->touches[id].scroll_y = y; - - /* Reset acceleration after half a second. */ - if (scroll_acceleration && time_before(now, - msc->scroll_jiffies + HZ / 2)) - msc->scroll_accel = max_t(int, - msc->scroll_accel - 1, 1); - else - msc->scroll_accel = SCROLL_ACCEL_DEFAULT; - - break; - case TOUCH_STATE_DRAG: - step_x /= (64 - (int)scroll_speed) * msc->scroll_accel; - if (step_x != 0) { - msc->touches[id].scroll_x -= step_x * - (64 - scroll_speed) * msc->scroll_accel; - msc->scroll_jiffies = now; - input_report_rel(input, REL_HWHEEL, -step_x); - } - - step_y /= (64 - (int)scroll_speed) * msc->scroll_accel; - if (step_y != 0) { - msc->touches[id].scroll_y -= step_y * - (64 - scroll_speed) * msc->scroll_accel; - msc->scroll_jiffies = now; - input_report_rel(input, REL_WHEEL, step_y); - } - break; - } - } - - if (down) { - msc->ntouches++; - if (msc->single_touch_id == NO_TOUCHES) - msc->single_touch_id = id; - } else if (msc->single_touch_id == id) - msc->single_touch_id = SINGLE_TOUCH_UP; - - /* Generate the input events for this touch. */ - if (report_touches && down) { - input_report_abs(input, ABS_MT_TRACKING_ID, id); - input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); - input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); - input_report_abs(input, ABS_MT_ORIENTATION, -orientation); - input_report_abs(input, ABS_MT_POSITION_X, x); - input_report_abs(input, ABS_MT_POSITION_Y, y); - - if (report_undeciphered) { - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) - input_event(input, EV_MSC, MSC_RAW, tdata[7]); - else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ - input_event(input, EV_MSC, MSC_RAW, tdata[8]); - } - - input_mt_sync(input); - } -} - -static int magicmouse_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *data, int size) -{ - struct magicmouse_sc *msc = hid_get_drvdata(hdev); - struct input_dev *input = msc->input; - int x = 0, y = 0, ii, clicks = 0, npoints; - - switch (data[0]) { - case TRACKPAD_REPORT_ID: - /* Expect four bytes of prefix, and N*9 bytes of touch data. */ - if (size < 4 || ((size - 4) % 9) != 0) - return 0; - npoints = (size - 4) / 9; - msc->ntouches = 0; - for (ii = 0; ii < npoints; ii++) - magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); - - /* We don't need an MT sync here because trackpad emits a - * BTN_TOUCH event in a new frame when all touches are released. - */ - if (msc->ntouches == 0) - msc->single_touch_id = NO_TOUCHES; - - clicks = data[1]; - - /* The following bits provide a device specific timestamp. They - * are unused here. - * - * ts = data[1] >> 6 | data[2] << 2 | data[3] << 10; - */ - break; - case MOUSE_REPORT_ID: - /* Expect six bytes of prefix, and N*8 bytes of touch data. */ - if (size < 6 || ((size - 6) % 8) != 0) - return 0; - npoints = (size - 6) / 8; - msc->ntouches = 0; - for (ii = 0; ii < npoints; ii++) - magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); - - if (report_touches && msc->ntouches == 0) - input_mt_sync(input); - - /* When emulating three-button mode, it is important - * to have the current touch information before - * generating a click event. - */ - x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; - y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; - clicks = data[3]; - - /* The following bits provide a device specific timestamp. They - * are unused here. - * - * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; - */ - break; - case DOUBLE_REPORT_ID: - /* Sometimes the trackpad sends two touch reports in one - * packet. - */ - magicmouse_raw_event(hdev, report, data + 2, data[1]); - magicmouse_raw_event(hdev, report, data + 2 + data[1], - size - 2 - data[1]); - break; - default: - return 0; - } - - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { - magicmouse_emit_buttons(msc, clicks & 3); - input_report_rel(input, REL_X, x); - input_report_rel(input, REL_Y, y); - } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ - input_report_key(input, BTN_MOUSE, clicks & 1); - input_report_key(input, BTN_TOUCH, msc->ntouches > 0); - input_report_key(input, BTN_TOOL_FINGER, msc->ntouches == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, msc->ntouches == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, msc->ntouches == 3); - input_report_key(input, BTN_TOOL_QUADTAP, msc->ntouches == 4); - if (msc->single_touch_id >= 0) { - input_report_abs(input, ABS_X, - msc->touches[msc->single_touch_id].x); - input_report_abs(input, ABS_Y, - msc->touches[msc->single_touch_id].y); - } - } - - input_sync(input); - return 1; -} - -static int magicmouse_setup_input(struct hid_device *hdev, struct hid_input *hi) -{ - struct input_dev *input = hi->input; - - __set_bit(EV_KEY, input->evbit); - - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { - __set_bit(BTN_LEFT, input->keybit); - __set_bit(BTN_RIGHT, input->keybit); - if (emulate_3button) - __set_bit(BTN_MIDDLE, input->keybit); - - __set_bit(EV_REL, input->evbit); - __set_bit(REL_X, input->relbit); - __set_bit(REL_Y, input->relbit); - if (emulate_scroll_wheel) { - __set_bit(REL_WHEEL, input->relbit); - __set_bit(REL_HWHEEL, input->relbit); - } - } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ - /* input->keybit is initialized with incorrect button info - * for Magic Trackpad. There really is only one physical - * button (BTN_LEFT == BTN_MOUSE). Make sure we don't - * advertise buttons that don't exist... - */ - __clear_bit(BTN_RIGHT, input->keybit); - __clear_bit(BTN_MIDDLE, input->keybit); - __set_bit(BTN_MOUSE, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); - __set_bit(BTN_TOOL_QUADTAP, input->keybit); - __set_bit(BTN_TOUCH, input->keybit); - __set_bit(INPUT_PROP_POINTER, input->propbit); - __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); - } - - if (report_touches) { - __set_bit(EV_ABS, input->evbit); - - input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); - input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); - - /* Note: Touch Y position from the device is inverted relative - * to how pointer motion is reported (and relative to how USB - * HID recommends the coordinates work). This driver keeps - * the origin at the same position, and just uses the additive - * inverse of the reported Y. - */ - if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { - input_set_abs_params(input, ABS_MT_POSITION_X, - MOUSE_MIN_X, MOUSE_MAX_X, 4, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, - MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0); - - input_abs_set_res(input, ABS_MT_POSITION_X, - MOUSE_RES_X); - input_abs_set_res(input, ABS_MT_POSITION_Y, - MOUSE_RES_Y); - } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ - input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X, - TRACKPAD_MAX_X, 4, 0); - input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y, - TRACKPAD_MAX_Y, 4, 0); - input_set_abs_params(input, ABS_MT_POSITION_X, - TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, - TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0); - - input_abs_set_res(input, ABS_X, TRACKPAD_RES_X); - input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y); - input_abs_set_res(input, ABS_MT_POSITION_X, - TRACKPAD_RES_X); - input_abs_set_res(input, ABS_MT_POSITION_Y, - TRACKPAD_RES_Y); - } - - input_set_events_per_packet(input, 60); - } - - if (report_undeciphered) { - __set_bit(EV_MSC, input->evbit); - __set_bit(MSC_RAW, input->mscbit); - } - - return 0; -} - -static int magicmouse_input_mapping(struct hid_device *hdev, - struct hid_input *hi, struct hid_field *field, - struct hid_usage *usage, unsigned long **bit, int *max) -{ - struct magicmouse_sc *msc = hid_get_drvdata(hdev); - - if (!msc->input) - msc->input = hi->input; - - /* Magic Trackpad does not give relative data after switching to MT */ - if (hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD && - field->flags & HID_MAIN_ITEM_RELATIVE) - return -1; - - return 0; -} - -static int magicmouse_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - __u8 feature[] = { 0xd7, 0x01 }; - struct magicmouse_sc *msc; - struct hid_report *report; - int ret; - - msc = kzalloc(sizeof(*msc), GFP_KERNEL); - if (msc == NULL) { - hid_err(hdev, "can't alloc magicmouse descriptor\n"); - return -ENOMEM; - } - - msc->scroll_accel = SCROLL_ACCEL_DEFAULT; - - msc->quirks = id->driver_data; - hid_set_drvdata(hdev, msc); - - msc->single_touch_id = NO_TOUCHES; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "magicmouse hid parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "magicmouse hw start failed\n"); - goto err_free; - } - - if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) - report = hid_register_report(hdev, HID_INPUT_REPORT, - MOUSE_REPORT_ID); - else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ - report = hid_register_report(hdev, HID_INPUT_REPORT, - TRACKPAD_REPORT_ID); - report = hid_register_report(hdev, HID_INPUT_REPORT, - DOUBLE_REPORT_ID); - } - - if (!report) { - hid_err(hdev, "unable to register touch report\n"); - ret = -ENOMEM; - goto err_stop_hw; - } - report->size = 6; - - /* - * Some devices repond with 'invalid report id' when feature - * report switching it into multitouch mode is sent to it. - * - * This results in -EIO from the _raw low-level transport callback, - * but there seems to be no other way of switching the mode. - * Thus the super-ugly hacky success check below. - */ - ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), - HID_FEATURE_REPORT); - if (ret != -EIO && ret != sizeof(feature)) { - hid_err(hdev, "unable to request touch data (%d)\n", ret); - goto err_stop_hw; - } - - return 0; -err_stop_hw: - hid_hw_stop(hdev); -err_free: - kfree(msc); - return ret; -} - -static void magicmouse_remove(struct hid_device *hdev) -{ - struct magicmouse_sc *msc = hid_get_drvdata(hdev); - - hid_hw_stop(hdev); - kfree(msc); -} - -static const struct hid_device_id magic_mice[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, - USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, - USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 }, - { } -}; -MODULE_DEVICE_TABLE(hid, magic_mice); - -static struct hid_driver magicmouse_driver = { - .name = "magicmouse", - .id_table = magic_mice, - .probe = magicmouse_probe, - .remove = magicmouse_remove, - .raw_event = magicmouse_raw_event, - .input_mapping = magicmouse_input_mapping, - .input_register = magicmouse_setup_input, -}; - -static int __init magicmouse_init(void) -{ - int ret; - - ret = hid_register_driver(&magicmouse_driver); - if (ret) - pr_err("can't register magicmouse driver\n"); - - return ret; -} - -static void __exit magicmouse_exit(void) -{ - hid_unregister_driver(&magicmouse_driver); -} - -module_init(magicmouse_init); -module_exit(magicmouse_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-microsoft.c b/ANDROID_3.4.5/drivers/hid/hid-microsoft.c deleted file mode 100644 index e5c699b6..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-microsoft.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * HID driver for some microsoft "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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/input.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#define MS_HIDINPUT 0x01 -#define MS_ERGONOMY 0x02 -#define MS_PRESENTER 0x04 -#define MS_RDESC 0x08 -#define MS_NOGET 0x10 -#define MS_DUPLICATE_USAGES 0x20 - -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ -static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && - rdesc[559] == 0x29) { - hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); - rdesc[557] = 0x35; - rdesc[559] = 0x45; - } - return rdesc; -} - -#define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct input_dev *input = hi->input; - - switch (usage->hid & HID_USAGE) { - case 0xfd06: ms_map_key_clear(KEY_CHAT); break; - case 0xfd07: ms_map_key_clear(KEY_PHONE); break; - case 0xff05: - set_bit(EV_REP, input->evbit); - ms_map_key_clear(KEY_F13); - set_bit(KEY_F14, input->keybit); - set_bit(KEY_F15, input->keybit); - set_bit(KEY_F16, input->keybit); - set_bit(KEY_F17, input->keybit); - set_bit(KEY_F18, input->keybit); - default: - return 0; - } - return 1; -} - -static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - set_bit(EV_REP, hi->input->evbit); - switch (usage->hid & HID_USAGE) { - case 0xfd08: ms_map_key_clear(KEY_FORWARD); break; - case 0xfd09: ms_map_key_clear(KEY_BACK); break; - case 0xfd0b: ms_map_key_clear(KEY_PLAYPAUSE); break; - case 0xfd0e: ms_map_key_clear(KEY_CLOSE); break; - case 0xfd0f: ms_map_key_clear(KEY_PLAY); break; - default: - return 0; - } - return 1; -} - -static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR) - return 0; - - if (quirks & MS_ERGONOMY) { - int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max); - if (ret) - return ret; - } - - if ((quirks & MS_PRESENTER) && - ms_presenter_8k_quirk(hi, usage, bit, max)) - return 1; - - return 0; -} - -static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if (quirks & MS_DUPLICATE_USAGES) - clear_bit(usage->code, *bit); - - return 0; -} - -static int ms_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); - - if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || - !usage->type) - return 0; - - /* Handling MS keyboards special buttons */ - if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) { - struct input_dev *input = field->hidinput->input; - static unsigned int last_key = 0; - unsigned int key = 0; - switch (value) { - case 0x01: key = KEY_F14; break; - case 0x02: key = KEY_F15; break; - case 0x04: key = KEY_F16; break; - case 0x08: key = KEY_F17; break; - case 0x10: key = KEY_F18; break; - } - if (key) { - input_event(input, usage->type, key, 1); - last_key = key; - } else - input_event(input, usage->type, last_key, 0); - - return 1; - } - - return 0; -} - -static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - unsigned long quirks = id->driver_data; - int ret; - - hid_set_drvdata(hdev, (void *)quirks); - - if (quirks & MS_NOGET) - hdev->quirks |= HID_QUIRK_NOGET; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ? - HID_CONNECT_HIDINPUT_FORCE : 0)); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - return ret; -} - -static const struct hid_device_id ms_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV), - .driver_data = MS_HIDINPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K), - .driver_data = MS_ERGONOMY }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K), - .driver_data = MS_ERGONOMY | MS_RDESC }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), - .driver_data = MS_PRESENTER }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), - .driver_data = MS_NOGET }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), - .driver_data = MS_DUPLICATE_USAGES }, - - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), - .driver_data = MS_PRESENTER }, - { } -}; -MODULE_DEVICE_TABLE(hid, ms_devices); - -static struct hid_driver ms_driver = { - .name = "microsoft", - .id_table = ms_devices, - .report_fixup = ms_report_fixup, - .input_mapping = ms_input_mapping, - .input_mapped = ms_input_mapped, - .event = ms_event, - .probe = ms_probe, -}; - -static int __init ms_init(void) -{ - return hid_register_driver(&ms_driver); -} - -static void __exit ms_exit(void) -{ - hid_unregister_driver(&ms_driver); -} - -module_init(ms_init); -module_exit(ms_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-monterey.c b/ANDROID_3.4.5/drivers/hid/hid-monterey.c deleted file mode 100644 index dedf7577..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-monterey.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * HID driver for some monterey "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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" - -static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { - hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); - rdesc[30] = 0x0c; - } - return rdesc; -} - -#define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int mr_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x156: mr_map_key_clear(KEY_WORDPROCESSOR); break; - case 0x157: mr_map_key_clear(KEY_SPREADSHEET); break; - case 0x158: mr_map_key_clear(KEY_PRESENTATION); break; - case 0x15c: mr_map_key_clear(KEY_STOP); break; - default: - return 0; - } - return 1; -} - -static const struct hid_device_id mr_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, - { } -}; -MODULE_DEVICE_TABLE(hid, mr_devices); - -static struct hid_driver mr_driver = { - .name = "monterey", - .id_table = mr_devices, - .report_fixup = mr_report_fixup, - .input_mapping = mr_input_mapping, -}; - -static int __init mr_init(void) -{ - return hid_register_driver(&mr_driver); -} - -static void __exit mr_exit(void) -{ - hid_unregister_driver(&mr_driver); -} - -module_init(mr_init); -module_exit(mr_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-multitouch.c b/ANDROID_3.4.5/drivers/hid/hid-multitouch.c deleted file mode 100644 index 8cf4310a..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-multitouch.c +++ /dev/null @@ -1,1081 +0,0 @@ -/* - * HID driver for multitouch panels - * - * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr> - * Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com> - * Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France - * - * This code is partly based on hid-egalax.c: - * - * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr> - * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> - * Copyright (c) 2010 Canonical, Ltd. - * - * This code is partly based on hid-3m-pct.c: - * - * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> - * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> - * Copyright (c) 2010 Canonical, Ltd. - * - */ - -/* - * 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 <linux/slab.h> -#include <linux/usb.h> -#include <linux/input/mt.h> -#include "usbhid/usbhid.h" - - -MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); -MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); -MODULE_DESCRIPTION("HID multitouch panels"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -/* quirks to control the device */ -#define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0) -#define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) -#define MT_QUIRK_CYPRESS (1 << 2) -#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) -#define MT_QUIRK_ALWAYS_VALID (1 << 4) -#define MT_QUIRK_VALID_IS_INRANGE (1 << 5) -#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) -#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) - -struct mt_slot { - __s32 x, y, p, w, h; - __s32 contactid; /* the device ContactID assigned to this slot */ - bool touch_state; /* is the touch valid? */ - bool seen_in_this_frame;/* has this slot been updated */ -}; - -struct mt_class { - __s32 name; /* MT_CLS */ - __s32 quirks; - __s32 sn_move; /* Signal/noise ratio for move events */ - __s32 sn_width; /* Signal/noise ratio for width events */ - __s32 sn_height; /* Signal/noise ratio for height events */ - __s32 sn_pressure; /* Signal/noise ratio for pressure events */ - __u8 maxcontacts; - bool is_indirect; /* true for touchpads */ -}; - -struct mt_fields { - unsigned usages[HID_MAX_FIELDS]; - unsigned int length; -}; - -struct mt_device { - struct mt_slot curdata; /* placeholder of incoming data */ - struct mt_class mtclass; /* our mt device class */ - struct mt_fields *fields; /* temporary placeholder for storing the - multitouch fields */ - unsigned last_field_index; /* last field index of the report */ - unsigned last_slot_field; /* the last field of a slot */ - __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ - __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, - -1 if non-existent */ - __u8 num_received; /* how many contacts we received */ - __u8 num_expected; /* expected last contact index */ - __u8 maxcontacts; - __u8 touches_by_report; /* how many touches are present in one report: - * 1 means we should use a serial protocol - * > 1 means hybrid (multitouch) protocol */ - bool curvalid; /* is the current contact valid? */ - struct mt_slot *slots; -}; - -/* classes of device behavior */ -#define MT_CLS_DEFAULT 0x0001 - -#define MT_CLS_SERIAL 0x0002 -#define MT_CLS_CONFIDENCE 0x0003 -#define MT_CLS_CONFIDENCE_CONTACT_ID 0x0004 -#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005 -#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006 -#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007 -#define MT_CLS_DUAL_NSMU_CONTACTID 0x0008 -#define MT_CLS_INRANGE_CONTACTNUMBER 0x0009 - -/* vendor specific classes */ -#define MT_CLS_3M 0x0101 -#define MT_CLS_CYPRESS 0x0102 -#define MT_CLS_EGALAX 0x0103 -#define MT_CLS_EGALAX_SERIAL 0x0104 -#define MT_CLS_TOPSEED 0x0105 -#define MT_CLS_PANASONIC 0x0106 - -#define MT_DEFAULT_MAXCONTACT 10 - -/* - * these device-dependent functions determine what slot corresponds - * to a valid contact that was just read. - */ - -static int cypress_compute_slot(struct mt_device *td) -{ - if (td->curdata.contactid != 0 || td->num_received == 0) - return td->curdata.contactid; - else - return -1; -} - -static int find_slot_from_contactid(struct mt_device *td) -{ - int i; - for (i = 0; i < td->maxcontacts; ++i) { - if (td->slots[i].contactid == td->curdata.contactid && - td->slots[i].touch_state) - return i; - } - for (i = 0; i < td->maxcontacts; ++i) { - if (!td->slots[i].seen_in_this_frame && - !td->slots[i].touch_state) - return i; - } - /* should not occurs. If this happens that means - * that the device sent more touches that it says - * in the report descriptor. It is ignored then. */ - return -1; -} - -static struct mt_class mt_classes[] = { - { .name = MT_CLS_DEFAULT, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, - { .name = MT_CLS_SERIAL, - .quirks = MT_QUIRK_ALWAYS_VALID}, - { .name = MT_CLS_CONFIDENCE, - .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, - { .name = MT_CLS_CONFIDENCE_CONTACT_ID, - .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | - MT_QUIRK_SLOT_IS_CONTACTID }, - { .name = MT_CLS_CONFIDENCE_MINUS_ONE, - .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | - MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, - { .name = MT_CLS_DUAL_INRANGE_CONTACTID, - .quirks = MT_QUIRK_VALID_IS_INRANGE | - MT_QUIRK_SLOT_IS_CONTACTID, - .maxcontacts = 2 }, - { .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, - .quirks = MT_QUIRK_VALID_IS_INRANGE | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, - .maxcontacts = 2 }, - { .name = MT_CLS_DUAL_NSMU_CONTACTID, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTID, - .maxcontacts = 2 }, - { .name = MT_CLS_INRANGE_CONTACTNUMBER, - .quirks = MT_QUIRK_VALID_IS_INRANGE | - MT_QUIRK_SLOT_IS_CONTACTNUMBER }, - - /* - * vendor specific classes - */ - { .name = MT_CLS_3M, - .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | - MT_QUIRK_SLOT_IS_CONTACTID, - .sn_move = 2048, - .sn_width = 128, - .sn_height = 128 }, - { .name = MT_CLS_CYPRESS, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_CYPRESS, - .maxcontacts = 10 }, - { .name = MT_CLS_EGALAX, - .quirks = MT_QUIRK_SLOT_IS_CONTACTID | - MT_QUIRK_VALID_IS_INRANGE, - .sn_move = 4096, - .sn_pressure = 32, - }, - { .name = MT_CLS_EGALAX_SERIAL, - .quirks = MT_QUIRK_SLOT_IS_CONTACTID | - MT_QUIRK_ALWAYS_VALID, - .sn_move = 4096, - .sn_pressure = 32, - }, - { .name = MT_CLS_TOPSEED, - .quirks = MT_QUIRK_ALWAYS_VALID, - .is_indirect = true, - .maxcontacts = 2, - }, - { .name = MT_CLS_PANASONIC, - .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP, - .maxcontacts = 4 }, - - { } -}; - -static ssize_t mt_show_quirks(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct mt_device *td = hid_get_drvdata(hdev); - - return sprintf(buf, "%u\n", td->mtclass.quirks); -} - -static ssize_t mt_set_quirks(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct mt_device *td = hid_get_drvdata(hdev); - - unsigned long val; - - if (kstrtoul(buf, 0, &val)) - return -EINVAL; - - td->mtclass.quirks = val; - - return count; -} - -static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks); - -static struct attribute *sysfs_attrs[] = { - &dev_attr_quirks.attr, - NULL -}; - -static struct attribute_group mt_attribute_group = { - .attrs = sysfs_attrs -}; - -static void mt_feature_mapping(struct hid_device *hdev, - struct hid_field *field, struct hid_usage *usage) -{ - struct mt_device *td = hid_get_drvdata(hdev); - - switch (usage->hid) { - case HID_DG_INPUTMODE: - td->inputmode = field->report->id; - break; - case HID_DG_CONTACTMAX: - td->maxcontact_report_id = field->report->id; - td->maxcontacts = field->value[0]; - if (td->mtclass.maxcontacts) - /* check if the maxcontacts is given by the class */ - td->maxcontacts = td->mtclass.maxcontacts; - - break; - } -} - -static void set_abs(struct input_dev *input, unsigned int code, - struct hid_field *field, int snratio) -{ - int fmin = field->logical_minimum; - int fmax = field->logical_maximum; - int fuzz = snratio ? (fmax - fmin) / snratio : 0; - input_set_abs_params(input, code, fmin, fmax, fuzz, 0); -} - -static void mt_store_field(struct hid_usage *usage, struct mt_device *td, - struct hid_input *hi) -{ - struct mt_fields *f = td->fields; - - if (f->length >= HID_MAX_FIELDS) - return; - - f->usages[f->length++] = usage->hid; -} - -static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct mt_device *td = hid_get_drvdata(hdev); - struct mt_class *cls = &td->mtclass; - int code; - - /* Only map fields from TouchScreen or TouchPad collections. - * We need to ignore fields that belong to other collections - * such as Mouse that might have the same GenericDesktop usages. */ - if (field->application == HID_DG_TOUCHSCREEN) - set_bit(INPUT_PROP_DIRECT, hi->input->propbit); - else if (field->application != HID_DG_TOUCHPAD) - return 0; - - /* In case of an indirect device (touchpad), we need to add - * specific BTN_TOOL_* to be handled by the synaptics xorg - * driver. - * We also consider that touchscreens providing buttons are touchpads. - */ - if (field->application == HID_DG_TOUCHPAD || - (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON || - cls->is_indirect) { - set_bit(INPUT_PROP_POINTER, hi->input->propbit); - set_bit(BTN_TOOL_FINGER, hi->input->keybit); - set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit); - set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit); - set_bit(BTN_TOOL_QUADTAP, hi->input->keybit); - } - - /* eGalax devices provide a Digitizer.Stylus input which overrides - * the correct Digitizers.Finger X/Y ranges. - * Let's just ignore this input. */ - if (field->physical == HID_DG_STYLUS) - return -1; - - /* Only map fields from TouchScreen or TouchPad collections. - * We need to ignore fields that belong to other collections - * such as Mouse that might have the same GenericDesktop usages. */ - if (field->application == HID_DG_TOUCHSCREEN) - set_bit(INPUT_PROP_DIRECT, hi->input->propbit); - else if (field->application == HID_DG_TOUCHPAD) - set_bit(INPUT_PROP_POINTER, hi->input->propbit); - else - return 0; - - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - set_abs(hi->input, ABS_MT_POSITION_X, field, - cls->sn_move); - /* touchscreen emulation */ - set_abs(hi->input, ABS_X, field, cls->sn_move); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - set_abs(hi->input, ABS_MT_POSITION_Y, field, - cls->sn_move); - /* touchscreen emulation */ - set_abs(hi->input, ABS_Y, field, cls->sn_move); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - case HID_DG_INRANGE: - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_DG_CONFIDENCE: - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_DG_TIPSWITCH: - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - input_set_capability(hi->input, EV_KEY, BTN_TOUCH); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_DG_CONTACTID: - if (!td->maxcontacts) - td->maxcontacts = MT_DEFAULT_MAXCONTACT; - input_mt_init_slots(hi->input, td->maxcontacts); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - td->touches_by_report++; - return 1; - case HID_DG_WIDTH: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); - set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, - cls->sn_width); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_DG_HEIGHT: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); - set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, - cls->sn_height); - input_set_abs_params(hi->input, - ABS_MT_ORIENTATION, 0, 1, 0, 0); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_DG_TIPPRESSURE: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_PRESSURE); - set_abs(hi->input, ABS_MT_PRESSURE, field, - cls->sn_pressure); - /* touchscreen emulation */ - set_abs(hi->input, ABS_PRESSURE, field, - cls->sn_pressure); - mt_store_field(usage, td, hi); - td->last_field_index = field->index; - return 1; - case HID_DG_CONTACTCOUNT: - td->last_field_index = field->index; - return 1; - case HID_DG_CONTACTMAX: - /* we don't set td->last_slot_field as contactcount and - * contact max are global to the report */ - td->last_field_index = field->index; - return -1; - } - case HID_DG_TOUCH: - /* Legacy devices use TIPSWITCH and not TOUCH. - * Let's just ignore this field. */ - return -1; - /* let hid-input decide for the others */ - return 0; - - case HID_UP_BUTTON: - code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); - hid_map_usage(hi, usage, bit, max, EV_KEY, code); - input_set_capability(hi->input, EV_KEY, code); - return 1; - - case 0xff000000: - /* we do not want to map these: no input-oriented meaning */ - return -1; - } - - return 0; -} - -static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - set_bit(usage->type, hi->input->evbit); - - return -1; -} - -static int mt_compute_slot(struct mt_device *td) -{ - __s32 quirks = td->mtclass.quirks; - - if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) - return td->curdata.contactid; - - if (quirks & MT_QUIRK_CYPRESS) - return cypress_compute_slot(td); - - if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) - return td->num_received; - - if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) - return td->curdata.contactid - 1; - - return find_slot_from_contactid(td); -} - -/* - * this function is called when a whole contact has been processed, - * so that it can assign it to a slot and store the data there - */ -static void mt_complete_slot(struct mt_device *td) -{ - td->curdata.seen_in_this_frame = true; - if (td->curvalid) { - int slotnum = mt_compute_slot(td); - - if (slotnum >= 0 && slotnum < td->maxcontacts) - td->slots[slotnum] = td->curdata; - } - td->num_received++; -} - - -/* - * this function is called when a whole packet has been received and processed, - * so that it can decide what to send to the input layer. - */ -static void mt_emit_event(struct mt_device *td, struct input_dev *input) -{ - int i; - - for (i = 0; i < td->maxcontacts; ++i) { - struct mt_slot *s = &(td->slots[i]); - if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && - !s->seen_in_this_frame) { - s->touch_state = false; - } - - input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, - s->touch_state); - if (s->touch_state) { - /* this finger is on the screen */ - int wide = (s->w > s->h); - /* divided by two to match visual scale of touch */ - int major = max(s->w, s->h) >> 1; - int minor = min(s->w, s->h) >> 1; - - input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); - input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); - input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); - input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); - input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); - } - s->seen_in_this_frame = false; - - } - - input_mt_report_pointer_emulation(input, true); - input_sync(input); - td->num_received = 0; -} - - - -static int mt_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct mt_device *td = hid_get_drvdata(hid); - __s32 quirks = td->mtclass.quirks; - - if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { - switch (usage->hid) { - case HID_DG_INRANGE: - if (quirks & MT_QUIRK_ALWAYS_VALID) - td->curvalid = true; - else if (quirks & MT_QUIRK_VALID_IS_INRANGE) - td->curvalid = value; - break; - case HID_DG_TIPSWITCH: - if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) - td->curvalid = value; - td->curdata.touch_state = value; - break; - case HID_DG_CONFIDENCE: - if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE) - td->curvalid = value; - break; - case HID_DG_CONTACTID: - td->curdata.contactid = value; - break; - case HID_DG_TIPPRESSURE: - td->curdata.p = value; - break; - case HID_GD_X: - td->curdata.x = value; - break; - case HID_GD_Y: - td->curdata.y = value; - break; - case HID_DG_WIDTH: - td->curdata.w = value; - break; - case HID_DG_HEIGHT: - td->curdata.h = value; - break; - case HID_DG_CONTACTCOUNT: - /* - * Includes multi-packet support where subsequent - * packets are sent with zero contactcount. - */ - if (value) - td->num_expected = value; - break; - case HID_DG_TOUCH: - /* do nothing */ - break; - - default: - /* fallback to the generic hidinput handling */ - return 0; - } - - if (usage->hid == td->last_slot_field) - mt_complete_slot(td); - - if (field->index == td->last_field_index - && td->num_received >= td->num_expected) - mt_emit_event(td, field->hidinput->input); - - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static void mt_set_input_mode(struct hid_device *hdev) -{ - struct mt_device *td = hid_get_drvdata(hdev); - struct hid_report *r; - struct hid_report_enum *re; - - if (td->inputmode < 0) - return; - - re = &(hdev->report_enum[HID_FEATURE_REPORT]); - r = re->report_id_hash[td->inputmode]; - if (r) { - r->field[0]->value[0] = 0x02; - usbhid_submit_report(hdev, r, USB_DIR_OUT); - } -} - -static void mt_set_maxcontacts(struct hid_device *hdev) -{ - struct mt_device *td = hid_get_drvdata(hdev); - struct hid_report *r; - struct hid_report_enum *re; - int fieldmax, max; - - if (td->maxcontact_report_id < 0) - return; - - if (!td->mtclass.maxcontacts) - return; - - re = &hdev->report_enum[HID_FEATURE_REPORT]; - r = re->report_id_hash[td->maxcontact_report_id]; - if (r) { - max = td->mtclass.maxcontacts; - fieldmax = r->field[0]->logical_maximum; - max = min(fieldmax, max); - if (r->field[0]->value[0] != max) { - r->field[0]->value[0] = max; - usbhid_submit_report(hdev, r, USB_DIR_OUT); - } - } -} - -static void mt_post_parse(struct mt_device *td) -{ - struct mt_fields *f = td->fields; - - if (td->touches_by_report > 0) { - int field_count_per_touch = f->length / td->touches_by_report; - td->last_slot_field = f->usages[field_count_per_touch - 1]; - } -} - -static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret, i; - struct mt_device *td; - struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ - - if (id) { - for (i = 0; mt_classes[i].name ; i++) { - if (id->driver_data == mt_classes[i].name) { - mtclass = &(mt_classes[i]); - break; - } - } - } - - /* This allows the driver to correctly support devices - * that emit events over several HID messages. - */ - hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; - hdev->quirks &= ~HID_QUIRK_MULTITOUCH; - - td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); - if (!td) { - dev_err(&hdev->dev, "cannot allocate multitouch data\n"); - return -ENOMEM; - } - td->mtclass = *mtclass; - td->inputmode = -1; - td->maxcontact_report_id = -1; - hid_set_drvdata(hdev, td); - - td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); - if (!td->fields) { - dev_err(&hdev->dev, "cannot allocate multitouch fields data\n"); - ret = -ENOMEM; - goto fail; - } - - ret = hid_parse(hdev); - if (ret != 0) - goto fail; - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) - goto fail; - - mt_post_parse(td); - - if (!id && td->touches_by_report == 1) { - /* the device has been sent by hid-generic */ - mtclass = &td->mtclass; - mtclass->quirks |= MT_QUIRK_ALWAYS_VALID; - mtclass->quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP; - mtclass->quirks &= ~MT_QUIRK_VALID_IS_INRANGE; - mtclass->quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE; - } - - td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), - GFP_KERNEL); - if (!td->slots) { - dev_err(&hdev->dev, "cannot allocate multitouch slots\n"); - hid_hw_stop(hdev); - ret = -ENOMEM; - goto fail; - } - - ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); - - mt_set_maxcontacts(hdev); - mt_set_input_mode(hdev); - - kfree(td->fields); - td->fields = NULL; - - return 0; - -fail: - kfree(td->fields); - kfree(td); - return ret; -} - -#ifdef CONFIG_PM -static int mt_reset_resume(struct hid_device *hdev) -{ - mt_set_maxcontacts(hdev); - mt_set_input_mode(hdev); - return 0; -} -#endif - -static void mt_remove(struct hid_device *hdev) -{ - struct mt_device *td = hid_get_drvdata(hdev); - sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); - hid_hw_stop(hdev); - kfree(td->slots); - kfree(td); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id mt_devices[] = { - - /* 3M panels */ - { .driver_data = MT_CLS_3M, - HID_USB_DEVICE(USB_VENDOR_ID_3M, - USB_DEVICE_ID_3M1968) }, - { .driver_data = MT_CLS_3M, - HID_USB_DEVICE(USB_VENDOR_ID_3M, - USB_DEVICE_ID_3M2256) }, - { .driver_data = MT_CLS_3M, - HID_USB_DEVICE(USB_VENDOR_ID_3M, - USB_DEVICE_ID_3M3266) }, - - /* ActionStar panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, - USB_DEVICE_ID_ACTIONSTAR_1011) }, - - /* Atmel panels */ - { .driver_data = MT_CLS_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_ATMEL, - USB_DEVICE_ID_ATMEL_MULTITOUCH) }, - { .driver_data = MT_CLS_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_ATMEL, - USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) }, - - /* Cando panels */ - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, - - /* Chunghwa Telecom touch panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, - USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, - - /* CVTouch panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, - USB_DEVICE_ID_CVTOUCH_SCREEN) }, - - /* Cypress panel */ - { .driver_data = MT_CLS_CYPRESS, - HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, - USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, - - /* eGalax devices (resistive) */ - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, - - /* eGalax devices (capacitive) */ - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) }, - { .driver_data = MT_CLS_EGALAX, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) }, - { .driver_data = MT_CLS_EGALAX_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_DWAV, - USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, - - /* Elo TouchSystems IntelliTouch Plus panel */ - { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, - HID_USB_DEVICE(USB_VENDOR_ID_ELO, - USB_DEVICE_ID_ELO_TS2515) }, - - /* GeneralTouch panel */ - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, - USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, - - /* Gametel game controller */ - { .driver_data = MT_CLS_DEFAULT, - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_FRUCTEL, - USB_DEVICE_ID_GAMETEL_MT_MODE) }, - - /* GoodTouch panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, - USB_DEVICE_ID_GOODTOUCH_000f) }, - - /* Hanvon panels */ - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, - HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, - USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, - - /* Ideacom panel */ - { .driver_data = MT_CLS_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, - USB_DEVICE_ID_IDEACOM_IDC6650) }, - { .driver_data = MT_CLS_SERIAL, - HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, - USB_DEVICE_ID_IDEACOM_IDC6651) }, - - /* Ilitek dual touch panel */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, - USB_DEVICE_ID_ILITEK_MULTITOUCH) }, - - /* IRTOUCH panels */ - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, - HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, - USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, - - /* LG Display panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_LG, - USB_DEVICE_ID_LG_MULTITOUCH) }, - - /* Lumio panels */ - { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, - HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, - USB_DEVICE_ID_CRYSTALTOUCH) }, - { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, - HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, - USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, - - /* MosArt panels */ - { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, - HID_USB_DEVICE(USB_VENDOR_ID_ASUS, - USB_DEVICE_ID_ASUS_T91MT)}, - { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, - HID_USB_DEVICE(USB_VENDOR_ID_ASUS, - USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, - { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, - HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, - USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, - - /* Panasonic panels */ - { .driver_data = MT_CLS_PANASONIC, - HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, - USB_DEVICE_ID_PANABOARD_UBT780) }, - { .driver_data = MT_CLS_PANASONIC, - HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, - USB_DEVICE_ID_PANABOARD_UBT880) }, - - /* PenMount panels */ - { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, - USB_DEVICE_ID_PENMOUNT_PCI) }, - - /* PixArt optical touch screen */ - { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_PIXART, - USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, - { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_PIXART, - USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, - { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, - HID_USB_DEVICE(USB_VENDOR_ID_PIXART, - USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, - - /* PixCir-based panels */ - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, - HID_USB_DEVICE(USB_VENDOR_ID_HANVON, - USB_DEVICE_ID_HANVON_MULTITOUCH) }, - { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, - HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, - - /* Quanta-based panels */ - { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, - HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, - USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, - { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, - HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, - USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) }, - { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, - HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, - USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, - - /* Stantum panels */ - { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, - USB_DEVICE_ID_MTP)}, - { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, - USB_DEVICE_ID_MTP_STM)}, - { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, - USB_DEVICE_ID_MTP_SITRONIX)}, - - /* TopSeed panels */ - { .driver_data = MT_CLS_TOPSEED, - HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, - USB_DEVICE_ID_TOPSEED2_PERIPAD_701) }, - - /* Touch International panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, - USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) }, - - /* Unitec panels */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, - USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, - USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, - /* XAT */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XAT, - USB_DEVICE_ID_XAT_CSR) }, - - /* Xiroku */ - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_SPX) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_MPX) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_CSR) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_SPX1) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_MPX1) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_CSR1) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_SPX2) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_MPX2) }, - { .driver_data = MT_CLS_DEFAULT, - HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_CSR2) }, - - { } -}; -MODULE_DEVICE_TABLE(hid, mt_devices); - -static const struct hid_usage_id mt_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver mt_driver = { - .name = "hid-multitouch", - .id_table = mt_devices, - .probe = mt_probe, - .remove = mt_remove, - .input_mapping = mt_input_mapping, - .input_mapped = mt_input_mapped, - .feature_mapping = mt_feature_mapping, - .usage_table = mt_grabbed_usages, - .event = mt_event, -#ifdef CONFIG_PM - .reset_resume = mt_reset_resume, -#endif -}; - -static int __init mt_init(void) -{ - return hid_register_driver(&mt_driver); -} - -static void __exit mt_exit(void) -{ - hid_unregister_driver(&mt_driver); -} - -module_init(mt_init); -module_exit(mt_exit); diff --git a/ANDROID_3.4.5/drivers/hid/hid-ntrig.c b/ANDROID_3.4.5/drivers/hid/hid-ntrig.c deleted file mode 100644 index 9fae2ebd..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-ntrig.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * HID driver for N-Trig touchscreens - * - * Copyright (c) 2008-2010 Rafi Rubin - * Copyright (c) 2009-2010 Stephane Chatty - * - */ - -/* - * 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/usb.h> -#include "usbhid/usbhid.h" -#include <linux/module.h> -#include <linux/slab.h> - -#include "hid-ids.h" - -#define NTRIG_DUPLICATE_USAGES 0x001 - -static unsigned int min_width; -module_param(min_width, uint, 0644); -MODULE_PARM_DESC(min_width, "Minimum touch contact width to accept."); - -static unsigned int min_height; -module_param(min_height, uint, 0644); -MODULE_PARM_DESC(min_height, "Minimum touch contact height to accept."); - -static unsigned int activate_slack = 1; -module_param(activate_slack, uint, 0644); -MODULE_PARM_DESC(activate_slack, "Number of touch frames to ignore at " - "the start of touch input."); - -static unsigned int deactivate_slack = 4; -module_param(deactivate_slack, uint, 0644); -MODULE_PARM_DESC(deactivate_slack, "Number of empty frames to ignore before " - "deactivating touch."); - -static unsigned int activation_width = 64; -module_param(activation_width, uint, 0644); -MODULE_PARM_DESC(activation_width, "Width threshold to immediately start " - "processing touch events."); - -static unsigned int activation_height = 32; -module_param(activation_height, uint, 0644); -MODULE_PARM_DESC(activation_height, "Height threshold to immediately start " - "processing touch events."); - -struct ntrig_data { - /* Incoming raw values for a single contact */ - __u16 x, y, w, h; - __u16 id; - - bool tipswitch; - bool confidence; - bool first_contact_touch; - - bool reading_mt; - - __u8 mt_footer[4]; - __u8 mt_foot_count; - - /* The current activation state. */ - __s8 act_state; - - /* Empty frames to ignore before recognizing the end of activity */ - __s8 deactivate_slack; - - /* Frames to ignore before acknowledging the start of activity */ - __s8 activate_slack; - - /* Minimum size contact to accept */ - __u16 min_width; - __u16 min_height; - - /* Threshold to override activation slack */ - __u16 activation_width; - __u16 activation_height; - - __u16 sensor_logical_width; - __u16 sensor_logical_height; - __u16 sensor_physical_width; - __u16 sensor_physical_height; -}; - - -/* - * This function converts the 4 byte raw firmware code into - * a string containing 5 comma separated numbers. - */ -static int ntrig_version_string(unsigned char *raw, char *buf) -{ - __u8 a = (raw[1] & 0x0e) >> 1; - __u8 b = (raw[0] & 0x3c) >> 2; - __u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5); - __u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5); - __u8 e = raw[2] & 0x07; - - /* - * As yet unmapped bits: - * 0b11000000 0b11110001 0b00011000 0b00011000 - */ - - return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e); -} - -static inline int ntrig_get_mode(struct hid_device *hdev) -{ - struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. - report_id_hash[0x0d]; - - if (!report) - return -EINVAL; - - usbhid_submit_report(hdev, report, USB_DIR_IN); - usbhid_wait_io(hdev); - return (int)report->field[0]->value[0]; -} - -static inline void ntrig_set_mode(struct hid_device *hdev, const int mode) -{ - struct hid_report *report; - __u8 mode_commands[4] = { 0xe, 0xf, 0x1b, 0x10 }; - - if (mode < 0 || mode > 3) - return; - - report = hdev->report_enum[HID_FEATURE_REPORT]. - report_id_hash[mode_commands[mode]]; - - if (!report) - return; - - usbhid_submit_report(hdev, report, USB_DIR_IN); -} - -static void ntrig_report_version(struct hid_device *hdev) -{ - int ret; - char buf[20]; - struct usb_device *usb_dev = hid_to_usb_dev(hdev); - unsigned char *data = kmalloc(8, GFP_KERNEL); - - if (!data) - goto err_free; - - ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_DIR_IN, - 0x30c, 1, data, 8, - USB_CTRL_SET_TIMEOUT); - - if (ret == 8) { - ret = ntrig_version_string(&data[2], buf); - - hid_info(hdev, "Firmware version: %s (%02x%02x %02x%02x)\n", - buf, data[2], data[3], data[4], data[5]); - } - -err_free: - kfree(data); -} - -static ssize_t show_phys_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_physical_width); -} - -static DEVICE_ATTR(sensor_physical_width, S_IRUGO, show_phys_width, NULL); - -static ssize_t show_phys_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_physical_height); -} - -static DEVICE_ATTR(sensor_physical_height, S_IRUGO, show_phys_height, NULL); - -static ssize_t show_log_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_logical_width); -} - -static DEVICE_ATTR(sensor_logical_width, S_IRUGO, show_log_width, NULL); - -static ssize_t show_log_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_logical_height); -} - -static DEVICE_ATTR(sensor_logical_height, S_IRUGO, show_log_height, NULL); - -static ssize_t show_min_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->min_width * - nd->sensor_physical_width / - nd->sensor_logical_width); -} - -static ssize_t set_min_width(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_width) - return -EINVAL; - - nd->min_width = val * nd->sensor_logical_width / - nd->sensor_physical_width; - - return count; -} - -static DEVICE_ATTR(min_width, S_IWUSR | S_IRUGO, show_min_width, set_min_width); - -static ssize_t show_min_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->min_height * - nd->sensor_physical_height / - nd->sensor_logical_height); -} - -static ssize_t set_min_height(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_height) - return -EINVAL; - - nd->min_height = val * nd->sensor_logical_height / - nd->sensor_physical_height; - - return count; -} - -static DEVICE_ATTR(min_height, S_IWUSR | S_IRUGO, show_min_height, - set_min_height); - -static ssize_t show_activate_slack(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->activate_slack); -} - -static ssize_t set_activate_slack(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > 0x7f) - return -EINVAL; - - nd->activate_slack = val; - - return count; -} - -static DEVICE_ATTR(activate_slack, S_IWUSR | S_IRUGO, show_activate_slack, - set_activate_slack); - -static ssize_t show_activation_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->activation_width * - nd->sensor_physical_width / - nd->sensor_logical_width); -} - -static ssize_t set_activation_width(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_width) - return -EINVAL; - - nd->activation_width = val * nd->sensor_logical_width / - nd->sensor_physical_width; - - return count; -} - -static DEVICE_ATTR(activation_width, S_IWUSR | S_IRUGO, show_activation_width, - set_activation_width); - -static ssize_t show_activation_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->activation_height * - nd->sensor_physical_height / - nd->sensor_logical_height); -} - -static ssize_t set_activation_height(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_height) - return -EINVAL; - - nd->activation_height = val * nd->sensor_logical_height / - nd->sensor_physical_height; - - return count; -} - -static DEVICE_ATTR(activation_height, S_IWUSR | S_IRUGO, - show_activation_height, set_activation_height); - -static ssize_t show_deactivate_slack(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", -nd->deactivate_slack); -} - -static ssize_t set_deactivate_slack(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - /* - * No more than 8 terminal frames have been observed so far - * and higher slack is highly likely to leave the single - * touch emulation stuck down. - */ - if (val > 7) - return -EINVAL; - - nd->deactivate_slack = -val; - - return count; -} - -static DEVICE_ATTR(deactivate_slack, S_IWUSR | S_IRUGO, show_deactivate_slack, - set_deactivate_slack); - -static struct attribute *sysfs_attrs[] = { - &dev_attr_sensor_physical_width.attr, - &dev_attr_sensor_physical_height.attr, - &dev_attr_sensor_logical_width.attr, - &dev_attr_sensor_logical_height.attr, - &dev_attr_min_height.attr, - &dev_attr_min_width.attr, - &dev_attr_activate_slack.attr, - &dev_attr_activation_width.attr, - &dev_attr_activation_height.attr, - &dev_attr_deactivate_slack.attr, - NULL -}; - -static struct attribute_group ntrig_attribute_group = { - .attrs = sysfs_attrs -}; - -/* - * this driver is aimed at two firmware versions in circulation: - * - dual pen/finger single touch - * - finger multitouch, pen not working - */ - -static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct ntrig_data *nd = hid_get_drvdata(hdev); - - /* No special mappings needed for the pen and single touch */ - if (field->physical) - return 0; - - switch (usage->hid & HID_USAGE_PAGE) { - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - - if (!nd->sensor_logical_width) { - nd->sensor_logical_width = - field->logical_maximum - - field->logical_minimum; - nd->sensor_physical_width = - field->physical_maximum - - field->physical_minimum; - nd->activation_width = activation_width * - nd->sensor_logical_width / - nd->sensor_physical_width; - nd->min_width = min_width * - nd->sensor_logical_width / - nd->sensor_physical_width; - } - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - - if (!nd->sensor_logical_height) { - nd->sensor_logical_height = - field->logical_maximum - - field->logical_minimum; - nd->sensor_physical_height = - field->physical_maximum - - field->physical_minimum; - nd->activation_height = activation_height * - nd->sensor_logical_height / - nd->sensor_physical_height; - nd->min_height = min_height * - nd->sensor_logical_height / - nd->sensor_physical_height; - } - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - /* we do not want to map these for now */ - case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */ - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTMAX: - return -1; - - /* width/height mapped on TouchMajor/TouchMinor/Orientation */ - case HID_DG_WIDTH: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); - return 1; - case HID_DG_HEIGHT: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); - input_set_abs_params(hi->input, ABS_MT_ORIENTATION, - 0, 1, 0, 0); - return 1; - } - return 0; - - case 0xff000000: - /* we do not want to map these: no input-oriented meaning */ - return -1; - } - - return 0; -} - -static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - /* No special mappings needed for the pen and single touch */ - if (field->physical) - return 0; - - if (usage->type == EV_KEY || usage->type == EV_REL - || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called upon all reports - * so that we can filter contact point information, - * decide whether we are in multi or single touch mode - * and call input_mt_sync after each point if necessary - */ -static int ntrig_event (struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct ntrig_data *nd = hid_get_drvdata(hid); - struct input_dev *input; - - /* Skip processing if not a claimed input */ - if (!(hid->claimed & HID_CLAIMED_INPUT)) - goto not_claimed_input; - - /* This function is being called before the structures are fully - * initialized */ - if(!(field->hidinput && field->hidinput->input)) - return -EINVAL; - - input = field->hidinput->input; - - /* No special handling needed for the pen */ - if (field->application == HID_DG_PEN) - return 0; - - switch (usage->hid) { - case 0xff000001: - /* Tag indicating the start of a multitouch group */ - nd->reading_mt = 1; - nd->first_contact_touch = 0; - break; - case HID_DG_TIPSWITCH: - nd->tipswitch = value; - /* Prevent emission of touch until validated */ - return 1; - case HID_DG_CONFIDENCE: - nd->confidence = value; - break; - case HID_GD_X: - nd->x = value; - /* Clear the contact footer */ - nd->mt_foot_count = 0; - break; - case HID_GD_Y: - nd->y = value; - break; - case HID_DG_CONTACTID: - nd->id = value; - break; - case HID_DG_WIDTH: - nd->w = value; - break; - case HID_DG_HEIGHT: - nd->h = value; - /* - * when in single touch mode, this is the last - * report received in a finger event. We want - * to emit a normal (X, Y) position - */ - if (!nd->reading_mt) { - /* - * TipSwitch indicates the presence of a - * finger in single touch mode. - */ - input_report_key(input, BTN_TOUCH, - nd->tipswitch); - input_report_key(input, BTN_TOOL_DOUBLETAP, - nd->tipswitch); - input_event(input, EV_ABS, ABS_X, nd->x); - input_event(input, EV_ABS, ABS_Y, nd->y); - } - break; - case 0xff000002: - /* - * we receive this when the device is in multitouch - * mode. The first of the three values tagged with - * this usage tells if the contact point is real - * or a placeholder - */ - - /* Shouldn't get more than 4 footer packets, so skip */ - if (nd->mt_foot_count >= 4) - break; - - nd->mt_footer[nd->mt_foot_count++] = value; - - /* if the footer isn't complete break */ - if (nd->mt_foot_count != 4) - break; - - /* Pen activity signal. */ - if (nd->mt_footer[2]) { - /* - * When the pen deactivates touch, we see a - * bogus frame with ContactCount > 0. - * We can - * save a bit of work by ensuring act_state < 0 - * even if deactivation slack is turned off. - */ - nd->act_state = deactivate_slack - 1; - nd->confidence = 0; - break; - } - - /* - * The first footer value indicates the presence of a - * finger. - */ - if (nd->mt_footer[0]) { - /* - * We do not want to process contacts under - * the size threshold, but do not want to - * ignore them for activation state - */ - if (nd->w < nd->min_width || - nd->h < nd->min_height) - nd->confidence = 0; - } else - break; - - if (nd->act_state > 0) { - /* - * Contact meets the activation size threshold - */ - if (nd->w >= nd->activation_width && - nd->h >= nd->activation_height) { - if (nd->id) - /* - * first contact, activate now - */ - nd->act_state = 0; - else { - /* - * avoid corrupting this frame - * but ensure next frame will - * be active - */ - nd->act_state = 1; - break; - } - } else - /* - * Defer adjusting the activation state - * until the end of the frame. - */ - break; - } - - /* Discarding this contact */ - if (!nd->confidence) - break; - - /* emit a normal (X, Y) for the first point only */ - if (nd->id == 0) { - /* - * TipSwitch is superfluous in multitouch - * mode. The footer events tell us - * if there is a finger on the screen or - * not. - */ - nd->first_contact_touch = nd->confidence; - input_event(input, EV_ABS, ABS_X, nd->x); - input_event(input, EV_ABS, ABS_Y, nd->y); - } - - /* Emit MT events */ - input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); - - /* - * Translate from height and width to size - * and orientation. - */ - if (nd->w > nd->h) { - input_event(input, EV_ABS, - ABS_MT_ORIENTATION, 1); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MAJOR, nd->w); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MINOR, nd->h); - } else { - input_event(input, EV_ABS, - ABS_MT_ORIENTATION, 0); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MAJOR, nd->h); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MINOR, nd->w); - } - input_mt_sync(field->hidinput->input); - break; - - case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ - if (!nd->reading_mt) /* Just to be sure */ - break; - - nd->reading_mt = 0; - - - /* - * Activation state machine logic: - * - * Fundamental states: - * state > 0: Inactive - * state <= 0: Active - * state < -deactivate_slack: - * Pen termination of touch - * - * Specific values of interest - * state == activate_slack - * no valid input since the last reset - * - * state == 0 - * general operational state - * - * state == -deactivate_slack - * read sufficient empty frames to accept - * the end of input and reset - */ - - if (nd->act_state > 0) { /* Currently inactive */ - if (value) - /* - * Consider each live contact as - * evidence of intentional activity. - */ - nd->act_state = (nd->act_state > value) - ? nd->act_state - value - : 0; - else - /* - * Empty frame before we hit the - * activity threshold, reset. - */ - nd->act_state = nd->activate_slack; - - /* - * Entered this block inactive and no - * coordinates sent this frame, so hold off - * on button state. - */ - break; - } else { /* Currently active */ - if (value && nd->act_state >= - nd->deactivate_slack) - /* - * Live point: clear accumulated - * deactivation count. - */ - nd->act_state = 0; - else if (nd->act_state <= nd->deactivate_slack) - /* - * We've consumed the deactivation - * slack, time to deactivate and reset. - */ - nd->act_state = - nd->activate_slack; - else { /* Move towards deactivation */ - nd->act_state--; - break; - } - } - - if (nd->first_contact_touch && nd->act_state <= 0) { - /* - * Check to see if we're ready to start - * emitting touch events. - * - * Note: activation slack will decrease over - * the course of the frame, and it will be - * inconsistent from the start to the end of - * the frame. However if the frame starts - * with slack, first_contact_touch will still - * be 0 and we will not get to this point. - */ - input_report_key(input, BTN_TOOL_DOUBLETAP, 1); - input_report_key(input, BTN_TOUCH, 1); - } else { - input_report_key(input, BTN_TOOL_DOUBLETAP, 0); - input_report_key(input, BTN_TOUCH, 0); - } - break; - - default: - /* fall-back to the generic hidinput handling */ - return 0; - } - -not_claimed_input: - - /* we have handled the hidinput part, now remains hiddev */ - if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct ntrig_data *nd; - struct hid_input *hidinput; - struct input_dev *input; - struct hid_report *report; - - if (id->driver_data) - hdev->quirks |= HID_QUIRK_MULTI_INPUT - | HID_QUIRK_NO_INIT_REPORTS; - - nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); - if (!nd) { - hid_err(hdev, "cannot allocate N-Trig data\n"); - return -ENOMEM; - } - - nd->reading_mt = 0; - nd->min_width = 0; - nd->min_height = 0; - nd->activate_slack = activate_slack; - nd->act_state = activate_slack; - nd->deactivate_slack = -deactivate_slack; - nd->sensor_logical_width = 0; - nd->sensor_logical_height = 0; - nd->sensor_physical_width = 0; - nd->sensor_physical_height = 0; - - hid_set_drvdata(hdev, nd); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - - list_for_each_entry(hidinput, &hdev->inputs, list) { - if (hidinput->report->maxfield < 1) - continue; - - input = hidinput->input; - switch (hidinput->report->field[0]->application) { - case HID_DG_PEN: - input->name = "N-Trig Pen"; - break; - case HID_DG_TOUCHSCREEN: - /* These keys are redundant for fingers, clear them - * to prevent incorrect identification */ - __clear_bit(BTN_TOOL_PEN, input->keybit); - __clear_bit(BTN_TOOL_FINGER, input->keybit); - __clear_bit(BTN_0, input->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); - /* - * The physical touchscreen (single touch) - * input has a value for physical, whereas - * the multitouch only has logical input - * fields. - */ - input->name = - (hidinput->report->field[0] - ->physical) ? - "N-Trig Touchscreen" : - "N-Trig MultiTouch"; - break; - } - } - - /* This is needed for devices with more recent firmware versions */ - report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; - if (report) { - /* Let the device settle to ensure the wakeup message gets - * through */ - usbhid_wait_io(hdev); - usbhid_submit_report(hdev, report, USB_DIR_IN); - - /* - * Sanity check: if the current mode is invalid reset it to - * something reasonable. - */ - if (ntrig_get_mode(hdev) >= 4) - ntrig_set_mode(hdev, 3); - } - - ntrig_report_version(hdev); - - ret = sysfs_create_group(&hdev->dev.kobj, - &ntrig_attribute_group); - - return 0; -err_free: - kfree(nd); - return ret; -} - -static void ntrig_remove(struct hid_device *hdev) -{ - sysfs_remove_group(&hdev->dev.kobj, - &ntrig_attribute_group); - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); -} - -static const struct hid_device_id ntrig_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { } -}; -MODULE_DEVICE_TABLE(hid, ntrig_devices); - -static const struct hid_usage_id ntrig_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 } -}; - -static struct hid_driver ntrig_driver = { - .name = "ntrig", - .id_table = ntrig_devices, - .probe = ntrig_probe, - .remove = ntrig_remove, - .input_mapping = ntrig_input_mapping, - .input_mapped = ntrig_input_mapped, - .usage_table = ntrig_grabbed_usages, - .event = ntrig_event, -}; - -static int __init ntrig_init(void) -{ - return hid_register_driver(&ntrig_driver); -} - -static void __exit ntrig_exit(void) -{ - hid_unregister_driver(&ntrig_driver); -} - -module_init(ntrig_init); -module_exit(ntrig_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-ortek.c b/ANDROID_3.4.5/drivers/hid/hid-ortek.c deleted file mode 100644 index 0ffa1d2d..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-ortek.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * HID driver for various devices which are apparently based on the same chipset - * from certain vendor which produces chips that contain wrong LogicalMaximum - * value in their HID report descriptor. Currently supported devices are: - * - * Ortek PKB-1700 - * Ortek WKB-2000 - * Skycable wireless presenter - * - * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> - * Copyright (c) 2011 Jiri Kosina - */ - -/* - * 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" - -static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { - hid_info(hdev, "Fixing up logical minimum in report descriptor (Ortek)\n"); - rdesc[55] = 0x92; - } else if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { - hid_info(hdev, "Fixing up logical minimum in report descriptor (Skycable)\n"); - rdesc[53] = 0x65; - } - return rdesc; -} - -static const struct hid_device_id ortek_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ortek_devices); - -static struct hid_driver ortek_driver = { - .name = "ortek", - .id_table = ortek_devices, - .report_fixup = ortek_report_fixup -}; - -static int __init ortek_init(void) -{ - return hid_register_driver(&ortek_driver); -} - -static void __exit ortek_exit(void) -{ - hid_unregister_driver(&ortek_driver); -} - -module_init(ortek_init); -module_exit(ortek_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-petalynx.c b/ANDROID_3.4.5/drivers/hid/hid-petalynx.c deleted file mode 100644 index f1ea3ff8..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-petalynx.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * HID driver for some petalynx "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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" - -/* Petalynx Maxter Remote has maximum for consumer page set too low */ -static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && - rdesc[41] == 0x00 && rdesc[59] == 0x26 && - rdesc[60] == 0xf9 && rdesc[61] == 0x00) { - hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); - rdesc[60] = 0xfa; - rdesc[40] = 0xfa; - } - return rdesc; -} - -#define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int pl_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR) { - switch (usage->hid & HID_USAGE) { - case 0x05a: pl_map_key_clear(KEY_TEXT); break; - case 0x05b: pl_map_key_clear(KEY_RED); break; - case 0x05c: pl_map_key_clear(KEY_GREEN); break; - case 0x05d: pl_map_key_clear(KEY_YELLOW); break; - case 0x05e: pl_map_key_clear(KEY_BLUE); break; - default: - return 0; - } - return 1; - } - - if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) { - switch (usage->hid & HID_USAGE) { - case 0x0f6: pl_map_key_clear(KEY_NEXT); break; - case 0x0fa: pl_map_key_clear(KEY_BACK); break; - default: - return 0; - } - return 1; - } - - return 0; -} - -static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - hdev->quirks |= HID_QUIRK_NOGET; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - return ret; -} - -static const struct hid_device_id pl_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, - { } -}; -MODULE_DEVICE_TABLE(hid, pl_devices); - -static struct hid_driver pl_driver = { - .name = "petalynx", - .id_table = pl_devices, - .report_fixup = pl_report_fixup, - .input_mapping = pl_input_mapping, - .probe = pl_probe, -}; - -static int __init pl_init(void) -{ - return hid_register_driver(&pl_driver); -} - -static void __exit pl_exit(void) -{ - hid_unregister_driver(&pl_driver); -} - -module_init(pl_init); -module_exit(pl_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-picolcd.c b/ANDROID_3.4.5/drivers/hid/hid-picolcd.c deleted file mode 100644 index 45c3433f..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-picolcd.c +++ /dev/null @@ -1,2752 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010 by Bruno Prémont <bonbons@linux-vserver.org> * - * * - * Based on Logitech G13 driver (v0.4) * - * Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu> * - * * - * 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, version 2 of the License. * - * * - * This driver is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this software. If not see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -#include <linux/hid.h> -#include <linux/hid-debug.h> -#include <linux/input.h> -#include "hid-ids.h" -#include "usbhid/usbhid.h" -#include <linux/usb.h> - -#include <linux/fb.h> -#include <linux/vmalloc.h> -#include <linux/backlight.h> -#include <linux/lcd.h> - -#include <linux/leds.h> - -#include <linux/seq_file.h> -#include <linux/debugfs.h> - -#include <linux/completion.h> -#include <linux/uaccess.h> -#include <linux/module.h> - -#define PICOLCD_NAME "PicoLCD (graphic)" - -/* Report numbers */ -#define REPORT_ERROR_CODE 0x10 /* LCD: IN[16] */ -#define ERR_SUCCESS 0x00 -#define ERR_PARAMETER_MISSING 0x01 -#define ERR_DATA_MISSING 0x02 -#define ERR_BLOCK_READ_ONLY 0x03 -#define ERR_BLOCK_NOT_ERASABLE 0x04 -#define ERR_BLOCK_TOO_BIG 0x05 -#define ERR_SECTION_OVERFLOW 0x06 -#define ERR_INVALID_CMD_LEN 0x07 -#define ERR_INVALID_DATA_LEN 0x08 -#define REPORT_KEY_STATE 0x11 /* LCD: IN[2] */ -#define REPORT_IR_DATA 0x21 /* LCD: IN[63] */ -#define REPORT_EE_DATA 0x32 /* LCD: IN[63] */ -#define REPORT_MEMORY 0x41 /* LCD: IN[63] */ -#define REPORT_LED_STATE 0x81 /* LCD: OUT[1] */ -#define REPORT_BRIGHTNESS 0x91 /* LCD: OUT[1] */ -#define REPORT_CONTRAST 0x92 /* LCD: OUT[1] */ -#define REPORT_RESET 0x93 /* LCD: OUT[2] */ -#define REPORT_LCD_CMD 0x94 /* LCD: OUT[63] */ -#define REPORT_LCD_DATA 0x95 /* LCD: OUT[63] */ -#define REPORT_LCD_CMD_DATA 0x96 /* LCD: OUT[63] */ -#define REPORT_EE_READ 0xa3 /* LCD: OUT[63] */ -#define REPORT_EE_WRITE 0xa4 /* LCD: OUT[63] */ -#define REPORT_ERASE_MEMORY 0xb2 /* LCD: OUT[2] */ -#define REPORT_READ_MEMORY 0xb3 /* LCD: OUT[3] */ -#define REPORT_WRITE_MEMORY 0xb4 /* LCD: OUT[63] */ -#define REPORT_SPLASH_RESTART 0xc1 /* LCD: OUT[1] */ -#define REPORT_EXIT_KEYBOARD 0xef /* LCD: OUT[2] */ -#define REPORT_VERSION 0xf1 /* LCD: IN[2],OUT[1] Bootloader: IN[2],OUT[1] */ -#define REPORT_BL_ERASE_MEMORY 0xf2 /* Bootloader: IN[36],OUT[4] */ -#define REPORT_BL_READ_MEMORY 0xf3 /* Bootloader: IN[36],OUT[4] */ -#define REPORT_BL_WRITE_MEMORY 0xf4 /* Bootloader: IN[36],OUT[36] */ -#define REPORT_DEVID 0xf5 /* LCD: IN[5], OUT[1] Bootloader: IN[5],OUT[1] */ -#define REPORT_SPLASH_SIZE 0xf6 /* LCD: IN[4], OUT[1] */ -#define REPORT_HOOK_VERSION 0xf7 /* LCD: IN[2], OUT[1] */ -#define REPORT_EXIT_FLASHER 0xff /* Bootloader: OUT[2] */ - -#ifdef CONFIG_HID_PICOLCD_FB -/* Framebuffer - * - * The PicoLCD use a Topway LCD module of 256x64 pixel - * This display area is tiled over 4 controllers with 8 tiles - * each. Each tile has 8x64 pixel, each data byte representing - * a 1-bit wide vertical line of the tile. - * - * The display can be updated at a tile granularity. - * - * Chip 1 Chip 2 Chip 3 Chip 4 - * +----------------+----------------+----------------+----------------+ - * | Tile 1 | Tile 1 | Tile 1 | Tile 1 | - * +----------------+----------------+----------------+----------------+ - * | Tile 2 | Tile 2 | Tile 2 | Tile 2 | - * +----------------+----------------+----------------+----------------+ - * ... - * +----------------+----------------+----------------+----------------+ - * | Tile 8 | Tile 8 | Tile 8 | Tile 8 | - * +----------------+----------------+----------------+----------------+ - */ -#define PICOLCDFB_NAME "picolcdfb" -#define PICOLCDFB_WIDTH (256) -#define PICOLCDFB_HEIGHT (64) -#define PICOLCDFB_SIZE (PICOLCDFB_WIDTH * PICOLCDFB_HEIGHT / 8) - -#define PICOLCDFB_UPDATE_RATE_LIMIT 10 -#define PICOLCDFB_UPDATE_RATE_DEFAULT 2 - -/* Framebuffer visual structures */ -static const struct fb_fix_screeninfo picolcdfb_fix = { - .id = PICOLCDFB_NAME, - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_MONO01, - .xpanstep = 0, - .ypanstep = 0, - .ywrapstep = 0, - .line_length = PICOLCDFB_WIDTH / 8, - .accel = FB_ACCEL_NONE, -}; - -static const struct fb_var_screeninfo picolcdfb_var = { - .xres = PICOLCDFB_WIDTH, - .yres = PICOLCDFB_HEIGHT, - .xres_virtual = PICOLCDFB_WIDTH, - .yres_virtual = PICOLCDFB_HEIGHT, - .width = 103, - .height = 26, - .bits_per_pixel = 1, - .grayscale = 1, - .red = { - .offset = 0, - .length = 1, - .msb_right = 0, - }, - .green = { - .offset = 0, - .length = 1, - .msb_right = 0, - }, - .blue = { - .offset = 0, - .length = 1, - .msb_right = 0, - }, - .transp = { - .offset = 0, - .length = 0, - .msb_right = 0, - }, -}; -#endif /* CONFIG_HID_PICOLCD_FB */ - -/* Input device - * - * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys - * and header for 4x4 key matrix. The built-in keys are part of the matrix. - */ -static const unsigned short def_keymap[] = { - KEY_RESERVED, /* none */ - KEY_BACK, /* col 4 + row 1 */ - KEY_HOMEPAGE, /* col 3 + row 1 */ - KEY_RESERVED, /* col 2 + row 1 */ - KEY_RESERVED, /* col 1 + row 1 */ - KEY_SCROLLUP, /* col 4 + row 2 */ - KEY_OK, /* col 3 + row 2 */ - KEY_SCROLLDOWN, /* col 2 + row 2 */ - KEY_RESERVED, /* col 1 + row 2 */ - KEY_RESERVED, /* col 4 + row 3 */ - KEY_RESERVED, /* col 3 + row 3 */ - KEY_RESERVED, /* col 2 + row 3 */ - KEY_RESERVED, /* col 1 + row 3 */ - KEY_RESERVED, /* col 4 + row 4 */ - KEY_RESERVED, /* col 3 + row 4 */ - KEY_RESERVED, /* col 2 + row 4 */ - KEY_RESERVED, /* col 1 + row 4 */ -}; -#define PICOLCD_KEYS ARRAY_SIZE(def_keymap) - -/* Description of in-progress IO operation, used for operations - * that trigger response from device */ -struct picolcd_pending { - struct hid_report *out_report; - struct hid_report *in_report; - struct completion ready; - int raw_size; - u8 raw_data[64]; -}; - -/* Per device data structure */ -struct picolcd_data { - struct hid_device *hdev; -#ifdef CONFIG_DEBUG_FS - struct dentry *debug_reset; - struct dentry *debug_eeprom; - struct dentry *debug_flash; - struct mutex mutex_flash; - int addr_sz; -#endif - u8 version[2]; - unsigned short opmode_delay; - /* input stuff */ - u8 pressed_keys[2]; - struct input_dev *input_keys; - struct input_dev *input_cir; - unsigned short keycode[PICOLCD_KEYS]; - -#ifdef CONFIG_HID_PICOLCD_FB - /* Framebuffer stuff */ - u8 fb_update_rate; - u8 fb_bpp; - u8 fb_force; - u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */ - u8 *fb_bitmap; /* framebuffer */ - struct fb_info *fb_info; - struct fb_deferred_io fb_defio; -#endif /* CONFIG_HID_PICOLCD_FB */ -#ifdef CONFIG_HID_PICOLCD_LCD - struct lcd_device *lcd; - u8 lcd_contrast; -#endif /* CONFIG_HID_PICOLCD_LCD */ -#ifdef CONFIG_HID_PICOLCD_BACKLIGHT - struct backlight_device *backlight; - u8 lcd_brightness; - u8 lcd_power; -#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ -#ifdef CONFIG_HID_PICOLCD_LEDS - /* LED stuff */ - u8 led_state; - struct led_classdev *led[8]; -#endif /* CONFIG_HID_PICOLCD_LEDS */ - - /* Housekeeping stuff */ - spinlock_t lock; - struct mutex mutex; - struct picolcd_pending *pending; - int status; -#define PICOLCD_BOOTLOADER 1 -#define PICOLCD_FAILED 2 -#define PICOLCD_READY_FB 4 -}; - - -/* Find a given report */ -#define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT) -#define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT) - -static struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir) -{ - struct list_head *feature_report_list = &hdev->report_enum[dir].report_list; - struct hid_report *report = NULL; - - list_for_each_entry(report, feature_report_list, list) { - if (report->id == id) - return report; - } - hid_warn(hdev, "No report with id 0x%x found\n", id); - return NULL; -} - -#ifdef CONFIG_DEBUG_FS -static void picolcd_debug_out_report(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report); -#define usbhid_submit_report(a, b, c) \ - do { \ - picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ - usbhid_submit_report(a, b, c); \ - } while (0) -#endif - -/* Submit a report and wait for a reply from device - if device fades away - * or does not respond in time, return NULL */ -static struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, - int report_id, const u8 *raw_data, int size) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct picolcd_pending *work; - struct hid_report *report = picolcd_out_report(report_id, hdev); - unsigned long flags; - int i, j, k; - - if (!report || !data) - return NULL; - if (data->status & PICOLCD_FAILED) - return NULL; - work = kzalloc(sizeof(*work), GFP_KERNEL); - if (!work) - return NULL; - - init_completion(&work->ready); - work->out_report = report; - work->in_report = NULL; - work->raw_size = 0; - - mutex_lock(&data->mutex); - spin_lock_irqsave(&data->lock, flags); - for (i = k = 0; i < report->maxfield; i++) - for (j = 0; j < report->field[i]->report_count; j++) { - hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0); - k++; - } - data->pending = work; - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - wait_for_completion_interruptible_timeout(&work->ready, HZ*2); - spin_lock_irqsave(&data->lock, flags); - data->pending = NULL; - spin_unlock_irqrestore(&data->lock, flags); - mutex_unlock(&data->mutex); - return work; -} - -#ifdef CONFIG_HID_PICOLCD_FB -/* Send a given tile to PicoLCD */ -static int picolcd_fb_send_tile(struct hid_device *hdev, int chip, int tile) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct hid_report *report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, hdev); - struct hid_report *report2 = picolcd_out_report(REPORT_LCD_DATA, hdev); - unsigned long flags; - u8 *tdata; - int i; - - if (!report1 || report1->maxfield != 1 || !report2 || report2->maxfield != 1) - return -ENODEV; - - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report1->field[0], 0, chip << 2); - hid_set_field(report1->field[0], 1, 0x02); - hid_set_field(report1->field[0], 2, 0x00); - hid_set_field(report1->field[0], 3, 0x00); - hid_set_field(report1->field[0], 4, 0xb8 | tile); - hid_set_field(report1->field[0], 5, 0x00); - hid_set_field(report1->field[0], 6, 0x00); - hid_set_field(report1->field[0], 7, 0x40); - hid_set_field(report1->field[0], 8, 0x00); - hid_set_field(report1->field[0], 9, 0x00); - hid_set_field(report1->field[0], 10, 32); - - hid_set_field(report2->field[0], 0, (chip << 2) | 0x01); - hid_set_field(report2->field[0], 1, 0x00); - hid_set_field(report2->field[0], 2, 0x00); - hid_set_field(report2->field[0], 3, 32); - - tdata = data->fb_vbitmap + (tile * 4 + chip) * 64; - for (i = 0; i < 64; i++) - if (i < 32) - hid_set_field(report1->field[0], 11 + i, tdata[i]); - else - hid_set_field(report2->field[0], 4 + i - 32, tdata[i]); - - usbhid_submit_report(data->hdev, report1, USB_DIR_OUT); - usbhid_submit_report(data->hdev, report2, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -/* Translate a single tile*/ -static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp, - int chip, int tile) -{ - int i, b, changed = 0; - u8 tdata[64]; - u8 *vdata = vbitmap + (tile * 4 + chip) * 64; - - if (bpp == 1) { - for (b = 7; b >= 0; b--) { - const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32; - for (i = 0; i < 64; i++) { - tdata[i] <<= 1; - tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01; - } - } - } else if (bpp == 8) { - for (b = 7; b >= 0; b--) { - const u8 *bdata = bitmap + (tile * 256 + chip * 8 + b * 32) * 8; - for (i = 0; i < 64; i++) { - tdata[i] <<= 1; - tdata[i] |= (bdata[i] & 0x80) ? 0x01 : 0x00; - } - } - } else { - /* Oops, we should never get here! */ - WARN_ON(1); - return 0; - } - - for (i = 0; i < 64; i++) - if (tdata[i] != vdata[i]) { - changed = 1; - vdata[i] = tdata[i]; - } - return changed; -} - -/* Reconfigure LCD display */ -static int picolcd_fb_reset(struct picolcd_data *data, int clear) -{ - struct hid_report *report = picolcd_out_report(REPORT_LCD_CMD, data->hdev); - int i, j; - unsigned long flags; - static const u8 mapcmd[8] = { 0x00, 0x02, 0x00, 0x64, 0x3f, 0x00, 0x64, 0xc0 }; - - if (!report || report->maxfield != 1) - return -ENODEV; - - spin_lock_irqsave(&data->lock, flags); - for (i = 0; i < 4; i++) { - for (j = 0; j < report->field[0]->maxusage; j++) - if (j == 0) - hid_set_field(report->field[0], j, i << 2); - else if (j < sizeof(mapcmd)) - hid_set_field(report->field[0], j, mapcmd[j]); - else - hid_set_field(report->field[0], j, 0); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - } - - data->status |= PICOLCD_READY_FB; - spin_unlock_irqrestore(&data->lock, flags); - - if (data->fb_bitmap) { - if (clear) { - memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE); - memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp); - } - data->fb_force = 1; - } - - /* schedule first output of framebuffer */ - if (data->fb_info) - schedule_delayed_work(&data->fb_info->deferred_work, 0); - - return 0; -} - -/* Update fb_vbitmap from the screen_base and send changed tiles to device */ -static void picolcd_fb_update(struct picolcd_data *data) -{ - int chip, tile, n; - unsigned long flags; - - if (!data) - return; - - spin_lock_irqsave(&data->lock, flags); - if (!(data->status & PICOLCD_READY_FB)) { - spin_unlock_irqrestore(&data->lock, flags); - picolcd_fb_reset(data, 0); - } else { - spin_unlock_irqrestore(&data->lock, flags); - } - - /* - * Translate the framebuffer into the format needed by the PicoLCD. - * See display layout above. - * Do this one tile after the other and push those tiles that changed. - * - * Wait for our IO to complete as otherwise we might flood the queue! - */ - n = 0; - for (chip = 0; chip < 4; chip++) - for (tile = 0; tile < 8; tile++) - if (picolcd_fb_update_tile(data->fb_vbitmap, - data->fb_bitmap, data->fb_bpp, chip, tile) || - data->fb_force) { - n += 2; - if (!data->fb_info->par) - return; /* device lost! */ - if (n >= HID_OUTPUT_FIFO_SIZE / 2) { - usbhid_wait_io(data->hdev); - n = 0; - } - picolcd_fb_send_tile(data->hdev, chip, tile); - } - data->fb_force = false; - if (n) - usbhid_wait_io(data->hdev); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - if (!info->par) - return; - sys_fillrect(info, rect); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - if (!info->par) - return; - sys_copyarea(info, area); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image) -{ - if (!info->par) - return; - sys_imageblit(info, image); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* - * this is the slow path from userspace. they can seek and write to - * the fb. it's inefficient to do anything less than a full screen draw - */ -static ssize_t picolcd_fb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t ret; - if (!info->par) - return -ENODEV; - ret = fb_sys_write(info, buf, count, ppos); - if (ret >= 0) - schedule_delayed_work(&info->deferred_work, 0); - return ret; -} - -static int picolcd_fb_blank(int blank, struct fb_info *info) -{ - if (!info->par) - return -ENODEV; - /* We let fb notification do this for us via lcd/backlight device */ - return 0; -} - -static void picolcd_fb_destroy(struct fb_info *info) -{ - struct picolcd_data *data = info->par; - u32 *ref_cnt = info->pseudo_palette; - int may_release; - - info->par = NULL; - if (data) - data->fb_info = NULL; - fb_deferred_io_cleanup(info); - - ref_cnt--; - mutex_lock(&info->lock); - (*ref_cnt)--; - may_release = !*ref_cnt; - mutex_unlock(&info->lock); - if (may_release) { - vfree((u8 *)info->fix.smem_start); - framebuffer_release(info); - } -} - -static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - __u32 bpp = var->bits_per_pixel; - __u32 activate = var->activate; - - /* only allow 1/8 bit depth (8-bit is grayscale) */ - *var = picolcdfb_var; - var->activate = activate; - if (bpp >= 8) { - var->bits_per_pixel = 8; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - } else { - var->bits_per_pixel = 1; - var->red.length = 1; - var->green.length = 1; - var->blue.length = 1; - } - return 0; -} - -static int picolcd_set_par(struct fb_info *info) -{ - struct picolcd_data *data = info->par; - u8 *tmp_fb, *o_fb; - if (!data) - return -ENODEV; - if (info->var.bits_per_pixel == data->fb_bpp) - return 0; - /* switch between 1/8 bit depths */ - if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8) - return -EINVAL; - - o_fb = data->fb_bitmap; - tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL); - if (!tmp_fb) - return -ENOMEM; - - /* translate FB content to new bits-per-pixel */ - if (info->var.bits_per_pixel == 1) { - int i, b; - for (i = 0; i < PICOLCDFB_SIZE; i++) { - u8 p = 0; - for (b = 0; b < 8; b++) { - p <<= 1; - p |= o_fb[i*8+b] ? 0x01 : 0x00; - } - tmp_fb[i] = p; - } - memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE); - info->fix.visual = FB_VISUAL_MONO01; - info->fix.line_length = PICOLCDFB_WIDTH / 8; - } else { - int i; - memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE); - for (i = 0; i < PICOLCDFB_SIZE * 8; i++) - o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00; - info->fix.visual = FB_VISUAL_DIRECTCOLOR; - info->fix.line_length = PICOLCDFB_WIDTH; - } - - kfree(tmp_fb); - data->fb_bpp = info->var.bits_per_pixel; - return 0; -} - -/* Do refcounting on our FB and cleanup per worker if FB is - * closed after unplug of our device - * (fb_release holds info->lock and still touches info after - * we return so we can't release it immediately. - */ -struct picolcd_fb_cleanup_item { - struct fb_info *info; - struct picolcd_fb_cleanup_item *next; -}; -static struct picolcd_fb_cleanup_item *fb_pending; -static DEFINE_SPINLOCK(fb_pending_lock); - -static void picolcd_fb_do_cleanup(struct work_struct *data) -{ - struct picolcd_fb_cleanup_item *item; - unsigned long flags; - - do { - spin_lock_irqsave(&fb_pending_lock, flags); - item = fb_pending; - fb_pending = item ? item->next : NULL; - spin_unlock_irqrestore(&fb_pending_lock, flags); - - if (item) { - u8 *fb = (u8 *)item->info->fix.smem_start; - /* make sure we do not race against fb core when - * releasing */ - mutex_lock(&item->info->lock); - mutex_unlock(&item->info->lock); - framebuffer_release(item->info); - vfree(fb); - } - } while (item); -} - -static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); - -static int picolcd_fb_open(struct fb_info *info, int u) -{ - u32 *ref_cnt = info->pseudo_palette; - ref_cnt--; - - (*ref_cnt)++; - return 0; -} - -static int picolcd_fb_release(struct fb_info *info, int u) -{ - u32 *ref_cnt = info->pseudo_palette; - ref_cnt--; - - (*ref_cnt)++; - if (!*ref_cnt) { - unsigned long flags; - struct picolcd_fb_cleanup_item *item = (struct picolcd_fb_cleanup_item *)ref_cnt; - item--; - spin_lock_irqsave(&fb_pending_lock, flags); - item->next = fb_pending; - fb_pending = item; - spin_unlock_irqrestore(&fb_pending_lock, flags); - schedule_work(&picolcd_fb_cleanup); - } - return 0; -} - -/* Note this can't be const because of struct fb_info definition */ -static struct fb_ops picolcdfb_ops = { - .owner = THIS_MODULE, - .fb_destroy = picolcd_fb_destroy, - .fb_open = picolcd_fb_open, - .fb_release = picolcd_fb_release, - .fb_read = fb_sys_read, - .fb_write = picolcd_fb_write, - .fb_blank = picolcd_fb_blank, - .fb_fillrect = picolcd_fb_fillrect, - .fb_copyarea = picolcd_fb_copyarea, - .fb_imageblit = picolcd_fb_imageblit, - .fb_check_var = picolcd_fb_check_var, - .fb_set_par = picolcd_set_par, -}; - - -/* Callback from deferred IO workqueue */ -static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist) -{ - picolcd_fb_update(info->par); -} - -static const struct fb_deferred_io picolcd_fb_defio = { - .delay = HZ / PICOLCDFB_UPDATE_RATE_DEFAULT, - .deferred_io = picolcd_fb_deferred_io, -}; - - -/* - * The "fb_update_rate" sysfs attribute - */ -static ssize_t picolcd_fb_update_rate_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - unsigned i, fb_update_rate = data->fb_update_rate; - size_t ret = 0; - - for (i = 1; i <= PICOLCDFB_UPDATE_RATE_LIMIT; i++) - if (ret >= PAGE_SIZE) - break; - else if (i == fb_update_rate) - ret += snprintf(buf+ret, PAGE_SIZE-ret, "[%u] ", i); - else - ret += snprintf(buf+ret, PAGE_SIZE-ret, "%u ", i); - if (ret > 0) - buf[min(ret, (size_t)PAGE_SIZE)-1] = '\n'; - return ret; -} - -static ssize_t picolcd_fb_update_rate_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - int i; - unsigned u; - - if (count < 1 || count > 10) - return -EINVAL; - - i = sscanf(buf, "%u", &u); - if (i != 1) - return -EINVAL; - - if (u > PICOLCDFB_UPDATE_RATE_LIMIT) - return -ERANGE; - else if (u == 0) - u = PICOLCDFB_UPDATE_RATE_DEFAULT; - - data->fb_update_rate = u; - data->fb_defio.delay = HZ / data->fb_update_rate; - return count; -} - -static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show, - picolcd_fb_update_rate_store); - -/* initialize Framebuffer device */ -static int picolcd_init_framebuffer(struct picolcd_data *data) -{ - struct device *dev = &data->hdev->dev; - struct fb_info *info = NULL; - int i, error = -ENOMEM; - u8 *fb_vbitmap = NULL; - u8 *fb_bitmap = NULL; - u32 *palette; - - fb_bitmap = vmalloc(PICOLCDFB_SIZE*8); - if (fb_bitmap == NULL) { - dev_err(dev, "can't get a free page for framebuffer\n"); - goto err_nomem; - } - - fb_vbitmap = kmalloc(PICOLCDFB_SIZE, GFP_KERNEL); - if (fb_vbitmap == NULL) { - dev_err(dev, "can't alloc vbitmap image buffer\n"); - goto err_nomem; - } - - data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT; - data->fb_defio = picolcd_fb_defio; - /* The extra memory is: - * - struct picolcd_fb_cleanup_item - * - u32 for ref_count - * - 256*u32 for pseudo_palette - */ - info = framebuffer_alloc(257 * sizeof(u32) + sizeof(struct picolcd_fb_cleanup_item), dev); - if (info == NULL) { - dev_err(dev, "failed to allocate a framebuffer\n"); - goto err_nomem; - } - - palette = info->par + sizeof(struct picolcd_fb_cleanup_item); - *palette = 1; - palette++; - for (i = 0; i < 256; i++) - palette[i] = i > 0 && i < 16 ? 0xff : 0; - info->pseudo_palette = palette; - info->fbdefio = &data->fb_defio; - info->screen_base = (char __force __iomem *)fb_bitmap; - info->fbops = &picolcdfb_ops; - info->var = picolcdfb_var; - info->fix = picolcdfb_fix; - info->fix.smem_len = PICOLCDFB_SIZE*8; - info->fix.smem_start = (unsigned long)fb_bitmap; - info->par = data; - info->flags = FBINFO_FLAG_DEFAULT; - - data->fb_vbitmap = fb_vbitmap; - data->fb_bitmap = fb_bitmap; - data->fb_bpp = picolcdfb_var.bits_per_pixel; - error = picolcd_fb_reset(data, 1); - if (error) { - dev_err(dev, "failed to configure display\n"); - goto err_cleanup; - } - error = device_create_file(dev, &dev_attr_fb_update_rate); - if (error) { - dev_err(dev, "failed to create sysfs attributes\n"); - goto err_cleanup; - } - fb_deferred_io_init(info); - data->fb_info = info; - error = register_framebuffer(info); - if (error) { - dev_err(dev, "failed to register framebuffer\n"); - goto err_sysfs; - } - /* schedule first output of framebuffer */ - data->fb_force = 1; - schedule_delayed_work(&info->deferred_work, 0); - return 0; - -err_sysfs: - fb_deferred_io_cleanup(info); - device_remove_file(dev, &dev_attr_fb_update_rate); -err_cleanup: - data->fb_vbitmap = NULL; - data->fb_bitmap = NULL; - data->fb_bpp = 0; - data->fb_info = NULL; - -err_nomem: - framebuffer_release(info); - vfree(fb_bitmap); - kfree(fb_vbitmap); - return error; -} - -static void picolcd_exit_framebuffer(struct picolcd_data *data) -{ - struct fb_info *info = data->fb_info; - u8 *fb_vbitmap = data->fb_vbitmap; - - if (!info) - return; - - info->par = NULL; - device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); - unregister_framebuffer(info); - data->fb_vbitmap = NULL; - data->fb_bitmap = NULL; - data->fb_bpp = 0; - data->fb_info = NULL; - kfree(fb_vbitmap); -} - -#define picolcd_fbinfo(d) ((d)->fb_info) -#else -static inline int picolcd_fb_reset(struct picolcd_data *data, int clear) -{ - return 0; -} -static inline int picolcd_init_framebuffer(struct picolcd_data *data) -{ - return 0; -} -static inline void picolcd_exit_framebuffer(struct picolcd_data *data) -{ -} -#define picolcd_fbinfo(d) NULL -#endif /* CONFIG_HID_PICOLCD_FB */ - -#ifdef CONFIG_HID_PICOLCD_BACKLIGHT -/* - * backlight class device - */ -static int picolcd_get_brightness(struct backlight_device *bdev) -{ - struct picolcd_data *data = bl_get_data(bdev); - return data->lcd_brightness; -} - -static int picolcd_set_brightness(struct backlight_device *bdev) -{ - struct picolcd_data *data = bl_get_data(bdev); - struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev); - unsigned long flags; - - if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) - return -ENODEV; - - data->lcd_brightness = bdev->props.brightness & 0x0ff; - data->lcd_power = bdev->props.power; - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -static int picolcd_check_bl_fb(struct backlight_device *bdev, struct fb_info *fb) -{ - return fb && fb == picolcd_fbinfo((struct picolcd_data *)bl_get_data(bdev)); -} - -static const struct backlight_ops picolcd_blops = { - .update_status = picolcd_set_brightness, - .get_brightness = picolcd_get_brightness, - .check_fb = picolcd_check_bl_fb, -}; - -static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report) -{ - struct device *dev = &data->hdev->dev; - struct backlight_device *bdev; - struct backlight_properties props; - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 1 || - report->field[0]->report_size != 8) { - dev_err(dev, "unsupported BRIGHTNESS report"); - return -EINVAL; - } - - memset(&props, 0, sizeof(props)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 0xff; - bdev = backlight_device_register(dev_name(dev), dev, data, - &picolcd_blops, &props); - if (IS_ERR(bdev)) { - dev_err(dev, "failed to register backlight\n"); - return PTR_ERR(bdev); - } - bdev->props.brightness = 0xff; - data->lcd_brightness = 0xff; - data->backlight = bdev; - picolcd_set_brightness(bdev); - return 0; -} - -static void picolcd_exit_backlight(struct picolcd_data *data) -{ - struct backlight_device *bdev = data->backlight; - - data->backlight = NULL; - if (bdev) - backlight_device_unregister(bdev); -} - -static inline int picolcd_resume_backlight(struct picolcd_data *data) -{ - if (!data->backlight) - return 0; - return picolcd_set_brightness(data->backlight); -} - -#ifdef CONFIG_PM -static void picolcd_suspend_backlight(struct picolcd_data *data) -{ - int bl_power = data->lcd_power; - if (!data->backlight) - return; - - data->backlight->props.power = FB_BLANK_POWERDOWN; - picolcd_set_brightness(data->backlight); - data->lcd_power = data->backlight->props.power = bl_power; -} -#endif /* CONFIG_PM */ -#else -static inline int picolcd_init_backlight(struct picolcd_data *data, - struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_backlight(struct picolcd_data *data) -{ -} -static inline int picolcd_resume_backlight(struct picolcd_data *data) -{ - return 0; -} -static inline void picolcd_suspend_backlight(struct picolcd_data *data) -{ -} -#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ - -#ifdef CONFIG_HID_PICOLCD_LCD -/* - * lcd class device - */ -static int picolcd_get_contrast(struct lcd_device *ldev) -{ - struct picolcd_data *data = lcd_get_data(ldev); - return data->lcd_contrast; -} - -static int picolcd_set_contrast(struct lcd_device *ldev, int contrast) -{ - struct picolcd_data *data = lcd_get_data(ldev); - struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev); - unsigned long flags; - - if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) - return -ENODEV; - - data->lcd_contrast = contrast & 0x0ff; - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->lcd_contrast); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return 0; -} - -static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb) -{ - return fb && fb == picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev)); -} - -static struct lcd_ops picolcd_lcdops = { - .get_contrast = picolcd_get_contrast, - .set_contrast = picolcd_set_contrast, - .check_fb = picolcd_check_lcd_fb, -}; - -static int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report) -{ - struct device *dev = &data->hdev->dev; - struct lcd_device *ldev; - - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 1 || - report->field[0]->report_size != 8) { - dev_err(dev, "unsupported CONTRAST report"); - return -EINVAL; - } - - ldev = lcd_device_register(dev_name(dev), dev, data, &picolcd_lcdops); - if (IS_ERR(ldev)) { - dev_err(dev, "failed to register LCD\n"); - return PTR_ERR(ldev); - } - ldev->props.max_contrast = 0x0ff; - data->lcd_contrast = 0xe5; - data->lcd = ldev; - picolcd_set_contrast(ldev, 0xe5); - return 0; -} - -static void picolcd_exit_lcd(struct picolcd_data *data) -{ - struct lcd_device *ldev = data->lcd; - - data->lcd = NULL; - if (ldev) - lcd_device_unregister(ldev); -} - -static inline int picolcd_resume_lcd(struct picolcd_data *data) -{ - if (!data->lcd) - return 0; - return picolcd_set_contrast(data->lcd, data->lcd_contrast); -} -#else -static inline int picolcd_init_lcd(struct picolcd_data *data, - struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_lcd(struct picolcd_data *data) -{ -} -static inline int picolcd_resume_lcd(struct picolcd_data *data) -{ - return 0; -} -#endif /* CONFIG_HID_PICOLCD_LCD */ - -#ifdef CONFIG_HID_PICOLCD_LEDS -/** - * LED class device - */ -static void picolcd_leds_set(struct picolcd_data *data) -{ - struct hid_report *report; - unsigned long flags; - - if (!data->led[0]) - return; - report = picolcd_out_report(REPORT_LED_STATE, data->hdev); - if (!report || report->maxfield != 1 || report->field[0]->report_count != 1) - return; - - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->led_state); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); -} - -static void picolcd_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness value) -{ - struct device *dev; - struct hid_device *hdev; - struct picolcd_data *data; - int i, state = 0; - - dev = led_cdev->dev->parent; - hdev = container_of(dev, struct hid_device, dev); - data = hid_get_drvdata(hdev); - for (i = 0; i < 8; i++) { - if (led_cdev != data->led[i]) - continue; - state = (data->led_state >> i) & 1; - if (value == LED_OFF && state) { - data->led_state &= ~(1 << i); - picolcd_leds_set(data); - } else if (value != LED_OFF && !state) { - data->led_state |= 1 << i; - picolcd_leds_set(data); - } - break; - } -} - -static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev) -{ - struct device *dev; - struct hid_device *hdev; - struct picolcd_data *data; - int i, value = 0; - - dev = led_cdev->dev->parent; - hdev = container_of(dev, struct hid_device, dev); - data = hid_get_drvdata(hdev); - for (i = 0; i < 8; i++) - if (led_cdev == data->led[i]) { - value = (data->led_state >> i) & 1; - break; - } - return value ? LED_FULL : LED_OFF; -} - -static int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report) -{ - struct device *dev = &data->hdev->dev; - struct led_classdev *led; - size_t name_sz = strlen(dev_name(dev)) + 8; - char *name; - int i, ret = 0; - - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 1 || - report->field[0]->report_size != 8) { - dev_err(dev, "unsupported LED_STATE report"); - return -EINVAL; - } - - for (i = 0; i < 8; i++) { - led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); - if (!led) { - dev_err(dev, "can't allocate memory for LED %d\n", i); - ret = -ENOMEM; - goto err; - } - name = (void *)(&led[1]); - snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i); - led->name = name; - led->brightness = 0; - led->max_brightness = 1; - led->brightness_get = picolcd_led_get_brightness; - led->brightness_set = picolcd_led_set_brightness; - - data->led[i] = led; - ret = led_classdev_register(dev, data->led[i]); - if (ret) { - data->led[i] = NULL; - kfree(led); - dev_err(dev, "can't register LED %d\n", i); - goto err; - } - } - return 0; -err: - for (i = 0; i < 8; i++) - if (data->led[i]) { - led = data->led[i]; - data->led[i] = NULL; - led_classdev_unregister(led); - kfree(led); - } - return ret; -} - -static void picolcd_exit_leds(struct picolcd_data *data) -{ - struct led_classdev *led; - int i; - - for (i = 0; i < 8; i++) { - led = data->led[i]; - data->led[i] = NULL; - if (!led) - continue; - led_classdev_unregister(led); - kfree(led); - } -} - -#else -static inline int picolcd_init_leds(struct picolcd_data *data, - struct hid_report *report) -{ - return 0; -} -static inline void picolcd_exit_leds(struct picolcd_data *data) -{ -} -static inline int picolcd_leds_set(struct picolcd_data *data) -{ - return 0; -} -#endif /* CONFIG_HID_PICOLCD_LEDS */ - -/* - * input class device - */ -static int picolcd_raw_keypad(struct picolcd_data *data, - struct hid_report *report, u8 *raw_data, int size) -{ - /* - * Keypad event - * First and second data bytes list currently pressed keys, - * 0x00 means no key and at most 2 keys may be pressed at same time - */ - int i, j; - - /* determine newly pressed keys */ - for (i = 0; i < size; i++) { - unsigned int key_code; - if (raw_data[i] == 0) - continue; - for (j = 0; j < sizeof(data->pressed_keys); j++) - if (data->pressed_keys[j] == raw_data[i]) - goto key_already_down; - for (j = 0; j < sizeof(data->pressed_keys); j++) - if (data->pressed_keys[j] == 0) { - data->pressed_keys[j] = raw_data[i]; - break; - } - input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]); - if (raw_data[i] < PICOLCD_KEYS) - key_code = data->keycode[raw_data[i]]; - else - key_code = KEY_UNKNOWN; - if (key_code != KEY_UNKNOWN) { - dbg_hid(PICOLCD_NAME " got key press for %u:%d", - raw_data[i], key_code); - input_report_key(data->input_keys, key_code, 1); - } - input_sync(data->input_keys); -key_already_down: - continue; - } - - /* determine newly released keys */ - for (j = 0; j < sizeof(data->pressed_keys); j++) { - unsigned int key_code; - if (data->pressed_keys[j] == 0) - continue; - for (i = 0; i < size; i++) - if (data->pressed_keys[j] == raw_data[i]) - goto key_still_down; - input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]); - if (data->pressed_keys[j] < PICOLCD_KEYS) - key_code = data->keycode[data->pressed_keys[j]]; - else - key_code = KEY_UNKNOWN; - if (key_code != KEY_UNKNOWN) { - dbg_hid(PICOLCD_NAME " got key release for %u:%d", - data->pressed_keys[j], key_code); - input_report_key(data->input_keys, key_code, 0); - } - input_sync(data->input_keys); - data->pressed_keys[j] = 0; -key_still_down: - continue; - } - return 1; -} - -static int picolcd_raw_cir(struct picolcd_data *data, - struct hid_report *report, u8 *raw_data, int size) -{ - /* Need understanding of CIR data format to implement ... */ - return 1; -} - -static int picolcd_check_version(struct hid_device *hdev) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct picolcd_pending *verinfo; - int ret = 0; - - if (!data) - return -ENODEV; - - verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); - if (!verinfo) { - hid_err(hdev, "no version response from PicoLCD\n"); - return -ENODEV; - } - - if (verinfo->raw_size == 2) { - data->version[0] = verinfo->raw_data[1]; - data->version[1] = verinfo->raw_data[0]; - if (data->status & PICOLCD_BOOTLOADER) { - hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", - verinfo->raw_data[1], verinfo->raw_data[0]); - } else { - hid_info(hdev, "PicoLCD, firmware version %d.%d\n", - verinfo->raw_data[1], verinfo->raw_data[0]); - } - } else { - hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); - ret = -EINVAL; - } - kfree(verinfo); - return ret; -} - -/* - * Reset our device and wait for answer to VERSION request - */ -static int picolcd_reset(struct hid_device *hdev) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev); - unsigned long flags; - int error; - - if (!data || !report || report->maxfield != 1) - return -ENODEV; - - spin_lock_irqsave(&data->lock, flags); - if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) - data->status |= PICOLCD_BOOTLOADER; - - /* perform the reset */ - hid_set_field(report->field[0], 0, 1); - usbhid_submit_report(hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - - error = picolcd_check_version(hdev); - if (error) - return error; - - picolcd_resume_lcd(data); - picolcd_resume_backlight(data); -#ifdef CONFIG_HID_PICOLCD_FB - if (data->fb_info) - schedule_delayed_work(&data->fb_info->deferred_work, 0); -#endif /* CONFIG_HID_PICOLCD_FB */ - - picolcd_leds_set(data); - return 0; -} - -/* - * The "operation_mode" sysfs attribute - */ -static ssize_t picolcd_operation_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - - if (data->status & PICOLCD_BOOTLOADER) - return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n"); - else - return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n"); -} - -static ssize_t picolcd_operation_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - struct hid_report *report = NULL; - size_t cnt = count; - int timeout = data->opmode_delay; - unsigned long flags; - - if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) { - if (data->status & PICOLCD_BOOTLOADER) - report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev); - buf += 3; - cnt -= 3; - } else if (cnt >= 10 && strncmp("bootloader", buf, 10) == 0) { - if (!(data->status & PICOLCD_BOOTLOADER)) - report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev); - buf += 10; - cnt -= 10; - } - if (!report) - return -EINVAL; - - while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) - cnt--; - if (cnt != 0) - return -EINVAL; - - spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, timeout & 0xff); - hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - return count; -} - -static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, - picolcd_operation_mode_store); - -/* - * The "operation_mode_delay" sysfs attribute - */ -static ssize_t picolcd_operation_mode_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay); -} - -static ssize_t picolcd_operation_mode_delay_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct picolcd_data *data = dev_get_drvdata(dev); - unsigned u; - if (sscanf(buf, "%u", &u) != 1) - return -EINVAL; - if (u > 30000) - return -EINVAL; - else - data->opmode_delay = u; - return count; -} - -static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show, - picolcd_operation_mode_delay_store); - - -#ifdef CONFIG_DEBUG_FS -/* - * The "reset" file - */ -static int picolcd_debug_reset_show(struct seq_file *f, void *p) -{ - if (picolcd_fbinfo((struct picolcd_data *)f->private)) - seq_printf(f, "all fb\n"); - else - seq_printf(f, "all\n"); - return 0; -} - -static int picolcd_debug_reset_open(struct inode *inode, struct file *f) -{ - return single_open(f, picolcd_debug_reset_show, inode->i_private); -} - -static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct picolcd_data *data = ((struct seq_file *)f->private_data)->private; - char buf[32]; - size_t cnt = min(count, sizeof(buf)-1); - if (copy_from_user(buf, user_buf, cnt)) - return -EFAULT; - - while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n')) - cnt--; - buf[cnt] = '\0'; - if (strcmp(buf, "all") == 0) { - picolcd_reset(data->hdev); - picolcd_fb_reset(data, 1); - } else if (strcmp(buf, "fb") == 0) { - picolcd_fb_reset(data, 1); - } else { - return -EINVAL; - } - return count; -} - -static const struct file_operations picolcd_debug_reset_fops = { - .owner = THIS_MODULE, - .open = picolcd_debug_reset_open, - .read = seq_read, - .llseek = seq_lseek, - .write = picolcd_debug_reset_write, - .release = single_release, -}; - -/* - * The "eeprom" file - */ -static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - struct picolcd_pending *resp; - u8 raw_data[3]; - ssize_t ret = -EIO; - - if (s == 0) - return -EINVAL; - if (*off > 0x0ff) - return 0; - - /* prepare buffer with info about what we want to read (addr & len) */ - raw_data[0] = *off & 0xff; - raw_data[1] = (*off >> 8) & 0xff; - raw_data[2] = s < 20 ? s : 20; - if (*off + raw_data[2] > 0xff) - raw_data[2] = 0x100 - *off; - resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data, - sizeof(raw_data)); - if (!resp) - return -EIO; - - if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { - /* successful read :) */ - ret = resp->raw_data[2]; - if (ret > s) - ret = s; - if (copy_to_user(u, resp->raw_data+3, ret)) - ret = -EFAULT; - else - *off += ret; - } /* anything else is some kind of IO error */ - - kfree(resp); - return ret; -} - -static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - struct picolcd_pending *resp; - ssize_t ret = -EIO; - u8 raw_data[23]; - - if (s == 0) - return -EINVAL; - if (*off > 0x0ff) - return -ENOSPC; - - memset(raw_data, 0, sizeof(raw_data)); - raw_data[0] = *off & 0xff; - raw_data[1] = (*off >> 8) & 0xff; - raw_data[2] = min((size_t)20, s); - if (*off + raw_data[2] > 0xff) - raw_data[2] = 0x100 - *off; - - if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2]))) - return -EFAULT; - resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, - sizeof(raw_data)); - - if (!resp) - return -EIO; - - if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { - /* check if written data matches */ - if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) { - *off += raw_data[2]; - ret = raw_data[2]; - } - } - kfree(resp); - return ret; -} - -/* - * Notes: - * - read/write happens in chunks of at most 20 bytes, it's up to userspace - * to loop in order to get more data. - * - on write errors on otherwise correct write request the bytes - * that should have been written are in undefined state. - */ -static const struct file_operations picolcd_debug_eeprom_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = picolcd_debug_eeprom_read, - .write = picolcd_debug_eeprom_write, - .llseek = generic_file_llseek, -}; - -/* - * The "flash" file - */ -/* record a flash address to buf (bounds check to be done by caller) */ -static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off) -{ - buf[0] = off & 0xff; - buf[1] = (off >> 8) & 0xff; - if (data->addr_sz == 3) - buf[2] = (off >> 16) & 0xff; - return data->addr_sz == 2 ? 2 : 3; -} - -/* read a given size of data (bounds check to be done by caller) */ -static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id, - char __user *u, size_t s, loff_t *off) -{ - struct picolcd_pending *resp; - u8 raw_data[4]; - ssize_t ret = 0; - int len_off, err = -EIO; - - while (s > 0) { - err = -EIO; - len_off = _picolcd_flash_setaddr(data, raw_data, *off); - raw_data[len_off] = s > 32 ? 32 : s; - resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1); - if (!resp || !resp->in_report) - goto skip; - if (resp->in_report->id == REPORT_MEMORY || - resp->in_report->id == REPORT_BL_READ_MEMORY) { - if (memcmp(raw_data, resp->raw_data, len_off+1) != 0) - goto skip; - if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) { - err = -EFAULT; - goto skip; - } - *off += raw_data[len_off]; - s -= raw_data[len_off]; - ret += raw_data[len_off]; - err = 0; - } -skip: - kfree(resp); - if (err) - return ret > 0 ? ret : err; - } - return ret; -} - -static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - - if (s == 0) - return -EINVAL; - if (*off > 0x05fff) - return 0; - if (*off + s > 0x05fff) - s = 0x06000 - *off; - - if (data->status & PICOLCD_BOOTLOADER) - return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off); - else - return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off); -} - -/* erase block aligned to 64bytes boundary */ -static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id, - loff_t *off) -{ - struct picolcd_pending *resp; - u8 raw_data[3]; - int len_off; - ssize_t ret = -EIO; - - if (*off & 0x3f) - return -EINVAL; - - len_off = _picolcd_flash_setaddr(data, raw_data, *off); - resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off); - if (!resp || !resp->in_report) - goto skip; - if (resp->in_report->id == REPORT_MEMORY || - resp->in_report->id == REPORT_BL_ERASE_MEMORY) { - if (memcmp(raw_data, resp->raw_data, len_off) != 0) - goto skip; - ret = 0; - } -skip: - kfree(resp); - return ret; -} - -/* write a given size of data (bounds check to be done by caller) */ -static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id, - const char __user *u, size_t s, loff_t *off) -{ - struct picolcd_pending *resp; - u8 raw_data[36]; - ssize_t ret = 0; - int len_off, err = -EIO; - - while (s > 0) { - err = -EIO; - len_off = _picolcd_flash_setaddr(data, raw_data, *off); - raw_data[len_off] = s > 32 ? 32 : s; - if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) { - err = -EFAULT; - break; - } - resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, - len_off+1+raw_data[len_off]); - if (!resp || !resp->in_report) - goto skip; - if (resp->in_report->id == REPORT_MEMORY || - resp->in_report->id == REPORT_BL_WRITE_MEMORY) { - if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0) - goto skip; - *off += raw_data[len_off]; - s -= raw_data[len_off]; - ret += raw_data[len_off]; - err = 0; - } -skip: - kfree(resp); - if (err) - break; - } - return ret > 0 ? ret : err; -} - -static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, - size_t s, loff_t *off) -{ - struct picolcd_data *data = f->private_data; - ssize_t err, ret = 0; - int report_erase, report_write; - - if (s == 0) - return -EINVAL; - if (*off > 0x5fff) - return -ENOSPC; - if (s & 0x3f) - return -EINVAL; - if (*off & 0x3f) - return -EINVAL; - - if (data->status & PICOLCD_BOOTLOADER) { - report_erase = REPORT_BL_ERASE_MEMORY; - report_write = REPORT_BL_WRITE_MEMORY; - } else { - report_erase = REPORT_ERASE_MEMORY; - report_write = REPORT_WRITE_MEMORY; - } - mutex_lock(&data->mutex_flash); - while (s > 0) { - err = _picolcd_flash_erase64(data, report_erase, off); - if (err) - break; - err = _picolcd_flash_write(data, report_write, u, 64, off); - if (err < 0) - break; - ret += err; - *off += err; - s -= err; - if (err != 64) - break; - } - mutex_unlock(&data->mutex_flash); - return ret > 0 ? ret : err; -} - -/* - * Notes: - * - concurrent writing is prevented by mutex and all writes must be - * n*64 bytes and 64-byte aligned, each write being preceded by an - * ERASE which erases a 64byte block. - * If less than requested was written or an error is returned for an - * otherwise correct write request the next 64-byte block which should - * have been written is in undefined state (mostly: original, erased, - * (half-)written with write error) - * - reading can happen without special restriction - */ -static const struct file_operations picolcd_debug_flash_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = picolcd_debug_flash_read, - .write = picolcd_debug_flash_write, - .llseek = generic_file_llseek, -}; - - -/* - * Helper code for HID report level dumping/debugging - */ -static const char *error_codes[] = { - "success", "parameter missing", "data_missing", "block readonly", - "block not erasable", "block too big", "section overflow", - "invalid command length", "invalid data length", -}; - -static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data, - const size_t data_len) -{ - int i, j; - for (i = j = 0; i < data_len && j + 3 < dst_sz; i++) { - dst[j++] = hex_asc[(data[i] >> 4) & 0x0f]; - dst[j++] = hex_asc[data[i] & 0x0f]; - dst[j++] = ' '; - } - if (j < dst_sz) { - dst[j--] = '\0'; - dst[j] = '\n'; - } else - dst[j] = '\0'; -} - -static void picolcd_debug_out_report(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report) -{ - u8 raw_data[70]; - int raw_size = (report->size >> 3) + 1; - char *buff; -#define BUFF_SZ 256 - - /* Avoid unnecessary overhead if debugfs is disabled */ - if (!hdev->debug_events) - return; - - buff = kmalloc(BUFF_SZ, GFP_ATOMIC); - if (!buff) - return; - - snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", - report->id, raw_size); - hid_debug_event(hdev, buff); - if (raw_size + 5 > sizeof(raw_data)) { - kfree(buff); - hid_debug_event(hdev, " TOO BIG\n"); - return; - } else { - raw_data[0] = report->id; - hid_output_report(report, raw_data); - dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size); - hid_debug_event(hdev, buff); - } - - switch (report->id) { - case REPORT_LED_STATE: - /* 1 data byte with GPO state */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LED_STATE", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_BRIGHTNESS: - /* 1 data byte with brightness */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_BRIGHTNESS", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_CONTRAST: - /* 1 data byte with contrast */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_CONTRAST", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_RESET: - /* 2 data bytes with reset duration in ms */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_RESET", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n", - raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_LCD_CMD: - /* 63 data bytes with LCD commands */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LCD_CMD", report->id, raw_size-1); - hid_debug_event(hdev, buff); - /* TODO: format decoding */ - break; - case REPORT_LCD_DATA: - /* 63 data bytes with LCD data */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LCD_CMD", report->id, raw_size-1); - /* TODO: format decoding */ - hid_debug_event(hdev, buff); - break; - case REPORT_LCD_CMD_DATA: - /* 63 data bytes with LCD commands and data */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_LCD_CMD", report->id, raw_size-1); - /* TODO: format decoding */ - hid_debug_event(hdev, buff); - break; - case REPORT_EE_READ: - /* 3 data bytes with read area description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_EE_READ", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - break; - case REPORT_EE_WRITE: - /* 3+1..20 data bytes with write area description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_EE_WRITE", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[3] + 4 <= raw_size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_ERASE_MEMORY: - case REPORT_BL_ERASE_MEMORY: - /* 3 data bytes with pointer inside erase block */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_ERASE_MEMORY", report->id, raw_size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - break; - case 3: - snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_READ_MEMORY: - case REPORT_BL_READ_MEMORY: - /* 4 data bytes with read area description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_READ_MEMORY", report->id, raw_size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - break; - case 3: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_WRITE_MEMORY: - case REPORT_BL_WRITE_MEMORY: - /* 4+1..32 data bytes with write adrea description */ - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_WRITE_MEMORY", report->id, raw_size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[3] + 4 <= raw_size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - case 3: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); - hid_debug_event(hdev, buff); - if (raw_data[4] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[4] + 5 <= raw_size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_SPLASH_RESTART: - /* TODO */ - break; - case REPORT_EXIT_KEYBOARD: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_EXIT_KEYBOARD", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n", - raw_data[1] | (raw_data[2] << 8), - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_VERSION: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_VERSION", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_DEVID: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_DEVID", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_SPLASH_SIZE: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_SPLASH_SIZE", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_HOOK_VERSION: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_HOOK_VERSION", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - case REPORT_EXIT_FLASHER: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "REPORT_VERSION", report->id, raw_size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n", - raw_data[1] | (raw_data[2] << 8), - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - default: - snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n", - "<unknown>", report->id, raw_size-1); - hid_debug_event(hdev, buff); - break; - } - wake_up_interruptible(&hdev->debug_wait); - kfree(buff); -} - -static void picolcd_debug_raw_event(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ - char *buff; - -#define BUFF_SZ 256 - /* Avoid unnecessary overhead if debugfs is disabled */ - if (!hdev->debug_events) - return; - - buff = kmalloc(BUFF_SZ, GFP_ATOMIC); - if (!buff) - return; - - switch (report->id) { - case REPORT_ERROR_CODE: - /* 2 data bytes with affected report and error code */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_ERROR_CODE", report->id, size-1); - hid_debug_event(hdev, buff); - if (raw_data[2] < ARRAY_SIZE(error_codes)) - snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n", - raw_data[2], error_codes[raw_data[2]], raw_data[1]); - else - snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_KEY_STATE: - /* 2 data bytes with key state */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_KEY_STATE", report->id, size-1); - hid_debug_event(hdev, buff); - if (raw_data[1] == 0) - snprintf(buff, BUFF_SZ, "\tNo key pressed\n"); - else if (raw_data[2] == 0) - snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n", - raw_data[1], raw_data[1]); - else - snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n", - raw_data[1], raw_data[1], raw_data[2], raw_data[2]); - hid_debug_event(hdev, buff); - break; - case REPORT_IR_DATA: - /* Up to 20 byes of IR scancode data */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_IR_DATA", report->id, size-1); - hid_debug_event(hdev, buff); - if (raw_data[1] == 0) { - snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n"); - hid_debug_event(hdev, buff); - } else if (raw_data[1] + 1 <= size) { - snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ", - raw_data[1]-1); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]-1); - hid_debug_event(hdev, buff); - } else { - snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n", - raw_data[1]-1); - hid_debug_event(hdev, buff); - } - break; - case REPORT_EE_DATA: - /* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_EE_DATA", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - hid_debug_event(hdev, buff); - } else if (raw_data[3] + 4 <= size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - hid_debug_event(hdev, buff); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - hid_debug_event(hdev, buff); - } - break; - case REPORT_MEMORY: - /* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */ - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - switch (data->addr_sz) { - case 2: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]); - hid_debug_event(hdev, buff); - if (raw_data[3] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[3] + 4 <= size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - case 3: - snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n", - raw_data[3], raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]); - hid_debug_event(hdev, buff); - if (raw_data[4] == 0) { - snprintf(buff, BUFF_SZ, "\tNo data\n"); - } else if (raw_data[4] + 5 <= size) { - snprintf(buff, BUFF_SZ, "\tData: "); - hid_debug_event(hdev, buff); - dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]); - } else { - snprintf(buff, BUFF_SZ, "\tData overflowed\n"); - } - break; - default: - snprintf(buff, BUFF_SZ, "\tNot supported\n"); - } - hid_debug_event(hdev, buff); - break; - case REPORT_VERSION: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_VERSION", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n", - raw_data[2], raw_data[1]); - hid_debug_event(hdev, buff); - break; - case REPORT_BL_ERASE_MEMORY: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_BL_ERASE_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - /* TODO */ - break; - case REPORT_BL_READ_MEMORY: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_BL_READ_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - /* TODO */ - break; - case REPORT_BL_WRITE_MEMORY: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_BL_WRITE_MEMORY", report->id, size-1); - hid_debug_event(hdev, buff); - /* TODO */ - break; - case REPORT_DEVID: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_DEVID", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n", - raw_data[1], raw_data[2], raw_data[3], raw_data[4]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n", - raw_data[5]); - hid_debug_event(hdev, buff); - break; - case REPORT_SPLASH_SIZE: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_SPLASH_SIZE", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n", - (raw_data[2] << 8) | raw_data[1]); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n", - (raw_data[4] << 8) | raw_data[3]); - hid_debug_event(hdev, buff); - break; - case REPORT_HOOK_VERSION: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "REPORT_HOOK_VERSION", report->id, size-1); - hid_debug_event(hdev, buff); - snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n", - raw_data[1], raw_data[2]); - hid_debug_event(hdev, buff); - break; - default: - snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n", - "<unknown>", report->id, size-1); - hid_debug_event(hdev, buff); - break; - } - wake_up_interruptible(&hdev->debug_wait); - kfree(buff); -} - -static void picolcd_init_devfs(struct picolcd_data *data, - struct hid_report *eeprom_r, struct hid_report *eeprom_w, - struct hid_report *flash_r, struct hid_report *flash_w, - struct hid_report *reset) -{ - struct hid_device *hdev = data->hdev; - - mutex_init(&data->mutex_flash); - - /* reset */ - if (reset) - data->debug_reset = debugfs_create_file("reset", 0600, - hdev->debug_dir, data, &picolcd_debug_reset_fops); - - /* eeprom */ - if (eeprom_r || eeprom_w) - data->debug_eeprom = debugfs_create_file("eeprom", - (eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0), - hdev->debug_dir, data, &picolcd_debug_eeprom_fops); - - /* flash */ - if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8) - data->addr_sz = flash_r->field[0]->report_count - 1; - else - data->addr_sz = -1; - if (data->addr_sz == 2 || data->addr_sz == 3) { - data->debug_flash = debugfs_create_file("flash", - (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), - hdev->debug_dir, data, &picolcd_debug_flash_fops); - } else if (flash_r || flash_w) - hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n"); -} - -static void picolcd_exit_devfs(struct picolcd_data *data) -{ - struct dentry *dent; - - dent = data->debug_reset; - data->debug_reset = NULL; - if (dent) - debugfs_remove(dent); - dent = data->debug_eeprom; - data->debug_eeprom = NULL; - if (dent) - debugfs_remove(dent); - dent = data->debug_flash; - data->debug_flash = NULL; - if (dent) - debugfs_remove(dent); - mutex_destroy(&data->mutex_flash); -} -#else -static inline void picolcd_debug_raw_event(struct picolcd_data *data, - struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ -} -static inline void picolcd_init_devfs(struct picolcd_data *data, - struct hid_report *eeprom_r, struct hid_report *eeprom_w, - struct hid_report *flash_r, struct hid_report *flash_w, - struct hid_report *reset) -{ -} -static inline void picolcd_exit_devfs(struct picolcd_data *data) -{ -} -#endif /* CONFIG_DEBUG_FS */ - -/* - * Handle raw report as sent by device - */ -static int picolcd_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *raw_data, int size) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - unsigned long flags; - int ret = 0; - - if (!data) - return 1; - - if (report->id == REPORT_KEY_STATE) { - if (data->input_keys) - ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); - } else if (report->id == REPORT_IR_DATA) { - if (data->input_cir) - ret = picolcd_raw_cir(data, report, raw_data+1, size-1); - } else { - spin_lock_irqsave(&data->lock, flags); - /* - * We let the caller of picolcd_send_and_wait() check if the - * report we got is one of the expected ones or not. - */ - if (data->pending) { - memcpy(data->pending->raw_data, raw_data+1, size-1); - data->pending->raw_size = size-1; - data->pending->in_report = report; - complete(&data->pending->ready); - } - spin_unlock_irqrestore(&data->lock, flags); - } - - picolcd_debug_raw_event(data, hdev, report, raw_data, size); - return 1; -} - -#ifdef CONFIG_PM -static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) -{ - if (PMSG_IS_AUTO(message)) - return 0; - - picolcd_suspend_backlight(hid_get_drvdata(hdev)); - dbg_hid(PICOLCD_NAME " device ready for suspend\n"); - return 0; -} - -static int picolcd_resume(struct hid_device *hdev) -{ - int ret; - ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); - if (ret) - dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); - return 0; -} - -static int picolcd_reset_resume(struct hid_device *hdev) -{ - int ret; - ret = picolcd_reset(hdev); - if (ret) - dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret); - ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0); - if (ret) - dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret); - ret = picolcd_resume_lcd(hid_get_drvdata(hdev)); - if (ret) - dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret); - ret = picolcd_resume_backlight(hid_get_drvdata(hdev)); - if (ret) - dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret); - picolcd_leds_set(hid_get_drvdata(hdev)); - return 0; -} -#endif - -/* initialize keypad input device */ -static int picolcd_init_keys(struct picolcd_data *data, - struct hid_report *report) -{ - struct hid_device *hdev = data->hdev; - struct input_dev *idev; - int error, i; - - if (!report) - return -ENODEV; - if (report->maxfield != 1 || report->field[0]->report_count != 2 || - report->field[0]->report_size != 8) { - hid_err(hdev, "unsupported KEY_STATE report\n"); - return -EINVAL; - } - - idev = input_allocate_device(); - if (idev == NULL) { - hid_err(hdev, "failed to allocate input device\n"); - return -ENOMEM; - } - input_set_drvdata(idev, hdev); - memcpy(data->keycode, def_keymap, sizeof(def_keymap)); - idev->name = hdev->name; - idev->phys = hdev->phys; - idev->uniq = hdev->uniq; - idev->id.bustype = hdev->bus; - idev->id.vendor = hdev->vendor; - idev->id.product = hdev->product; - idev->id.version = hdev->version; - idev->dev.parent = hdev->dev.parent; - idev->keycode = &data->keycode; - idev->keycodemax = PICOLCD_KEYS; - idev->keycodesize = sizeof(data->keycode[0]); - input_set_capability(idev, EV_MSC, MSC_SCAN); - set_bit(EV_REP, idev->evbit); - for (i = 0; i < PICOLCD_KEYS; i++) - input_set_capability(idev, EV_KEY, data->keycode[i]); - error = input_register_device(idev); - if (error) { - hid_err(hdev, "error registering the input device\n"); - input_free_device(idev); - return error; - } - data->input_keys = idev; - return 0; -} - -static void picolcd_exit_keys(struct picolcd_data *data) -{ - struct input_dev *idev = data->input_keys; - - data->input_keys = NULL; - if (idev) - input_unregister_device(idev); -} - -/* initialize CIR input device */ -static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) -{ - /* support not implemented yet */ - return 0; -} - -static inline void picolcd_exit_cir(struct picolcd_data *data) -{ -} - -static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) -{ - int error; - - error = picolcd_check_version(hdev); - if (error) - return error; - - if (data->version[0] != 0 && data->version[1] != 3) - hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", - dev_name(&hdev->dev)); - - /* Setup keypad input device */ - error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); - if (error) - goto err; - - /* Setup CIR input device */ - error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev)); - if (error) - goto err; - - /* Set up the framebuffer device */ - error = picolcd_init_framebuffer(data); - if (error) - goto err; - - /* Setup lcd class device */ - error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev)); - if (error) - goto err; - - /* Setup backlight class device */ - error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev)); - if (error) - goto err; - - /* Setup the LED class devices */ - error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev)); - if (error) - goto err; - - picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev), - picolcd_out_report(REPORT_EE_WRITE, hdev), - picolcd_out_report(REPORT_READ_MEMORY, hdev), - picolcd_out_report(REPORT_WRITE_MEMORY, hdev), - picolcd_out_report(REPORT_RESET, hdev)); - return 0; -err: - picolcd_exit_leds(data); - picolcd_exit_backlight(data); - picolcd_exit_lcd(data); - picolcd_exit_framebuffer(data); - picolcd_exit_cir(data); - picolcd_exit_keys(data); - return error; -} - -static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) -{ - int error; - - error = picolcd_check_version(hdev); - if (error) - return error; - - if (data->version[0] != 1 && data->version[1] != 0) - hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", - dev_name(&hdev->dev)); - - picolcd_init_devfs(data, NULL, NULL, - picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), - picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL); - return 0; -} - -static int picolcd_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - struct picolcd_data *data; - int error = -ENOMEM; - - dbg_hid(PICOLCD_NAME " hardware probe...\n"); - - /* - * Let's allocate the picolcd data structure, set some reasonable - * defaults, and associate it with the device - */ - data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); - if (data == NULL) { - hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); - error = -ENOMEM; - goto err_no_cleanup; - } - - spin_lock_init(&data->lock); - mutex_init(&data->mutex); - data->hdev = hdev; - data->opmode_delay = 5000; - if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) - data->status |= PICOLCD_BOOTLOADER; - hid_set_drvdata(hdev, data); - - /* Parse the device reports and start it up */ - error = hid_parse(hdev); - if (error) { - hid_err(hdev, "device report parse failed\n"); - goto err_cleanup_data; - } - - /* We don't use hidinput but hid_hw_start() fails if nothing is - * claimed. So spoof claimed input. */ - hdev->claimed = HID_CLAIMED_INPUT; - error = hid_hw_start(hdev, 0); - hdev->claimed = 0; - if (error) { - hid_err(hdev, "hardware start failed\n"); - goto err_cleanup_data; - } - - error = hid_hw_open(hdev); - if (error) { - hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); - goto err_cleanup_hid_hw; - } - - error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); - if (error) { - hid_err(hdev, "failed to create sysfs attributes\n"); - goto err_cleanup_hid_ll; - } - - error = device_create_file(&hdev->dev, &dev_attr_operation_mode); - if (error) { - hid_err(hdev, "failed to create sysfs attributes\n"); - goto err_cleanup_sysfs1; - } - - if (data->status & PICOLCD_BOOTLOADER) - error = picolcd_probe_bootloader(hdev, data); - else - error = picolcd_probe_lcd(hdev, data); - if (error) - goto err_cleanup_sysfs2; - - dbg_hid(PICOLCD_NAME " activated and initialized\n"); - return 0; - -err_cleanup_sysfs2: - device_remove_file(&hdev->dev, &dev_attr_operation_mode); -err_cleanup_sysfs1: - device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); -err_cleanup_hid_ll: - hid_hw_close(hdev); -err_cleanup_hid_hw: - hid_hw_stop(hdev); -err_cleanup_data: - kfree(data); -err_no_cleanup: - hid_set_drvdata(hdev, NULL); - - return error; -} - -static void picolcd_remove(struct hid_device *hdev) -{ - struct picolcd_data *data = hid_get_drvdata(hdev); - unsigned long flags; - - dbg_hid(PICOLCD_NAME " hardware remove...\n"); - spin_lock_irqsave(&data->lock, flags); - data->status |= PICOLCD_FAILED; - spin_unlock_irqrestore(&data->lock, flags); -#ifdef CONFIG_HID_PICOLCD_FB - /* short-circuit FB as early as possible in order to - * avoid long delays if we host console. - */ - if (data->fb_info) - data->fb_info->par = NULL; -#endif - - picolcd_exit_devfs(data); - device_remove_file(&hdev->dev, &dev_attr_operation_mode); - device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); - hid_hw_close(hdev); - hid_hw_stop(hdev); - hid_set_drvdata(hdev, NULL); - - /* Shortcut potential pending reply that will never arrive */ - spin_lock_irqsave(&data->lock, flags); - if (data->pending) - complete(&data->pending->ready); - spin_unlock_irqrestore(&data->lock, flags); - - /* Cleanup LED */ - picolcd_exit_leds(data); - /* Clean up the framebuffer */ - picolcd_exit_backlight(data); - picolcd_exit_lcd(data); - picolcd_exit_framebuffer(data); - /* Cleanup input */ - picolcd_exit_cir(data); - picolcd_exit_keys(data); - - mutex_destroy(&data->mutex); - /* Finally, clean up the picolcd data itself */ - kfree(data); -} - -static const struct hid_device_id picolcd_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, - { } -}; -MODULE_DEVICE_TABLE(hid, picolcd_devices); - -static struct hid_driver picolcd_driver = { - .name = "hid-picolcd", - .id_table = picolcd_devices, - .probe = picolcd_probe, - .remove = picolcd_remove, - .raw_event = picolcd_raw_event, -#ifdef CONFIG_PM - .suspend = picolcd_suspend, - .resume = picolcd_resume, - .reset_resume = picolcd_reset_resume, -#endif -}; - -static int __init picolcd_init(void) -{ - return hid_register_driver(&picolcd_driver); -} - -static void __exit picolcd_exit(void) -{ - hid_unregister_driver(&picolcd_driver); -#ifdef CONFIG_HID_PICOLCD_FB - flush_work_sync(&picolcd_fb_cleanup); - WARN_ON(fb_pending); -#endif -} - -module_init(picolcd_init); -module_exit(picolcd_exit); -MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-pl.c b/ANDROID_3.4.5/drivers/hid/hid-pl.c deleted file mode 100644 index 47ed74c4..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-pl.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Force feedback support for PantherLord/GreenAsia based devices - * - * The devices are distributed under various names and the same USB device ID - * can be used in both adapters and actual game controllers. - * - * 0810:0001 "Twin USB Joystick" - * - tested with PantherLord USB/PS2 2in1 Adapter - * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) - * - * 0e8f:0003 "GreenAsia Inc. USB Joystick " - * - tested with König Gaming gamepad - * - * 0e8f:0003 "GASIA USB Gamepad" - * - another version of the König gamepad - * - * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* #define DEBUG */ - -#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/hid.h> - -#include "hid-ids.h" - -#ifdef CONFIG_PANTHERLORD_FF -#include "usbhid/usbhid.h" - -struct plff_device { - struct hid_report *report; - s32 *strong; - s32 *weak; -}; - -static int hid_plff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct plff_device *plff = data; - int left, right; - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - debug("called with 0x%04x 0x%04x", left, right); - - left = left * 0x7f / 0xffff; - right = right * 0x7f / 0xffff; - - *plff->strong = left; - *plff->weak = right; - debug("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, plff->report, USB_DIR_OUT); - - return 0; -} - -static int plff_init(struct hid_device *hid) -{ - struct plff_device *plff; - struct hid_report *report; - struct hid_input *hidinput; - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct list_head *report_ptr = report_list; - struct input_dev *dev; - int error; - s32 *strong; - s32 *weak; - - /* The device contains one output report per physical device, all - containing 1 field, which contains 4 ff00.0002 usages and 4 16bit - absolute values. - - The input reports also contain a field which contains - 8 ff00.0001 usages and 8 boolean values. Their meaning is - currently unknown. - - A version of the 0e8f:0003 exists that has all the values in - separate fields and misses the extra input field, thus resembling - Zeroplus (hid-zpff) devices. - */ - - if (list_empty(report_list)) { - hid_err(hid, "no output reports found\n"); - return -ENODEV; - } - - list_for_each_entry(hidinput, &hid->inputs, list) { - - report_ptr = report_ptr->next; - - if (report_ptr == report_list) { - hid_err(hid, "required output report is missing\n"); - return -ENODEV; - } - - report = list_entry(report_ptr, struct hid_report, list); - if (report->maxfield < 1) { - hid_err(hid, "no fields in the report\n"); - return -ENODEV; - } - - if (report->field[0]->report_count >= 4) { - report->field[0]->value[0] = 0x00; - report->field[0]->value[1] = 0x00; - strong = &report->field[0]->value[2]; - weak = &report->field[0]->value[3]; - debug("detected single-field device"); - } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && - report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { - report->field[0]->value[0] = 0x00; - report->field[1]->value[0] = 0x00; - strong = &report->field[2]->value[0]; - weak = &report->field[3]->value[0]; - debug("detected 4-field device"); - } else { - hid_err(hid, "not enough fields or values\n"); - return -ENODEV; - } - - plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); - if (!plff) - return -ENOMEM; - - dev = hidinput->input; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, plff, hid_plff_play); - if (error) { - kfree(plff); - return error; - } - - plff->report = report; - plff->strong = strong; - plff->weak = weak; - - *strong = 0x00; - *weak = 0x00; - usbhid_submit_report(hid, plff->report, USB_DIR_OUT); - } - - hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); - - return 0; -} -#else -static inline int plff_init(struct hid_device *hid) -{ - return 0; -} -#endif - -static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - if (id->driver_data) - hdev->quirks |= HID_QUIRK_MULTI_INPUT; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - plff_init(hdev); - - return 0; -err: - return ret; -} - -static const struct hid_device_id pl_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR), - .driver_data = 1 }, /* Twin USB Joystick */ - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR), - .driver_data = 1 }, /* Twin USB Joystick */ - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, - { } -}; -MODULE_DEVICE_TABLE(hid, pl_devices); - -static struct hid_driver pl_driver = { - .name = "pantherlord", - .id_table = pl_devices, - .probe = pl_probe, -}; - -static int __init pl_init(void) -{ - return hid_register_driver(&pl_driver); -} - -static void __exit pl_exit(void) -{ - hid_unregister_driver(&pl_driver); -} - -module_init(pl_init); -module_exit(pl_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-primax.c b/ANDROID_3.4.5/drivers/hid/hid-primax.c deleted file mode 100644 index 4d3c60d8..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-primax.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * HID driver for primax and similar keyboards with in-band modifiers - * - * Copyright 2011 Google Inc. All Rights Reserved - * - * Author: - * Terry Lambert <tlambert@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/device.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -static int px_raw_event(struct hid_device *hid, struct hid_report *report, - u8 *data, int size) -{ - int idx = size; - - switch (report->id) { - case 0: /* keyboard input */ - /* - * Convert in-band modifier key values into out of band - * modifier bits and pull the key strokes from the report. - * Thus a report data set which looked like: - * - * [00][00][E0][30][00][00][00][00] - * (no modifier bits + "Left Shift" key + "1" key) - * - * Would be converted to: - * - * [01][00][00][30][00][00][00][00] - * (Left Shift modifier bit + "1" key) - * - * As long as it's in the size range, the upper level - * drivers don't particularly care if there are in-band - * 0-valued keys, so they don't stop parsing. - */ - while (--idx > 1) { - if (data[idx] < 0xE0 || data[idx] > 0xE7) - continue; - data[0] |= (1 << (data[idx] - 0xE0)); - data[idx] = 0; - } - hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0); - return 1; - - default: /* unknown report */ - /* Unknown report type; pass upstream */ - hid_info(hid, "unknown report type %d\n", report->id); - break; - } - - return 0; -} - -static int px_probe(struct hid_device *hid, const struct hid_device_id *id) -{ - int ret; - - ret = hid_parse(hid); - if (ret) { - hid_err(hid, "parse failed\n"); - goto fail; - } - - ret = hid_hw_start(hid, HID_CONNECT_DEFAULT); - if (ret) - hid_err(hid, "hw start failed\n"); - -fail: - return ret; -} - -static void px_remove(struct hid_device *hid) -{ - hid_hw_stop(hid); -} - -static const struct hid_device_id px_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - { } -}; -MODULE_DEVICE_TABLE(hid, px_devices); - -static struct hid_driver px_driver = { - .name = "primax", - .id_table = px_devices, - .raw_event = px_raw_event, - .probe = px_probe, - .remove = px_remove, -}; - -static int __init px_init(void) -{ - return hid_register_driver(&px_driver); -} - -static void __exit px_exit(void) -{ - hid_unregister_driver(&px_driver); -} - -module_init(px_init); -module_exit(px_exit); -MODULE_AUTHOR("Terry Lambert <tlambert@google.com>"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-prodikeys.c b/ANDROID_3.4.5/drivers/hid/hid-prodikeys.c deleted file mode 100644 index b71b77ab..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-prodikeys.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - * HID driver for the Prodikeys PC-MIDI Keyboard - * providing midi & extra multimedia keys functionality - * - * Copyright (c) 2009 Don Prince <dhprince.devel@yahoo.co.uk> - * - * Controls for Octave Shift Up/Down, Channel, and - * Sustain Duration available via sysfs. - * - */ - -/* - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/device.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/mutex.h> -#include <linux/hid.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/rawmidi.h> -#include "usbhid/usbhid.h" -#include "hid-ids.h" - - -#define pk_debug(format, arg...) \ - pr_debug("hid-prodikeys: " format "\n" , ## arg) -#define pk_error(format, arg...) \ - pr_err("hid-prodikeys: " format "\n" , ## arg) - -struct pcmidi_snd; - -struct pk_device { - unsigned long quirks; - - struct hid_device *hdev; - struct pcmidi_snd *pm; /* pcmidi device context */ -}; - -struct pcmidi_sustain { - unsigned long in_use; - struct pcmidi_snd *pm; - struct timer_list timer; - unsigned char status; - unsigned char note; - unsigned char velocity; -}; - -#define PCMIDI_SUSTAINED_MAX 32 -struct pcmidi_snd { - struct pk_device *pk; - unsigned short ifnum; - struct hid_report *pcmidi_report6; - struct input_dev *input_ep82; - unsigned short midi_mode; - unsigned short midi_sustain_mode; - unsigned short midi_sustain; - unsigned short midi_channel; - short midi_octave; - struct pcmidi_sustain sustained_notes[PCMIDI_SUSTAINED_MAX]; - unsigned short fn_state; - unsigned short last_key[24]; - spinlock_t rawmidi_in_lock; - struct snd_card *card; - struct snd_rawmidi *rwmidi; - struct snd_rawmidi_substream *in_substream; - struct snd_rawmidi_substream *out_substream; - unsigned long in_triggered; - unsigned long out_active; -}; - -#define PK_QUIRK_NOGET 0x00010000 -#define PCMIDI_MIDDLE_C 60 -#define PCMIDI_CHANNEL_MIN 0 -#define PCMIDI_CHANNEL_MAX 15 -#define PCMIDI_OCTAVE_MIN (-2) -#define PCMIDI_OCTAVE_MAX 2 -#define PCMIDI_SUSTAIN_MIN 0 -#define PCMIDI_SUSTAIN_MAX 5000 - -static const char shortname[] = "PC-MIDI"; -static const char longname[] = "Prodikeys PC-MIDI Keyboard"; - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -module_param_array(id, charp, NULL, 0444); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the PC-MIDI virtual audio driver"); -MODULE_PARM_DESC(id, "ID string for the PC-MIDI virtual audio driver"); -MODULE_PARM_DESC(enable, "Enable for the PC-MIDI virtual audio driver"); - - -/* Output routine for the sysfs channel file */ -static ssize_t show_channel(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - - dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel); - - return sprintf(buf, "%u (min:%u, max:%u)\n", pk->pm->midi_channel, - PCMIDI_CHANNEL_MIN, PCMIDI_CHANNEL_MAX); -} - -/* Input routine for the sysfs channel file */ -static ssize_t store_channel(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - - unsigned channel = 0; - - if (sscanf(buf, "%u", &channel) > 0 && channel <= PCMIDI_CHANNEL_MAX) { - dbg_hid("pcmidi sysfs write channel=%u\n", channel); - pk->pm->midi_channel = channel; - return strlen(buf); - } - return -EINVAL; -} - -static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel, - store_channel); - -static struct device_attribute *sysfs_device_attr_channel = { - &dev_attr_channel, - }; - -/* Output routine for the sysfs sustain file */ -static ssize_t show_sustain(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - - dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain); - - return sprintf(buf, "%u (off:%u, max:%u (ms))\n", pk->pm->midi_sustain, - PCMIDI_SUSTAIN_MIN, PCMIDI_SUSTAIN_MAX); -} - -/* Input routine for the sysfs sustain file */ -static ssize_t store_sustain(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - - unsigned sustain = 0; - - if (sscanf(buf, "%u", &sustain) > 0 && sustain <= PCMIDI_SUSTAIN_MAX) { - dbg_hid("pcmidi sysfs write sustain=%u\n", sustain); - pk->pm->midi_sustain = sustain; - pk->pm->midi_sustain_mode = - (0 == sustain || !pk->pm->midi_mode) ? 0 : 1; - return strlen(buf); - } - return -EINVAL; -} - -static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain, - store_sustain); - -static struct device_attribute *sysfs_device_attr_sustain = { - &dev_attr_sustain, - }; - -/* Output routine for the sysfs octave file */ -static ssize_t show_octave(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - - dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave); - - return sprintf(buf, "%d (min:%d, max:%d)\n", pk->pm->midi_octave, - PCMIDI_OCTAVE_MIN, PCMIDI_OCTAVE_MAX); -} - -/* Input routine for the sysfs octave file */ -static ssize_t store_octave(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - - int octave = 0; - - if (sscanf(buf, "%d", &octave) > 0 && - octave >= PCMIDI_OCTAVE_MIN && octave <= PCMIDI_OCTAVE_MAX) { - dbg_hid("pcmidi sysfs write octave=%d\n", octave); - pk->pm->midi_octave = octave; - return strlen(buf); - } - return -EINVAL; -} - -static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave, - store_octave); - -static struct device_attribute *sysfs_device_attr_octave = { - &dev_attr_octave, - }; - - -static void pcmidi_send_note(struct pcmidi_snd *pm, - unsigned char status, unsigned char note, unsigned char velocity) -{ - unsigned long flags; - unsigned char buffer[3]; - - buffer[0] = status; - buffer[1] = note; - buffer[2] = velocity; - - spin_lock_irqsave(&pm->rawmidi_in_lock, flags); - - if (!pm->in_substream) - goto drop_note; - if (!test_bit(pm->in_substream->number, &pm->in_triggered)) - goto drop_note; - - snd_rawmidi_receive(pm->in_substream, buffer, 3); - -drop_note: - spin_unlock_irqrestore(&pm->rawmidi_in_lock, flags); - - return; -} - -static void pcmidi_sustained_note_release(unsigned long data) -{ - struct pcmidi_sustain *pms = (struct pcmidi_sustain *)data; - - pcmidi_send_note(pms->pm, pms->status, pms->note, pms->velocity); - pms->in_use = 0; -} - -static void init_sustain_timers(struct pcmidi_snd *pm) -{ - struct pcmidi_sustain *pms; - unsigned i; - - for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { - pms = &pm->sustained_notes[i]; - pms->in_use = 0; - pms->pm = pm; - setup_timer(&pms->timer, pcmidi_sustained_note_release, - (unsigned long)pms); - } -} - -static void stop_sustain_timers(struct pcmidi_snd *pm) -{ - struct pcmidi_sustain *pms; - unsigned i; - - for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { - pms = &pm->sustained_notes[i]; - pms->in_use = 1; - del_timer_sync(&pms->timer); - } -} - -static int pcmidi_get_output_report(struct pcmidi_snd *pm) -{ - struct hid_device *hdev = pm->pk->hdev; - struct hid_report *report; - - list_for_each_entry(report, - &hdev->report_enum[HID_OUTPUT_REPORT].report_list, list) { - if (!(6 == report->id)) - continue; - - if (report->maxfield < 1) { - hid_err(hdev, "output report is empty\n"); - break; - } - if (report->field[0]->report_count != 2) { - hid_err(hdev, "field count too low\n"); - break; - } - pm->pcmidi_report6 = report; - return 0; - } - /* should never get here */ - return -ENODEV; -} - -static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state) -{ - struct hid_device *hdev = pm->pk->hdev; - struct hid_report *report = pm->pcmidi_report6; - report->field[0]->value[0] = 0x01; - report->field[0]->value[1] = state; - - usbhid_submit_report(hdev, report, USB_DIR_OUT); -} - -static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data) -{ - u32 bit_mask; - - bit_mask = data[1]; - bit_mask = (bit_mask << 8) | data[2]; - bit_mask = (bit_mask << 8) | data[3]; - - dbg_hid("pcmidi mode: %d\n", pm->midi_mode); - - /*KEY_MAIL or octave down*/ - if (pm->midi_mode && bit_mask == 0x004000) { - /* octave down */ - pm->midi_octave--; - if (pm->midi_octave < -2) - pm->midi_octave = -2; - dbg_hid("pcmidi mode: %d octave: %d\n", - pm->midi_mode, pm->midi_octave); - return 1; - } - /*KEY_WWW or sustain*/ - else if (pm->midi_mode && bit_mask == 0x000004) { - /* sustain on/off*/ - pm->midi_sustain_mode ^= 0x1; - return 1; - } - - return 0; /* continue key processing */ -} - -static int pcmidi_handle_report3(struct pcmidi_snd *pm, u8 *data, int size) -{ - struct pcmidi_sustain *pms; - unsigned i, j; - unsigned char status, note, velocity; - - unsigned num_notes = (size-1)/2; - for (j = 0; j < num_notes; j++) { - note = data[j*2+1]; - velocity = data[j*2+2]; - - if (note < 0x81) { /* note on */ - status = 128 + 16 + pm->midi_channel; /* 1001nnnn */ - note = note - 0x54 + PCMIDI_MIDDLE_C + - (pm->midi_octave * 12); - if (0 == velocity) - velocity = 1; /* force note on */ - } else { /* note off */ - status = 128 + pm->midi_channel; /* 1000nnnn */ - note = note - 0x94 + PCMIDI_MIDDLE_C + - (pm->midi_octave*12); - - if (pm->midi_sustain_mode) { - for (i = 0; i < PCMIDI_SUSTAINED_MAX; i++) { - pms = &pm->sustained_notes[i]; - if (!pms->in_use) { - pms->status = status; - pms->note = note; - pms->velocity = velocity; - pms->in_use = 1; - - mod_timer(&pms->timer, - jiffies + - msecs_to_jiffies(pm->midi_sustain)); - return 1; - } - } - } - } - pcmidi_send_note(pm, status, note, velocity); - } - - return 1; -} - -static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) -{ - unsigned key; - u32 bit_mask; - u32 bit_index; - - bit_mask = data[1]; - bit_mask = (bit_mask << 8) | data[2]; - bit_mask = (bit_mask << 8) | data[3]; - - /* break keys */ - for (bit_index = 0; bit_index < 24; bit_index++) { - key = pm->last_key[bit_index]; - if (!((0x01 << bit_index) & bit_mask)) { - input_event(pm->input_ep82, EV_KEY, - pm->last_key[bit_index], 0); - pm->last_key[bit_index] = 0; - } - } - - /* make keys */ - for (bit_index = 0; bit_index < 24; bit_index++) { - key = 0; - switch ((0x01 << bit_index) & bit_mask) { - case 0x000010: /* Fn lock*/ - pm->fn_state ^= 0x000010; - if (pm->fn_state) - pcmidi_submit_output_report(pm, 0xc5); - else - pcmidi_submit_output_report(pm, 0xc6); - continue; - case 0x020000: /* midi launcher..send a key (qwerty) or not? */ - pcmidi_submit_output_report(pm, 0xc1); - pm->midi_mode ^= 0x01; - - dbg_hid("pcmidi mode: %d\n", pm->midi_mode); - continue; - case 0x100000: /* KEY_MESSENGER or octave up */ - dbg_hid("pcmidi mode: %d\n", pm->midi_mode); - if (pm->midi_mode) { - pm->midi_octave++; - if (pm->midi_octave > 2) - pm->midi_octave = 2; - dbg_hid("pcmidi mode: %d octave: %d\n", - pm->midi_mode, pm->midi_octave); - continue; - } else - key = KEY_MESSENGER; - break; - case 0x400000: - key = KEY_CALENDAR; - break; - case 0x080000: - key = KEY_ADDRESSBOOK; - break; - case 0x040000: - key = KEY_DOCUMENTS; - break; - case 0x800000: - key = KEY_WORDPROCESSOR; - break; - case 0x200000: - key = KEY_SPREADSHEET; - break; - case 0x010000: - key = KEY_COFFEE; - break; - case 0x000100: - key = KEY_HELP; - break; - case 0x000200: - key = KEY_SEND; - break; - case 0x000400: - key = KEY_REPLY; - break; - case 0x000800: - key = KEY_FORWARDMAIL; - break; - case 0x001000: - key = KEY_NEW; - break; - case 0x002000: - key = KEY_OPEN; - break; - case 0x004000: - key = KEY_CLOSE; - break; - case 0x008000: - key = KEY_SAVE; - break; - case 0x000001: - key = KEY_UNDO; - break; - case 0x000002: - key = KEY_REDO; - break; - case 0x000004: - key = KEY_SPELLCHECK; - break; - case 0x000008: - key = KEY_PRINT; - break; - } - if (key) { - input_event(pm->input_ep82, EV_KEY, key, 1); - pm->last_key[bit_index] = key; - } - } - - return 1; -} - -static int pcmidi_handle_report( - struct pcmidi_snd *pm, unsigned report_id, u8 *data, int size) -{ - int ret = 0; - - switch (report_id) { - case 0x01: /* midi keys (qwerty)*/ - ret = pcmidi_handle_report1(pm, data); - break; - case 0x03: /* midi keyboard (musical)*/ - ret = pcmidi_handle_report3(pm, data, size); - break; - case 0x04: /* multimedia/midi keys (qwerty)*/ - ret = pcmidi_handle_report4(pm, data); - break; - } - return ret; -} - -static void pcmidi_setup_extra_keys( - struct pcmidi_snd *pm, struct input_dev *input) -{ - /* reassigned functionality for N/A keys - MY PICTURES => KEY_WORDPROCESSOR - MY MUSIC=> KEY_SPREADSHEET - */ - unsigned int keys[] = { - KEY_FN, - KEY_MESSENGER, KEY_CALENDAR, - KEY_ADDRESSBOOK, KEY_DOCUMENTS, - KEY_WORDPROCESSOR, - KEY_SPREADSHEET, - KEY_COFFEE, - KEY_HELP, KEY_SEND, - KEY_REPLY, KEY_FORWARDMAIL, - KEY_NEW, KEY_OPEN, - KEY_CLOSE, KEY_SAVE, - KEY_UNDO, KEY_REDO, - KEY_SPELLCHECK, KEY_PRINT, - 0 - }; - - unsigned int *pkeys = &keys[0]; - unsigned short i; - - if (pm->ifnum != 1) /* only set up ONCE for interace 1 */ - return; - - pm->input_ep82 = input; - - for (i = 0; i < 24; i++) - pm->last_key[i] = 0; - - while (*pkeys != 0) { - set_bit(*pkeys, pm->input_ep82->keybit); - ++pkeys; - } -} - -static int pcmidi_set_operational(struct pcmidi_snd *pm) -{ - if (pm->ifnum != 1) - return 0; /* only set up ONCE for interace 1 */ - - pcmidi_get_output_report(pm); - pcmidi_submit_output_report(pm, 0xc1); - return 0; -} - -static int pcmidi_snd_free(struct snd_device *dev) -{ - return 0; -} - -static int pcmidi_in_open(struct snd_rawmidi_substream *substream) -{ - struct pcmidi_snd *pm = substream->rmidi->private_data; - - dbg_hid("pcmidi in open\n"); - pm->in_substream = substream; - return 0; -} - -static int pcmidi_in_close(struct snd_rawmidi_substream *substream) -{ - dbg_hid("pcmidi in close\n"); - return 0; -} - -static void pcmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct pcmidi_snd *pm = substream->rmidi->private_data; - - dbg_hid("pcmidi in trigger %d\n", up); - - pm->in_triggered = up; -} - -static struct snd_rawmidi_ops pcmidi_in_ops = { - .open = pcmidi_in_open, - .close = pcmidi_in_close, - .trigger = pcmidi_in_trigger -}; - -static int pcmidi_snd_initialise(struct pcmidi_snd *pm) -{ - static int dev; - struct snd_card *card; - struct snd_rawmidi *rwmidi; - int err; - - static struct snd_device_ops ops = { - .dev_free = pcmidi_snd_free, - }; - - if (pm->ifnum != 1) - return 0; /* only set up midi device ONCE for interace 1 */ - - if (dev >= SNDRV_CARDS) - return -ENODEV; - - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - /* Setup sound card */ - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - pk_error("failed to create pc-midi sound card\n"); - err = -ENOMEM; - goto fail; - } - pm->card = card; - - /* Setup sound device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pm, &ops); - if (err < 0) { - pk_error("failed to create pc-midi sound device: error %d\n", - err); - goto fail; - } - - strncpy(card->driver, shortname, sizeof(card->driver)); - strncpy(card->shortname, shortname, sizeof(card->shortname)); - strncpy(card->longname, longname, sizeof(card->longname)); - - /* Set up rawmidi */ - err = snd_rawmidi_new(card, card->shortname, 0, - 0, 1, &rwmidi); - if (err < 0) { - pk_error("failed to create pc-midi rawmidi device: error %d\n", - err); - goto fail; - } - pm->rwmidi = rwmidi; - strncpy(rwmidi->name, card->shortname, sizeof(rwmidi->name)); - rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT; - rwmidi->private_data = pm; - - snd_rawmidi_set_ops(rwmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &pcmidi_in_ops); - - snd_card_set_dev(card, &pm->pk->hdev->dev); - - /* create sysfs variables */ - err = device_create_file(&pm->pk->hdev->dev, - sysfs_device_attr_channel); - if (err < 0) { - pk_error("failed to create sysfs attribute channel: error %d\n", - err); - goto fail; - } - - err = device_create_file(&pm->pk->hdev->dev, - sysfs_device_attr_sustain); - if (err < 0) { - pk_error("failed to create sysfs attribute sustain: error %d\n", - err); - goto fail_attr_sustain; - } - - err = device_create_file(&pm->pk->hdev->dev, - sysfs_device_attr_octave); - if (err < 0) { - pk_error("failed to create sysfs attribute octave: error %d\n", - err); - goto fail_attr_octave; - } - - spin_lock_init(&pm->rawmidi_in_lock); - - init_sustain_timers(pm); - pcmidi_set_operational(pm); - - /* register it */ - err = snd_card_register(card); - if (err < 0) { - pk_error("failed to register pc-midi sound card: error %d\n", - err); - goto fail_register; - } - - dbg_hid("pcmidi_snd_initialise finished ok\n"); - return 0; - -fail_register: - stop_sustain_timers(pm); - device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_octave); -fail_attr_octave: - device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_sustain); -fail_attr_sustain: - device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_channel); -fail: - if (pm->card) { - snd_card_free(pm->card); - pm->card = NULL; - } - return err; -} - -static int pcmidi_snd_terminate(struct pcmidi_snd *pm) -{ - if (pm->card) { - stop_sustain_timers(pm); - - device_remove_file(&pm->pk->hdev->dev, - sysfs_device_attr_channel); - device_remove_file(&pm->pk->hdev->dev, - sysfs_device_attr_sustain); - device_remove_file(&pm->pk->hdev->dev, - sysfs_device_attr_octave); - - snd_card_disconnect(pm->card); - snd_card_free_when_closed(pm->card); - } - - return 0; -} - -/* - * PC-MIDI report descriptor for report id is wrong. - */ -static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize == 178 && - rdesc[111] == 0x06 && rdesc[112] == 0x00 && - rdesc[113] == 0xff) { - hid_info(hdev, - "fixing up pc-midi keyboard report descriptor\n"); - - rdesc[144] = 0x18; /* report 4: was 0x10 report count */ - } - return rdesc; -} - -static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - struct pcmidi_snd *pm; - - pm = pk->pm; - - if (HID_UP_MSVENDOR == (usage->hid & HID_USAGE_PAGE) && - 1 == pm->ifnum) { - pcmidi_setup_extra_keys(pm, hi->input); - return 0; - } - - return 0; -} - - -static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *data, int size) -{ - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - int ret = 0; - - if (1 == pk->pm->ifnum) { - if (report->id == data[0]) - switch (report->id) { - case 0x01: /* midi keys (qwerty)*/ - case 0x03: /* midi keyboard (musical)*/ - case 0x04: /* extra/midi keys (qwerty)*/ - ret = pcmidi_handle_report(pk->pm, - report->id, data, size); - break; - } - } - - return ret; -} - -static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - unsigned long quirks = id->driver_data; - struct pk_device *pk; - struct pcmidi_snd *pm = NULL; - - pk = kzalloc(sizeof(*pk), GFP_KERNEL); - if (pk == NULL) { - hid_err(hdev, "can't alloc descriptor\n"); - return -ENOMEM; - } - - pk->hdev = hdev; - - pm = kzalloc(sizeof(*pm), GFP_KERNEL); - if (pm == NULL) { - hid_err(hdev, "can't alloc descriptor\n"); - ret = -ENOMEM; - goto err_free_pk; - } - - pm->pk = pk; - pk->pm = pm; - pm->ifnum = ifnum; - - hid_set_drvdata(hdev, pk); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "hid parse failed\n"); - goto err_free; - } - - if (quirks & PK_QUIRK_NOGET) { /* hid_parse cleared all the quirks */ - hdev->quirks |= HID_QUIRK_NOGET; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - ret = pcmidi_snd_initialise(pm); - if (ret < 0) - goto err_stop; - - return 0; -err_stop: - hid_hw_stop(hdev); -err_free: - kfree(pm); -err_free_pk: - kfree(pk); - - return ret; -} - -static void pk_remove(struct hid_device *hdev) -{ - struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev); - struct pcmidi_snd *pm; - - pm = pk->pm; - if (pm) { - pcmidi_snd_terminate(pm); - kfree(pm); - } - - hid_hw_stop(hdev); - - kfree(pk); -} - -static const struct hid_device_id pk_devices[] = { - {HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, - USB_DEVICE_ID_PRODIKEYS_PCMIDI), - .driver_data = PK_QUIRK_NOGET}, - { } -}; -MODULE_DEVICE_TABLE(hid, pk_devices); - -static struct hid_driver pk_driver = { - .name = "prodikeys", - .id_table = pk_devices, - .report_fixup = pk_report_fixup, - .input_mapping = pk_input_mapping, - .raw_event = pk_raw_event, - .probe = pk_probe, - .remove = pk_remove, -}; - -static int pk_init(void) -{ - int ret; - - ret = hid_register_driver(&pk_driver); - if (ret) - pr_err("can't register prodikeys driver\n"); - - return ret; -} - -static void pk_exit(void) -{ - hid_unregister_driver(&pk_driver); -} - -module_init(pk_init); -module_exit(pk_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-arvo.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-arvo.c deleted file mode 100644 index 093bfad0..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-arvo.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Roccat Arvo driver for Linux - * - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Roccat Arvo is a gamer keyboard with 5 macro keys that can be configured in - * 5 profiles. - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hid-roccat.h> -#include "hid-ids.h" -#include "hid-roccat-common.h" -#include "hid-roccat-arvo.h" - -static struct class *arvo_class; - -static ssize_t arvo_sysfs_show_mode_key(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct arvo_device *arvo = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - struct usb_device *usb_dev = - interface_to_usbdev(to_usb_interface(dev->parent->parent)); - struct arvo_mode_key temp_buf; - int retval; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_receive(usb_dev, ARVO_COMMAND_MODE_KEY, - &temp_buf, sizeof(struct arvo_mode_key)); - mutex_unlock(&arvo->arvo_lock); - if (retval) - return retval; - - return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.state); -} - -static ssize_t arvo_sysfs_set_mode_key(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct arvo_device *arvo = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - struct usb_device *usb_dev = - interface_to_usbdev(to_usb_interface(dev->parent->parent)); - struct arvo_mode_key temp_buf; - unsigned long state; - int retval; - - retval = strict_strtoul(buf, 10, &state); - if (retval) - return retval; - - temp_buf.command = ARVO_COMMAND_MODE_KEY; - temp_buf.state = state; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_send(usb_dev, ARVO_COMMAND_MODE_KEY, - &temp_buf, sizeof(struct arvo_mode_key)); - mutex_unlock(&arvo->arvo_lock); - if (retval) - return retval; - - return size; -} - -static ssize_t arvo_sysfs_show_key_mask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct arvo_device *arvo = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - struct usb_device *usb_dev = - interface_to_usbdev(to_usb_interface(dev->parent->parent)); - struct arvo_key_mask temp_buf; - int retval; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_receive(usb_dev, ARVO_COMMAND_KEY_MASK, - &temp_buf, sizeof(struct arvo_key_mask)); - mutex_unlock(&arvo->arvo_lock); - if (retval) - return retval; - - return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.key_mask); -} - -static ssize_t arvo_sysfs_set_key_mask(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct arvo_device *arvo = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - struct usb_device *usb_dev = - interface_to_usbdev(to_usb_interface(dev->parent->parent)); - struct arvo_key_mask temp_buf; - unsigned long key_mask; - int retval; - - retval = strict_strtoul(buf, 10, &key_mask); - if (retval) - return retval; - - temp_buf.command = ARVO_COMMAND_KEY_MASK; - temp_buf.key_mask = key_mask; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_send(usb_dev, ARVO_COMMAND_KEY_MASK, - &temp_buf, sizeof(struct arvo_key_mask)); - mutex_unlock(&arvo->arvo_lock); - if (retval) - return retval; - - return size; -} - -/* retval is 1-5 on success, < 0 on error */ -static int arvo_get_actual_profile(struct usb_device *usb_dev) -{ - struct arvo_actual_profile temp_buf; - int retval; - - retval = roccat_common_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, - &temp_buf, sizeof(struct arvo_actual_profile)); - - if (retval) - return retval; - - return temp_buf.actual_profile; -} - -static ssize_t arvo_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct arvo_device *arvo = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - - return snprintf(buf, PAGE_SIZE, "%d\n", arvo->actual_profile); -} - -static ssize_t arvo_sysfs_set_actual_profile(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct arvo_device *arvo = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - struct usb_device *usb_dev = - interface_to_usbdev(to_usb_interface(dev->parent->parent)); - struct arvo_actual_profile temp_buf; - unsigned long profile; - int retval; - - retval = strict_strtoul(buf, 10, &profile); - if (retval) - return retval; - - if (profile < 1 || profile > 5) - return -EINVAL; - - temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE; - temp_buf.actual_profile = profile; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, - &temp_buf, sizeof(struct arvo_actual_profile)); - if (!retval) { - arvo->actual_profile = profile; - retval = size; - } - mutex_unlock(&arvo->arvo_lock); - return retval; -} - -static ssize_t arvo_sysfs_write(struct file *fp, - struct kobject *kobj, void const *buf, - loff_t off, size_t count, size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_send(usb_dev, command, buf, real_size); - mutex_unlock(&arvo->arvo_lock); - - return (retval ? retval : real_size); -} - -static ssize_t arvo_sysfs_read(struct file *fp, - struct kobject *kobj, void *buf, loff_t off, - size_t count, size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off >= real_size) - return 0; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&arvo->arvo_lock); - retval = roccat_common_receive(usb_dev, command, buf, real_size); - mutex_unlock(&arvo->arvo_lock); - - return (retval ? retval : real_size); -} - -static ssize_t arvo_sysfs_write_button(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return arvo_sysfs_write(fp, kobj, buf, off, count, - sizeof(struct arvo_button), ARVO_COMMAND_BUTTON); -} - -static ssize_t arvo_sysfs_read_info(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return arvo_sysfs_read(fp, kobj, buf, off, count, - sizeof(struct arvo_info), ARVO_COMMAND_INFO); -} - - -static struct device_attribute arvo_attributes[] = { - __ATTR(mode_key, 0660, - arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key), - __ATTR(key_mask, 0660, - arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask), - __ATTR(actual_profile, 0660, - arvo_sysfs_show_actual_profile, - arvo_sysfs_set_actual_profile), - __ATTR_NULL -}; - -static struct bin_attribute arvo_bin_attributes[] = { - { - .attr = { .name = "button", .mode = 0220 }, - .size = sizeof(struct arvo_button), - .write = arvo_sysfs_write_button - }, - { - .attr = { .name = "info", .mode = 0440 }, - .size = sizeof(struct arvo_info), - .read = arvo_sysfs_read_info - }, - __ATTR_NULL -}; - -static int arvo_init_arvo_device_struct(struct usb_device *usb_dev, - struct arvo_device *arvo) -{ - int retval; - - mutex_init(&arvo->arvo_lock); - - retval = arvo_get_actual_profile(usb_dev); - if (retval < 0) - return retval; - arvo->actual_profile = retval; - - return 0; -} - -static int arvo_init_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct arvo_device *arvo; - int retval; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_KEYBOARD) { - hid_set_drvdata(hdev, NULL); - return 0; - } - - arvo = kzalloc(sizeof(*arvo), GFP_KERNEL); - if (!arvo) { - hid_err(hdev, "can't alloc device descriptor\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, arvo); - - retval = arvo_init_arvo_device_struct(usb_dev, arvo); - if (retval) { - hid_err(hdev, "couldn't init struct arvo_device\n"); - goto exit_free; - } - - retval = roccat_connect(arvo_class, hdev, - sizeof(struct arvo_roccat_report)); - if (retval < 0) { - hid_err(hdev, "couldn't init char dev\n"); - } else { - arvo->chrdev_minor = retval; - arvo->roccat_claimed = 1; - } - - return 0; -exit_free: - kfree(arvo); - return retval; -} - -static void arvo_remove_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct arvo_device *arvo; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_KEYBOARD) - return; - - arvo = hid_get_drvdata(hdev); - if (arvo->roccat_claimed) - roccat_disconnect(arvo->chrdev_minor); - kfree(arvo); -} - -static int arvo_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int retval; - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); - goto exit; - } - - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "hw start failed\n"); - goto exit; - } - - retval = arvo_init_specials(hdev); - if (retval) { - hid_err(hdev, "couldn't install keyboard\n"); - goto exit_stop; - } - - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void arvo_remove(struct hid_device *hdev) -{ - arvo_remove_specials(hdev); - hid_hw_stop(hdev); -} - -static void arvo_report_to_chrdev(struct arvo_device const *arvo, - u8 const *data) -{ - struct arvo_special_report const *special_report; - struct arvo_roccat_report roccat_report; - - special_report = (struct arvo_special_report const *)data; - - roccat_report.profile = arvo->actual_profile; - roccat_report.button = special_report->event & - ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON; - if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) == - ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS) - roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS; - else - roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE; - - roccat_report_event(arvo->chrdev_minor, - (uint8_t const *)&roccat_report); -} - -static int arvo_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *data, int size) -{ - struct arvo_device *arvo = hid_get_drvdata(hdev); - - if (size != 3) - return 0; - - if (arvo && arvo->roccat_claimed) - arvo_report_to_chrdev(arvo, data); - - return 0; -} - -static const struct hid_device_id arvo_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, arvo_devices); - -static struct hid_driver arvo_driver = { - .name = "arvo", - .id_table = arvo_devices, - .probe = arvo_probe, - .remove = arvo_remove, - .raw_event = arvo_raw_event -}; - -static int __init arvo_init(void) -{ - int retval; - - arvo_class = class_create(THIS_MODULE, "arvo"); - if (IS_ERR(arvo_class)) - return PTR_ERR(arvo_class); - arvo_class->dev_attrs = arvo_attributes; - arvo_class->dev_bin_attrs = arvo_bin_attributes; - - retval = hid_register_driver(&arvo_driver); - if (retval) - class_destroy(arvo_class); - return retval; -} - -static void __exit arvo_exit(void) -{ - hid_unregister_driver(&arvo_driver); - class_destroy(arvo_class); -} - -module_init(arvo_init); -module_exit(arvo_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat Arvo driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-arvo.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-arvo.h deleted file mode 100644 index ce8415e4..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-arvo.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __HID_ROCCAT_ARVO_H -#define __HID_ROCCAT_ARVO_H - -/* - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/types.h> - -struct arvo_mode_key { /* 2 bytes */ - uint8_t command; /* ARVO_COMMAND_MODE_KEY */ - uint8_t state; -} __packed; - -struct arvo_button { - uint8_t unknown[24]; -} __packed; - -struct arvo_info { - uint8_t unknown[8]; -} __packed; - -struct arvo_key_mask { /* 2 bytes */ - uint8_t command; /* ARVO_COMMAND_KEY_MASK */ - uint8_t key_mask; -} __packed; - -/* selected profile is persistent */ -struct arvo_actual_profile { /* 2 bytes */ - uint8_t command; /* ARVO_COMMAND_ACTUAL_PROFILE */ - uint8_t actual_profile; -} __packed; - -enum arvo_commands { - ARVO_COMMAND_MODE_KEY = 0x3, - ARVO_COMMAND_BUTTON = 0x4, - ARVO_COMMAND_INFO = 0x5, - ARVO_COMMAND_KEY_MASK = 0x6, - ARVO_COMMAND_ACTUAL_PROFILE = 0x7, -}; - -struct arvo_special_report { - uint8_t unknown1; /* always 0x01 */ - uint8_t event; - uint8_t unknown2; /* always 0x70 */ -} __packed; - -enum arvo_special_report_events { - ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS = 0x10, - ARVO_SPECIAL_REPORT_EVENT_ACTION_RELEASE = 0x0, -}; - -enum arvo_special_report_event_masks { - ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION = 0xf0, - ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON = 0x0f, -}; - -struct arvo_roccat_report { - uint8_t profile; - uint8_t button; - uint8_t action; -} __packed; - -enum arvo_roccat_report_action { - ARVO_ROCCAT_REPORT_ACTION_RELEASE = 0, - ARVO_ROCCAT_REPORT_ACTION_PRESS = 1, -}; - -struct arvo_device { - int roccat_claimed; - int chrdev_minor; - - struct mutex arvo_lock; - - int actual_profile; -}; - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-common.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-common.c deleted file mode 100644 index a6d93992..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-common.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Roccat common functions for device specific drivers - * - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/hid.h> -#include <linux/slab.h> -#include <linux/module.h> -#include "hid-roccat-common.h" - -static inline uint16_t roccat_common_feature_report(uint8_t report_id) -{ - return 0x300 | report_id; -} - -int roccat_common_receive(struct usb_device *usb_dev, uint report_id, - void *data, uint size) -{ - char *buf; - int len; - - buf = kmalloc(size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), - HID_REQ_GET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - roccat_common_feature_report(report_id), - 0, buf, size, USB_CTRL_SET_TIMEOUT); - - memcpy(data, buf, size); - kfree(buf); - return ((len < 0) ? len : ((len != size) ? -EIO : 0)); -} -EXPORT_SYMBOL_GPL(roccat_common_receive); - -int roccat_common_send(struct usb_device *usb_dev, uint report_id, - void const *data, uint size) -{ - char *buf; - int len; - - buf = kmemdup(data, size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - HID_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - roccat_common_feature_report(report_id), - 0, buf, size, USB_CTRL_SET_TIMEOUT); - - kfree(buf); - return ((len < 0) ? len : ((len != size) ? -EIO : 0)); -} -EXPORT_SYMBOL_GPL(roccat_common_send); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat common driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-common.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-common.h deleted file mode 100644 index 9a5bc61f..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-common.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __HID_ROCCAT_COMMON_H -#define __HID_ROCCAT_COMMON_H - -/* - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/usb.h> -#include <linux/types.h> - -int roccat_common_receive(struct usb_device *usb_dev, uint report_id, - void *data, uint size); -int roccat_common_send(struct usb_device *usb_dev, uint report_id, - void const *data, uint size); - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-isku.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-isku.c deleted file mode 100644 index 0e4a0ab4..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-isku.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Roccat Isku driver for Linux - * - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Roccat Isku is a gamer keyboard with macro keys that can be configured in - * 5 profiles. - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hid-roccat.h> -#include "hid-ids.h" -#include "hid-roccat-common.h" -#include "hid-roccat-isku.h" - -static struct class *isku_class; - -static void isku_profile_activated(struct isku_device *isku, uint new_profile) -{ - isku->actual_profile = new_profile; -} - -static int isku_receive(struct usb_device *usb_dev, uint command, - void *buf, uint size) -{ - return roccat_common_receive(usb_dev, command, buf, size); -} - -static int isku_receive_control_status(struct usb_device *usb_dev) -{ - int retval; - struct isku_control control; - - do { - msleep(50); - retval = isku_receive(usb_dev, ISKU_COMMAND_CONTROL, - &control, sizeof(struct isku_control)); - - if (retval) - return retval; - - switch (control.value) { - case ISKU_CONTROL_VALUE_STATUS_OK: - return 0; - case ISKU_CONTROL_VALUE_STATUS_WAIT: - continue; - case ISKU_CONTROL_VALUE_STATUS_INVALID: - /* seems to be critical - replug necessary */ - case ISKU_CONTROL_VALUE_STATUS_OVERLOAD: - return -EINVAL; - default: - hid_err(usb_dev, "isku_receive_control_status: " - "unknown response value 0x%x\n", - control.value); - return -EINVAL; - } - - } while (1); -} - -static int isku_send(struct usb_device *usb_dev, uint command, - void const *buf, uint size) -{ - int retval; - - retval = roccat_common_send(usb_dev, command, buf, size); - if (retval) - return retval; - - return isku_receive_control_status(usb_dev); -} - -static int isku_get_actual_profile(struct usb_device *usb_dev) -{ - struct isku_actual_profile buf; - int retval; - - retval = isku_receive(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, - &buf, sizeof(struct isku_actual_profile)); - return retval ? retval : buf.actual_profile; -} - -static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile) -{ - struct isku_actual_profile buf; - - buf.command = ISKU_COMMAND_ACTUAL_PROFILE; - buf.size = sizeof(struct isku_actual_profile); - buf.actual_profile = new_profile; - return isku_send(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, &buf, - sizeof(struct isku_actual_profile)); -} - -static ssize_t isku_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct isku_device *isku = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", isku->actual_profile); -} - -static ssize_t isku_sysfs_set_actual_profile(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct isku_device *isku; - struct usb_device *usb_dev; - unsigned long profile; - int retval; - struct isku_roccat_report roccat_report; - - dev = dev->parent->parent; - isku = hid_get_drvdata(dev_get_drvdata(dev)); - usb_dev = interface_to_usbdev(to_usb_interface(dev)); - - retval = strict_strtoul(buf, 10, &profile); - if (retval) - return retval; - - if (profile > 4) - return -EINVAL; - - mutex_lock(&isku->isku_lock); - - retval = isku_set_actual_profile(usb_dev, profile); - if (retval) { - mutex_unlock(&isku->isku_lock); - return retval; - } - - isku_profile_activated(isku, profile); - - roccat_report.event = ISKU_REPORT_BUTTON_EVENT_PROFILE; - roccat_report.data1 = profile + 1; - roccat_report.data2 = 0; - roccat_report.profile = profile + 1; - roccat_report_event(isku->chrdev_minor, (uint8_t const *)&roccat_report); - - mutex_unlock(&isku->isku_lock); - - return size; -} - -static struct device_attribute isku_attributes[] = { - __ATTR(actual_profile, 0660, - isku_sysfs_show_actual_profile, - isku_sysfs_set_actual_profile), - __ATTR_NULL -}; - -static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, - char *buf, loff_t off, size_t count, - size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off >= real_size) - return 0; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&isku->isku_lock); - retval = isku_receive(usb_dev, command, buf, real_size); - mutex_unlock(&isku->isku_lock); - - return retval ? retval : real_size; -} - -static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj, - void const *buf, loff_t off, size_t count, - size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&isku->isku_lock); - retval = isku_send(usb_dev, command, (void *)buf, real_size); - mutex_unlock(&isku->isku_lock); - - return retval ? retval : real_size; -} - -#define ISKU_SYSFS_W(thingy, THINGY) \ -static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj, \ - struct bin_attribute *attr, char *buf, \ - loff_t off, size_t count) \ -{ \ - return isku_sysfs_write(fp, kobj, buf, off, count, \ - sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ -} - -#define ISKU_SYSFS_R(thingy, THINGY) \ -static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, \ - struct bin_attribute *attr, char *buf, \ - loff_t off, size_t count) \ -{ \ - return isku_sysfs_read(fp, kobj, buf, off, count, \ - sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ -} - -#define ISKU_SYSFS_RW(thingy, THINGY) \ -ISKU_SYSFS_R(thingy, THINGY) \ -ISKU_SYSFS_W(thingy, THINGY) - -#define ISKU_BIN_ATTR_RW(thingy) \ -{ \ - .attr = { .name = #thingy, .mode = 0660 }, \ - .size = sizeof(struct isku_ ## thingy), \ - .read = isku_sysfs_read_ ## thingy, \ - .write = isku_sysfs_write_ ## thingy \ -} - -#define ISKU_BIN_ATTR_R(thingy) \ -{ \ - .attr = { .name = #thingy, .mode = 0440 }, \ - .size = sizeof(struct isku_ ## thingy), \ - .read = isku_sysfs_read_ ## thingy, \ -} - -#define ISKU_BIN_ATTR_W(thingy) \ -{ \ - .attr = { .name = #thingy, .mode = 0220 }, \ - .size = sizeof(struct isku_ ## thingy), \ - .write = isku_sysfs_write_ ## thingy \ -} - -ISKU_SYSFS_RW(macro, MACRO) -ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION) -ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE) -ISKU_SYSFS_RW(keys_media, KEYS_MEDIA) -ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER) -ISKU_SYSFS_RW(keys_macro, KEYS_MACRO) -ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK) -ISKU_SYSFS_RW(light, LIGHT) -ISKU_SYSFS_RW(key_mask, KEY_MASK) -ISKU_SYSFS_RW(last_set, LAST_SET) -ISKU_SYSFS_W(talk, TALK) -ISKU_SYSFS_R(info, INFO) -ISKU_SYSFS_W(control, CONTROL) - -static struct bin_attribute isku_bin_attributes[] = { - ISKU_BIN_ATTR_RW(macro), - ISKU_BIN_ATTR_RW(keys_function), - ISKU_BIN_ATTR_RW(keys_easyzone), - ISKU_BIN_ATTR_RW(keys_media), - ISKU_BIN_ATTR_RW(keys_thumbster), - ISKU_BIN_ATTR_RW(keys_macro), - ISKU_BIN_ATTR_RW(keys_capslock), - ISKU_BIN_ATTR_RW(light), - ISKU_BIN_ATTR_RW(key_mask), - ISKU_BIN_ATTR_RW(last_set), - ISKU_BIN_ATTR_W(talk), - ISKU_BIN_ATTR_R(info), - ISKU_BIN_ATTR_W(control), - __ATTR_NULL -}; - -static int isku_init_isku_device_struct(struct usb_device *usb_dev, - struct isku_device *isku) -{ - int retval; - - mutex_init(&isku->isku_lock); - - retval = isku_get_actual_profile(usb_dev); - if (retval < 0) - return retval; - isku_profile_activated(isku, retval); - - return 0; -} - -static int isku_init_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct isku_device *isku; - int retval; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - != ISKU_USB_INTERFACE_PROTOCOL) { - hid_set_drvdata(hdev, NULL); - return 0; - } - - isku = kzalloc(sizeof(*isku), GFP_KERNEL); - if (!isku) { - hid_err(hdev, "can't alloc device descriptor\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, isku); - - retval = isku_init_isku_device_struct(usb_dev, isku); - if (retval) { - hid_err(hdev, "couldn't init struct isku_device\n"); - goto exit_free; - } - - retval = roccat_connect(isku_class, hdev, - sizeof(struct isku_roccat_report)); - if (retval < 0) { - hid_err(hdev, "couldn't init char dev\n"); - } else { - isku->chrdev_minor = retval; - isku->roccat_claimed = 1; - } - - return 0; -exit_free: - kfree(isku); - return retval; -} - -static void isku_remove_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct isku_device *isku; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - != ISKU_USB_INTERFACE_PROTOCOL) - return; - - isku = hid_get_drvdata(hdev); - if (isku->roccat_claimed) - roccat_disconnect(isku->chrdev_minor); - kfree(isku); -} - -static int isku_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int retval; - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); - goto exit; - } - - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "hw start failed\n"); - goto exit; - } - - retval = isku_init_specials(hdev); - if (retval) { - hid_err(hdev, "couldn't install keyboard\n"); - goto exit_stop; - } - - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void isku_remove(struct hid_device *hdev) -{ - isku_remove_specials(hdev); - hid_hw_stop(hdev); -} - -static void isku_keep_values_up_to_date(struct isku_device *isku, - u8 const *data) -{ - struct isku_report_button const *button_report; - - switch (data[0]) { - case ISKU_REPORT_NUMBER_BUTTON: - button_report = (struct isku_report_button const *)data; - switch (button_report->event) { - case ISKU_REPORT_BUTTON_EVENT_PROFILE: - isku_profile_activated(isku, button_report->data1 - 1); - break; - } - break; - } -} - -static void isku_report_to_chrdev(struct isku_device const *isku, - u8 const *data) -{ - struct isku_roccat_report roccat_report; - struct isku_report_button const *button_report; - - if (data[0] != ISKU_REPORT_NUMBER_BUTTON) - return; - - button_report = (struct isku_report_button const *)data; - - roccat_report.event = button_report->event; - roccat_report.data1 = button_report->data1; - roccat_report.data2 = button_report->data2; - roccat_report.profile = isku->actual_profile + 1; - roccat_report_event(isku->chrdev_minor, - (uint8_t const *)&roccat_report); -} - -static int isku_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *data, int size) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct isku_device *isku = hid_get_drvdata(hdev); - - if (intf->cur_altsetting->desc.bInterfaceProtocol - != ISKU_USB_INTERFACE_PROTOCOL) - return 0; - - if (isku == NULL) - return 0; - - isku_keep_values_up_to_date(isku, data); - - if (isku->roccat_claimed) - isku_report_to_chrdev(isku, data); - - return 0; -} - -static const struct hid_device_id isku_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, isku_devices); - -static struct hid_driver isku_driver = { - .name = "isku", - .id_table = isku_devices, - .probe = isku_probe, - .remove = isku_remove, - .raw_event = isku_raw_event -}; - -static int __init isku_init(void) -{ - int retval; - isku_class = class_create(THIS_MODULE, "isku"); - if (IS_ERR(isku_class)) - return PTR_ERR(isku_class); - isku_class->dev_attrs = isku_attributes; - isku_class->dev_bin_attrs = isku_bin_attributes; - - retval = hid_register_driver(&isku_driver); - if (retval) - class_destroy(isku_class); - return retval; -} - -static void __exit isku_exit(void) -{ - hid_unregister_driver(&isku_driver); - class_destroy(isku_class); -} - -module_init(isku_init); -module_exit(isku_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat Isku driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-isku.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-isku.h deleted file mode 100644 index 075f6efa..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-isku.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef __HID_ROCCAT_ISKU_H -#define __HID_ROCCAT_ISKU_H - -/* - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/types.h> - -enum { - ISKU_PROFILE_NUM = 5, - ISKU_USB_INTERFACE_PROTOCOL = 0, -}; - -struct isku_control { - uint8_t command; /* ISKU_COMMAND_CONTROL */ - uint8_t value; - uint8_t request; -} __packed; - -enum isku_control_values { - ISKU_CONTROL_VALUE_STATUS_OVERLOAD = 0, - ISKU_CONTROL_VALUE_STATUS_OK = 1, - ISKU_CONTROL_VALUE_STATUS_INVALID = 2, - ISKU_CONTROL_VALUE_STATUS_WAIT = 3, -}; - -struct isku_actual_profile { - uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ - uint8_t size; /* always 3 */ - uint8_t actual_profile; -} __packed; - -struct isku_key_mask { - uint8_t command; /* ISKU_COMMAND_KEY_MASK */ - uint8_t size; /* 6 */ - uint8_t profile_number; /* 0-4 */ - uint8_t mask; - uint16_t checksum; -} __packed; - -struct isku_keys_function { - uint8_t data[0x29]; -} __packed; - -struct isku_keys_easyzone { - uint8_t data[0x41]; -} __packed; - -struct isku_keys_media { - uint8_t data[0x1d]; -} __packed; - -struct isku_keys_thumbster { - uint8_t data[0x17]; -} __packed; - -struct isku_keys_macro { - uint8_t data[0x23]; -} __packed; - -struct isku_keys_capslock { - uint8_t data[0x6]; -} __packed; - -struct isku_macro { - uint8_t data[0x823]; -} __packed; - -struct isku_light { - uint8_t data[0xa]; -} __packed; - -struct isku_info { - uint8_t data[2]; - uint8_t firmware_version; - uint8_t unknown[3]; -} __packed; - -struct isku_talk { - uint8_t data[0x10]; -} __packed; - -struct isku_last_set { - uint8_t data[0x14]; -} __packed; - -enum isku_commands { - ISKU_COMMAND_CONTROL = 0x4, - ISKU_COMMAND_ACTUAL_PROFILE = 0x5, - ISKU_COMMAND_KEY_MASK = 0x7, - ISKU_COMMAND_KEYS_FUNCTION = 0x8, - ISKU_COMMAND_KEYS_EASYZONE = 0x9, - ISKU_COMMAND_KEYS_MEDIA = 0xa, - ISKU_COMMAND_KEYS_THUMBSTER = 0xb, - ISKU_COMMAND_KEYS_MACRO = 0xd, - ISKU_COMMAND_MACRO = 0xe, - ISKU_COMMAND_INFO = 0xf, - ISKU_COMMAND_LIGHT = 0x10, - ISKU_COMMAND_KEYS_CAPSLOCK = 0x13, - ISKU_COMMAND_LAST_SET = 0x14, - ISKU_COMMAND_15 = 0x15, - ISKU_COMMAND_TALK = 0x16, - ISKU_COMMAND_FIRMWARE_WRITE = 0x1b, - ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, -}; - -struct isku_report_button { - uint8_t number; /* ISKU_REPORT_NUMBER_BUTTON */ - uint8_t zero; - uint8_t event; - uint8_t data1; - uint8_t data2; -}; - -enum isku_report_numbers { - ISKU_REPORT_NUMBER_BUTTON = 3, -}; - -enum isku_report_button_events { - ISKU_REPORT_BUTTON_EVENT_PROFILE = 0x2, -}; - -struct isku_roccat_report { - uint8_t event; - uint8_t data1; - uint8_t data2; - uint8_t profile; -} __packed; - -struct isku_device { - int roccat_claimed; - int chrdev_minor; - - struct mutex isku_lock; - - int actual_profile; -}; - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-kone.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-kone.c deleted file mode 100644 index 40090d60..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-kone.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Roccat Kone driver for Linux - * - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Roccat Kone is a gamer mouse which consists of a mouse part and a keyboard - * part. The keyboard part enables the mouse to execute stored macros with mixed - * key- and button-events. - * - * TODO implement on-the-fly polling-rate change - * The windows driver has the ability to change the polling rate of the - * device on the press of a mousebutton. - * Is it possible to remove and reinstall the urb in raw-event- or any - * other handler, or to defer this action to be executed somewhere else? - * - * TODO is it possible to overwrite group for sysfs attributes via udev? - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hid-roccat.h> -#include "hid-ids.h" -#include "hid-roccat-common.h" -#include "hid-roccat-kone.h" - -static uint profile_numbers[5] = {0, 1, 2, 3, 4}; - -static void kone_profile_activated(struct kone_device *kone, uint new_profile) -{ - kone->actual_profile = new_profile; - kone->actual_dpi = kone->profiles[new_profile - 1].startup_dpi; -} - -static void kone_profile_report(struct kone_device *kone, uint new_profile) -{ - struct kone_roccat_report roccat_report; - roccat_report.event = kone_mouse_event_switch_profile; - roccat_report.value = new_profile; - roccat_report.key = 0; - roccat_report_event(kone->chrdev_minor, (uint8_t *)&roccat_report); -} - -static int kone_receive(struct usb_device *usb_dev, uint usb_command, - void *data, uint size) -{ - char *buf; - int len; - - buf = kmalloc(size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), - HID_REQ_GET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); - - memcpy(data, buf, size); - kfree(buf); - return ((len < 0) ? len : ((len != size) ? -EIO : 0)); -} - -static int kone_send(struct usb_device *usb_dev, uint usb_command, - void const *data, uint size) -{ - char *buf; - int len; - - buf = kmemdup(data, size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - HID_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); - - kfree(buf); - return ((len < 0) ? len : ((len != size) ? -EIO : 0)); -} - -/* kone_class is used for creating sysfs attributes via roccat char device */ -static struct class *kone_class; - -static void kone_set_settings_checksum(struct kone_settings *settings) -{ - uint16_t checksum = 0; - unsigned char *address = (unsigned char *)settings; - int i; - - for (i = 0; i < sizeof(struct kone_settings) - 2; ++i, ++address) - checksum += *address; - settings->checksum = cpu_to_le16(checksum); -} - -/* - * Checks success after writing data to mouse - * On success returns 0 - * On failure returns errno - */ -static int kone_check_write(struct usb_device *usb_dev) -{ - int retval; - uint8_t data; - - do { - /* - * Mouse needs 50 msecs until it says ok, but there are - * 30 more msecs needed for next write to work. - */ - msleep(80); - - retval = kone_receive(usb_dev, - kone_command_confirm_write, &data, 1); - if (retval) - return retval; - - /* - * value of 3 seems to mean something like - * "not finished yet, but it looks good" - * So check again after a moment. - */ - } while (data == 3); - - if (data == 1) /* everything alright */ - return 0; - - /* unknown answer */ - hid_err(usb_dev, "got retval %d when checking write\n", data); - return -EIO; -} - -/* - * Reads settings from mouse and stores it in @buf - * On success returns 0 - * On failure returns errno - */ -static int kone_get_settings(struct usb_device *usb_dev, - struct kone_settings *buf) -{ - return kone_receive(usb_dev, kone_command_settings, buf, - sizeof(struct kone_settings)); -} - -/* - * Writes settings from @buf to mouse - * On success returns 0 - * On failure returns errno - */ -static int kone_set_settings(struct usb_device *usb_dev, - struct kone_settings const *settings) -{ - int retval; - retval = kone_send(usb_dev, kone_command_settings, - settings, sizeof(struct kone_settings)); - if (retval) - return retval; - return kone_check_write(usb_dev); -} - -/* - * Reads profile data from mouse and stores it in @buf - * @number: profile number to read - * On success returns 0 - * On failure returns errno - */ -static int kone_get_profile(struct usb_device *usb_dev, - struct kone_profile *buf, int number) -{ - int len; - - if (number < 1 || number > 5) - return -EINVAL; - - len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), - USB_REQ_CLEAR_FEATURE, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - kone_command_profile, number, buf, - sizeof(struct kone_profile), USB_CTRL_SET_TIMEOUT); - - if (len != sizeof(struct kone_profile)) - return -EIO; - - return 0; -} - -/* - * Writes profile data to mouse. - * @number: profile number to write - * On success returns 0 - * On failure returns errno - */ -static int kone_set_profile(struct usb_device *usb_dev, - struct kone_profile const *profile, int number) -{ - int len; - - if (number < 1 || number > 5) - return -EINVAL; - - len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), - USB_REQ_SET_CONFIGURATION, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - kone_command_profile, number, (void *)profile, - sizeof(struct kone_profile), - USB_CTRL_SET_TIMEOUT); - - if (len != sizeof(struct kone_profile)) - return len; - - if (kone_check_write(usb_dev)) - return -EIO; - - return 0; -} - -/* - * Reads value of "fast-clip-weight" and stores it in @result - * On success returns 0 - * On failure returns errno - */ -static int kone_get_weight(struct usb_device *usb_dev, int *result) -{ - int retval; - uint8_t data; - - retval = kone_receive(usb_dev, kone_command_weight, &data, 1); - - if (retval) - return retval; - - *result = (int)data; - return 0; -} - -/* - * Reads firmware_version of mouse and stores it in @result - * On success returns 0 - * On failure returns errno - */ -static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) -{ - int retval; - uint16_t data; - - retval = kone_receive(usb_dev, kone_command_firmware_version, - &data, 2); - if (retval) - return retval; - - *result = le16_to_cpu(data); - return 0; -} - -static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct kone_settings)) - return 0; - - if (off + count > sizeof(struct kone_settings)) - count = sizeof(struct kone_settings) - off; - - mutex_lock(&kone->kone_lock); - memcpy(buf, ((char const *)&kone->settings) + off, count); - mutex_unlock(&kone->kone_lock); - - return count; -} - -/* - * Writing settings automatically activates startup_profile. - * This function keeps values in kone_device up to date and assumes that in - * case of error the old data is still valid - */ -static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0, difference, old_profile; - - /* I need to get my data in one piece */ - if (off != 0 || count != sizeof(struct kone_settings)) - return -EINVAL; - - mutex_lock(&kone->kone_lock); - difference = memcmp(buf, &kone->settings, sizeof(struct kone_settings)); - if (difference) { - retval = kone_set_settings(usb_dev, - (struct kone_settings const *)buf); - if (retval) { - mutex_unlock(&kone->kone_lock); - return retval; - } - - old_profile = kone->settings.startup_profile; - memcpy(&kone->settings, buf, sizeof(struct kone_settings)); - - kone_profile_activated(kone, kone->settings.startup_profile); - - if (kone->settings.startup_profile != old_profile) - kone_profile_report(kone, kone->settings.startup_profile); - } - mutex_unlock(&kone->kone_lock); - - return sizeof(struct kone_settings); -} - -static ssize_t kone_sysfs_read_profilex(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct kone_profile)) - return 0; - - if (off + count > sizeof(struct kone_profile)) - count = sizeof(struct kone_profile) - off; - - mutex_lock(&kone->kone_lock); - memcpy(buf, ((char const *)&kone->profiles[*(uint *)(attr->private)]) + off, count); - mutex_unlock(&kone->kone_lock); - - return count; -} - -/* Writes data only if different to stored data */ -static ssize_t kone_sysfs_write_profilex(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) { - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - struct kone_profile *profile; - int retval = 0, difference; - - /* I need to get my data in one piece */ - if (off != 0 || count != sizeof(struct kone_profile)) - return -EINVAL; - - profile = &kone->profiles[*(uint *)(attr->private)]; - - mutex_lock(&kone->kone_lock); - difference = memcmp(buf, profile, sizeof(struct kone_profile)); - if (difference) { - retval = kone_set_profile(usb_dev, - (struct kone_profile const *)buf, - *(uint *)(attr->private) + 1); - if (!retval) - memcpy(profile, buf, sizeof(struct kone_profile)); - } - mutex_unlock(&kone->kone_lock); - - if (retval) - return retval; - - return sizeof(struct kone_profile); -} - -static ssize_t kone_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kone_device *kone = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile); -} - -static ssize_t kone_sysfs_show_actual_dpi(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kone_device *kone = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi); -} - -/* weight is read each time, since we don't get informed when it's changed */ -static ssize_t kone_sysfs_show_weight(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kone_device *kone; - struct usb_device *usb_dev; - int weight = 0; - int retval; - - dev = dev->parent->parent; - kone = hid_get_drvdata(dev_get_drvdata(dev)); - usb_dev = interface_to_usbdev(to_usb_interface(dev)); - - mutex_lock(&kone->kone_lock); - retval = kone_get_weight(usb_dev, &weight); - mutex_unlock(&kone->kone_lock); - - if (retval) - return retval; - return snprintf(buf, PAGE_SIZE, "%d\n", weight); -} - -static ssize_t kone_sysfs_show_firmware_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kone_device *kone = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version); -} - -static ssize_t kone_sysfs_show_tcu(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kone_device *kone = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu); -} - -static int kone_tcu_command(struct usb_device *usb_dev, int number) -{ - unsigned char value; - value = number; - return kone_send(usb_dev, kone_command_calibrate, &value, 1); -} - -/* - * Calibrating the tcu is the only action that changes settings data inside the - * mouse, so this data needs to be reread - */ -static ssize_t kone_sysfs_set_tcu(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct kone_device *kone; - struct usb_device *usb_dev; - int retval; - unsigned long state; - - dev = dev->parent->parent; - kone = hid_get_drvdata(dev_get_drvdata(dev)); - usb_dev = interface_to_usbdev(to_usb_interface(dev)); - - retval = strict_strtoul(buf, 10, &state); - if (retval) - return retval; - - if (state != 0 && state != 1) - return -EINVAL; - - mutex_lock(&kone->kone_lock); - - if (state == 1) { /* state activate */ - retval = kone_tcu_command(usb_dev, 1); - if (retval) - goto exit_unlock; - retval = kone_tcu_command(usb_dev, 2); - if (retval) - goto exit_unlock; - ssleep(5); /* tcu needs this time for calibration */ - retval = kone_tcu_command(usb_dev, 3); - if (retval) - goto exit_unlock; - retval = kone_tcu_command(usb_dev, 0); - if (retval) - goto exit_unlock; - retval = kone_tcu_command(usb_dev, 4); - if (retval) - goto exit_unlock; - /* - * Kone needs this time to settle things. - * Reading settings too early will result in invalid data. - * Roccat's driver waits 1 sec, maybe this time could be - * shortened. - */ - ssleep(1); - } - - /* calibration changes values in settings, so reread */ - retval = kone_get_settings(usb_dev, &kone->settings); - if (retval) - goto exit_no_settings; - - /* only write settings back if activation state is different */ - if (kone->settings.tcu != state) { - kone->settings.tcu = state; - kone_set_settings_checksum(&kone->settings); - - retval = kone_set_settings(usb_dev, &kone->settings); - if (retval) { - hid_err(usb_dev, "couldn't set tcu state\n"); - /* - * try to reread valid settings into buffer overwriting - * first error code - */ - retval = kone_get_settings(usb_dev, &kone->settings); - if (retval) - goto exit_no_settings; - goto exit_unlock; - } - /* calibration resets profile */ - kone_profile_activated(kone, kone->settings.startup_profile); - } - - retval = size; -exit_no_settings: - hid_err(usb_dev, "couldn't read settings\n"); -exit_unlock: - mutex_unlock(&kone->kone_lock); - return retval; -} - -static ssize_t kone_sysfs_show_startup_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kone_device *kone = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile); -} - -static ssize_t kone_sysfs_set_startup_profile(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct kone_device *kone; - struct usb_device *usb_dev; - int retval; - unsigned long new_startup_profile; - - dev = dev->parent->parent; - kone = hid_get_drvdata(dev_get_drvdata(dev)); - usb_dev = interface_to_usbdev(to_usb_interface(dev)); - - retval = strict_strtoul(buf, 10, &new_startup_profile); - if (retval) - return retval; - - if (new_startup_profile < 1 || new_startup_profile > 5) - return -EINVAL; - - mutex_lock(&kone->kone_lock); - - kone->settings.startup_profile = new_startup_profile; - kone_set_settings_checksum(&kone->settings); - - retval = kone_set_settings(usb_dev, &kone->settings); - if (retval) { - mutex_unlock(&kone->kone_lock); - return retval; - } - - /* changing the startup profile immediately activates this profile */ - kone_profile_activated(kone, new_startup_profile); - kone_profile_report(kone, new_startup_profile); - - mutex_unlock(&kone->kone_lock); - return size; -} - -static struct device_attribute kone_attributes[] = { - /* - * Read actual dpi settings. - * Returns raw value for further processing. Refer to enum - * kone_polling_rates to get real value. - */ - __ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL), - __ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL), - - /* - * The mouse can be equipped with one of four supplied weights from 5 - * to 20 grams which are recognized and its value can be read out. - * This returns the raw value reported by the mouse for easy evaluation - * by software. Refer to enum kone_weights to get corresponding real - * weight. - */ - __ATTR(weight, 0440, kone_sysfs_show_weight, NULL), - - /* - * Prints firmware version stored in mouse as integer. - * The raw value reported by the mouse is returned for easy evaluation, - * to get the real version number the decimal point has to be shifted 2 - * positions to the left. E.g. a value of 138 means 1.38. - */ - __ATTR(firmware_version, 0440, - kone_sysfs_show_firmware_version, NULL), - - /* - * Prints state of Tracking Control Unit as number where 0 = off and - * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and - * activates the tcu - */ - __ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu), - - /* Prints and takes the number of the profile the mouse starts with */ - __ATTR(startup_profile, 0660, - kone_sysfs_show_startup_profile, - kone_sysfs_set_startup_profile), - __ATTR_NULL -}; - -static struct bin_attribute kone_bin_attributes[] = { - { - .attr = { .name = "settings", .mode = 0660 }, - .size = sizeof(struct kone_settings), - .read = kone_sysfs_read_settings, - .write = kone_sysfs_write_settings - }, - { - .attr = { .name = "profile1", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profilex, - .write = kone_sysfs_write_profilex, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profilex, - .write = kone_sysfs_write_profilex, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profilex, - .write = kone_sysfs_write_profilex, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profilex, - .write = kone_sysfs_write_profilex, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5", .mode = 0660 }, - .size = sizeof(struct kone_profile), - .read = kone_sysfs_read_profilex, - .write = kone_sysfs_write_profilex, - .private = &profile_numbers[4] - }, - __ATTR_NULL -}; - -static int kone_init_kone_device_struct(struct usb_device *usb_dev, - struct kone_device *kone) -{ - uint i; - int retval; - - mutex_init(&kone->kone_lock); - - for (i = 0; i < 5; ++i) { - retval = kone_get_profile(usb_dev, &kone->profiles[i], i + 1); - if (retval) - return retval; - } - - retval = kone_get_settings(usb_dev, &kone->settings); - if (retval) - return retval; - - retval = kone_get_firmware_version(usb_dev, &kone->firmware_version); - if (retval) - return retval; - - kone_profile_activated(kone, kone->settings.startup_profile); - - return 0; -} - -/* - * Since IGNORE_MOUSE quirk moved to hid-apple, there is no way to bind only to - * mousepart if usb_hid is compiled into the kernel and kone is compiled as - * module. - * Secial behaviour is bound only to mousepart since only mouseevents contain - * additional notifications. - */ -static int kone_init_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct kone_device *kone; - int retval; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - - kone = kzalloc(sizeof(*kone), GFP_KERNEL); - if (!kone) { - hid_err(hdev, "can't alloc device descriptor\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, kone); - - retval = kone_init_kone_device_struct(usb_dev, kone); - if (retval) { - hid_err(hdev, "couldn't init struct kone_device\n"); - goto exit_free; - } - - retval = roccat_connect(kone_class, hdev, - sizeof(struct kone_roccat_report)); - if (retval < 0) { - hid_err(hdev, "couldn't init char dev\n"); - /* be tolerant about not getting chrdev */ - } else { - kone->roccat_claimed = 1; - kone->chrdev_minor = retval; - } - } else { - hid_set_drvdata(hdev, NULL); - } - - return 0; -exit_free: - kfree(kone); - return retval; -} - -static void kone_remove_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct kone_device *kone; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - kone = hid_get_drvdata(hdev); - if (kone->roccat_claimed) - roccat_disconnect(kone->chrdev_minor); - kfree(hid_get_drvdata(hdev)); - } -} - -static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int retval; - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); - goto exit; - } - - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "hw start failed\n"); - goto exit; - } - - retval = kone_init_specials(hdev); - if (retval) { - hid_err(hdev, "couldn't install mouse\n"); - goto exit_stop; - } - - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void kone_remove(struct hid_device *hdev) -{ - kone_remove_specials(hdev); - hid_hw_stop(hdev); -} - -/* handle special events and keep actual profile and dpi values up to date */ -static void kone_keep_values_up_to_date(struct kone_device *kone, - struct kone_mouse_event const *event) -{ - switch (event->event) { - case kone_mouse_event_switch_profile: - kone->actual_dpi = kone->profiles[event->value - 1]. - startup_dpi; - case kone_mouse_event_osd_profile: - kone->actual_profile = event->value; - break; - case kone_mouse_event_switch_dpi: - case kone_mouse_event_osd_dpi: - kone->actual_dpi = event->value; - break; - } -} - -static void kone_report_to_chrdev(struct kone_device const *kone, - struct kone_mouse_event const *event) -{ - struct kone_roccat_report roccat_report; - - switch (event->event) { - case kone_mouse_event_switch_profile: - case kone_mouse_event_switch_dpi: - case kone_mouse_event_osd_profile: - case kone_mouse_event_osd_dpi: - roccat_report.event = event->event; - roccat_report.value = event->value; - roccat_report.key = 0; - roccat_report_event(kone->chrdev_minor, - (uint8_t *)&roccat_report); - break; - case kone_mouse_event_call_overlong_macro: - if (event->value == kone_keystroke_action_press) { - roccat_report.event = kone_mouse_event_call_overlong_macro; - roccat_report.value = kone->actual_profile; - roccat_report.key = event->macro_key; - roccat_report_event(kone->chrdev_minor, - (uint8_t *)&roccat_report); - } - break; - } - -} - -/* - * Is called for keyboard- and mousepart. - * Only mousepart gets informations about special events in its extended event - * structure. - */ -static int kone_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *data, int size) -{ - struct kone_device *kone = hid_get_drvdata(hdev); - struct kone_mouse_event *event = (struct kone_mouse_event *)data; - - /* keyboard events are always processed by default handler */ - if (size != sizeof(struct kone_mouse_event)) - return 0; - - if (kone == NULL) - return 0; - - /* - * Firmware 1.38 introduced new behaviour for tilt and special buttons. - * Pressed button is reported in each movement event. - * Workaround sends only one event per press. - */ - if (memcmp(&kone->last_mouse_event.tilt, &event->tilt, 5)) - memcpy(&kone->last_mouse_event, event, - sizeof(struct kone_mouse_event)); - else - memset(&event->tilt, 0, 5); - - kone_keep_values_up_to_date(kone, event); - - if (kone->roccat_claimed) - kone_report_to_chrdev(kone, event); - - return 0; /* always do further processing */ -} - -static const struct hid_device_id kone_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, kone_devices); - -static struct hid_driver kone_driver = { - .name = "kone", - .id_table = kone_devices, - .probe = kone_probe, - .remove = kone_remove, - .raw_event = kone_raw_event -}; - -static int __init kone_init(void) -{ - int retval; - - /* class name has to be same as driver name */ - kone_class = class_create(THIS_MODULE, "kone"); - if (IS_ERR(kone_class)) - return PTR_ERR(kone_class); - kone_class->dev_attrs = kone_attributes; - kone_class->dev_bin_attrs = kone_bin_attributes; - - retval = hid_register_driver(&kone_driver); - if (retval) - class_destroy(kone_class); - return retval; -} - -static void __exit kone_exit(void) -{ - hid_unregister_driver(&kone_driver); - class_destroy(kone_class); -} - -module_init(kone_init); -module_exit(kone_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat Kone driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-kone.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-kone.h deleted file mode 100644 index 64abb5b8..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-kone.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef __HID_ROCCAT_KONE_H -#define __HID_ROCCAT_KONE_H - -/* - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/types.h> - -struct kone_keystroke { - uint8_t key; - uint8_t action; - uint16_t period; /* in milliseconds */ -} __attribute__ ((__packed__)); - -enum kone_keystroke_buttons { - kone_keystroke_button_1 = 0xf0, /* left mouse button */ - kone_keystroke_button_2 = 0xf1, /* right mouse button */ - kone_keystroke_button_3 = 0xf2, /* wheel */ - kone_keystroke_button_9 = 0xf3, /* side button up */ - kone_keystroke_button_8 = 0xf4 /* side button down */ -}; - -enum kone_keystroke_actions { - kone_keystroke_action_press = 0, - kone_keystroke_action_release = 1 -}; - -struct kone_button_info { - uint8_t number; /* range 1-8 */ - uint8_t type; - uint8_t macro_type; /* 0 = short, 1 = overlong */ - uint8_t macro_set_name[16]; /* can be max 15 chars long */ - uint8_t macro_name[16]; /* can be max 15 chars long */ - uint8_t count; - struct kone_keystroke keystrokes[20]; -} __attribute__ ((__packed__)); - -enum kone_button_info_types { - /* valid button types until firmware 1.32 */ - kone_button_info_type_button_1 = 0x1, /* click (left mouse button) */ - kone_button_info_type_button_2 = 0x2, /* menu (right mouse button)*/ - kone_button_info_type_button_3 = 0x3, /* scroll (wheel) */ - kone_button_info_type_double_click = 0x4, - kone_button_info_type_key = 0x5, - kone_button_info_type_macro = 0x6, - kone_button_info_type_off = 0x7, - /* TODO clarify function and rename */ - kone_button_info_type_osd_xy_prescaling = 0x8, - kone_button_info_type_osd_dpi = 0x9, - kone_button_info_type_osd_profile = 0xa, - kone_button_info_type_button_9 = 0xb, /* ie forward */ - kone_button_info_type_button_8 = 0xc, /* ie backward */ - kone_button_info_type_dpi_up = 0xd, /* internal */ - kone_button_info_type_dpi_down = 0xe, /* internal */ - kone_button_info_type_button_7 = 0xf, /* tilt left */ - kone_button_info_type_button_6 = 0x10, /* tilt right */ - kone_button_info_type_profile_up = 0x11, /* internal */ - kone_button_info_type_profile_down = 0x12, /* internal */ - /* additional valid button types since firmware 1.38 */ - kone_button_info_type_multimedia_open_player = 0x20, - kone_button_info_type_multimedia_next_track = 0x21, - kone_button_info_type_multimedia_prev_track = 0x22, - kone_button_info_type_multimedia_play_pause = 0x23, - kone_button_info_type_multimedia_stop = 0x24, - kone_button_info_type_multimedia_mute = 0x25, - kone_button_info_type_multimedia_volume_up = 0x26, - kone_button_info_type_multimedia_volume_down = 0x27 -}; - -enum kone_button_info_numbers { - kone_button_top = 1, - kone_button_wheel_tilt_left = 2, - kone_button_wheel_tilt_right = 3, - kone_button_forward = 4, - kone_button_backward = 5, - kone_button_middle = 6, - kone_button_plus = 7, - kone_button_minus = 8, -}; - -struct kone_light_info { - uint8_t number; /* number of light 1-5 */ - uint8_t mod; /* 1 = on, 2 = off */ - uint8_t red; /* range 0x00-0xff */ - uint8_t green; /* range 0x00-0xff */ - uint8_t blue; /* range 0x00-0xff */ -} __attribute__ ((__packed__)); - -struct kone_profile { - uint16_t size; /* always 975 */ - uint16_t unused; /* always 0 */ - - /* - * range 1-5 - * This number does not need to correspond with location where profile - * saved - */ - uint8_t profile; /* range 1-5 */ - - uint16_t main_sensitivity; /* range 100-1000 */ - uint8_t xy_sensitivity_enabled; /* 1 = on, 2 = off */ - uint16_t x_sensitivity; /* range 100-1000 */ - uint16_t y_sensitivity; /* range 100-1000 */ - uint8_t dpi_rate; /* bit 1 = 800, ... */ - uint8_t startup_dpi; /* range 1-6 */ - uint8_t polling_rate; /* 1 = 125Hz, 2 = 500Hz, 3 = 1000Hz */ - /* kone has no dcu - * value is always 2 in firmwares <= 1.32 and - * 1 in firmwares > 1.32 - */ - uint8_t dcu_flag; - uint8_t light_effect_1; /* range 1-3 */ - uint8_t light_effect_2; /* range 1-5 */ - uint8_t light_effect_3; /* range 1-4 */ - uint8_t light_effect_speed; /* range 0-255 */ - - struct kone_light_info light_infos[5]; - /* offset is kone_button_info_numbers - 1 */ - struct kone_button_info button_infos[8]; - - uint16_t checksum; /* \brief holds checksum of struct */ -} __attribute__ ((__packed__)); - -enum kone_polling_rates { - kone_polling_rate_125 = 1, - kone_polling_rate_500 = 2, - kone_polling_rate_1000 = 3 -}; - -struct kone_settings { - uint16_t size; /* always 36 */ - uint8_t startup_profile; /* 1-5 */ - uint8_t unknown1; - uint8_t tcu; /* 0 = off, 1 = on */ - uint8_t unknown2[23]; - uint8_t calibration_data[4]; - uint8_t unknown3[2]; - uint16_t checksum; -} __attribute__ ((__packed__)); - -/* - * 12 byte mouse event read by interrupt_read - */ -struct kone_mouse_event { - uint8_t report_number; /* always 1 */ - uint8_t button; - uint16_t x; - uint16_t y; - uint8_t wheel; /* up = 1, down = -1 */ - uint8_t tilt; /* right = 1, left = -1 */ - uint8_t unknown; - uint8_t event; - uint8_t value; /* press = 0, release = 1 */ - uint8_t macro_key; /* 0 to 8 */ -} __attribute__ ((__packed__)); - -enum kone_mouse_events { - /* osd events are thought to be display on screen */ - kone_mouse_event_osd_dpi = 0xa0, - kone_mouse_event_osd_profile = 0xb0, - /* TODO clarify meaning and occurence of kone_mouse_event_calibration */ - kone_mouse_event_calibration = 0xc0, - kone_mouse_event_call_overlong_macro = 0xe0, - /* switch events notify if user changed values with mousebutton click */ - kone_mouse_event_switch_dpi = 0xf0, - kone_mouse_event_switch_profile = 0xf1 -}; - -enum kone_commands { - kone_command_profile = 0x5a, - kone_command_settings = 0x15a, - kone_command_firmware_version = 0x25a, - kone_command_weight = 0x45a, - kone_command_calibrate = 0x55a, - kone_command_confirm_write = 0x65a, - kone_command_firmware = 0xe5a -}; - -struct kone_roccat_report { - uint8_t event; - uint8_t value; /* holds dpi or profile value */ - uint8_t key; /* macro key on overlong macro execution */ -} __attribute__ ((__packed__)); - -struct kone_device { - /* - * Storing actual values when we get informed about changes since there - * is no way of getting this information from the device on demand - */ - int actual_profile, actual_dpi; - /* Used for neutralizing abnormal button behaviour */ - struct kone_mouse_event last_mouse_event; - - /* - * It's unlikely that multiple sysfs attributes are accessed at a time, - * so only one mutex is used to secure hardware access and profiles and - * settings of this struct. - */ - struct mutex kone_lock; - - /* - * Storing the data here reduces IO and ensures that data is available - * when its needed (E.g. interrupt handler). - */ - struct kone_profile profiles[5]; - struct kone_settings settings; - - /* - * firmware doesn't change unless firmware update is implemented, - * so it's read only once - */ - int firmware_version; - - int roccat_claimed; - int chrdev_minor; -}; - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-koneplus.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-koneplus.c deleted file mode 100644 index 59e47770..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-koneplus.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Roccat Kone[+] driver for Linux - * - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Roccat Kone[+] is an updated/improved version of the Kone with more memory - * and functionality and without the non-standard behaviours the Kone had. - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hid-roccat.h> -#include "hid-ids.h" -#include "hid-roccat-common.h" -#include "hid-roccat-koneplus.h" - -static uint profile_numbers[5] = {0, 1, 2, 3, 4}; - -static struct class *koneplus_class; - -static void koneplus_profile_activated(struct koneplus_device *koneplus, - uint new_profile) -{ - koneplus->actual_profile = new_profile; -} - -static int koneplus_send_control(struct usb_device *usb_dev, uint value, - enum koneplus_control_requests request) -{ - struct koneplus_control control; - - if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || - request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && - value > 4) - return -EINVAL; - - control.command = KONEPLUS_COMMAND_CONTROL; - control.value = value; - control.request = request; - - return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL, - &control, sizeof(struct koneplus_control)); -} - -static int koneplus_receive_control_status(struct usb_device *usb_dev) -{ - int retval; - struct koneplus_control control; - - do { - retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL, - &control, sizeof(struct koneplus_control)); - - /* check if we get a completely wrong answer */ - if (retval) - return retval; - - if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) - return 0; - - /* indicates that hardware needs some more time to complete action */ - if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { - msleep(500); /* windows driver uses 1000 */ - continue; - } - - /* seems to be critical - replug necessary */ - if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) - return -EINVAL; - - hid_err(usb_dev, "koneplus_receive_control_status: " - "unknown response value 0x%x\n", control.value); - return -EINVAL; - } while (1); -} - -static int koneplus_send(struct usb_device *usb_dev, uint command, - void const *buf, uint size) -{ - int retval; - - retval = roccat_common_send(usb_dev, command, buf, size); - if (retval) - return retval; - - return koneplus_receive_control_status(usb_dev); -} - -static int koneplus_select_profile(struct usb_device *usb_dev, uint number, - enum koneplus_control_requests request) -{ - int retval; - - retval = koneplus_send_control(usb_dev, number, request); - if (retval) - return retval; - - /* allow time to settle things - windows driver uses 500 */ - msleep(100); - - retval = koneplus_receive_control_status(usb_dev); - if (retval) - return retval; - - return 0; -} - -static int koneplus_get_info(struct usb_device *usb_dev, - struct koneplus_info *buf) -{ - return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO, - buf, sizeof(struct koneplus_info)); -} - -static int koneplus_get_profile_settings(struct usb_device *usb_dev, - struct koneplus_profile_settings *buf, uint number) -{ - int retval; - - retval = koneplus_select_profile(usb_dev, number, - KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); - if (retval) - return retval; - - return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, - buf, sizeof(struct koneplus_profile_settings)); -} - -static int koneplus_set_profile_settings(struct usb_device *usb_dev, - struct koneplus_profile_settings const *settings) -{ - return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, - settings, sizeof(struct koneplus_profile_settings)); -} - -static int koneplus_get_profile_buttons(struct usb_device *usb_dev, - struct koneplus_profile_buttons *buf, int number) -{ - int retval; - - retval = koneplus_select_profile(usb_dev, number, - KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); - if (retval) - return retval; - - return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, - buf, sizeof(struct koneplus_profile_buttons)); -} - -static int koneplus_set_profile_buttons(struct usb_device *usb_dev, - struct koneplus_profile_buttons const *buttons) -{ - return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, - buttons, sizeof(struct koneplus_profile_buttons)); -} - -/* retval is 0-4 on success, < 0 on error */ -static int koneplus_get_actual_profile(struct usb_device *usb_dev) -{ - struct koneplus_actual_profile buf; - int retval; - - retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, - &buf, sizeof(struct koneplus_actual_profile)); - - return retval ? retval : buf.actual_profile; -} - -static int koneplus_set_actual_profile(struct usb_device *usb_dev, - int new_profile) -{ - struct koneplus_actual_profile buf; - - buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE; - buf.size = sizeof(struct koneplus_actual_profile); - buf.actual_profile = new_profile; - - return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, - &buf, sizeof(struct koneplus_actual_profile)); -} - -static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, - char *buf, loff_t off, size_t count, - size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off >= real_size) - return 0; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&koneplus->koneplus_lock); - retval = roccat_common_receive(usb_dev, command, buf, real_size); - mutex_unlock(&koneplus->koneplus_lock); - - if (retval) - return retval; - - return real_size; -} - -static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, - void const *buf, loff_t off, size_t count, - size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&koneplus->koneplus_lock); - retval = koneplus_send(usb_dev, command, buf, real_size); - mutex_unlock(&koneplus->koneplus_lock); - - if (retval) - return retval; - - return real_size; -} - -static ssize_t koneplus_sysfs_write_talk(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return koneplus_sysfs_write(fp, kobj, buf, off, count, - sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK); -} - -static ssize_t koneplus_sysfs_write_macro(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return koneplus_sysfs_write(fp, kobj, buf, off, count, - sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO); -} - -static ssize_t koneplus_sysfs_read_sensor(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return koneplus_sysfs_read(fp, kobj, buf, off, count, - sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR); -} - -static ssize_t koneplus_sysfs_write_sensor(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return koneplus_sysfs_write(fp, kobj, buf, off, count, - sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR); -} - -static ssize_t koneplus_sysfs_write_tcu(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return koneplus_sysfs_write(fp, kobj, buf, off, count, - sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU); -} - -static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - return koneplus_sysfs_read(fp, kobj, buf, off, count, - sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU); -} - -static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct koneplus_profile_settings)) - return 0; - - if (off + count > sizeof(struct koneplus_profile_settings)) - count = sizeof(struct koneplus_profile_settings) - off; - - mutex_lock(&koneplus->koneplus_lock); - memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, - count); - mutex_unlock(&koneplus->koneplus_lock); - - return count; -} - -static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - int profile_number; - struct koneplus_profile_settings *profile_settings; - - if (off != 0 || count != sizeof(struct koneplus_profile_settings)) - return -EINVAL; - - profile_number = ((struct koneplus_profile_settings const *)buf)->number; - profile_settings = &koneplus->profile_settings[profile_number]; - - mutex_lock(&koneplus->koneplus_lock); - difference = memcmp(buf, profile_settings, - sizeof(struct koneplus_profile_settings)); - if (difference) { - retval = koneplus_set_profile_settings(usb_dev, - (struct koneplus_profile_settings const *)buf); - if (!retval) - memcpy(profile_settings, buf, - sizeof(struct koneplus_profile_settings)); - } - mutex_unlock(&koneplus->koneplus_lock); - - if (retval) - return retval; - - return sizeof(struct koneplus_profile_settings); -} - -static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct koneplus_profile_buttons)) - return 0; - - if (off + count > sizeof(struct koneplus_profile_buttons)) - count = sizeof(struct koneplus_profile_buttons) - off; - - mutex_lock(&koneplus->koneplus_lock); - memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, - count); - mutex_unlock(&koneplus->koneplus_lock); - - return count; -} - -static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - uint profile_number; - struct koneplus_profile_buttons *profile_buttons; - - if (off != 0 || count != sizeof(struct koneplus_profile_buttons)) - return -EINVAL; - - profile_number = ((struct koneplus_profile_buttons const *)buf)->number; - profile_buttons = &koneplus->profile_buttons[profile_number]; - - mutex_lock(&koneplus->koneplus_lock); - difference = memcmp(buf, profile_buttons, - sizeof(struct koneplus_profile_buttons)); - if (difference) { - retval = koneplus_set_profile_buttons(usb_dev, - (struct koneplus_profile_buttons const *)buf); - if (!retval) - memcpy(profile_buttons, buf, - sizeof(struct koneplus_profile_buttons)); - } - mutex_unlock(&koneplus->koneplus_lock); - - if (retval) - return retval; - - return sizeof(struct koneplus_profile_buttons); -} - -static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct koneplus_device *koneplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); -} - -static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct koneplus_device *koneplus; - struct usb_device *usb_dev; - unsigned long profile; - int retval; - struct koneplus_roccat_report roccat_report; - - dev = dev->parent->parent; - koneplus = hid_get_drvdata(dev_get_drvdata(dev)); - usb_dev = interface_to_usbdev(to_usb_interface(dev)); - - retval = strict_strtoul(buf, 10, &profile); - if (retval) - return retval; - - if (profile > 4) - return -EINVAL; - - mutex_lock(&koneplus->koneplus_lock); - - retval = koneplus_set_actual_profile(usb_dev, profile); - if (retval) { - mutex_unlock(&koneplus->koneplus_lock); - return retval; - } - - koneplus_profile_activated(koneplus, profile); - - roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; - roccat_report.data1 = profile + 1; - roccat_report.data2 = 0; - roccat_report.profile = profile + 1; - roccat_report_event(koneplus->chrdev_minor, - (uint8_t const *)&roccat_report); - - mutex_unlock(&koneplus->koneplus_lock); - - return size; -} - -static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct koneplus_device *koneplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version); -} - -static struct device_attribute koneplus_attributes[] = { - __ATTR(actual_profile, 0660, - koneplus_sysfs_show_actual_profile, - koneplus_sysfs_set_actual_profile), - __ATTR(startup_profile, 0660, - koneplus_sysfs_show_actual_profile, - koneplus_sysfs_set_actual_profile), - __ATTR(firmware_version, 0440, - koneplus_sysfs_show_firmware_version, NULL), - __ATTR_NULL -}; - -static struct bin_attribute koneplus_bin_attributes[] = { - { - .attr = { .name = "sensor", .mode = 0660 }, - .size = sizeof(struct koneplus_sensor), - .read = koneplus_sysfs_read_sensor, - .write = koneplus_sysfs_write_sensor - }, - { - .attr = { .name = "tcu", .mode = 0220 }, - .size = sizeof(struct koneplus_tcu), - .write = koneplus_sysfs_write_tcu - }, - { - .attr = { .name = "tcu_image", .mode = 0440 }, - .size = sizeof(struct koneplus_tcu_image), - .read = koneplus_sysfs_read_tcu_image - }, - { - .attr = { .name = "profile_settings", .mode = 0220 }, - .size = sizeof(struct koneplus_profile_settings), - .write = koneplus_sysfs_write_profile_settings - }, - { - .attr = { .name = "profile1_settings", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_settings), - .read = koneplus_sysfs_read_profilex_settings, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2_settings", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_settings), - .read = koneplus_sysfs_read_profilex_settings, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3_settings", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_settings), - .read = koneplus_sysfs_read_profilex_settings, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4_settings", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_settings), - .read = koneplus_sysfs_read_profilex_settings, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5_settings", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_settings), - .read = koneplus_sysfs_read_profilex_settings, - .private = &profile_numbers[4] - }, - { - .attr = { .name = "profile_buttons", .mode = 0220 }, - .size = sizeof(struct koneplus_profile_buttons), - .write = koneplus_sysfs_write_profile_buttons - }, - { - .attr = { .name = "profile1_buttons", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_buttons), - .read = koneplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2_buttons", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_buttons), - .read = koneplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3_buttons", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_buttons), - .read = koneplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4_buttons", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_buttons), - .read = koneplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5_buttons", .mode = 0440 }, - .size = sizeof(struct koneplus_profile_buttons), - .read = koneplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[4] - }, - { - .attr = { .name = "macro", .mode = 0220 }, - .size = sizeof(struct koneplus_macro), - .write = koneplus_sysfs_write_macro - }, - { - .attr = { .name = "talk", .mode = 0220 }, - .size = sizeof(struct koneplus_talk), - .write = koneplus_sysfs_write_talk - }, - __ATTR_NULL -}; - -static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, - struct koneplus_device *koneplus) -{ - int retval, i; - static uint wait = 200; - - mutex_init(&koneplus->koneplus_lock); - - retval = koneplus_get_info(usb_dev, &koneplus->info); - if (retval) - return retval; - - for (i = 0; i < 5; ++i) { - msleep(wait); - retval = koneplus_get_profile_settings(usb_dev, - &koneplus->profile_settings[i], i); - if (retval) - return retval; - - msleep(wait); - retval = koneplus_get_profile_buttons(usb_dev, - &koneplus->profile_buttons[i], i); - if (retval) - return retval; - } - - msleep(wait); - retval = koneplus_get_actual_profile(usb_dev); - if (retval < 0) - return retval; - koneplus_profile_activated(koneplus, retval); - - return 0; -} - -static int koneplus_init_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct koneplus_device *koneplus; - int retval; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - - koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); - if (!koneplus) { - hid_err(hdev, "can't alloc device descriptor\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, koneplus); - - retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); - if (retval) { - hid_err(hdev, "couldn't init struct koneplus_device\n"); - goto exit_free; - } - - retval = roccat_connect(koneplus_class, hdev, - sizeof(struct koneplus_roccat_report)); - if (retval < 0) { - hid_err(hdev, "couldn't init char dev\n"); - } else { - koneplus->chrdev_minor = retval; - koneplus->roccat_claimed = 1; - } - } else { - hid_set_drvdata(hdev, NULL); - } - - return 0; -exit_free: - kfree(koneplus); - return retval; -} - -static void koneplus_remove_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct koneplus_device *koneplus; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - koneplus = hid_get_drvdata(hdev); - if (koneplus->roccat_claimed) - roccat_disconnect(koneplus->chrdev_minor); - kfree(koneplus); - } -} - -static int koneplus_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int retval; - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); - goto exit; - } - - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "hw start failed\n"); - goto exit; - } - - retval = koneplus_init_specials(hdev); - if (retval) { - hid_err(hdev, "couldn't install mouse\n"); - goto exit_stop; - } - - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void koneplus_remove(struct hid_device *hdev) -{ - koneplus_remove_specials(hdev); - hid_hw_stop(hdev); -} - -static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, - u8 const *data) -{ - struct koneplus_mouse_report_button const *button_report; - - switch (data[0]) { - case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: - button_report = (struct koneplus_mouse_report_button const *)data; - switch (button_report->type) { - case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: - koneplus_profile_activated(koneplus, button_report->data1 - 1); - break; - } - break; - } -} - -static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, - u8 const *data) -{ - struct koneplus_roccat_report roccat_report; - struct koneplus_mouse_report_button const *button_report; - - if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) - return; - - button_report = (struct koneplus_mouse_report_button const *)data; - - if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || - button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && - button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) - return; - - roccat_report.type = button_report->type; - roccat_report.data1 = button_report->data1; - roccat_report.data2 = button_report->data2; - roccat_report.profile = koneplus->actual_profile + 1; - roccat_report_event(koneplus->chrdev_minor, - (uint8_t const *)&roccat_report); -} - -static int koneplus_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *data, int size) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct koneplus_device *koneplus = hid_get_drvdata(hdev); - - if (intf->cur_altsetting->desc.bInterfaceProtocol - != USB_INTERFACE_PROTOCOL_MOUSE) - return 0; - - if (koneplus == NULL) - return 0; - - koneplus_keep_values_up_to_date(koneplus, data); - - if (koneplus->roccat_claimed) - koneplus_report_to_chrdev(koneplus, data); - - return 0; -} - -static const struct hid_device_id koneplus_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, koneplus_devices); - -static struct hid_driver koneplus_driver = { - .name = "koneplus", - .id_table = koneplus_devices, - .probe = koneplus_probe, - .remove = koneplus_remove, - .raw_event = koneplus_raw_event -}; - -static int __init koneplus_init(void) -{ - int retval; - - /* class name has to be same as driver name */ - koneplus_class = class_create(THIS_MODULE, "koneplus"); - if (IS_ERR(koneplus_class)) - return PTR_ERR(koneplus_class); - koneplus_class->dev_attrs = koneplus_attributes; - koneplus_class->dev_bin_attrs = koneplus_bin_attributes; - - retval = hid_register_driver(&koneplus_driver); - if (retval) - class_destroy(koneplus_class); - return retval; -} - -static void __exit koneplus_exit(void) -{ - hid_unregister_driver(&koneplus_driver); - class_destroy(koneplus_class); -} - -module_init(koneplus_init); -module_exit(koneplus_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-koneplus.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-koneplus.h deleted file mode 100644 index c03332a4..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-koneplus.h +++ /dev/null @@ -1,218 +0,0 @@ -#ifndef __HID_ROCCAT_KONEPLUS_H -#define __HID_ROCCAT_KONEPLUS_H - -/* - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/types.h> - -struct koneplus_talk { - uint8_t command; /* KONEPLUS_COMMAND_TALK */ - uint8_t size; /* always 0x10 */ - uint8_t data[14]; -} __packed; - -/* - * case 1: writes request 80 and reads value 1 - * - */ -struct koneplus_control { - uint8_t command; /* KONEPLUS_COMMAND_CONTROL */ - /* - * value is profile number in range 0-4 for requesting settings and buttons - * 1 if status ok for requesting status - */ - uint8_t value; - uint8_t request; -} __attribute__ ((__packed__)); - -enum koneplus_control_requests { - KONEPLUS_CONTROL_REQUEST_STATUS = 0x00, - KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, - KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90, -}; - -enum koneplus_control_values { - KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, - KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1, - KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, -}; - -struct koneplus_actual_profile { - uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */ - uint8_t size; /* always 3 */ - uint8_t actual_profile; /* Range 0-4! */ -} __attribute__ ((__packed__)); - -struct koneplus_profile_settings { - uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */ - uint8_t size; /* always 43 */ - uint8_t number; /* range 0-4 */ - uint8_t advanced_sensitivity; - uint8_t sensitivity_x; - uint8_t sensitivity_y; - uint8_t cpi_levels_enabled; - uint8_t cpi_levels_x[5]; - uint8_t cpi_startup_level; /* range 0-4 */ - uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */ - uint8_t unknown1; - uint8_t polling_rate; - uint8_t lights_enabled; - uint8_t light_effect_mode; - uint8_t color_flow_effect; - uint8_t light_effect_type; - uint8_t light_effect_speed; - uint8_t lights[16]; - uint16_t checksum; -} __attribute__ ((__packed__)); - -struct koneplus_profile_buttons { - uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */ - uint8_t size; /* always 77 */ - uint8_t number; /* range 0-4 */ - uint8_t data[72]; - uint16_t checksum; -} __attribute__ ((__packed__)); - -struct koneplus_macro { - uint8_t command; /* KONEPLUS_COMMAND_MACRO */ - uint16_t size; /* always 0x822 little endian */ - uint8_t profile; /* range 0-4 */ - uint8_t button; /* range 0-23 */ - uint8_t data[2075]; - uint16_t checksum; -} __attribute__ ((__packed__)); - -struct koneplus_info { - uint8_t command; /* KONEPLUS_COMMAND_INFO */ - uint8_t size; /* always 6 */ - uint8_t firmware_version; - uint8_t unknown[3]; -} __attribute__ ((__packed__)); - -struct koneplus_e { - uint8_t command; /* KONEPLUS_COMMAND_E */ - uint8_t size; /* always 3 */ - uint8_t unknown; /* TODO 1; 0 before firmware update */ -} __attribute__ ((__packed__)); - -struct koneplus_sensor { - uint8_t command; /* KONEPLUS_COMMAND_SENSOR */ - uint8_t size; /* always 6 */ - uint8_t data[4]; -} __attribute__ ((__packed__)); - -struct koneplus_firmware_write { - uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */ - uint8_t unknown[1025]; -} __attribute__ ((__packed__)); - -struct koneplus_firmware_write_control { - uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */ - /* - * value is 1 on success - * 3 means "not finished yet" - */ - uint8_t value; - uint8_t unknown; /* always 0x75 */ -} __attribute__ ((__packed__)); - -struct koneplus_tcu { - uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */ - uint8_t data[2]; -} __attribute__ ((__packed__)); - -struct koneplus_tcu_image { - uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */ - uint8_t data[1024]; - uint16_t checksum; -} __attribute__ ((__packed__)); - -enum koneplus_commands { - KONEPLUS_COMMAND_CONTROL = 0x4, - KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, - KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, - KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, - KONEPLUS_COMMAND_MACRO = 0x8, - KONEPLUS_COMMAND_INFO = 0x9, - KONEPLUS_COMMAND_TCU = 0xc, - KONEPLUS_COMMAND_E = 0xe, - KONEPLUS_COMMAND_SENSOR = 0xf, - KONEPLUS_COMMAND_TALK = 0x10, - KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b, - KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, -}; - -enum koneplus_mouse_report_numbers { - KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1, - KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, - KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3, -}; - -struct koneplus_mouse_report_button { - uint8_t report_number; /* always KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON */ - uint8_t zero1; - uint8_t type; - uint8_t data1; - uint8_t data2; - uint8_t zero2; - uint8_t unknown[2]; -} __attribute__ ((__packed__)); - -enum koneplus_mouse_report_button_types { - /* data1 = new profile range 1-5 */ - KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20, - - /* data1 = button number range 1-24; data2 = action */ - KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, - - /* data1 = button number range 1-24; data2 = action */ - KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, - - /* data1 = setting number range 1-5 */ - KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, - - /* data1 and data2 = range 0x1-0xb */ - KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, - - /* data1 = 22 = next track... - * data2 = action - */ - KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, - KONEPLUS_MOUSE_REPORT_TALK = 0xff, -}; - -enum koneplus_mouse_report_button_action { - KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0, - KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1, -}; - -struct koneplus_roccat_report { - uint8_t type; - uint8_t data1; - uint8_t data2; - uint8_t profile; -} __attribute__ ((__packed__)); - -struct koneplus_device { - int actual_profile; - - int roccat_claimed; - int chrdev_minor; - - struct mutex koneplus_lock; - - struct koneplus_info info; - struct koneplus_profile_settings profile_settings[5]; - struct koneplus_profile_buttons profile_buttons[5]; -}; - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-kovaplus.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-kovaplus.c deleted file mode 100644 index 112d9341..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-kovaplus.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * Roccat Kova[+] driver for Linux - * - * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Roccat Kova[+] is a bigger version of the Pyra with two more side buttons. - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hid-roccat.h> -#include "hid-ids.h" -#include "hid-roccat-common.h" -#include "hid-roccat-kovaplus.h" - -static uint profile_numbers[5] = {0, 1, 2, 3, 4}; - -static struct class *kovaplus_class; - -static uint kovaplus_convert_event_cpi(uint value) -{ - return (value == 7 ? 4 : (value == 4 ? 3 : value)); -} - -static void kovaplus_profile_activated(struct kovaplus_device *kovaplus, - uint new_profile_index) -{ - kovaplus->actual_profile = new_profile_index; - kovaplus->actual_cpi = kovaplus->profile_settings[new_profile_index].cpi_startup_level; - kovaplus->actual_x_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_x; - kovaplus->actual_y_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_y; -} - -static int kovaplus_send_control(struct usb_device *usb_dev, uint value, - enum kovaplus_control_requests request) -{ - int retval; - struct kovaplus_control control; - - if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || - request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && - value > 4) - return -EINVAL; - - control.command = KOVAPLUS_COMMAND_CONTROL; - control.value = value; - control.request = request; - - retval = roccat_common_send(usb_dev, KOVAPLUS_COMMAND_CONTROL, - &control, sizeof(struct kovaplus_control)); - - return retval; -} - -static int kovaplus_receive_control_status(struct usb_device *usb_dev) -{ - int retval; - struct kovaplus_control control; - - do { - retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_CONTROL, - &control, sizeof(struct kovaplus_control)); - - /* check if we get a completely wrong answer */ - if (retval) - return retval; - - if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK) - return 0; - - /* indicates that hardware needs some more time to complete action */ - if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) { - msleep(500); /* windows driver uses 1000 */ - continue; - } - - /* seems to be critical - replug necessary */ - if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) - return -EINVAL; - - hid_err(usb_dev, "roccat_common_receive_control_status: " - "unknown response value 0x%x\n", control.value); - return -EINVAL; - } while (1); -} - -static int kovaplus_send(struct usb_device *usb_dev, uint command, - void const *buf, uint size) -{ - int retval; - - retval = roccat_common_send(usb_dev, command, buf, size); - if (retval) - return retval; - - msleep(100); - - return kovaplus_receive_control_status(usb_dev); -} - -static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, - enum kovaplus_control_requests request) -{ - return kovaplus_send_control(usb_dev, number, request); -} - -static int kovaplus_get_info(struct usb_device *usb_dev, - struct kovaplus_info *buf) -{ - return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_INFO, - buf, sizeof(struct kovaplus_info)); -} - -static int kovaplus_get_profile_settings(struct usb_device *usb_dev, - struct kovaplus_profile_settings *buf, uint number) -{ - int retval; - - retval = kovaplus_select_profile(usb_dev, number, - KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); - if (retval) - return retval; - - return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, - buf, sizeof(struct kovaplus_profile_settings)); -} - -static int kovaplus_set_profile_settings(struct usb_device *usb_dev, - struct kovaplus_profile_settings const *settings) -{ - return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, - settings, sizeof(struct kovaplus_profile_settings)); -} - -static int kovaplus_get_profile_buttons(struct usb_device *usb_dev, - struct kovaplus_profile_buttons *buf, int number) -{ - int retval; - - retval = kovaplus_select_profile(usb_dev, number, - KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); - if (retval) - return retval; - - return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, - buf, sizeof(struct kovaplus_profile_buttons)); -} - -static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, - struct kovaplus_profile_buttons const *buttons) -{ - return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, - buttons, sizeof(struct kovaplus_profile_buttons)); -} - -/* retval is 0-4 on success, < 0 on error */ -static int kovaplus_get_actual_profile(struct usb_device *usb_dev) -{ - struct kovaplus_actual_profile buf; - int retval; - - retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, - &buf, sizeof(struct kovaplus_actual_profile)); - - return retval ? retval : buf.actual_profile; -} - -static int kovaplus_set_actual_profile(struct usb_device *usb_dev, - int new_profile) -{ - struct kovaplus_actual_profile buf; - - buf.command = KOVAPLUS_COMMAND_ACTUAL_PROFILE; - buf.size = sizeof(struct kovaplus_actual_profile); - buf.actual_profile = new_profile; - - return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, - &buf, sizeof(struct kovaplus_actual_profile)); -} - -static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct kovaplus_profile_settings)) - return 0; - - if (off + count > sizeof(struct kovaplus_profile_settings)) - count = sizeof(struct kovaplus_profile_settings) - off; - - mutex_lock(&kovaplus->kovaplus_lock); - memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off, - count); - mutex_unlock(&kovaplus->kovaplus_lock); - - return count; -} - -static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - int profile_index; - struct kovaplus_profile_settings *profile_settings; - - if (off != 0 || count != sizeof(struct kovaplus_profile_settings)) - return -EINVAL; - - profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index; - profile_settings = &kovaplus->profile_settings[profile_index]; - - mutex_lock(&kovaplus->kovaplus_lock); - difference = memcmp(buf, profile_settings, - sizeof(struct kovaplus_profile_settings)); - if (difference) { - retval = kovaplus_set_profile_settings(usb_dev, - (struct kovaplus_profile_settings const *)buf); - if (!retval) - memcpy(profile_settings, buf, - sizeof(struct kovaplus_profile_settings)); - } - mutex_unlock(&kovaplus->kovaplus_lock); - - if (retval) - return retval; - - return sizeof(struct kovaplus_profile_settings); -} - -static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct kovaplus_profile_buttons)) - return 0; - - if (off + count > sizeof(struct kovaplus_profile_buttons)) - count = sizeof(struct kovaplus_profile_buttons) - off; - - mutex_lock(&kovaplus->kovaplus_lock); - memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off, - count); - mutex_unlock(&kovaplus->kovaplus_lock); - - return count; -} - -static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - uint profile_index; - struct kovaplus_profile_buttons *profile_buttons; - - if (off != 0 || count != sizeof(struct kovaplus_profile_buttons)) - return -EINVAL; - - profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index; - profile_buttons = &kovaplus->profile_buttons[profile_index]; - - mutex_lock(&kovaplus->kovaplus_lock); - difference = memcmp(buf, profile_buttons, - sizeof(struct kovaplus_profile_buttons)); - if (difference) { - retval = kovaplus_set_profile_buttons(usb_dev, - (struct kovaplus_profile_buttons const *)buf); - if (!retval) - memcpy(profile_buttons, buf, - sizeof(struct kovaplus_profile_buttons)); - } - mutex_unlock(&kovaplus->kovaplus_lock); - - if (retval) - return retval; - - return sizeof(struct kovaplus_profile_buttons); -} - -static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kovaplus_device *kovaplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_profile); -} - -static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev, - struct device_attribute *attr, char const *buf, size_t size) -{ - struct kovaplus_device *kovaplus; - struct usb_device *usb_dev; - unsigned long profile; - int retval; - struct kovaplus_roccat_report roccat_report; - - dev = dev->parent->parent; - kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); - usb_dev = interface_to_usbdev(to_usb_interface(dev)); - - retval = strict_strtoul(buf, 10, &profile); - if (retval) - return retval; - - if (profile >= 5) - return -EINVAL; - - mutex_lock(&kovaplus->kovaplus_lock); - retval = kovaplus_set_actual_profile(usb_dev, profile); - if (retval) { - mutex_unlock(&kovaplus->kovaplus_lock); - return retval; - } - - kovaplus_profile_activated(kovaplus, profile); - - roccat_report.type = KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1; - roccat_report.profile = profile + 1; - roccat_report.button = 0; - roccat_report.data1 = profile + 1; - roccat_report.data2 = 0; - roccat_report_event(kovaplus->chrdev_minor, - (uint8_t const *)&roccat_report); - - mutex_unlock(&kovaplus->kovaplus_lock); - - return size; -} - -static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kovaplus_device *kovaplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi); -} - -static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kovaplus_device *kovaplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity); -} - -static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kovaplus_device *kovaplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity); -} - -static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kovaplus_device *kovaplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version); -} - -static struct device_attribute kovaplus_attributes[] = { - __ATTR(actual_cpi, 0440, - kovaplus_sysfs_show_actual_cpi, NULL), - __ATTR(firmware_version, 0440, - kovaplus_sysfs_show_firmware_version, NULL), - __ATTR(actual_profile, 0660, - kovaplus_sysfs_show_actual_profile, - kovaplus_sysfs_set_actual_profile), - __ATTR(actual_sensitivity_x, 0440, - kovaplus_sysfs_show_actual_sensitivity_x, NULL), - __ATTR(actual_sensitivity_y, 0440, - kovaplus_sysfs_show_actual_sensitivity_y, NULL), - __ATTR_NULL -}; - -static struct bin_attribute kovaplus_bin_attributes[] = { - { - .attr = { .name = "profile_settings", .mode = 0220 }, - .size = sizeof(struct kovaplus_profile_settings), - .write = kovaplus_sysfs_write_profile_settings - }, - { - .attr = { .name = "profile1_settings", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_settings), - .read = kovaplus_sysfs_read_profilex_settings, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2_settings", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_settings), - .read = kovaplus_sysfs_read_profilex_settings, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3_settings", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_settings), - .read = kovaplus_sysfs_read_profilex_settings, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4_settings", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_settings), - .read = kovaplus_sysfs_read_profilex_settings, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5_settings", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_settings), - .read = kovaplus_sysfs_read_profilex_settings, - .private = &profile_numbers[4] - }, - { - .attr = { .name = "profile_buttons", .mode = 0220 }, - .size = sizeof(struct kovaplus_profile_buttons), - .write = kovaplus_sysfs_write_profile_buttons - }, - { - .attr = { .name = "profile1_buttons", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_buttons), - .read = kovaplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2_buttons", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_buttons), - .read = kovaplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3_buttons", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_buttons), - .read = kovaplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4_buttons", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_buttons), - .read = kovaplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5_buttons", .mode = 0440 }, - .size = sizeof(struct kovaplus_profile_buttons), - .read = kovaplus_sysfs_read_profilex_buttons, - .private = &profile_numbers[4] - }, - __ATTR_NULL -}; - -static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev, - struct kovaplus_device *kovaplus) -{ - int retval, i; - static uint wait = 70; /* device will freeze with just 60 */ - - mutex_init(&kovaplus->kovaplus_lock); - - retval = kovaplus_get_info(usb_dev, &kovaplus->info); - if (retval) - return retval; - - for (i = 0; i < 5; ++i) { - msleep(wait); - retval = kovaplus_get_profile_settings(usb_dev, - &kovaplus->profile_settings[i], i); - if (retval) - return retval; - - msleep(wait); - retval = kovaplus_get_profile_buttons(usb_dev, - &kovaplus->profile_buttons[i], i); - if (retval) - return retval; - } - - msleep(wait); - retval = kovaplus_get_actual_profile(usb_dev); - if (retval < 0) - return retval; - kovaplus_profile_activated(kovaplus, retval); - - return 0; -} - -static int kovaplus_init_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct kovaplus_device *kovaplus; - int retval; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - - kovaplus = kzalloc(sizeof(*kovaplus), GFP_KERNEL); - if (!kovaplus) { - hid_err(hdev, "can't alloc device descriptor\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, kovaplus); - - retval = kovaplus_init_kovaplus_device_struct(usb_dev, kovaplus); - if (retval) { - hid_err(hdev, "couldn't init struct kovaplus_device\n"); - goto exit_free; - } - - retval = roccat_connect(kovaplus_class, hdev, - sizeof(struct kovaplus_roccat_report)); - if (retval < 0) { - hid_err(hdev, "couldn't init char dev\n"); - } else { - kovaplus->chrdev_minor = retval; - kovaplus->roccat_claimed = 1; - } - - } else { - hid_set_drvdata(hdev, NULL); - } - - return 0; -exit_free: - kfree(kovaplus); - return retval; -} - -static void kovaplus_remove_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct kovaplus_device *kovaplus; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - kovaplus = hid_get_drvdata(hdev); - if (kovaplus->roccat_claimed) - roccat_disconnect(kovaplus->chrdev_minor); - kfree(kovaplus); - } -} - -static int kovaplus_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int retval; - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); - goto exit; - } - - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "hw start failed\n"); - goto exit; - } - - retval = kovaplus_init_specials(hdev); - if (retval) { - hid_err(hdev, "couldn't install mouse\n"); - goto exit_stop; - } - - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void kovaplus_remove(struct hid_device *hdev) -{ - kovaplus_remove_specials(hdev); - hid_hw_stop(hdev); -} - -static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus, - u8 const *data) -{ - struct kovaplus_mouse_report_button const *button_report; - - if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON) - return; - - button_report = (struct kovaplus_mouse_report_button const *)data; - - switch (button_report->type) { - case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1: - kovaplus_profile_activated(kovaplus, button_report->data1 - 1); - break; - case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI: - kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1); - case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY: - kovaplus->actual_x_sensitivity = button_report->data1; - kovaplus->actual_y_sensitivity = button_report->data2; - } -} - -static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus, - u8 const *data) -{ - struct kovaplus_roccat_report roccat_report; - struct kovaplus_mouse_report_button const *button_report; - - if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON) - return; - - button_report = (struct kovaplus_mouse_report_button const *)data; - - if (button_report->type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2) - return; - - roccat_report.type = button_report->type; - roccat_report.profile = kovaplus->actual_profile + 1; - - if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO || - roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT || - roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || - roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) - roccat_report.button = button_report->data1; - else - roccat_report.button = 0; - - if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI) - roccat_report.data1 = kovaplus_convert_event_cpi(button_report->data1); - else - roccat_report.data1 = button_report->data1; - - roccat_report.data2 = button_report->data2; - - roccat_report_event(kovaplus->chrdev_minor, - (uint8_t const *)&roccat_report); -} - -static int kovaplus_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *data, int size) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct kovaplus_device *kovaplus = hid_get_drvdata(hdev); - - if (intf->cur_altsetting->desc.bInterfaceProtocol - != USB_INTERFACE_PROTOCOL_MOUSE) - return 0; - - if (kovaplus == NULL) - return 0; - - kovaplus_keep_values_up_to_date(kovaplus, data); - - if (kovaplus->roccat_claimed) - kovaplus_report_to_chrdev(kovaplus, data); - - return 0; -} - -static const struct hid_device_id kovaplus_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, kovaplus_devices); - -static struct hid_driver kovaplus_driver = { - .name = "kovaplus", - .id_table = kovaplus_devices, - .probe = kovaplus_probe, - .remove = kovaplus_remove, - .raw_event = kovaplus_raw_event -}; - -static int __init kovaplus_init(void) -{ - int retval; - - kovaplus_class = class_create(THIS_MODULE, "kovaplus"); - if (IS_ERR(kovaplus_class)) - return PTR_ERR(kovaplus_class); - kovaplus_class->dev_attrs = kovaplus_attributes; - kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes; - - retval = hid_register_driver(&kovaplus_driver); - if (retval) - class_destroy(kovaplus_class); - return retval; -} - -static void __exit kovaplus_exit(void) -{ - hid_unregister_driver(&kovaplus_driver); - class_destroy(kovaplus_class); -} - -module_init(kovaplus_init); -module_exit(kovaplus_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat Kova[+] driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-kovaplus.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-kovaplus.h deleted file mode 100644 index fb2aed44..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-kovaplus.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef __HID_ROCCAT_KOVAPLUS_H -#define __HID_ROCCAT_KOVAPLUS_H - -/* - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/types.h> - -struct kovaplus_control { - uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */ - uint8_t value; - uint8_t request; -} __packed; - -enum kovaplus_control_requests { - /* read after write; value = 1 */ - KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0, - /* write; value = profile number range 0-4 */ - KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, - /* write; value = profile number range 0-4 */ - KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20, -}; - -enum kovaplus_control_values { - KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */ - KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1, - KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */ -}; - -struct kovaplus_actual_profile { - uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */ - uint8_t size; /* always 3 */ - uint8_t actual_profile; /* Range 0-4! */ -} __packed; - -struct kovaplus_profile_settings { - uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_SETTINGS */ - uint8_t size; /* 16 */ - uint8_t profile_index; /* range 0-4 */ - uint8_t unknown1; - uint8_t sensitivity_x; /* range 1-10 */ - uint8_t sensitivity_y; /* range 1-10 */ - uint8_t cpi_levels_enabled; - uint8_t cpi_startup_level; /* range 1-4 */ - uint8_t data[8]; -} __packed; - -struct kovaplus_profile_buttons { - uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_BUTTONS */ - uint8_t size; /* 23 */ - uint8_t profile_index; /* range 0-4 */ - uint8_t data[20]; -} __packed; - -struct kovaplus_info { - uint8_t command; /* KOVAPLUS_COMMAND_INFO */ - uint8_t size; /* 6 */ - uint8_t firmware_version; - uint8_t unknown[3]; -} __packed; - -/* writes 1 on plugin */ -struct kovaplus_a { - uint8_t command; /* KOVAPLUS_COMMAND_A */ - uint8_t size; /* 3 */ - uint8_t unknown; -} __packed; - -enum kovaplus_commands { - KOVAPLUS_COMMAND_CONTROL = 0x4, - KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, - KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, - KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, - KOVAPLUS_COMMAND_INFO = 0x9, - KOVAPLUS_COMMAND_A = 0xa, -}; - -enum kovaplus_mouse_report_numbers { - KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1, - KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, - KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3, - KOVAPLUS_MOUSE_REPORT_NUMBER_KBD = 4, -}; - -struct kovaplus_mouse_report_button { - uint8_t report_number; /* KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON */ - uint8_t unknown1; - uint8_t type; - uint8_t data1; - uint8_t data2; -} __packed; - -enum kovaplus_mouse_report_button_types { - /* data1 = profile_number range 1-5; no release event */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1 = 0x20, - /* data1 = profile_number range 1-5; no release event */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2 = 0x30, - /* data1 = button_number range 1-18; data2 = action */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO = 0x40, - /* data1 = button_number range 1-18; data2 = action */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT = 0x50, - /* data1 = button_number range 1-18; data2 = action */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, - /* data1 = button_number range 1-18; data2 = action */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, - /* data1 = 1 = 400, 2 = 800, 4 = 1600, 7 = 3200; no release event */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, - /* data1 + data2 = sense range 1-10; no release event */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, - /* data1 = type as in profile_buttons; data2 = action */ - KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, -}; - -enum kovaplus_mouse_report_button_actions { - KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0, - KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1, -}; - -struct kovaplus_roccat_report { - uint8_t type; - uint8_t profile; - uint8_t button; - uint8_t data1; - uint8_t data2; -} __packed; - -struct kovaplus_device { - int actual_profile; - int actual_cpi; - int actual_x_sensitivity; - int actual_y_sensitivity; - int roccat_claimed; - int chrdev_minor; - struct mutex kovaplus_lock; - struct kovaplus_info info; - struct kovaplus_profile_settings profile_settings[5]; - struct kovaplus_profile_buttons profile_buttons[5]; -}; - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-pyra.c b/ANDROID_3.4.5/drivers/hid/hid-roccat-pyra.c deleted file mode 100644 index df05c1b1..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-pyra.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * Roccat Pyra driver for Linux - * - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Roccat Pyra is a mobile gamer mouse which comes in wired and wireless - * variant. Wireless variant is not tested. - * Userland tools can be found at http://sourceforge.net/projects/roccat - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hid-roccat.h> -#include "hid-ids.h" -#include "hid-roccat-common.h" -#include "hid-roccat-pyra.h" - -static uint profile_numbers[5] = {0, 1, 2, 3, 4}; - -/* pyra_class is used for creating sysfs attributes via roccat char device */ -static struct class *pyra_class; - -static void profile_activated(struct pyra_device *pyra, - unsigned int new_profile) -{ - pyra->actual_profile = new_profile; - pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; -} - -static int pyra_send_control(struct usb_device *usb_dev, int value, - enum pyra_control_requests request) -{ - struct pyra_control control; - - if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || - request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && - (value < 0 || value > 4)) - return -EINVAL; - - control.command = PYRA_COMMAND_CONTROL; - control.value = value; - control.request = request; - - return roccat_common_send(usb_dev, PYRA_COMMAND_CONTROL, - &control, sizeof(struct pyra_control)); -} - -static int pyra_receive_control_status(struct usb_device *usb_dev) -{ - int retval; - struct pyra_control control; - - do { - msleep(10); - retval = roccat_common_receive(usb_dev, PYRA_COMMAND_CONTROL, - &control, sizeof(struct pyra_control)); - - /* requested too early, try again */ - } while (retval == -EPROTO); - - if (!retval && control.command == PYRA_COMMAND_CONTROL && - control.request == PYRA_CONTROL_REQUEST_STATUS && - control.value == 1) - return 0; - else { - hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n", - control.request, control.value); - return retval ? retval : -EINVAL; - } -} - -static int pyra_get_profile_settings(struct usb_device *usb_dev, - struct pyra_profile_settings *buf, int number) -{ - int retval; - retval = pyra_send_control(usb_dev, number, - PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); - if (retval) - return retval; - return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, - buf, sizeof(struct pyra_profile_settings)); -} - -static int pyra_get_profile_buttons(struct usb_device *usb_dev, - struct pyra_profile_buttons *buf, int number) -{ - int retval; - retval = pyra_send_control(usb_dev, number, - PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); - if (retval) - return retval; - return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, - buf, sizeof(struct pyra_profile_buttons)); -} - -static int pyra_get_settings(struct usb_device *usb_dev, - struct pyra_settings *buf) -{ - return roccat_common_receive(usb_dev, PYRA_COMMAND_SETTINGS, - buf, sizeof(struct pyra_settings)); -} - -static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) -{ - return roccat_common_receive(usb_dev, PYRA_COMMAND_INFO, - buf, sizeof(struct pyra_info)); -} - -static int pyra_send(struct usb_device *usb_dev, uint command, - void const *buf, uint size) -{ - int retval; - retval = roccat_common_send(usb_dev, command, buf, size); - if (retval) - return retval; - return pyra_receive_control_status(usb_dev); -} - -static int pyra_set_profile_settings(struct usb_device *usb_dev, - struct pyra_profile_settings const *settings) -{ - return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, settings, - sizeof(struct pyra_profile_settings)); -} - -static int pyra_set_profile_buttons(struct usb_device *usb_dev, - struct pyra_profile_buttons const *buttons) -{ - return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, buttons, - sizeof(struct pyra_profile_buttons)); -} - -static int pyra_set_settings(struct usb_device *usb_dev, - struct pyra_settings const *settings) -{ - return pyra_send(usb_dev, PYRA_COMMAND_SETTINGS, settings, - sizeof(struct pyra_settings)); -} - -static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct pyra_profile_settings)) - return 0; - - if (off + count > sizeof(struct pyra_profile_settings)) - count = sizeof(struct pyra_profile_settings) - off; - - mutex_lock(&pyra->pyra_lock); - memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off, - count); - mutex_unlock(&pyra->pyra_lock); - - return count; -} - -static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct pyra_profile_buttons)) - return 0; - - if (off + count > sizeof(struct pyra_profile_buttons)) - count = sizeof(struct pyra_profile_buttons) - off; - - mutex_lock(&pyra->pyra_lock); - memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off, - count); - mutex_unlock(&pyra->pyra_lock); - - return count; -} - -static ssize_t pyra_sysfs_write_profile_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - int profile_number; - struct pyra_profile_settings *profile_settings; - - if (off != 0 || count != sizeof(struct pyra_profile_settings)) - return -EINVAL; - - profile_number = ((struct pyra_profile_settings const *)buf)->number; - profile_settings = &pyra->profile_settings[profile_number]; - - mutex_lock(&pyra->pyra_lock); - difference = memcmp(buf, profile_settings, - sizeof(struct pyra_profile_settings)); - if (difference) { - retval = pyra_set_profile_settings(usb_dev, - (struct pyra_profile_settings const *)buf); - if (!retval) - memcpy(profile_settings, buf, - sizeof(struct pyra_profile_settings)); - } - mutex_unlock(&pyra->pyra_lock); - - if (retval) - return retval; - - return sizeof(struct pyra_profile_settings); -} - -static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - int profile_number; - struct pyra_profile_buttons *profile_buttons; - - if (off != 0 || count != sizeof(struct pyra_profile_buttons)) - return -EINVAL; - - profile_number = ((struct pyra_profile_buttons const *)buf)->number; - profile_buttons = &pyra->profile_buttons[profile_number]; - - mutex_lock(&pyra->pyra_lock); - difference = memcmp(buf, profile_buttons, - sizeof(struct pyra_profile_buttons)); - if (difference) { - retval = pyra_set_profile_buttons(usb_dev, - (struct pyra_profile_buttons const *)buf); - if (!retval) - memcpy(profile_buttons, buf, - sizeof(struct pyra_profile_buttons)); - } - mutex_unlock(&pyra->pyra_lock); - - if (retval) - return retval; - - return sizeof(struct pyra_profile_buttons); -} - -static ssize_t pyra_sysfs_read_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); - - if (off >= sizeof(struct pyra_settings)) - return 0; - - if (off + count > sizeof(struct pyra_settings)) - count = sizeof(struct pyra_settings) - off; - - mutex_lock(&pyra->pyra_lock); - memcpy(buf, ((char const *)&pyra->settings) + off, count); - mutex_unlock(&pyra->pyra_lock); - - return count; -} - -static ssize_t pyra_sysfs_write_settings(struct file *fp, - struct kobject *kobj, struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval = 0; - int difference; - struct pyra_roccat_report roccat_report; - - if (off != 0 || count != sizeof(struct pyra_settings)) - return -EINVAL; - - mutex_lock(&pyra->pyra_lock); - difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings)); - if (difference) { - retval = pyra_set_settings(usb_dev, - (struct pyra_settings const *)buf); - if (retval) { - mutex_unlock(&pyra->pyra_lock); - return retval; - } - - memcpy(&pyra->settings, buf, - sizeof(struct pyra_settings)); - - profile_activated(pyra, pyra->settings.startup_profile); - - roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2; - roccat_report.value = pyra->settings.startup_profile + 1; - roccat_report.key = 0; - roccat_report_event(pyra->chrdev_minor, - (uint8_t const *)&roccat_report); - } - mutex_unlock(&pyra->pyra_lock); - return sizeof(struct pyra_settings); -} - - -static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pyra_device *pyra = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); -} - -static ssize_t pyra_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pyra_device *pyra = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile); -} - -static ssize_t pyra_sysfs_show_firmware_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pyra_device *pyra = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version); -} - -static ssize_t pyra_sysfs_show_startup_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pyra_device *pyra = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile); -} - -static struct device_attribute pyra_attributes[] = { - __ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL), - __ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL), - __ATTR(firmware_version, 0440, - pyra_sysfs_show_firmware_version, NULL), - __ATTR(startup_profile, 0440, - pyra_sysfs_show_startup_profile, NULL), - __ATTR_NULL -}; - -static struct bin_attribute pyra_bin_attributes[] = { - { - .attr = { .name = "profile_settings", .mode = 0220 }, - .size = sizeof(struct pyra_profile_settings), - .write = pyra_sysfs_write_profile_settings - }, - { - .attr = { .name = "profile1_settings", .mode = 0440 }, - .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profilex_settings, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2_settings", .mode = 0440 }, - .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profilex_settings, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3_settings", .mode = 0440 }, - .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profilex_settings, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4_settings", .mode = 0440 }, - .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profilex_settings, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5_settings", .mode = 0440 }, - .size = sizeof(struct pyra_profile_settings), - .read = pyra_sysfs_read_profilex_settings, - .private = &profile_numbers[4] - }, - { - .attr = { .name = "profile_buttons", .mode = 0220 }, - .size = sizeof(struct pyra_profile_buttons), - .write = pyra_sysfs_write_profile_buttons - }, - { - .attr = { .name = "profile1_buttons", .mode = 0440 }, - .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profilex_buttons, - .private = &profile_numbers[0] - }, - { - .attr = { .name = "profile2_buttons", .mode = 0440 }, - .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profilex_buttons, - .private = &profile_numbers[1] - }, - { - .attr = { .name = "profile3_buttons", .mode = 0440 }, - .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profilex_buttons, - .private = &profile_numbers[2] - }, - { - .attr = { .name = "profile4_buttons", .mode = 0440 }, - .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profilex_buttons, - .private = &profile_numbers[3] - }, - { - .attr = { .name = "profile5_buttons", .mode = 0440 }, - .size = sizeof(struct pyra_profile_buttons), - .read = pyra_sysfs_read_profilex_buttons, - .private = &profile_numbers[4] - }, - { - .attr = { .name = "settings", .mode = 0660 }, - .size = sizeof(struct pyra_settings), - .read = pyra_sysfs_read_settings, - .write = pyra_sysfs_write_settings - }, - __ATTR_NULL -}; - -static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, - struct pyra_device *pyra) -{ - struct pyra_info info; - int retval, i; - - mutex_init(&pyra->pyra_lock); - - retval = pyra_get_info(usb_dev, &info); - if (retval) - return retval; - - pyra->firmware_version = info.firmware_version; - - retval = pyra_get_settings(usb_dev, &pyra->settings); - if (retval) - return retval; - - for (i = 0; i < 5; ++i) { - retval = pyra_get_profile_settings(usb_dev, - &pyra->profile_settings[i], i); - if (retval) - return retval; - - retval = pyra_get_profile_buttons(usb_dev, - &pyra->profile_buttons[i], i); - if (retval) - return retval; - } - - profile_activated(pyra, pyra->settings.startup_profile); - - return 0; -} - -static int pyra_init_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct pyra_device *pyra; - int retval; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - - pyra = kzalloc(sizeof(*pyra), GFP_KERNEL); - if (!pyra) { - hid_err(hdev, "can't alloc device descriptor\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, pyra); - - retval = pyra_init_pyra_device_struct(usb_dev, pyra); - if (retval) { - hid_err(hdev, "couldn't init struct pyra_device\n"); - goto exit_free; - } - - retval = roccat_connect(pyra_class, hdev, - sizeof(struct pyra_roccat_report)); - if (retval < 0) { - hid_err(hdev, "couldn't init char dev\n"); - } else { - pyra->chrdev_minor = retval; - pyra->roccat_claimed = 1; - } - } else { - hid_set_drvdata(hdev, NULL); - } - - return 0; -exit_free: - kfree(pyra); - return retval; -} - -static void pyra_remove_specials(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct pyra_device *pyra; - - if (intf->cur_altsetting->desc.bInterfaceProtocol - == USB_INTERFACE_PROTOCOL_MOUSE) { - pyra = hid_get_drvdata(hdev); - if (pyra->roccat_claimed) - roccat_disconnect(pyra->chrdev_minor); - kfree(hid_get_drvdata(hdev)); - } -} - -static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int retval; - - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); - goto exit; - } - - retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (retval) { - hid_err(hdev, "hw start failed\n"); - goto exit; - } - - retval = pyra_init_specials(hdev); - if (retval) { - hid_err(hdev, "couldn't install mouse\n"); - goto exit_stop; - } - return 0; - -exit_stop: - hid_hw_stop(hdev); -exit: - return retval; -} - -static void pyra_remove(struct hid_device *hdev) -{ - pyra_remove_specials(hdev); - hid_hw_stop(hdev); -} - -static void pyra_keep_values_up_to_date(struct pyra_device *pyra, - u8 const *data) -{ - struct pyra_mouse_event_button const *button_event; - - switch (data[0]) { - case PYRA_MOUSE_REPORT_NUMBER_BUTTON: - button_event = (struct pyra_mouse_event_button const *)data; - switch (button_event->type) { - case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: - profile_activated(pyra, button_event->data1 - 1); - break; - case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: - pyra->actual_cpi = button_event->data1; - break; - } - break; - } -} - -static void pyra_report_to_chrdev(struct pyra_device const *pyra, - u8 const *data) -{ - struct pyra_roccat_report roccat_report; - struct pyra_mouse_event_button const *button_event; - - if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON) - return; - - button_event = (struct pyra_mouse_event_button const *)data; - - switch (button_event->type) { - case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: - case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: - roccat_report.type = button_event->type; - roccat_report.value = button_event->data1; - roccat_report.key = 0; - roccat_report_event(pyra->chrdev_minor, - (uint8_t const *)&roccat_report); - break; - case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: - case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: - case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH: - if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) { - roccat_report.type = button_event->type; - roccat_report.key = button_event->data1; - /* - * pyra reports profile numbers with range 1-5. - * Keeping this behaviour. - */ - roccat_report.value = pyra->actual_profile + 1; - roccat_report_event(pyra->chrdev_minor, - (uint8_t const *)&roccat_report); - } - break; - } -} - -static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *data, int size) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct pyra_device *pyra = hid_get_drvdata(hdev); - - if (intf->cur_altsetting->desc.bInterfaceProtocol - != USB_INTERFACE_PROTOCOL_MOUSE) - return 0; - - if (pyra == NULL) - return 0; - - pyra_keep_values_up_to_date(pyra, data); - - if (pyra->roccat_claimed) - pyra_report_to_chrdev(pyra, data); - - return 0; -} - -static const struct hid_device_id pyra_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, - USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, - USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, - { } -}; - -MODULE_DEVICE_TABLE(hid, pyra_devices); - -static struct hid_driver pyra_driver = { - .name = "pyra", - .id_table = pyra_devices, - .probe = pyra_probe, - .remove = pyra_remove, - .raw_event = pyra_raw_event -}; - -static int __init pyra_init(void) -{ - int retval; - - /* class name has to be same as driver name */ - pyra_class = class_create(THIS_MODULE, "pyra"); - if (IS_ERR(pyra_class)) - return PTR_ERR(pyra_class); - pyra_class->dev_attrs = pyra_attributes; - pyra_class->dev_bin_attrs = pyra_bin_attributes; - - retval = hid_register_driver(&pyra_driver); - if (retval) - class_destroy(pyra_class); - return retval; -} - -static void __exit pyra_exit(void) -{ - hid_unregister_driver(&pyra_driver); - class_destroy(pyra_class); -} - -module_init(pyra_init); -module_exit(pyra_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat Pyra driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat-pyra.h b/ANDROID_3.4.5/drivers/hid/hid-roccat-pyra.h deleted file mode 100644 index 0442d7fa..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat-pyra.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef __HID_ROCCAT_PYRA_H -#define __HID_ROCCAT_PYRA_H - -/* - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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/types.h> - -struct pyra_b { - uint8_t command; /* PYRA_COMMAND_B */ - uint8_t size; /* always 3 */ - uint8_t unknown; /* 1 */ -} __attribute__ ((__packed__)); - -struct pyra_control { - uint8_t command; /* PYRA_COMMAND_CONTROL */ - /* - * value is profile number for request_settings and request_buttons - * 1 if status ok for request_status - */ - uint8_t value; /* Range 0-4 */ - uint8_t request; -} __attribute__ ((__packed__)); - -enum pyra_control_requests { - PYRA_CONTROL_REQUEST_STATUS = 0x00, - PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, - PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20 -}; - -struct pyra_settings { - uint8_t command; /* PYRA_COMMAND_SETTINGS */ - uint8_t size; /* always 3 */ - uint8_t startup_profile; /* Range 0-4! */ -} __attribute__ ((__packed__)); - -struct pyra_profile_settings { - uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */ - uint8_t size; /* always 0xd */ - uint8_t number; /* Range 0-4 */ - uint8_t xysync; - uint8_t x_sensitivity; /* 0x1-0xa */ - uint8_t y_sensitivity; - uint8_t x_cpi; /* unused */ - uint8_t y_cpi; /* this value is for x and y */ - uint8_t lightswitch; /* 0 = off, 1 = on */ - uint8_t light_effect; - uint8_t handedness; - uint16_t checksum; /* byte sum */ -} __attribute__ ((__packed__)); - -struct pyra_profile_buttons { - uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */ - uint8_t size; /* always 0x13 */ - uint8_t number; /* Range 0-4 */ - uint8_t buttons[14]; - uint16_t checksum; /* byte sum */ -} __attribute__ ((__packed__)); - -struct pyra_info { - uint8_t command; /* PYRA_COMMAND_INFO */ - uint8_t size; /* always 6 */ - uint8_t firmware_version; - uint8_t unknown1; /* always 0 */ - uint8_t unknown2; /* always 1 */ - uint8_t unknown3; /* always 0 */ -} __attribute__ ((__packed__)); - -enum pyra_commands { - PYRA_COMMAND_CONTROL = 0x4, - PYRA_COMMAND_SETTINGS = 0x5, - PYRA_COMMAND_PROFILE_SETTINGS = 0x6, - PYRA_COMMAND_PROFILE_BUTTONS = 0x7, - PYRA_COMMAND_INFO = 0x9, - PYRA_COMMAND_B = 0xb -}; - -enum pyra_mouse_report_numbers { - PYRA_MOUSE_REPORT_NUMBER_HID = 1, - PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2, - PYRA_MOUSE_REPORT_NUMBER_BUTTON = 3, -}; - -struct pyra_mouse_event_button { - uint8_t report_number; /* always 3 */ - uint8_t unknown; /* always 0 */ - uint8_t type; - uint8_t data1; - uint8_t data2; -} __attribute__ ((__packed__)); - -struct pyra_mouse_event_audio { - uint8_t report_number; /* always 2 */ - uint8_t type; - uint8_t unused; /* always 0 */ -} __attribute__ ((__packed__)); - -/* hid audio controls */ -enum pyra_mouse_event_audio_types { - PYRA_MOUSE_EVENT_AUDIO_TYPE_MUTE = 0xe2, - PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_UP = 0xe9, - PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_DOWN = 0xea, -}; - -enum pyra_mouse_event_button_types { - /* - * Mouse sends tilt events on report_number 1 and 3 - * Tilt events are sent repeatedly with 0.94s between first and second - * event and 0.22s on subsequent - */ - PYRA_MOUSE_EVENT_BUTTON_TYPE_TILT = 0x10, - - /* - * These are sent sequentially - * data1 contains new profile number in range 1-5 - */ - PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_1 = 0x20, - PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2 = 0x30, - - /* - * data1 = button_number (rmp index) - * data2 = pressed/released - */ - PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO = 0x40, - PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT = 0x50, - - /* - * data1 = button_number (rmp index) - */ - PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH = 0x60, - - /* data1 = new cpi */ - PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI = 0xb0, - - /* data1 and data2 = new sensitivity */ - PYRA_MOUSE_EVENT_BUTTON_TYPE_SENSITIVITY = 0xc0, - - PYRA_MOUSE_EVENT_BUTTON_TYPE_MULTIMEDIA = 0xf0, -}; - -enum { - PYRA_MOUSE_EVENT_BUTTON_PRESS = 0, - PYRA_MOUSE_EVENT_BUTTON_RELEASE = 1, -}; - -struct pyra_roccat_report { - uint8_t type; - uint8_t value; - uint8_t key; -} __attribute__ ((__packed__)); - -struct pyra_device { - int actual_profile; - int actual_cpi; - int firmware_version; - int roccat_claimed; - int chrdev_minor; - struct mutex pyra_lock; - struct pyra_settings settings; - struct pyra_profile_settings profile_settings[5]; - struct pyra_profile_buttons profile_buttons[5]; -}; - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-roccat.c b/ANDROID_3.4.5/drivers/hid/hid-roccat.c deleted file mode 100644 index b685b04d..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-roccat.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Roccat driver for Linux - * - * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> - */ - -/* - * 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. - */ - -/* - * Module roccat is a char device used to report special events of roccat - * hardware to userland. These events include requests for on-screen-display of - * profile or dpi settings or requests for execution of macro sequences that are - * not stored in device. The information in these events depends on hid device - * implementation and contains data that is not available in a single hid event - * or else hidraw could have been used. - * It is inspired by hidraw, but uses only one circular buffer for all readers. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/cdev.h> -#include <linux/poll.h> -#include <linux/sched.h> -#include <linux/hid-roccat.h> -#include <linux/module.h> - -#define ROCCAT_FIRST_MINOR 0 -#define ROCCAT_MAX_DEVICES 8 - -/* should be a power of 2 for performance reason */ -#define ROCCAT_CBUF_SIZE 16 - -struct roccat_report { - uint8_t *value; -}; - -struct roccat_device { - unsigned int minor; - int report_size; - int open; - int exist; - wait_queue_head_t wait; - struct device *dev; - struct hid_device *hid; - struct list_head readers; - /* protects modifications of readers list */ - struct mutex readers_lock; - - /* - * circular_buffer has one writer and multiple readers with their own - * read pointers - */ - struct roccat_report cbuf[ROCCAT_CBUF_SIZE]; - int cbuf_end; - struct mutex cbuf_lock; -}; - -struct roccat_reader { - struct list_head node; - struct roccat_device *device; - int cbuf_start; -}; - -static int roccat_major; -static struct cdev roccat_cdev; - -static struct roccat_device *devices[ROCCAT_MAX_DEVICES]; -/* protects modifications of devices array */ -static DEFINE_MUTEX(devices_lock); - -static ssize_t roccat_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct roccat_reader *reader = file->private_data; - struct roccat_device *device = reader->device; - struct roccat_report *report; - ssize_t retval = 0, len; - DECLARE_WAITQUEUE(wait, current); - - mutex_lock(&device->cbuf_lock); - - /* no data? */ - if (reader->cbuf_start == device->cbuf_end) { - add_wait_queue(&device->wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* wait for data */ - while (reader->cbuf_start == device->cbuf_end) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - if (!device->exist) { - retval = -EIO; - break; - } - - mutex_unlock(&device->cbuf_lock); - schedule(); - mutex_lock(&device->cbuf_lock); - set_current_state(TASK_INTERRUPTIBLE); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&device->wait, &wait); - } - - /* here we either have data or a reason to return if retval is set */ - if (retval) - goto exit_unlock; - - report = &device->cbuf[reader->cbuf_start]; - /* - * If report is larger than requested amount of data, rest of report - * is lost! - */ - len = device->report_size > count ? count : device->report_size; - - if (copy_to_user(buffer, report->value, len)) { - retval = -EFAULT; - goto exit_unlock; - } - retval += len; - reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; - -exit_unlock: - mutex_unlock(&device->cbuf_lock); - return retval; -} - -static unsigned int roccat_poll(struct file *file, poll_table *wait) -{ - struct roccat_reader *reader = file->private_data; - poll_wait(file, &reader->device->wait, wait); - if (reader->cbuf_start != reader->device->cbuf_end) - return POLLIN | POLLRDNORM; - if (!reader->device->exist) - return POLLERR | POLLHUP; - return 0; -} - -static int roccat_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct roccat_reader *reader; - struct roccat_device *device; - int error = 0; - - reader = kzalloc(sizeof(struct roccat_reader), GFP_KERNEL); - if (!reader) - return -ENOMEM; - - mutex_lock(&devices_lock); - - device = devices[minor]; - - if (!device) { - pr_emerg("roccat device with minor %d doesn't exist\n", minor); - error = -ENODEV; - goto exit_err_devices; - } - - mutex_lock(&device->readers_lock); - - if (!device->open++) { - /* power on device on adding first reader */ - error = hid_hw_power(device->hid, PM_HINT_FULLON); - if (error < 0) { - --device->open; - goto exit_err_readers; - } - - error = hid_hw_open(device->hid); - if (error < 0) { - hid_hw_power(device->hid, PM_HINT_NORMAL); - --device->open; - goto exit_err_readers; - } - } - - reader->device = device; - /* new reader doesn't get old events */ - reader->cbuf_start = device->cbuf_end; - - list_add_tail(&reader->node, &device->readers); - file->private_data = reader; - -exit_err_readers: - mutex_unlock(&device->readers_lock); -exit_err_devices: - mutex_unlock(&devices_lock); - if (error) - kfree(reader); - return error; -} - -static int roccat_release(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct roccat_reader *reader = file->private_data; - struct roccat_device *device; - - mutex_lock(&devices_lock); - - device = devices[minor]; - if (!device) { - mutex_unlock(&devices_lock); - pr_emerg("roccat device with minor %d doesn't exist\n", minor); - return -ENODEV; - } - - mutex_lock(&device->readers_lock); - list_del(&reader->node); - mutex_unlock(&device->readers_lock); - kfree(reader); - - if (!--device->open) { - /* removing last reader */ - if (device->exist) { - hid_hw_power(device->hid, PM_HINT_NORMAL); - hid_hw_close(device->hid); - } else { - kfree(device); - } - } - - mutex_unlock(&devices_lock); - - return 0; -} - -/* - * roccat_report_event() - output data to readers - * @minor: minor device number returned by roccat_connect() - * @data: pointer to data - * @len: size of data - * - * Return value is zero on success, a negative error code on failure. - * - * This is called from interrupt handler. - */ -int roccat_report_event(int minor, u8 const *data) -{ - struct roccat_device *device; - struct roccat_reader *reader; - struct roccat_report *report; - uint8_t *new_value; - - device = devices[minor]; - - new_value = kmemdup(data, device->report_size, GFP_ATOMIC); - if (!new_value) - return -ENOMEM; - - report = &device->cbuf[device->cbuf_end]; - - /* passing NULL is safe */ - kfree(report->value); - - report->value = new_value; - device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; - - list_for_each_entry(reader, &device->readers, node) { - /* - * As we already inserted one element, the buffer can't be - * empty. If start and end are equal, buffer is full and we - * increase start, so that slow reader misses one event, but - * gets the newer ones in the right order. - */ - if (reader->cbuf_start == device->cbuf_end) - reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; - } - - wake_up_interruptible(&device->wait); - return 0; -} -EXPORT_SYMBOL_GPL(roccat_report_event); - -/* - * roccat_connect() - create a char device for special event output - * @class: the class thats used to create the device. Meant to hold device - * specific sysfs attributes. - * @hid: the hid device the char device should be connected to. - * - * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on - * success, a negative error code on failure. - */ -int roccat_connect(struct class *klass, struct hid_device *hid, int report_size) -{ - unsigned int minor; - struct roccat_device *device; - int temp; - - device = kzalloc(sizeof(struct roccat_device), GFP_KERNEL); - if (!device) - return -ENOMEM; - - mutex_lock(&devices_lock); - - for (minor = 0; minor < ROCCAT_MAX_DEVICES; ++minor) { - if (devices[minor]) - continue; - break; - } - - if (minor < ROCCAT_MAX_DEVICES) { - devices[minor] = device; - } else { - mutex_unlock(&devices_lock); - kfree(device); - return -EINVAL; - } - - device->dev = device_create(klass, &hid->dev, - MKDEV(roccat_major, minor), NULL, - "%s%s%d", "roccat", hid->driver->name, minor); - - if (IS_ERR(device->dev)) { - devices[minor] = NULL; - mutex_unlock(&devices_lock); - temp = PTR_ERR(device->dev); - kfree(device); - return temp; - } - - mutex_unlock(&devices_lock); - - init_waitqueue_head(&device->wait); - INIT_LIST_HEAD(&device->readers); - mutex_init(&device->readers_lock); - mutex_init(&device->cbuf_lock); - device->minor = minor; - device->hid = hid; - device->exist = 1; - device->cbuf_end = 0; - device->report_size = report_size; - - return minor; -} -EXPORT_SYMBOL_GPL(roccat_connect); - -/* roccat_disconnect() - remove char device from hid device - * @minor: the minor device number returned by roccat_connect() - */ -void roccat_disconnect(int minor) -{ - struct roccat_device *device; - - mutex_lock(&devices_lock); - device = devices[minor]; - mutex_unlock(&devices_lock); - - device->exist = 0; /* TODO exist maybe not needed */ - - device_destroy(device->dev->class, MKDEV(roccat_major, minor)); - - mutex_lock(&devices_lock); - devices[minor] = NULL; - mutex_unlock(&devices_lock); - - if (device->open) { - hid_hw_close(device->hid); - wake_up_interruptible(&device->wait); - } else { - kfree(device); - } -} -EXPORT_SYMBOL_GPL(roccat_disconnect); - -static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct inode *inode = file->f_path.dentry->d_inode; - struct roccat_device *device; - unsigned int minor = iminor(inode); - long retval = 0; - - mutex_lock(&devices_lock); - - device = devices[minor]; - if (!device) { - retval = -ENODEV; - goto out; - } - - switch (cmd) { - case ROCCATIOCGREPSIZE: - if (put_user(device->report_size, (int __user *)arg)) - retval = -EFAULT; - break; - default: - retval = -ENOTTY; - } -out: - mutex_unlock(&devices_lock); - return retval; -} - -static const struct file_operations roccat_ops = { - .owner = THIS_MODULE, - .read = roccat_read, - .poll = roccat_poll, - .open = roccat_open, - .release = roccat_release, - .llseek = noop_llseek, - .unlocked_ioctl = roccat_ioctl, -}; - -static int __init roccat_init(void) -{ - int retval; - dev_t dev_id; - - retval = alloc_chrdev_region(&dev_id, ROCCAT_FIRST_MINOR, - ROCCAT_MAX_DEVICES, "roccat"); - - roccat_major = MAJOR(dev_id); - - if (retval < 0) { - pr_warn("can't get major number\n"); - return retval; - } - - cdev_init(&roccat_cdev, &roccat_ops); - cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES); - - return 0; -} - -static void __exit roccat_exit(void) -{ - dev_t dev_id = MKDEV(roccat_major, 0); - - cdev_del(&roccat_cdev); - unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); -} - -module_init(roccat_init); -module_exit(roccat_exit); - -MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat char device"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-saitek.c b/ANDROID_3.4.5/drivers/hid/hid-saitek.c deleted file mode 100644 index 45aea77b..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-saitek.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * HID driver for Saitek devices, currently only the PS1000 (USB gamepad). - * Fixes the HID report descriptor by removing a non-existent axis and - * clearing the constant bit on the input reports for buttons and d-pad. - * (This module is based on "hid-ortek".) - * - * Copyright (c) 2012 Andreas Hübner - */ - -/* - * 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 <linux/kernel.h> - -#include "hid-ids.h" - -static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize == 137 && rdesc[20] == 0x09 && rdesc[21] == 0x33 - && rdesc[94] == 0x81 && rdesc[95] == 0x03 - && rdesc[110] == 0x81 && rdesc[111] == 0x03) { - - hid_info(hdev, "Fixing up Saitek PS1000 report descriptor\n"); - - /* convert spurious axis to a "noop" Logical Minimum (0) */ - rdesc[20] = 0x15; - rdesc[21] = 0x00; - - /* clear constant bit on buttons and d-pad */ - rdesc[95] = 0x02; - rdesc[111] = 0x02; - - } - return rdesc; -} - -static const struct hid_device_id saitek_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000)}, - { } -}; - -MODULE_DEVICE_TABLE(hid, saitek_devices); - -static struct hid_driver saitek_driver = { - .name = "saitek", - .id_table = saitek_devices, - .report_fixup = saitek_report_fixup -}; - -static int __init saitek_init(void) -{ - return hid_register_driver(&saitek_driver); -} - -static void __exit saitek_exit(void) -{ - hid_unregister_driver(&saitek_driver); -} - -module_init(saitek_init); -module_exit(saitek_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-samsung.c b/ANDROID_3.4.5/drivers/hid/hid-samsung.c deleted file mode 100644 index 3c1fd8af..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-samsung.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * HID driver for some samsung "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - * Copyright (c) 2010 Don Prince <dhprince.devel@yahoo.co.uk> - * - * - * This driver supports several HID devices: - * - * [0419:0001] Samsung IrDA remote controller (reports as Cypress USB Mouse). - * various hid report fixups for different variants. - * - * [0419:0600] Creative Desktop Wireless 6000 keyboard/mouse combo - * several key mappings used from the consumer usage page - * deviate from the USB HUT 1.12 standard. - * - */ - -/* - * 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/usb.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -/* - * There are several variants for 0419:0001: - * - * 1. 184 byte report descriptor - * Vendor specific report #4 has a size of 48 bit, - * and therefore is not accepted when inspecting the descriptors. - * As a workaround we reinterpret the report as: - * Variable type, count 6, size 8 bit, log. maximum 255 - * The burden to reconstruct the data is moved into user space. - * - * 2. 203 byte report descriptor - * Report #4 has an array field with logical range 0..18 instead of 1..15. - * - * 3. 135 byte report descriptor - * Report #4 has an array field with logical range 0..17 instead of 1..14. - * - * 4. 171 byte report descriptor - * Report #3 has an array field with logical range 0..1 instead of 1..3. - */ -static inline void samsung_irda_dev_trace(struct hid_device *hdev, - unsigned int rsize) -{ - hid_info(hdev, "fixing up Samsung IrDA %d byte report descriptor\n", - rsize); -} - -static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && - rdesc[177] == 0x75 && rdesc[178] == 0x30 && - rdesc[179] == 0x95 && rdesc[180] == 0x01 && - rdesc[182] == 0x40) { - samsung_irda_dev_trace(hdev, 184); - rdesc[176] = 0xff; - rdesc[178] = 0x08; - rdesc[180] = 0x06; - rdesc[182] = 0x42; - } else - if (*rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && - rdesc[194] == 0x25 && rdesc[195] == 0x12) { - samsung_irda_dev_trace(hdev, 203); - rdesc[193] = 0x1; - rdesc[195] = 0xf; - } else - if (*rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && - rdesc[126] == 0x25 && rdesc[127] == 0x11) { - samsung_irda_dev_trace(hdev, 135); - rdesc[125] = 0x1; - rdesc[127] = 0xe; - } else - if (*rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && - rdesc[162] == 0x25 && rdesc[163] == 0x01) { - samsung_irda_dev_trace(hdev, 171); - rdesc[161] = 0x1; - rdesc[163] = 0x3; - } - return rdesc; -} - -#define samsung_kbd_mouse_map_key_clear(c) \ - hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) - -static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev, - struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - - if (1 != ifnum || HID_UP_CONSUMER != (usage->hid & HID_USAGE_PAGE)) - return 0; - - dbg_hid("samsung wireless keyboard/mouse input mapping event [0x%x]\n", - usage->hid & HID_USAGE); - - switch (usage->hid & HID_USAGE) { - /* report 2 */ - case 0x183: samsung_kbd_mouse_map_key_clear(KEY_MEDIA); break; - case 0x195: samsung_kbd_mouse_map_key_clear(KEY_EMAIL); break; - case 0x196: samsung_kbd_mouse_map_key_clear(KEY_CALC); break; - case 0x197: samsung_kbd_mouse_map_key_clear(KEY_COMPUTER); break; - case 0x22b: samsung_kbd_mouse_map_key_clear(KEY_SEARCH); break; - case 0x22c: samsung_kbd_mouse_map_key_clear(KEY_WWW); break; - case 0x22d: samsung_kbd_mouse_map_key_clear(KEY_BACK); break; - case 0x22e: samsung_kbd_mouse_map_key_clear(KEY_FORWARD); break; - case 0x22f: samsung_kbd_mouse_map_key_clear(KEY_FAVORITES); break; - case 0x230: samsung_kbd_mouse_map_key_clear(KEY_REFRESH); break; - case 0x231: samsung_kbd_mouse_map_key_clear(KEY_STOP); break; - default: - return 0; - } - - return 1; -} - -static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) - rdesc = samsung_irda_report_fixup(hdev, rdesc, rsize); - return rdesc; -} - -static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - int ret = 0; - - if (USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE == hdev->product) - ret = samsung_kbd_mouse_input_mapping(hdev, - hi, field, usage, bit, max); - - return ret; -} - -static int samsung_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int ret; - unsigned int cmask = HID_CONNECT_DEFAULT; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) { - if (hdev->rsize == 184) { - /* disable hidinput, force hiddev */ - cmask = (cmask & ~HID_CONNECT_HIDINPUT) | - HID_CONNECT_HIDDEV_FORCE; - } - } - - ret = hid_hw_start(hdev, cmask); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - return ret; -} - -static const struct hid_device_id samsung_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { } -}; -MODULE_DEVICE_TABLE(hid, samsung_devices); - -static struct hid_driver samsung_driver = { - .name = "samsung", - .id_table = samsung_devices, - .report_fixup = samsung_report_fixup, - .input_mapping = samsung_input_mapping, - .probe = samsung_probe, -}; - -static int __init samsung_init(void) -{ - return hid_register_driver(&samsung_driver); -} - -static void __exit samsung_exit(void) -{ - hid_unregister_driver(&samsung_driver); -} - -module_init(samsung_init); -module_exit(samsung_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-sjoy.c b/ANDROID_3.4.5/drivers/hid/hid-sjoy.c deleted file mode 100644 index 42257acf..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-sjoy.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Force feedback support for SmartJoy PLUS PS2->USB adapter - * - * Copyright (c) 2009 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> - * - * Based of hid-pl.c and hid-gaff.c - * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com> - * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* #define DEBUG */ - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/hid.h> -#include <linux/module.h> -#include "hid-ids.h" - -#ifdef CONFIG_SMARTJOYPLUS_FF -#include "usbhid/usbhid.h" - -struct sjoyff_device { - struct hid_report *report; -}; - -static int hid_sjoyff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct sjoyff_device *sjoyff = data; - u32 left, right; - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right); - - left = left * 0xff / 0xffff; - right = (right != 0); /* on/off only */ - - sjoyff->report->field[0]->value[1] = right; - sjoyff->report->field[0]->value[2] = left; - dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right); - usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); - - return 0; -} - -static int sjoyff_init(struct hid_device *hid) -{ - struct sjoyff_device *sjoyff; - struct hid_report *report; - struct hid_input *hidinput; - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct list_head *report_ptr = report_list; - struct input_dev *dev; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output reports found\n"); - return -ENODEV; - } - - list_for_each_entry(hidinput, &hid->inputs, list) { - report_ptr = report_ptr->next; - - if (report_ptr == report_list) { - hid_err(hid, "required output report is missing\n"); - return -ENODEV; - } - - report = list_entry(report_ptr, struct hid_report, list); - if (report->maxfield < 1) { - hid_err(hid, "no fields in the report\n"); - return -ENODEV; - } - - if (report->field[0]->report_count < 3) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } - - sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL); - if (!sjoyff) - return -ENOMEM; - - dev = hidinput->input; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play); - if (error) { - kfree(sjoyff); - return error; - } - - sjoyff->report = report; - sjoyff->report->field[0]->value[0] = 0x01; - sjoyff->report->field[0]->value[1] = 0x00; - sjoyff->report->field[0]->value[2] = 0x00; - usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); - } - - hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); - - return 0; -} -#else -static inline int sjoyff_init(struct hid_device *hid) -{ - return 0; -} -#endif - -static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - hdev->quirks |= id->driver_data; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - sjoyff_init(hdev); - - return 0; -err: - return ret; -} - -static const struct hid_device_id sjoy_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO), - .driver_data = HID_QUIRK_NOGET }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO), - .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET | - HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO), - .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET | - HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD), - .driver_data = HID_QUIRK_MULTI_INPUT | - HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { } -}; -MODULE_DEVICE_TABLE(hid, sjoy_devices); - -static struct hid_driver sjoy_driver = { - .name = "smartjoyplus", - .id_table = sjoy_devices, - .probe = sjoy_probe, -}; - -static int __init sjoy_init(void) -{ - return hid_register_driver(&sjoy_driver); -} - -static void __exit sjoy_exit(void) -{ - hid_unregister_driver(&sjoy_driver); -} - -module_init(sjoy_init); -module_exit(sjoy_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jussi Kivilinna"); - diff --git a/ANDROID_3.4.5/drivers/hid/hid-sony.c b/ANDROID_3.4.5/drivers/hid/hid-sony.c deleted file mode 100644 index 5cd25bd9..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-sony.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * HID driver for some sony "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - * Copyright (c) 2006-2008 Jiri Kosina - */ - -/* - * 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 <linux/slab.h> -#include <linux/usb.h> - -#include "hid-ids.h" - -#define VAIO_RDESC_CONSTANT (1 << 0) -#define SIXAXIS_CONTROLLER_USB (1 << 1) -#define SIXAXIS_CONTROLLER_BT (1 << 2) - -static const u8 sixaxis_rdesc_fixup[] = { - 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, - 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, - 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02 -}; - -struct sony_sc { - unsigned long quirks; -}; - -/* Sony Vaio VGX has wrongly mouse pointer declared as constant */ -static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - struct sony_sc *sc = hid_get_drvdata(hdev); - - if ((sc->quirks & VAIO_RDESC_CONSTANT) && - *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { - hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n"); - rdesc[55] = 0x06; - } - - /* The HID descriptor exposed over BT has a trailing zero byte */ - if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) || - ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) && - rdesc[83] == 0x75) { - hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n"); - memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup, - sizeof(sixaxis_rdesc_fixup)); - } - return rdesc; -} - -static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, - __u8 *rd, int size) -{ - struct sony_sc *sc = hid_get_drvdata(hdev); - - /* Sixaxis HID report has acclerometers/gyro with MSByte first, this - * has to be BYTE_SWAPPED before passing up to joystick interface - */ - if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) && - rd[0] == 0x01 && size == 49) { - swap(rd[41], rd[42]); - swap(rd[43], rd[44]); - swap(rd[45], rd[46]); - swap(rd[47], rd[48]); - } - - return 0; -} - -/* - * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP - * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() - * so we need to override that forcing HID Output Reports on the Control EP. - * - * There is also another issue about HID Output Reports via USB, the Sixaxis - * does not want the report_id as part of the data packet, so we have to - * discard buf[0] when sending the actual control message, even for numbered - * reports, humpf! - */ -static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf, - size_t count, unsigned char report_type) -{ - struct usb_interface *intf = to_usb_interface(hid->dev.parent); - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface = intf->cur_altsetting; - int report_id = buf[0]; - int ret; - - if (report_type == HID_OUTPUT_REPORT) { - /* Don't send the Report ID */ - buf++; - count--; - } - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_REPORT, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | report_id, - interface->desc.bInterfaceNumber, buf, count, - USB_CTRL_SET_TIMEOUT); - - /* Count also the Report ID, in case of an Output report. */ - if (ret > 0 && report_type == HID_OUTPUT_REPORT) - ret++; - - return ret; -} - -/* - * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller - * to "operational". Without this, the ps3 controller will not report any - * events. - */ -static int sixaxis_set_operational_usb(struct hid_device *hdev) -{ - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *dev = interface_to_usbdev(intf); - __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - int ret; - char *buf = kmalloc(18, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - HID_REQ_GET_REPORT, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, - (3 << 8) | 0xf2, ifnum, buf, 17, - USB_CTRL_GET_TIMEOUT); - if (ret < 0) - hid_err(hdev, "can't set operational mode\n"); - - kfree(buf); - - return ret; -} - -static int sixaxis_set_operational_bt(struct hid_device *hdev) -{ - unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; - return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); -} - -static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - unsigned long quirks = id->driver_data; - struct sony_sc *sc; - - sc = kzalloc(sizeof(*sc), GFP_KERNEL); - if (sc == NULL) { - hid_err(hdev, "can't alloc sony descriptor\n"); - return -ENOMEM; - } - - sc->quirks = quirks; - hid_set_drvdata(hdev, sc); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | - HID_CONNECT_HIDDEV_FORCE); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - if (sc->quirks & SIXAXIS_CONTROLLER_USB) { - hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; - ret = sixaxis_set_operational_usb(hdev); - } - else if (sc->quirks & SIXAXIS_CONTROLLER_BT) - ret = sixaxis_set_operational_bt(hdev); - else - ret = 0; - - if (ret < 0) - goto err_stop; - - return 0; -err_stop: - hid_hw_stop(hdev); -err_free: - kfree(sc); - return ret; -} - -static void sony_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); -} - -static const struct hid_device_id sony_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), - .driver_data = SIXAXIS_CONTROLLER_USB }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), - .driver_data = SIXAXIS_CONTROLLER_USB }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), - .driver_data = SIXAXIS_CONTROLLER_BT }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), - .driver_data = VAIO_RDESC_CONSTANT }, - { } -}; -MODULE_DEVICE_TABLE(hid, sony_devices); - -static struct hid_driver sony_driver = { - .name = "sony", - .id_table = sony_devices, - .probe = sony_probe, - .remove = sony_remove, - .report_fixup = sony_report_fixup, - .raw_event = sony_raw_event -}; - -static int __init sony_init(void) -{ - return hid_register_driver(&sony_driver); -} - -static void __exit sony_exit(void) -{ - hid_unregister_driver(&sony_driver); -} - -module_init(sony_init); -module_exit(sony_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-speedlink.c b/ANDROID_3.4.5/drivers/hid/hid-speedlink.c deleted file mode 100644 index 60201374..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-speedlink.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * HID driver for Speedlink Vicious and Divine Cezanne (USB mouse). - * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from - * the HID descriptor. - * - * Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.de> - */ - -/* - * 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 <linux/usb.h> - -#include "hid-ids.h" -#include "usbhid/usbhid.h" - -static const struct hid_device_id speedlink_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)}, - { } -}; - -static int speedlink_input_mapping(struct hid_device *hdev, - struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - /* - * The Cezanne mouse has a second "keyboard" USB endpoint for it is - * able to map keyboard events to the button presses. - * It sends a standard keyboard report descriptor, though, whose - * LEDs we ignore. - */ - switch (usage->hid & HID_USAGE_PAGE) { - case HID_UP_LED: - return -1; - } - return 0; -} - -static int speedlink_event(struct hid_device *hdev, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - /* No other conditions due to usage_table. */ - /* Fix "jumpy" cursor (invalid events sent by device). */ - if (value == 256) - return 1; - /* Drop useless distance 0 events (on button clicks etc.) as well */ - if (value == 0) - return 1; - - return 0; -} - -MODULE_DEVICE_TABLE(hid, speedlink_devices); - -static const struct hid_usage_id speedlink_grabbed_usages[] = { - { HID_GD_X, EV_REL, 0 }, - { HID_GD_Y, EV_REL, 1 }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver speedlink_driver = { - .name = "speedlink", - .id_table = speedlink_devices, - .usage_table = speedlink_grabbed_usages, - .input_mapping = speedlink_input_mapping, - .event = speedlink_event, -}; - -static int __init speedlink_init(void) -{ - return hid_register_driver(&speedlink_driver); -} - -static void __exit speedlink_exit(void) -{ - hid_unregister_driver(&speedlink_driver); -} - -module_init(speedlink_init); -module_exit(speedlink_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-sunplus.c b/ANDROID_3.4.5/drivers/hid/hid-sunplus.c deleted file mode 100644 index d484a004..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-sunplus.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * HID driver for some sunplus "special" devices - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby - */ - -/* - * 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" - -static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && - rdesc[106] == 0x03) { - hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); - rdesc[105] = rdesc[110] = 0x03; - rdesc[106] = rdesc[111] = 0x21; - } - return rdesc; -} - -#define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int sp_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x2003: sp_map_key_clear(KEY_ZOOMIN); break; - case 0x2103: sp_map_key_clear(KEY_ZOOMOUT); break; - default: - return 0; - } - return 1; -} - -static const struct hid_device_id sp_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, - { } -}; -MODULE_DEVICE_TABLE(hid, sp_devices); - -static struct hid_driver sp_driver = { - .name = "sunplus", - .id_table = sp_devices, - .report_fixup = sp_report_fixup, - .input_mapping = sp_input_mapping, -}; - -static int __init sp_init(void) -{ - return hid_register_driver(&sp_driver); -} - -static void __exit sp_exit(void) -{ - hid_unregister_driver(&sp_driver); -} - -module_init(sp_init); -module_exit(sp_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-tivo.c b/ANDROID_3.4.5/drivers/hid/hid-tivo.c deleted file mode 100644 index 9f85f827..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-tivo.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * HID driver for TiVo Slide Bluetooth remote - * - * Copyright (c) 2011 Jarod Wilson <jarod@redhat.com> - * based on the hid-topseed driver, which is in turn, based on hid-cherry... - */ - -/* - * 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" - -#define HID_UP_TIVOVENDOR 0xffff0000 -#define tivo_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) - -static int tivo_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - case HID_UP_TIVOVENDOR: - switch (usage->hid & HID_USAGE) { - /* TiVo button */ - case 0x3d: tivo_map_key_clear(KEY_MEDIA); break; - /* Live TV */ - case 0x3e: tivo_map_key_clear(KEY_TV); break; - /* Red thumbs down */ - case 0x41: tivo_map_key_clear(KEY_KPMINUS); break; - /* Green thumbs up */ - case 0x42: tivo_map_key_clear(KEY_KPPLUS); break; - default: - return 0; - } - break; - case HID_UP_CONSUMER: - switch (usage->hid & HID_USAGE) { - /* Enter/Last (default mapping: KEY_LAST) */ - case 0x083: tivo_map_key_clear(KEY_ENTER); break; - /* Info (default mapping: KEY_PROPS) */ - case 0x209: tivo_map_key_clear(KEY_INFO); break; - default: - return 0; - } - break; - default: - return 0; - } - - /* This means we found a matching mapping here, else, look in the - * standard hid mappings in hid-input.c */ - return 1; -} - -static const struct hid_device_id tivo_devices[] = { - /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */ - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, - { } -}; -MODULE_DEVICE_TABLE(hid, tivo_devices); - -static struct hid_driver tivo_driver = { - .name = "tivo_slide", - .id_table = tivo_devices, - .input_mapping = tivo_input_mapping, -}; - -static int __init tivo_init(void) -{ - return hid_register_driver(&tivo_driver); -} - -static void __exit tivo_exit(void) -{ - hid_unregister_driver(&tivo_driver); -} - -module_init(tivo_init); -module_exit(tivo_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-tmff.c b/ANDROID_3.4.5/drivers/hid/hid-tmff.c deleted file mode 100644 index 83a933b9..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-tmff.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Force feedback support for various HID compliant devices by ThrustMaster: - * ThrustMaster FireStorm Dual Power 2 - * and possibly others whose device ids haven't been added. - * - * Modified to support ThrustMaster devices by Zinx Verituse - * on 2003-01-25 from the Logitech force feedback driver, - * which is by Johann Deneux. - * - * Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org> - * Copyright (c) 2002 Johann Deneux - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/module.h> - -#include "hid-ids.h" - -static const signed short ff_rumble[] = { - FF_RUMBLE, - -1 -}; - -static const signed short ff_joystick[] = { - FF_CONSTANT, - -1 -}; - -#ifdef CONFIG_THRUSTMASTER_FF -#include "usbhid/usbhid.h" - -/* Usages for thrustmaster devices I know about */ -#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) - -struct tmff_device { - struct hid_report *report; - struct hid_field *ff_field; -}; - -/* Changes values from 0 to 0xffff into values from minimum to maximum */ -static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum) -{ - int ret; - - ret = (in * (maximum - minimum) / 0xffff) + minimum; - if (ret < minimum) - return minimum; - if (ret > maximum) - return maximum; - return ret; -} - -/* Changes values from -0x80 to 0x7f into values from minimum to maximum */ -static inline int tmff_scale_s8(int in, int minimum, int maximum) -{ - int ret; - - ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum; - if (ret < minimum) - return minimum; - if (ret > maximum) - return maximum; - return ret; -} - -static int tmff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct tmff_device *tmff = data; - struct hid_field *ff_field = tmff->ff_field; - int x, y; - int left, right; /* Rumbling */ - - switch (effect->type) { - case FF_CONSTANT: - x = tmff_scale_s8(effect->u.ramp.start_level, - ff_field->logical_minimum, - ff_field->logical_maximum); - y = tmff_scale_s8(effect->u.ramp.end_level, - ff_field->logical_minimum, - ff_field->logical_maximum); - - dbg_hid("(x, y)=(%04x, %04x)\n", x, y); - ff_field->value[0] = x; - ff_field->value[1] = y; - usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); - break; - - case FF_RUMBLE: - left = tmff_scale_u16(effect->u.rumble.weak_magnitude, - ff_field->logical_minimum, - ff_field->logical_maximum); - right = tmff_scale_u16(effect->u.rumble.strong_magnitude, - ff_field->logical_minimum, - ff_field->logical_maximum); - - dbg_hid("(left,right)=(%08x, %08x)\n", left, right); - ff_field->value[0] = left; - ff_field->value[1] = right; - usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); - break; - } - return 0; -} - -static int tmff_init(struct hid_device *hid, const signed short *ff_bits) -{ - struct tmff_device *tmff; - struct hid_report *report; - struct list_head *report_list; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct input_dev *input_dev = hidinput->input; - int error; - int i; - - tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); - if (!tmff) - return -ENOMEM; - - /* Find the report to use */ - report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - list_for_each_entry(report, report_list, list) { - int fieldnum; - - for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { - struct hid_field *field = report->field[fieldnum]; - - if (field->maxusage <= 0) - continue; - - switch (field->usage[0].hid) { - case THRUSTMASTER_USAGE_FF: - if (field->report_count < 2) { - hid_warn(hid, "ignoring FF field with report_count < 2\n"); - continue; - } - - if (field->logical_maximum == - field->logical_minimum) { - hid_warn(hid, "ignoring FF field with logical_maximum == logical_minimum\n"); - continue; - } - - if (tmff->report && tmff->report != report) { - hid_warn(hid, "ignoring FF field in other report\n"); - continue; - } - - if (tmff->ff_field && tmff->ff_field != field) { - hid_warn(hid, "ignoring duplicate FF field\n"); - continue; - } - - tmff->report = report; - tmff->ff_field = field; - - for (i = 0; ff_bits[i] >= 0; i++) - set_bit(ff_bits[i], input_dev->ffbit); - - break; - - default: - hid_warn(hid, "ignoring unknown output usage %08x\n", - field->usage[0].hid); - continue; - } - } - } - - if (!tmff->report) { - hid_err(hid, "can't find FF field in output reports\n"); - error = -ENODEV; - goto fail; - } - - error = input_ff_create_memless(input_dev, tmff, tmff_play); - if (error) - goto fail; - - hid_info(hid, "force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>\n"); - return 0; - -fail: - kfree(tmff); - return error; -} -#else -static inline int tmff_init(struct hid_device *hid, const signed short *ff_bits) -{ - return 0; -} -#endif - -static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - tmff_init(hdev, (void *)id->driver_data); - - return 0; -err: - return ret; -} - -static const struct hid_device_id tm_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300), - .driver_data = (unsigned long)ff_rumble }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304), /* FireStorm Dual Power 2 (and 3) */ - .driver_data = (unsigned long)ff_rumble }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323), /* Dual Trigger 3-in-1 (PC Mode) */ - .driver_data = (unsigned long)ff_rumble }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324), /* Dual Trigger 3-in-1 (PS3 Mode) */ - .driver_data = (unsigned long)ff_rumble }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651), /* FGT Rumble Force Wheel */ - .driver_data = (unsigned long)ff_rumble }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653), /* RGT Force Feedback CLUTCH Raging Wheel */ - .driver_data = (unsigned long)ff_joystick }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654), /* FGT Force Feedback Wheel */ - .driver_data = (unsigned long)ff_joystick }, - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a), /* F430 Force Feedback Wheel */ - .driver_data = (unsigned long)ff_joystick }, - { } -}; -MODULE_DEVICE_TABLE(hid, tm_devices); - -static struct hid_driver tm_driver = { - .name = "thrustmaster", - .id_table = tm_devices, - .probe = tm_probe, -}; - -static int __init tm_init(void) -{ - return hid_register_driver(&tm_driver); -} - -static void __exit tm_exit(void) -{ - hid_unregister_driver(&tm_driver); -} - -module_init(tm_init); -module_exit(tm_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-topseed.c b/ANDROID_3.4.5/drivers/hid/hid-topseed.c deleted file mode 100644 index 613ff7b1..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-topseed.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * HID driver for TopSeed Cyberlink remote - * - * Copyright (c) 2008 Lev Babiev - * based on hid-cherry driver - * - * Modified to also support BTC "Emprex 3009URF III Vista MCE Remote" by - * Wayne Thomas 2010. - * - * Modified to support Conceptronic CLLRCMCE by - * Kees Bakker 2010. - */ - -/* - * 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" - -#define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) - return 0; - - switch (usage->hid & HID_USAGE) { - case 0x00d: ts_map_key_clear(KEY_MEDIA); break; - case 0x024: ts_map_key_clear(KEY_MENU); break; - case 0x025: ts_map_key_clear(KEY_TV); break; - case 0x027: ts_map_key_clear(KEY_MODE); break; - case 0x031: ts_map_key_clear(KEY_AUDIO); break; - case 0x032: ts_map_key_clear(KEY_TEXT); break; - case 0x033: ts_map_key_clear(KEY_CHANNEL); break; - case 0x047: ts_map_key_clear(KEY_MP3); break; - case 0x048: ts_map_key_clear(KEY_TV2); break; - case 0x049: ts_map_key_clear(KEY_CAMERA); break; - case 0x04a: ts_map_key_clear(KEY_VIDEO); break; - case 0x04b: ts_map_key_clear(KEY_ANGLE); break; - case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break; - case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break; - case 0x050: ts_map_key_clear(KEY_RADIO); break; - case 0x05a: ts_map_key_clear(KEY_TEXT); break; - case 0x05b: ts_map_key_clear(KEY_RED); break; - case 0x05c: ts_map_key_clear(KEY_GREEN); break; - case 0x05d: ts_map_key_clear(KEY_YELLOW); break; - case 0x05e: ts_map_key_clear(KEY_BLUE); break; - default: - return 0; - } - - return 1; -} - -static const struct hid_device_id ts_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ts_devices); - -static struct hid_driver ts_driver = { - .name = "topseed", - .id_table = ts_devices, - .input_mapping = ts_input_mapping, -}; - -static int __init ts_init(void) -{ - return hid_register_driver(&ts_driver); -} - -static void __exit ts_exit(void) -{ - hid_unregister_driver(&ts_driver); -} - -module_init(ts_init); -module_exit(ts_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-twinhan.c b/ANDROID_3.4.5/drivers/hid/hid-twinhan.c deleted file mode 100644 index f23456b1..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-twinhan.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * HID driver for TwinHan IR remote control - * - * Based on hid-gyration.c - * - * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org> - */ - -/* - * 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. - */ - -#include <linux/device.h> -#include <linux/input.h> -#include <linux/hid.h> -#include <linux/module.h> - -#include "hid-ids.h" - -/* Remote control key layout + listing: - * - * Full Screen Power - * KEY_SCREEN KEY_POWER2 - * - * 1 2 3 - * KEY_NUMERIC_1 KEY_NUMERIC_2 KEY_NUMERIC_3 - * - * 4 5 6 - * KEY_NUMERIC_4 KEY_NUMERIC_5 KEY_NUMERIC_6 - * - * 7 8 9 - * KEY_NUMERIC_7 KEY_NUMERIC_8 KEY_NUMERIC_9 - * - * REC 0 Favorite - * KEY_RECORD KEY_NUMERIC_0 KEY_FAVORITES - * - * Rewind Forward - * KEY_REWIND CH+ KEY_FORWARD - * KEY_CHANNELUP - * - * VOL- > VOL+ - * KEY_VOLUMEDOWN KEY_PLAY KEY_VOLUMEUP - * - * CH- - * KEY_CHANNELDOWN - * Recall Stop - * KEY_RESTART KEY_STOP - * - * Timeshift/Pause Mute Cancel - * KEY_PAUSE KEY_MUTE KEY_CANCEL - * - * Capture Preview EPG - * KEY_PRINT KEY_PROGRAM KEY_EPG - * - * Record List Tab Teletext - * KEY_LIST KEY_TAB KEY_TEXT - */ - -#define th_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) -static int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD) - return 0; - - switch (usage->hid & HID_USAGE) { - /* Map all keys from Twinhan Remote */ - case 0x004: th_map_key_clear(KEY_TEXT); break; - case 0x006: th_map_key_clear(KEY_RESTART); break; - case 0x008: th_map_key_clear(KEY_EPG); break; - case 0x00c: th_map_key_clear(KEY_REWIND); break; - case 0x00e: th_map_key_clear(KEY_PROGRAM); break; - case 0x00f: th_map_key_clear(KEY_LIST); break; - case 0x010: th_map_key_clear(KEY_MUTE); break; - case 0x011: th_map_key_clear(KEY_FORWARD); break; - case 0x013: th_map_key_clear(KEY_PRINT); break; - case 0x017: th_map_key_clear(KEY_PAUSE); break; - case 0x019: th_map_key_clear(KEY_FAVORITES); break; - case 0x01d: th_map_key_clear(KEY_SCREEN); break; - case 0x01e: th_map_key_clear(KEY_NUMERIC_1); break; - case 0x01f: th_map_key_clear(KEY_NUMERIC_2); break; - case 0x020: th_map_key_clear(KEY_NUMERIC_3); break; - case 0x021: th_map_key_clear(KEY_NUMERIC_4); break; - case 0x022: th_map_key_clear(KEY_NUMERIC_5); break; - case 0x023: th_map_key_clear(KEY_NUMERIC_6); break; - case 0x024: th_map_key_clear(KEY_NUMERIC_7); break; - case 0x025: th_map_key_clear(KEY_NUMERIC_8); break; - case 0x026: th_map_key_clear(KEY_NUMERIC_9); break; - case 0x027: th_map_key_clear(KEY_NUMERIC_0); break; - case 0x028: th_map_key_clear(KEY_PLAY); break; - case 0x029: th_map_key_clear(KEY_CANCEL); break; - case 0x02b: th_map_key_clear(KEY_TAB); break; - /* Power = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */ - case 0x03f: th_map_key_clear(KEY_POWER2); break; - case 0x04a: th_map_key_clear(KEY_RECORD); break; - case 0x04b: th_map_key_clear(KEY_CHANNELUP); break; - case 0x04d: th_map_key_clear(KEY_STOP); break; - case 0x04e: th_map_key_clear(KEY_CHANNELDOWN); break; - /* Volume down = 0x0e1 + 0x051 */ - case 0x051: th_map_key_clear(KEY_VOLUMEDOWN); break; - /* Volume up = 0x0e1 + 0x052 */ - case 0x052: th_map_key_clear(KEY_VOLUMEUP); break; - /* Kill the extra keys used for multi-key "power" and "volume" keys - * as well as continuously to release CTRL,ALT,META,... keys */ - case 0x0e0: - case 0x0e1: - case 0x0e2: - case 0x0e3: - case 0x0e4: - case 0x0e5: - case 0x0e6: - case 0x0e7: - default: - return -1; - } - return 1; -} - -static const struct hid_device_id twinhan_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, - { } -}; -MODULE_DEVICE_TABLE(hid, twinhan_devices); - -static struct hid_driver twinhan_driver = { - .name = "twinhan", - .id_table = twinhan_devices, - .input_mapping = twinhan_input_mapping, -}; - -static int __init twinhan_init(void) -{ - return hid_register_driver(&twinhan_driver); -} - -static void __exit twinhan_exit(void) -{ - hid_unregister_driver(&twinhan_driver); -} - -module_init(twinhan_init); -module_exit(twinhan_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-uclogic.c b/ANDROID_3.4.5/drivers/hid/hid-uclogic.c deleted file mode 100644 index 1f112891..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-uclogic.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * HID driver for UC-Logic devices not fully compliant with HID standard - * - * Copyright (c) 2010 Nikolai Kondrashov - */ - -/* - * 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" - -/* - * See WPXXXXU model descriptions, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP4030U - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP5540U - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP8060U - */ - -/* Size of the original descriptor of WPXXXXU tablets */ -#define WPXXXXU_RDESC_ORIG_SIZE 212 - -/* Fixed WP4030U report descriptor */ -static __u8 wp4030u_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x09, /* Report ID (9), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* Fixed WP5540U report descriptor */ -static __u8 wp5540u_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x09, /* Report ID (9), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x02, /* Usage (Mouse), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x08, /* Report ID (8), */ - 0x09, 0x01, /* Usage (Pointer), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x05, 0x09, /* Usage Page (Button), */ - 0x19, 0x01, /* Usage Minimum (01h), */ - 0x29, 0x03, /* Usage Maximum (03h), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x75, 0x08, /* Report Size (8), */ - 0x09, 0x30, /* Usage (X), */ - 0x09, 0x31, /* Usage (Y), */ - 0x15, 0x81, /* Logical Minimum (-127), */ - 0x25, 0x7F, /* Logical Maximum (127), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x09, 0x38, /* Usage (Wheel), */ - 0x15, 0xFF, /* Logical Minimum (-1), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x81, 0x01, /* Input (Constant), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* Fixed WP8060U report descriptor */ -static __u8 wp8060u_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x09, /* Report ID (9), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x02, /* Usage (Mouse), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x08, /* Report ID (8), */ - 0x09, 0x01, /* Usage (Pointer), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x05, 0x09, /* Usage Page (Button), */ - 0x19, 0x01, /* Usage Minimum (01h), */ - 0x29, 0x03, /* Usage Maximum (03h), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x75, 0x08, /* Report Size (8), */ - 0x09, 0x30, /* Usage (X), */ - 0x09, 0x31, /* Usage (Y), */ - 0x15, 0x81, /* Logical Minimum (-127), */ - 0x25, 0x7F, /* Logical Maximum (127), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x09, 0x38, /* Usage (Wheel), */ - 0x15, 0xFF, /* Logical Minimum (-1), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x81, 0x01, /* Input (Constant), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See WP1062 description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP1062 - */ - -/* Size of the original descriptor of WP1062 tablet */ -#define WP1062_RDESC_ORIG_SIZE 254 - -/* Fixed WP1062 report descriptor */ -static __u8 wp1062_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x09, /* Report ID (9), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x04, /* Report Count (4), */ - 0x81, 0x01, /* Input (Constant), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ - 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0xB7, 0x19, /* Physical Maximum (6583), */ - 0x26, 0x6E, 0x33, /* Logical Maximum (13166), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See PF1209 description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_PF1209 - */ - -/* Size of the original descriptor of PF1209 tablet */ -#define PF1209_RDESC_ORIG_SIZE 234 - -/* Fixed PF1209 report descriptor */ -static __u8 pf1209_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x09, /* Report ID (9), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x02, /* Usage (Mouse), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x08, /* Report ID (8), */ - 0x09, 0x01, /* Usage (Pointer), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x01, /* Report Size (1), */ - 0x05, 0x09, /* Usage Page (Button), */ - 0x19, 0x01, /* Usage Minimum (01h), */ - 0x29, 0x03, /* Usage Maximum (03h), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x05, /* Report Count (5), */ - 0x81, 0x01, /* Input (Constant), */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x75, 0x08, /* Report Size (8), */ - 0x09, 0x30, /* Usage (X), */ - 0x09, 0x31, /* Usage (Y), */ - 0x15, 0x81, /* Logical Minimum (-127), */ - 0x25, 0x7F, /* Logical Maximum (127), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x09, 0x38, /* Usage (Wheel), */ - 0x15, 0xFF, /* Logical Minimum (-1), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x81, 0x01, /* Input (Constant), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - switch (hdev->product) { - case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: - if (*rsize == PF1209_RDESC_ORIG_SIZE) { - rdesc = pf1209_rdesc_fixed; - *rsize = sizeof(pf1209_rdesc_fixed); - } - break; - case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: - if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { - rdesc = wp4030u_rdesc_fixed; - *rsize = sizeof(wp4030u_rdesc_fixed); - } - break; - case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U: - if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { - rdesc = wp5540u_rdesc_fixed; - *rsize = sizeof(wp5540u_rdesc_fixed); - } - break; - case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U: - if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { - rdesc = wp8060u_rdesc_fixed; - *rsize = sizeof(wp8060u_rdesc_fixed); - } - break; - case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062: - if (*rsize == WP1062_RDESC_ORIG_SIZE) { - rdesc = wp1062_rdesc_fixed; - *rsize = sizeof(wp1062_rdesc_fixed); - } - break; - } - - return rdesc; -} - -static const struct hid_device_id uclogic_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, - USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, - USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, - USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, - USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, - { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, - USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, - { } -}; -MODULE_DEVICE_TABLE(hid, uclogic_devices); - -static struct hid_driver uclogic_driver = { - .name = "uclogic", - .id_table = uclogic_devices, - .report_fixup = uclogic_report_fixup, -}; - -static int __init uclogic_init(void) -{ - return hid_register_driver(&uclogic_driver); -} - -static void __exit uclogic_exit(void) -{ - hid_unregister_driver(&uclogic_driver); -} - -module_init(uclogic_init); -module_exit(uclogic_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-wacom.c b/ANDROID_3.4.5/drivers/hid/hid-wacom.c deleted file mode 100644 index 067e2963..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-wacom.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Bluetooth Wacom Tablet support - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> - * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> - * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> - * Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu> - */ - -/* - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/device.h> -#include <linux/hid.h> -#include <linux/module.h> -#include <linux/slab.h> -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY -#include <linux/power_supply.h> -#endif - -#include "hid-ids.h" - -#define PAD_DEVICE_ID 0x0F - -struct wacom_data { - __u16 tool; - __u16 butstate; - __u8 whlstate; - __u8 features; - __u32 id; - __u32 serial; - unsigned char high_speed; -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY - int battery_capacity; - struct power_supply battery; - struct power_supply ac; -#endif -}; - -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY -/*percent of battery capacity, 0 means AC online*/ -static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 }; - -static enum power_supply_property wacom_battery_props[] = { - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_SCOPE, -}; - -static enum power_supply_property wacom_ac_props[] = { - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_SCOPE, -}; - -static int wacom_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct wacom_data *wdata = container_of(psy, - struct wacom_data, battery); - int power_state = batcap[wdata->battery_capacity]; - int ret = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_PRESENT: - val->intval = 1; - break; - case POWER_SUPPLY_PROP_SCOPE: - val->intval = POWER_SUPPLY_SCOPE_DEVICE; - break; - case POWER_SUPPLY_PROP_CAPACITY: - /* show 100% battery capacity when charging */ - if (power_state == 0) - val->intval = 100; - else - val->intval = power_state; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int wacom_ac_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct wacom_data *wdata = container_of(psy, struct wacom_data, ac); - int power_state = batcap[wdata->battery_capacity]; - int ret = 0; - - switch (psp) { - case POWER_SUPPLY_PROP_PRESENT: - /* fall through */ - case POWER_SUPPLY_PROP_ONLINE: - if (power_state == 0) - val->intval = 1; - else - val->intval = 0; - break; - case POWER_SUPPLY_PROP_SCOPE: - val->intval = POWER_SUPPLY_SCOPE_DEVICE; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} -#endif - -static void wacom_set_features(struct hid_device *hdev) -{ - int ret; - __u8 rep_data[2]; - - /*set high speed, tablet mode*/ - rep_data[0] = 0x03; - rep_data[1] = 0x20; - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - return; -} - -static void wacom_poke(struct hid_device *hdev, u8 speed) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - int limit, ret; - char rep_data[2]; - - rep_data[0] = 0x03 ; rep_data[1] = 0x00; - limit = 3; - do { - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - } while (ret < 0 && limit-- > 0); - - if (ret >= 0) { - if (speed == 0) - rep_data[0] = 0x05; - else - rep_data[0] = 0x06; - - rep_data[1] = 0x00; - limit = 3; - do { - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - } while (ret < 0 && limit-- > 0); - - if (ret >= 0) { - wdata->high_speed = speed; - return; - } - } - - /* - * Note that if the raw queries fail, it's not a hard failure and it - * is safe to continue - */ - hid_warn(hdev, "failed to poke device, command %d, err %d\n", - rep_data[0], ret); - return; -} - -static ssize_t wacom_show_speed(struct device *dev, - struct device_attribute - *attr, char *buf) -{ - struct wacom_data *wdata = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed); -} - -static ssize_t wacom_store_speed(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - int new_speed; - - if (sscanf(buf, "%1d", &new_speed ) != 1) - return -EINVAL; - - if (new_speed == 0 || new_speed == 1) { - wacom_poke(hdev, new_speed); - return strnlen(buf, PAGE_SIZE); - } else - return -EINVAL; -} - -static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, - wacom_show_speed, wacom_store_speed); - -static int wacom_gr_parse_report(struct hid_device *hdev, - struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - int tool, x, y, rw; - - tool = 0; - /* Get X & Y positions */ - x = le16_to_cpu(*(__le16 *) &data[2]); - y = le16_to_cpu(*(__le16 *) &data[4]); - - /* Get current tool identifier */ - if (data[1] & 0x90) { /* If pen is in the in/active area */ - switch ((data[1] >> 5) & 3) { - case 0: /* Pen */ - tool = BTN_TOOL_PEN; - break; - - case 1: /* Rubber */ - tool = BTN_TOOL_RUBBER; - break; - - case 2: /* Mouse with wheel */ - case 3: /* Mouse without wheel */ - tool = BTN_TOOL_MOUSE; - break; - } - - /* Reset tool if out of active tablet area */ - if (!(data[1] & 0x10)) - tool = 0; - } - - /* If tool changed, notify input subsystem */ - if (wdata->tool != tool) { - if (wdata->tool) { - /* Completely reset old tool state */ - if (wdata->tool == BTN_TOOL_MOUSE) { - input_report_key(input, BTN_LEFT, 0); - input_report_key(input, BTN_RIGHT, 0); - input_report_key(input, BTN_MIDDLE, 0); - input_report_abs(input, ABS_DISTANCE, - input_abs_get_max(input, ABS_DISTANCE)); - } else { - input_report_key(input, BTN_TOUCH, 0); - input_report_key(input, BTN_STYLUS, 0); - input_report_key(input, BTN_STYLUS2, 0); - input_report_abs(input, ABS_PRESSURE, 0); - } - input_report_key(input, wdata->tool, 0); - input_sync(input); - } - wdata->tool = tool; - if (tool) - input_report_key(input, tool, 1); - } - - if (tool) { - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - - switch ((data[1] >> 5) & 3) { - case 2: /* Mouse with wheel */ - input_report_key(input, BTN_MIDDLE, data[1] & 0x04); - rw = (data[6] & 0x01) ? -1 : - (data[6] & 0x02) ? 1 : 0; - input_report_rel(input, REL_WHEEL, rw); - /* fall through */ - - case 3: /* Mouse without wheel */ - input_report_key(input, BTN_LEFT, data[1] & 0x01); - input_report_key(input, BTN_RIGHT, data[1] & 0x02); - /* Compute distance between mouse and tablet */ - rw = 44 - (data[6] >> 2); - if (rw < 0) - rw = 0; - else if (rw > 31) - rw = 31; - input_report_abs(input, ABS_DISTANCE, rw); - break; - - default: - input_report_abs(input, ABS_PRESSURE, - data[6] | (((__u16) (data[1] & 0x08)) << 5)); - input_report_key(input, BTN_TOUCH, data[1] & 0x01); - input_report_key(input, BTN_STYLUS, data[1] & 0x02); - input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04); - break; - } - - input_sync(input); - } - - /* Report the state of the two buttons at the top of the tablet - * as two extra fingerpad keys (buttons 4 & 5). */ - rw = data[7] & 0x03; - if (rw != wdata->butstate) { - wdata->butstate = rw; - input_report_key(input, BTN_0, rw & 0x02); - input_report_key(input, BTN_1, rw & 0x01); - input_report_key(input, BTN_TOOL_FINGER, 0xf0); - input_event(input, EV_MSC, MSC_SERIAL, 0xf0); - input_sync(input); - } - -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY - /* Store current battery capacity */ - rw = (data[7] >> 2 & 0x07); - if (rw != wdata->battery_capacity) - wdata->battery_capacity = rw; -#endif - return 1; -} - -static void wacom_i4_parse_button_report(struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - __u16 new_butstate; - __u8 new_whlstate; - __u8 sync = 0; - - new_whlstate = data[1]; - if (new_whlstate != wdata->whlstate) { - wdata->whlstate = new_whlstate; - if (new_whlstate & 0x80) { - input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f)); - input_report_key(input, BTN_TOOL_FINGER, 1); - } else { - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_WHEEL, 0); - input_report_key(input, BTN_TOOL_FINGER, 0); - } - sync = 1; - } - - new_butstate = (data[3] << 1) | (data[2] & 0x01); - if (new_butstate != wdata->butstate) { - wdata->butstate = new_butstate; - input_report_key(input, BTN_0, new_butstate & 0x001); - input_report_key(input, BTN_1, new_butstate & 0x002); - input_report_key(input, BTN_2, new_butstate & 0x004); - input_report_key(input, BTN_3, new_butstate & 0x008); - input_report_key(input, BTN_4, new_butstate & 0x010); - input_report_key(input, BTN_5, new_butstate & 0x020); - input_report_key(input, BTN_6, new_butstate & 0x040); - input_report_key(input, BTN_7, new_butstate & 0x080); - input_report_key(input, BTN_8, new_butstate & 0x100); - input_report_key(input, BTN_TOOL_FINGER, 1); - sync = 1; - } - - if (sync) { - input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); - input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); - input_sync(input); - } -} - -static void wacom_i4_parse_pen_report(struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - __u16 x, y, pressure; - __u8 distance; - - switch (data[1]) { - case 0x80: /* Out of proximity report */ - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_PRESSURE, 0); - input_report_key(input, BTN_STYLUS, 0); - input_report_key(input, BTN_STYLUS2, 0); - input_report_key(input, wdata->tool, 0); - input_report_abs(input, ABS_MISC, 0); - input_event(input, EV_MSC, MSC_SERIAL, wdata->serial); - wdata->tool = 0; - input_sync(input); - break; - case 0xC2: /* Tool report */ - wdata->id = ((data[2] << 4) | (data[3] >> 4) | - ((data[7] & 0x0f) << 20) | - ((data[8] & 0xf0) << 12)); - wdata->serial = ((data[3] & 0x0f) << 28) + - (data[4] << 20) + (data[5] << 12) + - (data[6] << 4) + (data[7] >> 4); - - switch (wdata->id) { - case 0x100802: - wdata->tool = BTN_TOOL_PEN; - break; - case 0x10080A: - wdata->tool = BTN_TOOL_RUBBER; - break; - } - break; - default: /* Position/pressure report */ - x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1); - y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); - pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) - | (data[1] & 0x01); - distance = (data[9] >> 2) & 0x3f; - - input_report_key(input, BTN_TOUCH, pressure > 1); - - input_report_key(input, BTN_STYLUS, data[1] & 0x02); - input_report_key(input, BTN_STYLUS2, data[1] & 0x04); - input_report_key(input, wdata->tool, 1); - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); - input_report_abs(input, ABS_PRESSURE, pressure); - input_report_abs(input, ABS_DISTANCE, distance); - input_report_abs(input, ABS_MISC, wdata->id); - input_event(input, EV_MSC, MSC_SERIAL, wdata->serial); - input_report_key(input, wdata->tool, 1); - input_sync(input); - break; - } - - return; -} - -static void wacom_i4_parse_report(struct hid_device *hdev, - struct wacom_data *wdata, - struct input_dev *input, unsigned char *data) -{ - switch (data[0]) { - case 0x00: /* Empty report */ - break; - case 0x02: /* Pen report */ - wacom_i4_parse_pen_report(wdata, input, data); - break; - case 0x03: /* Features Report */ - wdata->features = data[2]; - break; - case 0x0C: /* Button report */ - wacom_i4_parse_button_report(wdata, input, data); - break; - default: - hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); - break; - } -} - -static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ - struct wacom_data *wdata = hid_get_drvdata(hdev); - struct hid_input *hidinput; - struct input_dev *input; - unsigned char *data = (unsigned char *) raw_data; - int i; - - if (!(hdev->claimed & HID_CLAIMED_INPUT)) - return 0; - - hidinput = list_entry(hdev->inputs.next, struct hid_input, list); - input = hidinput->input; - - /* Check if this is a tablet report */ - if (data[0] != 0x03) - return 0; - - switch (hdev->product) { - case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: - return wacom_gr_parse_report(hdev, wdata, input, data); - break; - case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: - i = 1; - - switch (data[0]) { - case 0x04: - wacom_i4_parse_report(hdev, wdata, input, data + i); - i += 10; - /* fall through */ - case 0x03: - wacom_i4_parse_report(hdev, wdata, input, data + i); - i += 10; - wacom_i4_parse_report(hdev, wdata, input, data + i); - break; - default: - hid_err(hdev, "Unknown report: %d,%d size:%d\n", - data[0], data[1], size); - return 0; - } - } - return 1; -} - -static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, unsigned long **bit, - int *max) -{ - struct input_dev *input = hi->input; - - __set_bit(INPUT_PROP_POINTER, input->propbit); - - /* Basics */ - input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); - - __set_bit(REL_WHEEL, input->relbit); - - __set_bit(BTN_TOOL_PEN, input->keybit); - __set_bit(BTN_TOUCH, input->keybit); - __set_bit(BTN_STYLUS, input->keybit); - __set_bit(BTN_STYLUS2, input->keybit); - __set_bit(BTN_LEFT, input->keybit); - __set_bit(BTN_RIGHT, input->keybit); - __set_bit(BTN_MIDDLE, input->keybit); - - /* Pad */ - input_set_capability(input, EV_MSC, MSC_SERIAL); - - __set_bit(BTN_0, input->keybit); - __set_bit(BTN_1, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - - /* Distance, rubber and mouse */ - __set_bit(BTN_TOOL_RUBBER, input->keybit); - __set_bit(BTN_TOOL_MOUSE, input->keybit); - - switch (hdev->product) { - case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: - input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); - input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); - input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); - input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); - break; - case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: - __set_bit(ABS_WHEEL, input->absbit); - __set_bit(ABS_MISC, input->absbit); - __set_bit(BTN_2, input->keybit); - __set_bit(BTN_3, input->keybit); - __set_bit(BTN_4, input->keybit); - __set_bit(BTN_5, input->keybit); - __set_bit(BTN_6, input->keybit); - __set_bit(BTN_7, input->keybit); - __set_bit(BTN_8, input->keybit); - input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0); - input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); - input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); - input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); - input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0); - break; - } - - return 0; -} - -static int wacom_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - struct wacom_data *wdata; - int ret; - - wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); - if (wdata == NULL) { - hid_err(hdev, "can't alloc wacom descriptor\n"); - return -ENOMEM; - } - - hid_set_drvdata(hdev, wdata); - - /* Parse the HID report now */ - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - ret = device_create_file(&hdev->dev, &dev_attr_speed); - if (ret) - hid_warn(hdev, - "can't create sysfs speed attribute err: %d\n", ret); - - switch (hdev->product) { - case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: - /* Set Wacom mode 2 with high reporting speed */ - wacom_poke(hdev, 1); - break; - case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: - sprintf(hdev->name, "%s", "Wacom Intuos4 WL"); - wdata->features = 0; - wacom_set_features(hdev); - break; - } - -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY - wdata->battery.properties = wacom_battery_props; - wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props); - wdata->battery.get_property = wacom_battery_get_property; - wdata->battery.name = "wacom_battery"; - wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; - wdata->battery.use_for_apm = 0; - - - ret = power_supply_register(&hdev->dev, &wdata->battery); - if (ret) { - hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", - ret); - goto err_battery; - } - - power_supply_powers(&wdata->battery, &hdev->dev); - - wdata->ac.properties = wacom_ac_props; - wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props); - wdata->ac.get_property = wacom_ac_get_property; - wdata->ac.name = "wacom_ac"; - wdata->ac.type = POWER_SUPPLY_TYPE_MAINS; - wdata->ac.use_for_apm = 0; - - ret = power_supply_register(&hdev->dev, &wdata->ac); - if (ret) { - hid_warn(hdev, - "can't create ac battery attribute, err: %d\n", ret); - goto err_ac; - } - - power_supply_powers(&wdata->ac, &hdev->dev); -#endif - return 0; - -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY -err_ac: - power_supply_unregister(&wdata->battery); -err_battery: - device_remove_file(&hdev->dev, &dev_attr_speed); - hid_hw_stop(hdev); -#endif -err_free: - kfree(wdata); - return ret; -} - -static void wacom_remove(struct hid_device *hdev) -{ -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY - struct wacom_data *wdata = hid_get_drvdata(hdev); -#endif - device_remove_file(&hdev->dev, &dev_attr_speed); - hid_hw_stop(hdev); - -#ifdef CONFIG_HID_WACOM_POWER_SUPPLY - power_supply_unregister(&wdata->battery); - power_supply_unregister(&wdata->ac); -#endif - kfree(hid_get_drvdata(hdev)); -} - -static const struct hid_device_id wacom_devices[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, - - { } -}; -MODULE_DEVICE_TABLE(hid, wacom_devices); - -static struct hid_driver wacom_driver = { - .name = "wacom", - .id_table = wacom_devices, - .probe = wacom_probe, - .remove = wacom_remove, - .raw_event = wacom_raw_event, - .input_mapped = wacom_input_mapped, -}; - -static int __init wacom_init(void) -{ - int ret; - - ret = hid_register_driver(&wacom_driver); - if (ret) - pr_err("can't register wacom driver\n"); - return ret; -} - -static void __exit wacom_exit(void) -{ - hid_unregister_driver(&wacom_driver); -} - -module_init(wacom_init); -module_exit(wacom_exit); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/drivers/hid/hid-waltop.c b/ANDROID_3.4.5/drivers/hid/hid-waltop.c deleted file mode 100644 index 2cfd95c4..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-waltop.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * HID driver for Waltop devices not fully compliant with HID standard - * - * Copyright (c) 2010 Nikolai Kondrashov - */ - -/* - * 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" - -/* - * There exists an official driver on the manufacturer's website, which - * wasn't submitted to the kernel, for some reason. The official driver - * doesn't seem to support extra features of some tablets, like wheels. - * - * It shows that the feature report ID 2 could be used to control any waltop - * tablet input mode, switching it between "default", "tablet" and "ink". - * - * This driver only uses "default" mode for all the supported tablets. This - * mode tries to be HID-compatible (not very successfully), but cripples the - * resolution of some tablets. - * - * The "tablet" mode uses some proprietary, yet decipherable protocol, which - * represents the correct resolution, but is possibly HID-incompatible (i.e. - * indescribable by a report descriptor). - * - * The purpose of the "ink" mode is unknown. - * - * The feature reports needed for switching to each mode are these: - * - * 02 16 00 default - * 02 16 01 tablet - * 02 16 02 ink - */ - -/* - * See Slim Tablet 5.8 inch description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_5.8%22 - */ - -/* Size of the original report descriptor of Slim Tablet 5.8 inch */ -#define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 - -/* Fixed Slim Tablet 5.8 inch descriptor */ -static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x15, 0x01, /* Logical Minimum (1), */ - 0x25, 0x03, /* Logical Maximum (3), */ - 0x75, 0x04, /* Report Size (4), */ - 0x95, 0x01, /* Report Count (1), */ - 0x80, /* Input, */ - 0x09, 0x32, /* Usage (In Range), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ - 0x26, 0x10, 0x27, /* Logical Maximum (10000), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ - 0x26, 0x70, 0x17, /* Logical Maximum (6000), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See Slim Tablet 12.1 inch description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_12.1%22 - */ - -/* Size of the original report descriptor of Slim Tablet 12.1 inch */ -#define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269 - -/* Fixed Slim Tablet 12.1 inch descriptor */ -static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x15, 0x01, /* Logical Minimum (1), */ - 0x25, 0x03, /* Logical Maximum (3), */ - 0x75, 0x04, /* Report Size (4), */ - 0x95, 0x01, /* Report Count (1), */ - 0x80, /* Input, */ - 0x09, 0x32, /* Usage (In Range), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ - 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ - 0x26, 0xD4, 0x30, /* Logical Maximum (12500), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See Q Pad description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Q_Pad - */ - -/* Size of the original report descriptor of Q Pad */ -#define Q_PAD_RDESC_ORIG_SIZE 241 - -/* Fixed Q Pad descriptor */ -static __u8 q_pad_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x15, 0x01, /* Logical Minimum (1), */ - 0x25, 0x03, /* Logical Maximum (3), */ - 0x75, 0x04, /* Report Size (4), */ - 0x95, 0x01, /* Report Count (1), */ - 0x80, /* Input, */ - 0x09, 0x32, /* Usage (In Range), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ - 0x26, 0x00, 0x30, /* Logical Maximum (12288), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x94, 0x11, /* Physical Maximum (4500), */ - 0x26, 0x00, 0x24, /* Logical Maximum (9216), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See description, device and HID report descriptors of tablet with PID 0038 at - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_PID_0038 - */ - -/* Size of the original report descriptor of tablet with PID 0038 */ -#define PID_0038_RDESC_ORIG_SIZE 241 - -/* - * Fixed report descriptor for tablet with PID 0038. - */ -static __u8 pid_0038_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x15, 0x01, /* Logical Minimum (1), */ - 0x25, 0x03, /* Logical Maximum (3), */ - 0x75, 0x04, /* Report Size (4), */ - 0x95, 0x01, /* Report Count (1), */ - 0x80, /* Input, */ - 0x09, 0x32, /* Usage (In Range), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x2E, 0x22, /* Physical Maximum (8750), */ - 0x26, 0x00, 0x46, /* Logical Maximum (17920), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x82, 0x14, /* Physical Maximum (5250), */ - 0x26, 0x00, 0x2A, /* Logical Maximum (10752), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0 /* End Collection */ -}; - -/* - * See Media Tablet 10.6 inch description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22 - */ - -/* Size of the original report descriptor of Media Tablet 10.6 inch */ -#define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 - -/* Fixed Media Tablet 10.6 inch descriptor */ -static __u8 media_tablet_10_6_inch_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x15, 0x01, /* Logical Minimum (1), */ - 0x25, 0x03, /* Logical Maximum (3), */ - 0x75, 0x04, /* Report Size (4), */ - 0x95, 0x01, /* Report Count (1), */ - 0x80, /* Input, */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ - 0x26, 0x50, 0x46, /* Logical Maximum (18000), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ - 0x26, 0xF8, 0x2A, /* Logical Maximum (11000), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x02, /* Usage (Mouse), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x01, /* Report ID (1), */ - 0x09, 0x01, /* Usage (Pointer), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x95, 0x02, /* Report Count (2), */ - 0x15, 0xFF, /* Logical Minimum (-1), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x09, 0x38, /* Usage (Wheel), */ - 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ - 0x0C, 0x00, - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x0C, /* Usage Page (Consumer), */ - 0x09, 0x01, /* Usage (Consumer Control), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x0D, /* Report ID (13), */ - 0x95, 0x01, /* Report Count (1), */ - 0x75, 0x10, /* Report Size (16), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ - 0x09, 0xB6, /* Usage (Scan Previous Track), */ - 0x09, 0xB5, /* Usage (Scan Next Track), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ - 0x15, 0x0C, /* Logical Minimum (12), */ - 0x25, 0x17, /* Logical Maximum (23), */ - 0x75, 0x05, /* Report Size (5), */ - 0x80, /* Input, */ - 0x75, 0x03, /* Report Size (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x20, /* Report Size (32), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0xC0, /* End Collection, */ - 0x09, 0x01, /* Usage (Consumer Control), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x0C, /* Report ID (12), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0xE9, /* Usage (Volume Inc), */ - 0x09, 0xEA, /* Usage (Volume Dec), */ - 0x09, 0xE2, /* Usage (Mute), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x95, 0x35, /* Report Count (53), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0xC0 /* End Collection */ -}; - -/* - * See Media Tablet 14.1 inch description, device and HID report descriptors at - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_14.1%22 - */ - -/* Size of the original report descriptor of Media Tablet 14.1 inch */ -#define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309 - -/* Fixed Media Tablet 14.1 inch descriptor */ -static __u8 media_tablet_14_1_inch_rdesc_fixed[] = { - 0x05, 0x0D, /* Usage Page (Digitizer), */ - 0x09, 0x02, /* Usage (Pen), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x10, /* Report ID (16), */ - 0x09, 0x20, /* Usage (Stylus), */ - 0xA0, /* Collection (Physical), */ - 0x09, 0x42, /* Usage (Tip Switch), */ - 0x09, 0x44, /* Usage (Barrel Switch), */ - 0x09, 0x46, /* Usage (Tablet Pick), */ - 0x15, 0x01, /* Logical Minimum (1), */ - 0x25, 0x03, /* Logical Maximum (3), */ - 0x75, 0x04, /* Report Size (4), */ - 0x95, 0x01, /* Report Count (1), */ - 0x80, /* Input, */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0x32, /* Usage (In Range), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x01, /* Report Count (1), */ - 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x01, /* Report Count (1), */ - 0x14, /* Logical Minimum (0), */ - 0xA4, /* Push, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x65, 0x13, /* Unit (Inch), */ - 0x55, 0xFD, /* Unit Exponent (-3), */ - 0x34, /* Physical Minimum (0), */ - 0x09, 0x30, /* Usage (X), */ - 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ - 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ - 0x81, 0x02, /* Input (Variable), */ - 0x09, 0x31, /* Usage (Y), */ - 0x46, 0x52, 0x1C, /* Physical Maximum (7250), */ - 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ - 0x81, 0x02, /* Input (Variable), */ - 0xB4, /* Pop, */ - 0x09, 0x30, /* Usage (Tip Pressure), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x81, 0x02, /* Input (Variable), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x02, /* Usage (Mouse), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x01, /* Report ID (1), */ - 0x09, 0x01, /* Usage (Pointer), */ - 0xA0, /* Collection (Physical), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x95, 0x02, /* Report Count (2), */ - 0x15, 0xFF, /* Logical Minimum (-1), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x09, 0x38, /* Usage (Wheel), */ - 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ - 0x0C, 0x00, - 0x81, 0x06, /* Input (Variable, Relative), */ - 0xC0, /* End Collection, */ - 0xC0, /* End Collection, */ - 0x05, 0x0C, /* Usage Page (Consumer), */ - 0x09, 0x01, /* Usage (Consumer Control), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x0D, /* Report ID (13), */ - 0x95, 0x01, /* Report Count (1), */ - 0x75, 0x10, /* Report Size (16), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ - 0x09, 0xB6, /* Usage (Scan Previous Track), */ - 0x09, 0xB5, /* Usage (Scan Next Track), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x08, /* Usage (00h), */ - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ - 0x15, 0x0C, /* Logical Minimum (12), */ - 0x25, 0x17, /* Logical Maximum (23), */ - 0x75, 0x05, /* Report Size (5), */ - 0x80, /* Input, */ - 0x75, 0x03, /* Report Size (3), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0x75, 0x20, /* Report Size (32), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0xC0, /* End Collection, */ - 0x09, 0x01, /* Usage (Consumer Control), */ - 0xA1, 0x01, /* Collection (Application), */ - 0x85, 0x0C, /* Report ID (12), */ - 0x75, 0x01, /* Report Size (1), */ - 0x09, 0xE9, /* Usage (Volume Inc), */ - 0x09, 0xEA, /* Usage (Volume Dec), */ - 0x09, 0xE2, /* Usage (Mute), */ - 0x14, /* Logical Minimum (0), */ - 0x25, 0x01, /* Logical Maximum (1), */ - 0x95, 0x03, /* Report Count (3), */ - 0x81, 0x06, /* Input (Variable, Relative), */ - 0x75, 0x05, /* Report Size (5), */ - 0x81, 0x03, /* Input (Constant, Variable), */ - 0xC0 /* End Collection */ -}; - -struct waltop_state { - u8 pressure0; - u8 pressure1; -}; - -static int waltop_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int ret; - struct waltop_state *s; - - s = kzalloc(sizeof(*s), GFP_KERNEL); - if (s == NULL) { - hid_err(hdev, "can't allocate device state\n"); - ret = -ENOMEM; - goto err; - } - - s->pressure0 = 0; - s->pressure1 = 0; - - hid_set_drvdata(hdev, s); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - return 0; -err: - kfree(s); - return ret; -} - -static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - switch (hdev->product) { - case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH: - if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) { - rdesc = slim_tablet_5_8_inch_rdesc_fixed; - *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed); - } - break; - case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH: - if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) { - rdesc = slim_tablet_12_1_inch_rdesc_fixed; - *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed); - } - break; - case USB_DEVICE_ID_WALTOP_Q_PAD: - if (*rsize == Q_PAD_RDESC_ORIG_SIZE) { - rdesc = q_pad_rdesc_fixed; - *rsize = sizeof(q_pad_rdesc_fixed); - } - break; - case USB_DEVICE_ID_WALTOP_PID_0038: - if (*rsize == PID_0038_RDESC_ORIG_SIZE) { - rdesc = pid_0038_rdesc_fixed; - *rsize = sizeof(pid_0038_rdesc_fixed); - } - break; - case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: - if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { - rdesc = media_tablet_10_6_inch_rdesc_fixed; - *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed); - } - break; - case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH: - if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) { - rdesc = media_tablet_14_1_inch_rdesc_fixed; - *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed); - } - break; - } - return rdesc; -} - -static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *data, int size) -{ - /* If this is a pen input report of a tablet with PID 0038 */ - if (hdev->product == USB_DEVICE_ID_WALTOP_PID_0038 && - report->type == HID_INPUT_REPORT && - report->id == 16 && - size == 8) { - struct waltop_state *s = hid_get_drvdata(hdev); - - /* - * Ignore maximum pressure reported when a barrel button is - * pressed. - */ - - /* If a barrel button is pressed */ - if ((data[1] & 0xF) > 1) { - /* Use the last known pressure */ - data[6] = s->pressure0; - data[7] = s->pressure1; - } else { - /* Remember reported pressure */ - s->pressure0 = data[6]; - s->pressure1 = data[7]; - } - } - - return 0; -} - -static void waltop_remove(struct hid_device *hdev) -{ - struct waltop_state *s = hid_get_drvdata(hdev); - - hid_hw_stop(hdev); - kfree(s); -} - -static const struct hid_device_id waltop_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, - USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, - USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, - USB_DEVICE_ID_WALTOP_Q_PAD) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, - USB_DEVICE_ID_WALTOP_PID_0038) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, - USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, - USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, - { } -}; -MODULE_DEVICE_TABLE(hid, waltop_devices); - -static struct hid_driver waltop_driver = { - .name = "waltop", - .id_table = waltop_devices, - .probe = waltop_probe, - .report_fixup = waltop_report_fixup, - .raw_event = waltop_raw_event, - .remove = waltop_remove, -}; - -static int __init waltop_init(void) -{ - return hid_register_driver(&waltop_driver); -} - -static void __exit waltop_exit(void) -{ - hid_unregister_driver(&waltop_driver); -} - -module_init(waltop_init); -module_exit(waltop_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-wiimote-core.c b/ANDROID_3.4.5/drivers/hid/hid-wiimote-core.c deleted file mode 100644 index 84e2fbec..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-wiimote-core.c +++ /dev/null @@ -1,1318 +0,0 @@ -/* - * HID driver for Nintendo Wiimote devices - * Copyright (c) 2011 David Herrmann - */ - -/* - * 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/completion.h> -#include <linux/device.h> -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/leds.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/power_supply.h> -#include <linux/spinlock.h> -#include "hid-ids.h" -#include "hid-wiimote.h" - -enum wiiproto_keys { - WIIPROTO_KEY_LEFT, - WIIPROTO_KEY_RIGHT, - WIIPROTO_KEY_UP, - WIIPROTO_KEY_DOWN, - WIIPROTO_KEY_PLUS, - WIIPROTO_KEY_MINUS, - WIIPROTO_KEY_ONE, - WIIPROTO_KEY_TWO, - WIIPROTO_KEY_A, - WIIPROTO_KEY_B, - WIIPROTO_KEY_HOME, - WIIPROTO_KEY_COUNT -}; - -static __u16 wiiproto_keymap[] = { - KEY_LEFT, /* WIIPROTO_KEY_LEFT */ - KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ - KEY_UP, /* WIIPROTO_KEY_UP */ - KEY_DOWN, /* WIIPROTO_KEY_DOWN */ - KEY_NEXT, /* WIIPROTO_KEY_PLUS */ - KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ - BTN_1, /* WIIPROTO_KEY_ONE */ - BTN_2, /* WIIPROTO_KEY_TWO */ - BTN_A, /* WIIPROTO_KEY_A */ - BTN_B, /* WIIPROTO_KEY_B */ - BTN_MODE, /* WIIPROTO_KEY_HOME */ -}; - -static enum power_supply_property wiimote_battery_props[] = { - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_SCOPE, -}; - -static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, - size_t count) -{ - __u8 *buf; - ssize_t ret; - - if (!hdev->hid_output_raw_report) - return -ENODEV; - - buf = kmemdup(buffer, count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); - - kfree(buf); - return ret; -} - -static void wiimote_worker(struct work_struct *work) -{ - struct wiimote_data *wdata = container_of(work, struct wiimote_data, - worker); - unsigned long flags; - - spin_lock_irqsave(&wdata->qlock, flags); - - while (wdata->head != wdata->tail) { - spin_unlock_irqrestore(&wdata->qlock, flags); - wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data, - wdata->outq[wdata->tail].size); - spin_lock_irqsave(&wdata->qlock, flags); - - wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE; - } - - spin_unlock_irqrestore(&wdata->qlock, flags); -} - -static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, - size_t count) -{ - unsigned long flags; - __u8 newhead; - - if (count > HID_MAX_BUFFER_SIZE) { - hid_warn(wdata->hdev, "Sending too large output report\n"); - return; - } - - /* - * Copy new request into our output queue and check whether the - * queue is full. If it is full, discard this request. - * If it is empty we need to start a new worker that will - * send out the buffer to the hid device. - * If the queue is not empty, then there must be a worker - * that is currently sending out our buffer and this worker - * will reschedule itself until the queue is empty. - */ - - spin_lock_irqsave(&wdata->qlock, flags); - - memcpy(wdata->outq[wdata->head].data, buffer, count); - wdata->outq[wdata->head].size = count; - newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE; - - if (wdata->head == wdata->tail) { - wdata->head = newhead; - schedule_work(&wdata->worker); - } else if (newhead != wdata->tail) { - wdata->head = newhead; - } else { - hid_warn(wdata->hdev, "Output queue is full"); - } - - spin_unlock_irqrestore(&wdata->qlock, flags); -} - -/* - * This sets the rumble bit on the given output report if rumble is - * currently enabled. - * \cmd1 must point to the second byte in the output report => &cmd[1] - * This must be called on nearly every output report before passing it - * into the output queue! - */ -static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1) -{ - if (wdata->state.flags & WIIPROTO_FLAG_RUMBLE) - *cmd1 |= 0x01; -} - -static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) -{ - __u8 cmd[2]; - - rumble = !!rumble; - if (rumble == !!(wdata->state.flags & WIIPROTO_FLAG_RUMBLE)) - return; - - if (rumble) - wdata->state.flags |= WIIPROTO_FLAG_RUMBLE; - else - wdata->state.flags &= ~WIIPROTO_FLAG_RUMBLE; - - cmd[0] = WIIPROTO_REQ_RUMBLE; - cmd[1] = 0; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) -{ - __u8 cmd[2]; - - leds &= WIIPROTO_FLAGS_LEDS; - if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds) - return; - wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds; - - cmd[0] = WIIPROTO_REQ_LED; - cmd[1] = 0; - - if (leds & WIIPROTO_FLAG_LED1) - cmd[1] |= 0x10; - if (leds & WIIPROTO_FLAG_LED2) - cmd[1] |= 0x20; - if (leds & WIIPROTO_FLAG_LED3) - cmd[1] |= 0x40; - if (leds & WIIPROTO_FLAG_LED4) - cmd[1] |= 0x80; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -/* - * Check what peripherals of the wiimote are currently - * active and select a proper DRM that supports all of - * the requested data inputs. - */ -static __u8 select_drm(struct wiimote_data *wdata) -{ - __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; - bool ext = wiiext_active(wdata); - - if (ir == WIIPROTO_FLAG_IR_BASIC) { - if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) - return WIIPROTO_REQ_DRM_KAIE; - else - return WIIPROTO_REQ_DRM_KIE; - } else if (ir == WIIPROTO_FLAG_IR_EXT) { - return WIIPROTO_REQ_DRM_KAI; - } else if (ir == WIIPROTO_FLAG_IR_FULL) { - return WIIPROTO_REQ_DRM_SKAI1; - } else { - if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { - if (ext) - return WIIPROTO_REQ_DRM_KAE; - else - return WIIPROTO_REQ_DRM_KA; - } else { - if (ext) - return WIIPROTO_REQ_DRM_KE; - else - return WIIPROTO_REQ_DRM_K; - } - } -} - -void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) -{ - __u8 cmd[3]; - - if (drm == WIIPROTO_REQ_NULL) - drm = select_drm(wdata); - - cmd[0] = WIIPROTO_REQ_DRM; - cmd[1] = 0; - cmd[2] = drm; - - wdata->state.drm = drm; - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -static void wiiproto_req_status(struct wiimote_data *wdata) -{ - __u8 cmd[2]; - - cmd[0] = WIIPROTO_REQ_SREQ; - cmd[1] = 0; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) -{ - accel = !!accel; - if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) - return; - - if (accel) - wdata->state.flags |= WIIPROTO_FLAG_ACCEL; - else - wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL; - - wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); -} - -static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) -{ - __u8 cmd[2]; - - cmd[0] = WIIPROTO_REQ_IR1; - cmd[1] = flags; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) -{ - __u8 cmd[2]; - - cmd[0] = WIIPROTO_REQ_IR2; - cmd[1] = flags; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -#define wiiproto_req_wreg(wdata, os, buf, sz) \ - wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) - -#define wiiproto_req_weeprom(wdata, os, buf, sz) \ - wiiproto_req_wmem((wdata), true, (os), (buf), (sz)) - -static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom, - __u32 offset, const __u8 *buf, __u8 size) -{ - __u8 cmd[22]; - - if (size > 16 || size == 0) { - hid_warn(wdata->hdev, "Invalid length %d wmem request\n", size); - return; - } - - memset(cmd, 0, sizeof(cmd)); - cmd[0] = WIIPROTO_REQ_WMEM; - cmd[2] = (offset >> 16) & 0xff; - cmd[3] = (offset >> 8) & 0xff; - cmd[4] = offset & 0xff; - cmd[5] = size; - memcpy(&cmd[6], buf, size); - - if (!eeprom) - cmd[1] |= 0x04; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, __u32 offset, - __u16 size) -{ - __u8 cmd[7]; - - if (size == 0) { - hid_warn(wdata->hdev, "Invalid length %d rmem request\n", size); - return; - } - - cmd[0] = WIIPROTO_REQ_RMEM; - cmd[1] = 0; - cmd[2] = (offset >> 16) & 0xff; - cmd[3] = (offset >> 8) & 0xff; - cmd[4] = offset & 0xff; - cmd[5] = (size >> 8) & 0xff; - cmd[6] = size & 0xff; - - if (!eeprom) - cmd[1] |= 0x04; - - wiiproto_keep_rumble(wdata, &cmd[1]); - wiimote_queue(wdata, cmd, sizeof(cmd)); -} - -/* requries the cmd-mutex to be held */ -int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, - const __u8 *wmem, __u8 size) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&wdata->state.lock, flags); - wiimote_cmd_set(wdata, WIIPROTO_REQ_WMEM, 0); - wiiproto_req_wreg(wdata, offset, wmem, size); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_wait(wdata); - if (!ret && wdata->state.cmd_err) - ret = -EIO; - - return ret; -} - -/* requries the cmd-mutex to be held */ -ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem, - __u8 size) -{ - unsigned long flags; - ssize_t ret; - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->state.cmd_read_size = size; - wdata->state.cmd_read_buf = rmem; - wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, offset & 0xffff); - wiiproto_req_rreg(wdata, offset, size); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_wait(wdata); - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->state.cmd_read_buf = NULL; - spin_unlock_irqrestore(&wdata->state.lock, flags); - - if (!ret) { - if (wdata->state.cmd_read_size == 0) - ret = -EIO; - else - ret = wdata->state.cmd_read_size; - } - - return ret; -} - -static int wiimote_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct wiimote_data *wdata = container_of(psy, - struct wiimote_data, battery); - int ret = 0, state; - unsigned long flags; - - if (psp == POWER_SUPPLY_PROP_SCOPE) { - val->intval = POWER_SUPPLY_SCOPE_DEVICE; - return 0; - } - - ret = wiimote_cmd_acquire(wdata); - if (ret) - return ret; - - spin_lock_irqsave(&wdata->state.lock, flags); - wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); - wiiproto_req_status(wdata); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_wait(wdata); - state = wdata->state.cmd_battery; - wiimote_cmd_release(wdata); - - if (ret) - return ret; - - switch (psp) { - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = state * 100 / 255; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) -{ - int ret; - unsigned long flags; - __u8 format = 0; - static const __u8 data_enable[] = { 0x01 }; - static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, - 0x00, 0xaa, 0x00, 0x64 }; - static const __u8 data_sens2[] = { 0x63, 0x03 }; - static const __u8 data_fin[] = { 0x08 }; - - spin_lock_irqsave(&wdata->state.lock, flags); - - if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { - spin_unlock_irqrestore(&wdata->state.lock, flags); - return 0; - } - - if (mode == 0) { - wdata->state.flags &= ~WIIPROTO_FLAGS_IR; - wiiproto_req_ir1(wdata, 0); - wiiproto_req_ir2(wdata, 0); - wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); - spin_unlock_irqrestore(&wdata->state.lock, flags); - return 0; - } - - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_acquire(wdata); - if (ret) - return ret; - - /* send PIXEL CLOCK ENABLE cmd first */ - spin_lock_irqsave(&wdata->state.lock, flags); - wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); - wiiproto_req_ir1(wdata, 0x06); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_wait(wdata); - if (ret) - goto unlock; - if (wdata->state.cmd_err) { - ret = -EIO; - goto unlock; - } - - /* enable IR LOGIC */ - spin_lock_irqsave(&wdata->state.lock, flags); - wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); - wiiproto_req_ir2(wdata, 0x06); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_wait(wdata); - if (ret) - goto unlock; - if (wdata->state.cmd_err) { - ret = -EIO; - goto unlock; - } - - /* enable IR cam but do not make it send data, yet */ - ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, - sizeof(data_enable)); - if (ret) - goto unlock; - - /* write first sensitivity block */ - ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, - sizeof(data_sens1)); - if (ret) - goto unlock; - - /* write second sensitivity block */ - ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, - sizeof(data_sens2)); - if (ret) - goto unlock; - - /* put IR cam into desired state */ - switch (mode) { - case WIIPROTO_FLAG_IR_FULL: - format = 5; - break; - case WIIPROTO_FLAG_IR_EXT: - format = 3; - break; - case WIIPROTO_FLAG_IR_BASIC: - format = 1; - break; - } - ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); - if (ret) - goto unlock; - - /* make IR cam send data */ - ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); - if (ret) - goto unlock; - - /* request new DRM mode compatible to IR mode */ - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->state.flags &= ~WIIPROTO_FLAGS_IR; - wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; - wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); - spin_unlock_irqrestore(&wdata->state.lock, flags); - -unlock: - wiimote_cmd_release(wdata); - return ret; -} - -static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) -{ - struct wiimote_data *wdata; - struct device *dev = led_dev->dev->parent; - int i; - unsigned long flags; - bool value = false; - - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i] == led_dev) { - spin_lock_irqsave(&wdata->state.lock, flags); - value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); - spin_unlock_irqrestore(&wdata->state.lock, flags); - break; - } - } - - return value ? LED_FULL : LED_OFF; -} - -static void wiimote_leds_set(struct led_classdev *led_dev, - enum led_brightness value) -{ - struct wiimote_data *wdata; - struct device *dev = led_dev->dev->parent; - int i; - unsigned long flags; - __u8 state, flag; - - wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i] == led_dev) { - flag = WIIPROTO_FLAG_LED(i + 1); - spin_lock_irqsave(&wdata->state.lock, flags); - state = wdata->state.flags; - if (value == LED_OFF) - wiiproto_req_leds(wdata, state & ~flag); - else - wiiproto_req_leds(wdata, state | flag); - spin_unlock_irqrestore(&wdata->state.lock, flags); - break; - } - } -} - -static int wiimote_ff_play(struct input_dev *dev, void *data, - struct ff_effect *eff) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - __u8 value; - unsigned long flags; - - /* - * The wiimote supports only a single rumble motor so if any magnitude - * is set to non-zero then we start the rumble motor. If both are set to - * zero, we stop the rumble motor. - */ - - if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) - value = 1; - else - value = 0; - - spin_lock_irqsave(&wdata->state.lock, flags); - wiiproto_req_rumble(wdata, value); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - return 0; -} - -static int wiimote_input_open(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - - return hid_hw_open(wdata->hdev); -} - -static void wiimote_input_close(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - - hid_hw_close(wdata->hdev); -} - -static int wiimote_accel_open(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - int ret; - unsigned long flags; - - ret = hid_hw_open(wdata->hdev); - if (ret) - return ret; - - spin_lock_irqsave(&wdata->state.lock, flags); - wiiproto_req_accel(wdata, true); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - return 0; -} - -static void wiimote_accel_close(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - unsigned long flags; - - spin_lock_irqsave(&wdata->state.lock, flags); - wiiproto_req_accel(wdata, false); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - hid_hw_close(wdata->hdev); -} - -static int wiimote_ir_open(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - int ret; - - ret = hid_hw_open(wdata->hdev); - if (ret) - return ret; - - ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC); - if (ret) { - hid_hw_close(wdata->hdev); - return ret; - } - - return 0; -} - -static void wiimote_ir_close(struct input_dev *dev) -{ - struct wiimote_data *wdata = input_get_drvdata(dev); - - wiimote_init_ir(wdata, 0); - hid_hw_close(wdata->hdev); -} - -static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) -{ - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], - !!(payload[0] & 0x01)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT], - !!(payload[0] & 0x02)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN], - !!(payload[0] & 0x04)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP], - !!(payload[0] & 0x08)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS], - !!(payload[0] & 0x10)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO], - !!(payload[1] & 0x01)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE], - !!(payload[1] & 0x02)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B], - !!(payload[1] & 0x04)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A], - !!(payload[1] & 0x08)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS], - !!(payload[1] & 0x10)); - input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME], - !!(payload[1] & 0x80)); - input_sync(wdata->input); -} - -static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) -{ - __u16 x, y, z; - - if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) - return; - - /* - * payload is: BB BB XX YY ZZ - * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ - * contain the upper 8 bits of each value. The lower 2 bits are - * contained in the buttons data BB BB. - * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the - * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y - * accel value and bit 6 is the second bit of the Z value. - * The first bit of Y and Z values is not available and always set to 0. - * 0x200 is returned on no movement. - */ - - x = payload[2] << 2; - y = payload[3] << 2; - z = payload[4] << 2; - - x |= (payload[0] >> 5) & 0x3; - y |= (payload[1] >> 4) & 0x2; - z |= (payload[1] >> 5) & 0x2; - - input_report_abs(wdata->accel, ABS_RX, x - 0x200); - input_report_abs(wdata->accel, ABS_RY, y - 0x200); - input_report_abs(wdata->accel, ABS_RZ, z - 0x200); - input_sync(wdata->accel); -} - -#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ - ABS_HAT0X, ABS_HAT0Y) -#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ - ABS_HAT1X, ABS_HAT1Y) -#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ - ABS_HAT2X, ABS_HAT2Y) -#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ - ABS_HAT3X, ABS_HAT3Y) - -static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, - bool packed, __u8 xid, __u8 yid) -{ - __u16 x, y; - - if (!(wdata->state.flags & WIIPROTO_FLAGS_IR)) - return; - - /* - * Basic IR data is encoded into 3 bytes. The first two bytes are the - * lower 8 bit of the X/Y data, the 3rd byte contains the upper 2 bits - * of both. - * If data is packed, then the 3rd byte is put first and slightly - * reordered. This allows to interleave packed and non-packed data to - * have two IR sets in 5 bytes instead of 6. - * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev. - */ - - if (packed) { - x = ir[1] | ((ir[0] & 0x03) << 8); - y = ir[2] | ((ir[0] & 0x0c) << 6); - } else { - x = ir[0] | ((ir[2] & 0x30) << 4); - y = ir[1] | ((ir[2] & 0xc0) << 2); - } - - input_report_abs(wdata->ir, xid, x); - input_report_abs(wdata->ir, yid, y); -} - -static void handler_status(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - - /* on status reports the drm is reset so we need to resend the drm */ - wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); - - wiiext_event(wdata, payload[2] & 0x02); - - if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { - wdata->state.cmd_battery = payload[5]; - wiimote_cmd_complete(wdata); - } -} - -static void handler_data(struct wiimote_data *wdata, const __u8 *payload) -{ - __u16 offset = payload[3] << 8 | payload[4]; - __u8 size = (payload[2] >> 4) + 1; - __u8 err = payload[2] & 0x0f; - - handler_keys(wdata, payload); - - if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_RMEM, offset)) { - if (err) - size = 0; - else if (size > wdata->state.cmd_read_size) - size = wdata->state.cmd_read_size; - - wdata->state.cmd_read_size = size; - if (wdata->state.cmd_read_buf) - memcpy(wdata->state.cmd_read_buf, &payload[5], size); - wiimote_cmd_complete(wdata); - } -} - -static void handler_return(struct wiimote_data *wdata, const __u8 *payload) -{ - __u8 err = payload[3]; - __u8 cmd = payload[2]; - - handler_keys(wdata, payload); - - if (wiimote_cmd_pending(wdata, cmd, 0)) { - wdata->state.cmd_err = err; - wiimote_cmd_complete(wdata); - } else if (err) { - hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err, - cmd); - } -} - -static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - handler_accel(wdata, payload); -} - -static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - wiiext_handle(wdata, &payload[2]); -} - -static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - handler_accel(wdata, payload); - ir_to_input0(wdata, &payload[5], false); - ir_to_input1(wdata, &payload[8], false); - ir_to_input2(wdata, &payload[11], false); - ir_to_input3(wdata, &payload[14], false); - input_sync(wdata->ir); -} - -static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - wiiext_handle(wdata, &payload[2]); -} - -static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - ir_to_input0(wdata, &payload[2], false); - ir_to_input1(wdata, &payload[4], true); - ir_to_input2(wdata, &payload[7], false); - ir_to_input3(wdata, &payload[9], true); - input_sync(wdata->ir); - wiiext_handle(wdata, &payload[12]); -} - -static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - handler_accel(wdata, payload); - wiiext_handle(wdata, &payload[5]); -} - -static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - handler_accel(wdata, payload); - ir_to_input0(wdata, &payload[5], false); - ir_to_input1(wdata, &payload[7], true); - ir_to_input2(wdata, &payload[10], false); - ir_to_input3(wdata, &payload[12], true); - input_sync(wdata->ir); - wiiext_handle(wdata, &payload[15]); -} - -static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) -{ - wiiext_handle(wdata, payload); -} - -static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) -{ - handler_keys(wdata, payload); - - wdata->state.accel_split[0] = payload[2]; - wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20); - wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80); - - ir_to_input0(wdata, &payload[3], false); - ir_to_input1(wdata, &payload[12], false); - input_sync(wdata->ir); -} - -static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) -{ - __u8 buf[5]; - - handler_keys(wdata, payload); - - wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02); - wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08); - - buf[0] = 0; - buf[1] = 0; - buf[2] = wdata->state.accel_split[0]; - buf[3] = payload[2]; - buf[4] = wdata->state.accel_split[1]; - handler_accel(wdata, buf); - - ir_to_input2(wdata, &payload[3], false); - ir_to_input3(wdata, &payload[12], false); - input_sync(wdata->ir); -} - -struct wiiproto_handler { - __u8 id; - size_t size; - void (*func)(struct wiimote_data *wdata, const __u8 *payload); -}; - -static struct wiiproto_handler handlers[] = { - { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, - { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data }, - { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return }, - { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, - { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA }, - { .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE }, - { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI }, - { .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE }, - { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE }, - { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE }, - { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE }, - { .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E }, - { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 }, - { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 }, - { .id = 0 } -}; - -static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, - u8 *raw_data, int size) -{ - struct wiimote_data *wdata = hid_get_drvdata(hdev); - struct wiiproto_handler *h; - int i; - unsigned long flags; - bool handled = false; - - if (size < 1) - return -EINVAL; - - spin_lock_irqsave(&wdata->state.lock, flags); - - for (i = 0; handlers[i].id; ++i) { - h = &handlers[i]; - if (h->id == raw_data[0] && h->size < size) { - h->func(wdata, &raw_data[1]); - handled = true; - } - } - - if (!handled) - hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0], - size); - - spin_unlock_irqrestore(&wdata->state.lock, flags); - - return 0; -} - -static void wiimote_leds_destroy(struct wiimote_data *wdata) -{ - int i; - struct led_classdev *led; - - for (i = 0; i < 4; ++i) { - if (wdata->leds[i]) { - led = wdata->leds[i]; - wdata->leds[i] = NULL; - led_classdev_unregister(led); - kfree(led); - } - } -} - -static int wiimote_leds_create(struct wiimote_data *wdata) -{ - int i, ret; - struct device *dev = &wdata->hdev->dev; - size_t namesz = strlen(dev_name(dev)) + 9; - struct led_classdev *led; - char *name; - - for (i = 0; i < 4; ++i) { - led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); - if (!led) { - ret = -ENOMEM; - goto err; - } - name = (void*)&led[1]; - snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i); - led->name = name; - led->brightness = 0; - led->max_brightness = 1; - led->brightness_get = wiimote_leds_get; - led->brightness_set = wiimote_leds_set; - - ret = led_classdev_register(dev, led); - if (ret) { - kfree(led); - goto err; - } - wdata->leds[i] = led; - } - - return 0; - -err: - wiimote_leds_destroy(wdata); - return ret; -} - -static struct wiimote_data *wiimote_create(struct hid_device *hdev) -{ - struct wiimote_data *wdata; - int i; - - wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); - if (!wdata) - return NULL; - - wdata->input = input_allocate_device(); - if (!wdata->input) - goto err; - - wdata->hdev = hdev; - hid_set_drvdata(hdev, wdata); - - input_set_drvdata(wdata->input, wdata); - wdata->input->open = wiimote_input_open; - wdata->input->close = wiimote_input_close; - wdata->input->dev.parent = &wdata->hdev->dev; - wdata->input->id.bustype = wdata->hdev->bus; - wdata->input->id.vendor = wdata->hdev->vendor; - wdata->input->id.product = wdata->hdev->product; - wdata->input->id.version = wdata->hdev->version; - wdata->input->name = WIIMOTE_NAME; - - set_bit(EV_KEY, wdata->input->evbit); - for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) - set_bit(wiiproto_keymap[i], wdata->input->keybit); - - set_bit(FF_RUMBLE, wdata->input->ffbit); - if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play)) - goto err_input; - - wdata->accel = input_allocate_device(); - if (!wdata->accel) - goto err_input; - - input_set_drvdata(wdata->accel, wdata); - wdata->accel->open = wiimote_accel_open; - wdata->accel->close = wiimote_accel_close; - wdata->accel->dev.parent = &wdata->hdev->dev; - wdata->accel->id.bustype = wdata->hdev->bus; - wdata->accel->id.vendor = wdata->hdev->vendor; - wdata->accel->id.product = wdata->hdev->product; - wdata->accel->id.version = wdata->hdev->version; - wdata->accel->name = WIIMOTE_NAME " Accelerometer"; - - set_bit(EV_ABS, wdata->accel->evbit); - set_bit(ABS_RX, wdata->accel->absbit); - set_bit(ABS_RY, wdata->accel->absbit); - set_bit(ABS_RZ, wdata->accel->absbit); - input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); - input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); - input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); - - wdata->ir = input_allocate_device(); - if (!wdata->ir) - goto err_ir; - - input_set_drvdata(wdata->ir, wdata); - wdata->ir->open = wiimote_ir_open; - wdata->ir->close = wiimote_ir_close; - wdata->ir->dev.parent = &wdata->hdev->dev; - wdata->ir->id.bustype = wdata->hdev->bus; - wdata->ir->id.vendor = wdata->hdev->vendor; - wdata->ir->id.product = wdata->hdev->product; - wdata->ir->id.version = wdata->hdev->version; - wdata->ir->name = WIIMOTE_NAME " IR"; - - set_bit(EV_ABS, wdata->ir->evbit); - set_bit(ABS_HAT0X, wdata->ir->absbit); - set_bit(ABS_HAT0Y, wdata->ir->absbit); - set_bit(ABS_HAT1X, wdata->ir->absbit); - set_bit(ABS_HAT1Y, wdata->ir->absbit); - set_bit(ABS_HAT2X, wdata->ir->absbit); - set_bit(ABS_HAT2Y, wdata->ir->absbit); - set_bit(ABS_HAT3X, wdata->ir->absbit); - set_bit(ABS_HAT3Y, wdata->ir->absbit); - input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4); - input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4); - - spin_lock_init(&wdata->qlock); - INIT_WORK(&wdata->worker, wiimote_worker); - - spin_lock_init(&wdata->state.lock); - init_completion(&wdata->state.ready); - mutex_init(&wdata->state.sync); - wdata->state.drm = WIIPROTO_REQ_DRM_K; - - return wdata; - -err_ir: - input_free_device(wdata->accel); -err_input: - input_free_device(wdata->input); -err: - kfree(wdata); - return NULL; -} - -static void wiimote_destroy(struct wiimote_data *wdata) -{ - wiidebug_deinit(wdata); - wiiext_deinit(wdata); - wiimote_leds_destroy(wdata); - - power_supply_unregister(&wdata->battery); - input_unregister_device(wdata->accel); - input_unregister_device(wdata->ir); - input_unregister_device(wdata->input); - cancel_work_sync(&wdata->worker); - hid_hw_stop(wdata->hdev); - - kfree(wdata); -} - -static int wiimote_hid_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - struct wiimote_data *wdata; - int ret; - - hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; - - wdata = wiimote_create(hdev); - if (!wdata) { - hid_err(hdev, "Can't alloc device\n"); - return -ENOMEM; - } - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "HID parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); - if (ret) { - hid_err(hdev, "HW start failed\n"); - goto err; - } - - ret = input_register_device(wdata->accel); - if (ret) { - hid_err(hdev, "Cannot register input device\n"); - goto err_stop; - } - - ret = input_register_device(wdata->ir); - if (ret) { - hid_err(hdev, "Cannot register input device\n"); - goto err_ir; - } - - ret = input_register_device(wdata->input); - if (ret) { - hid_err(hdev, "Cannot register input device\n"); - goto err_input; - } - - wdata->battery.properties = wiimote_battery_props; - wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props); - wdata->battery.get_property = wiimote_battery_get_property; - wdata->battery.name = "wiimote_battery"; - wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; - wdata->battery.use_for_apm = 0; - - ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); - if (ret) { - hid_err(hdev, "Cannot register battery device\n"); - goto err_battery; - } - - power_supply_powers(&wdata->battery, &hdev->dev); - - ret = wiimote_leds_create(wdata); - if (ret) - goto err_free; - - ret = wiiext_init(wdata); - if (ret) - goto err_free; - - ret = wiidebug_init(wdata); - if (ret) - goto err_free; - - hid_info(hdev, "New device registered\n"); - - /* by default set led1 after device initialization */ - spin_lock_irq(&wdata->state.lock); - wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); - spin_unlock_irq(&wdata->state.lock); - - return 0; - -err_free: - wiimote_destroy(wdata); - return ret; - -err_battery: - input_unregister_device(wdata->input); - wdata->input = NULL; -err_input: - input_unregister_device(wdata->ir); - wdata->ir = NULL; -err_ir: - input_unregister_device(wdata->accel); - wdata->accel = NULL; -err_stop: - hid_hw_stop(hdev); -err: - input_free_device(wdata->ir); - input_free_device(wdata->accel); - input_free_device(wdata->input); - kfree(wdata); - return ret; -} - -static void wiimote_hid_remove(struct hid_device *hdev) -{ - struct wiimote_data *wdata = hid_get_drvdata(hdev); - - hid_info(hdev, "Device removed\n"); - wiimote_destroy(wdata); -} - -static const struct hid_device_id wiimote_hid_devices[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, - USB_DEVICE_ID_NINTENDO_WIIMOTE) }, - { } -}; -MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); - -static struct hid_driver wiimote_hid_driver = { - .name = "wiimote", - .id_table = wiimote_hid_devices, - .probe = wiimote_hid_probe, - .remove = wiimote_hid_remove, - .raw_event = wiimote_hid_event, -}; - -static int __init wiimote_init(void) -{ - int ret; - - ret = hid_register_driver(&wiimote_hid_driver); - if (ret) - pr_err("Can't register wiimote hid driver\n"); - - return ret; -} - -static void __exit wiimote_exit(void) -{ - hid_unregister_driver(&wiimote_hid_driver); -} - -module_init(wiimote_init); -module_exit(wiimote_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); -MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-wiimote-debug.c b/ANDROID_3.4.5/drivers/hid/hid-wiimote-debug.c deleted file mode 100644 index eec32919..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-wiimote-debug.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Debug support for HID Nintendo Wiimote devices - * Copyright (c) 2011 David Herrmann - */ - -/* - * 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/debugfs.h> -#include <linux/module.h> -#include <linux/seq_file.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> -#include "hid-wiimote.h" - -struct wiimote_debug { - struct wiimote_data *wdata; - struct dentry *eeprom; - struct dentry *drm; -}; - -static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, - loff_t *off) -{ - struct wiimote_debug *dbg = f->private_data; - struct wiimote_data *wdata = dbg->wdata; - unsigned long flags; - ssize_t ret; - char buf[16]; - __u16 size; - - if (s == 0) - return -EINVAL; - if (*off > 0xffffff) - return 0; - if (s > 16) - s = 16; - - ret = wiimote_cmd_acquire(wdata); - if (ret) - return ret; - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->state.cmd_read_size = s; - wdata->state.cmd_read_buf = buf; - wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff); - wiiproto_req_reeprom(wdata, *off, s); - spin_unlock_irqrestore(&wdata->state.lock, flags); - - ret = wiimote_cmd_wait(wdata); - if (!ret) - size = wdata->state.cmd_read_size; - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->state.cmd_read_buf = NULL; - spin_unlock_irqrestore(&wdata->state.lock, flags); - - wiimote_cmd_release(wdata); - - if (ret) - return ret; - else if (size == 0) - return -EIO; - - if (copy_to_user(u, buf, size)) - return -EFAULT; - - *off += size; - ret = size; - - return ret; -} - -static const struct file_operations wiidebug_eeprom_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = wiidebug_eeprom_read, - .llseek = generic_file_llseek, -}; - -static const char *wiidebug_drmmap[] = { - [WIIPROTO_REQ_NULL] = "NULL", - [WIIPROTO_REQ_DRM_K] = "K", - [WIIPROTO_REQ_DRM_KA] = "KA", - [WIIPROTO_REQ_DRM_KE] = "KE", - [WIIPROTO_REQ_DRM_KAI] = "KAI", - [WIIPROTO_REQ_DRM_KEE] = "KEE", - [WIIPROTO_REQ_DRM_KAE] = "KAE", - [WIIPROTO_REQ_DRM_KIE] = "KIE", - [WIIPROTO_REQ_DRM_KAIE] = "KAIE", - [WIIPROTO_REQ_DRM_E] = "E", - [WIIPROTO_REQ_DRM_SKAI1] = "SKAI1", - [WIIPROTO_REQ_DRM_SKAI2] = "SKAI2", - [WIIPROTO_REQ_MAX] = NULL -}; - -static int wiidebug_drm_show(struct seq_file *f, void *p) -{ - struct wiimote_debug *dbg = f->private; - const char *str = NULL; - unsigned long flags; - __u8 drm; - - spin_lock_irqsave(&dbg->wdata->state.lock, flags); - drm = dbg->wdata->state.drm; - spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); - - if (drm < WIIPROTO_REQ_MAX) - str = wiidebug_drmmap[drm]; - if (!str) - str = "unknown"; - - seq_printf(f, "%s\n", str); - - return 0; -} - -static int wiidebug_drm_open(struct inode *i, struct file *f) -{ - return single_open(f, wiidebug_drm_show, i->i_private); -} - -static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, - size_t s, loff_t *off) -{ - struct wiimote_debug *dbg = f->private_data; - unsigned long flags; - char buf[16]; - ssize_t len; - int i; - - if (s == 0) - return -EINVAL; - - len = min((size_t) 15, s); - if (copy_from_user(buf, u, len)) - return -EFAULT; - - buf[15] = 0; - - for (i = 0; i < WIIPROTO_REQ_MAX; ++i) { - if (!wiidebug_drmmap[i]) - continue; - if (!strcasecmp(buf, wiidebug_drmmap[i])) - break; - } - - if (i == WIIPROTO_REQ_MAX) - i = simple_strtoul(buf, NULL, 10); - - spin_lock_irqsave(&dbg->wdata->state.lock, flags); - wiiproto_req_drm(dbg->wdata, (__u8) i); - spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); - - return len; -} - -static const struct file_operations wiidebug_drm_fops = { - .owner = THIS_MODULE, - .open = wiidebug_drm_open, - .read = seq_read, - .llseek = seq_lseek, - .write = wiidebug_drm_write, - .release = single_release, -}; - -int wiidebug_init(struct wiimote_data *wdata) -{ - struct wiimote_debug *dbg; - unsigned long flags; - int ret = -ENOMEM; - - dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); - if (!dbg) - return -ENOMEM; - - dbg->wdata = wdata; - - dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR, - dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops); - if (!dbg->eeprom) - goto err; - - dbg->drm = debugfs_create_file("drm", S_IRUSR, - dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops); - if (!dbg->drm) - goto err_drm; - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->debug = dbg; - spin_unlock_irqrestore(&wdata->state.lock, flags); - - return 0; - -err_drm: - debugfs_remove(dbg->eeprom); -err: - kfree(dbg); - return ret; -} - -void wiidebug_deinit(struct wiimote_data *wdata) -{ - struct wiimote_debug *dbg = wdata->debug; - unsigned long flags; - - if (!dbg) - return; - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->debug = NULL; - spin_unlock_irqrestore(&wdata->state.lock, flags); - - debugfs_remove(dbg->drm); - debugfs_remove(dbg->eeprom); - kfree(dbg); -} diff --git a/ANDROID_3.4.5/drivers/hid/hid-wiimote-ext.c b/ANDROID_3.4.5/drivers/hid/hid-wiimote-ext.c deleted file mode 100644 index aa958706..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-wiimote-ext.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * HID driver for Nintendo Wiimote extension devices - * Copyright (c) 2011 David Herrmann - */ - -/* - * 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/atomic.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/workqueue.h> -#include "hid-wiimote.h" - -struct wiimote_ext { - struct wiimote_data *wdata; - struct work_struct worker; - struct input_dev *input; - struct input_dev *mp_input; - - atomic_t opened; - atomic_t mp_opened; - bool plugged; - bool mp_plugged; - bool motionp; - __u8 ext_type; -}; - -enum wiiext_type { - WIIEXT_NONE, /* placeholder */ - WIIEXT_CLASSIC, /* Nintendo classic controller */ - WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ -}; - -enum wiiext_keys { - WIIEXT_KEY_C, - WIIEXT_KEY_Z, - WIIEXT_KEY_A, - WIIEXT_KEY_B, - WIIEXT_KEY_X, - WIIEXT_KEY_Y, - WIIEXT_KEY_ZL, - WIIEXT_KEY_ZR, - WIIEXT_KEY_PLUS, - WIIEXT_KEY_MINUS, - WIIEXT_KEY_HOME, - WIIEXT_KEY_LEFT, - WIIEXT_KEY_RIGHT, - WIIEXT_KEY_UP, - WIIEXT_KEY_DOWN, - WIIEXT_KEY_LT, - WIIEXT_KEY_RT, - WIIEXT_KEY_COUNT -}; - -static __u16 wiiext_keymap[] = { - BTN_C, /* WIIEXT_KEY_C */ - BTN_Z, /* WIIEXT_KEY_Z */ - BTN_A, /* WIIEXT_KEY_A */ - BTN_B, /* WIIEXT_KEY_B */ - BTN_X, /* WIIEXT_KEY_X */ - BTN_Y, /* WIIEXT_KEY_Y */ - BTN_TL2, /* WIIEXT_KEY_ZL */ - BTN_TR2, /* WIIEXT_KEY_ZR */ - KEY_NEXT, /* WIIEXT_KEY_PLUS */ - KEY_PREVIOUS, /* WIIEXT_KEY_MINUS */ - BTN_MODE, /* WIIEXT_KEY_HOME */ - KEY_LEFT, /* WIIEXT_KEY_LEFT */ - KEY_RIGHT, /* WIIEXT_KEY_RIGHT */ - KEY_UP, /* WIIEXT_KEY_UP */ - KEY_DOWN, /* WIIEXT_KEY_DOWN */ - BTN_TL, /* WIIEXT_KEY_LT */ - BTN_TR, /* WIIEXT_KEY_RT */ -}; - -/* diable all extensions */ -static void ext_disable(struct wiimote_ext *ext) -{ - unsigned long flags; - __u8 wmem = 0x55; - - if (!wiimote_cmd_acquire(ext->wdata)) { - wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); - wiimote_cmd_release(ext->wdata); - } - - spin_lock_irqsave(&ext->wdata->state.lock, flags); - ext->motionp = false; - ext->ext_type = WIIEXT_NONE; - wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); - spin_unlock_irqrestore(&ext->wdata->state.lock, flags); -} - -static bool motionp_read(struct wiimote_ext *ext) -{ - __u8 rmem[2], wmem; - ssize_t ret; - bool avail = false; - - if (!atomic_read(&ext->mp_opened)) - return false; - - if (wiimote_cmd_acquire(ext->wdata)) - return false; - - /* initialize motion plus */ - wmem = 0x55; - ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem)); - if (ret) - goto error; - - /* read motion plus ID */ - ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2); - if (ret == 2 || rmem[1] == 0x5) - avail = true; - -error: - wiimote_cmd_release(ext->wdata); - return avail; -} - -static __u8 ext_read(struct wiimote_ext *ext) -{ - ssize_t ret; - __u8 rmem[2], wmem; - __u8 type = WIIEXT_NONE; - - if (!ext->plugged || !atomic_read(&ext->opened)) - return WIIEXT_NONE; - - if (wiimote_cmd_acquire(ext->wdata)) - return WIIEXT_NONE; - - /* initialize extension */ - wmem = 0x55; - ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); - if (!ret) { - /* disable encryption */ - wmem = 0x0; - wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem)); - } - - /* read extension ID */ - ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2); - if (ret == 2) { - if (rmem[0] == 0 && rmem[1] == 0) - type = WIIEXT_NUNCHUCK; - else if (rmem[0] == 0x01 && rmem[1] == 0x01) - type = WIIEXT_CLASSIC; - } - - wiimote_cmd_release(ext->wdata); - - return type; -} - -static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) -{ - unsigned long flags; - __u8 wmem; - int ret; - - if (motionp) { - if (wiimote_cmd_acquire(ext->wdata)) - return; - - if (ext_type == WIIEXT_CLASSIC) - wmem = 0x07; - else if (ext_type == WIIEXT_NUNCHUCK) - wmem = 0x05; - else - wmem = 0x04; - - ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem)); - wiimote_cmd_release(ext->wdata); - if (ret) - return; - } - - spin_lock_irqsave(&ext->wdata->state.lock, flags); - ext->motionp = motionp; - ext->ext_type = ext_type; - wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); - spin_unlock_irqrestore(&ext->wdata->state.lock, flags); -} - -static void wiiext_worker(struct work_struct *work) -{ - struct wiimote_ext *ext = container_of(work, struct wiimote_ext, - worker); - bool motionp; - __u8 ext_type; - - ext_disable(ext); - motionp = motionp_read(ext); - ext_type = ext_read(ext); - ext_enable(ext, motionp, ext_type); -} - -/* schedule work only once, otherwise mark for reschedule */ -static void wiiext_schedule(struct wiimote_ext *ext) -{ - queue_work(system_nrt_wq, &ext->worker); -} - -/* - * Reacts on extension port events - * Whenever the driver gets an event from the wiimote that an extension has been - * plugged or unplugged, this funtion shall be called. It checks what extensions - * are connected and initializes and activates them. - * This can be called in atomic context. The initialization is done in a - * separate worker thread. The state.lock spinlock must be held by the caller. - */ -void wiiext_event(struct wiimote_data *wdata, bool plugged) -{ - if (!wdata->ext) - return; - - if (wdata->ext->plugged == plugged) - return; - - wdata->ext->plugged = plugged; - - if (!plugged) - wdata->ext->mp_plugged = false; - - /* - * We need to call wiiext_schedule(wdata->ext) here, however, the - * extension initialization logic is not fully understood and so - * automatic initialization is not supported, yet. - */ -} - -/* - * Returns true if the current DRM mode should contain extension data and false - * if there is no interest in extension data. - * All supported extensions send 6 byte extension data so any DRM that contains - * extension bytes is fine. - * The caller must hold the state.lock spinlock. - */ -bool wiiext_active(struct wiimote_data *wdata) -{ - if (!wdata->ext) - return false; - - return wdata->ext->motionp || wdata->ext->ext_type; -} - -static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) -{ - __s32 x, y, z; - bool plugged; - - /* | 8 7 6 5 4 3 | 2 | 1 | - * -----+------------------------------+-----+-----+ - * 1 | Yaw Speed <7:0> | - * 2 | Roll Speed <7:0> | - * 3 | Pitch Speed <7:0> | - * -----+------------------------------+-----+-----+ - * 4 | Yaw Speed <13:8> | Yaw |Pitch| - * -----+------------------------------+-----+-----+ - * 5 | Roll Speed <13:8> |Roll | Ext | - * -----+------------------------------+-----+-----+ - * 6 | Pitch Speed <13:8> | 1 | 0 | - * -----+------------------------------+-----+-----+ - * The single bits Yaw, Roll, Pitch in the lower right corner specify - * whether the wiimote is rotating fast (0) or slow (1). Speed for slow - * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a - * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast - * and 9 for slow. - * If the wiimote is not rotating the sensor reports 2^13 = 8192. - * Ext specifies whether an extension is connected to the motionp. - */ - - x = payload[0]; - y = payload[1]; - z = payload[2]; - - x |= (((__u16)payload[3]) << 6) & 0xff00; - y |= (((__u16)payload[4]) << 6) & 0xff00; - z |= (((__u16)payload[5]) << 6) & 0xff00; - - x -= 8192; - y -= 8192; - z -= 8192; - - if (!(payload[3] & 0x02)) - x *= 18; - else - x *= 9; - if (!(payload[4] & 0x02)) - y *= 18; - else - y *= 9; - if (!(payload[3] & 0x01)) - z *= 18; - else - z *= 9; - - input_report_abs(ext->mp_input, ABS_RX, x); - input_report_abs(ext->mp_input, ABS_RY, y); - input_report_abs(ext->mp_input, ABS_RZ, z); - input_sync(ext->mp_input); - - plugged = payload[5] & 0x01; - if (plugged != ext->mp_plugged) - ext->mp_plugged = plugged; -} - -static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) -{ - __s16 x, y, z, bx, by; - - /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 | - * -----+----------+---------+---------+----+-----+ - * 1 | Button X <7:0> | - * 2 | Button Y <7:0> | - * -----+----------+---------+---------+----+-----+ - * 3 | Speed X <9:2> | - * 4 | Speed Y <9:2> | - * 5 | Speed Z <9:2> | - * -----+----------+---------+---------+----+-----+ - * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ | - * -----+----------+---------+---------+----+-----+ - * Button X/Y is the analog stick. Speed X, Y and Z are the - * accelerometer data in the same format as the wiimote's accelerometer. - * The 6th byte contains the LSBs of the accelerometer data. - * BC and BZ are the C and Z buttons: 0 means pressed - * - * If reported interleaved with motionp, then the layout changes. The - * 5th and 6th byte changes to: - * -----+-----------------------------------+-----+ - * 5 | Speed Z <9:3> | EXT | - * -----+--------+-----+-----+----+----+----+-----+ - * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 | - * -----+--------+-----+-----+----+----+----+-----+ - * All three accelerometer values lose their LSB. The other data is - * still available but slightly moved. - * - * Center data for button values is 128. Center value for accelerometer - * values it 512 / 0x200 - */ - - bx = payload[0]; - by = payload[1]; - bx -= 128; - by -= 128; - - x = payload[2] << 2; - y = payload[3] << 2; - z = payload[4] << 2; - - if (ext->motionp) { - x |= (payload[5] >> 3) & 0x02; - y |= (payload[5] >> 4) & 0x02; - z &= ~0x4; - z |= (payload[5] >> 5) & 0x06; - } else { - x |= (payload[5] >> 2) & 0x03; - y |= (payload[5] >> 4) & 0x03; - z |= (payload[5] >> 6) & 0x03; - } - - x -= 0x200; - y -= 0x200; - z -= 0x200; - - input_report_abs(ext->input, ABS_HAT0X, bx); - input_report_abs(ext->input, ABS_HAT0Y, by); - - input_report_abs(ext->input, ABS_RX, x); - input_report_abs(ext->input, ABS_RY, y); - input_report_abs(ext->input, ABS_RZ, z); - - if (ext->motionp) { - input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04)); - input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08)); - } else { - input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01)); - input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02)); - } - - input_sync(ext->input); -} - -static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) -{ - __s8 rx, ry, lx, ly, lt, rt; - - /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * 1 | RX <5:4> | LX <5:0> | - * 2 | RX <3:2> | LY <5:0> | - * -----+-----+-----+-----+-----------------------------+ - * 3 |RX<1>| LT <5:4> | RY <5:1> | - * -----+-----+-----------+-----------------------------+ - * 4 | LT <3:1> | RT <5:1> | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * All buttons are 0 if pressed - * RX and RY are right analog stick - * LX and LY are left analog stick - * LT is left trigger, RT is right trigger - * BLT is 0 if left trigger is fully pressed - * BRT is 0 if right trigger is fully pressed - * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons - * BZL is left Z button and BZR is right Z button - * B-, BH, B+ are +, HOME and - buttons - * BB, BY, BA, BX are A, B, X, Y buttons - * LSB of RX, RY, LT, and RT are not transmitted and always 0. - * - * With motionp enabled it changes slightly to this: - * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * 1 | RX <4:3> | LX <5:1> | BDU | - * 2 | RX <2:1> | LY <5:1> | BDL | - * -----+-----+-----+-----+-----------------------+-----+ - * 3 |RX<0>| LT <4:3> | RY <4:0> | - * -----+-----+-----------+-----------------------------+ - * 4 | LT <2:0> | RT <4:0> | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 | - * -----+-----+-----+-----+-----+-----+-----+-----+-----+ - * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest - * is the same as before. - */ - - if (ext->motionp) { - lx = payload[0] & 0x3e; - ly = payload[0] & 0x3e; - } else { - lx = payload[0] & 0x3f; - ly = payload[0] & 0x3f; - } - - rx = (payload[0] >> 3) & 0x14; - rx |= (payload[1] >> 5) & 0x06; - rx |= (payload[2] >> 7) & 0x01; - ry = payload[2] & 0x1f; - - rt = payload[3] & 0x1f; - lt = (payload[2] >> 2) & 0x18; - lt |= (payload[3] >> 5) & 0x07; - - rx <<= 1; - ry <<= 1; - rt <<= 1; - lt <<= 1; - - input_report_abs(ext->input, ABS_HAT1X, lx - 0x20); - input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20); - input_report_abs(ext->input, ABS_HAT2X, rx - 0x20); - input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20); - input_report_abs(ext->input, ABS_HAT3X, rt - 0x20); - input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20); - - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT], - !!(payload[4] & 0x80)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN], - !!(payload[4] & 0x40)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT], - !!(payload[4] & 0x20)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS], - !!(payload[4] & 0x10)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME], - !!(payload[4] & 0x08)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS], - !!(payload[4] & 0x04)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT], - !!(payload[4] & 0x02)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL], - !!(payload[5] & 0x80)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B], - !!(payload[5] & 0x40)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y], - !!(payload[5] & 0x20)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A], - !!(payload[5] & 0x10)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X], - !!(payload[5] & 0x08)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR], - !!(payload[5] & 0x04)); - - if (ext->motionp) { - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], - !!(payload[0] & 0x01)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], - !!(payload[1] & 0x01)); - } else { - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], - !!(payload[5] & 0x01)); - input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], - !!(payload[5] & 0x02)); - } - - input_sync(ext->input); -} - -/* call this with state.lock spinlock held */ -void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) -{ - struct wiimote_ext *ext = wdata->ext; - - if (!ext) - return; - - if (ext->motionp && (payload[5] & 0x02)) { - handler_motionp(ext, payload); - } else if (ext->ext_type == WIIEXT_NUNCHUCK) { - handler_nunchuck(ext, payload); - } else if (ext->ext_type == WIIEXT_CLASSIC) { - handler_classic(ext, payload); - } -} - -static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct wiimote_data *wdata = dev_to_wii(dev); - __u8 type = WIIEXT_NONE; - bool motionp = false; - unsigned long flags; - - spin_lock_irqsave(&wdata->state.lock, flags); - if (wdata->ext) { - motionp = wdata->ext->motionp; - type = wdata->ext->ext_type; - } - spin_unlock_irqrestore(&wdata->state.lock, flags); - - if (type == WIIEXT_NUNCHUCK) { - if (motionp) - return sprintf(buf, "motionp+nunchuck\n"); - else - return sprintf(buf, "nunchuck\n"); - } else if (type == WIIEXT_CLASSIC) { - if (motionp) - return sprintf(buf, "motionp+classic\n"); - else - return sprintf(buf, "classic\n"); - } else { - if (motionp) - return sprintf(buf, "motionp\n"); - else - return sprintf(buf, "none\n"); - } -} - -static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL); - -static int wiiext_input_open(struct input_dev *dev) -{ - struct wiimote_ext *ext = input_get_drvdata(dev); - int ret; - - ret = hid_hw_open(ext->wdata->hdev); - if (ret) - return ret; - - atomic_inc(&ext->opened); - wiiext_schedule(ext); - - return 0; -} - -static void wiiext_input_close(struct input_dev *dev) -{ - struct wiimote_ext *ext = input_get_drvdata(dev); - - atomic_dec(&ext->opened); - wiiext_schedule(ext); - hid_hw_close(ext->wdata->hdev); -} - -static int wiiext_mp_open(struct input_dev *dev) -{ - struct wiimote_ext *ext = input_get_drvdata(dev); - int ret; - - ret = hid_hw_open(ext->wdata->hdev); - if (ret) - return ret; - - atomic_inc(&ext->mp_opened); - wiiext_schedule(ext); - - return 0; -} - -static void wiiext_mp_close(struct input_dev *dev) -{ - struct wiimote_ext *ext = input_get_drvdata(dev); - - atomic_dec(&ext->mp_opened); - wiiext_schedule(ext); - hid_hw_close(ext->wdata->hdev); -} - -/* Initializes the extension driver of a wiimote */ -int wiiext_init(struct wiimote_data *wdata) -{ - struct wiimote_ext *ext; - unsigned long flags; - int ret, i; - - ext = kzalloc(sizeof(*ext), GFP_KERNEL); - if (!ext) - return -ENOMEM; - - ext->wdata = wdata; - INIT_WORK(&ext->worker, wiiext_worker); - - ext->input = input_allocate_device(); - if (!ext->input) { - ret = -ENOMEM; - goto err_input; - } - - input_set_drvdata(ext->input, ext); - ext->input->open = wiiext_input_open; - ext->input->close = wiiext_input_close; - ext->input->dev.parent = &wdata->hdev->dev; - ext->input->id.bustype = wdata->hdev->bus; - ext->input->id.vendor = wdata->hdev->vendor; - ext->input->id.product = wdata->hdev->product; - ext->input->id.version = wdata->hdev->version; - ext->input->name = WIIMOTE_NAME " Extension"; - - set_bit(EV_KEY, ext->input->evbit); - for (i = 0; i < WIIEXT_KEY_COUNT; ++i) - set_bit(wiiext_keymap[i], ext->input->keybit); - - set_bit(EV_ABS, ext->input->evbit); - set_bit(ABS_HAT0X, ext->input->absbit); - set_bit(ABS_HAT0Y, ext->input->absbit); - set_bit(ABS_HAT1X, ext->input->absbit); - set_bit(ABS_HAT1Y, ext->input->absbit); - set_bit(ABS_HAT2X, ext->input->absbit); - set_bit(ABS_HAT2Y, ext->input->absbit); - set_bit(ABS_HAT3X, ext->input->absbit); - set_bit(ABS_HAT3Y, ext->input->absbit); - input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4); - input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4); - input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1); - input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1); - input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1); - input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1); - input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1); - input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1); - set_bit(ABS_RX, ext->input->absbit); - set_bit(ABS_RY, ext->input->absbit); - set_bit(ABS_RZ, ext->input->absbit); - input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4); - input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4); - input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4); - - ret = input_register_device(ext->input); - if (ret) { - input_free_device(ext->input); - goto err_input; - } - - ext->mp_input = input_allocate_device(); - if (!ext->mp_input) { - ret = -ENOMEM; - goto err_mp; - } - - input_set_drvdata(ext->mp_input, ext); - ext->mp_input->open = wiiext_mp_open; - ext->mp_input->close = wiiext_mp_close; - ext->mp_input->dev.parent = &wdata->hdev->dev; - ext->mp_input->id.bustype = wdata->hdev->bus; - ext->mp_input->id.vendor = wdata->hdev->vendor; - ext->mp_input->id.product = wdata->hdev->product; - ext->mp_input->id.version = wdata->hdev->version; - ext->mp_input->name = WIIMOTE_NAME " Motion+"; - - set_bit(EV_ABS, ext->mp_input->evbit); - set_bit(ABS_RX, ext->mp_input->absbit); - set_bit(ABS_RY, ext->mp_input->absbit); - set_bit(ABS_RZ, ext->mp_input->absbit); - input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8); - input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8); - input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8); - - ret = input_register_device(ext->mp_input); - if (ret) { - input_free_device(ext->mp_input); - goto err_mp; - } - - ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension); - if (ret) - goto err_dev; - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->ext = ext; - spin_unlock_irqrestore(&wdata->state.lock, flags); - - return 0; - -err_dev: - input_unregister_device(ext->mp_input); -err_mp: - input_unregister_device(ext->input); -err_input: - kfree(ext); - return ret; -} - -/* Deinitializes the extension driver of a wiimote */ -void wiiext_deinit(struct wiimote_data *wdata) -{ - struct wiimote_ext *ext = wdata->ext; - unsigned long flags; - - if (!ext) - return; - - /* - * We first unset wdata->ext to avoid further input from the wiimote - * core. The worker thread does not access this pointer so it is not - * affected by this. - * We kill the worker after this so it does not get respawned during - * deinitialization. - */ - - spin_lock_irqsave(&wdata->state.lock, flags); - wdata->ext = NULL; - spin_unlock_irqrestore(&wdata->state.lock, flags); - - device_remove_file(&wdata->hdev->dev, &dev_attr_extension); - input_unregister_device(ext->mp_input); - input_unregister_device(ext->input); - - cancel_work_sync(&ext->worker); - kfree(ext); -} diff --git a/ANDROID_3.4.5/drivers/hid/hid-wiimote.h b/ANDROID_3.4.5/drivers/hid/hid-wiimote.h deleted file mode 100644 index c81dbeb0..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-wiimote.h +++ /dev/null @@ -1,208 +0,0 @@ -#ifndef __HID_WIIMOTE_H -#define __HID_WIIMOTE_H - -/* - * HID driver for Nintendo Wiimote devices - * Copyright (c) 2011 David Herrmann - */ - -/* - * 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/completion.h> -#include <linux/device.h> -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/leds.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/power_supply.h> -#include <linux/spinlock.h> - -#define WIIMOTE_NAME "Nintendo Wii Remote" -#define WIIMOTE_BUFSIZE 32 - -#define WIIPROTO_FLAG_LED1 0x01 -#define WIIPROTO_FLAG_LED2 0x02 -#define WIIPROTO_FLAG_LED3 0x04 -#define WIIPROTO_FLAG_LED4 0x08 -#define WIIPROTO_FLAG_RUMBLE 0x10 -#define WIIPROTO_FLAG_ACCEL 0x20 -#define WIIPROTO_FLAG_IR_BASIC 0x40 -#define WIIPROTO_FLAG_IR_EXT 0x80 -#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ -#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ - WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) -#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ - WIIPROTO_FLAG_IR_FULL) - -/* return flag for led \num */ -#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) - -struct wiimote_buf { - __u8 data[HID_MAX_BUFFER_SIZE]; - size_t size; -}; - -struct wiimote_state { - spinlock_t lock; - __u8 flags; - __u8 accel_split[2]; - __u8 drm; - - /* synchronous cmd requests */ - struct mutex sync; - struct completion ready; - int cmd; - __u32 opt; - - /* results of synchronous requests */ - __u8 cmd_battery; - __u8 cmd_err; - __u8 *cmd_read_buf; - __u8 cmd_read_size; -}; - -struct wiimote_data { - struct hid_device *hdev; - struct input_dev *input; - struct led_classdev *leds[4]; - struct input_dev *accel; - struct input_dev *ir; - struct power_supply battery; - struct wiimote_ext *ext; - struct wiimote_debug *debug; - - spinlock_t qlock; - __u8 head; - __u8 tail; - struct wiimote_buf outq[WIIMOTE_BUFSIZE]; - struct work_struct worker; - - struct wiimote_state state; -}; - -enum wiiproto_reqs { - WIIPROTO_REQ_NULL = 0x0, - WIIPROTO_REQ_RUMBLE = 0x10, - WIIPROTO_REQ_LED = 0x11, - WIIPROTO_REQ_DRM = 0x12, - WIIPROTO_REQ_IR1 = 0x13, - WIIPROTO_REQ_SREQ = 0x15, - WIIPROTO_REQ_WMEM = 0x16, - WIIPROTO_REQ_RMEM = 0x17, - WIIPROTO_REQ_IR2 = 0x1a, - WIIPROTO_REQ_STATUS = 0x20, - WIIPROTO_REQ_DATA = 0x21, - WIIPROTO_REQ_RETURN = 0x22, - WIIPROTO_REQ_DRM_K = 0x30, - WIIPROTO_REQ_DRM_KA = 0x31, - WIIPROTO_REQ_DRM_KE = 0x32, - WIIPROTO_REQ_DRM_KAI = 0x33, - WIIPROTO_REQ_DRM_KEE = 0x34, - WIIPROTO_REQ_DRM_KAE = 0x35, - WIIPROTO_REQ_DRM_KIE = 0x36, - WIIPROTO_REQ_DRM_KAIE = 0x37, - WIIPROTO_REQ_DRM_E = 0x3d, - WIIPROTO_REQ_DRM_SKAI1 = 0x3e, - WIIPROTO_REQ_DRM_SKAI2 = 0x3f, - WIIPROTO_REQ_MAX -}; - -#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ - dev)) - -extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); -extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, - const __u8 *wmem, __u8 size); -extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, - __u8 *rmem, __u8 size); - -#define wiiproto_req_rreg(wdata, os, sz) \ - wiiproto_req_rmem((wdata), false, (os), (sz)) -#define wiiproto_req_reeprom(wdata, os, sz) \ - wiiproto_req_rmem((wdata), true, (os), (sz)) -extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, - __u32 offset, __u16 size); - -#ifdef CONFIG_HID_WIIMOTE_EXT - -extern int wiiext_init(struct wiimote_data *wdata); -extern void wiiext_deinit(struct wiimote_data *wdata); -extern void wiiext_event(struct wiimote_data *wdata, bool plugged); -extern bool wiiext_active(struct wiimote_data *wdata); -extern void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload); - -#else - -static inline int wiiext_init(void *u) { return 0; } -static inline void wiiext_deinit(void *u) { } -static inline void wiiext_event(void *u, bool p) { } -static inline bool wiiext_active(void *u) { return false; } -static inline void wiiext_handle(void *u, const __u8 *p) { } - -#endif - -#ifdef CONFIG_DEBUG_FS - -extern int wiidebug_init(struct wiimote_data *wdata); -extern void wiidebug_deinit(struct wiimote_data *wdata); - -#else - -static inline int wiidebug_init(void *u) { return 0; } -static inline void wiidebug_deinit(void *u) { } - -#endif - -/* requires the state.lock spinlock to be held */ -static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, - __u32 opt) -{ - return wdata->state.cmd == cmd && wdata->state.opt == opt; -} - -/* requires the state.lock spinlock to be held */ -static inline void wiimote_cmd_complete(struct wiimote_data *wdata) -{ - wdata->state.cmd = WIIPROTO_REQ_NULL; - complete(&wdata->state.ready); -} - -static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) -{ - return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; -} - -/* requires the state.lock spinlock to be held */ -static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, - __u32 opt) -{ - INIT_COMPLETION(wdata->state.ready); - wdata->state.cmd = cmd; - wdata->state.opt = opt; -} - -static inline void wiimote_cmd_release(struct wiimote_data *wdata) -{ - mutex_unlock(&wdata->state.sync); -} - -static inline int wiimote_cmd_wait(struct wiimote_data *wdata) -{ - int ret; - - ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); - if (ret < 0) - return -ERESTARTSYS; - else if (ret == 0) - return -EIO; - else - return 0; -} - -#endif diff --git a/ANDROID_3.4.5/drivers/hid/hid-zpff.c b/ANDROID_3.4.5/drivers/hid/hid-zpff.c deleted file mode 100644 index f6ba81df..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-zpff.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Force feedback support for Zeroplus based devices - * - * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/module.h> - -#include "hid-ids.h" - -#ifdef CONFIG_ZEROPLUS_FF -#include "usbhid/usbhid.h" - -struct zpff_device { - struct hid_report *report; -}; - -static int zpff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct zpff_device *zpff = data; - int left, right; - - /* - * The following is specified the other way around in the Zeroplus - * datasheet but the order below is correct for the XFX Executioner; - * however it is possible that the XFX Executioner is an exception - */ - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - dbg_hid("called with 0x%04x 0x%04x\n", left, right); - - left = left * 0x7f / 0xffff; - right = right * 0x7f / 0xffff; - - zpff->report->field[2]->value[0] = left; - zpff->report->field[3]->value[0] = right; - dbg_hid("running with 0x%02x 0x%02x\n", left, right); - usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); - - return 0; -} - -static int zpff_init(struct hid_device *hid) -{ - struct zpff_device *zpff; - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); - return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 4) { - hid_err(hid, "not enough fields in report\n"); - return -ENODEV; - } - - zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); - if (!zpff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, zpff, zpff_play); - if (error) { - kfree(zpff); - return error; - } - - zpff->report = report; - zpff->report->field[0]->value[0] = 0x00; - zpff->report->field[1]->value[0] = 0x02; - zpff->report->field[2]->value[0] = 0x00; - zpff->report->field[3]->value[0] = 0x00; - usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); - - hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); - - return 0; -} -#else -static inline int zpff_init(struct hid_device *hid) -{ - return 0; -} -#endif - -static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err; - } - - zpff_init(hdev); - - return 0; -err: - return ret; -} - -static const struct hid_device_id zp_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, - { } -}; -MODULE_DEVICE_TABLE(hid, zp_devices); - -static struct hid_driver zp_driver = { - .name = "zeroplus", - .id_table = zp_devices, - .probe = zp_probe, -}; - -static int __init zp_init(void) -{ - return hid_register_driver(&zp_driver); -} - -static void __exit zp_exit(void) -{ - hid_unregister_driver(&zp_driver); -} - -module_init(zp_init); -module_exit(zp_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hid-zydacron.c b/ANDROID_3.4.5/drivers/hid/hid-zydacron.c deleted file mode 100644 index 1ad85f22..00000000 --- a/ANDROID_3.4.5/drivers/hid/hid-zydacron.c +++ /dev/null @@ -1,235 +0,0 @@ -/* -* HID driver for zydacron remote control -* -* Copyright (c) 2010 Don Prince <dhprince.devel@yahoo.co.uk> -*/ - -/* -* 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" - -struct zc_device { - struct input_dev *input_ep81; - unsigned short last_key[4]; -}; - - -/* -* Zydacron remote control has an invalid HID report descriptor, -* that needs fixing before we can parse it. -*/ -static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - if (*rsize >= 253 && - rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && - rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && - rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { - hid_info(hdev, - "fixing up zydacron remote control report descriptor\n"); - rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; - rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; - } - return rdesc; -} - -#define zc_map_key_clear(c) \ - hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) - -static int zc_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - int i; - struct zc_device *zc = hid_get_drvdata(hdev); - zc->input_ep81 = hi->input; - - if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) - return 0; - - dbg_hid("zynacron input mapping event [0x%x]\n", - usage->hid & HID_USAGE); - - switch (usage->hid & HID_USAGE) { - /* report 2 */ - case 0x10: - zc_map_key_clear(KEY_MODE); - break; - case 0x30: - zc_map_key_clear(KEY_SCREEN); - break; - case 0x70: - zc_map_key_clear(KEY_INFO); - break; - /* report 3 */ - case 0x04: - zc_map_key_clear(KEY_RADIO); - break; - /* report 4 */ - case 0x0d: - zc_map_key_clear(KEY_PVR); - break; - case 0x25: - zc_map_key_clear(KEY_TV); - break; - case 0x47: - zc_map_key_clear(KEY_AUDIO); - break; - case 0x49: - zc_map_key_clear(KEY_AUX); - break; - case 0x4a: - zc_map_key_clear(KEY_VIDEO); - break; - case 0x48: - zc_map_key_clear(KEY_DVD); - break; - case 0x24: - zc_map_key_clear(KEY_MENU); - break; - case 0x32: - zc_map_key_clear(KEY_TEXT); - break; - default: - return 0; - } - - for (i = 0; i < 4; i++) - zc->last_key[i] = 0; - - return 1; -} - -static int zc_raw_event(struct hid_device *hdev, struct hid_report *report, - u8 *data, int size) -{ - struct zc_device *zc = hid_get_drvdata(hdev); - int ret = 0; - unsigned key; - unsigned short index; - - if (report->id == data[0]) { - - /* break keys */ - for (index = 0; index < 4; index++) { - key = zc->last_key[index]; - if (key) { - input_event(zc->input_ep81, EV_KEY, key, 0); - zc->last_key[index] = 0; - } - } - - key = 0; - switch (report->id) { - case 0x02: - case 0x03: - switch (data[1]) { - case 0x10: - key = KEY_MODE; - index = 0; - break; - case 0x30: - key = KEY_SCREEN; - index = 1; - break; - case 0x70: - key = KEY_INFO; - index = 2; - break; - case 0x04: - key = KEY_RADIO; - index = 3; - break; - } - - if (key) { - input_event(zc->input_ep81, EV_KEY, key, 1); - zc->last_key[index] = key; - } - - ret = 1; - break; - } - } - - return ret; -} - -static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct zc_device *zc; - - zc = kzalloc(sizeof(*zc), GFP_KERNEL); - if (zc == NULL) { - hid_err(hdev, "can't alloc descriptor\n"); - return -ENOMEM; - } - - hid_set_drvdata(hdev, zc); - - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; - } - - return 0; -err_free: - kfree(zc); - - return ret; -} - -static void zc_remove(struct hid_device *hdev) -{ - struct zc_device *zc = hid_get_drvdata(hdev); - - hid_hw_stop(hdev); - kfree(zc); -} - -static const struct hid_device_id zc_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, - { } -}; -MODULE_DEVICE_TABLE(hid, zc_devices); - -static struct hid_driver zc_driver = { - .name = "zydacron", - .id_table = zc_devices, - .report_fixup = zc_report_fixup, - .input_mapping = zc_input_mapping, - .raw_event = zc_raw_event, - .probe = zc_probe, - .remove = zc_remove, -}; - -static int __init zc_init(void) -{ - return hid_register_driver(&zc_driver); -} - -static void __exit zc_exit(void) -{ - hid_unregister_driver(&zc_driver); -} - -module_init(zc_init); -module_exit(zc_exit); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hid/hidraw.c b/ANDROID_3.4.5/drivers/hid/hidraw.c deleted file mode 100644 index cf7d6d58..00000000 --- a/ANDROID_3.4.5/drivers/hid/hidraw.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * HID raw devices, giving access to raw HID events. - * - * In comparison to hiddev, this device does not process the - * hid events at all (no parsing, no lookups). This lets applications - * to work on raw hid events as they want to, and avoids a need to - * use a transport-specific userspace libhid/libusb libraries. - * - * Copyright (c) 2007 Jiri Kosina - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/fs.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/cdev.h> -#include <linux/poll.h> -#include <linux/device.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/hid.h> -#include <linux/mutex.h> -#include <linux/sched.h> - -#include <linux/hidraw.h> - -static int hidraw_major; -static struct cdev hidraw_cdev; -static struct class *hidraw_class; -static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; -static DEFINE_MUTEX(minors_lock); - -static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) -{ - struct hidraw_list *list = file->private_data; - int ret = 0, len; - DECLARE_WAITQUEUE(wait, current); - - mutex_lock(&list->read_mutex); - - while (ret == 0) { - if (list->head == list->tail) { - add_wait_queue(&list->hidraw->wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (list->head == list->tail) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - if (!list->hidraw->exist) { - ret = -EIO; - break; - } - - /* allow O_NONBLOCK to work well from other threads */ - mutex_unlock(&list->read_mutex); - schedule(); - mutex_lock(&list->read_mutex); - set_current_state(TASK_INTERRUPTIBLE); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&list->hidraw->wait, &wait); - } - - if (ret) - goto out; - - len = list->buffer[list->tail].len > count ? - count : list->buffer[list->tail].len; - - if (copy_to_user(buffer, list->buffer[list->tail].value, len)) { - ret = -EFAULT; - goto out; - } - ret = len; - - kfree(list->buffer[list->tail].value); - list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); - } -out: - mutex_unlock(&list->read_mutex); - return ret; -} - -/* The first byte is expected to be a report number. - * This function is to be called with the minors_lock mutex held */ -static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type) -{ - unsigned int minor = iminor(file->f_path.dentry->d_inode); - struct hid_device *dev; - __u8 *buf; - int ret = 0; - - if (!hidraw_table[minor]) { - ret = -ENODEV; - goto out; - } - - dev = hidraw_table[minor]->hid; - - if (!dev->hid_output_raw_report) { - ret = -ENODEV; - goto out; - } - - if (count > HID_MAX_BUFFER_SIZE) { - hid_warn(dev, "pid %d passed too large report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - if (count < 2) { - hid_warn(dev, "pid %d passed too short report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(buf, buffer, count)) { - ret = -EFAULT; - goto out_free; - } - - ret = dev->hid_output_raw_report(dev, buf, count, report_type); -out_free: - kfree(buf); -out: - return ret; -} - -/* the first byte is expected to be a report number */ -static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) -{ - ssize_t ret; - mutex_lock(&minors_lock); - ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); - mutex_unlock(&minors_lock); - return ret; -} - - -/* This function performs a Get_Report transfer over the control endpoint - * per section 7.2.1 of the HID specification, version 1.1. The first byte - * of buffer is the report number to request, or 0x0 if the defice does not - * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT - * or HID_INPUT_REPORT. This function is to be called with the minors_lock - * mutex held. */ -static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type) -{ - unsigned int minor = iminor(file->f_path.dentry->d_inode); - struct hid_device *dev; - __u8 *buf; - int ret = 0, len; - unsigned char report_number; - - dev = hidraw_table[minor]->hid; - - if (!dev->hid_get_raw_report) { - ret = -ENODEV; - goto out; - } - - if (count > HID_MAX_BUFFER_SIZE) { - printk(KERN_WARNING "hidraw: pid %d passed too large report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - if (count < 2) { - printk(KERN_WARNING "hidraw: pid %d passed too short report\n", - task_pid_nr(current)); - ret = -EINVAL; - goto out; - } - - buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - /* Read the first byte from the user. This is the report number, - * which is passed to dev->hid_get_raw_report(). */ - if (copy_from_user(&report_number, buffer, 1)) { - ret = -EFAULT; - goto out_free; - } - - ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type); - - if (ret < 0) - goto out_free; - - len = (ret < count) ? ret : count; - - if (copy_to_user(buffer, buf, len)) { - ret = -EFAULT; - goto out_free; - } - - ret = len; - -out_free: - kfree(buf); -out: - return ret; -} - -static unsigned int hidraw_poll(struct file *file, poll_table *wait) -{ - struct hidraw_list *list = file->private_data; - - poll_wait(file, &list->hidraw->wait, wait); - if (list->head != list->tail) - return POLLIN | POLLRDNORM; - if (!list->hidraw->exist) - return POLLERR | POLLHUP; - return 0; -} - -static int hidraw_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct hidraw *dev; - struct hidraw_list *list; - int err = 0; - - if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { - err = -ENOMEM; - goto out; - } - - mutex_lock(&minors_lock); - if (!hidraw_table[minor]) { - err = -ENODEV; - goto out_unlock; - } - - list->hidraw = hidraw_table[minor]; - mutex_init(&list->read_mutex); - list_add_tail(&list->node, &hidraw_table[minor]->list); - file->private_data = list; - - dev = hidraw_table[minor]; - if (!dev->open++) { - err = hid_hw_power(dev->hid, PM_HINT_FULLON); - if (err < 0) { - dev->open--; - goto out_unlock; - } - - err = hid_hw_open(dev->hid); - if (err < 0) { - hid_hw_power(dev->hid, PM_HINT_NORMAL); - dev->open--; - } - } - -out_unlock: - mutex_unlock(&minors_lock); -out: - if (err < 0) - kfree(list); - return err; - -} - -static int hidraw_release(struct inode * inode, struct file * file) -{ - unsigned int minor = iminor(inode); - struct hidraw *dev; - struct hidraw_list *list = file->private_data; - int ret; - - mutex_lock(&minors_lock); - if (!hidraw_table[minor]) { - ret = -ENODEV; - goto unlock; - } - - list_del(&list->node); - dev = hidraw_table[minor]; - if (!--dev->open) { - if (list->hidraw->exist) { - hid_hw_power(dev->hid, PM_HINT_NORMAL); - hid_hw_close(dev->hid); - } else { - kfree(list->hidraw); - } - } - kfree(list); - ret = 0; -unlock: - mutex_unlock(&minors_lock); - - return ret; -} - -static long hidraw_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = file->f_path.dentry->d_inode; - unsigned int minor = iminor(inode); - long ret = 0; - struct hidraw *dev; - void __user *user_arg = (void __user*) arg; - - mutex_lock(&minors_lock); - dev = hidraw_table[minor]; - if (!dev) { - ret = -ENODEV; - goto out; - } - - switch (cmd) { - case HIDIOCGRDESCSIZE: - if (put_user(dev->hid->rsize, (int __user *)arg)) - ret = -EFAULT; - break; - - case HIDIOCGRDESC: - { - __u32 len; - - if (get_user(len, (int __user *)arg)) - ret = -EFAULT; - else if (len > HID_MAX_DESCRIPTOR_SIZE - 1) - ret = -EINVAL; - else if (copy_to_user(user_arg + offsetof( - struct hidraw_report_descriptor, - value[0]), - dev->hid->rdesc, - min(dev->hid->rsize, len))) - ret = -EFAULT; - break; - } - case HIDIOCGRAWINFO: - { - struct hidraw_devinfo dinfo; - - dinfo.bustype = dev->hid->bus; - dinfo.vendor = dev->hid->vendor; - dinfo.product = dev->hid->product; - if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) - ret = -EFAULT; - break; - } - default: - { - struct hid_device *hid = dev->hid; - if (_IOC_TYPE(cmd) != 'H') { - ret = -EINVAL; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) { - int len = _IOC_SIZE(cmd); - ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT); - break; - } - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) { - int len = _IOC_SIZE(cmd); - ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT); - break; - } - - /* Begin Read-only ioctls. */ - if (_IOC_DIR(cmd) != _IOC_READ) { - ret = -EINVAL; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { - int len = strlen(hid->name) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - ret = copy_to_user(user_arg, hid->name, len) ? - -EFAULT : len; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { - int len = strlen(hid->phys) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - ret = copy_to_user(user_arg, hid->phys, len) ? - -EFAULT : len; - break; - } - } - - ret = -ENOTTY; - } -out: - mutex_unlock(&minors_lock); - return ret; -} - -static const struct file_operations hidraw_ops = { - .owner = THIS_MODULE, - .read = hidraw_read, - .write = hidraw_write, - .poll = hidraw_poll, - .open = hidraw_open, - .release = hidraw_release, - .unlocked_ioctl = hidraw_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = hidraw_ioctl, -#endif - .llseek = noop_llseek, -}; - -void hidraw_report_event(struct hid_device *hid, u8 *data, int len) -{ - struct hidraw *dev = hid->hidraw; - struct hidraw_list *list; - - list_for_each_entry(list, &dev->list, node) { - list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC); - list->buffer[list->head].len = len; - list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); - kill_fasync(&list->fasync, SIGIO, POLL_IN); - } - - wake_up_interruptible(&dev->wait); -} -EXPORT_SYMBOL_GPL(hidraw_report_event); - -int hidraw_connect(struct hid_device *hid) -{ - int minor, result; - struct hidraw *dev; - - /* we accept any HID device, no matter the applications */ - - dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - result = -EINVAL; - - mutex_lock(&minors_lock); - - for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { - if (hidraw_table[minor]) - continue; - hidraw_table[minor] = dev; - result = 0; - break; - } - - if (result) { - mutex_unlock(&minors_lock); - kfree(dev); - goto out; - } - - dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor), - NULL, "%s%d", "hidraw", minor); - - if (IS_ERR(dev->dev)) { - hidraw_table[minor] = NULL; - mutex_unlock(&minors_lock); - result = PTR_ERR(dev->dev); - kfree(dev); - goto out; - } - - mutex_unlock(&minors_lock); - init_waitqueue_head(&dev->wait); - INIT_LIST_HEAD(&dev->list); - - dev->hid = hid; - dev->minor = minor; - - dev->exist = 1; - hid->hidraw = dev; - -out: - return result; - -} -EXPORT_SYMBOL_GPL(hidraw_connect); - -void hidraw_disconnect(struct hid_device *hid) -{ - struct hidraw *hidraw = hid->hidraw; - - mutex_lock(&minors_lock); - hidraw->exist = 0; - - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); - - hidraw_table[hidraw->minor] = NULL; - - if (hidraw->open) { - hid_hw_close(hid); - wake_up_interruptible(&hidraw->wait); - } else { - kfree(hidraw); - } - mutex_unlock(&minors_lock); -} -EXPORT_SYMBOL_GPL(hidraw_disconnect); - -int __init hidraw_init(void) -{ - int result; - dev_t dev_id; - - result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR, - HIDRAW_MAX_DEVICES, "hidraw"); - - hidraw_major = MAJOR(dev_id); - - if (result < 0) { - pr_warn("can't get major number\n"); - result = 0; - goto out; - } - - hidraw_class = class_create(THIS_MODULE, "hidraw"); - if (IS_ERR(hidraw_class)) { - result = PTR_ERR(hidraw_class); - unregister_chrdev(hidraw_major, "hidraw"); - goto out; - } - - cdev_init(&hidraw_cdev, &hidraw_ops); - cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES); -out: - return result; -} - -void hidraw_exit(void) -{ - dev_t dev_id = MKDEV(hidraw_major, 0); - - cdev_del(&hidraw_cdev); - class_destroy(hidraw_class); - unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); - -} diff --git a/ANDROID_3.4.5/drivers/hid/uhid.c b/ANDROID_3.4.5/drivers/hid/uhid.c deleted file mode 100644 index 714cd8cc..00000000 --- a/ANDROID_3.4.5/drivers/hid/uhid.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * User-space I/O driver support for HID subsystem - * Copyright (c) 2012 David Herrmann - */ - -/* - * 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/atomic.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/hid.h> -#include <linux/input.h> -#include <linux/miscdevice.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/poll.h> -#include <linux/sched.h> -#include <linux/spinlock.h> -#include <linux/uhid.h> -#include <linux/wait.h> - -#define UHID_NAME "uhid" -#define UHID_BUFSIZE 32 - -struct uhid_device { - struct mutex devlock; - bool running; - - __u8 *rd_data; - uint rd_size; - - struct hid_device *hid; - struct uhid_event input_buf; - - wait_queue_head_t waitq; - spinlock_t qlock; - __u8 head; - __u8 tail; - struct uhid_event *outq[UHID_BUFSIZE]; - - struct mutex report_lock; - wait_queue_head_t report_wait; - atomic_t report_done; - atomic_t report_id; - struct uhid_event report_buf; -}; - -static struct miscdevice uhid_misc; - -static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev) -{ - __u8 newhead; - - newhead = (uhid->head + 1) % UHID_BUFSIZE; - - if (newhead != uhid->tail) { - uhid->outq[uhid->head] = ev; - uhid->head = newhead; - wake_up_interruptible(&uhid->waitq); - } else { - hid_warn(uhid->hid, "Output queue is full\n"); - kfree(ev); - } -} - -static int uhid_queue_event(struct uhid_device *uhid, __u32 event) -{ - unsigned long flags; - struct uhid_event *ev; - - ev = kzalloc(sizeof(*ev), GFP_KERNEL); - if (!ev) - return -ENOMEM; - - ev->type = event; - - spin_lock_irqsave(&uhid->qlock, flags); - uhid_queue(uhid, ev); - spin_unlock_irqrestore(&uhid->qlock, flags); - - return 0; -} - -static int uhid_hid_start(struct hid_device *hid) -{ - struct uhid_device *uhid = hid->driver_data; - - return uhid_queue_event(uhid, UHID_START); -} - -static void uhid_hid_stop(struct hid_device *hid) -{ - struct uhid_device *uhid = hid->driver_data; - - hid->claimed = 0; - uhid_queue_event(uhid, UHID_STOP); -} - -static int uhid_hid_open(struct hid_device *hid) -{ - struct uhid_device *uhid = hid->driver_data; - - return uhid_queue_event(uhid, UHID_OPEN); -} - -static void uhid_hid_close(struct hid_device *hid) -{ - struct uhid_device *uhid = hid->driver_data; - - uhid_queue_event(uhid, UHID_CLOSE); -} - -static int uhid_hid_input(struct input_dev *input, unsigned int type, - unsigned int code, int value) -{ - struct hid_device *hid = input_get_drvdata(input); - struct uhid_device *uhid = hid->driver_data; - unsigned long flags; - struct uhid_event *ev; - - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); - if (!ev) - return -ENOMEM; - - ev->type = UHID_OUTPUT_EV; - ev->u.output_ev.type = type; - ev->u.output_ev.code = code; - ev->u.output_ev.value = value; - - spin_lock_irqsave(&uhid->qlock, flags); - uhid_queue(uhid, ev); - spin_unlock_irqrestore(&uhid->qlock, flags); - - return 0; -} - -static int uhid_hid_parse(struct hid_device *hid) -{ - struct uhid_device *uhid = hid->driver_data; - - return hid_parse_report(hid, uhid->rd_data, uhid->rd_size); -} - -static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum, - __u8 *buf, size_t count, unsigned char rtype) -{ - struct uhid_device *uhid = hid->driver_data; - __u8 report_type; - struct uhid_event *ev; - unsigned long flags; - int ret; - size_t uninitialized_var(len); - struct uhid_feature_answer_req *req; - - if (!uhid->running) - return -EIO; - - switch (rtype) { - case HID_FEATURE_REPORT: - report_type = UHID_FEATURE_REPORT; - break; - case HID_OUTPUT_REPORT: - report_type = UHID_OUTPUT_REPORT; - break; - case HID_INPUT_REPORT: - report_type = UHID_INPUT_REPORT; - break; - default: - return -EINVAL; - } - - ret = mutex_lock_interruptible(&uhid->report_lock); - if (ret) - return ret; - - ev = kzalloc(sizeof(*ev), GFP_KERNEL); - if (!ev) { - ret = -ENOMEM; - goto unlock; - } - - spin_lock_irqsave(&uhid->qlock, flags); - ev->type = UHID_FEATURE; - ev->u.feature.id = atomic_inc_return(&uhid->report_id); - ev->u.feature.rnum = rnum; - ev->u.feature.rtype = report_type; - - atomic_set(&uhid->report_done, 0); - uhid_queue(uhid, ev); - spin_unlock_irqrestore(&uhid->qlock, flags); - - ret = wait_event_interruptible_timeout(uhid->report_wait, - atomic_read(&uhid->report_done), 5 * HZ); - - /* - * Make sure "uhid->running" is cleared on shutdown before - * "uhid->report_done" is set. - */ - smp_rmb(); - if (!ret || !uhid->running) { - ret = -EIO; - } else if (ret < 0) { - ret = -ERESTARTSYS; - } else { - spin_lock_irqsave(&uhid->qlock, flags); - req = &uhid->report_buf.u.feature_answer; - - if (req->err) { - ret = -EIO; - } else { - ret = 0; - len = min(count, - min_t(size_t, req->size, UHID_DATA_MAX)); - memcpy(buf, req->data, len); - } - - spin_unlock_irqrestore(&uhid->qlock, flags); - } - - atomic_set(&uhid->report_done, 1); - -unlock: - mutex_unlock(&uhid->report_lock); - return ret ? ret : len; -} - -static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count, - unsigned char report_type) -{ - struct uhid_device *uhid = hid->driver_data; - __u8 rtype; - unsigned long flags; - struct uhid_event *ev; - - switch (report_type) { - case HID_FEATURE_REPORT: - rtype = UHID_FEATURE_REPORT; - break; - case HID_OUTPUT_REPORT: - rtype = UHID_OUTPUT_REPORT; - break; - default: - return -EINVAL; - } - - if (count < 1 || count > UHID_DATA_MAX) - return -EINVAL; - - ev = kzalloc(sizeof(*ev), GFP_KERNEL); - if (!ev) - return -ENOMEM; - - ev->type = UHID_OUTPUT; - ev->u.output.size = count; - ev->u.output.rtype = rtype; - memcpy(ev->u.output.data, buf, count); - - spin_lock_irqsave(&uhid->qlock, flags); - uhid_queue(uhid, ev); - spin_unlock_irqrestore(&uhid->qlock, flags); - - return count; -} - -static struct hid_ll_driver uhid_hid_driver = { - .start = uhid_hid_start, - .stop = uhid_hid_stop, - .open = uhid_hid_open, - .close = uhid_hid_close, - .hidinput_input_event = uhid_hid_input, - .parse = uhid_hid_parse, -}; - -static int uhid_dev_create(struct uhid_device *uhid, - const struct uhid_event *ev) -{ - struct hid_device *hid; - int ret; - - if (uhid->running) - return -EALREADY; - - uhid->rd_size = ev->u.create.rd_size; - if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) - return -EINVAL; - - uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); - if (!uhid->rd_data) - return -ENOMEM; - - if (copy_from_user(uhid->rd_data, ev->u.create.rd_data, - uhid->rd_size)) { - ret = -EFAULT; - goto err_free; - } - - hid = hid_allocate_device(); - if (IS_ERR(hid)) { - ret = PTR_ERR(hid); - goto err_free; - } - - strncpy(hid->name, ev->u.create.name, 127); - hid->name[127] = 0; - strncpy(hid->phys, ev->u.create.phys, 63); - hid->phys[63] = 0; - strncpy(hid->uniq, ev->u.create.uniq, 63); - hid->uniq[63] = 0; - - hid->ll_driver = &uhid_hid_driver; - hid->hid_get_raw_report = uhid_hid_get_raw; - hid->hid_output_raw_report = uhid_hid_output_raw; - hid->bus = ev->u.create.bus; - hid->vendor = ev->u.create.vendor; - hid->product = ev->u.create.product; - hid->version = ev->u.create.version; - hid->country = ev->u.create.country; - hid->driver_data = uhid; - hid->dev.parent = uhid_misc.this_device; - - uhid->hid = hid; - uhid->running = true; - - ret = hid_add_device(hid); - if (ret) { - hid_err(hid, "Cannot register HID device\n"); - goto err_hid; - } - - return 0; - -err_hid: - hid_destroy_device(hid); - uhid->hid = NULL; - uhid->running = false; -err_free: - kfree(uhid->rd_data); - return ret; -} - -static int uhid_dev_destroy(struct uhid_device *uhid) -{ - if (!uhid->running) - return -EINVAL; - - /* clear "running" before setting "report_done" */ - uhid->running = false; - smp_wmb(); - atomic_set(&uhid->report_done, 1); - wake_up_interruptible(&uhid->report_wait); - - hid_destroy_device(uhid->hid); - kfree(uhid->rd_data); - - return 0; -} - -static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev) -{ - if (!uhid->running) - return -EINVAL; - - hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data, - min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0); - - return 0; -} - -static int uhid_dev_feature_answer(struct uhid_device *uhid, - struct uhid_event *ev) -{ - unsigned long flags; - - if (!uhid->running) - return -EINVAL; - - spin_lock_irqsave(&uhid->qlock, flags); - - /* id for old report; drop it silently */ - if (atomic_read(&uhid->report_id) != ev->u.feature_answer.id) - goto unlock; - if (atomic_read(&uhid->report_done)) - goto unlock; - - memcpy(&uhid->report_buf, ev, sizeof(*ev)); - atomic_set(&uhid->report_done, 1); - wake_up_interruptible(&uhid->report_wait); - -unlock: - spin_unlock_irqrestore(&uhid->qlock, flags); - return 0; -} - -static int uhid_char_open(struct inode *inode, struct file *file) -{ - struct uhid_device *uhid; - - uhid = kzalloc(sizeof(*uhid), GFP_KERNEL); - if (!uhid) - return -ENOMEM; - - mutex_init(&uhid->devlock); - mutex_init(&uhid->report_lock); - spin_lock_init(&uhid->qlock); - init_waitqueue_head(&uhid->waitq); - init_waitqueue_head(&uhid->report_wait); - uhid->running = false; - atomic_set(&uhid->report_done, 1); - - file->private_data = uhid; - nonseekable_open(inode, file); - - return 0; -} - -static int uhid_char_release(struct inode *inode, struct file *file) -{ - struct uhid_device *uhid = file->private_data; - unsigned int i; - - uhid_dev_destroy(uhid); - - for (i = 0; i < UHID_BUFSIZE; ++i) - kfree(uhid->outq[i]); - - kfree(uhid); - - return 0; -} - -static ssize_t uhid_char_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct uhid_device *uhid = file->private_data; - int ret; - unsigned long flags; - size_t len; - - /* they need at least the "type" member of uhid_event */ - if (count < sizeof(__u32)) - return -EINVAL; - -try_again: - if (file->f_flags & O_NONBLOCK) { - if (uhid->head == uhid->tail) - return -EAGAIN; - } else { - ret = wait_event_interruptible(uhid->waitq, - uhid->head != uhid->tail); - if (ret) - return ret; - } - - ret = mutex_lock_interruptible(&uhid->devlock); - if (ret) - return ret; - - if (uhid->head == uhid->tail) { - mutex_unlock(&uhid->devlock); - goto try_again; - } else { - len = min(count, sizeof(**uhid->outq)); - if (copy_to_user(buffer, uhid->outq[uhid->tail], len)) { - ret = -EFAULT; - } else { - kfree(uhid->outq[uhid->tail]); - uhid->outq[uhid->tail] = NULL; - - spin_lock_irqsave(&uhid->qlock, flags); - uhid->tail = (uhid->tail + 1) % UHID_BUFSIZE; - spin_unlock_irqrestore(&uhid->qlock, flags); - } - } - - mutex_unlock(&uhid->devlock); - return ret ? ret : len; -} - -static ssize_t uhid_char_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - struct uhid_device *uhid = file->private_data; - int ret; - size_t len; - - /* we need at least the "type" member of uhid_event */ - if (count < sizeof(__u32)) - return -EINVAL; - - ret = mutex_lock_interruptible(&uhid->devlock); - if (ret) - return ret; - - memset(&uhid->input_buf, 0, sizeof(uhid->input_buf)); - len = min(count, sizeof(uhid->input_buf)); - if (copy_from_user(&uhid->input_buf, buffer, len)) { - ret = -EFAULT; - goto unlock; - } - - switch (uhid->input_buf.type) { - case UHID_CREATE: - ret = uhid_dev_create(uhid, &uhid->input_buf); - break; - case UHID_DESTROY: - ret = uhid_dev_destroy(uhid); - break; - case UHID_INPUT: - ret = uhid_dev_input(uhid, &uhid->input_buf); - break; - case UHID_FEATURE_ANSWER: - ret = uhid_dev_feature_answer(uhid, &uhid->input_buf); - break; - default: - ret = -EOPNOTSUPP; - } - -unlock: - mutex_unlock(&uhid->devlock); - - /* return "count" not "len" to not confuse the caller */ - return ret ? ret : count; -} - -static unsigned int uhid_char_poll(struct file *file, poll_table *wait) -{ - struct uhid_device *uhid = file->private_data; - - poll_wait(file, &uhid->waitq, wait); - - if (uhid->head != uhid->tail) - return POLLIN | POLLRDNORM; - - return 0; -} - -static const struct file_operations uhid_fops = { - .owner = THIS_MODULE, - .open = uhid_char_open, - .release = uhid_char_release, - .read = uhid_char_read, - .write = uhid_char_write, - .poll = uhid_char_poll, - .llseek = no_llseek, -}; - -static struct miscdevice uhid_misc = { - .fops = &uhid_fops, - .minor = MISC_DYNAMIC_MINOR, - .name = UHID_NAME, -}; - -static int __init uhid_init(void) -{ - return misc_register(&uhid_misc); -} - -static void __exit uhid_exit(void) -{ - misc_deregister(&uhid_misc); -} - -module_init(uhid_init); -module_exit(uhid_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); -MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/Kconfig b/ANDROID_3.4.5/drivers/hid/usbhid/Kconfig deleted file mode 100644 index 0f20fd17..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/Kconfig +++ /dev/null @@ -1,84 +0,0 @@ -comment "USB Input Devices" - depends on USB - -config USB_HID - tristate "USB Human Interface Device (full HID) support" - default y - depends on USB && INPUT - select HID - ---help--- - Say Y here if you want full HID support to connect USB keyboards, - mice, joysticks, graphic tablets, or any other HID based devices - to your computer via USB, as well as Uninterruptible Power Supply - (UPS) and monitor control devices. - - You can't use this driver and the HIDBP (Boot Protocol) keyboard - and mouse drivers at the same time. More information is available: - <file:Documentation/input/input.txt>. - - If unsure, say Y. - - To compile this driver as a module, choose M here: the - module will be called usbhid. - -comment "Input core support is needed for USB HID input layer or HIDBP support" - depends on USB_HID && INPUT=n - -config HID_PID - bool "PID device support" - help - Say Y here if you have a PID-compliant device and wish to enable force - feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such - devices. - -config USB_HIDDEV - bool "/dev/hiddev raw HID device support" - depends on USB_HID - help - Say Y here if you want to support HID devices (from the USB - specification standpoint) that aren't strictly user interface - devices, like monitor controls and Uninterruptable Power Supplies. - - This module supports these devices separately using a separate - event interface on /dev/usb/hiddevX (char 180:96 to 180:111). - - If unsure, say Y. - -menu "USB HID Boot Protocol drivers" - depends on USB!=n && USB_HID!=y && EXPERT - -config USB_KBD - tristate "USB HIDBP Keyboard (simple Boot) support" - depends on USB && INPUT - ---help--- - Say Y here only if you are absolutely sure that you don't want - to use the generic HID driver for your USB keyboard and prefer - to use the keyboard in its limited Boot Protocol mode instead. - - This is almost certainly not what you want. This is mostly - useful for embedded applications or simple keyboards. - - To compile this driver as a module, choose M here: the - module will be called usbkbd. - - If even remotely unsure, say N. - -config USB_MOUSE - tristate "USB HIDBP Mouse (simple Boot) support" - depends on USB && INPUT - ---help--- - Say Y here only if you are absolutely sure that you don't want - to use the generic HID driver for your USB mouse and prefer - to use the mouse in its limited Boot Protocol mode instead. - - This is almost certainly not what you want. This is mostly - useful for embedded applications or simple mice. - - To compile this driver as a module, choose M here: the - module will be called usbmouse. - - If even remotely unsure, say N. - -endmenu - - diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/Makefile b/ANDROID_3.4.5/drivers/hid/usbhid/Makefile deleted file mode 100644 index db3cf31c..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# Makefile for the USB input drivers -# - -# Multipart objects. -usbhid-y := hid-core.o hid-quirks.o - -# Optional parts of multipart objects. - -ifeq ($(CONFIG_USB_HIDDEV),y) - usbhid-y += hiddev.o -endif -ifeq ($(CONFIG_HID_PID),y) - usbhid-y += hid-pidff.o -endif - -obj-$(CONFIG_USB_HID) += usbhid.o -obj-$(CONFIG_USB_KBD) += usbkbd.o -obj-$(CONFIG_USB_MOUSE) += usbmouse.o - diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/hid-core.c b/ANDROID_3.4.5/drivers/hid/usbhid/hid-core.c deleted file mode 100644 index 4bbb883a..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/hid-core.c +++ /dev/null @@ -1,1609 +0,0 @@ -/* - * USB HID support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2007-2008 Oliver Neukum - * Copyright (c) 2006-2010 Jiri Kosina - */ - -/* - * 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/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/input.h> -#include <linux/wait.h> -#include <linux/workqueue.h> - -#include <linux/usb.h> - -#include <linux/hid.h> -#include <linux/hiddev.h> -#include <linux/hid-debug.h> -#include <linux/hidraw.h> -#include "usbhid.h" - -/* - * Version Information - */ - -#define DRIVER_DESC "USB HID core driver" -#define DRIVER_LICENSE "GPL" - -/* - * Module parameters. - */ - -static unsigned int hid_mousepoll_interval; -module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); -MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - -static unsigned int ignoreled; -module_param_named(ignoreled, ignoreled, uint, 0644); -MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds"); - -/* Quirks specified at module load time */ -static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; -module_param_array_named(quirks, quirks_param, charp, NULL, 0444); -MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " - " quirks=vendorID:productID:quirks" - " where vendorID, productID, and quirks are all in" - " 0x-prefixed hex"); -/* - * Input submission and I/O error handler. - */ -static DEFINE_MUTEX(hid_open_mut); - -static void hid_io_error(struct hid_device *hid); -static int hid_submit_out(struct hid_device *hid); -static int hid_submit_ctrl(struct hid_device *hid); -static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid); - -/* Start up the input URB */ -static int hid_start_in(struct hid_device *hid) -{ - unsigned long flags; - int rc = 0; - struct usbhid_device *usbhid = hid->driver_data; - - spin_lock_irqsave(&usbhid->lock, flags); - if (hid->open > 0 && - !test_bit(HID_DISCONNECTED, &usbhid->iofl) && - !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && - !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { - rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); - if (rc != 0) - clear_bit(HID_IN_RUNNING, &usbhid->iofl); - } - spin_unlock_irqrestore(&usbhid->lock, flags); - return rc; -} - -/* I/O retry timer routine */ -static void hid_retry_timeout(unsigned long _hid) -{ - struct hid_device *hid = (struct hid_device *) _hid; - struct usbhid_device *usbhid = hid->driver_data; - - dev_dbg(&usbhid->intf->dev, "retrying intr urb\n"); - if (hid_start_in(hid)) - hid_io_error(hid); -} - -/* Workqueue routine to reset the device or clear a halt */ -static void hid_reset(struct work_struct *work) -{ - struct usbhid_device *usbhid = - container_of(work, struct usbhid_device, reset_work); - struct hid_device *hid = usbhid->hid; - int rc = 0; - - if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { - dev_dbg(&usbhid->intf->dev, "clear halt\n"); - rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe); - clear_bit(HID_CLEAR_HALT, &usbhid->iofl); - hid_start_in(hid); - } - - else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { - dev_dbg(&usbhid->intf->dev, "resetting device\n"); - rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); - if (rc == 0) { - rc = usb_reset_device(hid_to_usb_dev(hid)); - usb_unlock_device(hid_to_usb_dev(hid)); - } - clear_bit(HID_RESET_PENDING, &usbhid->iofl); - } - - switch (rc) { - case 0: - if (!test_bit(HID_IN_RUNNING, &usbhid->iofl)) - hid_io_error(hid); - break; - default: - hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n", - hid_to_usb_dev(hid)->bus->bus_name, - hid_to_usb_dev(hid)->devpath, - usbhid->ifnum, rc); - /* FALLTHROUGH */ - case -EHOSTUNREACH: - case -ENODEV: - case -EINTR: - break; - } -} - -/* Main I/O error handler */ -static void hid_io_error(struct hid_device *hid) -{ - unsigned long flags; - struct usbhid_device *usbhid = hid->driver_data; - - spin_lock_irqsave(&usbhid->lock, flags); - - /* Stop when disconnected */ - if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) - goto done; - - /* If it has been a while since the last error, we'll assume - * this a brand new error and reset the retry timeout. */ - if (time_after(jiffies, usbhid->stop_retry + HZ/2)) - usbhid->retry_delay = 0; - - /* When an error occurs, retry at increasing intervals */ - if (usbhid->retry_delay == 0) { - usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ - usbhid->stop_retry = jiffies + msecs_to_jiffies(1000); - } else if (usbhid->retry_delay < 100) - usbhid->retry_delay *= 2; - - if (time_after(jiffies, usbhid->stop_retry)) { - - /* Retries failed, so do a port reset */ - if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { - schedule_work(&usbhid->reset_work); - goto done; - } - } - - mod_timer(&usbhid->io_retry, - jiffies + msecs_to_jiffies(usbhid->retry_delay)); -done: - spin_unlock_irqrestore(&usbhid->lock, flags); -} - -static void usbhid_mark_busy(struct usbhid_device *usbhid) -{ - struct usb_interface *intf = usbhid->intf; - - usb_mark_last_busy(interface_to_usbdev(intf)); -} - -static int usbhid_restart_out_queue(struct usbhid_device *usbhid) -{ - struct hid_device *hid = usb_get_intfdata(usbhid->intf); - int kicked; - int r; - - if (!hid) - return 0; - - if ((kicked = (usbhid->outhead != usbhid->outtail))) { - dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); - - r = usb_autopm_get_interface_async(usbhid->intf); - if (r < 0) - return r; - /* Asynchronously flush queue. */ - set_bit(HID_OUT_RUNNING, &usbhid->iofl); - if (hid_submit_out(hid)) { - clear_bit(HID_OUT_RUNNING, &usbhid->iofl); - usb_autopm_put_interface_async(usbhid->intf); - } - wake_up(&usbhid->wait); - } - return kicked; -} - -static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) -{ - struct hid_device *hid = usb_get_intfdata(usbhid->intf); - int kicked; - int r; - - WARN_ON(hid == NULL); - if (!hid) - return 0; - - if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { - dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); - - r = usb_autopm_get_interface_async(usbhid->intf); - if (r < 0) - return r; - /* Asynchronously flush queue. */ - set_bit(HID_CTRL_RUNNING, &usbhid->iofl); - if (hid_submit_ctrl(hid)) { - clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); - usb_autopm_put_interface_async(usbhid->intf); - } - wake_up(&usbhid->wait); - } - return kicked; -} - -/* - * Input interrupt completion handler. - */ - -static void hid_irq_in(struct urb *urb) -{ - struct hid_device *hid = urb->context; - struct usbhid_device *usbhid = hid->driver_data; - int status; - - switch (urb->status) { - case 0: /* success */ - usbhid_mark_busy(usbhid); - usbhid->retry_delay = 0; - hid_input_report(urb->context, HID_INPUT_REPORT, - urb->transfer_buffer, - urb->actual_length, 1); - /* - * autosuspend refused while keys are pressed - * because most keyboards don't wake up when - * a key is released - */ - if (hid_check_keys_pressed(hid)) - set_bit(HID_KEYS_PRESSED, &usbhid->iofl); - else - clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); - break; - case -EPIPE: /* stall */ - usbhid_mark_busy(usbhid); - clear_bit(HID_IN_RUNNING, &usbhid->iofl); - set_bit(HID_CLEAR_HALT, &usbhid->iofl); - schedule_work(&usbhid->reset_work); - return; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: /* unplug */ - clear_bit(HID_IN_RUNNING, &usbhid->iofl); - return; - case -EILSEQ: /* protocol error or unplug */ - case -EPROTO: /* protocol error or unplug */ - case -ETIME: /* protocol error or unplug */ - case -ETIMEDOUT: /* Should never happen, but... */ - usbhid_mark_busy(usbhid); - clear_bit(HID_IN_RUNNING, &usbhid->iofl); - hid_io_error(hid); - return; - default: /* error */ - hid_warn(urb->dev, "input irq status %d received\n", - urb->status); - } - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - clear_bit(HID_IN_RUNNING, &usbhid->iofl); - if (status != -EPERM) { - hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n", - hid_to_usb_dev(hid)->bus->bus_name, - hid_to_usb_dev(hid)->devpath, - usbhid->ifnum, status); - hid_io_error(hid); - } - } -} - -static int hid_submit_out(struct hid_device *hid) -{ - struct hid_report *report; - char *raw_report; - struct usbhid_device *usbhid = hid->driver_data; - int r; - - report = usbhid->out[usbhid->outtail].report; - raw_report = usbhid->out[usbhid->outtail].raw_report; - - usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + - 1 + (report->id > 0); - usbhid->urbout->dev = hid_to_usb_dev(hid); - memcpy(usbhid->outbuf, raw_report, - usbhid->urbout->transfer_buffer_length); - kfree(raw_report); - - dbg_hid("submitting out urb\n"); - - r = usb_submit_urb(usbhid->urbout, GFP_ATOMIC); - if (r < 0) { - hid_err(hid, "usb_submit_urb(out) failed: %d\n", r); - return r; - } - usbhid->last_out = jiffies; - return 0; -} - -static int hid_submit_ctrl(struct hid_device *hid) -{ - struct hid_report *report; - unsigned char dir; - char *raw_report; - int len, r; - struct usbhid_device *usbhid = hid->driver_data; - - report = usbhid->ctrl[usbhid->ctrltail].report; - raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; - dir = usbhid->ctrl[usbhid->ctrltail].dir; - - len = ((report->size - 1) >> 3) + 1 + (report->id > 0); - if (dir == USB_DIR_OUT) { - usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); - usbhid->urbctrl->transfer_buffer_length = len; - memcpy(usbhid->ctrlbuf, raw_report, len); - kfree(raw_report); - } else { - int maxpacket, padlen; - - usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); - maxpacket = usb_maxpacket(hid_to_usb_dev(hid), - usbhid->urbctrl->pipe, 0); - if (maxpacket > 0) { - padlen = DIV_ROUND_UP(len, maxpacket); - padlen *= maxpacket; - if (padlen > usbhid->bufsize) - padlen = usbhid->bufsize; - } else - padlen = 0; - usbhid->urbctrl->transfer_buffer_length = padlen; - } - usbhid->urbctrl->dev = hid_to_usb_dev(hid); - - usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; - usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : - HID_REQ_GET_REPORT; - usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | - report->id); - usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); - usbhid->cr->wLength = cpu_to_le16(len); - - dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", - usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : - "Get_Report", - usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); - - r = usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC); - if (r < 0) { - hid_err(hid, "usb_submit_urb(ctrl) failed: %d\n", r); - return r; - } - usbhid->last_ctrl = jiffies; - return 0; -} - -/* - * Output interrupt completion handler. - */ - -static int irq_out_pump_restart(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - if (usbhid->outhead != usbhid->outtail) - return hid_submit_out(hid); - else - return -1; -} - -static void hid_irq_out(struct urb *urb) -{ - struct hid_device *hid = urb->context; - struct usbhid_device *usbhid = hid->driver_data; - unsigned long flags; - int unplug = 0; - - switch (urb->status) { - case 0: /* success */ - break; - case -ESHUTDOWN: /* unplug */ - unplug = 1; - case -EILSEQ: /* protocol error or unplug */ - case -EPROTO: /* protocol error or unplug */ - case -ECONNRESET: /* unlink */ - case -ENOENT: - break; - default: /* error */ - hid_warn(urb->dev, "output irq status %d received\n", - urb->status); - } - - spin_lock_irqsave(&usbhid->lock, flags); - - if (unplug) - usbhid->outtail = usbhid->outhead; - else - usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); - - if (!irq_out_pump_restart(hid)) { - /* Successfully submitted next urb in queue */ - spin_unlock_irqrestore(&usbhid->lock, flags); - return; - } - - clear_bit(HID_OUT_RUNNING, &usbhid->iofl); - spin_unlock_irqrestore(&usbhid->lock, flags); - usb_autopm_put_interface_async(usbhid->intf); - wake_up(&usbhid->wait); -} - -/* - * Control pipe completion handler. - */ -static int ctrl_pump_restart(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - if (usbhid->ctrlhead != usbhid->ctrltail) - return hid_submit_ctrl(hid); - else - return -1; -} - -static void hid_ctrl(struct urb *urb) -{ - struct hid_device *hid = urb->context; - struct usbhid_device *usbhid = hid->driver_data; - int unplug = 0, status = urb->status; - - spin_lock(&usbhid->lock); - - switch (status) { - case 0: /* success */ - if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) - hid_input_report(urb->context, - usbhid->ctrl[usbhid->ctrltail].report->type, - urb->transfer_buffer, urb->actual_length, 0); - break; - case -ESHUTDOWN: /* unplug */ - unplug = 1; - case -EILSEQ: /* protocol error or unplug */ - case -EPROTO: /* protocol error or unplug */ - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -EPIPE: /* report not available */ - break; - default: /* error */ - hid_warn(urb->dev, "ctrl urb status %d received\n", status); - } - - if (unplug) - usbhid->ctrltail = usbhid->ctrlhead; - else - usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); - - if (!ctrl_pump_restart(hid)) { - /* Successfully submitted next urb in queue */ - spin_unlock(&usbhid->lock); - return; - } - - clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); - spin_unlock(&usbhid->lock); - usb_autopm_put_interface_async(usbhid->intf); - wake_up(&usbhid->wait); -} - -static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, - unsigned char dir) -{ - int head; - struct usbhid_device *usbhid = hid->driver_data; - int len = ((report->size - 1) >> 3) + 1 + (report->id > 0); - - if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) - return; - - if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { - if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { - hid_warn(hid, "output queue full\n"); - return; - } - - usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); - if (!usbhid->out[usbhid->outhead].raw_report) { - hid_warn(hid, "output queueing failed\n"); - return; - } - hid_output_report(report, usbhid->out[usbhid->outhead].raw_report); - usbhid->out[usbhid->outhead].report = report; - usbhid->outhead = head; - - /* Try to awake from autosuspend... */ - if (usb_autopm_get_interface_async(usbhid->intf) < 0) - return; - - /* - * But if still suspended, leave urb enqueued, don't submit. - * Submission will occur if/when resume() drains the queue. - */ - if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) - return; - - if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { - if (hid_submit_out(hid)) { - clear_bit(HID_OUT_RUNNING, &usbhid->iofl); - usb_autopm_put_interface_async(usbhid->intf); - } - wake_up(&usbhid->wait); - } else { - /* - * the queue is known to run - * but an earlier request may be stuck - * we may need to time out - * no race because the URB is blocked under - * spinlock - */ - if (time_after(jiffies, usbhid->last_out + HZ * 5)) { - usb_block_urb(usbhid->urbout); - /* drop lock to not deadlock if the callback is called */ - spin_unlock(&usbhid->lock); - usb_unlink_urb(usbhid->urbout); - spin_lock(&usbhid->lock); - usb_unblock_urb(usbhid->urbout); - /* - * if the unlinking has already completed - * the pump will have been stopped - * it must be restarted now - */ - if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) - if (!irq_out_pump_restart(hid)) - set_bit(HID_OUT_RUNNING, &usbhid->iofl); - - - } - } - return; - } - - if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { - hid_warn(hid, "control queue full\n"); - return; - } - - if (dir == USB_DIR_OUT) { - usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); - if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { - hid_warn(hid, "control queueing failed\n"); - return; - } - hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report); - } - usbhid->ctrl[usbhid->ctrlhead].report = report; - usbhid->ctrl[usbhid->ctrlhead].dir = dir; - usbhid->ctrlhead = head; - - /* Try to awake from autosuspend... */ - if (usb_autopm_get_interface_async(usbhid->intf) < 0) - return; - - /* - * If already suspended, leave urb enqueued, but don't submit. - * Submission will occur if/when resume() drains the queue. - */ - if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) - return; - - if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { - if (hid_submit_ctrl(hid)) { - clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); - usb_autopm_put_interface_async(usbhid->intf); - } - wake_up(&usbhid->wait); - } else { - /* - * the queue is known to run - * but an earlier request may be stuck - * we may need to time out - * no race because the URB is blocked under - * spinlock - */ - if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { - usb_block_urb(usbhid->urbctrl); - /* drop lock to not deadlock if the callback is called */ - spin_unlock(&usbhid->lock); - usb_unlink_urb(usbhid->urbctrl); - spin_lock(&usbhid->lock); - usb_unblock_urb(usbhid->urbctrl); - /* - * if the unlinking has already completed - * the pump will have been stopped - * it must be restarted now - */ - if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) - if (!ctrl_pump_restart(hid)) - set_bit(HID_CTRL_RUNNING, &usbhid->iofl); - } - } -} - -void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) -{ - struct usbhid_device *usbhid = hid->driver_data; - unsigned long flags; - - spin_lock_irqsave(&usbhid->lock, flags); - __usbhid_submit_report(hid, report, dir); - spin_unlock_irqrestore(&usbhid->lock, flags); -} -EXPORT_SYMBOL_GPL(usbhid_submit_report); - -/* Workqueue routine to send requests to change LEDs */ -static void hid_led(struct work_struct *work) -{ - struct usbhid_device *usbhid = - container_of(work, struct usbhid_device, led_work); - struct hid_device *hid = usbhid->hid; - struct hid_field *field; - unsigned long flags; - - field = hidinput_get_led_field(hid); - if (!field) { - hid_warn(hid, "LED event field not found\n"); - return; - } - - spin_lock_irqsave(&usbhid->lock, flags); - if (!test_bit(HID_DISCONNECTED, &usbhid->iofl)) { - usbhid->ledcount = hidinput_count_leds(hid); - hid_dbg(usbhid->hid, "New ledcount = %u\n", usbhid->ledcount); - __usbhid_submit_report(hid, field->report, USB_DIR_OUT); - } - spin_unlock_irqrestore(&usbhid->lock, flags); -} - -static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct usbhid_device *usbhid = hid->driver_data; - struct hid_field *field; - unsigned long flags; - int offset; - - if (type == EV_FF) - return input_ff_event(dev, type, code, value); - - if (type != EV_LED) - return -1; - - if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { - hid_warn(dev, "event field not found\n"); - return -1; - } - - spin_lock_irqsave(&usbhid->lock, flags); - hid_set_field(field, offset, value); - spin_unlock_irqrestore(&usbhid->lock, flags); - - /* - * Defer performing requested LED action. - * This is more likely gather all LED changes into a single URB. - */ - schedule_work(&usbhid->led_work); - - return 0; -} - -int usbhid_wait_io(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - if (!wait_event_timeout(usbhid->wait, - (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) && - !test_bit(HID_OUT_RUNNING, &usbhid->iofl)), - 10*HZ)) { - dbg_hid("timeout waiting for ctrl or out queue to clear\n"); - return -1; - } - - return 0; -} -EXPORT_SYMBOL_GPL(usbhid_wait_io); - -static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, - ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); -} - -static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, - unsigned char type, void *buf, int size) -{ - int result, retries = 4; - - memset(buf, 0, size); - - do { - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); - retries--; - } while (result < size && retries); - return result; -} - -int usbhid_open(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - int res; - - mutex_lock(&hid_open_mut); - if (!hid->open++) { - res = usb_autopm_get_interface(usbhid->intf); - /* the device must be awake to reliably request remote wakeup */ - if (res < 0) { - hid->open--; - mutex_unlock(&hid_open_mut); - return -EIO; - } - usbhid->intf->needs_remote_wakeup = 1; - if (hid_start_in(hid)) - hid_io_error(hid); - - usb_autopm_put_interface(usbhid->intf); - } - mutex_unlock(&hid_open_mut); - return 0; -} - -void usbhid_close(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - mutex_lock(&hid_open_mut); - - /* protecting hid->open to make sure we don't restart - * data acquistion due to a resumption we no longer - * care about - */ - spin_lock_irq(&usbhid->lock); - if (!--hid->open) { - spin_unlock_irq(&usbhid->lock); - hid_cancel_delayed_stuff(usbhid); - usb_kill_urb(usbhid->urbin); - usbhid->intf->needs_remote_wakeup = 0; - } else { - spin_unlock_irq(&usbhid->lock); - } - mutex_unlock(&hid_open_mut); -} - -/* - * Initialize all reports - */ - -void usbhid_init_reports(struct hid_device *hid) -{ - struct hid_report *report; - struct usbhid_device *usbhid = hid->driver_data; - int err, ret; - - list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) - usbhid_submit_report(hid, report, USB_DIR_IN); - - list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) - usbhid_submit_report(hid, report, USB_DIR_IN); - - err = 0; - ret = usbhid_wait_io(hid); - while (ret) { - err |= ret; - if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) - usb_kill_urb(usbhid->urbctrl); - if (test_bit(HID_OUT_RUNNING, &usbhid->iofl)) - usb_kill_urb(usbhid->urbout); - ret = usbhid_wait_io(hid); - } - - if (err) - hid_warn(hid, "timeout initializing reports\n"); -} - -/* - * Reset LEDs which BIOS might have left on. For now, just NumLock (0x01). - */ -static int hid_find_field_early(struct hid_device *hid, unsigned int page, - unsigned int hid_code, struct hid_field **pfield) -{ - struct hid_report *report; - struct hid_field *field; - struct hid_usage *usage; - int i, j; - - list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { - for (i = 0; i < report->maxfield; i++) { - field = report->field[i]; - for (j = 0; j < field->maxusage; j++) { - usage = &field->usage[j]; - if ((usage->hid & HID_USAGE_PAGE) == page && - (usage->hid & 0xFFFF) == hid_code) { - *pfield = field; - return j; - } - } - } - } - return -1; -} - -void usbhid_set_leds(struct hid_device *hid) -{ - struct hid_field *field; - int offset; - - if ((offset = hid_find_field_early(hid, HID_UP_LED, 0x01, &field)) != -1) { - hid_set_field(field, offset, 0); - usbhid_submit_report(hid, field->report, USB_DIR_OUT); - } -} -EXPORT_SYMBOL_GPL(usbhid_set_leds); - -/* - * Traverse the supplied list of reports and find the longest - */ -static void hid_find_max_report(struct hid_device *hid, unsigned int type, - unsigned int *max) -{ - struct hid_report *report; - unsigned int size; - - list_for_each_entry(report, &hid->report_enum[type].report_list, list) { - size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered; - if (*max < size) - *max = size; - } -} - -static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, - &usbhid->inbuf_dma); - usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, - &usbhid->outbuf_dma); - usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL); - usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, - &usbhid->ctrlbuf_dma); - if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr || - !usbhid->ctrlbuf) - return -1; - - return 0; -} - -static int usbhid_get_raw_report(struct hid_device *hid, - unsigned char report_number, __u8 *buf, size_t count, - unsigned char report_type) -{ - struct usbhid_device *usbhid = hid->driver_data; - struct usb_device *dev = hid_to_usb_dev(hid); - struct usb_interface *intf = usbhid->intf; - struct usb_host_interface *interface = intf->cur_altsetting; - int skipped_report_id = 0; - int ret; - - /* Byte 0 is the report number. Report data starts at byte 1.*/ - buf[0] = report_number; - if (report_number == 0x0) { - /* Offset the return buffer by 1, so that the report ID - will remain in byte 0. */ - buf++; - count--; - skipped_report_id = 1; - } - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - HID_REQ_GET_REPORT, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | report_number, - interface->desc.bInterfaceNumber, buf, count, - USB_CTRL_SET_TIMEOUT); - - /* count also the report id */ - if (ret > 0 && skipped_report_id) - ret++; - - return ret; -} - -static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, - unsigned char report_type) -{ - struct usbhid_device *usbhid = hid->driver_data; - struct usb_device *dev = hid_to_usb_dev(hid); - struct usb_interface *intf = usbhid->intf; - struct usb_host_interface *interface = intf->cur_altsetting; - int ret; - - if (usbhid->urbout && report_type != HID_FEATURE_REPORT) { - int actual_length; - int skipped_report_id = 0; - - if (buf[0] == 0x0) { - /* Don't send the Report ID */ - buf++; - count--; - skipped_report_id = 1; - } - ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, - buf, count, &actual_length, - USB_CTRL_SET_TIMEOUT); - /* return the number of bytes transferred */ - if (ret == 0) { - ret = actual_length; - /* count also the report id */ - if (skipped_report_id) - ret++; - } - } else { - int skipped_report_id = 0; - int report_id = buf[0]; - if (buf[0] == 0x0) { - /* Don't send the Report ID */ - buf++; - count--; - skipped_report_id = 1; - } - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_REPORT, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | report_id, - interface->desc.bInterfaceNumber, buf, count, - USB_CTRL_SET_TIMEOUT); - /* count also the report id, if this was a numbered report. */ - if (ret > 0 && skipped_report_id) - ret++; - } - - return ret; -} - -static void usbhid_restart_queues(struct usbhid_device *usbhid) -{ - if (usbhid->urbout) - usbhid_restart_out_queue(usbhid); - usbhid_restart_ctrl_queue(usbhid); -} - -static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); - usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); - kfree(usbhid->cr); - usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); -} - -static int usbhid_parse(struct hid_device *hid) -{ - struct usb_interface *intf = to_usb_interface(hid->dev.parent); - struct usb_host_interface *interface = intf->cur_altsetting; - struct usb_device *dev = interface_to_usbdev (intf); - struct hid_descriptor *hdesc; - u32 quirks = 0; - unsigned int rsize = 0; - char *rdesc; - int ret, n; - - quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - if (quirks & HID_QUIRK_IGNORE) - return -ENODEV; - - /* Many keyboards and mice don't like to be polled for reports, - * so we will always set the HID_QUIRK_NOGET flag for them. */ - if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { - if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || - interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) - quirks |= HID_QUIRK_NOGET; - } - - if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && - (!interface->desc.bNumEndpoints || - usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { - dbg_hid("class descriptor not present\n"); - return -ENODEV; - } - - hid->version = le16_to_cpu(hdesc->bcdHID); - hid->country = hdesc->bCountryCode; - - for (n = 0; n < hdesc->bNumDescriptors; n++) - if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) - rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); - - if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { - dbg_hid("weird size of report descriptor (%u)\n", rsize); - return -EINVAL; - } - - if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { - dbg_hid("couldn't allocate rdesc memory\n"); - return -ENOMEM; - } - - hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); - - ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, - HID_DT_REPORT, rdesc, rsize); - if (ret < 0) { - dbg_hid("reading report descriptor failed\n"); - kfree(rdesc); - goto err; - } - - ret = hid_parse_report(hid, rdesc, rsize); - kfree(rdesc); - if (ret) { - dbg_hid("parsing report descriptor failed\n"); - goto err; - } - - hid->quirks |= quirks; - - return 0; -err: - return ret; -} - -static int usbhid_start(struct hid_device *hid) -{ - struct usb_interface *intf = to_usb_interface(hid->dev.parent); - struct usb_host_interface *interface = intf->cur_altsetting; - struct usb_device *dev = interface_to_usbdev(intf); - struct usbhid_device *usbhid = hid->driver_data; - unsigned int n, insize = 0; - int ret; - - clear_bit(HID_DISCONNECTED, &usbhid->iofl); - - usbhid->bufsize = HID_MIN_BUFFER_SIZE; - hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); - hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); - hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize); - - if (usbhid->bufsize > HID_MAX_BUFFER_SIZE) - usbhid->bufsize = HID_MAX_BUFFER_SIZE; - - hid_find_max_report(hid, HID_INPUT_REPORT, &insize); - - if (insize > HID_MAX_BUFFER_SIZE) - insize = HID_MAX_BUFFER_SIZE; - - if (hid_alloc_buffers(dev, hid)) { - ret = -ENOMEM; - goto fail; - } - - for (n = 0; n < interface->desc.bNumEndpoints; n++) { - struct usb_endpoint_descriptor *endpoint; - int pipe; - int interval; - - endpoint = &interface->endpoint[n].desc; - if (!usb_endpoint_xfer_int(endpoint)) - continue; - - interval = endpoint->bInterval; - - /* Some vendors give fullspeed interval on highspeed devides */ - if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL && - dev->speed == USB_SPEED_HIGH) { - interval = fls(endpoint->bInterval*8); - printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n", - hid->name, endpoint->bInterval, interval); - } - - /* Change the polling interval of mice. */ - if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) - interval = hid_mousepoll_interval; - - ret = -ENOMEM; - if (usb_endpoint_dir_in(endpoint)) { - if (usbhid->urbin) - continue; - if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL))) - goto fail; - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize, - hid_irq_in, hid, interval); - usbhid->urbin->transfer_dma = usbhid->inbuf_dma; - usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } else { - if (usbhid->urbout) - continue; - if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL))) - goto fail; - pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); - usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0, - hid_irq_out, hid, interval); - usbhid->urbout->transfer_dma = usbhid->outbuf_dma; - usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } - } - - usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); - if (!usbhid->urbctrl) { - ret = -ENOMEM; - goto fail; - } - - usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, - usbhid->ctrlbuf, 1, hid_ctrl, hid); - usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; - usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) - usbhid_init_reports(hid); - - set_bit(HID_STARTED, &usbhid->iofl); - - /* Some keyboards don't work until their LEDs have been set. - * Since BIOSes do set the LEDs, it must be safe for any device - * that supports the keyboard boot protocol. - * In addition, enable remote wakeup by default for all keyboard - * devices supporting the boot protocol. - */ - if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && - interface->desc.bInterfaceProtocol == - USB_INTERFACE_PROTOCOL_KEYBOARD) { - usbhid_set_leds(hid); - device_set_wakeup_enable(&dev->dev, 1); - } - return 0; - -fail: - usb_free_urb(usbhid->urbin); - usb_free_urb(usbhid->urbout); - usb_free_urb(usbhid->urbctrl); - usbhid->urbin = NULL; - usbhid->urbout = NULL; - usbhid->urbctrl = NULL; - hid_free_buffers(dev, hid); - return ret; -} - -static void usbhid_stop(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - if (WARN_ON(!usbhid)) - return; - - clear_bit(HID_STARTED, &usbhid->iofl); - spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ - set_bit(HID_DISCONNECTED, &usbhid->iofl); - spin_unlock_irq(&usbhid->lock); - usb_kill_urb(usbhid->urbin); - usb_kill_urb(usbhid->urbout); - usb_kill_urb(usbhid->urbctrl); - - hid_cancel_delayed_stuff(usbhid); - - hid->claimed = 0; - - usb_free_urb(usbhid->urbin); - usb_free_urb(usbhid->urbctrl); - usb_free_urb(usbhid->urbout); - usbhid->urbin = NULL; /* don't mess up next start */ - usbhid->urbctrl = NULL; - usbhid->urbout = NULL; - - hid_free_buffers(hid_to_usb_dev(hid), hid); -} - -static int usbhid_power(struct hid_device *hid, int lvl) -{ - int r = 0; - - switch (lvl) { - case PM_HINT_FULLON: - r = usbhid_get_power(hid); - break; - case PM_HINT_NORMAL: - usbhid_put_power(hid); - break; - } - return r; -} - -static struct hid_ll_driver usb_hid_driver = { - .parse = usbhid_parse, - .start = usbhid_start, - .stop = usbhid_stop, - .open = usbhid_open, - .close = usbhid_close, - .power = usbhid_power, - .hidinput_input_event = usb_hidinput_input_event, -}; - -static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_host_interface *interface = intf->cur_altsetting; - struct usb_device *dev = interface_to_usbdev(intf); - struct usbhid_device *usbhid; - struct hid_device *hid; - unsigned int n, has_in = 0; - size_t len; - int ret; - - dbg_hid("HID probe called for ifnum %d\n", - intf->altsetting->desc.bInterfaceNumber); - - for (n = 0; n < interface->desc.bNumEndpoints; n++) - if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) - has_in++; - if (!has_in) { - hid_err(intf, "couldn't find an input interrupt endpoint\n"); - return -ENODEV; - } - - hid = hid_allocate_device(); - if (IS_ERR(hid)) - return PTR_ERR(hid); - - usb_set_intfdata(intf, hid); - hid->ll_driver = &usb_hid_driver; - hid->hid_get_raw_report = usbhid_get_raw_report; - hid->hid_output_raw_report = usbhid_output_raw_report; - hid->ff_init = hid_pidff_init; -#ifdef CONFIG_USB_HIDDEV - hid->hiddev_connect = hiddev_connect; - hid->hiddev_disconnect = hiddev_disconnect; - hid->hiddev_hid_event = hiddev_hid_event; - hid->hiddev_report_event = hiddev_report_event; -#endif - hid->dev.parent = &intf->dev; - hid->bus = BUS_USB; - hid->vendor = le16_to_cpu(dev->descriptor.idVendor); - hid->product = le16_to_cpu(dev->descriptor.idProduct); - hid->name[0] = 0; - hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product); - if (intf->cur_altsetting->desc.bInterfaceProtocol == - USB_INTERFACE_PROTOCOL_MOUSE) - hid->type = HID_TYPE_USBMOUSE; - else if (intf->cur_altsetting->desc.bInterfaceProtocol == 0) - hid->type = HID_TYPE_USBNONE; - - if (dev->manufacturer) - strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(hid->name, " ", sizeof(hid->name)); - strlcat(hid->name, dev->product, sizeof(hid->name)); - } - - if (!strlen(hid->name)) - snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, hid->phys, sizeof(hid->phys)); - strlcat(hid->phys, "/input", sizeof(hid->phys)); - len = strlen(hid->phys); - if (len < sizeof(hid->phys) - 1) - snprintf(hid->phys + len, sizeof(hid->phys) - len, - "%d", intf->altsetting[0].desc.bInterfaceNumber); - - if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) - hid->uniq[0] = 0; - - usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL); - if (usbhid == NULL) { - ret = -ENOMEM; - goto err; - } - - hid->driver_data = usbhid; - usbhid->hid = hid; - usbhid->intf = intf; - usbhid->ifnum = interface->desc.bInterfaceNumber; - - init_waitqueue_head(&usbhid->wait); - INIT_WORK(&usbhid->reset_work, hid_reset); - setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); - spin_lock_init(&usbhid->lock); - - INIT_WORK(&usbhid->led_work, hid_led); - - ret = hid_add_device(hid); - if (ret) { - if (ret != -ENODEV) - hid_err(intf, "can't add hid device: %d\n", ret); - goto err_free; - } - - return 0; -err_free: - kfree(usbhid); -err: - hid_destroy_device(hid); - return ret; -} - -static void usbhid_disconnect(struct usb_interface *intf) -{ - struct hid_device *hid = usb_get_intfdata(intf); - struct usbhid_device *usbhid; - - if (WARN_ON(!hid)) - return; - - usbhid = hid->driver_data; - hid_destroy_device(hid); - kfree(usbhid); -} - -static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) -{ - del_timer_sync(&usbhid->io_retry); - cancel_work_sync(&usbhid->reset_work); - cancel_work_sync(&usbhid->led_work); -} - -static void hid_cease_io(struct usbhid_device *usbhid) -{ - del_timer_sync(&usbhid->io_retry); - usb_kill_urb(usbhid->urbin); - usb_kill_urb(usbhid->urbctrl); - usb_kill_urb(usbhid->urbout); -} - -/* Treat USB reset pretty much the same as suspend/resume */ -static int hid_pre_reset(struct usb_interface *intf) -{ - struct hid_device *hid = usb_get_intfdata(intf); - struct usbhid_device *usbhid = hid->driver_data; - - spin_lock_irq(&usbhid->lock); - set_bit(HID_RESET_PENDING, &usbhid->iofl); - spin_unlock_irq(&usbhid->lock); - hid_cease_io(usbhid); - - return 0; -} - -/* Same routine used for post_reset and reset_resume */ -static int hid_post_reset(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev (intf); - struct hid_device *hid = usb_get_intfdata(intf); - struct usbhid_device *usbhid = hid->driver_data; - int status; - - spin_lock_irq(&usbhid->lock); - clear_bit(HID_RESET_PENDING, &usbhid->iofl); - spin_unlock_irq(&usbhid->lock); - hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); - status = hid_start_in(hid); - if (status < 0) - hid_io_error(hid); - usbhid_restart_queues(usbhid); - - return 0; -} - -int usbhid_get_power(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - return usb_autopm_get_interface(usbhid->intf); -} - -void usbhid_put_power(struct hid_device *hid) -{ - struct usbhid_device *usbhid = hid->driver_data; - - usb_autopm_put_interface(usbhid->intf); -} - - -#ifdef CONFIG_PM -static int hid_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct hid_device *hid = usb_get_intfdata(intf); - struct usbhid_device *usbhid = hid->driver_data; - int status; - - if (PMSG_IS_AUTO(message)) { - spin_lock_irq(&usbhid->lock); /* Sync with error handler */ - if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) - && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) - && !test_bit(HID_OUT_RUNNING, &usbhid->iofl) - && !test_bit(HID_CTRL_RUNNING, &usbhid->iofl) - && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl) - && (!usbhid->ledcount || ignoreled)) - { - set_bit(HID_REPORTED_IDLE, &usbhid->iofl); - spin_unlock_irq(&usbhid->lock); - if (hid->driver && hid->driver->suspend) { - status = hid->driver->suspend(hid, message); - if (status < 0) - return status; - } - } else { - usbhid_mark_busy(usbhid); - spin_unlock_irq(&usbhid->lock); - return -EBUSY; - } - - } else { - if (hid->driver && hid->driver->suspend) { - status = hid->driver->suspend(hid, message); - if (status < 0) - return status; - } - spin_lock_irq(&usbhid->lock); - set_bit(HID_REPORTED_IDLE, &usbhid->iofl); - spin_unlock_irq(&usbhid->lock); - if (usbhid_wait_io(hid) < 0) - return -EIO; - } - - hid_cancel_delayed_stuff(usbhid); - hid_cease_io(usbhid); - - if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { - /* lost race against keypresses */ - status = hid_start_in(hid); - if (status < 0) - hid_io_error(hid); - usbhid_mark_busy(usbhid); - return -EBUSY; - } - dev_dbg(&intf->dev, "suspend\n"); - return 0; -} - -static int hid_resume(struct usb_interface *intf) -{ - struct hid_device *hid = usb_get_intfdata (intf); - struct usbhid_device *usbhid = hid->driver_data; - int status; - - if (!test_bit(HID_STARTED, &usbhid->iofl)) - return 0; - - clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); - usbhid_mark_busy(usbhid); - - if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) || - test_bit(HID_RESET_PENDING, &usbhid->iofl)) - schedule_work(&usbhid->reset_work); - usbhid->retry_delay = 0; - status = hid_start_in(hid); - if (status < 0) - hid_io_error(hid); - usbhid_restart_queues(usbhid); - - if (status >= 0 && hid->driver && hid->driver->resume) { - int ret = hid->driver->resume(hid); - if (ret < 0) - status = ret; - } - dev_dbg(&intf->dev, "resume status %d\n", status); - return 0; -} - -static int hid_reset_resume(struct usb_interface *intf) -{ - struct hid_device *hid = usb_get_intfdata(intf); - struct usbhid_device *usbhid = hid->driver_data; - int status; - - clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); - status = hid_post_reset(intf); - if (status >= 0 && hid->driver && hid->driver->reset_resume) { - int ret = hid->driver->reset_resume(hid); - if (ret < 0) - status = ret; - } - return status; -} - -#endif /* CONFIG_PM */ - -static const struct usb_device_id hid_usb_ids[] = { - { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, - .bInterfaceClass = USB_INTERFACE_CLASS_HID }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, hid_usb_ids); - -static struct usb_driver hid_driver = { - .name = "usbhid", - .probe = usbhid_probe, - .disconnect = usbhid_disconnect, -#ifdef CONFIG_PM - .suspend = hid_suspend, - .resume = hid_resume, - .reset_resume = hid_reset_resume, -#endif - .pre_reset = hid_pre_reset, - .post_reset = hid_post_reset, - .id_table = hid_usb_ids, - .supports_autosuspend = 1, -}; - -static const struct hid_device_id hid_usb_table[] = { - { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, - { } -}; - -struct usb_interface *usbhid_find_interface(int minor) -{ - return usb_find_interface(&hid_driver, minor); -} - -static struct hid_driver hid_usb_driver = { - .name = "generic-usb", - .id_table = hid_usb_table, -}; - -static int __init hid_init(void) -{ - int retval = -ENOMEM; - - retval = hid_register_driver(&hid_usb_driver); - if (retval) - goto hid_register_fail; - retval = usbhid_quirks_init(quirks_param); - if (retval) - goto usbhid_quirks_init_fail; - retval = usb_register(&hid_driver); - if (retval) - goto usb_register_fail; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - - return 0; -usb_register_fail: - usbhid_quirks_exit(); -usbhid_quirks_init_fail: - hid_unregister_driver(&hid_usb_driver); -hid_register_fail: - return retval; -} - -static void __exit hid_exit(void) -{ - usb_deregister(&hid_driver); - usbhid_quirks_exit(); - hid_unregister_driver(&hid_usb_driver); -} - -module_init(hid_init); -module_exit(hid_exit); - -MODULE_AUTHOR("Andreas Gal"); -MODULE_AUTHOR("Vojtech Pavlik"); -MODULE_AUTHOR("Jiri Kosina"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/hid-pidff.c b/ANDROID_3.4.5/drivers/hid/usbhid/hid-pidff.c deleted file mode 100644 index f91c1368..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/hid-pidff.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * Force feedback driver for USB HID PID compliant devices - * - * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* #define DEBUG */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include <linux/hid.h> - -#include "usbhid.h" - -#define PID_EFFECTS_MAX 64 - -/* Report usage table used to put reports into an array */ - -#define PID_SET_EFFECT 0 -#define PID_EFFECT_OPERATION 1 -#define PID_DEVICE_GAIN 2 -#define PID_POOL 3 -#define PID_BLOCK_LOAD 4 -#define PID_BLOCK_FREE 5 -#define PID_DEVICE_CONTROL 6 -#define PID_CREATE_NEW_EFFECT 7 - -#define PID_REQUIRED_REPORTS 7 - -#define PID_SET_ENVELOPE 8 -#define PID_SET_CONDITION 9 -#define PID_SET_PERIODIC 10 -#define PID_SET_CONSTANT 11 -#define PID_SET_RAMP 12 -static const u8 pidff_reports[] = { - 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, - 0x5a, 0x5f, 0x6e, 0x73, 0x74 -}; - -/* device_control is really 0x95, but 0x96 specified as it is the usage of -the only field in that report */ - -/* Value usage tables used to put fields and values into arrays */ - -#define PID_EFFECT_BLOCK_INDEX 0 - -#define PID_DURATION 1 -#define PID_GAIN 2 -#define PID_TRIGGER_BUTTON 3 -#define PID_TRIGGER_REPEAT_INT 4 -#define PID_DIRECTION_ENABLE 5 -#define PID_START_DELAY 6 -static const u8 pidff_set_effect[] = { - 0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7 -}; - -#define PID_ATTACK_LEVEL 1 -#define PID_ATTACK_TIME 2 -#define PID_FADE_LEVEL 3 -#define PID_FADE_TIME 4 -static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e }; - -#define PID_PARAM_BLOCK_OFFSET 1 -#define PID_CP_OFFSET 2 -#define PID_POS_COEFFICIENT 3 -#define PID_NEG_COEFFICIENT 4 -#define PID_POS_SATURATION 5 -#define PID_NEG_SATURATION 6 -#define PID_DEAD_BAND 7 -static const u8 pidff_set_condition[] = { - 0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 -}; - -#define PID_MAGNITUDE 1 -#define PID_OFFSET 2 -#define PID_PHASE 3 -#define PID_PERIOD 4 -static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 }; -static const u8 pidff_set_constant[] = { 0x22, 0x70 }; - -#define PID_RAMP_START 1 -#define PID_RAMP_END 2 -static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 }; - -#define PID_RAM_POOL_AVAILABLE 1 -static const u8 pidff_block_load[] = { 0x22, 0xac }; - -#define PID_LOOP_COUNT 1 -static const u8 pidff_effect_operation[] = { 0x22, 0x7c }; - -static const u8 pidff_block_free[] = { 0x22 }; - -#define PID_DEVICE_GAIN_FIELD 0 -static const u8 pidff_device_gain[] = { 0x7e }; - -#define PID_RAM_POOL_SIZE 0 -#define PID_SIMULTANEOUS_MAX 1 -#define PID_DEVICE_MANAGED_POOL 2 -static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; - -/* Special field key tables used to put special field keys into arrays */ - -#define PID_ENABLE_ACTUATORS 0 -#define PID_RESET 1 -static const u8 pidff_device_control[] = { 0x97, 0x9a }; - -#define PID_CONSTANT 0 -#define PID_RAMP 1 -#define PID_SQUARE 2 -#define PID_SINE 3 -#define PID_TRIANGLE 4 -#define PID_SAW_UP 5 -#define PID_SAW_DOWN 6 -#define PID_SPRING 7 -#define PID_DAMPER 8 -#define PID_INERTIA 9 -#define PID_FRICTION 10 -static const u8 pidff_effect_types[] = { - 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, - 0x40, 0x41, 0x42, 0x43 -}; - -#define PID_BLOCK_LOAD_SUCCESS 0 -#define PID_BLOCK_LOAD_FULL 1 -static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; - -#define PID_EFFECT_START 0 -#define PID_EFFECT_STOP 1 -static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; - -struct pidff_usage { - struct hid_field *field; - s32 *value; -}; - -struct pidff_device { - struct hid_device *hid; - - struct hid_report *reports[sizeof(pidff_reports)]; - - struct pidff_usage set_effect[sizeof(pidff_set_effect)]; - struct pidff_usage set_envelope[sizeof(pidff_set_envelope)]; - struct pidff_usage set_condition[sizeof(pidff_set_condition)]; - struct pidff_usage set_periodic[sizeof(pidff_set_periodic)]; - struct pidff_usage set_constant[sizeof(pidff_set_constant)]; - struct pidff_usage set_ramp[sizeof(pidff_set_ramp)]; - - struct pidff_usage device_gain[sizeof(pidff_device_gain)]; - struct pidff_usage block_load[sizeof(pidff_block_load)]; - struct pidff_usage pool[sizeof(pidff_pool)]; - struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; - struct pidff_usage block_free[sizeof(pidff_block_free)]; - - /* Special field is a field that is not composed of - usage<->value pairs that pidff_usage values are */ - - /* Special field in create_new_effect */ - struct hid_field *create_new_effect_type; - - /* Special fields in set_effect */ - struct hid_field *set_effect_type; - struct hid_field *effect_direction; - - /* Special field in device_control */ - struct hid_field *device_control; - - /* Special field in block_load */ - struct hid_field *block_load_status; - - /* Special field in effect_operation */ - struct hid_field *effect_operation_status; - - int control_id[sizeof(pidff_device_control)]; - int type_id[sizeof(pidff_effect_types)]; - int status_id[sizeof(pidff_block_load_status)]; - int operation_id[sizeof(pidff_effect_operation_status)]; - - int pid_id[PID_EFFECTS_MAX]; -}; - -/* - * Scale an unsigned value with range 0..max for the given field - */ -static int pidff_rescale(int i, int max, struct hid_field *field) -{ - return i * (field->logical_maximum - field->logical_minimum) / max + - field->logical_minimum; -} - -/* - * Scale a signed value in range -0x8000..0x7fff for the given field - */ -static int pidff_rescale_signed(int i, struct hid_field *field) -{ - return i == 0 ? 0 : i > - 0 ? i * field->logical_maximum / 0x7fff : i * - field->logical_minimum / -0x8000; -} - -static void pidff_set(struct pidff_usage *usage, u16 value) -{ - usage->value[0] = pidff_rescale(value, 0xffff, usage->field); - pr_debug("calculated from %d to %d\n", value, usage->value[0]); -} - -static void pidff_set_signed(struct pidff_usage *usage, s16 value) -{ - if (usage->field->logical_minimum < 0) - usage->value[0] = pidff_rescale_signed(value, usage->field); - else { - if (value < 0) - usage->value[0] = - pidff_rescale(-value, 0x8000, usage->field); - else - usage->value[0] = - pidff_rescale(value, 0x7fff, usage->field); - } - pr_debug("calculated from %d to %d\n", value, usage->value[0]); -} - -/* - * Send envelope report to the device - */ -static void pidff_set_envelope_report(struct pidff_device *pidff, - struct ff_envelope *envelope) -{ - pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - - pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = - pidff_rescale(envelope->attack_level > - 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, - pidff->set_envelope[PID_ATTACK_LEVEL].field); - pidff->set_envelope[PID_FADE_LEVEL].value[0] = - pidff_rescale(envelope->fade_level > - 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, - pidff->set_envelope[PID_FADE_LEVEL].field); - - pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; - pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; - - hid_dbg(pidff->hid, "attack %u => %d\n", - envelope->attack_level, - pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); - - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], - USB_DIR_OUT); -} - -/* - * Test if the new envelope differs from old one - */ -static int pidff_needs_set_envelope(struct ff_envelope *envelope, - struct ff_envelope *old) -{ - return envelope->attack_level != old->attack_level || - envelope->fade_level != old->fade_level || - envelope->attack_length != old->attack_length || - envelope->fade_length != old->fade_length; -} - -/* - * Send constant force report to the device - */ -static void pidff_set_constant_force_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], - effect->u.constant.level); - - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], - USB_DIR_OUT); -} - -/* - * Test if the constant parameters have changed between effects - */ -static int pidff_needs_set_constant(struct ff_effect *effect, - struct ff_effect *old) -{ - return effect->u.constant.level != old->u.constant.level; -} - -/* - * Send set effect report to the device - */ -static void pidff_set_effect_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff->set_effect_type->value[0] = - pidff->create_new_effect_type->value[0]; - pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; - pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; - pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = - effect->trigger.interval; - pidff->set_effect[PID_GAIN].value[0] = - pidff->set_effect[PID_GAIN].field->logical_maximum; - pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; - pidff->effect_direction->value[0] = - pidff_rescale(effect->direction, 0xffff, - pidff->effect_direction); - pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; - - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], - USB_DIR_OUT); -} - -/* - * Test if the values used in set_effect have changed - */ -static int pidff_needs_set_effect(struct ff_effect *effect, - struct ff_effect *old) -{ - return effect->replay.length != old->replay.length || - effect->trigger.interval != old->trigger.interval || - effect->trigger.button != old->trigger.button || - effect->direction != old->direction || - effect->replay.delay != old->replay.delay; -} - -/* - * Send periodic effect report to the device - */ -static void pidff_set_periodic_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE], - effect->u.periodic.magnitude); - pidff_set_signed(&pidff->set_periodic[PID_OFFSET], - effect->u.periodic.offset); - pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); - pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; - - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], - USB_DIR_OUT); - -} - -/* - * Test if periodic effect parameters have changed - */ -static int pidff_needs_set_periodic(struct ff_effect *effect, - struct ff_effect *old) -{ - return effect->u.periodic.magnitude != old->u.periodic.magnitude || - effect->u.periodic.offset != old->u.periodic.offset || - effect->u.periodic.phase != old->u.periodic.phase || - effect->u.periodic.period != old->u.periodic.period; -} - -/* - * Send condition effect reports to the device - */ -static void pidff_set_condition_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - int i; - - pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - - for (i = 0; i < 2; i++) { - pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; - pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], - effect->u.condition[i].center); - pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], - effect->u.condition[i].right_coeff); - pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT], - effect->u.condition[i].left_coeff); - pidff_set(&pidff->set_condition[PID_POS_SATURATION], - effect->u.condition[i].right_saturation); - pidff_set(&pidff->set_condition[PID_NEG_SATURATION], - effect->u.condition[i].left_saturation); - pidff_set(&pidff->set_condition[PID_DEAD_BAND], - effect->u.condition[i].deadband); - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], - USB_DIR_OUT); - } -} - -/* - * Test if condition effect parameters have changed - */ -static int pidff_needs_set_condition(struct ff_effect *effect, - struct ff_effect *old) -{ - int i; - int ret = 0; - - for (i = 0; i < 2; i++) { - struct ff_condition_effect *cond = &effect->u.condition[i]; - struct ff_condition_effect *old_cond = &old->u.condition[i]; - - ret |= cond->center != old_cond->center || - cond->right_coeff != old_cond->right_coeff || - cond->left_coeff != old_cond->left_coeff || - cond->right_saturation != old_cond->right_saturation || - cond->left_saturation != old_cond->left_saturation || - cond->deadband != old_cond->deadband; - } - - return ret; -} - -/* - * Send ramp force report to the device - */ -static void pidff_set_ramp_force_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff_set_signed(&pidff->set_ramp[PID_RAMP_START], - effect->u.ramp.start_level); - pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], - effect->u.ramp.end_level); - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], - USB_DIR_OUT); -} - -/* - * Test if ramp force parameters have changed - */ -static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) -{ - return effect->u.ramp.start_level != old->u.ramp.start_level || - effect->u.ramp.end_level != old->u.ramp.end_level; -} - -/* - * Send a request for effect upload to the device - * - * Returns 0 if device reported success, -ENOSPC if the device reported memory - * is full. Upon unknown response the function will retry for 60 times, if - * still unsuccessful -EIO is returned. - */ -static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) -{ - int j; - - pidff->create_new_effect_type->value[0] = efnum; - usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], - USB_DIR_OUT); - hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum); - - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; - pidff->block_load_status->value[0] = 0; - usbhid_wait_io(pidff->hid); - - for (j = 0; j < 60; j++) { - hid_dbg(pidff->hid, "pid_block_load requested\n"); - usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], - USB_DIR_IN); - usbhid_wait_io(pidff->hid); - if (pidff->block_load_status->value[0] == - pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { - hid_dbg(pidff->hid, "device reported free memory: %d bytes\n", - pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? - pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); - return 0; - } - if (pidff->block_load_status->value[0] == - pidff->status_id[PID_BLOCK_LOAD_FULL]) { - hid_dbg(pidff->hid, "not enough memory free: %d bytes\n", - pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? - pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); - return -ENOSPC; - } - } - hid_err(pidff->hid, "pid_block_load failed 60 times\n"); - return -EIO; -} - -/* - * Play the effect with PID id n times - */ -static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) -{ - pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; - - if (n == 0) { - pidff->effect_operation_status->value[0] = - pidff->operation_id[PID_EFFECT_STOP]; - } else { - pidff->effect_operation_status->value[0] = - pidff->operation_id[PID_EFFECT_START]; - pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; - } - - usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], - USB_DIR_OUT); -} - -/** - * Play the effect with effect id @effect_id for @value times - */ -static int pidff_playback(struct input_dev *dev, int effect_id, int value) -{ - struct pidff_device *pidff = dev->ff->private; - - pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); - - return 0; -} - -/* - * Erase effect with PID id - */ -static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) -{ - pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; - usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], - USB_DIR_OUT); -} - -/* - * Stop and erase effect with effect_id - */ -static int pidff_erase_effect(struct input_dev *dev, int effect_id) -{ - struct pidff_device *pidff = dev->ff->private; - int pid_id = pidff->pid_id[effect_id]; - - hid_dbg(pidff->hid, "starting to erase %d/%d\n", - effect_id, pidff->pid_id[effect_id]); - /* Wait for the queue to clear. We do not want a full fifo to - prevent the effect removal. */ - usbhid_wait_io(pidff->hid); - pidff_playback_pid(pidff, pid_id, 0); - pidff_erase_pid(pidff, pid_id); - - return 0; -} - -/* - * Effect upload handler - */ -static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, - struct ff_effect *old) -{ - struct pidff_device *pidff = dev->ff->private; - int type_id; - int error; - - switch (effect->type) { - case FF_CONSTANT: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_CONSTANT]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_constant(effect, old)) - pidff_set_constant_force_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.constant.envelope, - &old->u.constant.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.constant.envelope); - break; - - case FF_PERIODIC: - if (!old) { - switch (effect->u.periodic.waveform) { - case FF_SQUARE: - type_id = PID_SQUARE; - break; - case FF_TRIANGLE: - type_id = PID_TRIANGLE; - break; - case FF_SINE: - type_id = PID_SINE; - break; - case FF_SAW_UP: - type_id = PID_SAW_UP; - break; - case FF_SAW_DOWN: - type_id = PID_SAW_DOWN; - break; - default: - hid_err(pidff->hid, "invalid waveform\n"); - return -EINVAL; - } - - error = pidff_request_effect_upload(pidff, - pidff->type_id[type_id]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_periodic(effect, old)) - pidff_set_periodic_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.periodic.envelope, - &old->u.periodic.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.periodic.envelope); - break; - - case FF_RAMP: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_RAMP]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_ramp(effect, old)) - pidff_set_ramp_force_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.ramp.envelope, - &old->u.ramp.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.ramp.envelope); - break; - - case FF_SPRING: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_SPRING]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_FRICTION: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_FRICTION]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_DAMPER: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_DAMPER]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_INERTIA: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_INERTIA]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - default: - hid_err(pidff->hid, "invalid type\n"); - return -EINVAL; - } - - if (!old) - pidff->pid_id[effect->id] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - - hid_dbg(pidff->hid, "uploaded\n"); - - return 0; -} - -/* - * set_gain() handler - */ -static void pidff_set_gain(struct input_dev *dev, u16 gain) -{ - struct pidff_device *pidff = dev->ff->private; - - pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); - usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); -} - -static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) -{ - struct hid_field *field = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field; - - if (!magnitude) { - pidff_playback_pid(pidff, field->logical_minimum, 0); - return; - } - - pidff_playback_pid(pidff, field->logical_minimum, 1); - - pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum; - pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING]; - pidff->set_effect[PID_DURATION].value[0] = 0; - pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; - pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; - pidff_set(&pidff->set_effect[PID_GAIN], magnitude); - pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; - pidff->set_effect[PID_START_DELAY].value[0] = 0; - - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], - USB_DIR_OUT); -} - -/* - * pidff_set_autocenter() handler - */ -static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) -{ - struct pidff_device *pidff = dev->ff->private; - - pidff_autocenter(pidff, magnitude); -} - -/* - * Find fields from a report and fill a pidff_usage - */ -static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, - struct hid_report *report, int count, int strict) -{ - int i, j, k, found; - - for (k = 0; k < count; k++) { - found = 0; - for (i = 0; i < report->maxfield; i++) { - if (report->field[i]->maxusage != - report->field[i]->report_count) { - pr_debug("maxusage and report_count do not match, skipping\n"); - continue; - } - for (j = 0; j < report->field[i]->maxusage; j++) { - if (report->field[i]->usage[j].hid == - (HID_UP_PID | table[k])) { - pr_debug("found %d at %d->%d\n", - k, i, j); - usage[k].field = report->field[i]; - usage[k].value = - &report->field[i]->value[j]; - found = 1; - break; - } - } - if (found) - break; - } - if (!found && strict) { - pr_debug("failed to locate %d\n", k); - return -1; - } - } - return 0; -} - -/* - * Return index into pidff_reports for the given usage - */ -static int pidff_check_usage(int usage) -{ - int i; - - for (i = 0; i < sizeof(pidff_reports); i++) - if (usage == (HID_UP_PID | pidff_reports[i])) - return i; - - return -1; -} - -/* - * Find the reports and fill pidff->reports[] - * report_type specifies either OUTPUT or FEATURE reports - */ -static void pidff_find_reports(struct hid_device *hid, int report_type, - struct pidff_device *pidff) -{ - struct hid_report *report; - int i, ret; - - list_for_each_entry(report, - &hid->report_enum[report_type].report_list, list) { - if (report->maxfield < 1) - continue; - ret = pidff_check_usage(report->field[0]->logical); - if (ret != -1) { - hid_dbg(hid, "found usage 0x%02x from field->logical\n", - pidff_reports[ret]); - pidff->reports[ret] = report; - continue; - } - - /* - * Sometimes logical collections are stacked to indicate - * different usages for the report and the field, in which - * case we want the usage of the parent. However, Linux HID - * implementation hides this fact, so we have to dig it up - * ourselves - */ - i = report->field[0]->usage[0].collection_index; - if (i <= 0 || - hid->collection[i - 1].type != HID_COLLECTION_LOGICAL) - continue; - ret = pidff_check_usage(hid->collection[i - 1].usage); - if (ret != -1 && !pidff->reports[ret]) { - hid_dbg(hid, - "found usage 0x%02x from collection array\n", - pidff_reports[ret]); - pidff->reports[ret] = report; - } - } -} - -/* - * Test if the required reports have been found - */ -static int pidff_reports_ok(struct pidff_device *pidff) -{ - int i; - - for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { - if (!pidff->reports[i]) { - hid_dbg(pidff->hid, "%d missing\n", i); - return 0; - } - } - - return 1; -} - -/* - * Find a field with a specific usage within a report - */ -static struct hid_field *pidff_find_special_field(struct hid_report *report, - int usage, int enforce_min) -{ - int i; - - for (i = 0; i < report->maxfield; i++) { - if (report->field[i]->logical == (HID_UP_PID | usage) && - report->field[i]->report_count > 0) { - if (!enforce_min || - report->field[i]->logical_minimum == 1) - return report->field[i]; - else { - pr_err("logical_minimum is not 1 as it should be\n"); - return NULL; - } - } - } - return NULL; -} - -/* - * Fill a pidff->*_id struct table - */ -static int pidff_find_special_keys(int *keys, struct hid_field *fld, - const u8 *usagetable, int count) -{ - - int i, j; - int found = 0; - - for (i = 0; i < count; i++) { - for (j = 0; j < fld->maxusage; j++) { - if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) { - keys[i] = j + 1; - found++; - break; - } - } - } - return found; -} - -#define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \ - pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \ - sizeof(pidff_ ## name)) - -/* - * Find and check the special fields - */ -static int pidff_find_special_fields(struct pidff_device *pidff) -{ - hid_dbg(pidff->hid, "finding special fields\n"); - - pidff->create_new_effect_type = - pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], - 0x25, 1); - pidff->set_effect_type = - pidff_find_special_field(pidff->reports[PID_SET_EFFECT], - 0x25, 1); - pidff->effect_direction = - pidff_find_special_field(pidff->reports[PID_SET_EFFECT], - 0x57, 0); - pidff->device_control = - pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], - 0x96, 1); - pidff->block_load_status = - pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], - 0x8b, 1); - pidff->effect_operation_status = - pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], - 0x78, 1); - - hid_dbg(pidff->hid, "search done\n"); - - if (!pidff->create_new_effect_type || !pidff->set_effect_type) { - hid_err(pidff->hid, "effect lists not found\n"); - return -1; - } - - if (!pidff->effect_direction) { - hid_err(pidff->hid, "direction field not found\n"); - return -1; - } - - if (!pidff->device_control) { - hid_err(pidff->hid, "device control field not found\n"); - return -1; - } - - if (!pidff->block_load_status) { - hid_err(pidff->hid, "block load status field not found\n"); - return -1; - } - - if (!pidff->effect_operation_status) { - hid_err(pidff->hid, "effect operation field not found\n"); - return -1; - } - - pidff_find_special_keys(pidff->control_id, pidff->device_control, - pidff_device_control, - sizeof(pidff_device_control)); - - PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); - - if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, - effect_types)) { - hid_err(pidff->hid, "no effect types found\n"); - return -1; - } - - if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, - block_load_status) != - sizeof(pidff_block_load_status)) { - hid_err(pidff->hid, - "block load status identifiers not found\n"); - return -1; - } - - if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, - effect_operation_status) != - sizeof(pidff_effect_operation_status)) { - hid_err(pidff->hid, "effect operation identifiers not found\n"); - return -1; - } - - return 0; -} - -/** - * Find the implemented effect types - */ -static int pidff_find_effects(struct pidff_device *pidff, - struct input_dev *dev) -{ - int i; - - for (i = 0; i < sizeof(pidff_effect_types); i++) { - int pidff_type = pidff->type_id[i]; - if (pidff->set_effect_type->usage[pidff_type].hid != - pidff->create_new_effect_type->usage[pidff_type].hid) { - hid_err(pidff->hid, - "effect type number %d is invalid\n", i); - return -1; - } - } - - if (pidff->type_id[PID_CONSTANT]) - set_bit(FF_CONSTANT, dev->ffbit); - if (pidff->type_id[PID_RAMP]) - set_bit(FF_RAMP, dev->ffbit); - if (pidff->type_id[PID_SQUARE]) { - set_bit(FF_SQUARE, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SINE]) { - set_bit(FF_SINE, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_TRIANGLE]) { - set_bit(FF_TRIANGLE, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SAW_UP]) { - set_bit(FF_SAW_UP, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SAW_DOWN]) { - set_bit(FF_SAW_DOWN, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SPRING]) - set_bit(FF_SPRING, dev->ffbit); - if (pidff->type_id[PID_DAMPER]) - set_bit(FF_DAMPER, dev->ffbit); - if (pidff->type_id[PID_INERTIA]) - set_bit(FF_INERTIA, dev->ffbit); - if (pidff->type_id[PID_FRICTION]) - set_bit(FF_FRICTION, dev->ffbit); - - return 0; - -} - -#define PIDFF_FIND_FIELDS(name, report, strict) \ - pidff_find_fields(pidff->name, pidff_ ## name, \ - pidff->reports[report], \ - sizeof(pidff_ ## name), strict) - -/* - * Fill and check the pidff_usages - */ -static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) -{ - int envelope_ok = 0; - - if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { - hid_err(pidff->hid, "unknown set_effect report layout\n"); - return -ENODEV; - } - - PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); - if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { - hid_err(pidff->hid, "unknown pid_block_load report layout\n"); - return -ENODEV; - } - - if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { - hid_err(pidff->hid, "unknown effect_operation report layout\n"); - return -ENODEV; - } - - if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { - hid_err(pidff->hid, "unknown pid_block_free report layout\n"); - return -ENODEV; - } - - if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) - envelope_ok = 1; - - if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) - return -ENODEV; - - if (!envelope_ok) { - if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) - hid_warn(pidff->hid, - "has constant effect but no envelope\n"); - if (test_and_clear_bit(FF_RAMP, dev->ffbit)) - hid_warn(pidff->hid, - "has ramp effect but no envelope\n"); - - if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) - hid_warn(pidff->hid, - "has periodic effect but no envelope\n"); - } - - if (test_bit(FF_CONSTANT, dev->ffbit) && - PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { - hid_warn(pidff->hid, "unknown constant effect layout\n"); - clear_bit(FF_CONSTANT, dev->ffbit); - } - - if (test_bit(FF_RAMP, dev->ffbit) && - PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { - hid_warn(pidff->hid, "unknown ramp effect layout\n"); - clear_bit(FF_RAMP, dev->ffbit); - } - - if ((test_bit(FF_SPRING, dev->ffbit) || - test_bit(FF_DAMPER, dev->ffbit) || - test_bit(FF_FRICTION, dev->ffbit) || - test_bit(FF_INERTIA, dev->ffbit)) && - PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { - hid_warn(pidff->hid, "unknown condition effect layout\n"); - clear_bit(FF_SPRING, dev->ffbit); - clear_bit(FF_DAMPER, dev->ffbit); - clear_bit(FF_FRICTION, dev->ffbit); - clear_bit(FF_INERTIA, dev->ffbit); - } - - if (test_bit(FF_PERIODIC, dev->ffbit) && - PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { - hid_warn(pidff->hid, "unknown periodic effect layout\n"); - clear_bit(FF_PERIODIC, dev->ffbit); - } - - PIDFF_FIND_FIELDS(pool, PID_POOL, 0); - - if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1)) - set_bit(FF_GAIN, dev->ffbit); - - return 0; -} - -/* - * Reset the device - */ -static void pidff_reset(struct pidff_device *pidff) -{ - struct hid_device *hid = pidff->hid; - int i = 0; - - pidff->device_control->value[0] = pidff->control_id[PID_RESET]; - /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - usbhid_wait_io(hid); - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - usbhid_wait_io(hid); - - pidff->device_control->value[0] = - pidff->control_id[PID_ENABLE_ACTUATORS]; - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - usbhid_wait_io(hid); - - /* pool report is sometimes messed up, refetch it */ - usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); - usbhid_wait_io(hid); - - if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { - while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { - if (i++ > 20) { - hid_warn(pidff->hid, - "device reports %d simultaneous effects\n", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); - break; - } - hid_dbg(pidff->hid, "pid_pool requested again\n"); - usbhid_submit_report(hid, pidff->reports[PID_POOL], - USB_DIR_IN); - usbhid_wait_io(hid); - } - } -} - -/* - * Test if autocenter modification is using the supported method - */ -static int pidff_check_autocenter(struct pidff_device *pidff, - struct input_dev *dev) -{ - int error; - - /* - * Let's find out if autocenter modification is supported - * Specification doesn't specify anything, so we request an - * effect upload and cancel it immediately. If the approved - * effect id was one above the minimum, then we assume the first - * effect id is a built-in spring type effect used for autocenter - */ - - error = pidff_request_effect_upload(pidff, 1); - if (error) { - hid_err(pidff->hid, "upload request failed\n"); - return error; - } - - if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { - pidff_autocenter(pidff, 0xffff); - set_bit(FF_AUTOCENTER, dev->ffbit); - } else { - hid_notice(pidff->hid, - "device has unknown autocenter control method\n"); - } - - pidff_erase_pid(pidff, - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); - - return 0; - -} - -/* - * Check if the device is PID and initialize it - */ -int hid_pidff_init(struct hid_device *hid) -{ - struct pidff_device *pidff; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct input_dev *dev = hidinput->input; - struct ff_device *ff; - int max_effects; - int error; - - hid_dbg(hid, "starting pid init\n"); - - if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { - hid_dbg(hid, "not a PID device, no output report\n"); - return -ENODEV; - } - - pidff = kzalloc(sizeof(*pidff), GFP_KERNEL); - if (!pidff) - return -ENOMEM; - - pidff->hid = hid; - - pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff); - pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); - - if (!pidff_reports_ok(pidff)) { - hid_dbg(hid, "reports not ok, aborting\n"); - error = -ENODEV; - goto fail; - } - - error = pidff_init_fields(pidff, dev); - if (error) - goto fail; - - pidff_reset(pidff); - - if (test_bit(FF_GAIN, dev->ffbit)) { - pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); - } - - error = pidff_check_autocenter(pidff, dev); - if (error) - goto fail; - - max_effects = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + - 1; - hid_dbg(hid, "max effects is %d\n", max_effects); - - if (max_effects > PID_EFFECTS_MAX) - max_effects = PID_EFFECTS_MAX; - - if (pidff->pool[PID_SIMULTANEOUS_MAX].value) - hid_dbg(hid, "max simultaneous effects is %d\n", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); - - if (pidff->pool[PID_RAM_POOL_SIZE].value) - hid_dbg(hid, "device memory size is %d bytes\n", - pidff->pool[PID_RAM_POOL_SIZE].value[0]); - - if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && - pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { - hid_notice(hid, - "device does not support device managed pool\n"); - goto fail; - } - - error = input_ff_create(dev, max_effects); - if (error) - goto fail; - - ff = dev->ff; - ff->private = pidff; - ff->upload = pidff_upload_effect; - ff->erase = pidff_erase_effect; - ff->set_gain = pidff_set_gain; - ff->set_autocenter = pidff_set_autocenter; - ff->playback = pidff_playback; - - hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); - - return 0; - - fail: - kfree(pidff); - return error; -} diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/hid-quirks.c b/ANDROID_3.4.5/drivers/hid/usbhid/hid-quirks.c deleted file mode 100644 index 782c6395..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/hid-quirks.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * USB HID quirks support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - * Copyright (c) 2006-2007 Jiri Kosina - * Copyright (c) 2007 Paul Walmsley - */ - -/* - * 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/hid.h> -#include <linux/export.h> -#include <linux/slab.h> - -#include "../hid-ids.h" - -/* - * Alphabetically sorted blacklist by quirk type. - */ - -static const struct hid_blacklist { - __u16 idVendor; - __u16 idProduct; - __u32 quirks; -} hid_blacklist[] = { - { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, - { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN, HID_QUIRK_MULTI_INPUT}, - { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, - - { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, - - { USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, - - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, - { 0, 0 } -}; - -/* Dynamic HID quirks list - specified at runtime */ -struct quirks_list_struct { - struct hid_blacklist hid_bl_item; - struct list_head node; -}; - -static LIST_HEAD(dquirks_list); -static DECLARE_RWSEM(dquirks_rwsem); - -/* Runtime ("dynamic") quirks manipulation functions */ - -/** - * usbhid_exists_dquirk: find any dynamic quirks for a USB HID device - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * - * Description: - * Scans dquirks_list for a matching dynamic quirk and returns - * the pointer to the relevant struct hid_blacklist if found. - * Must be called with a read lock held on dquirks_rwsem. - * - * Returns: NULL if no quirk found, struct hid_blacklist * if found. - */ -static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor, - const u16 idProduct) -{ - struct quirks_list_struct *q; - struct hid_blacklist *bl_entry = NULL; - - list_for_each_entry(q, &dquirks_list, node) { - if (q->hid_bl_item.idVendor == idVendor && - q->hid_bl_item.idProduct == idProduct) { - bl_entry = &q->hid_bl_item; - break; - } - } - - if (bl_entry != NULL) - dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n", - bl_entry->quirks, bl_entry->idVendor, - bl_entry->idProduct); - - return bl_entry; -} - - -/** - * usbhid_modify_dquirk: add/replace a HID quirk - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * @quirks: the u32 quirks value to add/replace - * - * Description: - * If an dynamic quirk exists in memory for this (idVendor, - * idProduct) pair, replace its quirks value with what was - * provided. Otherwise, add the quirk to the dynamic quirks list. - * - * Returns: 0 OK, -error on failure. - */ -static int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, - const u32 quirks) -{ - struct quirks_list_struct *q_new, *q; - int list_edited = 0; - - if (!idVendor) { - dbg_hid("Cannot add a quirk with idVendor = 0\n"); - return -EINVAL; - } - - q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL); - if (!q_new) { - dbg_hid("Could not allocate quirks_list_struct\n"); - return -ENOMEM; - } - - q_new->hid_bl_item.idVendor = idVendor; - q_new->hid_bl_item.idProduct = idProduct; - q_new->hid_bl_item.quirks = quirks; - - down_write(&dquirks_rwsem); - - list_for_each_entry(q, &dquirks_list, node) { - - if (q->hid_bl_item.idVendor == idVendor && - q->hid_bl_item.idProduct == idProduct) { - - list_replace(&q->node, &q_new->node); - kfree(q); - list_edited = 1; - break; - - } - - } - - if (!list_edited) - list_add_tail(&q_new->node, &dquirks_list); - - up_write(&dquirks_rwsem); - - return 0; -} - -/** - * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory - * - * Description: - * Free all memory associated with dynamic quirks - called before - * module unload. - * - */ -static void usbhid_remove_all_dquirks(void) -{ - struct quirks_list_struct *q, *temp; - - down_write(&dquirks_rwsem); - list_for_each_entry_safe(q, temp, &dquirks_list, node) { - list_del(&q->node); - kfree(q); - } - up_write(&dquirks_rwsem); - -} - -/** - * usbhid_quirks_init: apply USB HID quirks specified at module load time - */ -int usbhid_quirks_init(char **quirks_param) -{ - u16 idVendor, idProduct; - u32 quirks; - int n = 0, m; - - for (; n < MAX_USBHID_BOOT_QUIRKS && quirks_param[n]; n++) { - - m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", - &idVendor, &idProduct, &quirks); - - if (m != 3 || - usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) { - printk(KERN_WARNING - "Could not parse HID quirk module param %s\n", - quirks_param[n]); - } - } - - return 0; -} - -/** - * usbhid_quirks_exit: release memory associated with dynamic_quirks - * - * Description: - * Release all memory associated with dynamic quirks. Called upon - * module unload. - * - * Returns: nothing - */ -void usbhid_quirks_exit(void) -{ - usbhid_remove_all_dquirks(); -} - -/** - * usbhid_exists_squirk: return any static quirks for a USB HID device - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * - * Description: - * Given a USB vendor ID and product ID, return a pointer to - * the hid_blacklist entry associated with that device. - * - * Returns: pointer if quirk found, or NULL if no quirks found. - */ -static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor, - const u16 idProduct) -{ - const struct hid_blacklist *bl_entry = NULL; - int n = 0; - - for (; hid_blacklist[n].idVendor; n++) - if (hid_blacklist[n].idVendor == idVendor && - hid_blacklist[n].idProduct == idProduct) - bl_entry = &hid_blacklist[n]; - - if (bl_entry != NULL) - dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n", - bl_entry->quirks, bl_entry->idVendor, - bl_entry->idProduct); - return bl_entry; -} - -/** - * usbhid_lookup_quirk: return any quirks associated with a USB HID device - * @idVendor: the 16-bit USB vendor ID, in native byteorder - * @idProduct: the 16-bit USB product ID, in native byteorder - * - * Description: - * Given a USB vendor ID and product ID, return any quirks associated - * with that device. - * - * Returns: a u32 quirks value. - */ -u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct) -{ - u32 quirks = 0; - const struct hid_blacklist *bl_entry = NULL; - - /* NCR devices must not be queried for reports */ - if (idVendor == USB_VENDOR_ID_NCR && - idProduct >= USB_DEVICE_ID_NCR_FIRST && - idProduct <= USB_DEVICE_ID_NCR_LAST) - return HID_QUIRK_NO_INIT_REPORTS; - - down_read(&dquirks_rwsem); - bl_entry = usbhid_exists_dquirk(idVendor, idProduct); - if (!bl_entry) - bl_entry = usbhid_exists_squirk(idVendor, idProduct); - if (bl_entry) - quirks = bl_entry->quirks; - up_read(&dquirks_rwsem); - - return quirks; -} - -EXPORT_SYMBOL_GPL(usbhid_lookup_quirk); diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/hiddev.c b/ANDROID_3.4.5/drivers/hid/usbhid/hiddev.c deleted file mode 100644 index b1ec0e2a..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/hiddev.c +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Copyright (c) 2001 Paul Stewart - * Copyright (c) 2001 Vojtech Pavlik - * - * HID char devices, giving access to raw HID device events. - * - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net> - */ - -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/usb.h> -#include <linux/hid.h> -#include <linux/hiddev.h> -#include <linux/compat.h> -#include "usbhid.h" - -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define HIDDEV_MINOR_BASE 0 -#define HIDDEV_MINORS 256 -#else -#define HIDDEV_MINOR_BASE 96 -#define HIDDEV_MINORS 16 -#endif -#define HIDDEV_BUFFER_SIZE 2048 - -struct hiddev { - int exist; - int open; - struct mutex existancelock; - wait_queue_head_t wait; - struct hid_device *hid; - struct list_head list; - spinlock_t list_lock; -}; - -struct hiddev_list { - struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; - int head; - int tail; - unsigned flags; - struct fasync_struct *fasync; - struct hiddev *hiddev; - struct list_head node; - struct mutex thread_lock; -}; - -/* - * Find a report, given the report's type and ID. The ID can be specified - * indirectly by REPORT_ID_FIRST (which returns the first report of the given - * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the - * given type which follows old_id. - */ -static struct hid_report * -hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) -{ - unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; - unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; - struct hid_report_enum *report_enum; - struct hid_report *report; - struct list_head *list; - - if (rinfo->report_type < HID_REPORT_TYPE_MIN || - rinfo->report_type > HID_REPORT_TYPE_MAX) - return NULL; - - report_enum = hid->report_enum + - (rinfo->report_type - HID_REPORT_TYPE_MIN); - - switch (flags) { - case 0: /* Nothing to do -- report_id is already set correctly */ - break; - - case HID_REPORT_ID_FIRST: - if (list_empty(&report_enum->report_list)) - return NULL; - - list = report_enum->report_list.next; - report = list_entry(list, struct hid_report, list); - rinfo->report_id = report->id; - break; - - case HID_REPORT_ID_NEXT: - report = report_enum->report_id_hash[rid]; - if (!report) - return NULL; - - list = report->list.next; - if (list == &report_enum->report_list) - return NULL; - - report = list_entry(list, struct hid_report, list); - rinfo->report_id = report->id; - break; - - default: - return NULL; - } - - return report_enum->report_id_hash[rinfo->report_id]; -} - -/* - * Perform an exhaustive search of the report table for a usage, given its - * type and usage id. - */ -static struct hid_field * -hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) -{ - int i, j; - struct hid_report *report; - struct hid_report_enum *report_enum; - struct hid_field *field; - - if (uref->report_type < HID_REPORT_TYPE_MIN || - uref->report_type > HID_REPORT_TYPE_MAX) - return NULL; - - report_enum = hid->report_enum + - (uref->report_type - HID_REPORT_TYPE_MIN); - - list_for_each_entry(report, &report_enum->report_list, list) { - for (i = 0; i < report->maxfield; i++) { - field = report->field[i]; - for (j = 0; j < field->maxusage; j++) { - if (field->usage[j].hid == uref->usage_code) { - uref->report_id = report->id; - uref->field_index = i; - uref->usage_index = j; - return field; - } - } - } - } - - return NULL; -} - -static void hiddev_send_event(struct hid_device *hid, - struct hiddev_usage_ref *uref) -{ - struct hiddev *hiddev = hid->hiddev; - struct hiddev_list *list; - unsigned long flags; - - spin_lock_irqsave(&hiddev->list_lock, flags); - list_for_each_entry(list, &hiddev->list, node) { - if (uref->field_index != HID_FIELD_INDEX_NONE || - (list->flags & HIDDEV_FLAG_REPORT) != 0) { - list->buffer[list->head] = *uref; - list->head = (list->head + 1) & - (HIDDEV_BUFFER_SIZE - 1); - kill_fasync(&list->fasync, SIGIO, POLL_IN); - } - } - spin_unlock_irqrestore(&hiddev->list_lock, flags); - - wake_up_interruptible(&hiddev->wait); -} - -/* - * This is where hid.c calls into hiddev to pass an event that occurred over - * the interrupt pipe - */ -void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - unsigned type = field->report_type; - struct hiddev_usage_ref uref; - - uref.report_type = - (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : - ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); - uref.report_id = field->report->id; - uref.field_index = field->index; - uref.usage_index = (usage - field->usage); - uref.usage_code = usage->hid; - uref.value = value; - - hiddev_send_event(hid, &uref); -} -EXPORT_SYMBOL_GPL(hiddev_hid_event); - -void hiddev_report_event(struct hid_device *hid, struct hid_report *report) -{ - unsigned type = report->type; - struct hiddev_usage_ref uref; - - memset(&uref, 0, sizeof(uref)); - uref.report_type = - (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : - ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); - uref.report_id = report->id; - uref.field_index = HID_FIELD_INDEX_NONE; - - hiddev_send_event(hid, &uref); -} - -/* - * fasync file op - */ -static int hiddev_fasync(int fd, struct file *file, int on) -{ - struct hiddev_list *list = file->private_data; - - return fasync_helper(fd, file, on, &list->fasync); -} - - -/* - * release file op - */ -static int hiddev_release(struct inode * inode, struct file * file) -{ - struct hiddev_list *list = file->private_data; - unsigned long flags; - - spin_lock_irqsave(&list->hiddev->list_lock, flags); - list_del(&list->node); - spin_unlock_irqrestore(&list->hiddev->list_lock, flags); - - mutex_lock(&list->hiddev->existancelock); - if (!--list->hiddev->open) { - if (list->hiddev->exist) { - usbhid_close(list->hiddev->hid); - usbhid_put_power(list->hiddev->hid); - } else { - mutex_unlock(&list->hiddev->existancelock); - kfree(list->hiddev); - kfree(list); - return 0; - } - } - - mutex_unlock(&list->hiddev->existancelock); - kfree(list); - - return 0; -} - -/* - * open file op - */ -static int hiddev_open(struct inode *inode, struct file *file) -{ - struct hiddev_list *list; - struct usb_interface *intf; - struct hid_device *hid; - struct hiddev *hiddev; - int res; - - intf = usbhid_find_interface(iminor(inode)); - if (!intf) - return -ENODEV; - hid = usb_get_intfdata(intf); - hiddev = hid->hiddev; - - if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) - return -ENOMEM; - mutex_init(&list->thread_lock); - list->hiddev = hiddev; - file->private_data = list; - - /* - * no need for locking because the USB major number - * is shared which usbcore guards against disconnect - */ - if (list->hiddev->exist) { - if (!list->hiddev->open++) { - res = usbhid_open(hiddev->hid); - if (res < 0) { - res = -EIO; - goto bail; - } - } - } else { - res = -ENODEV; - goto bail; - } - - spin_lock_irq(&list->hiddev->list_lock); - list_add_tail(&list->node, &hiddev->list); - spin_unlock_irq(&list->hiddev->list_lock); - - mutex_lock(&hiddev->existancelock); - if (!list->hiddev->open++) - if (list->hiddev->exist) { - struct hid_device *hid = hiddev->hid; - res = usbhid_get_power(hid); - if (res < 0) { - res = -EIO; - goto bail_unlock; - } - usbhid_open(hid); - } - mutex_unlock(&hiddev->existancelock); - return 0; -bail_unlock: - mutex_unlock(&hiddev->existancelock); -bail: - file->private_data = NULL; - kfree(list); - return res; -} - -/* - * "write" file op - */ -static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -/* - * "read" file op - */ -static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) -{ - DEFINE_WAIT(wait); - struct hiddev_list *list = file->private_data; - int event_size; - int retval; - - event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? - sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); - - if (count < event_size) - return 0; - - /* lock against other threads */ - retval = mutex_lock_interruptible(&list->thread_lock); - if (retval) - return -ERESTARTSYS; - - while (retval == 0) { - if (list->head == list->tail) { - prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE); - - while (list->head == list->tail) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - if (!list->hiddev->exist) { - retval = -EIO; - break; - } - - /* let O_NONBLOCK tasks run */ - mutex_unlock(&list->thread_lock); - schedule(); - if (mutex_lock_interruptible(&list->thread_lock)) { - finish_wait(&list->hiddev->wait, &wait); - return -EINTR; - } - set_current_state(TASK_INTERRUPTIBLE); - } - finish_wait(&list->hiddev->wait, &wait); - - } - - if (retval) { - mutex_unlock(&list->thread_lock); - return retval; - } - - - while (list->head != list->tail && - retval + event_size <= count) { - if ((list->flags & HIDDEV_FLAG_UREF) == 0) { - if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) { - struct hiddev_event event; - - event.hid = list->buffer[list->tail].usage_code; - event.value = list->buffer[list->tail].value; - if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) { - mutex_unlock(&list->thread_lock); - return -EFAULT; - } - retval += sizeof(struct hiddev_event); - } - } else { - if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || - (list->flags & HIDDEV_FLAG_REPORT) != 0) { - - if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) { - mutex_unlock(&list->thread_lock); - return -EFAULT; - } - retval += sizeof(struct hiddev_usage_ref); - } - } - list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); - } - - } - mutex_unlock(&list->thread_lock); - - return retval; -} - -/* - * "poll" file op - * No kernel lock - fine - */ -static unsigned int hiddev_poll(struct file *file, poll_table *wait) -{ - struct hiddev_list *list = file->private_data; - - poll_wait(file, &list->hiddev->wait, wait); - if (list->head != list->tail) - return POLLIN | POLLRDNORM; - if (!list->hiddev->exist) - return POLLERR | POLLHUP; - return 0; -} - -/* - * "ioctl" file op - */ -static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg) -{ - struct hid_device *hid = hiddev->hid; - struct hiddev_report_info rinfo; - struct hiddev_usage_ref_multi *uref_multi = NULL; - struct hiddev_usage_ref *uref; - struct hid_report *report; - struct hid_field *field; - int i; - - uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); - if (!uref_multi) - return -ENOMEM; - uref = &uref_multi->uref; - if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { - if (copy_from_user(uref_multi, user_arg, - sizeof(*uref_multi))) - goto fault; - } else { - if (copy_from_user(uref, user_arg, sizeof(*uref))) - goto fault; - } - - switch (cmd) { - case HIDIOCGUCODE: - rinfo.report_type = uref->report_type; - rinfo.report_id = uref->report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - goto inval; - - if (uref->field_index >= report->maxfield) - goto inval; - - field = report->field[uref->field_index]; - if (uref->usage_index >= field->maxusage) - goto inval; - - uref->usage_code = field->usage[uref->usage_index].hid; - - if (copy_to_user(user_arg, uref, sizeof(*uref))) - goto fault; - - goto goodreturn; - - default: - if (cmd != HIDIOCGUSAGE && - cmd != HIDIOCGUSAGES && - uref->report_type == HID_REPORT_TYPE_INPUT) - goto inval; - - if (uref->report_id == HID_REPORT_ID_UNKNOWN) { - field = hiddev_lookup_usage(hid, uref); - if (field == NULL) - goto inval; - } else { - rinfo.report_type = uref->report_type; - rinfo.report_id = uref->report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - goto inval; - - if (uref->field_index >= report->maxfield) - goto inval; - - field = report->field[uref->field_index]; - - if (cmd == HIDIOCGCOLLECTIONINDEX) { - if (uref->usage_index >= field->maxusage) - goto inval; - } else if (uref->usage_index >= field->report_count) - goto inval; - - else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && - (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values > field->report_count)) - goto inval; - } - - switch (cmd) { - case HIDIOCGUSAGE: - uref->value = field->value[uref->usage_index]; - if (copy_to_user(user_arg, uref, sizeof(*uref))) - goto fault; - goto goodreturn; - - case HIDIOCSUSAGE: - field->value[uref->usage_index] = uref->value; - goto goodreturn; - - case HIDIOCGCOLLECTIONINDEX: - i = field->usage[uref->usage_index].collection_index; - kfree(uref_multi); - return i; - case HIDIOCGUSAGES: - for (i = 0; i < uref_multi->num_values; i++) - uref_multi->values[i] = - field->value[uref->usage_index + i]; - if (copy_to_user(user_arg, uref_multi, - sizeof(*uref_multi))) - goto fault; - goto goodreturn; - case HIDIOCSUSAGES: - for (i = 0; i < uref_multi->num_values; i++) - field->value[uref->usage_index + i] = - uref_multi->values[i]; - goto goodreturn; - } - -goodreturn: - kfree(uref_multi); - return 0; -fault: - kfree(uref_multi); - return -EFAULT; -inval: - kfree(uref_multi); - return -EINVAL; - } -} - -static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg) -{ - struct hid_device *hid = hiddev->hid; - struct usb_device *dev = hid_to_usb_dev(hid); - int idx, len; - char *buf; - - if (get_user(idx, (int __user *)user_arg)) - return -EFAULT; - - if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - - if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { - kfree(buf); - return -EINVAL; - } - - if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { - kfree(buf); - return -EFAULT; - } - - kfree(buf); - - return len; -} - -static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct hiddev_list *list = file->private_data; - struct hiddev *hiddev = list->hiddev; - struct hid_device *hid; - struct hiddev_collection_info cinfo; - struct hiddev_report_info rinfo; - struct hiddev_field_info finfo; - struct hiddev_devinfo dinfo; - struct hid_report *report; - struct hid_field *field; - void __user *user_arg = (void __user *)arg; - int i, r = -EINVAL; - - /* Called without BKL by compat methods so no BKL taken */ - - mutex_lock(&hiddev->existancelock); - if (!hiddev->exist) { - r = -ENODEV; - goto ret_unlock; - } - - hid = hiddev->hid; - - switch (cmd) { - - case HIDIOCGVERSION: - r = put_user(HID_VERSION, (int __user *)arg) ? - -EFAULT : 0; - break; - - case HIDIOCAPPLICATION: - if (arg < 0 || arg >= hid->maxapplication) - break; - - for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == - HID_COLLECTION_APPLICATION && arg-- == 0) - break; - - if (i < hid->maxcollection) - r = hid->collection[i].usage; - break; - - case HIDIOCGDEVINFO: - { - struct usb_device *dev = hid_to_usb_dev(hid); - struct usbhid_device *usbhid = hid->driver_data; - - memset(&dinfo, 0, sizeof(dinfo)); - - dinfo.bustype = BUS_USB; - dinfo.busnum = dev->bus->busnum; - dinfo.devnum = dev->devnum; - dinfo.ifnum = usbhid->ifnum; - dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); - dinfo.product = le16_to_cpu(dev->descriptor.idProduct); - dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); - dinfo.num_applications = hid->maxapplication; - - r = copy_to_user(user_arg, &dinfo, sizeof(dinfo)) ? - -EFAULT : 0; - break; - } - - case HIDIOCGFLAG: - r = put_user(list->flags, (int __user *)arg) ? - -EFAULT : 0; - break; - - case HIDIOCSFLAG: - { - int newflags; - - if (get_user(newflags, (int __user *)arg)) { - r = -EFAULT; - break; - } - - if ((newflags & ~HIDDEV_FLAGS) != 0 || - ((newflags & HIDDEV_FLAG_REPORT) != 0 && - (newflags & HIDDEV_FLAG_UREF) == 0)) - break; - - list->flags = newflags; - - r = 0; - break; - } - - case HIDIOCGSTRING: - r = hiddev_ioctl_string(hiddev, cmd, user_arg); - break; - - case HIDIOCINITREPORT: - usbhid_init_reports(hid); - r = 0; - break; - - case HIDIOCGREPORT: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { - r = -EFAULT; - break; - } - - if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) - break; - - report = hiddev_lookup_report(hid, &rinfo); - if (report == NULL) - break; - - usbhid_submit_report(hid, report, USB_DIR_IN); - usbhid_wait_io(hid); - - r = 0; - break; - - case HIDIOCSREPORT: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { - r = -EFAULT; - break; - } - - if (rinfo.report_type == HID_REPORT_TYPE_INPUT) - break; - - report = hiddev_lookup_report(hid, &rinfo); - if (report == NULL) - break; - - usbhid_submit_report(hid, report, USB_DIR_OUT); - usbhid_wait_io(hid); - - r = 0; - break; - - case HIDIOCGREPORTINFO: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { - r = -EFAULT; - break; - } - - report = hiddev_lookup_report(hid, &rinfo); - if (report == NULL) - break; - - rinfo.num_fields = report->maxfield; - - r = copy_to_user(user_arg, &rinfo, sizeof(rinfo)) ? - -EFAULT : 0; - break; - - case HIDIOCGFIELDINFO: - if (copy_from_user(&finfo, user_arg, sizeof(finfo))) { - r = -EFAULT; - break; - } - - rinfo.report_type = finfo.report_type; - rinfo.report_id = finfo.report_id; - - report = hiddev_lookup_report(hid, &rinfo); - if (report == NULL) - break; - - if (finfo.field_index >= report->maxfield) - break; - - field = report->field[finfo.field_index]; - memset(&finfo, 0, sizeof(finfo)); - finfo.report_type = rinfo.report_type; - finfo.report_id = rinfo.report_id; - finfo.field_index = field->report_count - 1; - finfo.maxusage = field->maxusage; - finfo.flags = field->flags; - finfo.physical = field->physical; - finfo.logical = field->logical; - finfo.application = field->application; - finfo.logical_minimum = field->logical_minimum; - finfo.logical_maximum = field->logical_maximum; - finfo.physical_minimum = field->physical_minimum; - finfo.physical_maximum = field->physical_maximum; - finfo.unit_exponent = field->unit_exponent; - finfo.unit = field->unit; - - r = copy_to_user(user_arg, &finfo, sizeof(finfo)) ? - -EFAULT : 0; - break; - - case HIDIOCGUCODE: - /* fall through */ - case HIDIOCGUSAGE: - case HIDIOCSUSAGE: - case HIDIOCGUSAGES: - case HIDIOCSUSAGES: - case HIDIOCGCOLLECTIONINDEX: - r = hiddev_ioctl_usage(hiddev, cmd, user_arg); - break; - - case HIDIOCGCOLLECTIONINFO: - if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) { - r = -EFAULT; - break; - } - - if (cinfo.index >= hid->maxcollection) - break; - - cinfo.type = hid->collection[cinfo.index].type; - cinfo.usage = hid->collection[cinfo.index].usage; - cinfo.level = hid->collection[cinfo.index].level; - - r = copy_to_user(user_arg, &cinfo, sizeof(cinfo)) ? - -EFAULT : 0; - break; - - default: - if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) - break; - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { - int len = strlen(hid->name) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - r = copy_to_user(user_arg, hid->name, len) ? - -EFAULT : len; - break; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { - int len = strlen(hid->phys) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - r = copy_to_user(user_arg, hid->phys, len) ? - -EFAULT : len; - break; - } - } - -ret_unlock: - mutex_unlock(&hiddev->existancelock); - return r; -} - -#ifdef CONFIG_COMPAT -static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - -static const struct file_operations hiddev_fops = { - .owner = THIS_MODULE, - .read = hiddev_read, - .write = hiddev_write, - .poll = hiddev_poll, - .open = hiddev_open, - .release = hiddev_release, - .unlocked_ioctl = hiddev_ioctl, - .fasync = hiddev_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = hiddev_compat_ioctl, -#endif - .llseek = noop_llseek, -}; - -static char *hiddev_devnode(struct device *dev, umode_t *mode) -{ - return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); -} - -static struct usb_class_driver hiddev_class = { - .name = "hiddev%d", - .devnode = hiddev_devnode, - .fops = &hiddev_fops, - .minor_base = HIDDEV_MINOR_BASE, -}; - -/* - * This is where hid.c calls us to connect a hid device to the hiddev driver - */ -int hiddev_connect(struct hid_device *hid, unsigned int force) -{ - struct hiddev *hiddev; - struct usbhid_device *usbhid = hid->driver_data; - int retval; - - if (!force) { - unsigned int i; - for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == - HID_COLLECTION_APPLICATION && - !IS_INPUT_APPLICATION(hid->collection[i].usage)) - break; - - if (i == hid->maxcollection) - return -1; - } - - if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) - return -1; - - init_waitqueue_head(&hiddev->wait); - INIT_LIST_HEAD(&hiddev->list); - spin_lock_init(&hiddev->list_lock); - mutex_init(&hiddev->existancelock); - hid->hiddev = hiddev; - hiddev->hid = hid; - hiddev->exist = 1; - retval = usb_register_dev(usbhid->intf, &hiddev_class); - if (retval) { - hid_err(hid, "Not able to get a minor for this device\n"); - hid->hiddev = NULL; - kfree(hiddev); - return -1; - } - return 0; -} - -/* - * This is where hid.c calls us to disconnect a hiddev device from the - * corresponding hid device (usually because the usb device has disconnected) - */ -static struct usb_class_driver hiddev_class; -void hiddev_disconnect(struct hid_device *hid) -{ - struct hiddev *hiddev = hid->hiddev; - struct usbhid_device *usbhid = hid->driver_data; - - usb_deregister_dev(usbhid->intf, &hiddev_class); - - mutex_lock(&hiddev->existancelock); - hiddev->exist = 0; - - if (hiddev->open) { - mutex_unlock(&hiddev->existancelock); - usbhid_close(hiddev->hid); - wake_up_interruptible(&hiddev->wait); - } else { - mutex_unlock(&hiddev->existancelock); - kfree(hiddev); - } -} diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/usbhid.h b/ANDROID_3.4.5/drivers/hid/usbhid/usbhid.h deleted file mode 100644 index cb8f703e..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/usbhid.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef __USBHID_H -#define __USBHID_H - -/* - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2001 Vojtech Pavlik - * Copyright (c) 2006 Jiri Kosina - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/timer.h> -#include <linux/wait.h> -#include <linux/workqueue.h> -#include <linux/input.h> - -/* API provided by hid-core.c for USB HID drivers */ -int usbhid_wait_io(struct hid_device* hid); -void usbhid_close(struct hid_device *hid); -int usbhid_open(struct hid_device *hid); -void usbhid_init_reports(struct hid_device *hid); -void usbhid_submit_report -(struct hid_device *hid, struct hid_report *report, unsigned char dir); -int usbhid_get_power(struct hid_device *hid); -void usbhid_put_power(struct hid_device *hid); -struct usb_interface *usbhid_find_interface(int minor); - -/* iofl flags */ -#define HID_CTRL_RUNNING 1 -#define HID_OUT_RUNNING 2 -#define HID_IN_RUNNING 3 -#define HID_RESET_PENDING 4 -#define HID_SUSPENDED 5 -#define HID_CLEAR_HALT 6 -#define HID_DISCONNECTED 7 -#define HID_STARTED 8 -#define HID_REPORTED_IDLE 9 -#define HID_KEYS_PRESSED 10 - -/* - * USB-specific HID struct, to be pointed to - * from struct hid_device->driver_data - */ - -struct usbhid_device { - struct hid_device *hid; /* pointer to corresponding HID dev */ - - struct usb_interface *intf; /* USB interface */ - int ifnum; /* USB interface number */ - - unsigned int bufsize; /* URB buffer size */ - - struct urb *urbin; /* Input URB */ - char *inbuf; /* Input buffer */ - dma_addr_t inbuf_dma; /* Input buffer dma */ - - struct urb *urbctrl; /* Control URB */ - struct usb_ctrlrequest *cr; /* Control request struct */ - struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ - unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ - char *ctrlbuf; /* Control buffer */ - dma_addr_t ctrlbuf_dma; /* Control buffer dma */ - unsigned long last_ctrl; /* record of last output for timeouts */ - - struct urb *urbout; /* Output URB */ - struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ - unsigned char outhead, outtail; /* Output pipe fifo head & tail */ - char *outbuf; /* Output buffer */ - dma_addr_t outbuf_dma; /* Output buffer dma */ - unsigned long last_out; /* record of last output for timeouts */ - - spinlock_t lock; /* fifo spinlock */ - unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ - struct timer_list io_retry; /* Retry timer */ - unsigned long stop_retry; /* Time to give up, in jiffies */ - unsigned int retry_delay; /* Delay length in ms */ - struct work_struct reset_work; /* Task context for resets */ - wait_queue_head_t wait; /* For sleeping */ - int ledcount; /* counting the number of active leds */ - - struct work_struct led_work; /* Task context for setting LEDs */ -}; - -#define hid_to_usb_dev(hid_dev) \ - container_of(hid_dev->dev.parent->parent, struct usb_device, dev) - -#endif - diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/usbkbd.c b/ANDROID_3.4.5/drivers/hid/usbhid/usbkbd.c deleted file mode 100644 index 79608698..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/usbkbd.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * USB HIDBP Keyboard support - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> -#include <linux/hid.h> - -/* - * Version Information - */ -#define DRIVER_VERSION "" -#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" -#define DRIVER_DESC "USB HID Boot Protocol keyboard driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -static const unsigned char usb_kbd_keycode[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, - 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140 -}; - - -/** - * struct usb_kbd - state of each attached keyboard - * @dev: input device associated with this keyboard - * @usbdev: usb device associated with this keyboard - * @old: data received in the past from the @irq URB representing which - * keys were pressed. By comparing with the current list of keys - * that are pressed, we are able to see key releases. - * @irq: URB for receiving a list of keys that are pressed when a - * new key is pressed or a key that was pressed is released. - * @led: URB for sending LEDs (e.g. numlock, ...) - * @newleds: data that will be sent with the @led URB representing which LEDs - should be on - * @name: Name of the keyboard. @dev's name field points to this buffer - * @phys: Physical path of the keyboard. @dev's phys field points to this - * buffer - * @new: Buffer for the @irq URB - * @cr: Control request for @led URB - * @leds: Buffer for the @led URB - * @new_dma: DMA address for @irq URB - * @leds_dma: DMA address for @led URB - * @leds_lock: spinlock that protects @leds, @newleds, and @led_urb_submitted - * @led_urb_submitted: indicates whether @led is in progress, i.e. it has been - * submitted and its completion handler has not returned yet - * without resubmitting @led - */ -struct usb_kbd { - struct input_dev *dev; - struct usb_device *usbdev; - unsigned char old[8]; - struct urb *irq, *led; - unsigned char newleds; - char name[128]; - char phys[64]; - - unsigned char *new; - struct usb_ctrlrequest *cr; - unsigned char *leds; - dma_addr_t new_dma; - dma_addr_t leds_dma; - - spinlock_t leds_lock; - bool led_urb_submitted; - -}; - -static void usb_kbd_irq(struct urb *urb) -{ - struct usb_kbd *kbd = urb->context; - int i; - - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - for (i = 0; i < 8; i++) - input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); - - for (i = 2; i < 8; i++) { - - if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { - if (usb_kbd_keycode[kbd->old[i]]) - input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); - else - hid_info(urb->dev, - "Unknown key (scancode %#x) released.\n", - kbd->old[i]); - } - - if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { - if (usb_kbd_keycode[kbd->new[i]]) - input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); - else - hid_info(urb->dev, - "Unknown key (scancode %#x) released.\n", - kbd->new[i]); - } - } - - input_sync(kbd->dev); - - memcpy(kbd->old, kbd->new, 8); - -resubmit: - i = usb_submit_urb (urb, GFP_ATOMIC); - if (i) - hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d", - kbd->usbdev->bus->bus_name, - kbd->usbdev->devpath, i); -} - -static int usb_kbd_event(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ - unsigned long flags; - struct usb_kbd *kbd = input_get_drvdata(dev); - - if (type != EV_LED) - return -1; - - spin_lock_irqsave(&kbd->leds_lock, flags); - kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | - (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | - (!!test_bit(LED_NUML, dev->led)); - - if (kbd->led_urb_submitted){ - spin_unlock_irqrestore(&kbd->leds_lock, flags); - return 0; - } - - if (*(kbd->leds) == kbd->newleds){ - spin_unlock_irqrestore(&kbd->leds_lock, flags); - return 0; - } - - *(kbd->leds) = kbd->newleds; - - kbd->led->dev = kbd->usbdev; - if (usb_submit_urb(kbd->led, GFP_ATOMIC)) - pr_err("usb_submit_urb(leds) failed\n"); - else - kbd->led_urb_submitted = true; - - spin_unlock_irqrestore(&kbd->leds_lock, flags); - - return 0; -} - -static void usb_kbd_led(struct urb *urb) -{ - unsigned long flags; - struct usb_kbd *kbd = urb->context; - - if (urb->status) - hid_warn(urb->dev, "led urb status %d received\n", - urb->status); - - spin_lock_irqsave(&kbd->leds_lock, flags); - - if (*(kbd->leds) == kbd->newleds){ - kbd->led_urb_submitted = false; - spin_unlock_irqrestore(&kbd->leds_lock, flags); - return; - } - - *(kbd->leds) = kbd->newleds; - - kbd->led->dev = kbd->usbdev; - if (usb_submit_urb(kbd->led, GFP_ATOMIC)){ - hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); - kbd->led_urb_submitted = false; - } - spin_unlock_irqrestore(&kbd->leds_lock, flags); - -} - -static int usb_kbd_open(struct input_dev *dev) -{ - struct usb_kbd *kbd = input_get_drvdata(dev); - - kbd->irq->dev = kbd->usbdev; - if (usb_submit_urb(kbd->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usb_kbd_close(struct input_dev *dev) -{ - struct usb_kbd *kbd = input_get_drvdata(dev); - - usb_kill_urb(kbd->irq); -} - -static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) -{ - if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) - return -1; - if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) - return -1; - if (!(kbd->new = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &kbd->new_dma))) - return -1; - if (!(kbd->cr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) - return -1; - if (!(kbd->leds = usb_alloc_coherent(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) - return -1; - - return 0; -} - -static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) -{ - usb_free_urb(kbd->irq); - usb_free_urb(kbd->led); - usb_free_coherent(dev, 8, kbd->new, kbd->new_dma); - kfree(kbd->cr); - usb_free_coherent(dev, 1, kbd->leds, kbd->leds_dma); -} - -static int usb_kbd_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(iface); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_kbd *kbd; - struct input_dev *input_dev; - int i, pipe, maxp; - int error = -ENOMEM; - - interface = iface->cur_altsetting; - - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_is_int_in(endpoint)) - return -ENODEV; - - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbd || !input_dev) - goto fail1; - - if (usb_kbd_alloc_mem(dev, kbd)) - goto fail2; - - kbd->usbdev = dev; - kbd->dev = input_dev; - spin_lock_init(&kbd->leds_lock); - - if (dev->manufacturer) - strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(kbd->name, " ", sizeof(kbd->name)); - strlcat(kbd->name, dev->product, sizeof(kbd->name)); - } - - if (!strlen(kbd->name)) - snprintf(kbd->name, sizeof(kbd->name), - "USB HIDBP Keyboard %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); - strlcat(kbd->phys, "/input0", sizeof(kbd->phys)); - - input_dev->name = kbd->name; - input_dev->phys = kbd->phys; - usb_to_input_id(dev, &input_dev->id); - input_dev->dev.parent = &iface->dev; - - input_set_drvdata(input_dev, kbd); - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) | - BIT_MASK(EV_REP); - input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | - BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) | - BIT_MASK(LED_KANA); - - for (i = 0; i < 255; i++) - set_bit(usb_kbd_keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - - input_dev->event = usb_kbd_event; - input_dev->open = usb_kbd_open; - input_dev->close = usb_kbd_close; - - usb_fill_int_urb(kbd->irq, dev, pipe, - kbd->new, (maxp > 8 ? 8 : maxp), - usb_kbd_irq, kbd, endpoint->bInterval); - kbd->irq->transfer_dma = kbd->new_dma; - kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; - kbd->cr->bRequest = 0x09; - kbd->cr->wValue = cpu_to_le16(0x200); - kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); - kbd->cr->wLength = cpu_to_le16(1); - - usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), - (void *) kbd->cr, kbd->leds, 1, - usb_kbd_led, kbd); - kbd->led->transfer_dma = kbd->leds_dma; - kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - error = input_register_device(kbd->dev); - if (error) - goto fail2; - - usb_set_intfdata(iface, kbd); - device_set_wakeup_enable(&dev->dev, 1); - return 0; - -fail2: - usb_kbd_free_mem(dev, kbd); -fail1: - input_free_device(input_dev); - kfree(kbd); - return error; -} - -static void usb_kbd_disconnect(struct usb_interface *intf) -{ - struct usb_kbd *kbd = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (kbd) { - usb_kill_urb(kbd->irq); - input_unregister_device(kbd->dev); - usb_kill_urb(kbd->led); - usb_kbd_free_mem(interface_to_usbdev(intf), kbd); - kfree(kbd); - } -} - -static struct usb_device_id usb_kbd_id_table [] = { - { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, - USB_INTERFACE_PROTOCOL_KEYBOARD) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); - -static struct usb_driver usb_kbd_driver = { - .name = "usbkbd", - .probe = usb_kbd_probe, - .disconnect = usb_kbd_disconnect, - .id_table = usb_kbd_id_table, -}; - -module_usb_driver(usb_kbd_driver); diff --git a/ANDROID_3.4.5/drivers/hid/usbhid/usbmouse.c b/ANDROID_3.4.5/drivers/hid/usbhid/usbmouse.c deleted file mode 100644 index 0f6be45d..00000000 --- a/ANDROID_3.4.5/drivers/hid/usbhid/usbmouse.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * USB HIDBP Mouse support - */ - -/* - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> -#include <linux/hid.h> - -/* for apple IDs */ -#ifdef CONFIG_USB_HID_MODULE -#include "../hid-ids.h" -#endif - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.6" -#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" -#define DRIVER_DESC "USB HID Boot Protocol mouse driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -struct usb_mouse { - char name[128]; - char phys[64]; - struct usb_device *usbdev; - struct input_dev *dev; - struct urb *irq; - - signed char *data; - dma_addr_t data_dma; -}; - -static void usb_mouse_irq(struct urb *urb) -{ - struct usb_mouse *mouse = urb->context; - signed char *data = mouse->data; - struct input_dev *dev = mouse->dev; - int status; - - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - input_report_key(dev, BTN_LEFT, data[0] & 0x01); - input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); - input_report_key(dev, BTN_SIDE, data[0] & 0x08); - input_report_key(dev, BTN_EXTRA, data[0] & 0x10); - - input_report_rel(dev, REL_X, data[1]); - input_report_rel(dev, REL_Y, data[2]); - input_report_rel(dev, REL_WHEEL, data[3]); - - input_sync(dev); -resubmit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", - mouse->usbdev->bus->bus_name, - mouse->usbdev->devpath, status); -} - -static int usb_mouse_open(struct input_dev *dev) -{ - struct usb_mouse *mouse = input_get_drvdata(dev); - - mouse->irq->dev = mouse->usbdev; - if (usb_submit_urb(mouse->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usb_mouse_close(struct input_dev *dev) -{ - struct usb_mouse *mouse = input_get_drvdata(dev); - - usb_kill_urb(mouse->irq); -} - -static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_mouse *mouse; - struct input_dev *input_dev; - int pipe, maxp; - int error = -ENOMEM; - - interface = intf->cur_altsetting; - - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_is_int_in(endpoint)) - return -ENODEV; - - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!mouse || !input_dev) - goto fail1; - - mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma); - if (!mouse->data) - goto fail1; - - mouse->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mouse->irq) - goto fail2; - - mouse->usbdev = dev; - mouse->dev = input_dev; - - if (dev->manufacturer) - strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(mouse->name, " ", sizeof(mouse->name)); - strlcat(mouse->name, dev->product, sizeof(mouse->name)); - } - - if (!strlen(mouse->name)) - snprintf(mouse->name, sizeof(mouse->name), - "USB HIDBP Mouse %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); - strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); - - input_dev->name = mouse->name; - input_dev->phys = mouse->phys; - usb_to_input_id(dev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | - BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); - input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); - input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) | - BIT_MASK(BTN_EXTRA); - input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - - input_set_drvdata(input_dev, mouse); - - input_dev->open = usb_mouse_open; - input_dev->close = usb_mouse_close; - - usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, - (maxp > 8 ? 8 : maxp), - usb_mouse_irq, mouse, endpoint->bInterval); - mouse->irq->transfer_dma = mouse->data_dma; - mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - error = input_register_device(mouse->dev); - if (error) - goto fail3; - - usb_set_intfdata(intf, mouse); - return 0; - -fail3: - usb_free_urb(mouse->irq); -fail2: - usb_free_coherent(dev, 8, mouse->data, mouse->data_dma); -fail1: - input_free_device(input_dev); - kfree(mouse); - return error; -} - -static void usb_mouse_disconnect(struct usb_interface *intf) -{ - struct usb_mouse *mouse = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (mouse) { - usb_kill_urb(mouse->irq); - input_unregister_device(mouse->dev); - usb_free_urb(mouse->irq); - usb_free_coherent(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); - kfree(mouse); - } -} - -static struct usb_device_id usb_mouse_id_table [] = { - { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, - USB_INTERFACE_PROTOCOL_MOUSE) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); - -static struct usb_driver usb_mouse_driver = { - .name = "usbmouse", - .probe = usb_mouse_probe, - .disconnect = usb_mouse_disconnect, - .id_table = usb_mouse_id_table, -}; - -module_usb_driver(usb_mouse_driver); |