|
@@ -100,6 +100,7 @@ struct hidled_device {
|
|
const struct hidled_config *config;
|
|
const struct hidled_config *config;
|
|
struct hid_device *hdev;
|
|
struct hid_device *hdev;
|
|
struct hidled_rgb *rgb;
|
|
struct hidled_rgb *rgb;
|
|
|
|
+ u8 *buf;
|
|
struct mutex lock;
|
|
struct mutex lock;
|
|
};
|
|
};
|
|
|
|
|
|
@@ -118,13 +119,19 @@ static int hidled_send(struct hidled_device *ldev, __u8 *buf)
|
|
|
|
|
|
mutex_lock(&ldev->lock);
|
|
mutex_lock(&ldev->lock);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * buffer provided to hid_hw_raw_request must not be on the stack
|
|
|
|
+ * and must not be part of a data structure
|
|
|
|
+ */
|
|
|
|
+ memcpy(ldev->buf, buf, ldev->config->report_size);
|
|
|
|
+
|
|
if (ldev->config->report_type == RAW_REQUEST)
|
|
if (ldev->config->report_type == RAW_REQUEST)
|
|
- ret = hid_hw_raw_request(ldev->hdev, buf[0], buf,
|
|
|
|
|
|
+ ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
|
|
ldev->config->report_size,
|
|
ldev->config->report_size,
|
|
HID_FEATURE_REPORT,
|
|
HID_FEATURE_REPORT,
|
|
HID_REQ_SET_REPORT);
|
|
HID_REQ_SET_REPORT);
|
|
else if (ldev->config->report_type == OUTPUT_REPORT)
|
|
else if (ldev->config->report_type == OUTPUT_REPORT)
|
|
- ret = hid_hw_output_report(ldev->hdev, buf,
|
|
|
|
|
|
+ ret = hid_hw_output_report(ldev->hdev, ldev->buf,
|
|
ldev->config->report_size);
|
|
ldev->config->report_size);
|
|
else
|
|
else
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
@@ -147,17 +154,21 @@ static int hidled_recv(struct hidled_device *ldev, __u8 *buf)
|
|
|
|
|
|
mutex_lock(&ldev->lock);
|
|
mutex_lock(&ldev->lock);
|
|
|
|
|
|
- ret = hid_hw_raw_request(ldev->hdev, buf[0], buf,
|
|
|
|
|
|
+ memcpy(ldev->buf, buf, ldev->config->report_size);
|
|
|
|
+
|
|
|
|
+ ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
|
|
ldev->config->report_size,
|
|
ldev->config->report_size,
|
|
HID_FEATURE_REPORT,
|
|
HID_FEATURE_REPORT,
|
|
HID_REQ_SET_REPORT);
|
|
HID_REQ_SET_REPORT);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
- ret = hid_hw_raw_request(ldev->hdev, buf[0], buf,
|
|
|
|
|
|
+ ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
|
|
ldev->config->report_size,
|
|
ldev->config->report_size,
|
|
HID_FEATURE_REPORT,
|
|
HID_FEATURE_REPORT,
|
|
HID_REQ_GET_REPORT);
|
|
HID_REQ_GET_REPORT);
|
|
|
|
+
|
|
|
|
+ memcpy(buf, ldev->buf, ldev->config->report_size);
|
|
err:
|
|
err:
|
|
mutex_unlock(&ldev->lock);
|
|
mutex_unlock(&ldev->lock);
|
|
|
|
|
|
@@ -447,6 +458,10 @@ static int hidled_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|
if (!ldev)
|
|
if (!ldev)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
+ ldev->buf = devm_kmalloc(&hdev->dev, MAX_REPORT_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!ldev->buf)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
ret = hid_parse(hdev);
|
|
ret = hid_parse(hdev);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|