diff options
| -rw-r--r-- | Documentation/ABI/testing/sysfs-driver-hid-thingm | 23 | ||||
| -rw-r--r-- | drivers/hid/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/hid/Makefile | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-core.c | 24 | ||||
| -rw-r--r-- | drivers/hid/hid-debug.c | 91 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 9 | ||||
| -rw-r--r-- | drivers/hid/hid-input.c | 19 | ||||
| -rw-r--r-- | drivers/hid/hid-rmi.c | 920 | ||||
| -rw-r--r-- | drivers/hid/hid-saitek.c | 154 | ||||
| -rw-r--r-- | drivers/hid/hid-sensor-hub.c | 11 | ||||
| -rw-r--r-- | drivers/hid/hid-sony.c | 434 | ||||
| -rw-r--r-- | drivers/hid/hid-thingm.c | 361 | ||||
| -rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 45 | ||||
| -rw-r--r-- | drivers/hid/uhid.c | 5 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 1 | ||||
| -rw-r--r-- | drivers/leds/Kconfig | 2 | ||||
| -rw-r--r-- | include/linux/hid.h | 17 | ||||
| -rw-r--r-- | include/uapi/linux/input.h | 17 |
18 files changed, 1819 insertions, 328 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-thingm b/Documentation/ABI/testing/sysfs-driver-hid-thingm deleted file mode 100644 index abcffeedd20a..000000000000 --- a/Documentation/ABI/testing/sysfs-driver-hid-thingm +++ /dev/null | |||
| @@ -1,23 +0,0 @@ | |||
| 1 | What: /sys/class/leds/blink1::<serial>/rgb | ||
| 2 | Date: January 2013 | ||
| 3 | Contact: Vivien Didelot <vivien.didelot@savoirfairelinux.com> | ||
| 4 | Description: The ThingM blink1 is an USB RGB LED. The color notation is | ||
| 5 | 3-byte hexadecimal. Read this attribute to get the last set | ||
| 6 | color. Write the 24-bit hexadecimal color to change the current | ||
| 7 | LED color. The default color is full white (0xFFFFFF). | ||
| 8 | For instance, set the color to green with: echo 00FF00 > rgb | ||
| 9 | |||
| 10 | What: /sys/class/leds/blink1::<serial>/fade | ||
| 11 | Date: January 2013 | ||
| 12 | Contact: Vivien Didelot <vivien.didelot@savoirfairelinux.com> | ||
| 13 | Description: This attribute allows to set a fade time in milliseconds for | ||
| 14 | the next color change. Read the attribute to know the current | ||
| 15 | fade time. The default value is set to 0 (no fade time). For | ||
| 16 | instance, set a fade time of 2 seconds with: echo 2000 > fade | ||
| 17 | |||
| 18 | What: /sys/class/leds/blink1::<serial>/play | ||
| 19 | Date: January 2013 | ||
| 20 | Contact: Vivien Didelot <vivien.didelot@savoirfairelinux.com> | ||
| 21 | Description: This attribute is used to play/pause the light patterns. Write 1 | ||
| 22 | to start playing, 0 to stop. Reading this attribute returns the | ||
| 23 | current playing status. | ||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 7af9d0b5dea1..800c8b60f7a2 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -608,7 +608,10 @@ config HID_SAITEK | |||
| 608 | Support for Saitek devices that are not fully compliant with the | 608 | Support for Saitek devices that are not fully compliant with the |
| 609 | HID standard. | 609 | HID standard. |
| 610 | 610 | ||
| 611 | Currently only supports the PS1000 controller. | 611 | Supported devices: |
| 612 | - PS1000 Dual Analog Pad | ||
| 613 | - R.A.T.7 Gaming Mouse | ||
| 614 | - M.M.O.7 Gaming Mouse | ||
| 612 | 615 | ||
| 613 | config HID_SAMSUNG | 616 | config HID_SAMSUNG |
| 614 | tristate "Samsung InfraRed remote control or keyboards" | 617 | tristate "Samsung InfraRed remote control or keyboards" |
| @@ -657,6 +660,14 @@ config HID_SUNPLUS | |||
| 657 | ---help--- | 660 | ---help--- |
| 658 | Support for Sunplus wireless desktop. | 661 | Support for Sunplus wireless desktop. |
| 659 | 662 | ||
| 663 | config HID_RMI | ||
| 664 | tristate "Synaptics RMI4 device support" | ||
| 665 | depends on HID | ||
| 666 | ---help--- | ||
| 667 | Support for Synaptics RMI4 touchpads. | ||
| 668 | Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid | ||
| 669 | and want support for its special functionalities. | ||
| 670 | |||
| 660 | config HID_GREENASIA | 671 | config HID_GREENASIA |
| 661 | tristate "GreenAsia (Product ID 0x12) game controller support" | 672 | tristate "GreenAsia (Product ID 0x12) game controller support" |
| 662 | depends on HID | 673 | depends on HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index fc712dde02a4..a6fa6baf368e 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -97,6 +97,7 @@ obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ | |||
| 97 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ | 97 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ |
| 98 | hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ | 98 | hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ |
| 99 | hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o | 99 | hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o |
| 100 | obj-$(CONFIG_HID_RMI) += hid-rmi.o | ||
| 100 | obj-$(CONFIG_HID_SAITEK) += hid-saitek.o | 101 | obj-$(CONFIG_HID_SAITEK) += hid-saitek.o |
| 101 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 102 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
| 102 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o | 103 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index da52279de939..8ed66fd1ea87 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -779,6 +779,14 @@ static int hid_scan_report(struct hid_device *hid) | |||
| 779 | (hid->group == HID_GROUP_MULTITOUCH)) | 779 | (hid->group == HID_GROUP_MULTITOUCH)) |
| 780 | hid->group = HID_GROUP_MULTITOUCH_WIN_8; | 780 | hid->group = HID_GROUP_MULTITOUCH_WIN_8; |
| 781 | 781 | ||
| 782 | /* | ||
| 783 | * Vendor specific handlings | ||
| 784 | */ | ||
| 785 | if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) && | ||
| 786 | (hid->group == HID_GROUP_GENERIC)) | ||
| 787 | /* hid-rmi should take care of them, not hid-generic */ | ||
| 788 | hid->group = HID_GROUP_RMI; | ||
| 789 | |||
| 782 | vfree(parser); | 790 | vfree(parser); |
| 783 | return 0; | 791 | return 0; |
| 784 | } | 792 | } |
| @@ -842,7 +850,17 @@ struct hid_report *hid_validate_values(struct hid_device *hid, | |||
| 842 | * ->numbered being checked, which may not always be the case when | 850 | * ->numbered being checked, which may not always be the case when |
| 843 | * drivers go to access report values. | 851 | * drivers go to access report values. |
| 844 | */ | 852 | */ |
| 845 | report = hid->report_enum[type].report_id_hash[id]; | 853 | if (id == 0) { |
| 854 | /* | ||
| 855 | * Validating on id 0 means we should examine the first | ||
| 856 | * report in the list. | ||
| 857 | */ | ||
| 858 | report = list_entry( | ||
| 859 | hid->report_enum[type].report_list.next, | ||
| 860 | struct hid_report, list); | ||
| 861 | } else { | ||
| 862 | report = hid->report_enum[type].report_id_hash[id]; | ||
| 863 | } | ||
| 846 | if (!report) { | 864 | if (!report) { |
| 847 | hid_err(hid, "missing %s %u\n", hid_report_names[type], id); | 865 | hid_err(hid, "missing %s %u\n", hid_report_names[type], id); |
| 848 | return NULL; | 866 | return NULL; |
| @@ -1868,7 +1886,11 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1868 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) }, | 1886 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) }, |
| 1869 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, | 1887 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, |
| 1870 | #endif | 1888 | #endif |
| 1889 | #if IS_ENABLED(CONFIG_HID_SAITEK) | ||
| 1871 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, | 1890 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, |
| 1891 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, | ||
| 1892 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, | ||
| 1893 | #endif | ||
| 1872 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1894 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
| 1873 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, | 1895 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |
| 1874 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, | 1896 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 53b771d5683c..84c3cb15ccdd 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
| @@ -165,6 +165,8 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
| 165 | {0, 0x53, "DeviceIndex"}, | 165 | {0, 0x53, "DeviceIndex"}, |
| 166 | {0, 0x54, "ContactCount"}, | 166 | {0, 0x54, "ContactCount"}, |
| 167 | {0, 0x55, "ContactMaximumNumber"}, | 167 | {0, 0x55, "ContactMaximumNumber"}, |
| 168 | {0, 0x5A, "SecondaryBarrelSwitch"}, | ||
| 169 | {0, 0x5B, "TransducerSerialNumber"}, | ||
| 168 | { 15, 0, "PhysicalInterfaceDevice" }, | 170 | { 15, 0, "PhysicalInterfaceDevice" }, |
| 169 | {0, 0x00, "Undefined"}, | 171 | {0, 0x00, "Undefined"}, |
| 170 | {0, 0x01, "Physical_Interface_Device"}, | 172 | {0, 0x01, "Physical_Interface_Device"}, |
| @@ -272,6 +274,85 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
| 272 | {0, 0xAA, "Shared_Parameter_Blocks"}, | 274 | {0, 0xAA, "Shared_Parameter_Blocks"}, |
| 273 | {0, 0xAB, "Create_New_Effect_Report"}, | 275 | {0, 0xAB, "Create_New_Effect_Report"}, |
| 274 | {0, 0xAC, "RAM_Pool_Available"}, | 276 | {0, 0xAC, "RAM_Pool_Available"}, |
| 277 | { 0x20, 0, "Sensor" }, | ||
| 278 | { 0x20, 0x01, "Sensor" }, | ||
| 279 | { 0x20, 0x10, "Biometric" }, | ||
| 280 | { 0x20, 0x11, "BiometricHumanPresence" }, | ||
| 281 | { 0x20, 0x12, "BiometricHumanProximity" }, | ||
| 282 | { 0x20, 0x13, "BiometricHumanTouch" }, | ||
| 283 | { 0x20, 0x20, "Electrical" }, | ||
| 284 | { 0x20, 0x21, "ElectricalCapacitance" }, | ||
| 285 | { 0x20, 0x22, "ElectricalCurrent" }, | ||
| 286 | { 0x20, 0x23, "ElectricalPower" }, | ||
| 287 | { 0x20, 0x24, "ElectricalInductance" }, | ||
| 288 | { 0x20, 0x25, "ElectricalResistance" }, | ||
| 289 | { 0x20, 0x26, "ElectricalVoltage" }, | ||
| 290 | { 0x20, 0x27, "ElectricalPoteniometer" }, | ||
| 291 | { 0x20, 0x28, "ElectricalFrequency" }, | ||
| 292 | { 0x20, 0x29, "ElectricalPeriod" }, | ||
| 293 | { 0x20, 0x30, "Environmental" }, | ||
| 294 | { 0x20, 0x31, "EnvironmentalAtmosphericPressure" }, | ||
| 295 | { 0x20, 0x32, "EnvironmentalHumidity" }, | ||
| 296 | { 0x20, 0x33, "EnvironmentalTemperature" }, | ||
| 297 | { 0x20, 0x34, "EnvironmentalWindDirection" }, | ||
| 298 | { 0x20, 0x35, "EnvironmentalWindSpeed" }, | ||
| 299 | { 0x20, 0x40, "Light" }, | ||
| 300 | { 0x20, 0x41, "LightAmbientLight" }, | ||
| 301 | { 0x20, 0x42, "LightConsumerInfrared" }, | ||
| 302 | { 0x20, 0x50, "Location" }, | ||
| 303 | { 0x20, 0x51, "LocationBroadcast" }, | ||
| 304 | { 0x20, 0x52, "LocationDeadReckoning" }, | ||
| 305 | { 0x20, 0x53, "LocationGPS" }, | ||
| 306 | { 0x20, 0x54, "LocationLookup" }, | ||
| 307 | { 0x20, 0x55, "LocationOther" }, | ||
| 308 | { 0x20, 0x56, "LocationStatic" }, | ||
| 309 | { 0x20, 0x57, "LocationTriangulation" }, | ||
| 310 | { 0x20, 0x60, "Mechanical" }, | ||
| 311 | { 0x20, 0x61, "MechanicalBooleanSwitch" }, | ||
| 312 | { 0x20, 0x62, "MechanicalBooleanSwitchArray" }, | ||
| 313 | { 0x20, 0x63, "MechanicalMultivalueSwitch" }, | ||
| 314 | { 0x20, 0x64, "MechanicalForce" }, | ||
| 315 | { 0x20, 0x65, "MechanicalPressure" }, | ||
| 316 | { 0x20, 0x66, "MechanicalStrain" }, | ||
| 317 | { 0x20, 0x67, "MechanicalWeight" }, | ||
| 318 | { 0x20, 0x68, "MechanicalHapticVibrator" }, | ||
| 319 | { 0x20, 0x69, "MechanicalHallEffectSwitch" }, | ||
| 320 | { 0x20, 0x70, "Motion" }, | ||
| 321 | { 0x20, 0x71, "MotionAccelerometer1D" }, | ||
| 322 | { 0x20, 0x72, "MotionAccelerometer2D" }, | ||
| 323 | { 0x20, 0x73, "MotionAccelerometer3D" }, | ||
| 324 | { 0x20, 0x74, "MotionGyrometer1D" }, | ||
| 325 | { 0x20, 0x75, "MotionGyrometer2D" }, | ||
| 326 | { 0x20, 0x76, "MotionGyrometer3D" }, | ||
| 327 | { 0x20, 0x77, "MotionMotionDetector" }, | ||
| 328 | { 0x20, 0x78, "MotionSpeedometer" }, | ||
| 329 | { 0x20, 0x79, "MotionAccelerometer" }, | ||
| 330 | { 0x20, 0x7A, "MotionGyrometer" }, | ||
| 331 | { 0x20, 0x80, "Orientation" }, | ||
| 332 | { 0x20, 0x81, "OrientationCompass1D" }, | ||
| 333 | { 0x20, 0x82, "OrientationCompass2D" }, | ||
| 334 | { 0x20, 0x83, "OrientationCompass3D" }, | ||
| 335 | { 0x20, 0x84, "OrientationInclinometer1D" }, | ||
| 336 | { 0x20, 0x85, "OrientationInclinometer2D" }, | ||
| 337 | { 0x20, 0x86, "OrientationInclinometer3D" }, | ||
| 338 | { 0x20, 0x87, "OrientationDistance1D" }, | ||
| 339 | { 0x20, 0x88, "OrientationDistance2D" }, | ||
| 340 | { 0x20, 0x89, "OrientationDistance3D" }, | ||
| 341 | { 0x20, 0x8A, "OrientationDeviceOrientation" }, | ||
| 342 | { 0x20, 0x8B, "OrientationCompass" }, | ||
| 343 | { 0x20, 0x8C, "OrientationInclinometer" }, | ||
| 344 | { 0x20, 0x8D, "OrientationDistance" }, | ||
| 345 | { 0x20, 0x90, "Scanner" }, | ||
| 346 | { 0x20, 0x91, "ScannerBarcode" }, | ||
| 347 | { 0x20, 0x91, "ScannerRFID" }, | ||
| 348 | { 0x20, 0x91, "ScannerNFC" }, | ||
| 349 | { 0x20, 0xA0, "Time" }, | ||
| 350 | { 0x20, 0xA1, "TimeAlarmTimer" }, | ||
| 351 | { 0x20, 0xA2, "TimeRealTimeClock" }, | ||
| 352 | { 0x20, 0xE0, "Other" }, | ||
| 353 | { 0x20, 0xE1, "OtherCustom" }, | ||
| 354 | { 0x20, 0xE2, "OtherGeneric" }, | ||
| 355 | { 0x20, 0xE3, "OtherGenericEnumerator" }, | ||
| 275 | { 0x84, 0, "Power Device" }, | 356 | { 0x84, 0, "Power Device" }, |
| 276 | { 0x84, 0x02, "PresentStatus" }, | 357 | { 0x84, 0x02, "PresentStatus" }, |
| 277 | { 0x84, 0x03, "ChangeStatus" }, | 358 | { 0x84, 0x03, "ChangeStatus" }, |
| @@ -855,6 +936,16 @@ static const char *keys[KEY_MAX + 1] = { | |||
| 855 | [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", | 936 | [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", |
| 856 | [KEY_KBDILLUMUP] = "KbdIlluminationUp", | 937 | [KEY_KBDILLUMUP] = "KbdIlluminationUp", |
| 857 | [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", | 938 | [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", |
| 939 | [KEY_BUTTONCONFIG] = "ButtonConfig", | ||
| 940 | [KEY_TASKMANAGER] = "TaskManager", | ||
| 941 | [KEY_JOURNAL] = "Journal", | ||
| 942 | [KEY_CONTROLPANEL] = "ControlPanel", | ||
| 943 | [KEY_APPSELECT] = "AppSelect", | ||
| 944 | [KEY_SCREENSAVER] = "ScreenSaver", | ||
| 945 | [KEY_VOICECOMMAND] = "VoiceCommand", | ||
| 946 | [KEY_BRIGHTNESS_MIN] = "BrightnessMin", | ||
| 947 | [KEY_BRIGHTNESS_MAX] = "BrightnessMax", | ||
| 948 | [KEY_BRIGHTNESS_AUTO] = "BrightnessAuto", | ||
| 858 | }; | 949 | }; |
| 859 | 950 | ||
| 860 | static const char *relatives[REL_MAX + 1] = { | 951 | static const char *relatives[REL_MAX + 1] = { |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 34bb2205d2ea..6d00bb9366fa 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -463,6 +463,7 @@ | |||
| 463 | 463 | ||
| 464 | #define USB_VENDOR_ID_STM_0 0x0483 | 464 | #define USB_VENDOR_ID_STM_0 0x0483 |
| 465 | #define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1 | 465 | #define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1 |
| 466 | #define USB_DEVICE_ID_STM_HID_SENSOR_1 0x9100 | ||
| 466 | 467 | ||
| 467 | #define USB_VENDOR_ID_ION 0x15e4 | 468 | #define USB_VENDOR_ID_ION 0x15e4 |
| 468 | #define USB_DEVICE_ID_ICADE 0x0132 | 469 | #define USB_DEVICE_ID_ICADE 0x0132 |
| @@ -633,6 +634,9 @@ | |||
| 633 | #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 | 634 | #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 |
| 634 | #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 | 635 | #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 |
| 635 | #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c | 636 | #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c |
| 637 | #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 | ||
| 638 | #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 | ||
| 639 | #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 | ||
| 636 | 640 | ||
| 637 | #define USB_VENDOR_ID_MOJO 0x8282 | 641 | #define USB_VENDOR_ID_MOJO 0x8282 |
| 638 | #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 | 642 | #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 |
| @@ -764,11 +768,16 @@ | |||
| 764 | #define USB_VENDOR_ID_SAITEK 0x06a3 | 768 | #define USB_VENDOR_ID_SAITEK 0x06a3 |
| 765 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | 769 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 |
| 766 | #define USB_DEVICE_ID_SAITEK_PS1000 0x0621 | 770 | #define USB_DEVICE_ID_SAITEK_PS1000 0x0621 |
| 771 | #define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7 | ||
| 772 | #define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0 | ||
| 767 | 773 | ||
| 768 | #define USB_VENDOR_ID_SAMSUNG 0x0419 | 774 | #define USB_VENDOR_ID_SAMSUNG 0x0419 |
| 769 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 | 775 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 |
| 770 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 | 776 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 |
| 771 | 777 | ||
| 778 | #define USB_VENDOR_ID_SEMICO 0x1a2c | ||
| 779 | #define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023 | ||
| 780 | |||
| 772 | #define USB_VENDOR_ID_SENNHEISER 0x1395 | 781 | #define USB_VENDOR_ID_SENNHEISER 0x1395 |
| 773 | #define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c | 782 | #define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c |
| 774 | 783 | ||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index e7e8b19a9284..2619f7f4517a 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -684,9 +684,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 684 | break; | 684 | break; |
| 685 | 685 | ||
| 686 | case 0x46: /* TabletPick */ | 686 | case 0x46: /* TabletPick */ |
| 687 | case 0x5a: /* SecondaryBarrelSwitch */ | ||
| 687 | map_key_clear(BTN_STYLUS2); | 688 | map_key_clear(BTN_STYLUS2); |
| 688 | break; | 689 | break; |
| 689 | 690 | ||
| 691 | case 0x5b: /* TransducerSerialNumber */ | ||
| 692 | set_bit(MSC_SERIAL, input->mscbit); | ||
| 693 | break; | ||
| 694 | |||
| 690 | default: goto unknown; | 695 | default: goto unknown; |
| 691 | } | 696 | } |
| 692 | break; | 697 | break; |
| @@ -721,6 +726,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 721 | case 0x06c: map_key_clear(KEY_YELLOW); break; | 726 | case 0x06c: map_key_clear(KEY_YELLOW); break; |
| 722 | case 0x06d: map_key_clear(KEY_ZOOM); break; | 727 | case 0x06d: map_key_clear(KEY_ZOOM); break; |
| 723 | 728 | ||
| 729 | case 0x06f: map_key_clear(KEY_BRIGHTNESSUP); break; | ||
| 730 | case 0x070: map_key_clear(KEY_BRIGHTNESSDOWN); break; | ||
| 731 | case 0x072: map_key_clear(KEY_BRIGHTNESS_TOGGLE); break; | ||
| 732 | case 0x073: map_key_clear(KEY_BRIGHTNESS_MIN); break; | ||
| 733 | case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX); break; | ||
| 734 | case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO); break; | ||
| 735 | |||
| 724 | case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; | 736 | case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; |
| 725 | case 0x083: map_key_clear(KEY_LAST); break; | 737 | case 0x083: map_key_clear(KEY_LAST); break; |
| 726 | case 0x084: map_key_clear(KEY_ENTER); break; | 738 | case 0x084: map_key_clear(KEY_ENTER); break; |
| @@ -761,6 +773,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 761 | case 0x0bf: map_key_clear(KEY_SLOW); break; | 773 | case 0x0bf: map_key_clear(KEY_SLOW); break; |
| 762 | 774 | ||
| 763 | case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; | 775 | case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; |
| 776 | case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break; | ||
| 764 | case 0x0e0: map_abs_clear(ABS_VOLUME); break; | 777 | case 0x0e0: map_abs_clear(ABS_VOLUME); break; |
| 765 | case 0x0e2: map_key_clear(KEY_MUTE); break; | 778 | case 0x0e2: map_key_clear(KEY_MUTE); break; |
| 766 | case 0x0e5: map_key_clear(KEY_BASSBOOST); break; | 779 | case 0x0e5: map_key_clear(KEY_BASSBOOST); break; |
| @@ -768,6 +781,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 768 | case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; | 781 | case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; |
| 769 | case 0x0f5: map_key_clear(KEY_SLOW); break; | 782 | case 0x0f5: map_key_clear(KEY_SLOW); break; |
| 770 | 783 | ||
| 784 | case 0x181: map_key_clear(KEY_BUTTONCONFIG); break; | ||
| 771 | case 0x182: map_key_clear(KEY_BOOKMARKS); break; | 785 | case 0x182: map_key_clear(KEY_BOOKMARKS); break; |
| 772 | case 0x183: map_key_clear(KEY_CONFIG); break; | 786 | case 0x183: map_key_clear(KEY_CONFIG); break; |
| 773 | case 0x184: map_key_clear(KEY_WORDPROCESSOR); break; | 787 | case 0x184: map_key_clear(KEY_WORDPROCESSOR); break; |
| @@ -781,6 +795,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 781 | case 0x18c: map_key_clear(KEY_VOICEMAIL); break; | 795 | case 0x18c: map_key_clear(KEY_VOICEMAIL); break; |
| 782 | case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break; | 796 | case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break; |
| 783 | case 0x18e: map_key_clear(KEY_CALENDAR); break; | 797 | case 0x18e: map_key_clear(KEY_CALENDAR); break; |
| 798 | case 0x18f: map_key_clear(KEY_TASKMANAGER); break; | ||
| 799 | case 0x190: map_key_clear(KEY_JOURNAL); break; | ||
| 784 | case 0x191: map_key_clear(KEY_FINANCE); break; | 800 | case 0x191: map_key_clear(KEY_FINANCE); break; |
| 785 | case 0x192: map_key_clear(KEY_CALC); break; | 801 | case 0x192: map_key_clear(KEY_CALC); break; |
| 786 | case 0x193: map_key_clear(KEY_PLAYER); break; | 802 | case 0x193: map_key_clear(KEY_PLAYER); break; |
| @@ -789,12 +805,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 789 | case 0x199: map_key_clear(KEY_CHAT); break; | 805 | case 0x199: map_key_clear(KEY_CHAT); break; |
| 790 | case 0x19c: map_key_clear(KEY_LOGOFF); break; | 806 | case 0x19c: map_key_clear(KEY_LOGOFF); break; |
| 791 | case 0x19e: map_key_clear(KEY_COFFEE); break; | 807 | case 0x19e: map_key_clear(KEY_COFFEE); break; |
| 808 | case 0x19f: map_key_clear(KEY_CONTROLPANEL); break; | ||
| 809 | case 0x1a2: map_key_clear(KEY_APPSELECT); break; | ||
| 792 | case 0x1a3: map_key_clear(KEY_NEXT); break; | 810 | case 0x1a3: map_key_clear(KEY_NEXT); break; |
| 793 | case 0x1a4: map_key_clear(KEY_PREVIOUS); break; | 811 | case 0x1a4: map_key_clear(KEY_PREVIOUS); break; |
| 794 | case 0x1a6: map_key_clear(KEY_HELP); break; | 812 | case 0x1a6: map_key_clear(KEY_HELP); break; |
| 795 | case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; | 813 | case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; |
| 796 | case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; | 814 | case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; |
| 797 | case 0x1ae: map_key_clear(KEY_KEYBOARD); break; | 815 | case 0x1ae: map_key_clear(KEY_KEYBOARD); break; |
| 816 | case 0x1b1: map_key_clear(KEY_SCREENSAVER); break; | ||
| 798 | case 0x1b4: map_key_clear(KEY_FILE); break; | 817 | case 0x1b4: map_key_clear(KEY_FILE); break; |
| 799 | case 0x1b6: map_key_clear(KEY_IMAGES); break; | 818 | case 0x1b6: map_key_clear(KEY_IMAGES); break; |
| 800 | case 0x1b7: map_key_clear(KEY_AUDIO); break; | 819 | case 0x1b7: map_key_clear(KEY_AUDIO); break; |
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c new file mode 100644 index 000000000000..2451c7e5febd --- /dev/null +++ b/drivers/hid/hid-rmi.c | |||
| @@ -0,0 +1,920 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Andrew Duggan <aduggan@synaptics.com> | ||
| 3 | * Copyright (c) 2013 Synaptics Incorporated | ||
| 4 | * Copyright (c) 2014 Benjamin Tissoires <benjamin.tissoires@gmail.com> | ||
| 5 | * Copyright (c) 2014 Red Hat, Inc | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/hid.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/input/mt.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/pm.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/wait.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include "hid-ids.h" | ||
| 23 | |||
| 24 | #define RMI_MOUSE_REPORT_ID 0x01 /* Mouse emulation Report */ | ||
| 25 | #define RMI_WRITE_REPORT_ID 0x09 /* Output Report */ | ||
| 26 | #define RMI_READ_ADDR_REPORT_ID 0x0a /* Output Report */ | ||
| 27 | #define RMI_READ_DATA_REPORT_ID 0x0b /* Input Report */ | ||
| 28 | #define RMI_ATTN_REPORT_ID 0x0c /* Input Report */ | ||
| 29 | #define RMI_SET_RMI_MODE_REPORT_ID 0x0f /* Feature Report */ | ||
| 30 | |||
| 31 | /* flags */ | ||
| 32 | #define RMI_READ_REQUEST_PENDING BIT(0) | ||
| 33 | #define RMI_READ_DATA_PENDING BIT(1) | ||
| 34 | #define RMI_STARTED BIT(2) | ||
| 35 | |||
| 36 | enum rmi_mode_type { | ||
| 37 | RMI_MODE_OFF = 0, | ||
| 38 | RMI_MODE_ATTN_REPORTS = 1, | ||
| 39 | RMI_MODE_NO_PACKED_ATTN_REPORTS = 2, | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct rmi_function { | ||
| 43 | unsigned page; /* page of the function */ | ||
| 44 | u16 query_base_addr; /* base address for queries */ | ||
| 45 | u16 command_base_addr; /* base address for commands */ | ||
| 46 | u16 control_base_addr; /* base address for controls */ | ||
| 47 | u16 data_base_addr; /* base address for datas */ | ||
| 48 | unsigned int interrupt_base; /* cross-function interrupt number | ||
| 49 | * (uniq in the device)*/ | ||
| 50 | unsigned int interrupt_count; /* number of interrupts */ | ||
| 51 | unsigned int report_size; /* size of a report */ | ||
| 52 | unsigned long irq_mask; /* mask of the interrupts | ||
| 53 | * (to be applied against ATTN IRQ) */ | ||
| 54 | }; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * struct rmi_data - stores information for hid communication | ||
| 58 | * | ||
| 59 | * @page_mutex: Locks current page to avoid changing pages in unexpected ways. | ||
| 60 | * @page: Keeps track of the current virtual page | ||
| 61 | * | ||
| 62 | * @wait: Used for waiting for read data | ||
| 63 | * | ||
| 64 | * @writeReport: output buffer when writing RMI registers | ||
| 65 | * @readReport: input buffer when reading RMI registers | ||
| 66 | * | ||
| 67 | * @input_report_size: size of an input report (advertised by HID) | ||
| 68 | * @output_report_size: size of an output report (advertised by HID) | ||
| 69 | * | ||
| 70 | * @flags: flags for the current device (started, reading, etc...) | ||
| 71 | * | ||
| 72 | * @f11: placeholder of internal RMI function F11 description | ||
| 73 | * @f30: placeholder of internal RMI function F30 description | ||
| 74 | * | ||
| 75 | * @max_fingers: maximum finger count reported by the device | ||
| 76 | * @max_x: maximum x value reported by the device | ||
| 77 | * @max_y: maximum y value reported by the device | ||
| 78 | * | ||
| 79 | * @gpio_led_count: count of GPIOs + LEDs reported by F30 | ||
| 80 | * @button_count: actual physical buttons count | ||
| 81 | * @button_mask: button mask used to decode GPIO ATTN reports | ||
| 82 | * @button_state_mask: pull state of the buttons | ||
| 83 | * | ||
| 84 | * @input: pointer to the kernel input device | ||
| 85 | * | ||
| 86 | * @reset_work: worker which will be called in case of a mouse report | ||
| 87 | * @hdev: pointer to the struct hid_device | ||
| 88 | */ | ||
| 89 | struct rmi_data { | ||
| 90 | struct mutex page_mutex; | ||
| 91 | int page; | ||
| 92 | |||
| 93 | wait_queue_head_t wait; | ||
| 94 | |||
| 95 | u8 *writeReport; | ||
| 96 | u8 *readReport; | ||
| 97 | |||
| 98 | int input_report_size; | ||
| 99 | int output_report_size; | ||
| 100 | |||
| 101 | unsigned long flags; | ||
| 102 | |||
| 103 | struct rmi_function f11; | ||
| 104 | struct rmi_function f30; | ||
| 105 | |||
| 106 | unsigned int max_fingers; | ||
| 107 | unsigned int max_x; | ||
| 108 | unsigned int max_y; | ||
| 109 | unsigned int x_size_mm; | ||
| 110 | unsigned int y_size_mm; | ||
| 111 | |||
| 112 | unsigned int gpio_led_count; | ||
| 113 | unsigned int button_count; | ||
| 114 | unsigned long button_mask; | ||
| 115 | unsigned long button_state_mask; | ||
| 116 | |||
| 117 | struct input_dev *input; | ||
| 118 | |||
| 119 | struct work_struct reset_work; | ||
| 120 | struct hid_device *hdev; | ||
| 121 | }; | ||
| 122 | |||
| 123 | #define RMI_PAGE(addr) (((addr) >> 8) & 0xff) | ||
| 124 | |||
| 125 | static int rmi_write_report(struct hid_device *hdev, u8 *report, int len); | ||
| 126 | |||
| 127 | /** | ||
| 128 | * rmi_set_page - Set RMI page | ||
| 129 | * @hdev: The pointer to the hid_device struct | ||
| 130 | * @page: The new page address. | ||
| 131 | * | ||
| 132 | * RMI devices have 16-bit addressing, but some of the physical | ||
| 133 | * implementations (like SMBus) only have 8-bit addressing. So RMI implements | ||
| 134 | * a page address at 0xff of every page so we can reliable page addresses | ||
| 135 | * every 256 registers. | ||
| 136 | * | ||
| 137 | * The page_mutex lock must be held when this function is entered. | ||
| 138 | * | ||
| 139 | * Returns zero on success, non-zero on failure. | ||
| 140 | */ | ||
| 141 | static int rmi_set_page(struct hid_device *hdev, u8 page) | ||
| 142 | { | ||
| 143 | struct rmi_data *data = hid_get_drvdata(hdev); | ||
| 144 | int retval; | ||
| 145 | |||
| 146 | data->writeReport[0] = RMI_WRITE_REPORT_ID; | ||
| 147 | data->writeReport[1] = 1; | ||
| 148 | data->writeReport[2] = 0xFF; | ||
| 149 | data->writeReport[4] = page; | ||
| 150 | |||
| 151 | retval = rmi_write_report(hdev, data->writeReport, | ||
| 152 | data->output_report_size); | ||
| 153 | if (retval != data->output_report_size) { | ||
| 154 | dev_err(&hdev->dev, | ||
| 155 | "%s: set page failed: %d.", __func__, retval); | ||
| 156 | return retval; | ||
| 157 | } | ||
| 158 | |||
| 159 | data->page = page; | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int rmi_set_mode(struct hid_device *hdev, u8 mode) | ||
| 164 | { | ||
| 165 | int ret; | ||
| 166 | u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode}; | ||
| 167 | |||
| 168 | ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, txbuf, | ||
| 169 | sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | ||
| 170 | if (ret < 0) { | ||
| 171 | dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode, | ||
| 172 | ret); | ||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int rmi_write_report(struct hid_device *hdev, u8 *report, int len) | ||
| 180 | { | ||
| 181 | int ret; | ||
| 182 | |||
| 183 | ret = hid_hw_output_report(hdev, (void *)report, len); | ||
| 184 | if (ret < 0) { | ||
| 185 | dev_err(&hdev->dev, "failed to write hid report (%d)\n", ret); | ||
| 186 | return ret; | ||
| 187 | } | ||
| 188 | |||
| 189 | return ret; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int rmi_read_block(struct hid_device *hdev, u16 addr, void *buf, | ||
| 193 | const int len) | ||
| 194 | { | ||
| 195 | struct rmi_data *data = hid_get_drvdata(hdev); | ||
| 196 | int ret; | ||
| 197 | int bytes_read; | ||
| 198 | int bytes_needed; | ||
| 199 | int retries; | ||
| 200 | int read_input_count; | ||
| 201 | |||
| 202 | mutex_lock(&data->page_mutex); | ||
| 203 | |||
| 204 | if (RMI_PAGE(addr) != data->page) { | ||
| 205 | ret = rmi_set_page(hdev, RMI_PAGE(addr)); | ||
| 206 | if (ret < 0) | ||
| 207 | goto exit; | ||
| 208 | } | ||
| 209 | |||
| 210 | for (retries = 5; retries > 0; retries--) { | ||
| 211 | data->writeReport[0] = RMI_READ_ADDR_REPORT_ID; | ||
| 212 | data->writeReport[1] = 0; /* old 1 byte read count */ | ||
| 213 | data->writeReport[2] = addr & 0xFF; | ||
| 214 | data->writeReport[3] = (addr >> 8) & 0xFF; | ||
| 215 | data->writeReport[4] = len & 0xFF; | ||
| 216 | data->writeReport[5] = (len >> 8) & 0xFF; | ||
| 217 | |||
| 218 | set_bit(RMI_READ_REQUEST_PENDING, &data->flags); | ||
| 219 | |||
| 220 | ret = rmi_write_report(hdev, data->writeReport, | ||
| 221 | data->output_report_size); | ||
| 222 | if (ret != data->output_report_size) { | ||
| 223 | clear_bit(RMI_READ_REQUEST_PENDING, &data->flags); | ||
| 224 | dev_err(&hdev->dev, | ||
| 225 | "failed to write request output report (%d)\n", | ||
| 226 | ret); | ||
| 227 | goto exit; | ||
| 228 | } | ||
| 229 | |||
| 230 | bytes_read = 0; | ||
| 231 | bytes_needed = len; | ||
| 232 | while (bytes_read < len) { | ||
| 233 | if (!wait_event_timeout(data->wait, | ||
| 234 | test_bit(RMI_READ_DATA_PENDING, &data->flags), | ||
| 235 | msecs_to_jiffies(1000))) { | ||
| 236 | hid_warn(hdev, "%s: timeout elapsed\n", | ||
| 237 | __func__); | ||
| 238 | ret = -EAGAIN; | ||
| 239 | break; | ||
| 240 | } | ||
| 241 | |||
| 242 | read_input_count = data->readReport[1]; | ||
| 243 | memcpy(buf + bytes_read, &data->readReport[2], | ||
| 244 | read_input_count < bytes_needed ? | ||
| 245 | read_input_count : bytes_needed); | ||
| 246 | |||
| 247 | bytes_read += read_input_count; | ||
| 248 | bytes_needed -= read_input_count; | ||
| 249 | clear_bit(RMI_READ_DATA_PENDING, &data->flags); | ||
| 250 | } | ||
| 251 | |||
| 252 | if (ret >= 0) { | ||
| 253 | ret = 0; | ||
| 254 | break; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | exit: | ||
| 259 | clear_bit(RMI_READ_REQUEST_PENDING, &data->flags); | ||
| 260 | mutex_unlock(&data->page_mutex); | ||
| 261 | return ret; | ||
| 262 | } | ||
| 263 | |||
| 264 | static inline int rmi_read(struct hid_device *hdev, u16 addr, void *buf) | ||
| 265 | { | ||
| 266 | return rmi_read_block(hdev, addr, buf, 1); | ||
| 267 | } | ||
| 268 | |||
| 269 | static void rmi_f11_process_touch(struct rmi_data *hdata, int slot, | ||
| 270 | u8 finger_state, u8 *touch_data) | ||
| 271 | { | ||
| 272 | int x, y, wx, wy; | ||
| 273 | int wide, major, minor; | ||
| 274 | int z; | ||
| 275 | |||
| 276 | input_mt_slot(hdata->input, slot); | ||
| 277 | input_mt_report_slot_state(hdata->input, MT_TOOL_FINGER, | ||
| 278 | finger_state == 0x01); | ||
| 279 | if (finger_state == 0x01) { | ||
| 280 | x = (touch_data[0] << 4) | (touch_data[2] & 0x0F); | ||
| 281 | y = (touch_data[1] << 4) | (touch_data[2] >> 4); | ||
| 282 | wx = touch_data[3] & 0x0F; | ||
| 283 | wy = touch_data[3] >> 4; | ||
| 284 | wide = (wx > wy); | ||
| 285 | major = max(wx, wy); | ||
| 286 | minor = min(wx, wy); | ||
| 287 | z = touch_data[4]; | ||
| 288 | |||
| 289 | /* y is inverted */ | ||
| 290 | y = hdata->max_y - y; | ||
| 291 | |||
| 292 | input_event(hdata->input, EV_ABS, ABS_MT_POSITION_X, x); | ||
| 293 | input_event(hdata->input, EV_ABS, ABS_MT_POSITION_Y, y); | ||
| 294 | input_event(hdata->input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
| 295 | input_event(hdata->input, EV_ABS, ABS_MT_PRESSURE, z); | ||
| 296 | input_event(hdata->input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); | ||
| 297 | input_event(hdata->input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | static void rmi_reset_work(struct work_struct *work) | ||
| 302 | { | ||
| 303 | struct rmi_data *hdata = container_of(work, struct rmi_data, | ||
| 304 | reset_work); | ||
| 305 | |||
| 306 | /* switch the device to RMI if we receive a generic mouse report */ | ||
| 307 | rmi_set_mode(hdata->hdev, RMI_MODE_ATTN_REPORTS); | ||
| 308 | } | ||
| 309 | |||
| 310 | static inline int rmi_schedule_reset(struct hid_device *hdev) | ||
| 311 | { | ||
| 312 | struct rmi_data *hdata = hid_get_drvdata(hdev); | ||
| 313 | return schedule_work(&hdata->reset_work); | ||
| 314 | } | ||
| 315 | |||
| 316 | static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data, | ||
| 317 | int size) | ||
| 318 | { | ||
| 319 | struct rmi_data *hdata = hid_get_drvdata(hdev); | ||
| 320 | int offset; | ||
| 321 | int i; | ||
| 322 | |||
| 323 | if (size < hdata->f11.report_size) | ||
| 324 | return 0; | ||
| 325 | |||
| 326 | if (!(irq & hdata->f11.irq_mask)) | ||
| 327 | return 0; | ||
| 328 | |||
| 329 | offset = (hdata->max_fingers >> 2) + 1; | ||
| 330 | for (i = 0; i < hdata->max_fingers; i++) { | ||
| 331 | int fs_byte_position = i >> 2; | ||
| 332 | int fs_bit_position = (i & 0x3) << 1; | ||
| 333 | int finger_state = (data[fs_byte_position] >> fs_bit_position) & | ||
| 334 | 0x03; | ||
| 335 | |||
| 336 | rmi_f11_process_touch(hdata, i, finger_state, | ||
| 337 | &data[offset + 5 * i]); | ||
| 338 | } | ||
| 339 | input_mt_sync_frame(hdata->input); | ||
| 340 | input_sync(hdata->input); | ||
| 341 | return hdata->f11.report_size; | ||
| 342 | } | ||
| 343 | |||
| 344 | static int rmi_f30_input_event(struct hid_device *hdev, u8 irq, u8 *data, | ||
| 345 | int size) | ||
| 346 | { | ||
| 347 | struct rmi_data *hdata = hid_get_drvdata(hdev); | ||
| 348 | int i; | ||
| 349 | int button = 0; | ||
| 350 | bool value; | ||
| 351 | |||
| 352 | if (!(irq & hdata->f30.irq_mask)) | ||
| 353 | return 0; | ||
| 354 | |||
| 355 | for (i = 0; i < hdata->gpio_led_count; i++) { | ||
| 356 | if (test_bit(i, &hdata->button_mask)) { | ||
| 357 | value = (data[i / 8] >> (i & 0x07)) & BIT(0); | ||
| 358 | if (test_bit(i, &hdata->button_state_mask)) | ||
| 359 | value = !value; | ||
| 360 | input_event(hdata->input, EV_KEY, BTN_LEFT + button++, | ||
| 361 | value); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | return hdata->f30.report_size; | ||
| 365 | } | ||
| 366 | |||
| 367 | static int rmi_input_event(struct hid_device *hdev, u8 *data, int size) | ||
| 368 | { | ||
| 369 | struct rmi_data *hdata = hid_get_drvdata(hdev); | ||
| 370 | unsigned long irq_mask = 0; | ||
| 371 | unsigned index = 2; | ||
| 372 | |||
| 373 | if (!(test_bit(RMI_STARTED, &hdata->flags))) | ||
| 374 | return 0; | ||
| 375 | |||
| 376 | irq_mask |= hdata->f11.irq_mask; | ||
| 377 | irq_mask |= hdata->f30.irq_mask; | ||
| 378 | |||
| 379 | if (data[1] & ~irq_mask) | ||
| 380 | hid_warn(hdev, "unknown intr source:%02lx %s:%d\n", | ||
| 381 | data[1] & ~irq_mask, __FILE__, __LINE__); | ||
| 382 | |||
| 383 | if (hdata->f11.interrupt_base < hdata->f30.interrupt_base) { | ||
| 384 | index += rmi_f11_input_event(hdev, data[1], &data[index], | ||
| 385 | size - index); | ||
| 386 | index += rmi_f30_input_event(hdev, data[1], &data[index], | ||
| 387 | size - index); | ||
| 388 | } else { | ||
| 389 | index += rmi_f30_input_event(hdev, data[1], &data[index], | ||
| 390 | size - index); | ||
| 391 | index += rmi_f11_input_event(hdev, data[1], &data[index], | ||
| 392 | size - index); | ||
| 393 | } | ||
| 394 | |||
| 395 | return 1; | ||
| 396 | } | ||
| 397 | |||
| 398 | static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size) | ||
| 399 | { | ||
| 400 | struct rmi_data *hdata = hid_get_drvdata(hdev); | ||
| 401 | |||
| 402 | if (!test_bit(RMI_READ_REQUEST_PENDING, &hdata->flags)) { | ||
| 403 | hid_err(hdev, "no read request pending\n"); | ||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | memcpy(hdata->readReport, data, size < hdata->input_report_size ? | ||
| 408 | size : hdata->input_report_size); | ||
| 409 | set_bit(RMI_READ_DATA_PENDING, &hdata->flags); | ||
| 410 | wake_up(&hdata->wait); | ||
| 411 | |||
| 412 | return 1; | ||
| 413 | } | ||
| 414 | |||
| 415 | static int rmi_raw_event(struct hid_device *hdev, | ||
| 416 | struct hid_report *report, u8 *data, int size) | ||
| 417 | { | ||
| 418 | switch (data[0]) { | ||
| 419 | case RMI_READ_DATA_REPORT_ID: | ||
| 420 | return rmi_read_data_event(hdev, data, size); | ||
| 421 | case RMI_ATTN_REPORT_ID: | ||
| 422 | return rmi_input_event(hdev, data, size); | ||
| 423 | case RMI_MOUSE_REPORT_ID: | ||
| 424 | rmi_schedule_reset(hdev); | ||
| 425 | break; | ||
| 426 | } | ||
| 427 | |||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | static int rmi_post_reset(struct hid_device *hdev) | ||
| 432 | { | ||
| 433 | return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS); | ||
| 434 | } | ||
| 435 | |||
| 436 | static int rmi_post_resume(struct hid_device *hdev) | ||
| 437 | { | ||
| 438 | return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS); | ||
| 439 | } | ||
| 440 | |||
| 441 | #define RMI4_MAX_PAGE 0xff | ||
| 442 | #define RMI4_PAGE_SIZE 0x0100 | ||
| 443 | |||
| 444 | #define PDT_START_SCAN_LOCATION 0x00e9 | ||
| 445 | #define PDT_END_SCAN_LOCATION 0x0005 | ||
| 446 | #define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff) | ||
| 447 | |||
| 448 | struct pdt_entry { | ||
| 449 | u8 query_base_addr:8; | ||
| 450 | u8 command_base_addr:8; | ||
| 451 | u8 control_base_addr:8; | ||
| 452 | u8 data_base_addr:8; | ||
| 453 | u8 interrupt_source_count:3; | ||
| 454 | u8 bits3and4:2; | ||
| 455 | u8 function_version:2; | ||
| 456 | u8 bit7:1; | ||
| 457 | u8 function_number:8; | ||
| 458 | } __attribute__((__packed__)); | ||
| 459 | |||
| 460 | static inline unsigned long rmi_gen_mask(unsigned irq_base, unsigned irq_count) | ||
| 461 | { | ||
| 462 | return GENMASK(irq_count + irq_base - 1, irq_base); | ||
| 463 | } | ||
| 464 | |||
| 465 | static void rmi_register_function(struct rmi_data *data, | ||
| 466 | struct pdt_entry *pdt_entry, int page, unsigned interrupt_count) | ||
| 467 | { | ||
| 468 | struct rmi_function *f = NULL; | ||
| 469 | u16 page_base = page << 8; | ||
| 470 | |||
| 471 | switch (pdt_entry->function_number) { | ||
| 472 | case 0x11: | ||
| 473 | f = &data->f11; | ||
| 474 | break; | ||
| 475 | case 0x30: | ||
| 476 | f = &data->f30; | ||
| 477 | break; | ||
| 478 | } | ||
| 479 | |||
| 480 | if (f) { | ||
| 481 | f->page = page; | ||
| 482 | f->query_base_addr = page_base | pdt_entry->query_base_addr; | ||
| 483 | f->command_base_addr = page_base | pdt_entry->command_base_addr; | ||
| 484 | f->control_base_addr = page_base | pdt_entry->control_base_addr; | ||
| 485 | f->data_base_addr = page_base | pdt_entry->data_base_addr; | ||
| 486 | f->interrupt_base = interrupt_count; | ||
| 487 | f->interrupt_count = pdt_entry->interrupt_source_count; | ||
| 488 | f->irq_mask = rmi_gen_mask(f->interrupt_base, | ||
| 489 | f->interrupt_count); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | static int rmi_scan_pdt(struct hid_device *hdev) | ||
| 494 | { | ||
| 495 | struct rmi_data *data = hid_get_drvdata(hdev); | ||
| 496 | struct pdt_entry entry; | ||
| 497 | int page; | ||
| 498 | bool page_has_function; | ||
| 499 | int i; | ||
| 500 | int retval; | ||
| 501 | int interrupt = 0; | ||
| 502 | u16 page_start, pdt_start , pdt_end; | ||
| 503 | |||
| 504 | hid_info(hdev, "Scanning PDT...\n"); | ||
| 505 | |||
| 506 | for (page = 0; (page <= RMI4_MAX_PAGE); page++) { | ||
| 507 | page_start = RMI4_PAGE_SIZE * page; | ||
| 508 | pdt_start = page_start + PDT_START_SCAN_LOCATION; | ||
| 509 | pdt_end = page_start + PDT_END_SCAN_LOCATION; | ||
| 510 | |||
| 511 | page_has_function = false; | ||
| 512 | for (i = pdt_start; i >= pdt_end; i -= sizeof(entry)) { | ||
| 513 | retval = rmi_read_block(hdev, i, &entry, sizeof(entry)); | ||
| 514 | if (retval) { | ||
| 515 | hid_err(hdev, | ||
| 516 | "Read of PDT entry at %#06x failed.\n", | ||
| 517 | i); | ||
| 518 | goto error_exit; | ||
| 519 | } | ||
| 520 | |||
| 521 | if (RMI4_END_OF_PDT(entry.function_number)) | ||
| 522 | break; | ||
| 523 | |||
| 524 | page_has_function = true; | ||
| 525 | |||
| 526 | hid_info(hdev, "Found F%02X on page %#04x\n", | ||
| 527 | entry.function_number, page); | ||
| 528 | |||
| 529 | rmi_register_function(data, &entry, page, interrupt); | ||
| 530 | interrupt += entry.interrupt_source_count; | ||
| 531 | } | ||
| 532 | |||
| 533 | if (!page_has_function) | ||
| 534 | break; | ||
| 535 | } | ||
| 536 | |||
| 537 | hid_info(hdev, "%s: Done with PDT scan.\n", __func__); | ||
| 538 | retval = 0; | ||
| 539 | |||
| 540 | error_exit: | ||
| 541 | return retval; | ||
| 542 | } | ||
| 543 | |||
| 544 | static int rmi_populate_f11(struct hid_device *hdev) | ||
| 545 | { | ||
| 546 | struct rmi_data *data = hid_get_drvdata(hdev); | ||
| 547 | u8 buf[20]; | ||
| 548 | int ret; | ||
| 549 | bool has_query9; | ||
| 550 | bool has_query10; | ||
| 551 | bool has_query11; | ||
| 552 | bool has_query12; | ||
| 553 | bool has_physical_props; | ||
| 554 | unsigned x_size, y_size; | ||
| 555 | u16 query12_offset; | ||
| 556 | |||
| 557 | if (!data->f11.query_base_addr) { | ||
| 558 | hid_err(hdev, "No 2D sensor found, giving up.\n"); | ||
| 559 | return -ENODEV; | ||
| 560 | } | ||
| 561 | |||
| 562 | /* query 0 contains some useful information */ | ||
| 563 | ret = rmi_read(hdev, data->f11.query_base_addr, buf); | ||
| 564 | if (ret) { | ||
| 565 | hid_err(hdev, "can not get query 0: %d.\n", ret); | ||
| 566 | return ret; | ||
| 567 | } | ||
| 568 | has_query9 = !!(buf[0] & BIT(3)); | ||
| 569 | has_query11 = !!(buf[0] & BIT(4)); | ||
| 570 | has_query12 = !!(buf[0] & BIT(5)); | ||
| 571 | |||
| 572 | /* query 1 to get the max number of fingers */ | ||
| 573 | ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf); | ||
| 574 | if (ret) { | ||
| 575 | hid_err(hdev, "can not get NumberOfFingers: %d.\n", ret); | ||
| 576 | return ret; | ||
| 577 | } | ||
| 578 | data->max_fingers = (buf[0] & 0x07) + 1; | ||
| 579 | if (data->max_fingers > 5) | ||
| 580 | data->max_fingers = 10; | ||
| 581 | |||
| 582 | data->f11.report_size = data->max_fingers * 5 + | ||
| 583 | DIV_ROUND_UP(data->max_fingers, 4); | ||
| 584 | |||
| 585 | if (!(buf[0] & BIT(4))) { | ||
| 586 | hid_err(hdev, "No absolute events, giving up.\n"); | ||
| 587 | return -ENODEV; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* query 8 to find out if query 10 exists */ | ||
| 591 | ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf); | ||
| 592 | if (ret) { | ||
| 593 | hid_err(hdev, "can not read gesture information: %d.\n", ret); | ||
| 594 | return ret; | ||
| 595 | } | ||
| 596 | has_query10 = !!(buf[0] & BIT(2)); | ||
| 597 | |||
| 598 | /* | ||
| 599 | * At least 8 queries are guaranteed to be present in F11 | ||
| 600 | * +1 for query12. | ||
| 601 | */ | ||
| 602 | query12_offset = 9; | ||
| 603 | |||
| 604 | if (has_query9) | ||
| 605 | ++query12_offset; | ||
| 606 | |||
| 607 | if (has_query10) | ||
| 608 | ++query12_offset; | ||
| 609 | |||
| 610 | if (has_query11) | ||
| 611 | ++query12_offset; | ||
| 612 | |||
| 613 | /* query 12 to know if the physical properties are reported */ | ||
| 614 | if (has_query12) { | ||
| 615 | ret = rmi_read(hdev, data->f11.query_base_addr | ||
| 616 | + query12_offset, buf); | ||
| 617 | if (ret) { | ||
| 618 | hid_err(hdev, "can not get query 12: %d.\n", ret); | ||
| 619 | return ret; | ||
| 620 | } | ||
| 621 | has_physical_props = !!(buf[0] & BIT(5)); | ||
| 622 | |||
| 623 | if (has_physical_props) { | ||
| 624 | ret = rmi_read_block(hdev, | ||
| 625 | data->f11.query_base_addr | ||
| 626 | + query12_offset + 1, buf, 4); | ||
| 627 | if (ret) { | ||
| 628 | hid_err(hdev, "can not read query 15-18: %d.\n", | ||
| 629 | ret); | ||
| 630 | return ret; | ||
| 631 | } | ||
| 632 | |||
| 633 | x_size = buf[0] | (buf[1] << 8); | ||
| 634 | y_size = buf[2] | (buf[3] << 8); | ||
| 635 | |||
| 636 | data->x_size_mm = DIV_ROUND_CLOSEST(x_size, 10); | ||
| 637 | data->y_size_mm = DIV_ROUND_CLOSEST(y_size, 10); | ||
| 638 | |||
| 639 | hid_info(hdev, "%s: size in mm: %d x %d\n", | ||
| 640 | __func__, data->x_size_mm, data->y_size_mm); | ||
| 641 | } | ||
| 642 | } | ||
| 643 | |||
| 644 | /* | ||
| 645 | * retrieve the ctrl registers | ||
| 646 | * the ctrl register has a size of 20 but a fw bug split it into 16 + 4, | ||
| 647 | * and there is no way to know if the first 20 bytes are here or not. | ||
| 648 | * We use only the first 10 bytes, so get only them. | ||
| 649 | */ | ||
| 650 | ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 10); | ||
| 651 | if (ret) { | ||
| 652 | hid_err(hdev, "can not read ctrl block of size 10: %d.\n", ret); | ||
| 653 | return ret; | ||
| 654 | } | ||
| 655 | |||
| 656 | data->max_x = buf[6] | (buf[7] << 8); | ||
| 657 | data->max_y = buf[8] | (buf[9] << 8); | ||
| 658 | |||
| 659 | return 0; | ||
| 660 | } | ||
| 661 | |||
| 662 | static int rmi_populate_f30(struct hid_device *hdev) | ||
| 663 | { | ||
| 664 | struct rmi_data *data = hid_get_drvdata(hdev); | ||
| 665 | u8 buf[20]; | ||
| 666 | int ret; | ||
| 667 | bool has_gpio, has_led; | ||
| 668 | unsigned bytes_per_ctrl; | ||
| 669 | u8 ctrl2_addr; | ||
| 670 | int ctrl2_3_length; | ||
| 671 | int i; | ||
| 672 | |||
| 673 | /* function F30 is for physical buttons */ | ||
| 674 | if (!data->f30.query_base_addr) { | ||
| 675 | hid_err(hdev, "No GPIO/LEDs found, giving up.\n"); | ||
| 676 | return -ENODEV; | ||
| 677 | } | ||
| 678 | |||
| 679 | ret = rmi_read_block(hdev, data->f30.query_base_addr, buf, 2); | ||
| 680 | if (ret) { | ||
| 681 | hid_err(hdev, "can not get F30 query registers: %d.\n", ret); | ||
| 682 | return ret; | ||
| 683 | } | ||
| 684 | |||
| 685 | has_gpio = !!(buf[0] & BIT(3)); | ||
| 686 | has_led = !!(buf[0] & BIT(2)); | ||
| 687 | data->gpio_led_count = buf[1] & 0x1f; | ||
| 688 | |||
| 689 | /* retrieve ctrl 2 & 3 registers */ | ||
| 690 | bytes_per_ctrl = (data->gpio_led_count + 7) / 8; | ||
| 691 | /* Ctrl0 is present only if both has_gpio and has_led are set*/ | ||
| 692 | ctrl2_addr = (has_gpio && has_led) ? bytes_per_ctrl : 0; | ||
| 693 | /* Ctrl1 is always be present */ | ||
| 694 | ctrl2_addr += bytes_per_ctrl; | ||
| 695 | ctrl2_3_length = 2 * bytes_per_ctrl; | ||
| 696 | |||
| 697 | data->f30.report_size = bytes_per_ctrl; | ||
| 698 | |||
| 699 | ret = rmi_read_block(hdev, data->f30.control_base_addr + ctrl2_addr, | ||
| 700 | buf, ctrl2_3_length); | ||
| 701 | if (ret) { | ||
| 702 | hid_err(hdev, "can not read ctrl 2&3 block of size %d: %d.\n", | ||
| 703 | ctrl2_3_length, ret); | ||
| 704 | return ret; | ||
| 705 | } | ||
| 706 | |||
| 707 | for (i = 0; i < data->gpio_led_count; i++) { | ||
| 708 | int byte_position = i >> 3; | ||
| 709 | int bit_position = i & 0x07; | ||
| 710 | u8 dir_byte = buf[byte_position]; | ||
| 711 | u8 data_byte = buf[byte_position + bytes_per_ctrl]; | ||
| 712 | bool dir = (dir_byte >> bit_position) & BIT(0); | ||
| 713 | bool dat = (data_byte >> bit_position) & BIT(0); | ||
| 714 | |||
| 715 | if (dir == 0) { | ||
| 716 | /* input mode */ | ||
| 717 | if (dat) { | ||
| 718 | /* actual buttons have pull up resistor */ | ||
| 719 | data->button_count++; | ||
| 720 | set_bit(i, &data->button_mask); | ||
| 721 | set_bit(i, &data->button_state_mask); | ||
| 722 | } | ||
| 723 | } | ||
| 724 | |||
| 725 | } | ||
| 726 | |||
| 727 | return 0; | ||
| 728 | } | ||
| 729 | |||
| 730 | static int rmi_populate(struct hid_device *hdev) | ||
| 731 | { | ||
| 732 | int ret; | ||
| 733 | |||
| 734 | ret = rmi_scan_pdt(hdev); | ||
| 735 | if (ret) { | ||
| 736 | hid_err(hdev, "PDT scan failed with code %d.\n", ret); | ||
| 737 | return ret; | ||
| 738 | } | ||
| 739 | |||
| 740 | ret = rmi_populate_f11(hdev); | ||
| 741 | if (ret) { | ||
| 742 | hid_err(hdev, "Error while initializing F11 (%d).\n", ret); | ||
| 743 | return ret; | ||
| 744 | } | ||
| 745 | |||
| 746 | ret = rmi_populate_f30(hdev); | ||
| 747 | if (ret) | ||
| 748 | hid_warn(hdev, "Error while initializing F30 (%d).\n", ret); | ||
| 749 | |||
| 750 | return 0; | ||
| 751 | } | ||
| 752 | |||
| 753 | static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) | ||
| 754 | { | ||
| 755 | struct rmi_data *data = hid_get_drvdata(hdev); | ||
| 756 | struct input_dev *input = hi->input; | ||
| 757 | int ret; | ||
| 758 | int res_x, res_y, i; | ||
| 759 | |||
| 760 | data->input = input; | ||
| 761 | |||
| 762 | hid_dbg(hdev, "Opening low level driver\n"); | ||
| 763 | ret = hid_hw_open(hdev); | ||
| 764 | if (ret) | ||
| 765 | return; | ||
| 766 | |||
| 767 | /* Allow incoming hid reports */ | ||
| 768 | hid_device_io_start(hdev); | ||
| 769 | |||
| 770 | ret = rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS); | ||
| 771 | if (ret < 0) { | ||
| 772 | dev_err(&hdev->dev, "failed to set rmi mode\n"); | ||
| 773 | goto exit; | ||
| 774 | } | ||
| 775 | |||
| 776 | ret = rmi_set_page(hdev, 0); | ||
| 777 | if (ret < 0) { | ||
| 778 | dev_err(&hdev->dev, "failed to set page select to 0.\n"); | ||
| 779 | goto exit; | ||
| 780 | } | ||
| 781 | |||
| 782 | ret = rmi_populate(hdev); | ||
| 783 | if (ret) | ||
| 784 | goto exit; | ||
| 785 | |||
| 786 | __set_bit(EV_ABS, input->evbit); | ||
| 787 | input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->max_x, 0, 0); | ||
| 788 | input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->max_y, 0, 0); | ||
| 789 | |||
| 790 | if (data->x_size_mm && data->y_size_mm) { | ||
| 791 | res_x = (data->max_x - 1) / data->x_size_mm; | ||
| 792 | res_y = (data->max_y - 1) / data->y_size_mm; | ||
| 793 | |||
| 794 | input_abs_set_res(input, ABS_MT_POSITION_X, res_x); | ||
| 795 | input_abs_set_res(input, ABS_MT_POSITION_Y, res_y); | ||
| 796 | } | ||
| 797 | |||
| 798 | input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); | ||
| 799 | input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0); | ||
| 800 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0); | ||
| 801 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0); | ||
| 802 | |||
| 803 | input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER); | ||
| 804 | |||
| 805 | if (data->button_count) { | ||
| 806 | __set_bit(EV_KEY, input->evbit); | ||
| 807 | for (i = 0; i < data->button_count; i++) | ||
| 808 | __set_bit(BTN_LEFT + i, input->keybit); | ||
| 809 | |||
| 810 | if (data->button_count == 1) | ||
| 811 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | ||
| 812 | } | ||
| 813 | |||
| 814 | set_bit(RMI_STARTED, &data->flags); | ||
| 815 | |||
| 816 | exit: | ||
| 817 | hid_device_io_stop(hdev); | ||
| 818 | hid_hw_close(hdev); | ||
| 819 | } | ||
| 820 | |||
| 821 | static int rmi_input_mapping(struct hid_device *hdev, | ||
| 822 | struct hid_input *hi, struct hid_field *field, | ||
| 823 | struct hid_usage *usage, unsigned long **bit, int *max) | ||
| 824 | { | ||
| 825 | /* we want to make HID ignore the advertised HID collection */ | ||
| 826 | return -1; | ||
| 827 | } | ||
| 828 | |||
| 829 | static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 830 | { | ||
| 831 | struct rmi_data *data = NULL; | ||
| 832 | int ret; | ||
| 833 | size_t alloc_size; | ||
| 834 | |||
| 835 | data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL); | ||
| 836 | if (!data) | ||
| 837 | return -ENOMEM; | ||
| 838 | |||
| 839 | INIT_WORK(&data->reset_work, rmi_reset_work); | ||
| 840 | data->hdev = hdev; | ||
| 841 | |||
| 842 | hid_set_drvdata(hdev, data); | ||
| 843 | |||
| 844 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | ||
| 845 | |||
| 846 | ret = hid_parse(hdev); | ||
| 847 | if (ret) { | ||
| 848 | hid_err(hdev, "parse failed\n"); | ||
| 849 | return ret; | ||
| 850 | } | ||
| 851 | |||
| 852 | data->input_report_size = (hdev->report_enum[HID_INPUT_REPORT] | ||
| 853 | .report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3) | ||
| 854 | + 1 /* report id */; | ||
| 855 | data->output_report_size = (hdev->report_enum[HID_OUTPUT_REPORT] | ||
| 856 | .report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3) | ||
| 857 | + 1 /* report id */; | ||
| 858 | |||
| 859 | alloc_size = data->output_report_size + data->input_report_size; | ||
| 860 | |||
| 861 | data->writeReport = devm_kzalloc(&hdev->dev, alloc_size, GFP_KERNEL); | ||
| 862 | if (!data->writeReport) { | ||
| 863 | ret = -ENOMEM; | ||
| 864 | return ret; | ||
| 865 | } | ||
| 866 | |||
| 867 | data->readReport = data->writeReport + data->output_report_size; | ||
| 868 | |||
| 869 | init_waitqueue_head(&data->wait); | ||
| 870 | |||
| 871 | mutex_init(&data->page_mutex); | ||
| 872 | |||
| 873 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 874 | if (ret) { | ||
| 875 | hid_err(hdev, "hw start failed\n"); | ||
| 876 | return ret; | ||
| 877 | } | ||
| 878 | |||
| 879 | if (!test_bit(RMI_STARTED, &data->flags)) { | ||
| 880 | hid_hw_stop(hdev); | ||
| 881 | return -EIO; | ||
| 882 | } | ||
| 883 | |||
| 884 | return 0; | ||
| 885 | } | ||
| 886 | |||
| 887 | static void rmi_remove(struct hid_device *hdev) | ||
| 888 | { | ||
| 889 | struct rmi_data *hdata = hid_get_drvdata(hdev); | ||
| 890 | |||
| 891 | clear_bit(RMI_STARTED, &hdata->flags); | ||
| 892 | |||
| 893 | hid_hw_stop(hdev); | ||
| 894 | } | ||
| 895 | |||
| 896 | static const struct hid_device_id rmi_id[] = { | ||
| 897 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_RMI, HID_ANY_ID, HID_ANY_ID) }, | ||
| 898 | { } | ||
| 899 | }; | ||
| 900 | MODULE_DEVICE_TABLE(hid, rmi_id); | ||
| 901 | |||
| 902 | static struct hid_driver rmi_driver = { | ||
| 903 | .name = "hid-rmi", | ||
| 904 | .id_table = rmi_id, | ||
| 905 | .probe = rmi_probe, | ||
| 906 | .remove = rmi_remove, | ||
| 907 | .raw_event = rmi_raw_event, | ||
| 908 | .input_mapping = rmi_input_mapping, | ||
| 909 | .input_configured = rmi_input_configured, | ||
| 910 | #ifdef CONFIG_PM | ||
| 911 | .resume = rmi_post_resume, | ||
| 912 | .reset_resume = rmi_post_reset, | ||
| 913 | #endif | ||
| 914 | }; | ||
| 915 | |||
| 916 | module_hid_driver(rmi_driver); | ||
| 917 | |||
| 918 | MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>"); | ||
| 919 | MODULE_DESCRIPTION("RMI HID driver"); | ||
| 920 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c index 37961c7e397d..69cca1476a0c 100644 --- a/drivers/hid/hid-saitek.c +++ b/drivers/hid/hid-saitek.c | |||
| @@ -1,10 +1,17 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * HID driver for Saitek devices, currently only the PS1000 (USB gamepad). | 2 | * HID driver for Saitek devices. |
| 3 | * | ||
| 4 | * PS1000 (USB gamepad): | ||
| 3 | * Fixes the HID report descriptor by removing a non-existent axis and | 5 | * Fixes the HID report descriptor by removing a non-existent axis and |
| 4 | * clearing the constant bit on the input reports for buttons and d-pad. | 6 | * clearing the constant bit on the input reports for buttons and d-pad. |
| 5 | * (This module is based on "hid-ortek".) | 7 | * (This module is based on "hid-ortek".) |
| 6 | * | ||
| 7 | * Copyright (c) 2012 Andreas Hübner | 8 | * Copyright (c) 2012 Andreas Hübner |
| 9 | * | ||
| 10 | * R.A.T.7, M.M.O.7 (USB gaming mice): | ||
| 11 | * Fixes the mode button which cycles through three constantly pressed | ||
| 12 | * buttons. All three press events are mapped to one button and the | ||
| 13 | * missing release event is generated immediately. | ||
| 14 | * | ||
| 8 | */ | 15 | */ |
| 9 | 16 | ||
| 10 | /* | 17 | /* |
| @@ -21,12 +28,57 @@ | |||
| 21 | 28 | ||
| 22 | #include "hid-ids.h" | 29 | #include "hid-ids.h" |
| 23 | 30 | ||
| 31 | #define SAITEK_FIX_PS1000 0x0001 | ||
| 32 | #define SAITEK_RELEASE_MODE_RAT7 0x0002 | ||
| 33 | #define SAITEK_RELEASE_MODE_MMO7 0x0004 | ||
| 34 | |||
| 35 | struct saitek_sc { | ||
| 36 | unsigned long quirks; | ||
| 37 | int mode; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int saitek_probe(struct hid_device *hdev, | ||
| 41 | const struct hid_device_id *id) | ||
| 42 | { | ||
| 43 | unsigned long quirks = id->driver_data; | ||
| 44 | struct saitek_sc *ssc; | ||
| 45 | int ret; | ||
| 46 | |||
| 47 | ssc = devm_kzalloc(&hdev->dev, sizeof(*ssc), GFP_KERNEL); | ||
| 48 | if (ssc == NULL) { | ||
| 49 | hid_err(hdev, "can't alloc saitek descriptor\n"); | ||
| 50 | return -ENOMEM; | ||
| 51 | } | ||
| 52 | |||
| 53 | ssc->quirks = quirks; | ||
| 54 | ssc->mode = -1; | ||
| 55 | |||
| 56 | hid_set_drvdata(hdev, ssc); | ||
| 57 | |||
| 58 | ret = hid_parse(hdev); | ||
| 59 | if (ret) { | ||
| 60 | hid_err(hdev, "parse failed\n"); | ||
| 61 | return ret; | ||
| 62 | } | ||
| 63 | |||
| 64 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 65 | if (ret) { | ||
| 66 | hid_err(hdev, "hw start failed\n"); | ||
| 67 | return ret; | ||
| 68 | } | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 24 | static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 73 | static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 25 | unsigned int *rsize) | 74 | unsigned int *rsize) |
| 26 | { | 75 | { |
| 27 | if (*rsize == 137 && rdesc[20] == 0x09 && rdesc[21] == 0x33 | 76 | struct saitek_sc *ssc = hid_get_drvdata(hdev); |
| 28 | && rdesc[94] == 0x81 && rdesc[95] == 0x03 | 77 | |
| 29 | && rdesc[110] == 0x81 && rdesc[111] == 0x03) { | 78 | if ((ssc->quirks & SAITEK_FIX_PS1000) && *rsize == 137 && |
| 79 | rdesc[20] == 0x09 && rdesc[21] == 0x33 && | ||
| 80 | rdesc[94] == 0x81 && rdesc[95] == 0x03 && | ||
| 81 | rdesc[110] == 0x81 && rdesc[111] == 0x03) { | ||
| 30 | 82 | ||
| 31 | hid_info(hdev, "Fixing up Saitek PS1000 report descriptor\n"); | 83 | hid_info(hdev, "Fixing up Saitek PS1000 report descriptor\n"); |
| 32 | 84 | ||
| @@ -42,8 +94,93 @@ static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 42 | return rdesc; | 94 | return rdesc; |
| 43 | } | 95 | } |
| 44 | 96 | ||
| 97 | static int saitek_raw_event(struct hid_device *hdev, | ||
| 98 | struct hid_report *report, u8 *raw_data, int size) | ||
| 99 | { | ||
| 100 | struct saitek_sc *ssc = hid_get_drvdata(hdev); | ||
| 101 | |||
| 102 | if (ssc->quirks & SAITEK_RELEASE_MODE_RAT7 && size == 7) { | ||
| 103 | /* R.A.T.7 uses bits 13, 14, 15 for the mode */ | ||
| 104 | int mode = -1; | ||
| 105 | if (raw_data[1] & 0x01) | ||
| 106 | mode = 0; | ||
| 107 | else if (raw_data[1] & 0x02) | ||
| 108 | mode = 1; | ||
| 109 | else if (raw_data[1] & 0x04) | ||
| 110 | mode = 2; | ||
| 111 | |||
| 112 | /* clear mode bits */ | ||
| 113 | raw_data[1] &= ~0x07; | ||
| 114 | |||
| 115 | if (mode != ssc->mode) { | ||
| 116 | hid_dbg(hdev, "entered mode %d\n", mode); | ||
| 117 | if (ssc->mode != -1) { | ||
| 118 | /* use bit 13 as the mode button */ | ||
| 119 | raw_data[1] |= 0x04; | ||
| 120 | } | ||
| 121 | ssc->mode = mode; | ||
| 122 | } | ||
| 123 | } else if (ssc->quirks & SAITEK_RELEASE_MODE_MMO7 && size == 8) { | ||
| 124 | |||
| 125 | /* M.M.O.7 uses bits 8, 22, 23 for the mode */ | ||
| 126 | int mode = -1; | ||
| 127 | if (raw_data[1] & 0x80) | ||
| 128 | mode = 0; | ||
| 129 | else if (raw_data[2] & 0x01) | ||
| 130 | mode = 1; | ||
| 131 | else if (raw_data[2] & 0x02) | ||
| 132 | mode = 2; | ||
| 133 | |||
| 134 | /* clear mode bits */ | ||
| 135 | raw_data[1] &= ~0x80; | ||
| 136 | raw_data[2] &= ~0x03; | ||
| 137 | |||
| 138 | if (mode != ssc->mode) { | ||
| 139 | hid_dbg(hdev, "entered mode %d\n", mode); | ||
| 140 | if (ssc->mode != -1) { | ||
| 141 | /* use bit 8 as the mode button, bits 22 | ||
| 142 | * and 23 do not represent buttons | ||
| 143 | * according to the HID report descriptor | ||
| 144 | */ | ||
| 145 | raw_data[1] |= 0x80; | ||
| 146 | } | ||
| 147 | ssc->mode = mode; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int saitek_event(struct hid_device *hdev, struct hid_field *field, | ||
| 155 | struct hid_usage *usage, __s32 value) | ||
| 156 | { | ||
| 157 | struct saitek_sc *ssc = hid_get_drvdata(hdev); | ||
| 158 | struct input_dev *input = field->hidinput->input; | ||
| 159 | |||
| 160 | if (usage->type == EV_KEY && value && | ||
| 161 | (((ssc->quirks & SAITEK_RELEASE_MODE_RAT7) && | ||
| 162 | usage->code - BTN_MOUSE == 10) || | ||
| 163 | ((ssc->quirks & SAITEK_RELEASE_MODE_MMO7) && | ||
| 164 | usage->code - BTN_MOUSE == 15))) { | ||
| 165 | |||
| 166 | input_report_key(input, usage->code, 1); | ||
| 167 | |||
| 168 | /* report missing release event */ | ||
| 169 | input_report_key(input, usage->code, 0); | ||
| 170 | |||
| 171 | return 1; | ||
| 172 | } | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 45 | static const struct hid_device_id saitek_devices[] = { | 177 | static const struct hid_device_id saitek_devices[] = { |
| 46 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000)}, | 178 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000), |
| 179 | .driver_data = SAITEK_FIX_PS1000 }, | ||
| 180 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), | ||
| 181 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, | ||
| 182 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7), | ||
| 183 | .driver_data = SAITEK_RELEASE_MODE_MMO7 }, | ||
| 47 | { } | 184 | { } |
| 48 | }; | 185 | }; |
| 49 | 186 | ||
| @@ -52,7 +189,10 @@ MODULE_DEVICE_TABLE(hid, saitek_devices); | |||
| 52 | static struct hid_driver saitek_driver = { | 189 | static struct hid_driver saitek_driver = { |
| 53 | .name = "saitek", | 190 | .name = "saitek", |
| 54 | .id_table = saitek_devices, | 191 | .id_table = saitek_devices, |
| 55 | .report_fixup = saitek_report_fixup | 192 | .probe = saitek_probe, |
| 193 | .report_fixup = saitek_report_fixup, | ||
| 194 | .raw_event = saitek_raw_event, | ||
| 195 | .event = saitek_event, | ||
| 56 | }; | 196 | }; |
| 57 | module_hid_driver(saitek_driver); | 197 | module_hid_driver(saitek_driver); |
| 58 | 198 | ||
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index be14b5690e94..a8d5c8faf8cf 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
| @@ -705,8 +705,17 @@ static const struct hid_device_id sensor_hub_devices[] = { | |||
| 705 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, | 705 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, |
| 706 | USB_DEVICE_ID_INTEL_HID_SENSOR_1), | 706 | USB_DEVICE_ID_INTEL_HID_SENSOR_1), |
| 707 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | 707 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, |
| 708 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT, | ||
| 709 | USB_DEVICE_ID_MS_SURFACE_PRO_2), | ||
| 710 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | ||
| 711 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT, | ||
| 712 | USB_DEVICE_ID_MS_TOUCH_COVER_2), | ||
| 713 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | ||
| 714 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT, | ||
| 715 | USB_DEVICE_ID_MS_TYPE_COVER_2), | ||
| 716 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | ||
| 708 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, | 717 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, |
| 709 | USB_DEVICE_ID_STM_HID_SENSOR), | 718 | USB_DEVICE_ID_STM_HID_SENSOR_1), |
| 710 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, | 719 | .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, |
| 711 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS, | 720 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS, |
| 712 | USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA), | 721 | USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA), |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 908de2789219..2259eaa8b988 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/power_supply.h> | 33 | #include <linux/power_supply.h> |
| 34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
| 35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
| 36 | #include <linux/idr.h> | ||
| 36 | #include <linux/input/mt.h> | 37 | #include <linux/input/mt.h> |
| 37 | 38 | ||
| 38 | #include "hid-ids.h" | 39 | #include "hid-ids.h" |
| @@ -717,8 +718,39 @@ static enum power_supply_property sony_battery_props[] = { | |||
| 717 | POWER_SUPPLY_PROP_STATUS, | 718 | POWER_SUPPLY_PROP_STATUS, |
| 718 | }; | 719 | }; |
| 719 | 720 | ||
| 721 | struct sixaxis_led { | ||
| 722 | __u8 time_enabled; /* the total time the led is active (0xff means forever) */ | ||
| 723 | __u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */ | ||
| 724 | __u8 enabled; | ||
| 725 | __u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ | ||
| 726 | __u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ | ||
| 727 | } __packed; | ||
| 728 | |||
| 729 | struct sixaxis_rumble { | ||
| 730 | __u8 padding; | ||
| 731 | __u8 right_duration; /* Right motor duration (0xff means forever) */ | ||
| 732 | __u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */ | ||
| 733 | __u8 left_duration; /* Left motor duration (0xff means forever) */ | ||
| 734 | __u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ | ||
| 735 | } __packed; | ||
| 736 | |||
| 737 | struct sixaxis_output_report { | ||
| 738 | __u8 report_id; | ||
| 739 | struct sixaxis_rumble rumble; | ||
| 740 | __u8 padding[4]; | ||
| 741 | __u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ | ||
| 742 | struct sixaxis_led led[4]; /* LEDx at (4 - x) */ | ||
| 743 | struct sixaxis_led _reserved; /* LED5, not actually soldered */ | ||
| 744 | } __packed; | ||
| 745 | |||
| 746 | union sixaxis_output_report_01 { | ||
| 747 | struct sixaxis_output_report data; | ||
| 748 | __u8 buf[36]; | ||
| 749 | }; | ||
| 750 | |||
| 720 | static spinlock_t sony_dev_list_lock; | 751 | static spinlock_t sony_dev_list_lock; |
| 721 | static LIST_HEAD(sony_device_list); | 752 | static LIST_HEAD(sony_device_list); |
| 753 | static DEFINE_IDA(sony_device_id_allocator); | ||
| 722 | 754 | ||
| 723 | struct sony_sc { | 755 | struct sony_sc { |
| 724 | spinlock_t lock; | 756 | spinlock_t lock; |
| @@ -728,6 +760,7 @@ struct sony_sc { | |||
| 728 | unsigned long quirks; | 760 | unsigned long quirks; |
| 729 | struct work_struct state_worker; | 761 | struct work_struct state_worker; |
| 730 | struct power_supply battery; | 762 | struct power_supply battery; |
| 763 | int device_id; | ||
| 731 | 764 | ||
| 732 | #ifdef CONFIG_SONY_FF | 765 | #ifdef CONFIG_SONY_FF |
| 733 | __u8 left; | 766 | __u8 left; |
| @@ -740,6 +773,8 @@ struct sony_sc { | |||
| 740 | __u8 battery_charging; | 773 | __u8 battery_charging; |
| 741 | __u8 battery_capacity; | 774 | __u8 battery_capacity; |
| 742 | __u8 led_state[MAX_LEDS]; | 775 | __u8 led_state[MAX_LEDS]; |
| 776 | __u8 led_delay_on[MAX_LEDS]; | ||
| 777 | __u8 led_delay_off[MAX_LEDS]; | ||
| 743 | __u8 led_count; | 778 | __u8 led_count; |
| 744 | }; | 779 | }; |
| 745 | 780 | ||
| @@ -1048,6 +1083,52 @@ static int dualshock4_set_operational_bt(struct hid_device *hdev) | |||
| 1048 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1083 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
| 1049 | } | 1084 | } |
| 1050 | 1085 | ||
| 1086 | static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) | ||
| 1087 | { | ||
| 1088 | static const __u8 sixaxis_leds[10][4] = { | ||
| 1089 | { 0x01, 0x00, 0x00, 0x00 }, | ||
| 1090 | { 0x00, 0x01, 0x00, 0x00 }, | ||
| 1091 | { 0x00, 0x00, 0x01, 0x00 }, | ||
| 1092 | { 0x00, 0x00, 0x00, 0x01 }, | ||
| 1093 | { 0x01, 0x00, 0x00, 0x01 }, | ||
| 1094 | { 0x00, 0x01, 0x00, 0x01 }, | ||
| 1095 | { 0x00, 0x00, 0x01, 0x01 }, | ||
| 1096 | { 0x01, 0x00, 0x01, 0x01 }, | ||
| 1097 | { 0x00, 0x01, 0x01, 0x01 }, | ||
| 1098 | { 0x01, 0x01, 0x01, 0x01 } | ||
| 1099 | }; | ||
| 1100 | |||
| 1101 | BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); | ||
| 1102 | |||
| 1103 | if (id < 0) | ||
| 1104 | return; | ||
| 1105 | |||
| 1106 | id %= 10; | ||
| 1107 | memcpy(values, sixaxis_leds[id], sizeof(sixaxis_leds[id])); | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | static void dualshock4_set_leds_from_id(int id, __u8 values[MAX_LEDS]) | ||
| 1111 | { | ||
| 1112 | /* The first 4 color/index entries match what the PS4 assigns */ | ||
| 1113 | static const __u8 color_code[7][3] = { | ||
| 1114 | /* Blue */ { 0x00, 0x00, 0x01 }, | ||
| 1115 | /* Red */ { 0x01, 0x00, 0x00 }, | ||
| 1116 | /* Green */ { 0x00, 0x01, 0x00 }, | ||
| 1117 | /* Pink */ { 0x02, 0x00, 0x01 }, | ||
| 1118 | /* Orange */ { 0x02, 0x01, 0x00 }, | ||
| 1119 | /* Teal */ { 0x00, 0x01, 0x01 }, | ||
| 1120 | /* White */ { 0x01, 0x01, 0x01 } | ||
| 1121 | }; | ||
| 1122 | |||
| 1123 | BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); | ||
| 1124 | |||
| 1125 | if (id < 0) | ||
| 1126 | return; | ||
| 1127 | |||
| 1128 | id %= 7; | ||
| 1129 | memcpy(values, color_code[id], sizeof(color_code[id])); | ||
| 1130 | } | ||
| 1131 | |||
| 1051 | static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds) | 1132 | static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds) |
| 1052 | { | 1133 | { |
| 1053 | struct list_head *report_list = | 1134 | struct list_head *report_list = |
| @@ -1066,19 +1147,18 @@ static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds) | |||
| 1066 | hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | 1147 | hid_hw_request(hdev, report, HID_REQ_SET_REPORT); |
| 1067 | } | 1148 | } |
| 1068 | 1149 | ||
| 1069 | static void sony_set_leds(struct hid_device *hdev, const __u8 *leds, int count) | 1150 | static void sony_set_leds(struct sony_sc *sc, const __u8 *leds, int count) |
| 1070 | { | 1151 | { |
| 1071 | struct sony_sc *drv_data = hid_get_drvdata(hdev); | ||
| 1072 | int n; | 1152 | int n; |
| 1073 | 1153 | ||
| 1074 | BUG_ON(count > MAX_LEDS); | 1154 | BUG_ON(count > MAX_LEDS); |
| 1075 | 1155 | ||
| 1076 | if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) { | 1156 | if (sc->quirks & BUZZ_CONTROLLER && count == 4) { |
| 1077 | buzz_set_leds(hdev, leds); | 1157 | buzz_set_leds(sc->hdev, leds); |
| 1078 | } else { | 1158 | } else { |
| 1079 | for (n = 0; n < count; n++) | 1159 | for (n = 0; n < count; n++) |
| 1080 | drv_data->led_state[n] = leds[n]; | 1160 | sc->led_state[n] = leds[n]; |
| 1081 | schedule_work(&drv_data->state_worker); | 1161 | schedule_work(&sc->state_worker); |
| 1082 | } | 1162 | } |
| 1083 | } | 1163 | } |
| 1084 | 1164 | ||
| @@ -1090,6 +1170,7 @@ static void sony_led_set_brightness(struct led_classdev *led, | |||
| 1090 | struct sony_sc *drv_data; | 1170 | struct sony_sc *drv_data; |
| 1091 | 1171 | ||
| 1092 | int n; | 1172 | int n; |
| 1173 | int force_update; | ||
| 1093 | 1174 | ||
| 1094 | drv_data = hid_get_drvdata(hdev); | 1175 | drv_data = hid_get_drvdata(hdev); |
| 1095 | if (!drv_data) { | 1176 | if (!drv_data) { |
| @@ -1097,12 +1178,29 @@ static void sony_led_set_brightness(struct led_classdev *led, | |||
| 1097 | return; | 1178 | return; |
| 1098 | } | 1179 | } |
| 1099 | 1180 | ||
| 1181 | /* | ||
| 1182 | * The Sixaxis on USB will override any LED settings sent to it | ||
| 1183 | * and keep flashing all of the LEDs until the PS button is pressed. | ||
| 1184 | * Updates, even if redundant, must be always be sent to the | ||
| 1185 | * controller to avoid having to toggle the state of an LED just to | ||
| 1186 | * stop the flashing later on. | ||
| 1187 | */ | ||
| 1188 | force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB); | ||
| 1189 | |||
| 1100 | for (n = 0; n < drv_data->led_count; n++) { | 1190 | for (n = 0; n < drv_data->led_count; n++) { |
| 1101 | if (led == drv_data->leds[n]) { | 1191 | if (led == drv_data->leds[n] && (force_update || |
| 1102 | if (value != drv_data->led_state[n]) { | 1192 | (value != drv_data->led_state[n] || |
| 1103 | drv_data->led_state[n] = value; | 1193 | drv_data->led_delay_on[n] || |
| 1104 | sony_set_leds(hdev, drv_data->led_state, drv_data->led_count); | 1194 | drv_data->led_delay_off[n]))) { |
| 1105 | } | 1195 | |
| 1196 | drv_data->led_state[n] = value; | ||
| 1197 | |||
| 1198 | /* Setting the brightness stops the blinking */ | ||
| 1199 | drv_data->led_delay_on[n] = 0; | ||
| 1200 | drv_data->led_delay_off[n] = 0; | ||
| 1201 | |||
| 1202 | sony_set_leds(drv_data, drv_data->led_state, | ||
| 1203 | drv_data->led_count); | ||
| 1106 | break; | 1204 | break; |
| 1107 | } | 1205 | } |
| 1108 | } | 1206 | } |
| @@ -1130,63 +1228,112 @@ static enum led_brightness sony_led_get_brightness(struct led_classdev *led) | |||
| 1130 | return LED_OFF; | 1228 | return LED_OFF; |
| 1131 | } | 1229 | } |
| 1132 | 1230 | ||
| 1133 | static void sony_leds_remove(struct hid_device *hdev) | 1231 | static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, |
| 1232 | unsigned long *delay_off) | ||
| 1134 | { | 1233 | { |
| 1135 | struct sony_sc *drv_data; | 1234 | struct device *dev = led->dev->parent; |
| 1136 | struct led_classdev *led; | 1235 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
| 1236 | struct sony_sc *drv_data = hid_get_drvdata(hdev); | ||
| 1137 | int n; | 1237 | int n; |
| 1238 | __u8 new_on, new_off; | ||
| 1138 | 1239 | ||
| 1139 | drv_data = hid_get_drvdata(hdev); | 1240 | if (!drv_data) { |
| 1140 | BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); | 1241 | hid_err(hdev, "No device data\n"); |
| 1242 | return -EINVAL; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | /* Max delay is 255 deciseconds or 2550 milliseconds */ | ||
| 1246 | if (*delay_on > 2550) | ||
| 1247 | *delay_on = 2550; | ||
| 1248 | if (*delay_off > 2550) | ||
| 1249 | *delay_off = 2550; | ||
| 1250 | |||
| 1251 | /* Blink at 1 Hz if both values are zero */ | ||
| 1252 | if (!*delay_on && !*delay_off) | ||
| 1253 | *delay_on = *delay_off = 500; | ||
| 1254 | |||
| 1255 | new_on = *delay_on / 10; | ||
| 1256 | new_off = *delay_off / 10; | ||
| 1141 | 1257 | ||
| 1142 | for (n = 0; n < drv_data->led_count; n++) { | 1258 | for (n = 0; n < drv_data->led_count; n++) { |
| 1143 | led = drv_data->leds[n]; | 1259 | if (led == drv_data->leds[n]) |
| 1144 | drv_data->leds[n] = NULL; | 1260 | break; |
| 1261 | } | ||
| 1262 | |||
| 1263 | /* This LED is not registered on this device */ | ||
| 1264 | if (n >= drv_data->led_count) | ||
| 1265 | return -EINVAL; | ||
| 1266 | |||
| 1267 | /* Don't schedule work if the values didn't change */ | ||
| 1268 | if (new_on != drv_data->led_delay_on[n] || | ||
| 1269 | new_off != drv_data->led_delay_off[n]) { | ||
| 1270 | drv_data->led_delay_on[n] = new_on; | ||
| 1271 | drv_data->led_delay_off[n] = new_off; | ||
| 1272 | schedule_work(&drv_data->state_worker); | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | return 0; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | static void sony_leds_remove(struct sony_sc *sc) | ||
| 1279 | { | ||
| 1280 | struct led_classdev *led; | ||
| 1281 | int n; | ||
| 1282 | |||
| 1283 | BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); | ||
| 1284 | |||
| 1285 | for (n = 0; n < sc->led_count; n++) { | ||
| 1286 | led = sc->leds[n]; | ||
| 1287 | sc->leds[n] = NULL; | ||
| 1145 | if (!led) | 1288 | if (!led) |
| 1146 | continue; | 1289 | continue; |
| 1147 | led_classdev_unregister(led); | 1290 | led_classdev_unregister(led); |
| 1148 | kfree(led); | 1291 | kfree(led); |
| 1149 | } | 1292 | } |
| 1150 | 1293 | ||
| 1151 | drv_data->led_count = 0; | 1294 | sc->led_count = 0; |
| 1152 | } | 1295 | } |
| 1153 | 1296 | ||
| 1154 | static int sony_leds_init(struct hid_device *hdev) | 1297 | static int sony_leds_init(struct sony_sc *sc) |
| 1155 | { | 1298 | { |
| 1156 | struct sony_sc *drv_data; | 1299 | struct hid_device *hdev = sc->hdev; |
| 1157 | int n, ret = 0; | 1300 | int n, ret = 0; |
| 1158 | int max_brightness; | 1301 | int use_ds4_names; |
| 1159 | int use_colors; | ||
| 1160 | struct led_classdev *led; | 1302 | struct led_classdev *led; |
| 1161 | size_t name_sz; | 1303 | size_t name_sz; |
| 1162 | char *name; | 1304 | char *name; |
| 1163 | size_t name_len; | 1305 | size_t name_len; |
| 1164 | const char *name_fmt; | 1306 | const char *name_fmt; |
| 1165 | static const char * const color_str[] = { "red", "green", "blue" }; | 1307 | static const char * const ds4_name_str[] = { "red", "green", "blue", |
| 1166 | static const __u8 initial_values[MAX_LEDS] = { 0x00, 0x00, 0x00, 0x00 }; | 1308 | "global" }; |
| 1309 | __u8 initial_values[MAX_LEDS] = { 0 }; | ||
| 1310 | __u8 max_brightness[MAX_LEDS] = { 1 }; | ||
| 1311 | __u8 use_hw_blink[MAX_LEDS] = { 0 }; | ||
| 1167 | 1312 | ||
| 1168 | drv_data = hid_get_drvdata(hdev); | 1313 | BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); |
| 1169 | BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT)); | ||
| 1170 | 1314 | ||
| 1171 | if (drv_data->quirks & BUZZ_CONTROLLER) { | 1315 | if (sc->quirks & BUZZ_CONTROLLER) { |
| 1172 | drv_data->led_count = 4; | 1316 | sc->led_count = 4; |
| 1173 | max_brightness = 1; | 1317 | use_ds4_names = 0; |
| 1174 | use_colors = 0; | ||
| 1175 | name_len = strlen("::buzz#"); | 1318 | name_len = strlen("::buzz#"); |
| 1176 | name_fmt = "%s::buzz%d"; | 1319 | name_fmt = "%s::buzz%d"; |
| 1177 | /* Validate expected report characteristics. */ | 1320 | /* Validate expected report characteristics. */ |
| 1178 | if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) | 1321 | if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) |
| 1179 | return -ENODEV; | 1322 | return -ENODEV; |
| 1180 | } else if (drv_data->quirks & DUALSHOCK4_CONTROLLER) { | 1323 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
| 1181 | drv_data->led_count = 3; | 1324 | dualshock4_set_leds_from_id(sc->device_id, initial_values); |
| 1182 | max_brightness = 255; | 1325 | initial_values[3] = 1; |
| 1183 | use_colors = 1; | 1326 | sc->led_count = 4; |
| 1327 | memset(max_brightness, 255, 3); | ||
| 1328 | use_hw_blink[3] = 1; | ||
| 1329 | use_ds4_names = 1; | ||
| 1184 | name_len = 0; | 1330 | name_len = 0; |
| 1185 | name_fmt = "%s:%s"; | 1331 | name_fmt = "%s:%s"; |
| 1186 | } else { | 1332 | } else { |
| 1187 | drv_data->led_count = 4; | 1333 | sixaxis_set_leds_from_id(sc->device_id, initial_values); |
| 1188 | max_brightness = 1; | 1334 | sc->led_count = 4; |
| 1189 | use_colors = 0; | 1335 | memset(use_hw_blink, 1, 4); |
| 1336 | use_ds4_names = 0; | ||
| 1190 | name_len = strlen("::sony#"); | 1337 | name_len = strlen("::sony#"); |
| 1191 | name_fmt = "%s::sony%d"; | 1338 | name_fmt = "%s::sony%d"; |
| 1192 | } | 1339 | } |
| @@ -1196,14 +1343,14 @@ static int sony_leds_init(struct hid_device *hdev) | |||
| 1196 | * only relevant if the driver is loaded after somebody actively set the | 1343 | * only relevant if the driver is loaded after somebody actively set the |
| 1197 | * LEDs to on | 1344 | * LEDs to on |
| 1198 | */ | 1345 | */ |
| 1199 | sony_set_leds(hdev, initial_values, drv_data->led_count); | 1346 | sony_set_leds(sc, initial_values, sc->led_count); |
| 1200 | 1347 | ||
| 1201 | name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; | 1348 | name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; |
| 1202 | 1349 | ||
| 1203 | for (n = 0; n < drv_data->led_count; n++) { | 1350 | for (n = 0; n < sc->led_count; n++) { |
| 1204 | 1351 | ||
| 1205 | if (use_colors) | 1352 | if (use_ds4_names) |
| 1206 | name_sz = strlen(dev_name(&hdev->dev)) + strlen(color_str[n]) + 2; | 1353 | name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2; |
| 1207 | 1354 | ||
| 1208 | led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); | 1355 | led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); |
| 1209 | if (!led) { | 1356 | if (!led) { |
| @@ -1213,30 +1360,35 @@ static int sony_leds_init(struct hid_device *hdev) | |||
| 1213 | } | 1360 | } |
| 1214 | 1361 | ||
| 1215 | name = (void *)(&led[1]); | 1362 | name = (void *)(&led[1]); |
| 1216 | if (use_colors) | 1363 | if (use_ds4_names) |
| 1217 | snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), color_str[n]); | 1364 | snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), |
| 1365 | ds4_name_str[n]); | ||
| 1218 | else | 1366 | else |
| 1219 | snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); | 1367 | snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); |
| 1220 | led->name = name; | 1368 | led->name = name; |
| 1221 | led->brightness = 0; | 1369 | led->brightness = initial_values[n]; |
| 1222 | led->max_brightness = max_brightness; | 1370 | led->max_brightness = max_brightness[n]; |
| 1223 | led->brightness_get = sony_led_get_brightness; | 1371 | led->brightness_get = sony_led_get_brightness; |
| 1224 | led->brightness_set = sony_led_set_brightness; | 1372 | led->brightness_set = sony_led_set_brightness; |
| 1225 | 1373 | ||
| 1374 | if (use_hw_blink[n]) | ||
| 1375 | led->blink_set = sony_led_blink_set; | ||
| 1376 | |||
| 1377 | sc->leds[n] = led; | ||
| 1378 | |||
| 1226 | ret = led_classdev_register(&hdev->dev, led); | 1379 | ret = led_classdev_register(&hdev->dev, led); |
| 1227 | if (ret) { | 1380 | if (ret) { |
| 1228 | hid_err(hdev, "Failed to register LED %d\n", n); | 1381 | hid_err(hdev, "Failed to register LED %d\n", n); |
| 1382 | sc->leds[n] = NULL; | ||
| 1229 | kfree(led); | 1383 | kfree(led); |
| 1230 | goto error_leds; | 1384 | goto error_leds; |
| 1231 | } | 1385 | } |
| 1232 | |||
| 1233 | drv_data->leds[n] = led; | ||
| 1234 | } | 1386 | } |
| 1235 | 1387 | ||
| 1236 | return ret; | 1388 | return ret; |
| 1237 | 1389 | ||
| 1238 | error_leds: | 1390 | error_leds: |
| 1239 | sony_leds_remove(hdev); | 1391 | sony_leds_remove(sc); |
| 1240 | 1392 | ||
| 1241 | return ret; | 1393 | return ret; |
| 1242 | } | 1394 | } |
| @@ -1244,29 +1396,52 @@ error_leds: | |||
| 1244 | static void sixaxis_state_worker(struct work_struct *work) | 1396 | static void sixaxis_state_worker(struct work_struct *work) |
| 1245 | { | 1397 | { |
| 1246 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | 1398 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); |
| 1247 | unsigned char buf[] = { | 1399 | int n; |
| 1248 | 0x01, | 1400 | union sixaxis_output_report_01 report = { |
| 1249 | 0x00, 0xff, 0x00, 0xff, 0x00, | 1401 | .buf = { |
| 1250 | 0x00, 0x00, 0x00, 0x00, 0x00, | 1402 | 0x01, |
| 1251 | 0xff, 0x27, 0x10, 0x00, 0x32, | 1403 | 0x00, 0xff, 0x00, 0xff, 0x00, |
| 1252 | 0xff, 0x27, 0x10, 0x00, 0x32, | 1404 | 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1253 | 0xff, 0x27, 0x10, 0x00, 0x32, | 1405 | 0xff, 0x27, 0x10, 0x00, 0x32, |
| 1254 | 0xff, 0x27, 0x10, 0x00, 0x32, | 1406 | 0xff, 0x27, 0x10, 0x00, 0x32, |
| 1255 | 0x00, 0x00, 0x00, 0x00, 0x00 | 1407 | 0xff, 0x27, 0x10, 0x00, 0x32, |
| 1408 | 0xff, 0x27, 0x10, 0x00, 0x32, | ||
| 1409 | 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 1410 | } | ||
| 1256 | }; | 1411 | }; |
| 1257 | 1412 | ||
| 1258 | #ifdef CONFIG_SONY_FF | 1413 | #ifdef CONFIG_SONY_FF |
| 1259 | buf[3] = sc->right ? 1 : 0; | 1414 | report.data.rumble.right_motor_on = sc->right ? 1 : 0; |
| 1260 | buf[5] = sc->left; | 1415 | report.data.rumble.left_motor_force = sc->left; |
| 1261 | #endif | 1416 | #endif |
| 1262 | 1417 | ||
| 1263 | buf[10] |= sc->led_state[0] << 1; | 1418 | report.data.leds_bitmap |= sc->led_state[0] << 1; |
| 1264 | buf[10] |= sc->led_state[1] << 2; | 1419 | report.data.leds_bitmap |= sc->led_state[1] << 2; |
| 1265 | buf[10] |= sc->led_state[2] << 3; | 1420 | report.data.leds_bitmap |= sc->led_state[2] << 3; |
| 1266 | buf[10] |= sc->led_state[3] << 4; | 1421 | report.data.leds_bitmap |= sc->led_state[3] << 4; |
| 1422 | |||
| 1423 | /* Set flag for all leds off, required for 3rd party INTEC controller */ | ||
| 1424 | if ((report.data.leds_bitmap & 0x1E) == 0) | ||
| 1425 | report.data.leds_bitmap |= 0x20; | ||
| 1267 | 1426 | ||
| 1268 | hid_hw_raw_request(sc->hdev, 0x01, buf, sizeof(buf), HID_OUTPUT_REPORT, | 1427 | /* |
| 1269 | HID_REQ_SET_REPORT); | 1428 | * The LEDs in the report are indexed in reverse order to their |
| 1429 | * corresponding light on the controller. | ||
| 1430 | * Index 0 = LED 4, index 1 = LED 3, etc... | ||
| 1431 | * | ||
| 1432 | * In the case of both delay values being zero (blinking disabled) the | ||
| 1433 | * default report values should be used or the controller LED will be | ||
| 1434 | * always off. | ||
| 1435 | */ | ||
| 1436 | for (n = 0; n < 4; n++) { | ||
| 1437 | if (sc->led_delay_on[n] || sc->led_delay_off[n]) { | ||
| 1438 | report.data.led[3 - n].duty_off = sc->led_delay_off[n]; | ||
| 1439 | report.data.led[3 - n].duty_on = sc->led_delay_on[n]; | ||
| 1440 | } | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | hid_hw_raw_request(sc->hdev, report.data.report_id, report.buf, | ||
| 1444 | sizeof(report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | ||
| 1270 | } | 1445 | } |
| 1271 | 1446 | ||
| 1272 | static void dualshock4_state_worker(struct work_struct *work) | 1447 | static void dualshock4_state_worker(struct work_struct *work) |
| @@ -1279,7 +1454,7 @@ static void dualshock4_state_worker(struct work_struct *work) | |||
| 1279 | 1454 | ||
| 1280 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 1455 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
| 1281 | buf[0] = 0x05; | 1456 | buf[0] = 0x05; |
| 1282 | buf[1] = 0x03; | 1457 | buf[1] = 0xFF; |
| 1283 | offset = 4; | 1458 | offset = 4; |
| 1284 | } else { | 1459 | } else { |
| 1285 | buf[0] = 0x11; | 1460 | buf[0] = 0x11; |
| @@ -1295,9 +1470,18 @@ static void dualshock4_state_worker(struct work_struct *work) | |||
| 1295 | offset += 2; | 1470 | offset += 2; |
| 1296 | #endif | 1471 | #endif |
| 1297 | 1472 | ||
| 1298 | buf[offset++] = sc->led_state[0]; | 1473 | /* LED 3 is the global control */ |
| 1299 | buf[offset++] = sc->led_state[1]; | 1474 | if (sc->led_state[3]) { |
| 1300 | buf[offset++] = sc->led_state[2]; | 1475 | buf[offset++] = sc->led_state[0]; |
| 1476 | buf[offset++] = sc->led_state[1]; | ||
| 1477 | buf[offset++] = sc->led_state[2]; | ||
| 1478 | } else { | ||
| 1479 | offset += 3; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | /* If both delay values are zero the DualShock 4 disables blinking. */ | ||
| 1483 | buf[offset++] = sc->led_delay_on[3]; | ||
| 1484 | buf[offset++] = sc->led_delay_off[3]; | ||
| 1301 | 1485 | ||
| 1302 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | 1486 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) |
| 1303 | hid_hw_output_report(hdev, buf, 32); | 1487 | hid_hw_output_report(hdev, buf, 32); |
| @@ -1323,9 +1507,9 @@ static int sony_play_effect(struct input_dev *dev, void *data, | |||
| 1323 | return 0; | 1507 | return 0; |
| 1324 | } | 1508 | } |
| 1325 | 1509 | ||
| 1326 | static int sony_init_ff(struct hid_device *hdev) | 1510 | static int sony_init_ff(struct sony_sc *sc) |
| 1327 | { | 1511 | { |
| 1328 | struct hid_input *hidinput = list_entry(hdev->inputs.next, | 1512 | struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, |
| 1329 | struct hid_input, list); | 1513 | struct hid_input, list); |
| 1330 | struct input_dev *input_dev = hidinput->input; | 1514 | struct input_dev *input_dev = hidinput->input; |
| 1331 | 1515 | ||
| @@ -1334,7 +1518,7 @@ static int sony_init_ff(struct hid_device *hdev) | |||
| 1334 | } | 1518 | } |
| 1335 | 1519 | ||
| 1336 | #else | 1520 | #else |
| 1337 | static int sony_init_ff(struct hid_device *hdev) | 1521 | static int sony_init_ff(struct sony_sc *sc) |
| 1338 | { | 1522 | { |
| 1339 | return 0; | 1523 | return 0; |
| 1340 | } | 1524 | } |
| @@ -1384,8 +1568,6 @@ static int sony_battery_get_property(struct power_supply *psy, | |||
| 1384 | 1568 | ||
| 1385 | static int sony_battery_probe(struct sony_sc *sc) | 1569 | static int sony_battery_probe(struct sony_sc *sc) |
| 1386 | { | 1570 | { |
| 1387 | static atomic_t power_id_seq = ATOMIC_INIT(0); | ||
| 1388 | unsigned long power_id; | ||
| 1389 | struct hid_device *hdev = sc->hdev; | 1571 | struct hid_device *hdev = sc->hdev; |
| 1390 | int ret; | 1572 | int ret; |
| 1391 | 1573 | ||
| @@ -1395,15 +1577,13 @@ static int sony_battery_probe(struct sony_sc *sc) | |||
| 1395 | */ | 1577 | */ |
| 1396 | sc->battery_capacity = 100; | 1578 | sc->battery_capacity = 100; |
| 1397 | 1579 | ||
| 1398 | power_id = (unsigned long)atomic_inc_return(&power_id_seq); | ||
| 1399 | |||
| 1400 | sc->battery.properties = sony_battery_props; | 1580 | sc->battery.properties = sony_battery_props; |
| 1401 | sc->battery.num_properties = ARRAY_SIZE(sony_battery_props); | 1581 | sc->battery.num_properties = ARRAY_SIZE(sony_battery_props); |
| 1402 | sc->battery.get_property = sony_battery_get_property; | 1582 | sc->battery.get_property = sony_battery_get_property; |
| 1403 | sc->battery.type = POWER_SUPPLY_TYPE_BATTERY; | 1583 | sc->battery.type = POWER_SUPPLY_TYPE_BATTERY; |
| 1404 | sc->battery.use_for_apm = 0; | 1584 | sc->battery.use_for_apm = 0; |
| 1405 | sc->battery.name = kasprintf(GFP_KERNEL, "sony_controller_battery_%lu", | 1585 | sc->battery.name = kasprintf(GFP_KERNEL, "sony_controller_battery_%pMR", |
| 1406 | power_id); | 1586 | sc->mac_address); |
| 1407 | if (!sc->battery.name) | 1587 | if (!sc->battery.name) |
| 1408 | return -ENOMEM; | 1588 | return -ENOMEM; |
| 1409 | 1589 | ||
| @@ -1578,6 +1758,52 @@ static int sony_check_add(struct sony_sc *sc) | |||
| 1578 | return sony_check_add_dev_list(sc); | 1758 | return sony_check_add_dev_list(sc); |
| 1579 | } | 1759 | } |
| 1580 | 1760 | ||
| 1761 | static int sony_set_device_id(struct sony_sc *sc) | ||
| 1762 | { | ||
| 1763 | int ret; | ||
| 1764 | |||
| 1765 | /* | ||
| 1766 | * Only DualShock 4 or Sixaxis controllers get an id. | ||
| 1767 | * All others are set to -1. | ||
| 1768 | */ | ||
| 1769 | if ((sc->quirks & SIXAXIS_CONTROLLER) || | ||
| 1770 | (sc->quirks & DUALSHOCK4_CONTROLLER)) { | ||
| 1771 | ret = ida_simple_get(&sony_device_id_allocator, 0, 0, | ||
| 1772 | GFP_KERNEL); | ||
| 1773 | if (ret < 0) { | ||
| 1774 | sc->device_id = -1; | ||
| 1775 | return ret; | ||
| 1776 | } | ||
| 1777 | sc->device_id = ret; | ||
| 1778 | } else { | ||
| 1779 | sc->device_id = -1; | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | return 0; | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | static void sony_release_device_id(struct sony_sc *sc) | ||
| 1786 | { | ||
| 1787 | if (sc->device_id >= 0) { | ||
| 1788 | ida_simple_remove(&sony_device_id_allocator, sc->device_id); | ||
| 1789 | sc->device_id = -1; | ||
| 1790 | } | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | static inline void sony_init_work(struct sony_sc *sc, | ||
| 1794 | void (*worker)(struct work_struct *)) | ||
| 1795 | { | ||
| 1796 | if (!sc->worker_initialized) | ||
| 1797 | INIT_WORK(&sc->state_worker, worker); | ||
| 1798 | |||
| 1799 | sc->worker_initialized = 1; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | static inline void sony_cancel_work_sync(struct sony_sc *sc) | ||
| 1803 | { | ||
| 1804 | if (sc->worker_initialized) | ||
| 1805 | cancel_work_sync(&sc->state_worker); | ||
| 1806 | } | ||
| 1581 | 1807 | ||
| 1582 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | 1808 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 1583 | { | 1809 | { |
| @@ -1615,6 +1841,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1615 | return ret; | 1841 | return ret; |
| 1616 | } | 1842 | } |
| 1617 | 1843 | ||
| 1844 | ret = sony_set_device_id(sc); | ||
| 1845 | if (ret < 0) { | ||
| 1846 | hid_err(hdev, "failed to allocate the device id\n"); | ||
| 1847 | goto err_stop; | ||
| 1848 | } | ||
| 1849 | |||
| 1618 | if (sc->quirks & SIXAXIS_CONTROLLER_USB) { | 1850 | if (sc->quirks & SIXAXIS_CONTROLLER_USB) { |
| 1619 | /* | 1851 | /* |
| 1620 | * The Sony Sixaxis does not handle HID Output Reports on the | 1852 | * The Sony Sixaxis does not handle HID Output Reports on the |
| @@ -1629,8 +1861,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1629 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | 1861 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; |
| 1630 | hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; | 1862 | hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; |
| 1631 | ret = sixaxis_set_operational_usb(hdev); | 1863 | ret = sixaxis_set_operational_usb(hdev); |
| 1632 | sc->worker_initialized = 1; | 1864 | sony_init_work(sc, sixaxis_state_worker); |
| 1633 | INIT_WORK(&sc->state_worker, sixaxis_state_worker); | ||
| 1634 | } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { | 1865 | } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { |
| 1635 | /* | 1866 | /* |
| 1636 | * The Sixaxis wants output reports sent on the ctrl endpoint | 1867 | * The Sixaxis wants output reports sent on the ctrl endpoint |
| @@ -1638,8 +1869,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1638 | */ | 1869 | */ |
| 1639 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; | 1870 | hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; |
| 1640 | ret = sixaxis_set_operational_bt(hdev); | 1871 | ret = sixaxis_set_operational_bt(hdev); |
| 1641 | sc->worker_initialized = 1; | 1872 | sony_init_work(sc, sixaxis_state_worker); |
| 1642 | INIT_WORK(&sc->state_worker, sixaxis_state_worker); | ||
| 1643 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { | 1873 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
| 1644 | if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { | 1874 | if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { |
| 1645 | /* | 1875 | /* |
| @@ -1661,8 +1891,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1661 | if (ret < 0) | 1891 | if (ret < 0) |
| 1662 | goto err_stop; | 1892 | goto err_stop; |
| 1663 | 1893 | ||
| 1664 | sc->worker_initialized = 1; | 1894 | sony_init_work(sc, dualshock4_state_worker); |
| 1665 | INIT_WORK(&sc->state_worker, dualshock4_state_worker); | ||
| 1666 | } else { | 1895 | } else { |
| 1667 | ret = 0; | 1896 | ret = 0; |
| 1668 | } | 1897 | } |
| @@ -1675,7 +1904,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1675 | goto err_stop; | 1904 | goto err_stop; |
| 1676 | 1905 | ||
| 1677 | if (sc->quirks & SONY_LED_SUPPORT) { | 1906 | if (sc->quirks & SONY_LED_SUPPORT) { |
| 1678 | ret = sony_leds_init(hdev); | 1907 | ret = sony_leds_init(sc); |
| 1679 | if (ret < 0) | 1908 | if (ret < 0) |
| 1680 | goto err_stop; | 1909 | goto err_stop; |
| 1681 | } | 1910 | } |
| @@ -1694,7 +1923,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1694 | } | 1923 | } |
| 1695 | 1924 | ||
| 1696 | if (sc->quirks & SONY_FF_SUPPORT) { | 1925 | if (sc->quirks & SONY_FF_SUPPORT) { |
| 1697 | ret = sony_init_ff(hdev); | 1926 | ret = sony_init_ff(sc); |
| 1698 | if (ret < 0) | 1927 | if (ret < 0) |
| 1699 | goto err_close; | 1928 | goto err_close; |
| 1700 | } | 1929 | } |
| @@ -1704,12 +1933,12 @@ err_close: | |||
| 1704 | hid_hw_close(hdev); | 1933 | hid_hw_close(hdev); |
| 1705 | err_stop: | 1934 | err_stop: |
| 1706 | if (sc->quirks & SONY_LED_SUPPORT) | 1935 | if (sc->quirks & SONY_LED_SUPPORT) |
| 1707 | sony_leds_remove(hdev); | 1936 | sony_leds_remove(sc); |
| 1708 | if (sc->quirks & SONY_BATTERY_SUPPORT) | 1937 | if (sc->quirks & SONY_BATTERY_SUPPORT) |
| 1709 | sony_battery_remove(sc); | 1938 | sony_battery_remove(sc); |
| 1710 | if (sc->worker_initialized) | 1939 | sony_cancel_work_sync(sc); |
| 1711 | cancel_work_sync(&sc->state_worker); | ||
| 1712 | sony_remove_dev_list(sc); | 1940 | sony_remove_dev_list(sc); |
| 1941 | sony_release_device_id(sc); | ||
| 1713 | hid_hw_stop(hdev); | 1942 | hid_hw_stop(hdev); |
| 1714 | return ret; | 1943 | return ret; |
| 1715 | } | 1944 | } |
| @@ -1719,18 +1948,19 @@ static void sony_remove(struct hid_device *hdev) | |||
| 1719 | struct sony_sc *sc = hid_get_drvdata(hdev); | 1948 | struct sony_sc *sc = hid_get_drvdata(hdev); |
| 1720 | 1949 | ||
| 1721 | if (sc->quirks & SONY_LED_SUPPORT) | 1950 | if (sc->quirks & SONY_LED_SUPPORT) |
| 1722 | sony_leds_remove(hdev); | 1951 | sony_leds_remove(sc); |
| 1723 | 1952 | ||
| 1724 | if (sc->quirks & SONY_BATTERY_SUPPORT) { | 1953 | if (sc->quirks & SONY_BATTERY_SUPPORT) { |
| 1725 | hid_hw_close(hdev); | 1954 | hid_hw_close(hdev); |
| 1726 | sony_battery_remove(sc); | 1955 | sony_battery_remove(sc); |
| 1727 | } | 1956 | } |
| 1728 | 1957 | ||
| 1729 | if (sc->worker_initialized) | 1958 | sony_cancel_work_sync(sc); |
| 1730 | cancel_work_sync(&sc->state_worker); | ||
| 1731 | 1959 | ||
| 1732 | sony_remove_dev_list(sc); | 1960 | sony_remove_dev_list(sc); |
| 1733 | 1961 | ||
| 1962 | sony_release_device_id(sc); | ||
| 1963 | |||
| 1734 | hid_hw_stop(hdev); | 1964 | hid_hw_stop(hdev); |
| 1735 | } | 1965 | } |
| 1736 | 1966 | ||
| @@ -1775,6 +2005,22 @@ static struct hid_driver sony_driver = { | |||
| 1775 | .report_fixup = sony_report_fixup, | 2005 | .report_fixup = sony_report_fixup, |
| 1776 | .raw_event = sony_raw_event | 2006 | .raw_event = sony_raw_event |
| 1777 | }; | 2007 | }; |
| 1778 | module_hid_driver(sony_driver); | 2008 | |
| 2009 | static int __init sony_init(void) | ||
| 2010 | { | ||
| 2011 | dbg_hid("Sony:%s\n", __func__); | ||
| 2012 | |||
| 2013 | return hid_register_driver(&sony_driver); | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | static void __exit sony_exit(void) | ||
| 2017 | { | ||
| 2018 | dbg_hid("Sony:%s\n", __func__); | ||
| 2019 | |||
| 2020 | ida_destroy(&sony_device_id_allocator); | ||
| 2021 | hid_unregister_driver(&sony_driver); | ||
| 2022 | } | ||
| 2023 | module_init(sony_init); | ||
| 2024 | module_exit(sony_exit); | ||
| 1779 | 2025 | ||
| 1780 | MODULE_LICENSE("GPL"); | 2026 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index a97c78845f7b..134be89b15ea 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * ThingM blink(1) USB RGB LED driver | 2 | * ThingM blink(1) USB RGB LED driver |
| 3 | * | 3 | * |
| 4 | * Copyright 2013 Savoir-faire Linux Inc. | 4 | * Copyright 2013-2014 Savoir-faire Linux Inc. |
| 5 | * Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 5 | * Vivien Didelot <vivien.didelot@savoirfairelinux.com> |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
| @@ -10,244 +10,285 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/hid.h> | 12 | #include <linux/hid.h> |
| 13 | #include <linux/hidraw.h> | ||
| 13 | #include <linux/leds.h> | 14 | #include <linux/leds.h> |
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <linux/workqueue.h> | ||
| 15 | 18 | ||
| 16 | #include "hid-ids.h" | 19 | #include "hid-ids.h" |
| 17 | 20 | ||
| 18 | #define BLINK1_CMD_SIZE 9 | 21 | #define REPORT_ID 1 |
| 22 | #define REPORT_SIZE 9 | ||
| 19 | 23 | ||
| 20 | #define blink1_rgb_to_r(rgb) ((rgb & 0xFF0000) >> 16) | 24 | /* Firmware major number of supported devices */ |
| 21 | #define blink1_rgb_to_g(rgb) ((rgb & 0x00FF00) >> 8) | 25 | #define THINGM_MAJOR_MK1 '1' |
| 22 | #define blink1_rgb_to_b(rgb) ((rgb & 0x0000FF) >> 0) | 26 | #define THINGM_MAJOR_MK2 '2' |
| 23 | 27 | ||
| 24 | /** | 28 | struct thingm_fwinfo { |
| 25 | * struct blink1_data - blink(1) device specific data | 29 | char major; |
| 26 | * @hdev: HID device. | 30 | unsigned numrgb; |
| 27 | * @led_cdev: LED class instance. | 31 | unsigned first; |
| 28 | * @rgb: 8-bit per channel RGB notation. | 32 | }; |
| 29 | * @fade: fade time in hundredths of a second. | 33 | |
| 30 | * @brightness: brightness coefficient. | 34 | static const struct thingm_fwinfo thingm_fwinfo[] = { |
| 31 | * @play: play/pause in-memory patterns. | 35 | { |
| 32 | */ | 36 | .major = THINGM_MAJOR_MK1, |
| 33 | struct blink1_data { | 37 | .numrgb = 1, |
| 38 | .first = 0, | ||
| 39 | }, { | ||
| 40 | .major = THINGM_MAJOR_MK2, | ||
| 41 | .numrgb = 2, | ||
| 42 | .first = 1, | ||
| 43 | } | ||
| 44 | }; | ||
| 45 | |||
| 46 | /* A red, green or blue channel, part of an RGB chip */ | ||
| 47 | struct thingm_led { | ||
| 48 | struct thingm_rgb *rgb; | ||
| 49 | struct led_classdev ldev; | ||
| 50 | char name[32]; | ||
| 51 | }; | ||
| 52 | |||
| 53 | /* Basically a WS2812 5050 RGB LED chip */ | ||
| 54 | struct thingm_rgb { | ||
| 55 | struct thingm_device *tdev; | ||
| 56 | struct thingm_led red; | ||
| 57 | struct thingm_led green; | ||
| 58 | struct thingm_led blue; | ||
| 59 | struct work_struct work; | ||
| 60 | u8 num; | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct thingm_device { | ||
| 34 | struct hid_device *hdev; | 64 | struct hid_device *hdev; |
| 35 | struct led_classdev led_cdev; | 65 | struct { |
| 36 | u32 rgb; | 66 | char major; |
| 37 | u16 fade; | 67 | char minor; |
| 38 | u8 brightness; | 68 | } version; |
| 39 | bool play; | 69 | const struct thingm_fwinfo *fwinfo; |
| 70 | struct mutex lock; | ||
| 71 | struct thingm_rgb *rgb; | ||
| 40 | }; | 72 | }; |
| 41 | 73 | ||
| 42 | static int blink1_send_command(struct blink1_data *data, | 74 | static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE]) |
| 43 | u8 buf[BLINK1_CMD_SIZE]) | ||
| 44 | { | 75 | { |
| 45 | int ret; | 76 | int ret; |
| 46 | 77 | ||
| 47 | hid_dbg(data->hdev, "command: %d%c%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n", | 78 | hid_dbg(tdev->hdev, "-> %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", |
| 48 | buf[0], buf[1], buf[2], buf[3], buf[4], | 79 | buf[0], buf[1], buf[2], buf[3], buf[4], |
| 49 | buf[5], buf[6], buf[7], buf[8]); | 80 | buf[5], buf[6], buf[7], buf[8]); |
| 50 | 81 | ||
| 51 | ret = hid_hw_raw_request(data->hdev, buf[0], buf, BLINK1_CMD_SIZE, | 82 | ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE, |
| 52 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | 83 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
| 53 | 84 | ||
| 54 | return ret < 0 ? ret : 0; | 85 | return ret < 0 ? ret : 0; |
| 55 | } | 86 | } |
| 56 | 87 | ||
| 57 | static int blink1_update_color(struct blink1_data *data) | 88 | static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE]) |
| 58 | { | 89 | { |
| 59 | u8 buf[BLINK1_CMD_SIZE] = { 1, 'n', 0, 0, 0, 0, 0, 0, 0 }; | 90 | int ret; |
| 60 | |||
| 61 | if (data->brightness) { | ||
| 62 | unsigned int coef = DIV_ROUND_CLOSEST(255, data->brightness); | ||
| 63 | 91 | ||
| 64 | buf[2] = DIV_ROUND_CLOSEST(blink1_rgb_to_r(data->rgb), coef); | 92 | ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE, |
| 65 | buf[3] = DIV_ROUND_CLOSEST(blink1_rgb_to_g(data->rgb), coef); | 93 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
| 66 | buf[4] = DIV_ROUND_CLOSEST(blink1_rgb_to_b(data->rgb), coef); | 94 | if (ret < 0) |
| 67 | } | 95 | return ret; |
| 68 | 96 | ||
| 69 | if (data->fade) { | 97 | hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", |
| 70 | buf[1] = 'c'; | 98 | buf[0], buf[1], buf[2], buf[3], buf[4], |
| 71 | buf[5] = (data->fade & 0xFF00) >> 8; | 99 | buf[5], buf[6], buf[7], buf[8]); |
| 72 | buf[6] = (data->fade & 0x00FF); | ||
| 73 | } | ||
| 74 | 100 | ||
| 75 | return blink1_send_command(data, buf); | 101 | return 0; |
| 76 | } | 102 | } |
| 77 | 103 | ||
| 78 | static void blink1_led_set(struct led_classdev *led_cdev, | 104 | static int thingm_version(struct thingm_device *tdev) |
| 79 | enum led_brightness brightness) | ||
| 80 | { | 105 | { |
| 81 | struct blink1_data *data = dev_get_drvdata(led_cdev->dev->parent); | 106 | u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 }; |
| 107 | int err; | ||
| 82 | 108 | ||
| 83 | data->brightness = brightness; | 109 | err = thingm_send(tdev, buf); |
| 84 | if (blink1_update_color(data)) | 110 | if (err) |
| 85 | hid_err(data->hdev, "failed to update color\n"); | 111 | return err; |
| 86 | } | ||
| 87 | 112 | ||
| 88 | static enum led_brightness blink1_led_get(struct led_classdev *led_cdev) | 113 | err = thingm_recv(tdev, buf); |
| 89 | { | 114 | if (err) |
| 90 | struct blink1_data *data = dev_get_drvdata(led_cdev->dev->parent); | 115 | return err; |
| 91 | 116 | ||
| 92 | return data->brightness; | 117 | tdev->version.major = buf[3]; |
| 118 | tdev->version.minor = buf[4]; | ||
| 119 | |||
| 120 | return 0; | ||
| 93 | } | 121 | } |
| 94 | 122 | ||
| 95 | static ssize_t blink1_show_rgb(struct device *dev, | 123 | static int thingm_write_color(struct thingm_rgb *rgb) |
| 96 | struct device_attribute *attr, char *buf) | ||
| 97 | { | 124 | { |
| 98 | struct blink1_data *data = dev_get_drvdata(dev->parent); | 125 | u8 buf[REPORT_SIZE] = { REPORT_ID, 'c', 0, 0, 0, 0, 0, rgb->num, 0 }; |
| 99 | 126 | ||
| 100 | return sprintf(buf, "%.6X\n", data->rgb); | 127 | buf[2] = rgb->red.ldev.brightness; |
| 128 | buf[3] = rgb->green.ldev.brightness; | ||
| 129 | buf[4] = rgb->blue.ldev.brightness; | ||
| 130 | |||
| 131 | return thingm_send(rgb->tdev, buf); | ||
| 101 | } | 132 | } |
| 102 | 133 | ||
| 103 | static ssize_t blink1_store_rgb(struct device *dev, | 134 | static void thingm_work(struct work_struct *work) |
| 104 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 105 | { | 135 | { |
| 106 | struct blink1_data *data = dev_get_drvdata(dev->parent); | 136 | struct thingm_rgb *rgb = container_of(work, struct thingm_rgb, work); |
| 107 | long unsigned int rgb; | ||
| 108 | int ret; | ||
| 109 | 137 | ||
| 110 | ret = kstrtoul(buf, 16, &rgb); | 138 | mutex_lock(&rgb->tdev->lock); |
| 111 | if (ret) | ||
| 112 | return ret; | ||
| 113 | |||
| 114 | /* RGB triplet notation is 24-bit hexadecimal */ | ||
| 115 | if (rgb > 0xFFFFFF) | ||
| 116 | return -EINVAL; | ||
| 117 | 139 | ||
| 118 | data->rgb = rgb; | 140 | if (thingm_write_color(rgb)) |
| 119 | ret = blink1_update_color(data); | 141 | hid_err(rgb->tdev->hdev, "failed to write color\n"); |
| 120 | 142 | ||
| 121 | return ret ? ret : count; | 143 | mutex_unlock(&rgb->tdev->lock); |
| 122 | } | 144 | } |
| 123 | 145 | ||
| 124 | static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR, blink1_show_rgb, blink1_store_rgb); | 146 | static void thingm_led_set(struct led_classdev *ldev, |
| 125 | 147 | enum led_brightness brightness) | |
| 126 | static ssize_t blink1_show_fade(struct device *dev, | ||
| 127 | struct device_attribute *attr, char *buf) | ||
| 128 | { | 148 | { |
| 129 | struct blink1_data *data = dev_get_drvdata(dev->parent); | 149 | struct thingm_led *led = container_of(ldev, struct thingm_led, ldev); |
| 130 | 150 | ||
| 131 | return sprintf(buf, "%d\n", data->fade * 10); | 151 | /* the ledclass has already stored the brightness value */ |
| 152 | schedule_work(&led->rgb->work); | ||
| 132 | } | 153 | } |
| 133 | 154 | ||
| 134 | static ssize_t blink1_store_fade(struct device *dev, | 155 | static int thingm_init_rgb(struct thingm_rgb *rgb) |
| 135 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 136 | { | 156 | { |
| 137 | struct blink1_data *data = dev_get_drvdata(dev->parent); | 157 | const int minor = ((struct hidraw *) rgb->tdev->hdev->hidraw)->minor; |
| 138 | long unsigned int fade; | 158 | int err; |
| 139 | int ret; | 159 | |
| 160 | /* Register the red diode */ | ||
| 161 | snprintf(rgb->red.name, sizeof(rgb->red.name), | ||
| 162 | "thingm%d:red:led%d", minor, rgb->num); | ||
| 163 | rgb->red.ldev.name = rgb->red.name; | ||
| 164 | rgb->red.ldev.max_brightness = 255; | ||
| 165 | rgb->red.ldev.brightness_set = thingm_led_set; | ||
| 166 | rgb->red.rgb = rgb; | ||
| 167 | |||
| 168 | err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->red.ldev); | ||
| 169 | if (err) | ||
| 170 | return err; | ||
| 171 | |||
| 172 | /* Register the green diode */ | ||
| 173 | snprintf(rgb->green.name, sizeof(rgb->green.name), | ||
| 174 | "thingm%d:green:led%d", minor, rgb->num); | ||
| 175 | rgb->green.ldev.name = rgb->green.name; | ||
| 176 | rgb->green.ldev.max_brightness = 255; | ||
| 177 | rgb->green.ldev.brightness_set = thingm_led_set; | ||
| 178 | rgb->green.rgb = rgb; | ||
| 179 | |||
| 180 | err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->green.ldev); | ||
| 181 | if (err) | ||
| 182 | goto unregister_red; | ||
| 183 | |||
| 184 | /* Register the blue diode */ | ||
| 185 | snprintf(rgb->blue.name, sizeof(rgb->blue.name), | ||
| 186 | "thingm%d:blue:led%d", minor, rgb->num); | ||
| 187 | rgb->blue.ldev.name = rgb->blue.name; | ||
| 188 | rgb->blue.ldev.max_brightness = 255; | ||
| 189 | rgb->blue.ldev.brightness_set = thingm_led_set; | ||
| 190 | rgb->blue.rgb = rgb; | ||
| 191 | |||
| 192 | err = led_classdev_register(&rgb->tdev->hdev->dev, &rgb->blue.ldev); | ||
| 193 | if (err) | ||
| 194 | goto unregister_green; | ||
| 195 | |||
| 196 | INIT_WORK(&rgb->work, thingm_work); | ||
| 140 | 197 | ||
| 141 | ret = kstrtoul(buf, 10, &fade); | 198 | return 0; |
| 142 | if (ret) | ||
| 143 | return ret; | ||
| 144 | 199 | ||
| 145 | /* blink(1) accepts 16-bit fade time, number of 10ms ticks */ | 200 | unregister_green: |
| 146 | fade = DIV_ROUND_CLOSEST(fade, 10); | 201 | led_classdev_unregister(&rgb->green.ldev); |
| 147 | if (fade > 65535) | ||
| 148 | return -EINVAL; | ||
| 149 | 202 | ||
| 150 | data->fade = fade; | 203 | unregister_red: |
| 204 | led_classdev_unregister(&rgb->red.ldev); | ||
| 151 | 205 | ||
| 152 | return count; | 206 | return err; |
| 153 | } | 207 | } |
| 154 | 208 | ||
| 155 | static DEVICE_ATTR(fade, S_IRUGO | S_IWUSR, | 209 | static void thingm_remove_rgb(struct thingm_rgb *rgb) |
| 156 | blink1_show_fade, blink1_store_fade); | ||
| 157 | |||
| 158 | static ssize_t blink1_show_play(struct device *dev, | ||
| 159 | struct device_attribute *attr, char *buf) | ||
| 160 | { | 210 | { |
| 161 | struct blink1_data *data = dev_get_drvdata(dev->parent); | 211 | flush_work(&rgb->work); |
| 162 | 212 | led_classdev_unregister(&rgb->red.ldev); | |
| 163 | return sprintf(buf, "%d\n", data->play); | 213 | led_classdev_unregister(&rgb->green.ldev); |
| 214 | led_classdev_unregister(&rgb->blue.ldev); | ||
| 164 | } | 215 | } |
| 165 | 216 | ||
| 166 | static ssize_t blink1_store_play(struct device *dev, | 217 | static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 167 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 168 | { | 218 | { |
| 169 | struct blink1_data *data = dev_get_drvdata(dev->parent); | 219 | struct thingm_device *tdev; |
| 170 | u8 cmd[BLINK1_CMD_SIZE] = { 1, 'p', 0, 0, 0, 0, 0, 0, 0 }; | 220 | int i, err; |
| 171 | long unsigned int play; | ||
| 172 | int ret; | ||
| 173 | 221 | ||
| 174 | ret = kstrtoul(buf, 10, &play); | 222 | tdev = devm_kzalloc(&hdev->dev, sizeof(struct thingm_device), |
| 175 | if (ret) | 223 | GFP_KERNEL); |
| 176 | return ret; | 224 | if (!tdev) |
| 225 | return -ENOMEM; | ||
| 177 | 226 | ||
| 178 | data->play = !!play; | 227 | tdev->hdev = hdev; |
| 179 | cmd[2] = data->play; | 228 | hid_set_drvdata(hdev, tdev); |
| 180 | ret = blink1_send_command(data, cmd); | ||
| 181 | 229 | ||
| 182 | return ret ? ret : count; | 230 | err = hid_parse(hdev); |
| 183 | } | 231 | if (err) |
| 184 | 232 | goto error; | |
| 185 | static DEVICE_ATTR(play, S_IRUGO | S_IWUSR, | ||
| 186 | blink1_show_play, blink1_store_play); | ||
| 187 | 233 | ||
| 188 | static const struct attribute_group blink1_sysfs_group = { | 234 | err = hid_hw_start(hdev, HID_CONNECT_HIDRAW); |
| 189 | .attrs = (struct attribute *[]) { | 235 | if (err) |
| 190 | &dev_attr_rgb.attr, | 236 | goto error; |
| 191 | &dev_attr_fade.attr, | ||
| 192 | &dev_attr_play.attr, | ||
| 193 | NULL | ||
| 194 | }, | ||
| 195 | }; | ||
| 196 | 237 | ||
| 197 | static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id) | 238 | mutex_init(&tdev->lock); |
| 198 | { | ||
| 199 | struct blink1_data *data; | ||
| 200 | struct led_classdev *led; | ||
| 201 | char led_name[13]; | ||
| 202 | int ret; | ||
| 203 | 239 | ||
| 204 | data = devm_kzalloc(&hdev->dev, sizeof(struct blink1_data), GFP_KERNEL); | 240 | err = thingm_version(tdev); |
| 205 | if (!data) | 241 | if (err) |
| 206 | return -ENOMEM; | 242 | goto stop; |
| 207 | 243 | ||
| 208 | hid_set_drvdata(hdev, data); | 244 | hid_dbg(hdev, "firmware version: %c.%c\n", |
| 209 | data->hdev = hdev; | 245 | tdev->version.major, tdev->version.minor); |
| 210 | data->rgb = 0xFFFFFF; /* set a default white color */ | ||
| 211 | 246 | ||
| 212 | ret = hid_parse(hdev); | 247 | for (i = 0; i < ARRAY_SIZE(thingm_fwinfo) && !tdev->fwinfo; ++i) |
| 213 | if (ret) | 248 | if (thingm_fwinfo[i].major == tdev->version.major) |
| 214 | goto error; | 249 | tdev->fwinfo = &thingm_fwinfo[i]; |
| 215 | 250 | ||
| 216 | ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); | 251 | if (!tdev->fwinfo) { |
| 217 | if (ret) | 252 | hid_err(hdev, "unsupported firmware %c\n", tdev->version.major); |
| 218 | goto error; | 253 | goto stop; |
| 254 | } | ||
| 219 | 255 | ||
| 220 | /* blink(1) serial numbers range is 0x1A001000 to 0x1A002FFF */ | 256 | tdev->rgb = devm_kzalloc(&hdev->dev, |
| 221 | led = &data->led_cdev; | 257 | sizeof(struct thingm_rgb) * tdev->fwinfo->numrgb, |
| 222 | snprintf(led_name, sizeof(led_name), "blink1::%s", hdev->uniq + 4); | 258 | GFP_KERNEL); |
| 223 | led->name = led_name; | 259 | if (!tdev->rgb) { |
| 224 | led->brightness_set = blink1_led_set; | 260 | err = -ENOMEM; |
| 225 | led->brightness_get = blink1_led_get; | ||
| 226 | ret = led_classdev_register(&hdev->dev, led); | ||
| 227 | if (ret) | ||
| 228 | goto stop; | 261 | goto stop; |
| 262 | } | ||
| 229 | 263 | ||
| 230 | ret = sysfs_create_group(&led->dev->kobj, &blink1_sysfs_group); | 264 | for (i = 0; i < tdev->fwinfo->numrgb; ++i) { |
| 231 | if (ret) | 265 | struct thingm_rgb *rgb = tdev->rgb + i; |
| 232 | goto remove_led; | 266 | |
| 267 | rgb->tdev = tdev; | ||
| 268 | rgb->num = tdev->fwinfo->first + i; | ||
| 269 | err = thingm_init_rgb(rgb); | ||
| 270 | if (err) { | ||
| 271 | while (--i >= 0) | ||
| 272 | thingm_remove_rgb(tdev->rgb + i); | ||
| 273 | goto stop; | ||
| 274 | } | ||
| 275 | } | ||
| 233 | 276 | ||
| 234 | return 0; | 277 | return 0; |
| 235 | |||
| 236 | remove_led: | ||
| 237 | led_classdev_unregister(led); | ||
| 238 | stop: | 278 | stop: |
| 239 | hid_hw_stop(hdev); | 279 | hid_hw_stop(hdev); |
| 240 | error: | 280 | error: |
| 241 | return ret; | 281 | return err; |
| 242 | } | 282 | } |
| 243 | 283 | ||
| 244 | static void thingm_remove(struct hid_device *hdev) | 284 | static void thingm_remove(struct hid_device *hdev) |
| 245 | { | 285 | { |
| 246 | struct blink1_data *data = hid_get_drvdata(hdev); | 286 | struct thingm_device *tdev = hid_get_drvdata(hdev); |
| 247 | struct led_classdev *led = &data->led_cdev; | 287 | int i; |
| 288 | |||
| 289 | for (i = 0; i < tdev->fwinfo->numrgb; ++i) | ||
| 290 | thingm_remove_rgb(tdev->rgb + i); | ||
| 248 | 291 | ||
| 249 | sysfs_remove_group(&led->dev->kobj, &blink1_sysfs_group); | ||
| 250 | led_classdev_unregister(led); | ||
| 251 | hid_hw_stop(hdev); | 292 | hid_hw_stop(hdev); |
| 252 | } | 293 | } |
| 253 | 294 | ||
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index b50860db92f1..21aafc8f48c8 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
| @@ -807,34 +807,18 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) | |||
| 807 | unsigned int dsize; | 807 | unsigned int dsize; |
| 808 | int ret; | 808 | int ret; |
| 809 | 809 | ||
| 810 | /* Fetch the length of HID description, retrieve the 4 first bytes: | 810 | /* i2c hid fetch using a fixed descriptor size (30 bytes) */ |
| 811 | * bytes 0-1 -> length | 811 | i2c_hid_dbg(ihid, "Fetching the HID descriptor\n"); |
| 812 | * bytes 2-3 -> bcdVersion (has to be 1.00) */ | 812 | ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, |
| 813 | ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4); | 813 | sizeof(struct i2c_hid_desc)); |
| 814 | |||
| 815 | i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %4ph\n", __func__, | ||
| 816 | ihid->hdesc_buffer); | ||
| 817 | |||
| 818 | if (ret) { | 814 | if (ret) { |
| 819 | dev_err(&client->dev, | 815 | dev_err(&client->dev, "hid_descr_cmd failed\n"); |
| 820 | "unable to fetch the size of HID descriptor (ret=%d)\n", | ||
| 821 | ret); | ||
| 822 | return -ENODEV; | ||
| 823 | } | ||
| 824 | |||
| 825 | dsize = le16_to_cpu(hdesc->wHIDDescLength); | ||
| 826 | /* | ||
| 827 | * the size of the HID descriptor should at least contain | ||
| 828 | * its size and the bcdVersion (4 bytes), and should not be greater | ||
| 829 | * than sizeof(struct i2c_hid_desc) as we directly fill this struct | ||
| 830 | * through i2c_hid_command. | ||
| 831 | */ | ||
| 832 | if (dsize < 4 || dsize > sizeof(struct i2c_hid_desc)) { | ||
| 833 | dev_err(&client->dev, "weird size of HID descriptor (%u)\n", | ||
| 834 | dsize); | ||
| 835 | return -ENODEV; | 816 | return -ENODEV; |
| 836 | } | 817 | } |
| 837 | 818 | ||
| 819 | /* Validate the length of HID descriptor, the 4 first bytes: | ||
| 820 | * bytes 0-1 -> length | ||
| 821 | * bytes 2-3 -> bcdVersion (has to be 1.00) */ | ||
| 838 | /* check bcdVersion == 1.0 */ | 822 | /* check bcdVersion == 1.0 */ |
| 839 | if (le16_to_cpu(hdesc->bcdVersion) != 0x0100) { | 823 | if (le16_to_cpu(hdesc->bcdVersion) != 0x0100) { |
| 840 | dev_err(&client->dev, | 824 | dev_err(&client->dev, |
| @@ -843,17 +827,14 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) | |||
| 843 | return -ENODEV; | 827 | return -ENODEV; |
| 844 | } | 828 | } |
| 845 | 829 | ||
| 846 | i2c_hid_dbg(ihid, "Fetching the HID descriptor\n"); | 830 | /* Descriptor length should be 30 bytes as per the specification */ |
| 847 | 831 | dsize = le16_to_cpu(hdesc->wHIDDescLength); | |
| 848 | ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, | 832 | if (dsize != sizeof(struct i2c_hid_desc)) { |
| 849 | dsize); | 833 | dev_err(&client->dev, "weird size of HID descriptor (%u)\n", |
| 850 | if (ret) { | 834 | dsize); |
| 851 | dev_err(&client->dev, "hid_descr_cmd Fail\n"); | ||
| 852 | return -ENODEV; | 835 | return -ENODEV; |
| 853 | } | 836 | } |
| 854 | |||
| 855 | i2c_hid_dbg(ihid, "HID Descriptor: %*ph\n", dsize, ihid->hdesc_buffer); | 837 | i2c_hid_dbg(ihid, "HID Descriptor: %*ph\n", dsize, ihid->hdesc_buffer); |
| 856 | |||
| 857 | return 0; | 838 | return 0; |
| 858 | } | 839 | } |
| 859 | 840 | ||
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 0d078c32db4f..0cb92e347258 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c | |||
| @@ -441,12 +441,11 @@ static int uhid_dev_create2(struct uhid_device *uhid, | |||
| 441 | if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) | 441 | if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) |
| 442 | return -EINVAL; | 442 | return -EINVAL; |
| 443 | 443 | ||
| 444 | uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); | 444 | uhid->rd_data = kmemdup(ev->u.create2.rd_data, uhid->rd_size, |
| 445 | GFP_KERNEL); | ||
| 445 | if (!uhid->rd_data) | 446 | if (!uhid->rd_data) |
| 446 | return -ENOMEM; | 447 | return -ENOMEM; |
| 447 | 448 | ||
| 448 | memcpy(uhid->rd_data, ev->u.create2.rd_data, uhid->rd_size); | ||
| 449 | |||
| 450 | hid = hid_allocate_device(); | 449 | hid = hid_allocate_device(); |
| 451 | if (IS_ERR(hid)) { | 450 | if (IS_ERR(hid)) { |
| 452 | ret = PTR_ERR(hid); | 451 | ret = PTR_ERR(hid); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 8e4ddb369883..59badc10a08c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -115,6 +115,7 @@ static const struct hid_blacklist { | |||
| 115 | { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, | 115 | { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, |
| 116 | { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, | 116 | { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, |
| 117 | { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, | 117 | { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, |
| 118 | { USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 118 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, | 119 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, |
| 119 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, | 120 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS }, |
| 120 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, | 121 | { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 39e717797cc0..089841ca180f 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -479,6 +479,8 @@ config LEDS_OT200 | |||
| 479 | This option enables support for the LEDs on the Bachmann OT200. | 479 | This option enables support for the LEDs on the Bachmann OT200. |
| 480 | Say Y to enable LEDs on the Bachmann OT200. | 480 | Say Y to enable LEDs on the Bachmann OT200. |
| 481 | 481 | ||
| 482 | comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" | ||
| 483 | |||
| 482 | config LEDS_BLINKM | 484 | config LEDS_BLINKM |
| 483 | tristate "LED support for the BlinkM I2C RGB LED" | 485 | tristate "LED support for the BlinkM I2C RGB LED" |
| 484 | depends on LEDS_CLASS | 486 | depends on LEDS_CLASS |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 720e3a10608c..77632cf159c0 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -233,11 +233,6 @@ struct hid_item { | |||
| 233 | #define HID_DG_BARRELSWITCH 0x000d0044 | 233 | #define HID_DG_BARRELSWITCH 0x000d0044 |
| 234 | #define HID_DG_ERASER 0x000d0045 | 234 | #define HID_DG_ERASER 0x000d0045 |
| 235 | #define HID_DG_TABLETPICK 0x000d0046 | 235 | #define HID_DG_TABLETPICK 0x000d0046 |
| 236 | /* | ||
| 237 | * as of May 20, 2009 the usages below are not yet in the official USB spec | ||
| 238 | * but are being pushed by Microsft as described in their paper "Digitizer | ||
| 239 | * Drivers for Windows Touch and Pen-Based Computers" | ||
| 240 | */ | ||
| 241 | #define HID_DG_CONFIDENCE 0x000d0047 | 236 | #define HID_DG_CONFIDENCE 0x000d0047 |
| 242 | #define HID_DG_WIDTH 0x000d0048 | 237 | #define HID_DG_WIDTH 0x000d0048 |
| 243 | #define HID_DG_HEIGHT 0x000d0049 | 238 | #define HID_DG_HEIGHT 0x000d0049 |
| @@ -246,6 +241,8 @@ struct hid_item { | |||
| 246 | #define HID_DG_DEVICEINDEX 0x000d0053 | 241 | #define HID_DG_DEVICEINDEX 0x000d0053 |
| 247 | #define HID_DG_CONTACTCOUNT 0x000d0054 | 242 | #define HID_DG_CONTACTCOUNT 0x000d0054 |
| 248 | #define HID_DG_CONTACTMAX 0x000d0055 | 243 | #define HID_DG_CONTACTMAX 0x000d0055 |
| 244 | #define HID_DG_BARRELSWITCH2 0x000d005a | ||
| 245 | #define HID_DG_TOOLSERIALNUMBER 0x000d005b | ||
| 249 | 246 | ||
| 250 | /* | 247 | /* |
| 251 | * HID report types --- Ouch! HID spec says 1 2 3! | 248 | * HID report types --- Ouch! HID spec says 1 2 3! |
| @@ -299,6 +296,9 @@ struct hid_item { | |||
| 299 | 296 | ||
| 300 | /* | 297 | /* |
| 301 | * HID device groups | 298 | * HID device groups |
| 299 | * | ||
| 300 | * Note: HID_GROUP_ANY is declared in linux/mod_devicetable.h | ||
| 301 | * and has a value of 0x0000 | ||
| 302 | */ | 302 | */ |
| 303 | #define HID_GROUP_GENERIC 0x0001 | 303 | #define HID_GROUP_GENERIC 0x0001 |
| 304 | #define HID_GROUP_MULTITOUCH 0x0002 | 304 | #define HID_GROUP_MULTITOUCH 0x0002 |
| @@ -306,6 +306,11 @@ struct hid_item { | |||
| 306 | #define HID_GROUP_MULTITOUCH_WIN_8 0x0004 | 306 | #define HID_GROUP_MULTITOUCH_WIN_8 0x0004 |
| 307 | 307 | ||
| 308 | /* | 308 | /* |
| 309 | * Vendor specific HID device groups | ||
| 310 | */ | ||
| 311 | #define HID_GROUP_RMI 0x0100 | ||
| 312 | |||
| 313 | /* | ||
| 309 | * This is the global environment of the parser. This information is | 314 | * This is the global environment of the parser. This information is |
| 310 | * persistent for main-items. The global environment can be saved and | 315 | * persistent for main-items. The global environment can be saved and |
| 311 | * restored with PUSH/POP statements. | 316 | * restored with PUSH/POP statements. |
| @@ -570,6 +575,8 @@ struct hid_descriptor { | |||
| 570 | .bus = BUS_USB, .vendor = (ven), .product = (prod) | 575 | .bus = BUS_USB, .vendor = (ven), .product = (prod) |
| 571 | #define HID_BLUETOOTH_DEVICE(ven, prod) \ | 576 | #define HID_BLUETOOTH_DEVICE(ven, prod) \ |
| 572 | .bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod) | 577 | .bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod) |
| 578 | #define HID_I2C_DEVICE(ven, prod) \ | ||
| 579 | .bus = BUS_I2C, .vendor = (ven), .product = (prod) | ||
| 573 | 580 | ||
| 574 | #define HID_REPORT_ID(rep) \ | 581 | #define HID_REPORT_ID(rep) \ |
| 575 | .report_type = (rep) | 582 | .report_type = (rep) |
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index f4849525519c..19df18c9b8be 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h | |||
| @@ -462,7 +462,10 @@ struct input_keymap_entry { | |||
| 462 | #define KEY_VIDEO_NEXT 241 /* drive next video source */ | 462 | #define KEY_VIDEO_NEXT 241 /* drive next video source */ |
| 463 | #define KEY_VIDEO_PREV 242 /* drive previous video source */ | 463 | #define KEY_VIDEO_PREV 242 /* drive previous video source */ |
| 464 | #define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ | 464 | #define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ |
| 465 | #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */ | 465 | #define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual |
| 466 | brightness control is off, | ||
| 467 | rely on ambient */ | ||
| 468 | #define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO | ||
| 466 | #define KEY_DISPLAY_OFF 245 /* display device to off state */ | 469 | #define KEY_DISPLAY_OFF 245 /* display device to off state */ |
| 467 | 470 | ||
| 468 | #define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ | 471 | #define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ |
| @@ -632,6 +635,7 @@ struct input_keymap_entry { | |||
| 632 | #define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ | 635 | #define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ |
| 633 | #define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ | 636 | #define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ |
| 634 | #define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ | 637 | #define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ |
| 638 | #define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE | ||
| 635 | #define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */ | 639 | #define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */ |
| 636 | #define KEY_LOGOFF 0x1b1 /* AL Logoff */ | 640 | #define KEY_LOGOFF 0x1b1 /* AL Logoff */ |
| 637 | 641 | ||
| @@ -723,6 +727,17 @@ struct input_keymap_entry { | |||
| 723 | 727 | ||
| 724 | #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ | 728 | #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ |
| 725 | 729 | ||
| 730 | #define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ | ||
| 731 | #define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ | ||
| 732 | #define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */ | ||
| 733 | #define KEY_CONTROLPANEL 0x243 /* AL Control Panel */ | ||
| 734 | #define KEY_APPSELECT 0x244 /* AL Select Task/Application */ | ||
| 735 | #define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ | ||
| 736 | #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ | ||
| 737 | |||
| 738 | #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ | ||
| 739 | #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ | ||
| 740 | |||
| 726 | #define BTN_TRIGGER_HAPPY 0x2c0 | 741 | #define BTN_TRIGGER_HAPPY 0x2c0 |
| 727 | #define BTN_TRIGGER_HAPPY1 0x2c0 | 742 | #define BTN_TRIGGER_HAPPY1 0x2c0 |
| 728 | #define BTN_TRIGGER_HAPPY2 0x2c1 | 743 | #define BTN_TRIGGER_HAPPY2 0x2c1 |
