Commit 53f04e83 authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Benjamin Tissoires

HID: playstation: track devices in list.

Track devices in a list, so we can detect when a device is connected
twice when using Bluetooth and USB.
Signed-off-by: default avatarRoderick Colenbrander <roderick.colenbrander@sony.com>
Reviewed-by: default avatarBarnabás Pőcze <pobrn@protonmail.com>
Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
parent 402987c5
...@@ -15,10 +15,15 @@ ...@@ -15,10 +15,15 @@
#include "hid-ids.h" #include "hid-ids.h"
/* List of connected playstation devices. */
static DEFINE_MUTEX(ps_devices_lock);
static LIST_HEAD(ps_devices_list);
#define HID_PLAYSTATION_VERSION_PATCH 0x8000 #define HID_PLAYSTATION_VERSION_PATCH 0x8000
/* Base class for playstation devices. */ /* Base class for playstation devices. */
struct ps_device { struct ps_device {
struct list_head list;
struct hid_device *hdev; struct hid_device *hdev;
spinlock_t lock; spinlock_t lock;
...@@ -160,6 +165,38 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = { ...@@ -160,6 +165,38 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
{0, 0}, {0, 0},
}; };
/*
* Add a new ps_device to ps_devices if it doesn't exist.
* Return error on duplicate device, which can happen if the same
* device is connected using both Bluetooth and USB.
*/
static int ps_devices_list_add(struct ps_device *dev)
{
struct ps_device *entry;
mutex_lock(&ps_devices_lock);
list_for_each_entry(entry, &ps_devices_list, list) {
if (!memcmp(entry->mac_address, dev->mac_address, sizeof(dev->mac_address))) {
hid_err(dev->hdev, "Duplicate device found for MAC address %pMR.\n",
dev->mac_address);
mutex_unlock(&ps_devices_lock);
return -EEXIST;
}
}
list_add_tail(&dev->list, &ps_devices_list);
mutex_unlock(&ps_devices_lock);
return 0;
}
static int ps_devices_list_remove(struct ps_device *dev)
{
mutex_lock(&ps_devices_lock);
list_del(&dev->list);
mutex_unlock(&ps_devices_lock);
return 0;
}
static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const char *name_suffix) static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const char *name_suffix)
{ {
struct input_dev *input_dev; struct input_dev *input_dev;
...@@ -675,6 +712,10 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) ...@@ -675,6 +712,10 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
} }
snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address); snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address);
ret = ps_devices_list_add(ps_dev);
if (ret)
return ERR_PTR(ret);
ret = dualsense_get_calibration_data(ds); ret = dualsense_get_calibration_data(ds);
if (ret) { if (ret) {
hid_err(hdev, "Failed to get calibration data from DualSense\n"); hid_err(hdev, "Failed to get calibration data from DualSense\n");
...@@ -707,6 +748,7 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) ...@@ -707,6 +748,7 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
return &ds->base; return &ds->base;
err: err:
ps_devices_list_remove(ps_dev);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -764,6 +806,10 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -764,6 +806,10 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
static void ps_remove(struct hid_device *hdev) static void ps_remove(struct hid_device *hdev)
{ {
struct ps_device *dev = hid_get_drvdata(hdev);
ps_devices_list_remove(dev);
hid_hw_close(hdev); hid_hw_close(hdev);
hid_hw_stop(hdev); hid_hw_stop(hdev);
} }
......
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