mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
HID: playstation: add DualShock4 touchpad support.
Support the DualShock4 touchpad as a separate input device. The code describes the touchpad input reports through structures similar a bit to the DualSense code. Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
8871ed304e
commit
7520382488
|
|
@ -291,17 +291,43 @@ struct dualsense_output_report {
|
||||||
#define DS4_FEATURE_REPORT_PAIRING_INFO 0x12
|
#define DS4_FEATURE_REPORT_PAIRING_INFO 0x12
|
||||||
#define DS4_FEATURE_REPORT_PAIRING_INFO_SIZE 16
|
#define DS4_FEATURE_REPORT_PAIRING_INFO_SIZE 16
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status of a DualShock4 touch point contact.
|
||||||
|
* Contact IDs, with highest bit set are 'inactive'
|
||||||
|
* and any associated data is then invalid.
|
||||||
|
*/
|
||||||
|
#define DS4_TOUCH_POINT_INACTIVE BIT(7)
|
||||||
|
|
||||||
/* Status field of DualShock4 input report. */
|
/* Status field of DualShock4 input report. */
|
||||||
#define DS4_STATUS0_BATTERY_CAPACITY GENMASK(3, 0)
|
#define DS4_STATUS0_BATTERY_CAPACITY GENMASK(3, 0)
|
||||||
#define DS4_STATUS0_CABLE_STATE BIT(4)
|
#define DS4_STATUS0_CABLE_STATE BIT(4)
|
||||||
/* Battery status within batery_status field. */
|
/* Battery status within batery_status field. */
|
||||||
#define DS4_BATTERY_STATUS_FULL 11
|
#define DS4_BATTERY_STATUS_FULL 11
|
||||||
|
|
||||||
|
/* DualShock4 hardware limits */
|
||||||
|
#define DS4_TOUCHPAD_WIDTH 1920
|
||||||
|
#define DS4_TOUCHPAD_HEIGHT 942
|
||||||
|
|
||||||
struct dualshock4 {
|
struct dualshock4 {
|
||||||
struct ps_device base;
|
struct ps_device base;
|
||||||
struct input_dev *gamepad;
|
struct input_dev *gamepad;
|
||||||
|
struct input_dev *touchpad;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dualshock4_touch_point {
|
||||||
|
uint8_t contact;
|
||||||
|
uint8_t x_lo;
|
||||||
|
uint8_t x_hi:4, y_lo:4;
|
||||||
|
uint8_t y_hi;
|
||||||
|
} __packed;
|
||||||
|
static_assert(sizeof(struct dualshock4_touch_point) == 4);
|
||||||
|
|
||||||
|
struct dualshock4_touch_report {
|
||||||
|
uint8_t timestamp;
|
||||||
|
struct dualshock4_touch_point points[2];
|
||||||
|
} __packed;
|
||||||
|
static_assert(sizeof(struct dualshock4_touch_report) == 9);
|
||||||
|
|
||||||
/* Main DualShock4 input report excluding any BT/USB specific headers. */
|
/* Main DualShock4 input report excluding any BT/USB specific headers. */
|
||||||
struct dualshock4_input_report_common {
|
struct dualshock4_input_report_common {
|
||||||
uint8_t x, y;
|
uint8_t x, y;
|
||||||
|
|
@ -317,7 +343,9 @@ static_assert(sizeof(struct dualshock4_input_report_common) == 32);
|
||||||
struct dualshock4_input_report_usb {
|
struct dualshock4_input_report_usb {
|
||||||
uint8_t report_id; /* 0x01 */
|
uint8_t report_id; /* 0x01 */
|
||||||
struct dualshock4_input_report_common common;
|
struct dualshock4_input_report_common common;
|
||||||
uint8_t reserved[31];
|
uint8_t num_touch_reports;
|
||||||
|
struct dualshock4_touch_report touch_reports[3];
|
||||||
|
uint8_t reserved[3];
|
||||||
} __packed;
|
} __packed;
|
||||||
static_assert(sizeof(struct dualshock4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE);
|
static_assert(sizeof(struct dualshock4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE);
|
||||||
|
|
||||||
|
|
@ -1556,8 +1584,9 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
|
||||||
struct hid_device *hdev = ps_dev->hdev;
|
struct hid_device *hdev = ps_dev->hdev;
|
||||||
struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
|
struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
|
||||||
struct dualshock4_input_report_common *ds4_report;
|
struct dualshock4_input_report_common *ds4_report;
|
||||||
uint8_t battery_capacity, value;
|
struct dualshock4_touch_report *touch_reports;
|
||||||
int battery_status;
|
uint8_t battery_capacity, num_touch_reports, value;
|
||||||
|
int battery_status, i, j;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1570,6 +1599,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
|
||||||
struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data;
|
struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data;
|
||||||
|
|
||||||
ds4_report = &usb->common;
|
ds4_report = &usb->common;
|
||||||
|
num_touch_reports = usb->num_touch_reports;
|
||||||
|
touch_reports = usb->touch_reports;
|
||||||
} else {
|
} else {
|
||||||
hid_err(hdev, "Unhandled reportID=%d\n", report->id);
|
hid_err(hdev, "Unhandled reportID=%d\n", report->id);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1603,6 +1634,29 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
|
||||||
input_report_key(ds4->gamepad, BTN_MODE, ds4_report->buttons[2] & DS_BUTTONS2_PS_HOME);
|
input_report_key(ds4->gamepad, BTN_MODE, ds4_report->buttons[2] & DS_BUTTONS2_PS_HOME);
|
||||||
input_sync(ds4->gamepad);
|
input_sync(ds4->gamepad);
|
||||||
|
|
||||||
|
for (i = 0; i < num_touch_reports; i++) {
|
||||||
|
struct dualshock4_touch_report *touch_report = &touch_reports[i];
|
||||||
|
|
||||||
|
for (j = 0; j < ARRAY_SIZE(touch_report->points); j++) {
|
||||||
|
struct dualshock4_touch_point *point = &touch_report->points[j];
|
||||||
|
bool active = (point->contact & DS4_TOUCH_POINT_INACTIVE) ? false : true;
|
||||||
|
|
||||||
|
input_mt_slot(ds4->touchpad, j);
|
||||||
|
input_mt_report_slot_state(ds4->touchpad, MT_TOOL_FINGER, active);
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
int x = (point->x_hi << 8) | point->x_lo;
|
||||||
|
int y = (point->y_hi << 4) | point->y_lo;
|
||||||
|
|
||||||
|
input_report_abs(ds4->touchpad, ABS_MT_POSITION_X, x);
|
||||||
|
input_report_abs(ds4->touchpad, ABS_MT_POSITION_Y, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input_mt_sync_frame(ds4->touchpad);
|
||||||
|
input_sync(ds4->touchpad);
|
||||||
|
}
|
||||||
|
input_report_key(ds4->touchpad, BTN_LEFT, ds4_report->buttons[2] & DS_BUTTONS2_TOUCHPAD);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interpretation of the battery_capacity data depends on the cable state.
|
* Interpretation of the battery_capacity data depends on the cable state.
|
||||||
* When no cable is connected (bit4 is 0):
|
* When no cable is connected (bit4 is 0):
|
||||||
|
|
@ -1700,6 +1754,12 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ds4->touchpad = ps_touchpad_create(hdev, DS4_TOUCHPAD_WIDTH, DS4_TOUCHPAD_HEIGHT, 2);
|
||||||
|
if (IS_ERR(ds4->touchpad)) {
|
||||||
|
ret = PTR_ERR(ds4->touchpad);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ps_device_register_battery(ps_dev);
|
ret = ps_device_register_battery(ps_dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user