Skip to content

Commit 43a4a04

Browse files
hkallweitJiri Kosina
authored andcommitted
HID: thingm: improve locking
Reading from the device consists of two operations: sending the read command and the actual read from the device. If the device is accessed in between we might read wrong data. Therefore protect the full sequence of both operations with a mutex. Also change the semantics of thingm_recv to include both operations. Signed-off-by: Heiner Kallweit <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent c46fab2 commit 43a4a04

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

drivers/hid/hid-thingm.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,37 +77,52 @@ static int thingm_send(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
7777
buf[0], buf[1], buf[2], buf[3], buf[4],
7878
buf[5], buf[6], buf[7], buf[8]);
7979

80+
mutex_lock(&tdev->lock);
81+
8082
ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
8183
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
8284

85+
mutex_unlock(&tdev->lock);
86+
8387
return ret < 0 ? ret : 0;
8488
}
8589

8690
static int thingm_recv(struct thingm_device *tdev, u8 buf[REPORT_SIZE])
8791
{
8892
int ret;
8993

94+
/*
95+
* A read consists of two operations: sending the read command
96+
* and the actual read from the device. Use the mutex to protect
97+
* the full sequence of both operations.
98+
*/
99+
mutex_lock(&tdev->lock);
100+
101+
ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
102+
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
103+
if (ret < 0)
104+
goto err;
105+
90106
ret = hid_hw_raw_request(tdev->hdev, buf[0], buf, REPORT_SIZE,
91107
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
92108
if (ret < 0)
93-
return ret;
109+
goto err;
110+
111+
ret = 0;
94112

95113
hid_dbg(tdev->hdev, "<- %d %c %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n",
96114
buf[0], buf[1], buf[2], buf[3], buf[4],
97115
buf[5], buf[6], buf[7], buf[8]);
98-
99-
return 0;
116+
err:
117+
mutex_unlock(&tdev->lock);
118+
return ret;
100119
}
101120

102121
static int thingm_version(struct thingm_device *tdev)
103122
{
104123
u8 buf[REPORT_SIZE] = { REPORT_ID, 'v', 0, 0, 0, 0, 0, 0, 0 };
105124
int err;
106125

107-
err = thingm_send(tdev, buf);
108-
if (err)
109-
return err;
110-
111126
err = thingm_recv(tdev, buf);
112127
if (err)
113128
return err;
@@ -135,14 +150,10 @@ static int thingm_led_set(struct led_classdev *ldev,
135150
struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);
136151
int ret;
137152

138-
mutex_lock(&led->rgb->tdev->lock);
139-
140153
ret = thingm_write_color(led->rgb);
141154
if (ret)
142155
hid_err(led->rgb->tdev->hdev, "failed to write color\n");
143156

144-
mutex_unlock(&led->rgb->tdev->lock);
145-
146157
return ret;
147158
}
148159

0 commit comments

Comments
 (0)