diff options
author | Henrik Rydberg <rydberg@euromail.se> | 2012-04-22 08:21:39 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-05-01 06:54:53 -0400 |
commit | 2a039bf5a6caa6b41c3839c1e3a19b20fb38270b (patch) | |
tree | ead38dc1262b0f62063607d08ef354faccdc9df9 /drivers/hid/hid-logitech-dj.c | |
parent | 07d9ab4f0e52cb2a383596e5ebbbd20232501393 (diff) |
HID: hid-logitech: Collect report descriptors before sending
The current code allows several consecutive calls to hid_parse_report(),
which may have happened to work before, but would cause a memory leak
and generally be incorrect. This patch collects all the reports
before sending them once.
Cc: Nestor Lopez Casado <nlopezcasad@logitech.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-logitech-dj.c')
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 71 |
1 files changed, 29 insertions, 42 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 2b56efcbdf61..e1c38bba4375 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -155,6 +155,14 @@ static const char media_descriptor[] = { | |||
155 | /* Maximum size of all defined hid reports in bytes (including report id) */ | 155 | /* Maximum size of all defined hid reports in bytes (including report id) */ |
156 | #define MAX_REPORT_SIZE 8 | 156 | #define MAX_REPORT_SIZE 8 |
157 | 157 | ||
158 | /* Make sure all descriptors are present here */ | ||
159 | #define MAX_RDESC_SIZE \ | ||
160 | (sizeof(kbd_descriptor) + \ | ||
161 | sizeof(mse_descriptor) + \ | ||
162 | sizeof(consumer_descriptor) + \ | ||
163 | sizeof(syscontrol_descriptor) + \ | ||
164 | sizeof(media_descriptor)) | ||
165 | |||
158 | /* Number of possible hid report types that can be created by this driver. | 166 | /* Number of possible hid report types that can be created by this driver. |
159 | * | 167 | * |
160 | * Right now, RF report types have the same report types (or report id's) | 168 | * Right now, RF report types have the same report types (or report id's) |
@@ -473,9 +481,17 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, | |||
473 | return 0; | 481 | return 0; |
474 | } | 482 | } |
475 | 483 | ||
484 | static void rdcat(char **rdesc, unsigned int *rsize, const char *data, unsigned int size) | ||
485 | { | ||
486 | memcpy(*rdesc + *rsize, data, size); | ||
487 | *rsize += size; | ||
488 | } | ||
489 | |||
476 | static int logi_dj_ll_parse(struct hid_device *hid) | 490 | static int logi_dj_ll_parse(struct hid_device *hid) |
477 | { | 491 | { |
478 | struct dj_device *djdev = hid->driver_data; | 492 | struct dj_device *djdev = hid->driver_data; |
493 | unsigned int rsize = 0; | ||
494 | char *rdesc; | ||
479 | int retval; | 495 | int retval; |
480 | 496 | ||
481 | dbg_hid("%s\n", __func__); | 497 | dbg_hid("%s\n", __func__); |
@@ -483,70 +499,38 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
483 | djdev->hdev->version = 0x0111; | 499 | djdev->hdev->version = 0x0111; |
484 | djdev->hdev->country = 0x00; | 500 | djdev->hdev->country = 0x00; |
485 | 501 | ||
502 | rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL); | ||
503 | if (!rdesc) | ||
504 | return -ENOMEM; | ||
505 | |||
486 | if (djdev->reports_supported & STD_KEYBOARD) { | 506 | if (djdev->reports_supported & STD_KEYBOARD) { |
487 | dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n", | 507 | dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n", |
488 | __func__, djdev->reports_supported); | 508 | __func__, djdev->reports_supported); |
489 | retval = hid_parse_report(hid, | 509 | rdcat(&rdesc, &rsize, kbd_descriptor, sizeof(kbd_descriptor)); |
490 | (u8 *) kbd_descriptor, | ||
491 | sizeof(kbd_descriptor)); | ||
492 | if (retval) { | ||
493 | dbg_hid("%s: sending a kbd descriptor, hid_parse failed" | ||
494 | " error: %d\n", __func__, retval); | ||
495 | return retval; | ||
496 | } | ||
497 | } | 510 | } |
498 | 511 | ||
499 | if (djdev->reports_supported & STD_MOUSE) { | 512 | if (djdev->reports_supported & STD_MOUSE) { |
500 | dbg_hid("%s: sending a mouse descriptor, reports_supported: " | 513 | dbg_hid("%s: sending a mouse descriptor, reports_supported: " |
501 | "%x\n", __func__, djdev->reports_supported); | 514 | "%x\n", __func__, djdev->reports_supported); |
502 | retval = hid_parse_report(hid, | 515 | rdcat(&rdesc, &rsize, mse_descriptor, sizeof(mse_descriptor)); |
503 | (u8 *) mse_descriptor, | ||
504 | sizeof(mse_descriptor)); | ||
505 | if (retval) { | ||
506 | dbg_hid("%s: sending a mouse descriptor, hid_parse " | ||
507 | "failed error: %d\n", __func__, retval); | ||
508 | return retval; | ||
509 | } | ||
510 | } | 516 | } |
511 | 517 | ||
512 | if (djdev->reports_supported & MULTIMEDIA) { | 518 | if (djdev->reports_supported & MULTIMEDIA) { |
513 | dbg_hid("%s: sending a multimedia report descriptor: %x\n", | 519 | dbg_hid("%s: sending a multimedia report descriptor: %x\n", |
514 | __func__, djdev->reports_supported); | 520 | __func__, djdev->reports_supported); |
515 | retval = hid_parse_report(hid, | 521 | rdcat(&rdesc, &rsize, consumer_descriptor, sizeof(consumer_descriptor)); |
516 | (u8 *) consumer_descriptor, | ||
517 | sizeof(consumer_descriptor)); | ||
518 | if (retval) { | ||
519 | dbg_hid("%s: sending a consumer_descriptor, hid_parse " | ||
520 | "failed error: %d\n", __func__, retval); | ||
521 | return retval; | ||
522 | } | ||
523 | } | 522 | } |
524 | 523 | ||
525 | if (djdev->reports_supported & POWER_KEYS) { | 524 | if (djdev->reports_supported & POWER_KEYS) { |
526 | dbg_hid("%s: sending a power keys report descriptor: %x\n", | 525 | dbg_hid("%s: sending a power keys report descriptor: %x\n", |
527 | __func__, djdev->reports_supported); | 526 | __func__, djdev->reports_supported); |
528 | retval = hid_parse_report(hid, | 527 | rdcat(&rdesc, &rsize, syscontrol_descriptor, sizeof(syscontrol_descriptor)); |
529 | (u8 *) syscontrol_descriptor, | ||
530 | sizeof(syscontrol_descriptor)); | ||
531 | if (retval) { | ||
532 | dbg_hid("%s: sending a syscontrol_descriptor, " | ||
533 | "hid_parse failed error: %d\n", | ||
534 | __func__, retval); | ||
535 | return retval; | ||
536 | } | ||
537 | } | 528 | } |
538 | 529 | ||
539 | if (djdev->reports_supported & MEDIA_CENTER) { | 530 | if (djdev->reports_supported & MEDIA_CENTER) { |
540 | dbg_hid("%s: sending a media center report descriptor: %x\n", | 531 | dbg_hid("%s: sending a media center report descriptor: %x\n", |
541 | __func__, djdev->reports_supported); | 532 | __func__, djdev->reports_supported); |
542 | retval = hid_parse_report(hid, | 533 | rdcat(&rdesc, &rsize, media_descriptor, sizeof(media_descriptor)); |
543 | (u8 *) media_descriptor, | ||
544 | sizeof(media_descriptor)); | ||
545 | if (retval) { | ||
546 | dbg_hid("%s: sending a media_descriptor, hid_parse " | ||
547 | "failed error: %d\n", __func__, retval); | ||
548 | return retval; | ||
549 | } | ||
550 | } | 534 | } |
551 | 535 | ||
552 | if (djdev->reports_supported & KBD_LEDS) { | 536 | if (djdev->reports_supported & KBD_LEDS) { |
@@ -554,7 +538,10 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
554 | __func__, djdev->reports_supported); | 538 | __func__, djdev->reports_supported); |
555 | } | 539 | } |
556 | 540 | ||
557 | return 0; | 541 | retval = hid_parse_report(hid, rdesc, rsize); |
542 | kfree(rdesc); | ||
543 | |||
544 | return retval; | ||
558 | } | 545 | } |
559 | 546 | ||
560 | static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, | 547 | static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, |