aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-led.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/hid/hid-led.c b/drivers/hid/hid-led.c
index d8d55f37b4f5..d3e1ab162f7c 100644
--- a/drivers/hid/hid-led.c
+++ b/drivers/hid/hid-led.c
@@ -100,6 +100,7 @@ struct hidled_device {
100 const struct hidled_config *config; 100 const struct hidled_config *config;
101 struct hid_device *hdev; 101 struct hid_device *hdev;
102 struct hidled_rgb *rgb; 102 struct hidled_rgb *rgb;
103 u8 *buf;
103 struct mutex lock; 104 struct mutex lock;
104}; 105};
105 106
@@ -118,13 +119,19 @@ static int hidled_send(struct hidled_device *ldev, __u8 *buf)
118 119
119 mutex_lock(&ldev->lock); 120 mutex_lock(&ldev->lock);
120 121
122 /*
123 * buffer provided to hid_hw_raw_request must not be on the stack
124 * and must not be part of a data structure
125 */
126 memcpy(ldev->buf, buf, ldev->config->report_size);
127
121 if (ldev->config->report_type == RAW_REQUEST) 128 if (ldev->config->report_type == RAW_REQUEST)
122 ret = hid_hw_raw_request(ldev->hdev, buf[0], buf, 129 ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
123 ldev->config->report_size, 130 ldev->config->report_size,
124 HID_FEATURE_REPORT, 131 HID_FEATURE_REPORT,
125 HID_REQ_SET_REPORT); 132 HID_REQ_SET_REPORT);
126 else if (ldev->config->report_type == OUTPUT_REPORT) 133 else if (ldev->config->report_type == OUTPUT_REPORT)
127 ret = hid_hw_output_report(ldev->hdev, buf, 134 ret = hid_hw_output_report(ldev->hdev, ldev->buf,
128 ldev->config->report_size); 135 ldev->config->report_size);
129 else 136 else
130 ret = -EINVAL; 137 ret = -EINVAL;
@@ -147,17 +154,21 @@ static int hidled_recv(struct hidled_device *ldev, __u8 *buf)
147 154
148 mutex_lock(&ldev->lock); 155 mutex_lock(&ldev->lock);
149 156
150 ret = hid_hw_raw_request(ldev->hdev, buf[0], buf, 157 memcpy(ldev->buf, buf, ldev->config->report_size);
158
159 ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
151 ldev->config->report_size, 160 ldev->config->report_size,
152 HID_FEATURE_REPORT, 161 HID_FEATURE_REPORT,
153 HID_REQ_SET_REPORT); 162 HID_REQ_SET_REPORT);
154 if (ret < 0) 163 if (ret < 0)
155 goto err; 164 goto err;
156 165
157 ret = hid_hw_raw_request(ldev->hdev, buf[0], buf, 166 ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
158 ldev->config->report_size, 167 ldev->config->report_size,
159 HID_FEATURE_REPORT, 168 HID_FEATURE_REPORT,
160 HID_REQ_GET_REPORT); 169 HID_REQ_GET_REPORT);
170
171 memcpy(buf, ldev->buf, ldev->config->report_size);
161err: 172err:
162 mutex_unlock(&ldev->lock); 173 mutex_unlock(&ldev->lock);
163 174
@@ -447,6 +458,10 @@ static int hidled_probe(struct hid_device *hdev, const struct hid_device_id *id)
447 if (!ldev) 458 if (!ldev)
448 return -ENOMEM; 459 return -ENOMEM;
449 460
461 ldev->buf = devm_kmalloc(&hdev->dev, MAX_REPORT_SIZE, GFP_KERNEL);
462 if (!ldev->buf)
463 return -ENOMEM;
464
450 ret = hid_parse(hdev); 465 ret = hid_parse(hdev);
451 if (ret) 466 if (ret)
452 return ret; 467 return ret;