Commit d6b92c2c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid into next

Pull HID patches from Jiri Kosina:
 - RMI driver for Synaptics touchpads, by Benjamin Tissoires, Andrew
   Duggan and Jiri Kosina
 - cleanup of hid-sony driver and improved support for Sixaxis and
   Dualshock 4, by Frank Praznik
 - other usual small fixes and support for new device IDs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (29 commits)
  HID: thingm: thingm_fwinfo[] doesn't need to be global
  HID: core: add two new usages for digitizer
  HID: hid-sensor-hub: new device id and quirk for STM Sensor hub
  HID: usbhid: enable NO_INIT_REPORTS quirk for Semico USB Keykoard
  HID: hid-sensor-hub: Set report quirk for Microsoft Surface
  HID: debug: add labels for HID Sensor Usages
  HID: uhid: Use kmemdup instead of kmalloc + memcpy
  HID: rmi: do not handle touchscreens through hid-rmi
  HID: quirk for Saitek RAT7 and MMO7 mices' mode button
  HID: core: fix validation of report id 0
  HID: rmi: fix masks for x and w_x data
  HID: rmi: fix wrong struct field name
  HID: rmi: do not fetch more than 16 bytes in a query
  HID: rmi: check for the existence of some optional queries before reading query 12
  HID: i2c-hid: hid report descriptor retrieval changes
  HID: add missing hid usages
  HID: hid-sony - allow 3rd party INTEC controller to turn off all leds
  HID: sony: Add blink support to the Sixaxis and DualShock 4 LEDs
  HID: sony: Initialize the controller LEDs with a device ID value
  HID: sony: Use the controller Bluetooth MAC address as the unique value in the battery name string
  ...
parents 1aacb90e beea3f4a
What: /sys/class/leds/blink1::<serial>/rgb
Date: January 2013
Contact: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Description: The ThingM blink1 is an USB RGB LED. The color notation is
3-byte hexadecimal. Read this attribute to get the last set
color. Write the 24-bit hexadecimal color to change the current
LED color. The default color is full white (0xFFFFFF).
For instance, set the color to green with: echo 00FF00 > rgb
What: /sys/class/leds/blink1::<serial>/fade
Date: January 2013
Contact: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Description: This attribute allows to set a fade time in milliseconds for
the next color change. Read the attribute to know the current
fade time. The default value is set to 0 (no fade time). For
instance, set a fade time of 2 seconds with: echo 2000 > fade
What: /sys/class/leds/blink1::<serial>/play
Date: January 2013
Contact: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Description: This attribute is used to play/pause the light patterns. Write 1
to start playing, 0 to stop. Reading this attribute returns the
current playing status.
......@@ -608,7 +608,10 @@ config HID_SAITEK
Support for Saitek devices that are not fully compliant with the
HID standard.
Currently only supports the PS1000 controller.
Supported devices:
- PS1000 Dual Analog Pad
- R.A.T.7 Gaming Mouse
- M.M.O.7 Gaming Mouse
config HID_SAMSUNG
tristate "Samsung InfraRed remote control or keyboards"
......@@ -657,6 +660,14 @@ config HID_SUNPLUS
---help---
Support for Sunplus wireless desktop.
config HID_RMI
tristate "Synaptics RMI4 device support"
depends on HID
---help---
Support for Synaptics RMI4 touchpads.
Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid
and want support for its special functionalities.
config HID_GREENASIA
tristate "GreenAsia (Product ID 0x12) game controller support"
depends on HID
......
......@@ -97,6 +97,7 @@ 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-konepure.o hid-roccat-kovaplus.o \
hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o
obj-$(CONFIG_HID_RMI) += hid-rmi.o
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
......
......@@ -779,6 +779,14 @@ static int hid_scan_report(struct hid_device *hid)
(hid->group == HID_GROUP_MULTITOUCH))
hid->group = HID_GROUP_MULTITOUCH_WIN_8;
/*
* Vendor specific handlings
*/
if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) &&
(hid->group == HID_GROUP_GENERIC))
/* hid-rmi should take care of them, not hid-generic */
hid->group = HID_GROUP_RMI;
vfree(parser);
return 0;
}
......@@ -842,7 +850,17 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
* ->numbered being checked, which may not always be the case when
* drivers go to access report values.
*/
report = hid->report_enum[type].report_id_hash[id];
if (id == 0) {
/*
* Validating on id 0 means we should examine the first
* report in the list.
*/
report = list_entry(
hid->report_enum[type].report_list.next,
struct hid_report, list);
} else {
report = hid->report_enum[type].report_id_hash[id];
}
if (!report) {
hid_err(hid, "missing %s %u\n", hid_report_names[type], id);
return NULL;
......@@ -1868,7 +1886,11 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
#endif
#if IS_ENABLED(CONFIG_HID_SAITEK)
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
#endif
{ 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) },
......
......@@ -165,6 +165,8 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x53, "DeviceIndex"},
{0, 0x54, "ContactCount"},
{0, 0x55, "ContactMaximumNumber"},
{0, 0x5A, "SecondaryBarrelSwitch"},
{0, 0x5B, "TransducerSerialNumber"},
{ 15, 0, "PhysicalInterfaceDevice" },
{0, 0x00, "Undefined"},
{0, 0x01, "Physical_Interface_Device"},
......@@ -272,6 +274,85 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0xAA, "Shared_Parameter_Blocks"},
{0, 0xAB, "Create_New_Effect_Report"},
{0, 0xAC, "RAM_Pool_Available"},
{ 0x20, 0, "Sensor" },
{ 0x20, 0x01, "Sensor" },
{ 0x20, 0x10, "Biometric" },
{ 0x20, 0x11, "BiometricHumanPresence" },
{ 0x20, 0x12, "BiometricHumanProximity" },
{ 0x20, 0x13, "BiometricHumanTouch" },
{ 0x20, 0x20, "Electrical" },
{ 0x20, 0x21, "ElectricalCapacitance" },
{ 0x20, 0x22, "ElectricalCurrent" },
{ 0x20, 0x23, "ElectricalPower" },
{ 0x20, 0x24, "ElectricalInductance" },
{ 0x20, 0x25, "ElectricalResistance" },
{ 0x20, 0x26, "ElectricalVoltage" },
{ 0x20, 0x27, "ElectricalPoteniometer" },
{ 0x20, 0x28, "ElectricalFrequency" },
{ 0x20, 0x29, "ElectricalPeriod" },
{ 0x20, 0x30, "Environmental" },
{ 0x20, 0x31, "EnvironmentalAtmosphericPressure" },
{ 0x20, 0x32, "EnvironmentalHumidity" },
{ 0x20, 0x33, "EnvironmentalTemperature" },
{ 0x20, 0x34, "EnvironmentalWindDirection" },
{ 0x20, 0x35, "EnvironmentalWindSpeed" },
{ 0x20, 0x40, "Light" },
{ 0x20, 0x41, "LightAmbientLight" },
{ 0x20, 0x42, "LightConsumerInfrared" },
{ 0x20, 0x50, "Location" },
{ 0x20, 0x51, "LocationBroadcast" },
{ 0x20, 0x52, "LocationDeadReckoning" },
{ 0x20, 0x53, "LocationGPS" },
{ 0x20, 0x54, "LocationLookup" },
{ 0x20, 0x55, "LocationOther" },
{ 0x20, 0x56, "LocationStatic" },
{ 0x20, 0x57, "LocationTriangulation" },
{ 0x20, 0x60, "Mechanical" },
{ 0x20, 0x61, "MechanicalBooleanSwitch" },
{ 0x20, 0x62, "MechanicalBooleanSwitchArray" },
{ 0x20, 0x63, "MechanicalMultivalueSwitch" },
{ 0x20, 0x64, "MechanicalForce" },
{ 0x20, 0x65, "MechanicalPressure" },
{ 0x20, 0x66, "MechanicalStrain" },
{ 0x20, 0x67, "MechanicalWeight" },
{ 0x20, 0x68, "MechanicalHapticVibrator" },
{ 0x20, 0x69, "MechanicalHallEffectSwitch" },
{ 0x20, 0x70, "Motion" },
{ 0x20, 0x71, "MotionAccelerometer1D" },
{ 0x20, 0x72, "MotionAccelerometer2D" },
{ 0x20, 0x73, "MotionAccelerometer3D" },
{ 0x20, 0x74, "MotionGyrometer1D" },
{ 0x20, 0x75, "MotionGyrometer2D" },
{ 0x20, 0x76, "MotionGyrometer3D" },
{ 0x20, 0x77, "MotionMotionDetector" },
{ 0x20, 0x78, "MotionSpeedometer" },
{ 0x20, 0x79, "MotionAccelerometer" },
{ 0x20, 0x7A, "MotionGyrometer" },
{ 0x20, 0x80, "Orientation" },
{ 0x20, 0x81, "OrientationCompass1D" },
{ 0x20, 0x82, "OrientationCompass2D" },
{ 0x20, 0x83, "OrientationCompass3D" },
{ 0x20, 0x84, "OrientationInclinometer1D" },
{ 0x20, 0x85, "OrientationInclinometer2D" },
{ 0x20, 0x86, "OrientationInclinometer3D" },
{ 0x20, 0x87, "OrientationDistance1D" },
{ 0x20, 0x88, "OrientationDistance2D" },
{ 0x20, 0x89, "OrientationDistance3D" },
{ 0x20, 0x8A, "OrientationDeviceOrientation" },
{ 0x20, 0x8B, "OrientationCompass" },
{ 0x20, 0x8C, "OrientationInclinometer" },
{ 0x20, 0x8D, "OrientationDistance" },
{ 0x20, 0x90, "Scanner" },
{ 0x20, 0x91, "ScannerBarcode" },
{ 0x20, 0x91, "ScannerRFID" },
{ 0x20, 0x91, "ScannerNFC" },
{ 0x20, 0xA0, "Time" },
{ 0x20, 0xA1, "TimeAlarmTimer" },
{ 0x20, 0xA2, "TimeRealTimeClock" },
{ 0x20, 0xE0, "Other" },
{ 0x20, 0xE1, "OtherCustom" },
{ 0x20, 0xE2, "OtherGeneric" },
{ 0x20, 0xE3, "OtherGenericEnumerator" },
{ 0x84, 0, "Power Device" },
{ 0x84, 0x02, "PresentStatus" },
{ 0x84, 0x03, "ChangeStatus" },
......@@ -855,6 +936,16 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
[KEY_KBDILLUMUP] = "KbdIlluminationUp",
[KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
[KEY_BUTTONCONFIG] = "ButtonConfig",
[KEY_TASKMANAGER] = "TaskManager",
[KEY_JOURNAL] = "Journal",
[KEY_CONTROLPANEL] = "ControlPanel",
[KEY_APPSELECT] = "AppSelect",
[KEY_SCREENSAVER] = "ScreenSaver",
[KEY_VOICECOMMAND] = "VoiceCommand",
[KEY_BRIGHTNESS_MIN] = "BrightnessMin",
[KEY_BRIGHTNESS_MAX] = "BrightnessMax",
[KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
};
static const char *relatives[REL_MAX + 1] = {
......
......@@ -463,6 +463,7 @@
#define USB_VENDOR_ID_STM_0 0x0483
#define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1
#define USB_DEVICE_ID_STM_HID_SENSOR_1 0x9100
#define USB_VENDOR_ID_ION 0x15e4
#define USB_DEVICE_ID_ICADE 0x0132
......@@ -633,6 +634,9 @@
#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_DEVICE_ID_MS_SURFACE_PRO_2 0x0799
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_VENDOR_ID_MOJO 0x8282
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
......@@ -764,11 +768,16 @@
#define USB_VENDOR_ID_SAITEK 0x06a3
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
#define USB_DEVICE_ID_SAITEK_PS1000 0x0621
#define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
#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_SEMICO 0x1a2c
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023
#define USB_VENDOR_ID_SENNHEISER 0x1395
#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c
......
......@@ -684,9 +684,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case 0x46: /* TabletPick */
case 0x5a: /* SecondaryBarrelSwitch */
map_key_clear(BTN_STYLUS2);
break;
case 0x5b: /* TransducerSerialNumber */
set_bit(MSC_SERIAL, input->mscbit);
break;
default: goto unknown;
}
break;
......@@ -721,6 +726,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x06c: map_key_clear(KEY_YELLOW); break;
case 0x06d: map_key_clear(KEY_ZOOM); break;
case 0x06f: map_key_clear(KEY_BRIGHTNESSUP); break;
case 0x070: map_key_clear(KEY_BRIGHTNESSDOWN); break;
case 0x072: map_key_clear(KEY_BRIGHTNESS_TOGGLE); break;
case 0x073: map_key_clear(KEY_BRIGHTNESS_MIN); break;
case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX); break;
case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO); 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;
......@@ -761,6 +773,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0bf: map_key_clear(KEY_SLOW); break;
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0cf: map_key_clear(KEY_VOICECOMMAND); 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;
......@@ -768,6 +781,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
case 0x0f5: map_key_clear(KEY_SLOW); break;
case 0x181: map_key_clear(KEY_BUTTONCONFIG); 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;
......@@ -781,6 +795,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
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 0x18f: map_key_clear(KEY_TASKMANAGER); break;
case 0x190: map_key_clear(KEY_JOURNAL); 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;
......@@ -789,12 +805,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
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 0x19f: map_key_clear(KEY_CONTROLPANEL); break;
case 0x1a2: map_key_clear(KEY_APPSELECT); break;
case 0x1a3: map_key_clear(KEY_NEXT); break;
case 0x1a4: map_key_clear(KEY_PREVIOUS); 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 0x1b1: map_key_clear(KEY_SCREENSAVER); break;
case 0x1b4: map_key_clear(KEY_FILE); break;
case 0x1b6: map_key_clear(KEY_IMAGES); break;
case 0x1b7: map_key_clear(KEY_AUDIO); break;
......
This diff is collapsed.
/*
* HID driver for Saitek devices, currently only the PS1000 (USB gamepad).
* HID driver for Saitek devices.
*
* 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
*
* R.A.T.7, M.M.O.7 (USB gaming mice):
* Fixes the mode button which cycles through three constantly pressed
* buttons. All three press events are mapped to one button and the
* missing release event is generated immediately.
*
*/
/*
......@@ -21,12 +28,57 @@
#include "hid-ids.h"
#define SAITEK_FIX_PS1000 0x0001
#define SAITEK_RELEASE_MODE_RAT7 0x0002
#define SAITEK_RELEASE_MODE_MMO7 0x0004
struct saitek_sc {
unsigned long quirks;
int mode;
};
static int saitek_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
unsigned long quirks = id->driver_data;
struct saitek_sc *ssc;
int ret;
ssc = devm_kzalloc(&hdev->dev, sizeof(*ssc), GFP_KERNEL);
if (ssc == NULL) {
hid_err(hdev, "can't alloc saitek descriptor\n");
return -ENOMEM;
}
ssc->quirks = quirks;
ssc->mode = -1;
hid_set_drvdata(hdev, ssc);
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
return ret;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");
return ret;
}
return 0;
}
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) {
struct saitek_sc *ssc = hid_get_drvdata(hdev);
if ((ssc->quirks & SAITEK_FIX_PS1000) && *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");
......@@ -42,8 +94,93 @@ static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}
static int saitek_raw_event(struct hid_device *hdev,
struct hid_report *report, u8 *raw_data, int size)
{
struct saitek_sc *ssc = hid_get_drvdata(hdev);
if (ssc->quirks & SAITEK_RELEASE_MODE_RAT7 && size == 7) {
/* R.A.T.7 uses bits 13, 14, 15 for the mode */
int mode = -1;
if (raw_data[1] & 0x01)
mode = 0;
else if (raw_data[1] & 0x02)
mode = 1;
else if (raw_data[1] & 0x04)
mode = 2;
/* clear mode bits */
raw_data[1] &= ~0x07;
if (mode != ssc->mode) {
hid_dbg(hdev, "entered mode %d\n", mode);
if (ssc->mode != -1) {
/* use bit 13 as the mode button */
raw_data[1] |= 0x04;
}
ssc->mode = mode;
}
} else if (ssc->quirks & SAITEK_RELEASE_MODE_MMO7 && size == 8) {
/* M.M.O.7 uses bits 8, 22, 23 for the mode */
int mode = -1;
if (raw_data[1] & 0x80)
mode = 0;
else if (raw_data[2] & 0x01)
mode = 1;
else if (raw_data[2] & 0x02)
mode = 2;
/* clear mode bits */
raw_data[1] &= ~0x80;
raw_data[2] &= ~0x03;
if (mode != ssc->mode) {
hid_dbg(hdev, "entered mode %d\n", mode);
if (ssc->mode != -1) {
/* use bit 8 as the mode button, bits 22
* and 23 do not represent buttons
* according to the HID report descriptor
*/
raw_data[1] |= 0x80;
}
ssc->mode = mode;
}
}
return 0;
}
static int saitek_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct saitek_sc *ssc = hid_get_drvdata(hdev);
struct input_dev *input = field->hidinput->input;
if (usage->type == EV_KEY && value &&
(((ssc->quirks & SAITEK_RELEASE_MODE_RAT7) &&
usage->code - BTN_MOUSE == 10) ||
((ssc->quirks & SAITEK_RELEASE_MODE_MMO7) &&
usage->code - BTN_MOUSE == 15))) {
input_report_key(input, usage->code, 1);
/* report missing release event */
input_report_key(input, usage->code, 0);
return 1;
}
return 0;
}
static const struct hid_device_id saitek_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000)},
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000),
.driver_data = SAITEK_FIX_PS1000 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
.driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
.driver_data = SAITEK_RELEASE_MODE_MMO7 },
{ }
};
......@@ -52,7 +189,10 @@ MODULE_DEVICE_TABLE(hid, saitek_devices);
static struct hid_driver saitek_driver = {
.name = "saitek",
.id_table = saitek_devices,
.report_fixup = saitek_report_fixup
.probe = saitek_probe,
.report_fixup = saitek_report_fixup,
.raw_event = saitek_raw_event,
.event = saitek_event,
};
module_hid_driver(saitek_driver);
......
......@@ -705,8 +705,17 @@ static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
USB_DEVICE_ID_INTEL_HID_SENSOR_1),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
USB_DEVICE_ID_MS_SURFACE_PRO_2),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
USB_DEVICE_ID_MS_TOUCH_COVER_2),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
USB_DEVICE_ID_MS_TYPE_COVER_2),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
USB_DEVICE_ID_STM_HID_SENSOR),
USB_DEVICE_ID_STM_HID_SENSOR_1),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS,
USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA),
......
This diff is collapsed.
/*
* ThingM blink(1) USB RGB LED driver
*
* Copyright 2013 Savoir-faire Linux Inc.
* Copyright 2013-2014 Savoir-faire Linux Inc.
* Vivien Didelot <vivien.didelot@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or
......@@ -10,244 +10,285 @@
*/
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include "hid-ids.h"
#define BLINK1_CMD_SIZE 9
#define REPORT_ID 1
#define REPORT_SIZE 9
#define blink1_rgb_to_r(rgb) ((rgb & 0xFF0000) >> 16)
#define blink1_rgb_to_g(rgb) ((rgb & 0x00FF00) >> 8)
#define blink1_rgb_to_b(rgb) ((rgb & 0x0000FF) >> 0)
/* Firmware major number of supported devices */
#define THINGM_MAJOR_MK1 '1'
#define THINGM_MAJOR_MK2 '2'
/**
* struct blink1_data - blink(1) device specific data
* @hdev: HID device.
* @led_cdev: LED class instance.
* @rgb: 8-bit per channel RGB notation.
* @fade: fade time in hundredths of a second.
* @brightness: brightness coefficient.
* @play: play/pause in-memory patterns.
*/
struct blink1_data {
struct thingm_fwinfo {
char major;
unsigned numrgb;
unsigned first;
};
static const struct thingm_fwinfo thingm_fwinfo[] = {
{
.major = THINGM_MAJOR_MK1,
.numrgb = 1,
.first = 0,
}, {
.major = THINGM_MAJOR_MK2,
.numrgb = 2,
.first = 1,
}
};
/* A red, green or blue channel, part of an RGB chip */
struct thingm_led {
struct thingm_rgb *rgb;
struct led_classdev ldev;
char name[32];
};
/* Basically a WS2812 5050 RGB LED chip */
struct thingm_rgb {
struct thingm_device *tdev;
struct thingm_led red;
struct thingm_led green;
struct thingm_led blue;
struct work_struct work;
u8 num;
};
struct thingm_device {
struct hid_device *hdev;
struct led_classdev led_cdev;
u32 rgb;
u16 fade;
u8 brightness;
bool play;
struct {
char major;
char minor;
} version;
const struct thingm_fwinfo *fwinfo;
struct mutex lock;
struct thingm_rgb *rgb;
};