diff options
-rw-r--r-- | drivers/hid/hid-core.c | 19 | ||||
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 12 | ||||
-rw-r--r-- | drivers/hid/hid-picolcd_debugfs.c | 23 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 5 | ||||
-rw-r--r-- | include/linux/hid.h | 1 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 14 |
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 | ||
1134 | void hid_output_report(struct hid_report *report, __u8 *data) | 1135 | void hid_output_report(struct hid_report *report, __u8 *data) |
@@ -1145,6 +1146,22 @@ void hid_output_report(struct hid_report *report, __u8 *data) | |||
1145 | EXPORT_SYMBOL_GPL(hid_output_report); | 1146 | EXPORT_SYMBOL_GPL(hid_output_report); |
1146 | 1147 | ||
1147 | /* | 1148 | /* |
1149 | * Allocator for buffer that is going to be passed to hid_output_report() | ||
1150 | */ | ||
1151 | u8 *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 | } | ||
1162 | EXPORT_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 | ||
607 | static int logi_dj_ll_start(struct hid_device *hid) | 615 | static 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, | |||
394 | void picolcd_debug_out_report(struct picolcd_data *data, | 394 | void 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); | |||
744 | unsigned int hidinput_count_leds(struct hid_device *hid); | 744 | unsigned 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); |
746 | void hid_output_report(struct hid_report *report, __u8 *data); | 746 | void hid_output_report(struct hid_report *report, __u8 *data); |
747 | u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); | ||
747 | struct hid_device *hid_allocate_device(void); | 748 | struct hid_device *hid_allocate_device(void); |
748 | struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); | 749 | struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); |
749 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); | 750 | int 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 | ||
232 | static int hidp_send_report(struct hidp_session *session, struct hid_report *report) | 232 | static 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 | ||
247 | static int hidp_get_raw_report(struct hid_device *hid, | 251 | static int hidp_get_raw_report(struct hid_device *hid, |