diff options
Diffstat (limited to 'drivers/hid/hid-logitech-dj.c')
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 2b56efcbdf61..5e8a7ed42344 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/hid.h> | 26 | #include <linux/hid.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
29 | #include <asm/unaligned.h> | ||
29 | #include "usbhid/usbhid.h" | 30 | #include "usbhid/usbhid.h" |
30 | #include "hid-ids.h" | 31 | #include "hid-ids.h" |
31 | #include "hid-logitech-dj.h" | 32 | #include "hid-logitech-dj.h" |
@@ -155,6 +156,14 @@ static const char media_descriptor[] = { | |||
155 | /* Maximum size of all defined hid reports in bytes (including report id) */ | 156 | /* Maximum size of all defined hid reports in bytes (including report id) */ |
156 | #define MAX_REPORT_SIZE 8 | 157 | #define MAX_REPORT_SIZE 8 |
157 | 158 | ||
159 | /* Make sure all descriptors are present here */ | ||
160 | #define MAX_RDESC_SIZE \ | ||
161 | (sizeof(kbd_descriptor) + \ | ||
162 | sizeof(mse_descriptor) + \ | ||
163 | sizeof(consumer_descriptor) + \ | ||
164 | sizeof(syscontrol_descriptor) + \ | ||
165 | sizeof(media_descriptor)) | ||
166 | |||
158 | /* Number of possible hid report types that can be created by this driver. | 167 | /* Number of possible hid report types that can be created by this driver. |
159 | * | 168 | * |
160 | * Right now, RF report types have the same report types (or report id's) | 169 | * Right now, RF report types have the same report types (or report id's) |
@@ -265,8 +274,8 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, | |||
265 | goto dj_device_allocate_fail; | 274 | goto dj_device_allocate_fail; |
266 | } | 275 | } |
267 | 276 | ||
268 | dj_dev->reports_supported = le32_to_cpu( | 277 | dj_dev->reports_supported = get_unaligned_le32( |
269 | dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]); | 278 | dj_report->report_params + DEVICE_PAIRED_RF_REPORT_TYPE); |
270 | dj_dev->hdev = dj_hiddev; | 279 | dj_dev->hdev = dj_hiddev; |
271 | dj_dev->dj_receiver_dev = djrcv_dev; | 280 | dj_dev->dj_receiver_dev = djrcv_dev; |
272 | dj_dev->device_index = dj_report->device_index; | 281 | dj_dev->device_index = dj_report->device_index; |
@@ -473,9 +482,17 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, | |||
473 | return 0; | 482 | return 0; |
474 | } | 483 | } |
475 | 484 | ||
485 | static void rdcat(char **rdesc, unsigned int *rsize, const char *data, unsigned int size) | ||
486 | { | ||
487 | memcpy(*rdesc + *rsize, data, size); | ||
488 | *rsize += size; | ||
489 | } | ||
490 | |||
476 | static int logi_dj_ll_parse(struct hid_device *hid) | 491 | static int logi_dj_ll_parse(struct hid_device *hid) |
477 | { | 492 | { |
478 | struct dj_device *djdev = hid->driver_data; | 493 | struct dj_device *djdev = hid->driver_data; |
494 | unsigned int rsize = 0; | ||
495 | char *rdesc; | ||
479 | int retval; | 496 | int retval; |
480 | 497 | ||
481 | dbg_hid("%s\n", __func__); | 498 | dbg_hid("%s\n", __func__); |
@@ -483,70 +500,38 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
483 | djdev->hdev->version = 0x0111; | 500 | djdev->hdev->version = 0x0111; |
484 | djdev->hdev->country = 0x00; | 501 | djdev->hdev->country = 0x00; |
485 | 502 | ||
503 | rdesc = kmalloc(MAX_RDESC_SIZE, GFP_KERNEL); | ||
504 | if (!rdesc) | ||
505 | return -ENOMEM; | ||
506 | |||
486 | if (djdev->reports_supported & STD_KEYBOARD) { | 507 | if (djdev->reports_supported & STD_KEYBOARD) { |
487 | dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n", | 508 | dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n", |
488 | __func__, djdev->reports_supported); | 509 | __func__, djdev->reports_supported); |
489 | retval = hid_parse_report(hid, | 510 | 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 | } | 511 | } |
498 | 512 | ||
499 | if (djdev->reports_supported & STD_MOUSE) { | 513 | if (djdev->reports_supported & STD_MOUSE) { |
500 | dbg_hid("%s: sending a mouse descriptor, reports_supported: " | 514 | dbg_hid("%s: sending a mouse descriptor, reports_supported: " |
501 | "%x\n", __func__, djdev->reports_supported); | 515 | "%x\n", __func__, djdev->reports_supported); |
502 | retval = hid_parse_report(hid, | 516 | 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 | } | 517 | } |
511 | 518 | ||
512 | if (djdev->reports_supported & MULTIMEDIA) { | 519 | if (djdev->reports_supported & MULTIMEDIA) { |
513 | dbg_hid("%s: sending a multimedia report descriptor: %x\n", | 520 | dbg_hid("%s: sending a multimedia report descriptor: %x\n", |
514 | __func__, djdev->reports_supported); | 521 | __func__, djdev->reports_supported); |
515 | retval = hid_parse_report(hid, | 522 | 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 | } | 523 | } |
524 | 524 | ||
525 | if (djdev->reports_supported & POWER_KEYS) { | 525 | if (djdev->reports_supported & POWER_KEYS) { |
526 | dbg_hid("%s: sending a power keys report descriptor: %x\n", | 526 | dbg_hid("%s: sending a power keys report descriptor: %x\n", |
527 | __func__, djdev->reports_supported); | 527 | __func__, djdev->reports_supported); |
528 | retval = hid_parse_report(hid, | 528 | 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 | } | 529 | } |
538 | 530 | ||
539 | if (djdev->reports_supported & MEDIA_CENTER) { | 531 | if (djdev->reports_supported & MEDIA_CENTER) { |
540 | dbg_hid("%s: sending a media center report descriptor: %x\n", | 532 | dbg_hid("%s: sending a media center report descriptor: %x\n", |
541 | __func__, djdev->reports_supported); | 533 | __func__, djdev->reports_supported); |
542 | retval = hid_parse_report(hid, | 534 | 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 | } | 535 | } |
551 | 536 | ||
552 | if (djdev->reports_supported & KBD_LEDS) { | 537 | if (djdev->reports_supported & KBD_LEDS) { |
@@ -554,7 +539,10 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
554 | __func__, djdev->reports_supported); | 539 | __func__, djdev->reports_supported); |
555 | } | 540 | } |
556 | 541 | ||
557 | return 0; | 542 | retval = hid_parse_report(hid, rdesc, rsize); |
543 | kfree(rdesc); | ||
544 | |||
545 | return retval; | ||
558 | } | 546 | } |
559 | 547 | ||
560 | static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, | 548 | static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, |