Input updates for v6.15-rc7
- even more Xbox controllers added to xpad driver: Turtle Beach Recon Wired Controller, Turtle Beach Stealth Ultra, and PowerA Wired Controller - a fix to Synaptics RMI driver to not crash if controller reports unsupported version of F34 (firmware flash) function. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQST2eWILY88ieB2DOtAj56VGEWXnAUCaDJzrQAKCRBAj56VGEWX nJLwAP4zeNCtEIMex8lAmVcLe9smcHuin+kEAKeIwTY3Y3VhKgD9G46WKFz2Ft3A Zc1CVi333GiMNlt0iiW+n+oQAYRPHAk= =X3Z5 -----END PGP SIGNATURE----- Merge tag 'input-for-v6.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input Pull input fixes from Dmitry Torokhov: - even more Xbox controllers added to xpad driver: Turtle Beach Recon Wired Controller, Turtle Beach Stealth Ultra, and PowerA Wired Controller - a fix to Synaptics RMI driver to not crash if controller reports unsupported version of F34 (firmware flash) function * tag 'input-for-v6.15-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: synaptics-rmi - fix crash with unsupported versions of F34 Input: xpad - add more controllers
This commit is contained in:
commit
d0c22de999
2 changed files with 78 additions and 58 deletions
|
@ -290,6 +290,8 @@ static const struct xpad_device {
|
||||||
{ 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
|
{ 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
|
||||||
{ 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
|
{ 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
|
||||||
{ 0x10f5, 0x7005, "Turtle Beach Recon Controller", 0, XTYPE_XBOXONE },
|
{ 0x10f5, 0x7005, "Turtle Beach Recon Controller", 0, XTYPE_XBOXONE },
|
||||||
|
{ 0x10f5, 0x7008, "Turtle Beach Recon Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
||||||
|
{ 0x10f5, 0x7073, "Turtle Beach Stealth Ultra Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
||||||
{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
|
{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
|
||||||
{ 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 },
|
{ 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 },
|
||||||
{ 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
|
{ 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
|
||||||
|
@ -354,6 +356,7 @@ static const struct xpad_device {
|
||||||
{ 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 },
|
{ 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 },
|
||||||
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
|
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
|
||||||
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
|
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
|
||||||
|
{ 0x20d6, 0x2064, "PowerA Wired Controller for Xbox", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
||||||
{ 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
|
{ 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
|
||||||
{ 0x20d6, 0x400b, "PowerA FUSION Pro 4 Wired Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
{ 0x20d6, 0x400b, "PowerA FUSION Pro 4 Wired Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
||||||
{ 0x20d6, 0x890b, "PowerA MOGA XP-Ultra Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
{ 0x20d6, 0x890b, "PowerA MOGA XP-Ultra Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 2016 Zodiac Inflight Innovations
|
* Copyright (C) 2016 Zodiac Inflight Innovations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "linux/device.h"
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/rmi.h>
|
#include <linux/rmi.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
|
@ -289,39 +290,30 @@ static int rmi_f34_update_firmware(struct f34_data *f34,
|
||||||
return rmi_f34_flash_firmware(f34, syn_fw);
|
return rmi_f34_flash_firmware(f34, syn_fw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rmi_f34_status(struct rmi_function *fn)
|
|
||||||
{
|
|
||||||
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The status is the percentage complete, or once complete,
|
|
||||||
* zero for success or a negative return code.
|
|
||||||
*/
|
|
||||||
return f34->update_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t rmi_driver_bootloader_id_show(struct device *dev,
|
static ssize_t rmi_driver_bootloader_id_show(struct device *dev,
|
||||||
struct device_attribute *dattr,
|
struct device_attribute *dattr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
||||||
struct rmi_function *fn = data->f34_container;
|
struct rmi_function *fn;
|
||||||
struct f34_data *f34;
|
struct f34_data *f34;
|
||||||
|
|
||||||
if (fn) {
|
fn = data->f34_container;
|
||||||
f34 = dev_get_drvdata(&fn->dev);
|
if (!fn)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
if (f34->bl_version == 5)
|
f34 = dev_get_drvdata(&fn->dev);
|
||||||
return sysfs_emit(buf, "%c%c\n",
|
if (!f34)
|
||||||
f34->bootloader_id[0],
|
return -ENODEV;
|
||||||
f34->bootloader_id[1]);
|
|
||||||
else
|
|
||||||
return sysfs_emit(buf, "V%d.%d\n",
|
|
||||||
f34->bootloader_id[1],
|
|
||||||
f34->bootloader_id[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
if (f34->bl_version == 5)
|
||||||
|
return sysfs_emit(buf, "%c%c\n",
|
||||||
|
f34->bootloader_id[0],
|
||||||
|
f34->bootloader_id[1]);
|
||||||
|
else
|
||||||
|
return sysfs_emit(buf, "V%d.%d\n",
|
||||||
|
f34->bootloader_id[1],
|
||||||
|
f34->bootloader_id[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(bootloader_id, 0444, rmi_driver_bootloader_id_show, NULL);
|
static DEVICE_ATTR(bootloader_id, 0444, rmi_driver_bootloader_id_show, NULL);
|
||||||
|
@ -334,13 +326,16 @@ static ssize_t rmi_driver_configuration_id_show(struct device *dev,
|
||||||
struct rmi_function *fn = data->f34_container;
|
struct rmi_function *fn = data->f34_container;
|
||||||
struct f34_data *f34;
|
struct f34_data *f34;
|
||||||
|
|
||||||
if (fn) {
|
fn = data->f34_container;
|
||||||
f34 = dev_get_drvdata(&fn->dev);
|
if (!fn)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
return sysfs_emit(buf, "%s\n", f34->configuration_id);
|
f34 = dev_get_drvdata(&fn->dev);
|
||||||
}
|
if (!f34)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
return sysfs_emit(buf, "%s\n", f34->configuration_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(configuration_id, 0444,
|
static DEVICE_ATTR(configuration_id, 0444,
|
||||||
|
@ -356,10 +351,14 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
|
||||||
|
|
||||||
if (!data->f34_container) {
|
if (!data->f34_container) {
|
||||||
dev_warn(dev, "%s: No F34 present!\n", __func__);
|
dev_warn(dev, "%s: No F34 present!\n", __func__);
|
||||||
return -EINVAL;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
f34 = dev_get_drvdata(&data->f34_container->dev);
|
f34 = dev_get_drvdata(&data->f34_container->dev);
|
||||||
|
if (!f34) {
|
||||||
|
dev_warn(dev, "%s: No valid F34 present!\n", __func__);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
if (f34->bl_version >= 7) {
|
if (f34->bl_version >= 7) {
|
||||||
if (data->pdt_props & HAS_BSR) {
|
if (data->pdt_props & HAS_BSR) {
|
||||||
|
@ -485,10 +484,18 @@ static ssize_t rmi_driver_update_fw_status_show(struct device *dev,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
struct rmi_driver_data *data = dev_get_drvdata(dev);
|
||||||
int update_status = 0;
|
struct f34_data *f34;
|
||||||
|
int update_status = -ENODEV;
|
||||||
|
|
||||||
if (data->f34_container)
|
/*
|
||||||
update_status = rmi_f34_status(data->f34_container);
|
* The status is the percentage complete, or once complete,
|
||||||
|
* zero for success or a negative return code.
|
||||||
|
*/
|
||||||
|
if (data->f34_container) {
|
||||||
|
f34 = dev_get_drvdata(&data->f34_container->dev);
|
||||||
|
if (f34)
|
||||||
|
update_status = f34->update_status;
|
||||||
|
}
|
||||||
|
|
||||||
return sysfs_emit(buf, "%d\n", update_status);
|
return sysfs_emit(buf, "%d\n", update_status);
|
||||||
}
|
}
|
||||||
|
@ -508,33 +515,21 @@ static const struct attribute_group rmi_firmware_attr_group = {
|
||||||
.attrs = rmi_firmware_attrs,
|
.attrs = rmi_firmware_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int rmi_f34_probe(struct rmi_function *fn)
|
static int rmi_f34v5_probe(struct f34_data *f34)
|
||||||
{
|
{
|
||||||
struct f34_data *f34;
|
struct rmi_function *fn = f34->fn;
|
||||||
unsigned char f34_queries[9];
|
u8 f34_queries[9];
|
||||||
bool has_config_id;
|
bool has_config_id;
|
||||||
u8 version = fn->fd.function_version;
|
int error;
|
||||||
int ret;
|
|
||||||
|
|
||||||
f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL);
|
|
||||||
if (!f34)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
f34->fn = fn;
|
|
||||||
dev_set_drvdata(&fn->dev, f34);
|
|
||||||
|
|
||||||
/* v5 code only supported version 0, try V7 probe */
|
|
||||||
if (version > 0)
|
|
||||||
return rmi_f34v7_probe(f34);
|
|
||||||
|
|
||||||
f34->bl_version = 5;
|
f34->bl_version = 5;
|
||||||
|
|
||||||
ret = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
|
error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
|
||||||
f34_queries, sizeof(f34_queries));
|
f34_queries, sizeof(f34_queries));
|
||||||
if (ret) {
|
if (error) {
|
||||||
dev_err(&fn->dev, "%s: Failed to query properties\n",
|
dev_err(&fn->dev, "%s: Failed to query properties\n",
|
||||||
__func__);
|
__func__);
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(f34->bootloader_id, sizeof(f34->bootloader_id),
|
snprintf(f34->bootloader_id, sizeof(f34->bootloader_id),
|
||||||
|
@ -560,11 +555,11 @@ static int rmi_f34_probe(struct rmi_function *fn)
|
||||||
f34->v5.config_blocks);
|
f34->v5.config_blocks);
|
||||||
|
|
||||||
if (has_config_id) {
|
if (has_config_id) {
|
||||||
ret = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
|
error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
|
||||||
f34_queries, sizeof(f34_queries));
|
f34_queries, sizeof(f34_queries));
|
||||||
if (ret) {
|
if (error) {
|
||||||
dev_err(&fn->dev, "Failed to read F34 config ID\n");
|
dev_err(&fn->dev, "Failed to read F34 config ID\n");
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(f34->configuration_id, sizeof(f34->configuration_id),
|
snprintf(f34->configuration_id, sizeof(f34->configuration_id),
|
||||||
|
@ -573,12 +568,34 @@ static int rmi_f34_probe(struct rmi_function *fn)
|
||||||
f34_queries[2], f34_queries[3]);
|
f34_queries[2], f34_queries[3]);
|
||||||
|
|
||||||
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Configuration ID: %s\n",
|
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Configuration ID: %s\n",
|
||||||
f34->configuration_id);
|
f34->configuration_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rmi_f34_probe(struct rmi_function *fn)
|
||||||
|
{
|
||||||
|
struct f34_data *f34;
|
||||||
|
u8 version = fn->fd.function_version;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL);
|
||||||
|
if (!f34)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
f34->fn = fn;
|
||||||
|
|
||||||
|
/* v5 code only supported version 0 */
|
||||||
|
error = version == 0 ? rmi_f34v5_probe(f34) : rmi_f34v7_probe(f34);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
dev_set_drvdata(&fn->dev, f34);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
|
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
|
||||||
{
|
{
|
||||||
return sysfs_create_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
|
return sysfs_create_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue