Skip to content

Commit e2b6535

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID fixes from Jiri Kosina: - DMA-on-stack fixes for a couple drivers, from Benjamin Tissoires - small memory sanitization fix for sensor-hub driver, from Song Hongyan * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: hid-sensor-hub: clear memory to avoid random data HID: rmi: make transfer buffers DMA capable HID: magicmouse: make transfer buffers DMA capable HID: lg: make transfer buffers DMA capable HID: cp2112: make transfer buffers DMA capable
2 parents 18594e9 + d443a0a commit e2b6535

File tree

5 files changed

+108
-44
lines changed

5 files changed

+108
-44
lines changed

drivers/hid/hid-cp2112.c

Lines changed: 79 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
#include <linux/usb/ch9.h>
3333
#include "hid-ids.h"
3434

35+
#define CP2112_REPORT_MAX_LENGTH 64
36+
#define CP2112_GPIO_CONFIG_LENGTH 5
37+
#define CP2112_GPIO_GET_LENGTH 2
38+
#define CP2112_GPIO_SET_LENGTH 3
39+
3540
enum {
3641
CP2112_GPIO_CONFIG = 0x02,
3742
CP2112_GPIO_GET = 0x03,
@@ -161,6 +166,8 @@ struct cp2112_device {
161166
atomic_t read_avail;
162167
atomic_t xfer_avail;
163168
struct gpio_chip gc;
169+
u8 *in_out_buffer;
170+
spinlock_t lock;
164171
};
165172

166173
static int gpio_push_pull = 0xFF;
@@ -171,97 +178,131 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
171178
{
172179
struct cp2112_device *dev = gpiochip_get_data(chip);
173180
struct hid_device *hdev = dev->hdev;
174-
u8 buf[5];
181+
u8 *buf = dev->in_out_buffer;
182+
unsigned long flags;
175183
int ret;
176184

185+
spin_lock_irqsave(&dev->lock, flags);
186+
177187
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
178-
sizeof(buf), HID_FEATURE_REPORT,
179-
HID_REQ_GET_REPORT);
180-
if (ret != sizeof(buf)) {
188+
CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
189+
HID_REQ_GET_REPORT);
190+
if (ret != CP2112_GPIO_CONFIG_LENGTH) {
181191
hid_err(hdev, "error requesting GPIO config: %d\n", ret);
182-
return ret;
192+
goto exit;
183193
}
184194

185195
buf[1] &= ~(1 << offset);
186196
buf[2] = gpio_push_pull;
187197

188-
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, sizeof(buf),
189-
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
198+
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
199+
CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
200+
HID_REQ_SET_REPORT);
190201
if (ret < 0) {
191202
hid_err(hdev, "error setting GPIO config: %d\n", ret);
192-
return ret;
203+
goto exit;
193204
}
194205

195-
return 0;
206+
ret = 0;
207+
208+
exit:
209+
spin_unlock_irqrestore(&dev->lock, flags);
210+
return ret <= 0 ? ret : -EIO;
196211
}
197212

198213
static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
199214
{
200215
struct cp2112_device *dev = gpiochip_get_data(chip);
201216
struct hid_device *hdev = dev->hdev;
202-
u8 buf[3];
217+
u8 *buf = dev->in_out_buffer;
218+
unsigned long flags;
203219
int ret;
204220

221+
spin_lock_irqsave(&dev->lock, flags);
222+
205223
buf[0] = CP2112_GPIO_SET;
206224
buf[1] = value ? 0xff : 0;
207225
buf[2] = 1 << offset;
208226

209-
ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf, sizeof(buf),
210-
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
227+
ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf,
228+
CP2112_GPIO_SET_LENGTH, HID_FEATURE_REPORT,
229+
HID_REQ_SET_REPORT);
211230
if (ret < 0)
212231
hid_err(hdev, "error setting GPIO values: %d\n", ret);
232+
233+
spin_unlock_irqrestore(&dev->lock, flags);
213234
}
214235

215236
static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset)
216237
{
217238
struct cp2112_device *dev = gpiochip_get_data(chip);
218239
struct hid_device *hdev = dev->hdev;
219-
u8 buf[2];
240+
u8 *buf = dev->in_out_buffer;
241+
unsigned long flags;
220242
int ret;
221243

222-
ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf, sizeof(buf),
223-
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
224-
if (ret != sizeof(buf)) {
244+
spin_lock_irqsave(&dev->lock, flags);
245+
246+
ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
247+
CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
248+
HID_REQ_GET_REPORT);
249+
if (ret != CP2112_GPIO_GET_LENGTH) {
225250
hid_err(hdev, "error requesting GPIO values: %d\n", ret);
226-
return ret;
251+
ret = ret < 0 ? ret : -EIO;
252+
goto exit;
227253
}
228254

229-
return (buf[1] >> offset) & 1;
255+
ret = (buf[1] >> offset) & 1;
256+
257+
exit:
258+
spin_unlock_irqrestore(&dev->lock, flags);
259+
260+
return ret;
230261
}
231262

232263
static int cp2112_gpio_direction_output(struct gpio_chip *chip,
233264
unsigned offset, int value)
234265
{
235266
struct cp2112_device *dev = gpiochip_get_data(chip);
236267
struct hid_device *hdev = dev->hdev;
237-
u8 buf[5];
268+
u8 *buf = dev->in_out_buffer;
269+
unsigned long flags;
238270
int ret;
239271

272+
spin_lock_irqsave(&dev->lock, flags);
273+
240274
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
241-
sizeof(buf), HID_FEATURE_REPORT,
242-
HID_REQ_GET_REPORT);
243-
if (ret != sizeof(buf)) {
275+
CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
276+
HID_REQ_GET_REPORT);
277+
if (ret != CP2112_GPIO_CONFIG_LENGTH) {
244278
hid_err(hdev, "error requesting GPIO config: %d\n", ret);
245-
return ret;
279+
goto fail;
246280
}
247281

248282
buf[1] |= 1 << offset;
249283
buf[2] = gpio_push_pull;
250284

251-
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, sizeof(buf),
252-
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
285+
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
286+
CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
287+
HID_REQ_SET_REPORT);
253288
if (ret < 0) {
254289
hid_err(hdev, "error setting GPIO config: %d\n", ret);
255-
return ret;
290+
goto fail;
256291
}
257292

293+
spin_unlock_irqrestore(&dev->lock, flags);
294+
258295
/*
259296
* Set gpio value when output direction is already set,
260297
* as specified in AN495, Rev. 0.2, cpt. 4.4
261298
*/
262299
cp2112_gpio_set(chip, offset, value);
263300

264301
return 0;
302+
303+
fail:
304+
spin_unlock_irqrestore(&dev->lock, flags);
305+
return ret < 0 ? ret : -EIO;
265306
}
266307

267308
static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number,
@@ -1007,6 +1048,17 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10071048
struct cp2112_smbus_config_report config;
10081049
int ret;
10091050

1051+
dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
1052+
if (!dev)
1053+
return -ENOMEM;
1054+
1055+
dev->in_out_buffer = devm_kzalloc(&hdev->dev, CP2112_REPORT_MAX_LENGTH,
1056+
GFP_KERNEL);
1057+
if (!dev->in_out_buffer)
1058+
return -ENOMEM;
1059+
1060+
spin_lock_init(&dev->lock);
1061+
10101062
ret = hid_parse(hdev);
10111063
if (ret) {
10121064
hid_err(hdev, "parse failed\n");
@@ -1063,12 +1115,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10631115
goto err_power_normal;
10641116
}
10651117

1066-
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1067-
if (!dev) {
1068-
ret = -ENOMEM;
1069-
goto err_power_normal;
1070-
}
1071-
10721118
hid_set_drvdata(hdev, (void *)dev);
10731119
dev->hdev = hdev;
10741120
dev->adap.owner = THIS_MODULE;
@@ -1087,7 +1133,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10871133

10881134
if (ret) {
10891135
hid_err(hdev, "error registering i2c adapter\n");
1090-
goto err_free_dev;
1136+
goto err_power_normal;
10911137
}
10921138

10931139
hid_dbg(hdev, "adapter registered\n");
@@ -1123,8 +1169,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
11231169
gpiochip_remove(&dev->gc);
11241170
err_free_i2c:
11251171
i2c_del_adapter(&dev->adap);
1126-
err_free_dev:
1127-
kfree(dev);
11281172
err_power_normal:
11291173
hid_hw_power(hdev, PM_HINT_NORMAL);
11301174
err_hid_close:
@@ -1149,7 +1193,6 @@ static void cp2112_remove(struct hid_device *hdev)
11491193
*/
11501194
hid_hw_close(hdev);
11511195
hid_hw_stop(hdev);
1152-
kfree(dev);
11531196
}
11541197

11551198
static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,

drivers/hid/hid-lg.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,16 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
756756

757757
/* Setup wireless link with Logitech Wii wheel */
758758
if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
759-
unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
759+
const unsigned char cbuf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
760+
u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
760761

761-
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
762-
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
762+
if (!buf) {
763+
ret = -ENOMEM;
764+
goto err_free;
765+
}
763766

767+
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
768+
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
764769
if (ret >= 0) {
765770
/* insert a little delay of 10 jiffies ~ 40ms */
766771
wait_queue_head_t wait;
@@ -772,9 +777,10 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
772777
buf[1] = 0xB2;
773778
get_random_bytes(&buf[2], 2);
774779

775-
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
780+
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
776781
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
777782
}
783+
kfree(buf);
778784
}
779785

780786
if (drv_data->quirks & LG_FF)

drivers/hid/hid-magicmouse.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,8 @@ static int magicmouse_input_configured(struct hid_device *hdev,
493493
static int magicmouse_probe(struct hid_device *hdev,
494494
const struct hid_device_id *id)
495495
{
496-
__u8 feature[] = { 0xd7, 0x01 };
496+
const u8 feature[] = { 0xd7, 0x01 };
497+
u8 *buf;
497498
struct magicmouse_sc *msc;
498499
struct hid_report *report;
499500
int ret;
@@ -544,6 +545,12 @@ static int magicmouse_probe(struct hid_device *hdev,
544545
}
545546
report->size = 6;
546547

548+
buf = kmemdup(feature, sizeof(feature), GFP_KERNEL);
549+
if (!buf) {
550+
ret = -ENOMEM;
551+
goto err_stop_hw;
552+
}
553+
547554
/*
548555
* Some devices repond with 'invalid report id' when feature
549556
* report switching it into multitouch mode is sent to it.
@@ -552,8 +559,9 @@ static int magicmouse_probe(struct hid_device *hdev,
552559
* but there seems to be no other way of switching the mode.
553560
* Thus the super-ugly hacky success check below.
554561
*/
555-
ret = hid_hw_raw_request(hdev, feature[0], feature, sizeof(feature),
562+
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(feature),
556563
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
564+
kfree(buf);
557565
if (ret != -EIO && ret != sizeof(feature)) {
558566
hid_err(hdev, "unable to request touch data (%d)\n", ret);
559567
goto err_stop_hw;

drivers/hid/hid-rmi.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,16 @@ static int rmi_set_page(struct hid_device *hdev, u8 page)
188188
static int rmi_set_mode(struct hid_device *hdev, u8 mode)
189189
{
190190
int ret;
191-
u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode};
191+
const u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode};
192+
u8 *buf;
192193

193-
ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, txbuf,
194+
buf = kmemdup(txbuf, sizeof(txbuf), GFP_KERNEL);
195+
if (!buf)
196+
return -ENOMEM;
197+
198+
ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, buf,
194199
sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
200+
kfree(buf);
195201
if (ret < 0) {
196202
dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode,
197203
ret);

drivers/hid/hid-sensor-hub.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
212212
__s32 value;
213213
int ret = 0;
214214

215+
memset(buffer, 0, buffer_size);
215216
mutex_lock(&data->mutex);
216217
report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
217218
if (!report || (field_index >= report->maxfield)) {

0 commit comments

Comments
 (0)