[PATCH 2/6] hidclass.sys: Use a single switch to parse all item types.
Rémi Bernon
rbernon at codeweavers.com
Thu Jun 17 03:20:17 CDT 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/hidclass.sys/descriptor.c | 365 +++++++++++++++------------------
1 file changed, 165 insertions(+), 200 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c
index cf0e8436b91..c1e9b93bed5 100644
--- a/dlls/hidclass.sys/descriptor.c
+++ b/dlls/hidclass.sys/descriptor.c
@@ -318,16 +318,16 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
{
int usages_top = 0;
USAGE usages[256];
- int i;
+ int i, j;
UINT32 value;
INT32 signed_value;
+ struct feature *feature;
for (i = index; i < length;)
{
- BYTE b0 = descriptor[i++];
- int size = b0 & 0x03;
- int bType = (b0 >> 2) & 0x03;
- int bTag = (b0 >> 4) & 0x0F;
+ BYTE item = descriptor[i++];
+ BYTE tag = item >> 4;
+ int size = item & 0x03;
if (size == 3) size = 4;
if (length - i < size)
@@ -347,215 +347,180 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
}
i += size;
- if (bType == TAG_TYPE_RESERVED && bTag == 0x0F && size == 2)
+#define SHORT_ITEM(tag,type) (((tag)<<4)|((type)<<2))
+ switch (item & SHORT_ITEM(0xf,0x3))
{
- /* Long data items: Should be unused */
- ERR("Long Data Item, should be unused\n");
- return -1;
- }
- else
- {
- unsigned int j;
-
- TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0,i-size-1,bType, bTag, size, value );
-
- if (bType == TAG_TYPE_MAIN)
+ case SHORT_ITEM(TAG_MAIN_INPUT, TAG_TYPE_MAIN):
+ case SHORT_ITEM(TAG_MAIN_OUTPUT, TAG_TYPE_MAIN):
+ case SHORT_ITEM(TAG_MAIN_FEATURE, TAG_TYPE_MAIN):
+ for (j = 0; j < caps->ReportCount; j++)
{
- struct feature *feature;
- switch(bTag)
+ if (!(feature = calloc(1, sizeof(*feature)))) return -1;
+ list_add_tail(&collection->features, &feature->entry);
+ if (tag == TAG_MAIN_INPUT)
+ feature->type = HidP_Input;
+ else if (tag == TAG_MAIN_OUTPUT)
+ feature->type = HidP_Output;
+ else
+ feature->type = HidP_Feature;
+ parse_io_feature(size, value, tag, feature_index, feature);
+ if (j < usages_top)
+ caps->NotRange.Usage = usages[j];
+ feature->caps = *caps;
+ feature->caps.ReportCount = 1;
+ feature->collection = collection;
+ if (j+1 >= usages_top)
{
- case TAG_MAIN_INPUT:
- case TAG_MAIN_OUTPUT:
- case TAG_MAIN_FEATURE:
- for (j = 0; j < caps->ReportCount; j++)
- {
- if (!(feature = calloc(1, sizeof(*feature)))) return -1;
- list_add_tail(&collection->features, &feature->entry);
- if (bTag == TAG_MAIN_INPUT)
- feature->type = HidP_Input;
- else if (bTag == TAG_MAIN_OUTPUT)
- feature->type = HidP_Output;
- else
- feature->type = HidP_Feature;
- parse_io_feature(size, value, bTag, feature_index, feature);
- if (j < usages_top)
- caps->NotRange.Usage = usages[j];
- feature->caps = *caps;
- feature->caps.ReportCount = 1;
- feature->collection = collection;
- if (j+1 >= usages_top)
- {
- feature->caps.ReportCount += caps->ReportCount - (j + 1);
- break;
- }
- }
- usages_top = 0;
- new_caps(caps);
- break;
- case TAG_MAIN_COLLECTION:
- {
- struct collection *subcollection;
- if (!(subcollection = calloc(1, sizeof(struct collection)))) return -1;
- list_add_tail(&collection->collections, &subcollection->entry);
- subcollection->parent = collection;
- /* Only set our collection once...
- We do not properly handle composite devices yet. */
- if (usages_top)
- {
- caps->NotRange.Usage = usages[usages_top-1];
- usages_top = 0;
- }
- if (*collection_index == 0)
- collection->caps = *caps;
- subcollection->caps = *caps;
- subcollection->index = *collection_index;
- *collection_index = *collection_index + 1;
- list_init(&subcollection->features);
- list_init(&subcollection->collections);
- new_caps(caps);
-
- parse_collection(size, value, subcollection);
-
- if ((i = parse_descriptor(descriptor, i, length, feature_index, collection_index, subcollection, caps, stack)) < 0) return i;
- continue;
- }
- case TAG_MAIN_END_COLLECTION:
- return i;
- default:
- ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
- return -1;
+ feature->caps.ReportCount += caps->ReportCount - (j + 1);
+ break;
}
}
- else if (bType == TAG_TYPE_GLOBAL)
+ usages_top = 0;
+ new_caps(caps);
+ break;
+ case SHORT_ITEM(TAG_MAIN_COLLECTION, TAG_TYPE_MAIN):
+ {
+ struct collection *subcollection;
+ if (!(subcollection = calloc(1, sizeof(struct collection)))) return -1;
+ list_add_tail(&collection->collections, &subcollection->entry);
+ subcollection->parent = collection;
+ /* Only set our collection once...
+ We do not properly handle composite devices yet. */
+ if (usages_top)
{
- switch(bTag)
- {
- case TAG_GLOBAL_USAGE_PAGE:
- caps->UsagePage = value;
- break;
- case TAG_GLOBAL_LOGICAL_MINIMUM:
- caps->LogicalMin = signed_value;
- break;
- case TAG_GLOBAL_LOGICAL_MAXIMUM:
- caps->LogicalMax = signed_value;
- break;
- case TAG_GLOBAL_PHYSICAL_MINIMUM:
- caps->PhysicalMin = signed_value;
- break;
- case TAG_GLOBAL_PHYSICAL_MAXIMUM:
- caps->PhysicalMax = signed_value;
- break;
- case TAG_GLOBAL_UNIT_EXPONENT:
- caps->UnitsExp = signed_value;
- break;
- case TAG_GLOBAL_UNIT:
- caps->Units = signed_value;
- break;
- case TAG_GLOBAL_REPORT_SIZE:
- caps->BitSize = value;
- break;
- case TAG_GLOBAL_REPORT_ID:
- caps->ReportID = value;
- break;
- case TAG_GLOBAL_REPORT_COUNT:
- caps->ReportCount = value;
- break;
- case TAG_GLOBAL_PUSH:
- {
- struct caps_stack *saved;
- if (!(saved = malloc(sizeof(*saved)))) return -1;
- saved->caps = *caps;
- TRACE("Push\n");
- list_add_tail(stack, &saved->entry);
- break;
- }
- case TAG_GLOBAL_POP:
- {
- struct list *tail;
- struct caps_stack *saved;
- TRACE("Pop\n");
- tail = list_tail(stack);
- if (tail)
- {
- saved = LIST_ENTRY(tail, struct caps_stack, entry);
- *caps = saved->caps;
- list_remove(tail);
- free(saved);
- }
- else
- {
- ERR("Pop but no stack!\n");
- return -1;
- }
- break;
- }
- default:
- ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
- return -1;
- }
+ caps->NotRange.Usage = usages[usages_top-1];
+ usages_top = 0;
}
- else if (bType == TAG_TYPE_LOCAL)
+ if (*collection_index == 0)
+ collection->caps = *caps;
+ subcollection->caps = *caps;
+ subcollection->index = *collection_index;
+ *collection_index = *collection_index + 1;
+ list_init(&subcollection->features);
+ list_init(&subcollection->collections);
+ new_caps(caps);
+
+ parse_collection(size, value, subcollection);
+
+ if ((i = parse_descriptor(descriptor, i, length, feature_index, collection_index, subcollection, caps, stack)) < 0) return i;
+ continue;
+ }
+ case SHORT_ITEM(TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN):
+ return i;
+
+ case SHORT_ITEM(TAG_GLOBAL_USAGE_PAGE, TAG_TYPE_GLOBAL):
+ caps->UsagePage = value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_LOGICAL_MINIMUM, TAG_TYPE_GLOBAL):
+ caps->LogicalMin = signed_value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_LOGICAL_MAXIMUM, TAG_TYPE_GLOBAL):
+ caps->LogicalMax = signed_value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_PHYSICAL_MINIMUM, TAG_TYPE_GLOBAL):
+ caps->PhysicalMin = signed_value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_PHYSICAL_MAXIMUM, TAG_TYPE_GLOBAL):
+ caps->PhysicalMax = signed_value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_UNIT_EXPONENT, TAG_TYPE_GLOBAL):
+ caps->UnitsExp = signed_value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_UNIT, TAG_TYPE_GLOBAL):
+ caps->Units = signed_value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_REPORT_SIZE, TAG_TYPE_GLOBAL):
+ caps->BitSize = value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_REPORT_ID, TAG_TYPE_GLOBAL):
+ caps->ReportID = value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_REPORT_COUNT, TAG_TYPE_GLOBAL):
+ caps->ReportCount = value;
+ break;
+ case SHORT_ITEM(TAG_GLOBAL_PUSH, TAG_TYPE_GLOBAL):
+ {
+ struct caps_stack *saved;
+ if (!(saved = malloc(sizeof(*saved)))) return -1;
+ saved->caps = *caps;
+ TRACE("Push\n");
+ list_add_tail(stack, &saved->entry);
+ break;
+ }
+ case SHORT_ITEM(TAG_GLOBAL_POP, TAG_TYPE_GLOBAL):
+ {
+ struct list *tail;
+ struct caps_stack *saved;
+ TRACE("Pop\n");
+ tail = list_tail(stack);
+ if (tail)
{
- switch(bTag)
- {
- case TAG_LOCAL_USAGE:
- if (usages_top == sizeof(usages))
- {
- ERR("More than 256 individual usages defined\n");
- return -1;
- }
- else
- {
- usages[usages_top++] = value;
- caps->IsRange = FALSE;
- }
- break;
- case TAG_LOCAL_USAGE_MINIMUM:
- caps->Range.UsageMin = value;
- caps->IsRange = TRUE;
- break;
- case TAG_LOCAL_USAGE_MAXIMUM:
- caps->Range.UsageMax = value;
- caps->IsRange = TRUE;
- break;
- case TAG_LOCAL_DESIGNATOR_INDEX:
- caps->NotRange.DesignatorIndex = value;
- caps->IsDesignatorRange = FALSE;
- break;
- case TAG_LOCAL_DESIGNATOR_MINIMUM:
- caps->Range.DesignatorMin = value;
- caps->IsDesignatorRange = TRUE;
- break;
- case TAG_LOCAL_DESIGNATOR_MAXIMUM:
- caps->Range.DesignatorMax = value;
- caps->IsDesignatorRange = TRUE;
- break;
- case TAG_LOCAL_STRING_INDEX:
- caps->NotRange.StringIndex = value;
- caps->IsStringRange = FALSE;
- break;
- case TAG_LOCAL_STRING_MINIMUM:
- caps->Range.StringMin = value;
- caps->IsStringRange = TRUE;
- break;
- case TAG_LOCAL_STRING_MAXIMUM:
- caps->Range.StringMax = value;
- caps->IsStringRange = TRUE;
- break;
- case TAG_LOCAL_DELIMITER:
- FIXME("delimiter %d not implemented!\n", value);
- return -1;
- default:
- ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
- return -1;
- }
+ saved = LIST_ENTRY(tail, struct caps_stack, entry);
+ *caps = saved->caps;
+ list_remove(tail);
+ free(saved);
}
else
{
- ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
+ ERR("Pop but no stack!\n");
+ return -1;
+ }
+ break;
+ }
+
+ case SHORT_ITEM(TAG_LOCAL_USAGE, TAG_TYPE_LOCAL):
+ if (usages_top == sizeof(usages))
+ {
+ ERR("More than 256 individual usages defined\n");
return -1;
}
+ else
+ {
+ usages[usages_top++] = value;
+ caps->IsRange = FALSE;
+ }
+ break;
+ case SHORT_ITEM(TAG_LOCAL_USAGE_MINIMUM, TAG_TYPE_LOCAL):
+ caps->Range.UsageMin = value;
+ caps->IsRange = TRUE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_USAGE_MAXIMUM, TAG_TYPE_LOCAL):
+ caps->Range.UsageMax = value;
+ caps->IsRange = TRUE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL):
+ caps->NotRange.DesignatorIndex = value;
+ caps->IsDesignatorRange = FALSE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_MINIMUM, TAG_TYPE_LOCAL):
+ caps->Range.DesignatorMin = value;
+ caps->IsDesignatorRange = TRUE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_MAXIMUM, TAG_TYPE_LOCAL):
+ caps->Range.DesignatorMax = value;
+ caps->IsDesignatorRange = TRUE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_STRING_INDEX, TAG_TYPE_LOCAL):
+ caps->NotRange.StringIndex = value;
+ caps->IsStringRange = FALSE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_STRING_MINIMUM, TAG_TYPE_LOCAL):
+ caps->Range.StringMin = value;
+ caps->IsStringRange = TRUE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_STRING_MAXIMUM, TAG_TYPE_LOCAL):
+ caps->Range.StringMax = value;
+ caps->IsStringRange = TRUE;
+ break;
+ case SHORT_ITEM(TAG_LOCAL_DELIMITER, TAG_TYPE_LOCAL):
+ FIXME("delimiter %d not implemented!\n", value);
+ return -1;
+
+ default:
+ FIXME("item type %x not implemented!\n", item);
+ return -1;
}
+#undef SHORT_ITEM
}
return i;
}
--
2.31.0
More information about the wine-devel
mailing list