diff options
-rw-r--r-- | drivers/usb/input/hid-core.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index a6738a83ff5b..feabda73a6f9 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -750,21 +750,31 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) | |||
750 | } | 750 | } |
751 | 751 | ||
752 | /* | 752 | /* |
753 | * Extract/implement a data field from/to a report. | 753 | * Extract/implement a data field from/to a little endian report (bit array). |
754 | */ | 754 | */ |
755 | 755 | ||
756 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | 756 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) |
757 | { | 757 | { |
758 | report += (offset >> 5) << 2; offset &= 31; | 758 | u32 x; |
759 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1); | 759 | |
760 | report += offset >> 3; /* adjust byte index */ | ||
761 | offset &= 8 - 1; | ||
762 | x = get_unaligned((u32 *) report); | ||
763 | x = le32_to_cpu(x); | ||
764 | x = (x >> offset) & ((1 << n) - 1); | ||
765 | return x; | ||
760 | } | 766 | } |
761 | 767 | ||
762 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) | 768 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) |
763 | { | 769 | { |
764 | report += (offset >> 5) << 2; offset &= 31; | 770 | u32 x; |
765 | put_unaligned((get_unaligned((__le64*)report) | 771 | |
766 | & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset))) | 772 | report += offset >> 3; |
767 | | cpu_to_le64((__u64)value << offset), (__le64*)report); | 773 | offset &= 8 - 1; |
774 | x = get_unaligned((u32 *)report); | ||
775 | x &= cpu_to_le32(~((((__u32) 1 << n) - 1) << offset)); | ||
776 | x |= cpu_to_le32(value << offset); | ||
777 | put_unaligned(x,(u32 *)report); | ||
768 | } | 778 | } |
769 | 779 | ||
770 | /* | 780 | /* |