aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-core.c19
-rw-r--r--drivers/hid/hid-logitech-dj.c12
-rw-r--r--drivers/hid/hid-picolcd_debugfs.c23
-rw-r--r--drivers/hid/usbhid/hid-core.c5
-rw-r--r--include/linux/hid.h1
-rw-r--r--net/bluetooth/hidp/core.c14
6 files changed, 52 insertions, 22 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index b0f2f459f59b..a1b248cea5b0 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1128,7 +1128,8 @@ static void hid_output_field(const struct hid_device *hid,
1128} 1128}
1129 1129
1130/* 1130/*
1131 * Create a report. 1131 * Create a report. 'data' has to be allocated using
1132 * hid_alloc_report_buf() so that it has proper size.
1132 */ 1133 */
1133 1134
1134void hid_output_report(struct hid_report *report, __u8 *data) 1135void hid_output_report(struct hid_report *report, __u8 *data)
@@ -1145,6 +1146,22 @@ void hid_output_report(struct hid_report *report, __u8 *data)
1145EXPORT_SYMBOL_GPL(hid_output_report); 1146EXPORT_SYMBOL_GPL(hid_output_report);
1146 1147
1147/* 1148/*
1149 * Allocator for buffer that is going to be passed to hid_output_report()
1150 */
1151u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
1152{
1153 /*
1154 * 7 extra bytes are necessary to achieve proper functionality
1155 * of implement() working on 8 byte chunks
1156 */
1157
1158 int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
1159
1160 return kmalloc(len, flags);
1161}
1162EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
1163
1164/*
1148 * Set a field value. The report this field belongs to has to be 1165 * Set a field value. The report this field belongs to has to be
1149 * created and transferred to the device, to set this value in the 1166 * created and transferred to the device, to set this value in the
1150 * device. 1167 * device.
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 5207591a598c..4d792739dbd1 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -574,7 +574,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
574 574
575 struct hid_field *field; 575 struct hid_field *field;
576 struct hid_report *report; 576 struct hid_report *report;
577 unsigned char data[8]; 577 unsigned char *data;
578 int offset; 578 int offset;
579 579
580 dbg_hid("%s: %s, type:%d | code:%d | value:%d\n", 580 dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
@@ -590,6 +590,13 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
590 return -1; 590 return -1;
591 } 591 }
592 hid_set_field(field, offset, value); 592 hid_set_field(field, offset, value);
593
594 data = hid_alloc_report_buf(field->report, GFP_KERNEL);
595 if (!data) {
596 dev_warn(&dev->dev, "failed to allocate report buf memory\n");
597 return -1;
598 }
599
593 hid_output_report(field->report, &data[0]); 600 hid_output_report(field->report, &data[0]);
594 601
595 output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT]; 602 output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
@@ -600,8 +607,9 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
600 607
601 hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT); 608 hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
602 609
603 return 0; 610 kfree(data);
604 611
612 return 0;
605} 613}
606 614
607static int logi_dj_ll_start(struct hid_device *hid) 615static int logi_dj_ll_start(struct hid_device *hid)
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
index 59ab8e157e6b..024cdf3c2297 100644
--- a/drivers/hid/hid-picolcd_debugfs.c
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -394,7 +394,7 @@ static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
394void picolcd_debug_out_report(struct picolcd_data *data, 394void picolcd_debug_out_report(struct picolcd_data *data,
395 struct hid_device *hdev, struct hid_report *report) 395 struct hid_device *hdev, struct hid_report *report)
396{ 396{
397 u8 raw_data[70]; 397 u8 *raw_data;
398 int raw_size = (report->size >> 3) + 1; 398 int raw_size = (report->size >> 3) + 1;
399 char *buff; 399 char *buff;
400#define BUFF_SZ 256 400#define BUFF_SZ 256
@@ -407,20 +407,20 @@ void picolcd_debug_out_report(struct picolcd_data *data,
407 if (!buff) 407 if (!buff)
408 return; 408 return;
409 409
410 snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", 410 raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
411 report->id, raw_size); 411 if (!raw_data) {
412 hid_debug_event(hdev, buff);
413 if (raw_size + 5 > sizeof(raw_data)) {
414 kfree(buff); 412 kfree(buff);
415 hid_debug_event(hdev, " TOO BIG\n");
416 return; 413 return;
417 } else {
418 raw_data[0] = report->id;
419 hid_output_report(report, raw_data);
420 dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
421 hid_debug_event(hdev, buff);
422 } 414 }
423 415
416 snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ",
417 report->id, raw_size);
418 hid_debug_event(hdev, buff);
419 raw_data[0] = report->id;
420 hid_output_report(report, raw_data);
421 dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
422 hid_debug_event(hdev, buff);
423
424 switch (report->id) { 424 switch (report->id) {
425 case REPORT_LED_STATE: 425 case REPORT_LED_STATE:
426 /* 1 data byte with GPO state */ 426 /* 1 data byte with GPO state */
@@ -644,6 +644,7 @@ void picolcd_debug_out_report(struct picolcd_data *data,
644 break; 644 break;
645 } 645 }
646 wake_up_interruptible(&hdev->debug_wait); 646 wake_up_interruptible(&hdev->debug_wait);
647 kfree(raw_data);
647 kfree(buff); 648 kfree(buff);
648} 649}
649 650
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 99418285222c..ada164e1b3a1 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -535,7 +535,6 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
535{ 535{
536 int head; 536 int head;
537 struct usbhid_device *usbhid = hid->driver_data; 537 struct usbhid_device *usbhid = hid->driver_data;
538 int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
539 538
540 if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) 539 if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
541 return; 540 return;
@@ -546,7 +545,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
546 return; 545 return;
547 } 546 }
548 547
549 usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); 548 usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
550 if (!usbhid->out[usbhid->outhead].raw_report) { 549 if (!usbhid->out[usbhid->outhead].raw_report) {
551 hid_warn(hid, "output queueing failed\n"); 550 hid_warn(hid, "output queueing failed\n");
552 return; 551 return;
@@ -595,7 +594,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
595 } 594 }
596 595
597 if (dir == USB_DIR_OUT) { 596 if (dir == USB_DIR_OUT) {
598 usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); 597 usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
599 if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { 598 if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
600 hid_warn(hid, "control queueing failed\n"); 599 hid_warn(hid, "control queueing failed\n");
601 return; 600 return;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0c48991b0402..acccdf4eb485 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -744,6 +744,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid);
744unsigned int hidinput_count_leds(struct hid_device *hid); 744unsigned int hidinput_count_leds(struct hid_device *hid);
745__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); 745__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
746void hid_output_report(struct hid_report *report, __u8 *data); 746void hid_output_report(struct hid_report *report, __u8 *data);
747u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
747struct hid_device *hid_allocate_device(void); 748struct hid_device *hid_allocate_device(void);
748struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); 749struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
749int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); 750int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 46c6a148f0b3..212980ff99b9 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -231,17 +231,21 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
231 231
232static int hidp_send_report(struct hidp_session *session, struct hid_report *report) 232static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
233{ 233{
234 unsigned char buf[32], hdr; 234 unsigned char hdr;
235 int rsize; 235 u8 *buf;
236 int rsize, ret;
236 237
237 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0); 238 buf = hid_alloc_report_buf(report, GFP_ATOMIC);
238 if (rsize > sizeof(buf)) 239 if (!buf)
239 return -EIO; 240 return -EIO;
240 241
241 hid_output_report(report, buf); 242 hid_output_report(report, buf);
242 hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; 243 hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
243 244
244 return hidp_send_intr_message(session, hdr, buf, rsize); 245 ret = hidp_send_intr_message(session, hdr, buf, rsize);
246
247 kfree(buf);
248 return ret;
245} 249}
246 250
247static int hidp_get_raw_report(struct hid_device *hid, 251static int hidp_get_raw_report(struct hid_device *hid,