diff options
28 files changed, 6907 insertions, 157 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-picolcd b/Documentation/ABI/testing/sysfs-driver-hid-picolcd new file mode 100644 index 00000000000..08579e7e1e8 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-picolcd @@ -0,0 +1,43 @@ +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode +Date: March 2010 +Contact: Bruno Prémont <bonbons@linux-vserver.org> +Description: Make it possible to switch the PicoLCD device between LCD + (firmware) and bootloader (flasher) operation modes. + + Reading: returns list of available modes, the active mode being + enclosed in brackets ('[' and ']') + + Writing: causes operation mode switch. Permitted values are + the non-active mode names listed when read. + + Note: when switching mode the current PicoLCD HID device gets + disconnected and reconnects after above delay (see attribute + operation_mode_delay for its value). + + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode_delay +Date: April 2010 +Contact: Bruno Prémont <bonbons@linux-vserver.org> +Description: Delay PicoLCD waits before restarting in new mode when + operation_mode has changed. + + Reading/Writing: It is expressed in ms and permitted range is + 0..30000ms. + + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fb_update_rate +Date: March 2010 +Contact: Bruno Prémont <bonbons@linux-vserver.org> +Description: Make it possible to adjust defio refresh rate. + + Reading: returns list of available refresh rates (expressed in Hz), + the active refresh rate being enclosed in brackets ('[' and ']') + + Writing: accepts new refresh rate expressed in integer Hz + within permitted rates. + + Note: As device can barely do 2 complete refreshes a second + it only makes sense to adjust this value if only one or two + tiles get changed and it's not appropriate to expect the application + to flush it's tiny changes explicitely at higher than default rate. + diff --git a/Documentation/ABI/testing/sysfs-driver-hid-prodikeys b/Documentation/ABI/testing/sysfs-driver-hid-prodikeys new file mode 100644 index 00000000000..05d988c29a8 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-prodikeys @@ -0,0 +1,29 @@ +What: /sys/bus/hid/drivers/prodikeys/.../channel +Date: April 2010 +KernelVersion: 2.6.34 +Contact: Don Prince <dhprince.devel@yahoo.co.uk> +Description: + Allows control (via software) the midi channel to which + that the pc-midi keyboard will output.midi data. + Range: 0..15 + Type: Read/write +What: /sys/bus/hid/drivers/prodikeys/.../sustain +Date: April 2010 +KernelVersion: 2.6.34 +Contact: Don Prince <dhprince.devel@yahoo.co.uk> +Description: + Allows control (via software) the sustain duration of a + note held by the pc-midi driver. + 0 means sustain mode is disabled. + Range: 0..5000 (milliseconds) + Type: Read/write +What: /sys/bus/hid/drivers/prodikeys/.../octave +Date: April 2010 +KernelVersion: 2.6.34 +Contact: Don Prince <dhprince.devel@yahoo.co.uk> +Description: + Controls the octave shift modifier in the pc-midi driver. + The octave can be shifted via software up/down 2 octaves. + 0 means the no ocatve shift. + Range: -2..2 (minus 2 to plus 2) + Type: Read/Write diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone new file mode 100644 index 00000000000..88340a23ce9 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone @@ -0,0 +1,111 @@ +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_dpi +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: It is possible to switch the dpi setting of the mouse with the + press of a button. + When read, this file returns the raw number of the actual dpi + setting reported by the mouse. This number has to be further + processed to receive the real dpi value. + + VALUE DPI + 1 800 + 2 1200 + 3 1600 + 4 2000 + 5 2400 + 6 3200 + + This file is readonly. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: When read, this file returns the number of the actual profile. + This file is readonly. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: When read, this file returns the raw integer version number of the + firmware reported by the mouse. Using the integer value eases + further usage in other programs. To receive the real version + number the decimal point has to be shifted 2 positions to the + left. E.g. a returned value of 138 means 1.38 + This file is readonly. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/kone_driver_version +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: When read, this file returns the driver version. + The format of the string is "v<major>.<minor>.<patchlevel>". + This attribute is used by the userland tools to find the sysfs- + paths of installed kone-mice and determine the capabilites of + the driver. Versions of this driver for old kernels replace + usbhid instead of generic-usb. The way to scan for this file + has been chosen to provide a consistent way for all supported + kernel versions. + This file is readonly. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5] +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: The mouse can store 5 profiles which can be switched by the + press of a button. A profile holds informations like button + mappings, sensitivity, the colors of the 5 leds and light + effects. + When read, these files return the respective profile. The + returned data is 975 bytes in size. + When written, this file lets one write the respective profile + data back to the mouse. The data has to be 975 bytes long. + The mouse will reject invalid data, whereas the profile number + stored in the profile doesn't need to fit the number of the + store. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: When read, this file returns the settings stored in the mouse. + The size of the data is 36 bytes and holds information like the + startup_profile, tcu state and calibration_data. + When written, this file lets write settings back to the mouse. + The data has to be 36 bytes long. The mouse will reject invalid + data. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: The integer value of this attribute ranges from 1 to 5. + When read, this attribute returns the number of the profile + that's active when the mouse is powered on. + When written, this file sets the number of the startup profile + and the mouse activates this profile immediately. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/tcu +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: The mouse has a "Tracking Control Unit" which lets the user + calibrate the laser power to fit the mousepad surface. + When read, this file returns the current state of the TCU, + where 0 means off and 1 means on. + Writing 0 in this file will switch the TCU off. + Writing 1 in this file will start the calibration which takes + around 6 seconds to complete and activates the TCU. + +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/weight +Date: March 2010 +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> +Description: The mouse can be equipped with one of four supplied weights + ranging from 5 to 20 grams which are recognized by the mouse + and its value can be read out. When read, this file returns the + raw value returned by the mouse which eases further processing + in other software. + The values map to the weights as follows: + + VALUE WEIGHT + 0 none + 1 5g + 2 10g + 3 15g + 4 20g + + This file is readonly. diff --git a/Documentation/ABI/testing/sysfs-wacom b/Documentation/ABI/testing/sysfs-wacom new file mode 100644 index 00000000000..1517976e25c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-wacom @@ -0,0 +1,10 @@ +What: /sys/class/hidraw/hidraw*/device/speed +Date: April 2010 +Kernel Version: 2.6.35 +Contact: linux-bluetooth@vger.kernel.org +Description: + The /sys/class/hidraw/hidraw*/device/speed file controls + reporting speed of wacom bluetooth tablet. Reading from + this file returns 1 if tablet reports in high speed mode + or 0 otherwise. Writing to this file one of these values + switches reporting speed. diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 71d4c070362..76ba59b9fea 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -86,6 +86,12 @@ config HID_BELKIN ---help--- Support for Belkin Flip KVM and Wireless keyboard. +config HID_CANDO + tristate "Cando dual touch panel" + depends on USB_HID + ---help--- + Support for Cando dual touch panel. + config HID_CHERRY tristate "Cherry" if EMBEDDED depends on USB_HID @@ -100,6 +106,21 @@ config HID_CHICONY ---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" if EMBEDDED depends on USB_HID @@ -108,9 +129,8 @@ config HID_CYPRESS Support for cypress mouse and barcode readers. config HID_DRAGONRISE - tristate "DragonRise Inc. support" if EMBEDDED + tristate "DragonRise Inc. support" depends on USB_HID - default !EMBEDDED ---help--- Say Y here if you have DragonRise Inc.game controllers. @@ -122,6 +142,12 @@ config DRAGONRISE_FF Say Y here if you want to enable force feedback support for DragonRise Inc. game controllers. +config HID_EGALAX + tristate "eGalax multi-touch panel" + depends on USB_HID + ---help--- + Support for the eGalax dual-touch panel. + config HID_EZKEY tristate "Ezkey" if EMBEDDED depends on USB_HID @@ -137,16 +163,14 @@ config HID_KYE Support for Kye/Genius Ergo Mouse. config HID_GYRATION - tristate "Gyration" if EMBEDDED + tristate "Gyration" depends on USB_HID - default !EMBEDDED ---help--- Support for Gyration remote control. config HID_TWINHAN - tristate "Twinhan" if EMBEDDED + tristate "Twinhan" depends on USB_HID - default !EMBEDDED ---help--- Support for Twinhan IR remote control. @@ -233,16 +257,14 @@ config HID_NTRIG Support for N-Trig touch screen. config HID_ORTEK - tristate "Ortek" if EMBEDDED + tristate "Ortek" depends on USB_HID - default !EMBEDDED ---help--- Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. config HID_PANTHERLORD - tristate "Pantherlord support" if EMBEDDED + tristate "Pantherlord support" depends on USB_HID - default !EMBEDDED ---help--- Say Y here if you have a PantherLord/GreenAsia based game controller or adapter. @@ -256,29 +278,90 @@ config PANTHERLORD_FF or adapter and want to enable force feedback support for it. config HID_PETALYNX - tristate "Petalynx" if EMBEDDED + tristate "Petalynx" depends on USB_HID - default !EMBEDDED ---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 EMBEDDED + default !EMBEDDED + 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 EMBEDDED + default !EMBEDDED + 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 EMBEDDED + default !EMBEDDED + 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 EMBEDDED + default !EMBEDDED + 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_QUANTA tristate "Quanta Optical Touch" depends on USB_HID ---help--- Support for Quanta Optical Touch dual-touch panels. +config HID_ROCCAT_KONE + tristate "Roccat Kone Mouse support" + depends on USB_HID + ---help--- + Support for Roccat Kone mouse. + config HID_SAMSUNG - tristate "Samsung" if EMBEDDED + tristate "Samsung" depends on USB_HID - default !EMBEDDED ---help--- - Support for Samsung InfraRed remote control. + Support for Samsung InfraRed remote control or keyboards. config HID_SONY - tristate "Sony" if EMBEDDED + tristate "Sony" depends on USB_HID - default !EMBEDDED ---help--- Support for Sony PS3 controller. @@ -289,16 +372,14 @@ config HID_STANTUM Support for Stantum multitouch panel. config HID_SUNPLUS - tristate "Sunplus" if EMBEDDED + tristate "Sunplus" depends on USB_HID - default !EMBEDDED ---help--- Support for Sunplus wireless desktop. config HID_GREENASIA - tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED + tristate "GreenAsia (Product ID 0x12) support" depends on USB_HID - default !EMBEDDED ---help--- Say Y here if you have a GreenAsia (Product ID 0x12) based game controller or adapter. @@ -313,9 +394,8 @@ config GREENASIA_FF and want to enable force feedback support for it. config HID_SMARTJOYPLUS - tristate "SmartJoy PLUS PS2/USB adapter support" if EMBEDDED + tristate "SmartJoy PLUS PS2/USB adapter support" depends on USB_HID - default !EMBEDDED ---help--- Support for SmartJoy PLUS PS2/USB adapter. @@ -328,16 +408,14 @@ config SMARTJOYPLUS_FF enable force feedback support for it. config HID_TOPSEED - tristate "TopSeed Cyberlink remote control support" if EMBEDDED + tristate "TopSeed Cyberlink remote control support" depends on USB_HID - default !EMBEDDED ---help--- - Say Y if you have a TopSeed Cyberlink remote control. + Say Y if you have a TopSeed Cyberlink or BTC Emprex remote control. config HID_THRUSTMASTER - tristate "ThrustMaster devices support" if EMBEDDED + tristate "ThrustMaster devices support" depends on USB_HID - default !EMBEDDED ---help--- Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or a THRUSTMASTER Ferrari GT Rumble Wheel. @@ -357,10 +435,17 @@ config HID_WACOM ---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_ZEROPLUS - tristate "Zeroplus based game controller support" if EMBEDDED + tristate "Zeroplus based game controller support" depends on USB_HID - default !EMBEDDED ---help--- Say Y here if you have a Zeroplus based game controller. @@ -372,6 +457,12 @@ config ZEROPLUS_FF 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/drivers/hid/Makefile b/drivers/hid/Makefile index 0b2618f092c..22e47eaeea3 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -26,10 +26,12 @@ obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_BELKIN) += hid-belkin.o +obj-$(CONFIG_HID_CANDO) += hid-cando.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-drff.o +obj-$(CONFIG_HID_EGALAX) += hid-egalax.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o @@ -41,9 +43,12 @@ obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MOSART) += hid-mosart.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_QUANTA) += hid-quanta.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_ROCCAT_KONE) += hid-roccat-kone.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SONY) += hid-sony.o @@ -54,6 +59,7 @@ obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o +obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o obj-$(CONFIG_USB_HID) += usbhid/ diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c index c31e0be8cce..2a0d56b7a02 100644 --- a/drivers/hid/hid-3m-pct.c +++ b/drivers/hid/hid-3m-pct.c @@ -1,7 +1,7 @@ /* * HID driver for 3M PCT multitouch panels * - * Copyright (c) 2009 Stephane Chatty <chatty@enac.fr> + * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> * */ @@ -25,7 +25,7 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" struct mmm_finger { - __s32 x, y; + __s32 x, y, w, h; __u8 rank; bool touch, valid; }; @@ -82,7 +82,18 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* touchscreen emulation */ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); return 1; + 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, + 1, 1, 0, 0); + return 1; case HID_DG_CONTACTID: + field->logical_maximum = 59; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TRACKING_ID); return 1; @@ -128,9 +139,15 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) /* this finger is just placeholder data, ignore */ } else if (f->touch) { /* this finger is on the screen */ + int wide = (f->w > f->h); input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i); input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); + input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); + input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, + wide ? f->w : f->h); + input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, + wide ? f->h : f->w); input_mt_sync(input); /* * touchscreen emulation: maintain the age rank @@ -197,6 +214,14 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field, case HID_DG_CONFIDENCE: md->valid = value; break; + case HID_DG_WIDTH: + if (md->valid) + md->f[md->curid].w = value; + break; + case HID_DG_HEIGHT: + if (md->valid) + md->f[md->curid].h = value; + break; case HID_DG_CONTACTID: if (md->valid) { md->curid = value; @@ -255,6 +280,7 @@ static void mmm_remove(struct hid_device *hdev) static const struct hid_device_id mmm_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, + { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, { } }; MODULE_DEVICE_TABLE(hid, mmm_devices); @@ -287,5 +313,4 @@ static void __exit mmm_exit(void) module_init(mmm_init); module_exit(mmm_exit); -MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c new file mode 100644 index 00000000000..4267a6fdc27 --- /dev/null +++ b/drivers/hid/hid-cando.c @@ -0,0 +1,272 @@ +/* + * HID driver for Cando dual-touch panels + * + * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr> + * + */ + +/* + * 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> + +MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); +MODULE_DESCRIPTION("Cando dual-touch panel"); +MODULE_LICENSE("GPL"); + +#include "hid-ids.h" + +struct cando_data { + __u16 x, y; + __u8 id; + __s8 oldest; /* id of the oldest finger in previous frame */ + bool valid; /* valid finger data, or just placeholder? */ + bool first; /* is this the first finger in this frame? */ + __s8 firstid; /* id of the first finger in the frame */ + __u16 firstx, firsty; /* (x, y) of the first finger in the frame */ +}; + +static int cando_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_GENDESK: + switch (usage->hid) { + case HID_GD_X: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_POSITION_X); + /* touchscreen emulation */ + input_set_abs_params(hi->input, ABS_X, + field->logical_minimum, + field->logical_maximum, 0, 0); + return 1; + case HID_GD_Y: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_POSITION_Y); + /* touchscreen emulation */ + input_set_abs_params(hi->input, ABS_Y, + field->logical_minimum, + field->logical_maximum, 0, 0); + return 1; + } + return 0; + + case HID_UP_DIGITIZER: + switch (usage->hid) { + case HID_DG_TIPSWITCH: + case HID_DG_CONTACTMAX: + return -1; + case HID_DG_INRANGE: + /* touchscreen emulation */ + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); + return 1; + case HID_DG_CONTACTID: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TRACKING_ID); + return 1; + } + return 0; + } + + return 0; +} + +static int cando_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) + clear_bit(usage->code, *bit); + + return 0; +} + +/* + * this function is called when a whole finger has been parsed, + * so that it can decide what to send to the input layer. + */ +static void cando_filter_event(struct cando_data *td, struct input_dev *input) +{ + td->first = !td->first; /* touchscreen emulation */ + + if (!td->valid) { + /* + * touchscreen emulation: if this is the second finger and + * the first was valid, the first was the oldest; if the + * first was not valid and there was a valid finger in the + * previous frame, this is a release. + */ + if (td->first) { + td->firstid = -1; + } else if (td->firstid >= 0) { + input_event(input, EV_ABS, ABS_X, td->firstx); + input_event(input, EV_ABS, ABS_Y, td->firsty); + td->oldest = td->firstid; + } else if (td->oldest >= 0) { + input_event(input, EV_KEY, BTN_TOUCH, 0); + td->oldest = -1; + } + + return; + } + + input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); + input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); + + input_mt_sync(input); + + /* + * touchscreen emulation: if there was no touching finger previously, + * emit touch event + */ + if (td->oldest < 0) { + input_event(input, EV_KEY, BTN_TOUCH, 1); + td->oldest = td->id; + } + + /* + * touchscreen emulation: if this is the first finger, wait for the + * second; the oldest is then the second if it was the oldest already + * or if there was no first, the first otherwise. + */ + if (td->first) { + td->firstx = td->x; + td->firsty = td->y; + td->firstid = td->id; + } else { + int x, y, oldest; + if (td->id == td->oldest || td->firstid < 0) { + x = td->x; + y = td->y; + oldest = td->id; + } else { + x = td->firstx; + y = td->firsty; + oldest = td->firstid; + } + input_event(input, EV_ABS, ABS_X, x); + input_event(input, EV_ABS, ABS_Y, y); + td->oldest = oldest; + } +} + + +static int cando_event(struct hid_device *hid, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + struct cando_data *td = hid_get_drvdata(hid); + + if (hid->claimed & HID_CLAIMED_INPUT) { + struct input_dev *input = field->hidinput->input; + + switch (usage->hid) { + case HID_DG_INRANGE: + td->valid = value; + break; + case HID_DG_CONTACTID: + td->id = value; + break; + case HID_GD_X: + td->x = value; + break; + case HID_GD_Y: + td->y = value; + cando_filter_event(td, input); + break; + case HID_DG_TIPSWITCH: + /* avoid interference from generic hidinput handling */ + break; + + default: + /* fallback to the generic hidinput handling */ + return 0; + } + } + + /* 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 cando_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + struct cando_data *td; + + td = kmalloc(sizeof(struct cando_data), GFP_KERNEL); + if (!td) { + dev_err(&hdev->dev, "cannot allocate Cando Touch data\n"); + return -ENOMEM; + } + hid_set_drvdata(hdev, td); + td->first = false; + td->oldest = -1; + td->valid = false; + + ret = hid_parse(hdev); + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + + if (ret) + kfree(td); + + return ret; +} + +static void cando_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); + kfree(hid_get_drvdata(hdev)); + hid_set_drvdata(hdev, NULL); +} + +static const struct hid_device_id cando_devices[] = { + { 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_11_6) }, + { } +}; +MODULE_DEVICE_TABLE(hid, cando_devices); + +static const struct hid_usage_id cando_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 cando_driver = { + .name = "cando-touch", + .id_table = cando_devices, + .probe = cando_probe, + .remove = cando_remove, + .input_mapping = cando_input_mapping, |