Commit e2b6535d authored by Linus Torvalds's avatar Linus Torvalds

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
parents 18594e9b d443a0aa
...@@ -32,6 +32,11 @@ ...@@ -32,6 +32,11 @@
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include "hid-ids.h" #include "hid-ids.h"
#define CP2112_REPORT_MAX_LENGTH 64
#define CP2112_GPIO_CONFIG_LENGTH 5
#define CP2112_GPIO_GET_LENGTH 2
#define CP2112_GPIO_SET_LENGTH 3
enum { enum {
CP2112_GPIO_CONFIG = 0x02, CP2112_GPIO_CONFIG = 0x02,
CP2112_GPIO_GET = 0x03, CP2112_GPIO_GET = 0x03,
...@@ -161,6 +166,8 @@ struct cp2112_device { ...@@ -161,6 +166,8 @@ struct cp2112_device {
atomic_t read_avail; atomic_t read_avail;
atomic_t xfer_avail; atomic_t xfer_avail;
struct gpio_chip gc; struct gpio_chip gc;
u8 *in_out_buffer;
spinlock_t lock;
}; };
static int gpio_push_pull = 0xFF; static int gpio_push_pull = 0xFF;
...@@ -171,62 +178,86 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -171,62 +178,86 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{ {
struct cp2112_device *dev = gpiochip_get_data(chip); struct cp2112_device *dev = gpiochip_get_data(chip);
struct hid_device *hdev = dev->hdev; struct hid_device *hdev = dev->hdev;
u8 buf[5]; u8 *buf = dev->in_out_buffer;
unsigned long flags;
int ret; int ret;
spin_lock_irqsave(&dev->lock, flags);
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
sizeof(buf), HID_FEATURE_REPORT, CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT); HID_REQ_GET_REPORT);
if (ret != sizeof(buf)) { if (ret != CP2112_GPIO_CONFIG_LENGTH) {
hid_err(hdev, "error requesting GPIO config: %d\n", ret); hid_err(hdev, "error requesting GPIO config: %d\n", ret);
return ret; goto exit;
} }
buf[1] &= ~(1 << offset); buf[1] &= ~(1 << offset);
buf[2] = gpio_push_pull; buf[2] = gpio_push_pull;
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, sizeof(buf), ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
HID_REQ_SET_REPORT);
if (ret < 0) { if (ret < 0) {
hid_err(hdev, "error setting GPIO config: %d\n", ret); hid_err(hdev, "error setting GPIO config: %d\n", ret);
return ret; goto exit;
} }
return 0; ret = 0;
exit:
spin_unlock_irqrestore(&dev->lock, flags);
return ret <= 0 ? ret : -EIO;
} }
static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
struct cp2112_device *dev = gpiochip_get_data(chip); struct cp2112_device *dev = gpiochip_get_data(chip);
struct hid_device *hdev = dev->hdev; struct hid_device *hdev = dev->hdev;
u8 buf[3]; u8 *buf = dev->in_out_buffer;
unsigned long flags;
int ret; int ret;
spin_lock_irqsave(&dev->lock, flags);
buf[0] = CP2112_GPIO_SET; buf[0] = CP2112_GPIO_SET;
buf[1] = value ? 0xff : 0; buf[1] = value ? 0xff : 0;
buf[2] = 1 << offset; buf[2] = 1 << offset;
ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf, sizeof(buf), ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); CP2112_GPIO_SET_LENGTH, HID_FEATURE_REPORT,
HID_REQ_SET_REPORT);
if (ret < 0) if (ret < 0)
hid_err(hdev, "error setting GPIO values: %d\n", ret); hid_err(hdev, "error setting GPIO values: %d\n", ret);
spin_unlock_irqrestore(&dev->lock, flags);
} }
static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset) static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
struct cp2112_device *dev = gpiochip_get_data(chip); struct cp2112_device *dev = gpiochip_get_data(chip);
struct hid_device *hdev = dev->hdev; struct hid_device *hdev = dev->hdev;
u8 buf[2]; u8 *buf = dev->in_out_buffer;
unsigned long flags;
int ret; int ret;
ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf, sizeof(buf), spin_lock_irqsave(&dev->lock, flags);
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (ret != sizeof(buf)) { ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret != CP2112_GPIO_GET_LENGTH) {
hid_err(hdev, "error requesting GPIO values: %d\n", ret); hid_err(hdev, "error requesting GPIO values: %d\n", ret);
return ret; ret = ret < 0 ? ret : -EIO;
goto exit;
} }
return (buf[1] >> offset) & 1; ret = (buf[1] >> offset) & 1;
exit:
spin_unlock_irqrestore(&dev->lock, flags);
return ret;
} }
static int cp2112_gpio_direction_output(struct gpio_chip *chip, static int cp2112_gpio_direction_output(struct gpio_chip *chip,
...@@ -234,27 +265,33 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip, ...@@ -234,27 +265,33 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
{ {
struct cp2112_device *dev = gpiochip_get_data(chip); struct cp2112_device *dev = gpiochip_get_data(chip);
struct hid_device *hdev = dev->hdev; struct hid_device *hdev = dev->hdev;
u8 buf[5]; u8 *buf = dev->in_out_buffer;
unsigned long flags;
int ret; int ret;
spin_lock_irqsave(&dev->lock, flags);
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
sizeof(buf), HID_FEATURE_REPORT, CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT); HID_REQ_GET_REPORT);
if (ret != sizeof(buf)) { if (ret != CP2112_GPIO_CONFIG_LENGTH) {
hid_err(hdev, "error requesting GPIO config: %d\n", ret); hid_err(hdev, "error requesting GPIO config: %d\n", ret);
return ret; goto fail;
} }
buf[1] |= 1 << offset; buf[1] |= 1 << offset;
buf[2] = gpio_push_pull; buf[2] = gpio_push_pull;
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, sizeof(buf), ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
HID_REQ_SET_REPORT);
if (ret < 0) { if (ret < 0) {
hid_err(hdev, "error setting GPIO config: %d\n", ret); hid_err(hdev, "error setting GPIO config: %d\n", ret);
return ret; goto fail;
} }
spin_unlock_irqrestore(&dev->lock, flags);
/* /*
* Set gpio value when output direction is already set, * Set gpio value when output direction is already set,
* as specified in AN495, Rev. 0.2, cpt. 4.4 * as specified in AN495, Rev. 0.2, cpt. 4.4
...@@ -262,6 +299,10 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip, ...@@ -262,6 +299,10 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
cp2112_gpio_set(chip, offset, value); cp2112_gpio_set(chip, offset, value);
return 0; return 0;
fail:
spin_unlock_irqrestore(&dev->lock, flags);
return ret < 0 ? ret : -EIO;
} }
static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number, 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) ...@@ -1007,6 +1048,17 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
struct cp2112_smbus_config_report config; struct cp2112_smbus_config_report config;
int ret; int ret;
dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->in_out_buffer = devm_kzalloc(&hdev->dev, CP2112_REPORT_MAX_LENGTH,
GFP_KERNEL);
if (!dev->in_out_buffer)
return -ENOMEM;
spin_lock_init(&dev->lock);
ret = hid_parse(hdev); ret = hid_parse(hdev);
if (ret) { if (ret) {
hid_err(hdev, "parse failed\n"); hid_err(hdev, "parse failed\n");
...@@ -1063,12 +1115,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1063,12 +1115,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_power_normal; goto err_power_normal;
} }
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto err_power_normal;
}
hid_set_drvdata(hdev, (void *)dev); hid_set_drvdata(hdev, (void *)dev);
dev->hdev = hdev; dev->hdev = hdev;
dev->adap.owner = THIS_MODULE; dev->adap.owner = THIS_MODULE;
...@@ -1087,7 +1133,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1087,7 +1133,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret) { if (ret) {
hid_err(hdev, "error registering i2c adapter\n"); hid_err(hdev, "error registering i2c adapter\n");
goto err_free_dev; goto err_power_normal;
} }
hid_dbg(hdev, "adapter registered\n"); hid_dbg(hdev, "adapter registered\n");
...@@ -1123,8 +1169,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1123,8 +1169,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
gpiochip_remove(&dev->gc); gpiochip_remove(&dev->gc);
err_free_i2c: err_free_i2c:
i2c_del_adapter(&dev->adap); i2c_del_adapter(&dev->adap);
err_free_dev:
kfree(dev);
err_power_normal: err_power_normal:
hid_hw_power(hdev, PM_HINT_NORMAL); hid_hw_power(hdev, PM_HINT_NORMAL);
err_hid_close: err_hid_close:
...@@ -1149,7 +1193,6 @@ static void cp2112_remove(struct hid_device *hdev) ...@@ -1149,7 +1193,6 @@ static void cp2112_remove(struct hid_device *hdev)
*/ */
hid_hw_close(hdev); hid_hw_close(hdev);
hid_hw_stop(hdev); hid_hw_stop(hdev);
kfree(dev);
} }
static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report, static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,
......
...@@ -756,11 +756,16 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -756,11 +756,16 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
/* Setup wireless link with Logitech Wii wheel */ /* Setup wireless link with Logitech Wii wheel */
if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char cbuf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), if (!buf) {
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); ret = -ENOMEM;
goto err_free;
}
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (ret >= 0) { if (ret >= 0) {
/* insert a little delay of 10 jiffies ~ 40ms */ /* insert a little delay of 10 jiffies ~ 40ms */
wait_queue_head_t wait; wait_queue_head_t wait;
...@@ -772,9 +777,10 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -772,9 +777,10 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
buf[1] = 0xB2; buf[1] = 0xB2;
get_random_bytes(&buf[2], 2); get_random_bytes(&buf[2], 2);
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
} }
kfree(buf);
} }
if (drv_data->quirks & LG_FF) if (drv_data->quirks & LG_FF)
......
...@@ -493,7 +493,8 @@ static int magicmouse_input_configured(struct hid_device *hdev, ...@@ -493,7 +493,8 @@ static int magicmouse_input_configured(struct hid_device *hdev,
static int magicmouse_probe(struct hid_device *hdev, static int magicmouse_probe(struct hid_device *hdev,
const struct hid_device_id *id) const struct hid_device_id *id)
{ {
__u8 feature[] = { 0xd7, 0x01 }; const u8 feature[] = { 0xd7, 0x01 };
u8 *buf;
struct magicmouse_sc *msc; struct magicmouse_sc *msc;
struct hid_report *report; struct hid_report *report;
int ret; int ret;
...@@ -544,6 +545,12 @@ static int magicmouse_probe(struct hid_device *hdev, ...@@ -544,6 +545,12 @@ static int magicmouse_probe(struct hid_device *hdev,
} }
report->size = 6; report->size = 6;
buf = kmemdup(feature, sizeof(feature), GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto err_stop_hw;
}
/* /*
* Some devices repond with 'invalid report id' when feature * Some devices repond with 'invalid report id' when feature
* report switching it into multitouch mode is sent to it. * report switching it into multitouch mode is sent to it.
...@@ -552,8 +559,9 @@ static int magicmouse_probe(struct hid_device *hdev, ...@@ -552,8 +559,9 @@ static int magicmouse_probe(struct hid_device *hdev,
* but there seems to be no other way of switching the mode. * but there seems to be no other way of switching the mode.
* Thus the super-ugly hacky success check below. * Thus the super-ugly hacky success check below.
*/ */
ret = hid_hw_raw_request(hdev, feature[0], feature, sizeof(feature), ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(feature),
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
kfree(buf);
if (ret != -EIO && ret != sizeof(feature)) { if (ret != -EIO && ret != sizeof(feature)) {
hid_err(hdev, "unable to request touch data (%d)\n", ret); hid_err(hdev, "unable to request touch data (%d)\n", ret);
goto err_stop_hw; goto err_stop_hw;
......
...@@ -188,10 +188,16 @@ static int rmi_set_page(struct hid_device *hdev, u8 page) ...@@ -188,10 +188,16 @@ static int rmi_set_page(struct hid_device *hdev, u8 page)
static int rmi_set_mode(struct hid_device *hdev, u8 mode) static int rmi_set_mode(struct hid_device *hdev, u8 mode)
{ {
int ret; int ret;
u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode}; const u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode};
u8 *buf;
ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, txbuf, buf = kmemdup(txbuf, sizeof(txbuf), GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, buf,
sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
kfree(buf);
if (ret < 0) { if (ret < 0) {
dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode, dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode,
ret); ret);
......
...@@ -212,6 +212,7 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, ...@@ -212,6 +212,7 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
__s32 value; __s32 value;
int ret = 0; int ret = 0;
memset(buffer, 0, buffer_size);
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
if (!report || (field_index >= report->maxfield)) { if (!report || (field_index >= report->maxfield)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment