mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 09:56:46 +00:00
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: Roderick Colenbrander <roderick.colenbrander@sony.com> Reviewed-by: Barnabás Pőcze <pobrn@protonmail.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
This commit is contained in:
parent
402987c5d9
commit
53f04e8357
@ -15,10 +15,15 @@
|
||||
|
||||
#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
|
||||
|
||||
/* Base class for playstation devices. */
|
||||
struct ps_device {
|
||||
struct list_head list;
|
||||
struct hid_device *hdev;
|
||||
spinlock_t lock;
|
||||
|
||||
@ -160,6 +165,38 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
|
||||
{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)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
@ -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);
|
||||
|
||||
ret = ps_devices_list_add(ps_dev);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = dualsense_get_calibration_data(ds);
|
||||
if (ret) {
|
||||
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)
|
||||
return &ds->base;
|
||||
|
||||
err:
|
||||
ps_devices_list_remove(ps_dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
@ -764,6 +806,10 @@ err_stop:
|
||||
|
||||
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_stop(hdev);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user