aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Praznik <frank.praznik@gmail.com>2016-09-22 20:18:08 -0400
committerJiri Kosina <jkosina@suse.cz>2016-09-26 09:32:47 -0400
commit0f3982308b5fc7373c8d4e6dcfc8a02ee5a3408d (patch)
tree42072fd692ed5f162db242a7e5f30e9ee45b76ca
parent884316deb4c9fdf9becfa31831a9e40717e3026c (diff)
HID: sony: Relax duplicate checking for USB-only devices
Some USB-only devices which masquerade as Sixaxis controllers report the same generic Bluetooth address for all hardware when queried via the HID report. This causes these devices to be wrongly rejected as duplicates when more than one is connected at once. This introduces a connection type comparison when checking for duplicates and only rejects the newly connected device if the existing matching device is connected using a different connection protocol. The results of the connection type comparison are also used when registering power supply info as the device Bluetooth address is used as the unique identifier string. In cases where more than one valid device has the same Bluetooth address the device ID is now appended to the power supply name string to avoid name collisions when registering the power supply information. Signed-off-by: Frank Praznik <frank.praznik@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-sony.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 310436a54a3f..92f27b7d892a 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -65,6 +65,8 @@
65 MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) 65 MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
66#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 66#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
67 MOTION_CONTROLLER) 67 MOTION_CONTROLLER)
68#define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\
69 MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT)
68 70
69#define MAX_LEDS 4 71#define MAX_LEDS 4
70 72
@@ -2039,8 +2041,11 @@ static int sony_battery_get_property(struct power_supply *psy,
2039 return ret; 2041 return ret;
2040} 2042}
2041 2043
2042static int sony_battery_probe(struct sony_sc *sc) 2044static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
2043{ 2045{
2046 const char *battery_str_fmt = append_dev_id ?
2047 "sony_controller_battery_%pMR_%i" :
2048 "sony_controller_battery_%pMR";
2044 struct power_supply_config psy_cfg = { .drv_data = sc, }; 2049 struct power_supply_config psy_cfg = { .drv_data = sc, };
2045 struct hid_device *hdev = sc->hdev; 2050 struct hid_device *hdev = sc->hdev;
2046 int ret; 2051 int ret;
@@ -2056,9 +2061,8 @@ static int sony_battery_probe(struct sony_sc *sc)
2056 sc->battery_desc.get_property = sony_battery_get_property; 2061 sc->battery_desc.get_property = sony_battery_get_property;
2057 sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 2062 sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
2058 sc->battery_desc.use_for_apm = 0; 2063 sc->battery_desc.use_for_apm = 0;
2059 sc->battery_desc.name = kasprintf(GFP_KERNEL, 2064 sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
2060 "sony_controller_battery_%pMR", 2065 sc->mac_address, sc->device_id);
2061 sc->mac_address);
2062 if (!sc->battery_desc.name) 2066 if (!sc->battery_desc.name)
2063 return -ENOMEM; 2067 return -ENOMEM;
2064 2068
@@ -2094,7 +2098,21 @@ static void sony_battery_remove(struct sony_sc *sc)
2094 * it will show up as two devices. A global list of connected controllers and 2098 * it will show up as two devices. A global list of connected controllers and
2095 * their MAC addresses is maintained to ensure that a device is only connected 2099 * their MAC addresses is maintained to ensure that a device is only connected
2096 * once. 2100 * once.
2101 *
2102 * Some USB-only devices masquerade as Sixaxis controllers and all have the
2103 * same dummy Bluetooth address, so a comparison of the connection type is
2104 * required. Devices are only rejected in the case where two devices have
2105 * matching Bluetooth addresses on different bus types.
2097 */ 2106 */
2107static inline int sony_compare_connection_type(struct sony_sc *sc0,
2108 struct sony_sc *sc1)
2109{
2110 const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE);
2111 const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
2112
2113 return sc0_not_bt == sc1_not_bt;
2114}
2115
2098static int sony_check_add_dev_list(struct sony_sc *sc) 2116static int sony_check_add_dev_list(struct sony_sc *sc)
2099{ 2117{
2100 struct sony_sc *entry; 2118 struct sony_sc *entry;
@@ -2107,9 +2125,14 @@ static int sony_check_add_dev_list(struct sony_sc *sc)
2107 ret = memcmp(sc->mac_address, entry->mac_address, 2125 ret = memcmp(sc->mac_address, entry->mac_address,
2108 sizeof(sc->mac_address)); 2126 sizeof(sc->mac_address));
2109 if (!ret) { 2127 if (!ret) {
2110 ret = -EEXIST; 2128 if (sony_compare_connection_type(sc, entry)) {
2111 hid_info(sc->hdev, "controller with MAC address %pMR already connected\n", 2129 ret = 1;
2130 } else {
2131 ret = -EEXIST;
2132 hid_info(sc->hdev,
2133 "controller with MAC address %pMR already connected\n",
2112 sc->mac_address); 2134 sc->mac_address);
2135 }
2113 goto unlock; 2136 goto unlock;
2114 } 2137 }
2115 } 2138 }
@@ -2285,6 +2308,7 @@ static inline void sony_cancel_work_sync(struct sony_sc *sc)
2285static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 2308static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2286{ 2309{
2287 int ret; 2310 int ret;
2311 int append_dev_id;
2288 unsigned long quirks = id->driver_data; 2312 unsigned long quirks = id->driver_data;
2289 struct sony_sc *sc; 2313 struct sony_sc *sc;
2290 unsigned int connect_mask = HID_CONNECT_DEFAULT; 2314 unsigned int connect_mask = HID_CONNECT_DEFAULT;
@@ -2379,7 +2403,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2379 if (ret < 0) 2403 if (ret < 0)
2380 goto err_stop; 2404 goto err_stop;
2381 2405
2382 ret = sony_check_add(sc); 2406 ret = append_dev_id = sony_check_add(sc);
2383 if (ret < 0) 2407 if (ret < 0)
2384 goto err_stop; 2408 goto err_stop;
2385 2409
@@ -2390,7 +2414,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2390 } 2414 }
2391 2415
2392 if (sc->quirks & SONY_BATTERY_SUPPORT) { 2416 if (sc->quirks & SONY_BATTERY_SUPPORT) {
2393 ret = sony_battery_probe(sc); 2417 ret = sony_battery_probe(sc, append_dev_id);
2394 if (ret < 0) 2418 if (ret < 0)
2395 goto err_stop; 2419 goto err_stop;
2396 2420