aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-core.c33
1 files changed, 15 insertions, 18 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bdb8cc89cacc..9985c0ab7c7f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1129,49 +1129,46 @@ EXPORT_SYMBOL_GPL(hid_field_extract);
1129static void __implement(u8 *report, unsigned offset, int n, u32 value) 1129static void __implement(u8 *report, unsigned offset, int n, u32 value)
1130{ 1130{
1131 unsigned int idx = offset / 8; 1131 unsigned int idx = offset / 8;
1132 unsigned int size = offset + n;
1133 unsigned int bit_shift = offset % 8; 1132 unsigned int bit_shift = offset % 8;
1134 int bits_to_set = 8 - bit_shift; 1133 int bits_to_set = 8 - bit_shift;
1135 u8 bit_mask = 0xff << bit_shift;
1136 1134
1137 while (n - bits_to_set >= 0) { 1135 while (n - bits_to_set >= 0) {
1138 report[idx] &= ~bit_mask; 1136 report[idx] &= ~(0xff << bit_shift);
1139 report[idx] |= value << bit_shift; 1137 report[idx] |= value << bit_shift;
1140 value >>= bits_to_set; 1138 value >>= bits_to_set;
1141 n -= bits_to_set; 1139 n -= bits_to_set;
1142 bits_to_set = 8; 1140 bits_to_set = 8;
1143 bit_mask = 0xff;
1144 bit_shift = 0; 1141 bit_shift = 0;
1145 idx++; 1142 idx++;
1146 } 1143 }
1147 1144
1148 /* last nibble */ 1145 /* last nibble */
1149 if (n) { 1146 if (n) {
1150 if (size % 8) 1147 u8 bit_mask = ((1U << n) - 1);
1151 bit_mask &= (1U << (size % 8)) - 1; 1148 report[idx] &= ~(bit_mask << bit_shift);
1152 report[idx] &= ~bit_mask; 1149 report[idx] |= value << bit_shift;
1153 report[idx] |= (value << bit_shift) & bit_mask;
1154 } 1150 }
1155} 1151}
1156 1152
1157static void implement(const struct hid_device *hid, u8 *report, 1153static void implement(const struct hid_device *hid, u8 *report,
1158 unsigned offset, unsigned n, u32 value) 1154 unsigned offset, unsigned n, u32 value)
1159{ 1155{
1160 u64 m; 1156 if (unlikely(n > 32)) {
1161
1162 if (n > 32) {
1163 hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", 1157 hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
1164 __func__, n, current->comm); 1158 __func__, n, current->comm);
1165 n = 32; 1159 n = 32;
1160 } else if (n < 32) {
1161 u32 m = (1U << n) - 1;
1162
1163 if (unlikely(value > m)) {
1164 hid_warn(hid,
1165 "%s() called with too large value %d (n: %d)! (%s)\n",
1166 __func__, value, n, current->comm);
1167 WARN_ON(1);
1168 value &= m;
1169 }
1166 } 1170 }
1167 1171
1168 m = (1ULL << n) - 1;
1169 if (value > m)
1170 hid_warn(hid, "%s() called with too large value %d! (%s)\n",
1171 __func__, value, current->comm);
1172 WARN_ON(value > m);
1173 value &= m;
1174
1175 __implement(report, offset, n, value); 1172 __implement(report, offset, n, value);
1176} 1173}
1177 1174