Commit 169f15ab authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Jiri Kosina

HID: sony: Report DS4 version info through sysfs

Report DS4 firmware and hardware version through sysfs for both
USB and Bluetooth. This information is important for userspace
in particular for device specific quirks (e.g. in Bluetooth stacks).
Signed-off-by: default avatarRoderick Colenbrander <roderick.colenbrander@sony.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 332347d4
...@@ -473,6 +473,7 @@ struct motion_output_report_02 { ...@@ -473,6 +473,7 @@ struct motion_output_report_02 {
#define DS4_FEATURE_REPORT_0x02_SIZE 37 #define DS4_FEATURE_REPORT_0x02_SIZE 37
#define DS4_FEATURE_REPORT_0x05_SIZE 41 #define DS4_FEATURE_REPORT_0x05_SIZE 41
#define DS4_FEATURE_REPORT_0x81_SIZE 7 #define DS4_FEATURE_REPORT_0x81_SIZE 7
#define DS4_FEATURE_REPORT_0xA3_SIZE 49
#define DS4_INPUT_REPORT_0x11_SIZE 78 #define DS4_INPUT_REPORT_0x11_SIZE 78
#define DS4_OUTPUT_REPORT_0x05_SIZE 32 #define DS4_OUTPUT_REPORT_0x05_SIZE 32
#define DS4_OUTPUT_REPORT_0x11_SIZE 78 #define DS4_OUTPUT_REPORT_0x11_SIZE 78
...@@ -544,6 +545,8 @@ struct sony_sc { ...@@ -544,6 +545,8 @@ struct sony_sc {
struct power_supply *battery; struct power_supply *battery;
struct power_supply_desc battery_desc; struct power_supply_desc battery_desc;
int device_id; int device_id;
unsigned fw_version;
unsigned hw_version;
u8 *output_report_dmabuf; u8 *output_report_dmabuf;
#ifdef CONFIG_SONY_FF #ifdef CONFIG_SONY_FF
...@@ -627,6 +630,29 @@ static ssize_t ds4_store_poll_interval(struct device *dev, ...@@ -627,6 +630,29 @@ static ssize_t ds4_store_poll_interval(struct device *dev,
static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval, static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval,
ds4_store_poll_interval); ds4_store_poll_interval);
static ssize_t sony_show_firmware_version(struct device *dev,
struct device_attribute
*attr, char *buf)
{
struct hid_device *hdev = to_hid_device(dev);
struct sony_sc *sc = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "0x%04x\n", sc->fw_version);
}
static DEVICE_ATTR(firmware_version, 0444, sony_show_firmware_version, NULL);
static ssize_t sony_show_hardware_version(struct device *dev,
struct device_attribute
*attr, char *buf)
{
struct hid_device *hdev = to_hid_device(dev);
struct sony_sc *sc = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "0x%04x\n", sc->hw_version);
}
static DEVICE_ATTR(hardware_version, 0444, sony_show_hardware_version, NULL);
static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
unsigned int *rsize) unsigned int *rsize)
...@@ -1646,6 +1672,31 @@ static void dualshock4_calibration_work(struct work_struct *work) ...@@ -1646,6 +1672,31 @@ static void dualshock4_calibration_work(struct work_struct *work)
spin_unlock_irqrestore(&sc->lock, flags); spin_unlock_irqrestore(&sc->lock, flags);
} }
static int dualshock4_get_version_info(struct sony_sc *sc)
{
u8 *buf;
int ret;
buf = kmalloc(DS4_FEATURE_REPORT_0xA3_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = hid_hw_raw_request(sc->hdev, 0xA3, buf,
DS4_FEATURE_REPORT_0xA3_SIZE,
HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret < 0) {
kfree(buf);
return ret;
}
sc->hw_version = get_unaligned_le16(&buf[35]);
sc->fw_version = get_unaligned_le16(&buf[41]);
kfree(buf);
return 0;
}
static void sixaxis_set_leds_from_id(struct sony_sc *sc) static void sixaxis_set_leds_from_id(struct sony_sc *sc)
{ {
static const u8 sixaxis_leds[10][4] = { static const u8 sixaxis_leds[10][4] = {
...@@ -2619,6 +2670,28 @@ static int sony_input_configured(struct hid_device *hdev, ...@@ -2619,6 +2670,28 @@ static int sony_input_configured(struct hid_device *hdev,
goto err_stop; goto err_stop;
} }
ret = dualshock4_get_version_info(sc);
if (ret < 0) {
hid_err(sc->hdev, "Failed to get version data from Dualshock 4\n");
goto err_stop;
}
ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version);
if (ret) {
/* Make zero for cleanup reasons of sysfs entries. */
sc->fw_version = 0;
sc->hw_version = 0;
hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret);
goto err_stop;
}
ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version);
if (ret) {
sc->hw_version = 0;
hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret);
goto err_stop;
}
/* /*
* The Dualshock 4 touchpad supports 2 touches and has a * The Dualshock 4 touchpad supports 2 touches and has a
* resolution of 1920x942 (44.86 dots/mm). * resolution of 1920x942 (44.86 dots/mm).
...@@ -2695,6 +2768,10 @@ static int sony_input_configured(struct hid_device *hdev, ...@@ -2695,6 +2768,10 @@ static int sony_input_configured(struct hid_device *hdev,
*/ */
if (sc->ds4_bt_poll_interval) if (sc->ds4_bt_poll_interval)
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
if (sc->fw_version)
device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
if (sc->hw_version)
device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
if (sc->quirks & SONY_LED_SUPPORT) if (sc->quirks & SONY_LED_SUPPORT)
sony_leds_remove(sc); sony_leds_remove(sc);
if (sc->quirks & SONY_BATTERY_SUPPORT) if (sc->quirks & SONY_BATTERY_SUPPORT)
...@@ -2796,6 +2873,12 @@ static void sony_remove(struct hid_device *hdev) ...@@ -2796,6 +2873,12 @@ static void sony_remove(struct hid_device *hdev)
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
if (sc->fw_version)
device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
if (sc->hw_version)
device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
sony_cancel_work_sync(sc); sony_cancel_work_sync(sc);
kfree(sc->output_report_dmabuf); kfree(sc->output_report_dmabuf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment