mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
HID: steam: Retry send/recv reports if stale
Sometimes recv report will reply with a stale result from a previous send report. Instead of failing out, we should retry them, as they generally reply correctly after three tries, give or take. Signed-off-by: Vicki Pfau <vi@endrift.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
parent
33ff7b49c3
commit
fcfa7db89f
|
|
@ -501,6 +501,43 @@ static int steam_write_settings(struct steam_device *steam,
|
|||
return steam_recv_report(steam, cmd, 2 + cmd[1]);
|
||||
}
|
||||
|
||||
static int steam_exchange_report(struct steam_device *steam, u8 *cmd, int csize,
|
||||
u8 *reply, int rsize)
|
||||
{
|
||||
unsigned int retries = 5;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&steam->report_mutex);
|
||||
do {
|
||||
ret = steam_send_report(steam, cmd, csize);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = steam_recv_report(steam, reply, rsize);
|
||||
/*
|
||||
* Sometimes this can fail on the first few tries on the Steam
|
||||
* Controller (2015). It appears to be a firmware bug, and Steam
|
||||
* itself just retries, so we should also retry a few times to
|
||||
* see if we get it.
|
||||
*/
|
||||
if (ret == -EPROTO)
|
||||
continue;
|
||||
if (ret < 0) {
|
||||
hid_err(steam->hdev, "%s: error reading reply (%*ph)\n",
|
||||
__func__, csize, cmd);
|
||||
return ret;
|
||||
}
|
||||
if (reply[0] == cmd[0] && reply[1] >= 1)
|
||||
break;
|
||||
if (retries > 0)
|
||||
continue;
|
||||
hid_err(steam->hdev, "%s: invalid reply (%*ph)\n", __func__,
|
||||
rsize, reply);
|
||||
return -EPROTO;
|
||||
} while (retries--);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int steam_get_serial(struct steam_device *steam)
|
||||
{
|
||||
/*
|
||||
|
|
@ -511,15 +548,10 @@ static int steam_get_serial(struct steam_device *steam)
|
|||
u8 cmd[] = {ID_GET_STRING_ATTRIBUTE, sizeof(steam->serial_no), ATTRIB_STR_UNIT_SERIAL};
|
||||
u8 reply[3 + STEAM_SERIAL_LEN + 1] = {0};
|
||||
|
||||
guard(mutex)(&steam->report_mutex);
|
||||
ret = steam_send_report(steam, cmd, sizeof(cmd));
|
||||
ret = steam_exchange_report(steam, cmd, sizeof(cmd), reply, sizeof(reply));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = steam_recv_report(steam, reply, sizeof(reply));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (reply[0] != ID_GET_STRING_ATTRIBUTE || reply[1] < 1 ||
|
||||
reply[1] > sizeof(steam->serial_no) || reply[2] != ATTRIB_STR_UNIT_SERIAL) {
|
||||
if (reply[1] > sizeof(steam->serial_no) || reply[2] != ATTRIB_STR_UNIT_SERIAL) {
|
||||
hid_err(steam->hdev, "%s: invalid reply (%*ph)\n", __func__,
|
||||
(int)sizeof(reply), reply);
|
||||
return -EIO;
|
||||
|
|
@ -537,14 +569,10 @@ static int steam_get_attributes(struct steam_device *steam)
|
|||
int i;
|
||||
struct steam_controller_attribute *attr;
|
||||
|
||||
guard(mutex)(&steam->report_mutex);
|
||||
ret = steam_send_report(steam, cmd, sizeof(cmd));
|
||||
ret = steam_exchange_report(steam, cmd, sizeof(cmd), reply, sizeof(reply));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = steam_recv_report(steam, reply, sizeof(reply));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (reply[0] != ID_GET_ATTRIBUTES_VALUES || reply[1] < 2) {
|
||||
if (reply[1] < 2) {
|
||||
hid_err(steam->hdev, "%s: invalid reply (%*ph)\n", __func__,
|
||||
(int)sizeof(reply), reply);
|
||||
return -EIO;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user