aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-core.c16
-rw-r--r--drivers/hid/hid-input.c13
-rw-r--r--include/linux/hid.h1
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
316static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) 316static 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
876s32 hid_snto32(__u32 value, unsigned n)
877{
878 return snto32(value, n);
879}
880EXPORT_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);
717void hid_disconnect(struct hid_device *hid); 717void hid_disconnect(struct hid_device *hid);
718const struct hid_device_id *hid_match_id(struct hid_device *hdev, 718const 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);
720s32 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