@@ -100,6 +100,7 @@ struct hidled_device {
100100 const struct hidled_config * config ;
101101 struct hid_device * hdev ;
102102 struct hidled_rgb * rgb ;
103+ u8 * buf ;
103104 struct mutex lock ;
104105};
105106
@@ -118,13 +119,19 @@ static int hidled_send(struct hidled_device *ldev, __u8 *buf)
118119
119120 mutex_lock (& ldev -> lock );
120121
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+
121128 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 ,
123130 ldev -> config -> report_size ,
124131 HID_FEATURE_REPORT ,
125132 HID_REQ_SET_REPORT );
126133 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 ,
128135 ldev -> config -> report_size );
129136 else
130137 ret = - EINVAL ;
@@ -147,17 +154,21 @@ static int hidled_recv(struct hidled_device *ldev, __u8 *buf)
147154
148155 mutex_lock (& ldev -> lock );
149156
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 ,
151160 ldev -> config -> report_size ,
152161 HID_FEATURE_REPORT ,
153162 HID_REQ_SET_REPORT );
154163 if (ret < 0 )
155164 goto err ;
156165
157- ret = hid_hw_raw_request (ldev -> hdev , buf [0 ], buf ,
166+ ret = hid_hw_raw_request (ldev -> hdev , buf [0 ], ldev -> buf ,
158167 ldev -> config -> report_size ,
159168 HID_FEATURE_REPORT ,
160169 HID_REQ_GET_REPORT );
170+
171+ memcpy (buf , ldev -> buf , ldev -> config -> report_size );
161172err :
162173 mutex_unlock (& ldev -> lock );
163174
@@ -447,6 +458,10 @@ static int hidled_probe(struct hid_device *hdev, const struct hid_device_id *id)
447458 if (!ldev )
448459 return - ENOMEM ;
449460
461+ ldev -> buf = devm_kmalloc (& hdev -> dev , MAX_REPORT_SIZE , GFP_KERNEL );
462+ if (!ldev -> buf )
463+ return - ENOMEM ;
464+
450465 ret = hid_parse (hdev );
451466 if (ret )
452467 return ret ;
0 commit comments