diff options
-rw-r--r-- | drivers/hid/hid-sony.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 04fd611d3099..2bd3f130be20 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/leds.h> | 32 | #include <linux/leds.h> |
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/input/mt.h> | ||
35 | 36 | ||
36 | #include "hid-ids.h" | 37 | #include "hid-ids.h" |
37 | 38 | ||
@@ -643,7 +644,11 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) | |||
643 | 644 | ||
644 | static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) | 645 | static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) |
645 | { | 646 | { |
647 | struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, | ||
648 | struct hid_input, list); | ||
649 | struct input_dev *input_dev = hidinput->input; | ||
646 | unsigned long flags; | 650 | unsigned long flags; |
651 | int n, offset = 35; | ||
647 | __u8 cable_state, battery_capacity, battery_charging; | 652 | __u8 cable_state, battery_capacity, battery_charging; |
648 | 653 | ||
649 | /* The lower 4 bits of byte 30 contain the battery level | 654 | /* The lower 4 bits of byte 30 contain the battery level |
@@ -669,6 +674,28 @@ static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size) | |||
669 | sc->battery_capacity = battery_capacity; | 674 | sc->battery_capacity = battery_capacity; |
670 | sc->battery_charging = battery_charging; | 675 | sc->battery_charging = battery_charging; |
671 | spin_unlock_irqrestore(&sc->lock, flags); | 676 | spin_unlock_irqrestore(&sc->lock, flags); |
677 | |||
678 | /* The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB. | ||
679 | * The first 7 bits of the first byte is a counter and bit 8 is a touch | ||
680 | * indicator that is 0 when pressed and 1 when not pressed. | ||
681 | * The next 3 bytes are two 12 bit touch coordinates, X and Y. | ||
682 | * The data for the second touch is in the same format and immediatly | ||
683 | * follows the data for the first. | ||
684 | */ | ||
685 | for (n = 0; n < 2; n++) { | ||
686 | __u16 x, y; | ||
687 | |||
688 | x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); | ||
689 | y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); | ||
690 | |||
691 | input_mt_slot(input_dev, n); | ||
692 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, | ||
693 | !(rd[offset] >> 7)); | ||
694 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
695 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
696 | |||
697 | offset += 4; | ||
698 | } | ||
672 | } | 699 | } |
673 | 700 | ||
674 | static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, | 701 | static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, |
@@ -1200,6 +1227,26 @@ static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size) | |||
1200 | return -EINVAL; | 1227 | return -EINVAL; |
1201 | } | 1228 | } |
1202 | 1229 | ||
1230 | static int sony_register_touchpad(struct sony_sc *sc, int touch_count, | ||
1231 | int w, int h) | ||
1232 | { | ||
1233 | struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, | ||
1234 | struct hid_input, list); | ||
1235 | struct input_dev *input_dev = hidinput->input; | ||
1236 | int ret; | ||
1237 | |||
1238 | ret = input_mt_init_slots(input_dev, touch_count, 0); | ||
1239 | if (ret < 0) { | ||
1240 | hid_err(sc->hdev, "Unable to initialize multi-touch slots\n"); | ||
1241 | return ret; | ||
1242 | } | ||
1243 | |||
1244 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0); | ||
1245 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0); | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1203 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | 1250 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) |
1204 | { | 1251 | { |
1205 | int ret; | 1252 | int ret; |
@@ -1249,6 +1296,13 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1249 | if (ret < 0) | 1296 | if (ret < 0) |
1250 | goto err_stop; | 1297 | goto err_stop; |
1251 | 1298 | ||
1299 | /* The Dualshock 4 touchpad supports 2 touches and has a | ||
1300 | * resolution of 1920x940. | ||
1301 | */ | ||
1302 | ret = sony_register_touchpad(sc, 2, 1920, 940); | ||
1303 | if (ret < 0) | ||
1304 | goto err_stop; | ||
1305 | |||
1252 | INIT_WORK(&sc->state_worker, dualshock4_state_worker); | 1306 | INIT_WORK(&sc->state_worker, dualshock4_state_worker); |
1253 | } else { | 1307 | } else { |
1254 | ret = 0; | 1308 | ret = 0; |