diff options
| -rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 68 |
1 files changed, 28 insertions, 40 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 34cca428a6a9..d00f1854cb82 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
| @@ -464,48 +464,38 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type, | |||
| 464 | } | 464 | } |
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | static int i2c_hid_alloc_buffers(struct i2c_hid *ihid) | 467 | static void i2c_hid_free_buffers(struct i2c_hid *ihid) |
| 468 | { | ||
| 469 | kfree(ihid->inbuf); | ||
| 470 | kfree(ihid->argsbuf); | ||
| 471 | kfree(ihid->cmdbuf); | ||
| 472 | ihid->inbuf = NULL; | ||
| 473 | ihid->cmdbuf = NULL; | ||
| 474 | ihid->argsbuf = NULL; | ||
| 475 | ihid->bufsize = 0; | ||
| 476 | } | ||
| 477 | |||
| 478 | static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) | ||
| 468 | { | 479 | { |
| 469 | /* the worst case is computed from the set_report command with a | 480 | /* the worst case is computed from the set_report command with a |
| 470 | * reportID > 15 and the maximum report length */ | 481 | * reportID > 15 and the maximum report length */ |
| 471 | int args_len = sizeof(__u8) + /* optional ReportID byte */ | 482 | int args_len = sizeof(__u8) + /* optional ReportID byte */ |
| 472 | sizeof(__u16) + /* data register */ | 483 | sizeof(__u16) + /* data register */ |
| 473 | sizeof(__u16) + /* size of the report */ | 484 | sizeof(__u16) + /* size of the report */ |
| 474 | ihid->bufsize; /* report */ | 485 | report_size; /* report */ |
| 475 | |||
| 476 | ihid->inbuf = kzalloc(ihid->bufsize, GFP_KERNEL); | ||
| 477 | |||
| 478 | if (!ihid->inbuf) | ||
| 479 | return -ENOMEM; | ||
| 480 | 486 | ||
| 487 | ihid->inbuf = kzalloc(report_size, GFP_KERNEL); | ||
| 481 | ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); | 488 | ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); |
| 482 | |||
| 483 | if (!ihid->argsbuf) { | ||
| 484 | kfree(ihid->inbuf); | ||
| 485 | return -ENOMEM; | ||
| 486 | } | ||
| 487 | |||
| 488 | ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); | 489 | ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); |
| 489 | 490 | ||
| 490 | if (!ihid->cmdbuf) { | 491 | if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) { |
| 491 | kfree(ihid->inbuf); | 492 | i2c_hid_free_buffers(ihid); |
| 492 | kfree(ihid->argsbuf); | ||
| 493 | ihid->inbuf = NULL; | ||
| 494 | ihid->argsbuf = NULL; | ||
| 495 | return -ENOMEM; | 493 | return -ENOMEM; |
| 496 | } | 494 | } |
| 497 | 495 | ||
| 498 | return 0; | 496 | ihid->bufsize = report_size; |
| 499 | } | ||
| 500 | 497 | ||
| 501 | static void i2c_hid_free_buffers(struct i2c_hid *ihid) | 498 | return 0; |
| 502 | { | ||
| 503 | kfree(ihid->inbuf); | ||
| 504 | kfree(ihid->argsbuf); | ||
| 505 | kfree(ihid->cmdbuf); | ||
| 506 | ihid->inbuf = NULL; | ||
| 507 | ihid->cmdbuf = NULL; | ||
| 508 | ihid->argsbuf = NULL; | ||
| 509 | } | 499 | } |
| 510 | 500 | ||
| 511 | static int i2c_hid_get_raw_report(struct hid_device *hid, | 501 | static int i2c_hid_get_raw_report(struct hid_device *hid, |
| @@ -610,22 +600,19 @@ static int i2c_hid_start(struct hid_device *hid) | |||
| 610 | struct i2c_client *client = hid->driver_data; | 600 | struct i2c_client *client = hid->driver_data; |
| 611 | struct i2c_hid *ihid = i2c_get_clientdata(client); | 601 | struct i2c_hid *ihid = i2c_get_clientdata(client); |
| 612 | int ret; | 602 | int ret; |
| 613 | int old_bufsize = ihid->bufsize; | 603 | unsigned int bufsize = HID_MIN_BUFFER_SIZE; |
| 614 | 604 | ||
| 615 | ihid->bufsize = HID_MIN_BUFFER_SIZE; | 605 | i2c_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize); |
| 616 | i2c_hid_find_max_report(hid, HID_INPUT_REPORT, &ihid->bufsize); | 606 | i2c_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize); |
| 617 | i2c_hid_find_max_report(hid, HID_OUTPUT_REPORT, &ihid->bufsize); | 607 | i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); |
| 618 | i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &ihid->bufsize); | ||
| 619 | 608 | ||
| 620 | if (ihid->bufsize > old_bufsize || !ihid->inbuf || !ihid->cmdbuf) { | 609 | if (bufsize > ihid->bufsize) { |
| 621 | i2c_hid_free_buffers(ihid); | 610 | i2c_hid_free_buffers(ihid); |
| 622 | 611 | ||
| 623 | ret = i2c_hid_alloc_buffers(ihid); | 612 | ret = i2c_hid_alloc_buffers(ihid, bufsize); |
| 624 | 613 | ||
| 625 | if (ret) { | 614 | if (ret) |
| 626 | ihid->bufsize = old_bufsize; | ||
| 627 | return ret; | 615 | return ret; |
| 628 | } | ||
| 629 | } | 616 | } |
| 630 | 617 | ||
| 631 | if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) | 618 | if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) |
| @@ -849,8 +836,9 @@ static int __devinit i2c_hid_probe(struct i2c_client *client, | |||
| 849 | /* we need to allocate the command buffer without knowing the maximum | 836 | /* we need to allocate the command buffer without knowing the maximum |
| 850 | * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the | 837 | * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the |
| 851 | * real computation later. */ | 838 | * real computation later. */ |
| 852 | ihid->bufsize = HID_MIN_BUFFER_SIZE; | 839 | ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE); |
| 853 | i2c_hid_alloc_buffers(ihid); | 840 | if (ret < 0) |
| 841 | goto err; | ||
| 854 | 842 | ||
| 855 | ret = i2c_hid_fetch_hid_descriptor(ihid); | 843 | ret = i2c_hid_fetch_hid_descriptor(ihid); |
| 856 | if (ret < 0) | 844 | if (ret < 0) |
