diff options
-rw-r--r-- | drivers/hid/hid-core.c | 16 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 13 | ||||
-rw-r--r-- | include/linux/hid.h | 1 |
3 files changed, 25 insertions, 5 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f4109fd657ff..f5004e2ca0c5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -315,6 +315,7 @@ static s32 item_sdata(struct hid_item *item) | |||
315 | 315 | ||
316 | static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | 316 | static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) |
317 | { | 317 | { |
318 | __u32 raw_value; | ||
318 | switch (item->tag) { | 319 | switch (item->tag) { |
319 | case HID_GLOBAL_ITEM_TAG_PUSH: | 320 | case HID_GLOBAL_ITEM_TAG_PUSH: |
320 | 321 | ||
@@ -365,7 +366,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
365 | return 0; | 366 | return 0; |
366 | 367 | ||
367 | case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: | 368 | case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: |
368 | parser->global.unit_exponent = item_sdata(item); | 369 | /* Units exponent negative numbers are given through a |
370 | * two's complement. | ||
371 | * See "6.2.2.7 Global Items" for more information. */ | ||
372 | raw_value = item_udata(item); | ||
373 | if (!(raw_value & 0xfffffff0)) | ||
374 | parser->global.unit_exponent = hid_snto32(raw_value, 4); | ||
375 | else | ||
376 | parser->global.unit_exponent = raw_value; | ||
369 | return 0; | 377 | return 0; |
370 | 378 | ||
371 | case HID_GLOBAL_ITEM_TAG_UNIT: | 379 | case HID_GLOBAL_ITEM_TAG_UNIT: |
@@ -865,6 +873,12 @@ static s32 snto32(__u32 value, unsigned n) | |||
865 | return value & (1 << (n - 1)) ? value | (-1 << n) : value; | 873 | return value & (1 << (n - 1)) ? value | (-1 << n) : value; |
866 | } | 874 | } |
867 | 875 | ||
876 | s32 hid_snto32(__u32 value, unsigned n) | ||
877 | { | ||
878 | return snto32(value, n); | ||
879 | } | ||
880 | EXPORT_SYMBOL_GPL(hid_snto32); | ||
881 | |||
868 | /* | 882 | /* |
869 | * Convert a signed 32-bit integer to a signed n-bit integer. | 883 | * Convert a signed 32-bit integer to a signed n-bit integer. |
870 | */ | 884 | */ |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 1b0adc3f7803..007a9433bfa7 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev, | |||
192 | return -EINVAL; | 192 | return -EINVAL; |
193 | } | 193 | } |
194 | 194 | ||
195 | |||
196 | /** | 195 | /** |
197 | * hidinput_calc_abs_res - calculate an absolute axis resolution | 196 | * hidinput_calc_abs_res - calculate an absolute axis resolution |
198 | * @field: the HID report field to calculate resolution for | 197 | * @field: the HID report field to calculate resolution for |
@@ -235,17 +234,23 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | |||
235 | case ABS_MT_TOOL_Y: | 234 | case ABS_MT_TOOL_Y: |
236 | case ABS_MT_TOUCH_MAJOR: | 235 | case ABS_MT_TOUCH_MAJOR: |
237 | case ABS_MT_TOUCH_MINOR: | 236 | case ABS_MT_TOUCH_MINOR: |
238 | if (field->unit == 0x11) { /* If centimeters */ | 237 | if (field->unit & 0xffffff00) /* Not a length */ |
238 | return 0; | ||
239 | unit_exponent += hid_snto32(field->unit >> 4, 4) - 1; | ||
240 | switch (field->unit & 0xf) { | ||
241 | case 0x1: /* If centimeters */ | ||
239 | /* Convert to millimeters */ | 242 | /* Convert to millimeters */ |
240 | unit_exponent += 1; | 243 | unit_exponent += 1; |
241 | } else if (field->unit == 0x13) { /* If inches */ | 244 | break; |
245 | case 0x3: /* If inches */ | ||
242 | /* Convert to millimeters */ | 246 | /* Convert to millimeters */ |
243 | prev = physical_extents; | 247 | prev = physical_extents; |
244 | physical_extents *= 254; | 248 | physical_extents *= 254; |
245 | if (physical_extents < prev) | 249 | if (physical_extents < prev) |
246 | return 0; | 250 | return 0; |
247 | unit_exponent -= 1; | 251 | unit_exponent -= 1; |
248 | } else { | 252 | break; |
253 | default: | ||
249 | return 0; | 254 | return 0; |
250 | } | 255 | } |
251 | break; | 256 | break; |
diff --git a/include/linux/hid.h b/include/linux/hid.h index c6bef8f54a82..4161bf2c0b5b 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -717,6 +717,7 @@ int hid_connect(struct hid_device *hid, unsigned int connect_mask); | |||
717 | void hid_disconnect(struct hid_device *hid); | 717 | void hid_disconnect(struct hid_device *hid); |
718 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, | 718 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, |
719 | const struct hid_device_id *id); | 719 | const struct hid_device_id *id); |
720 | s32 hid_snto32(__u32 value, unsigned n); | ||
720 | 721 | ||
721 | /** | 722 | /** |
722 | * hid_map_usage - map usage input bits | 723 | * hid_map_usage - map usage input bits |