Skip to content

Commit b79c1ab

Browse files
bentissJiri Kosina
authored andcommitted
HID: core: split data fetching from processing in hid_input_field()
This is a preparatory patch for being able to process the usages out of order. We split the retrieval of the data in a separate function and also split out the processing of the usages depending if the field is an array or a variable. No functional changes from this patch. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Reviewed-by: Ping Cheng <ping.cheng@wacom.com> Acked-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 74acc27 commit b79c1ab

2 files changed

Lines changed: 79 additions & 20 deletions

File tree

drivers/hid/hid-core.c

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,13 +1544,12 @@ static inline int hid_array_value_is_valid(struct hid_field *field,
15441544
}
15451545

15461546
/*
1547-
* Analyse a received field, and fetch the data from it. The field
1548-
* content is stored for next report processing (we do differential
1549-
* reporting to the layer).
1547+
* Fetch the field from the data. The field content is stored for next
1548+
* report processing (we do differential reporting to the layer).
15501549
*/
1551-
1552-
static void hid_input_field(struct hid_device *hid, struct hid_field *field,
1553-
__u8 *data, int interrupt)
1550+
static void hid_input_fetch_field(struct hid_device *hid,
1551+
struct hid_field *field,
1552+
__u8 *data)
15541553
{
15551554
unsigned n;
15561555
unsigned count = field->report_count;
@@ -1561,6 +1560,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
15611560

15621561
value = field->new_value;
15631562
memset(value, 0, count * sizeof(__s32));
1563+
field->ignored = false;
15641564

15651565
for (n = 0; n < count; n++) {
15661566

@@ -1572,21 +1572,56 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
15721572
/* Ignore report if ErrorRollOver */
15731573
if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
15741574
hid_array_value_is_valid(field, value[n]) &&
1575-
field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
1575+
field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) {
1576+
field->ignored = true;
15761577
return;
1578+
}
15771579
}
1580+
}
15781581

1579-
for (n = 0; n < count; n++) {
1582+
/*
1583+
* Process a received variable field.
1584+
*/
15801585

1581-
if (HID_MAIN_ITEM_VARIABLE & field->flags) {
1582-
hid_process_event(hid,
1583-
field,
1584-
&field->usage[n],
1585-
value[n],
1586-
interrupt);
1587-
continue;
1588-
}
1586+
static void hid_input_var_field(struct hid_device *hid,
1587+
struct hid_field *field,
1588+
int interrupt)
1589+
{
1590+
unsigned int count = field->report_count;
1591+
__s32 *value = field->new_value;
1592+
unsigned int n;
1593+
1594+
for (n = 0; n < count; n++)
1595+
hid_process_event(hid,
1596+
field,
1597+
&field->usage[n],
1598+
value[n],
1599+
interrupt);
1600+
1601+
memcpy(field->value, value, count * sizeof(__s32));
1602+
}
15891603

1604+
/*
1605+
* Process a received array field. The field content is stored for
1606+
* next report processing (we do differential reporting to the layer).
1607+
*/
1608+
1609+
static void hid_input_array_field(struct hid_device *hid,
1610+
struct hid_field *field,
1611+
int interrupt)
1612+
{
1613+
unsigned int n;
1614+
unsigned int count = field->report_count;
1615+
__s32 min = field->logical_minimum;
1616+
__s32 *value;
1617+
1618+
value = field->new_value;
1619+
1620+
/* ErrorRollOver */
1621+
if (field->ignored)
1622+
return;
1623+
1624+
for (n = 0; n < count; n++) {
15901625
if (hid_array_value_is_valid(field, field->value[n]) &&
15911626
search(value, field->value[n], count))
15921627
hid_process_event(hid,
@@ -1607,6 +1642,31 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
16071642
memcpy(field->value, value, count * sizeof(__s32));
16081643
}
16091644

1645+
/*
1646+
* Analyse a received report, and fetch the data from it. The field
1647+
* content is stored for next report processing (we do differential
1648+
* reporting to the layer).
1649+
*/
1650+
static void hid_process_report(struct hid_device *hid,
1651+
struct hid_report *report,
1652+
__u8 *data,
1653+
int interrupt)
1654+
{
1655+
unsigned int a;
1656+
struct hid_field *field;
1657+
1658+
for (a = 0; a < report->maxfield; a++) {
1659+
field = report->field[a];
1660+
1661+
hid_input_fetch_field(hid, field, data);
1662+
1663+
if (field->flags & HID_MAIN_ITEM_VARIABLE)
1664+
hid_input_var_field(hid, field, interrupt);
1665+
else
1666+
hid_input_array_field(hid, field, interrupt);
1667+
}
1668+
}
1669+
16101670
/*
16111671
* Output the field into the report.
16121672
*/
@@ -1768,7 +1828,6 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
17681828
struct hid_report_enum *report_enum = hid->report_enum + type;
17691829
struct hid_report *report;
17701830
struct hid_driver *hdrv;
1771-
unsigned int a;
17721831
u32 rsize, csize = size;
17731832
u8 *cdata = data;
17741833
int ret = 0;
@@ -1804,8 +1863,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
18041863
}
18051864

18061865
if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
1807-
for (a = 0; a < report->maxfield; a++)
1808-
hid_input_field(hid, report->field[a], cdata, interrupt);
1866+
hid_process_report(hid, report, cdata, interrupt);
18091867
hdrv = hid->driver;
18101868
if (hdrv && hdrv->report)
18111869
hdrv->report(hid, report);

include/linux/hid.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ struct hid_item {
342342
* HID device quirks.
343343
*/
344344

345-
/*
345+
/*
346346
* Increase this if you need to configure more HID quirks at module load time
347347
*/
348348
#define MAX_USBHID_BOOT_QUIRKS 4
@@ -483,6 +483,7 @@ struct hid_field {
483483
__s32 physical_maximum;
484484
__s32 unit_exponent;
485485
unsigned unit;
486+
bool ignored; /* this field is ignored in this event */
486487
struct hid_report *report; /* associated report */
487488
unsigned index; /* index into report->field[] */
488489
/* hidinput data */

0 commit comments

Comments
 (0)