Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 67 ++++++++++++++++++------------ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 25 ++++++----- 2 files changed, 56 insertions(+), 36 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 86b68863308..f7fcccf55d4 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -306,6 +306,9 @@ struct hid_parser_state DWORD stack_size; DWORD global_idx; DWORD collection_idx; + + struct hid_value_caps *collections; + DWORD collections_size; };
static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index ) @@ -390,12 +393,24 @@ static BOOL parse_new_collection( struct hid_parser_state *state ) return FALSE; }
+ if (!array_reserve( &state->collections, &state->collections_size, state->caps.NumberLinkCollectionNodes )) + { + ERR( "HID parser collections overflow!\n" ); + return FALSE; + } + copy_collection_items( state->stack + state->collection_idx, &state->items ); state->collection_idx++;
+ state->collections[state->caps.NumberLinkCollectionNodes] = state->items; state->items.link_collection = state->caps.NumberLinkCollectionNodes; state->items.link_usage_page = state->items.usage_page; state->items.link_usage = state->items.usage_min; + if (!state->caps.NumberLinkCollectionNodes) + { + state->caps.UsagePage = state->items.usage_page; + state->caps.Usage = state->items.usage_min; + } state->caps.NumberLinkCollectionNodes++;
reset_local_items( state ); @@ -421,6 +436,7 @@ static void free_parser_state( struct hid_parser_state *state ) if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx ); if (state->collection_idx) ERR( "%u unpopped device collection on the stack\n", state->collection_idx ); free( state->stack ); + free( state->collections ); free( state ); }
@@ -727,10 +743,8 @@ static void preparse_collection(const struct collection *root, const struct coll WINE_HIDP_PREPARSED_DATA *data, struct preparse_ctx *ctx) { WINE_HID_ELEMENT *elem = HID_ELEMS(data); - WINE_HID_LINK_COLLECTION_NODE *nodes = HID_NODES(data); struct feature *f; struct collection *c; - struct list *entry;
LIST_FOR_EACH_ENTRY(f, &base->features, struct feature, entry) { @@ -775,33 +789,18 @@ static void preparse_collection(const struct collection *root, const struct coll } }
- if (root != base) - { - nodes[base->index].LinkUsagePage = base->caps.UsagePage; - nodes[base->index].LinkUsage = base->caps.NotRange.Usage; - nodes[base->index].Parent = base->parent == root ? 0 : base->parent->index; - nodes[base->index].CollectionType = base->type; - nodes[base->index].IsAlias = 0; - - if ((entry = list_head(&base->collections))) - nodes[base->index].FirstChild = LIST_ENTRY(entry, struct collection, entry)->index; - } - LIST_FOR_EACH_ENTRY(c, &base->collections, struct collection, entry) - { preparse_collection(root, c, data, ctx); - - if ((entry = list_next(&base->collections, &c->entry))) - nodes[c->index].NextSibling = LIST_ENTRY(entry, struct collection, entry)->index; - if (root != base) nodes[base->index].NumberOfChildren++; - } }
-static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_collection, unsigned int node_count) +static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_collection, + struct hid_parser_state *state ) { + WINE_HID_LINK_COLLECTION_NODE *nodes; WINE_HIDP_PREPARSED_DATA *data; unsigned int report_count; unsigned int size; + DWORD i;
struct preparse_ctx ctx; unsigned int element_off; @@ -816,18 +815,34 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_coll size = element_off + (ctx.elem_count * sizeof(WINE_HID_ELEMENT));
nodes_offset = size; - size += node_count * sizeof(WINE_HID_LINK_COLLECTION_NODE); + size += state->caps.NumberLinkCollectionNodes * sizeof(WINE_HID_LINK_COLLECTION_NODE);
if (!(data = calloc(1, size))) return NULL; data->magic = HID_MAGIC; data->dwSize = size; - data->caps.Usage = base_collection->caps.NotRange.Usage; - data->caps.UsagePage = base_collection->caps.UsagePage; - data->caps.NumberLinkCollectionNodes = node_count; + data->caps = state->caps; data->elementOffset = element_off; data->nodesOffset = nodes_offset;
preparse_collection(base_collection, base_collection, data, &ctx); + + nodes = HID_NODES( data ); + for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++i) + { + nodes[i].LinkUsagePage = state->collections[i].usage_page; + nodes[i].LinkUsage = state->collections[i].usage_min; + nodes[i].Parent = state->collections[i].link_collection; + nodes[i].CollectionType = state->collections[i].bit_field; + nodes[i].IsAlias = 0; + + if (i > 0) + { + nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild; + nodes[nodes[i].Parent].FirstChild = i; + nodes[nodes[i].Parent].NumberOfChildren++; + } + } + return data; }
@@ -889,7 +904,7 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
debug_collection(base);
- if ((data = build_PreparseData(base, cidx))) + if ((data = build_preparsed_data( base, state ))) debug_print_preparsed(data); free_collection(base);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 5453af8ff1c..19099a5a19c 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1500,6 +1500,20 @@ static void test_pnp_driver(struct testsign_context *ctx) (val).member, (exp).member) #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
+#define check_hidp_link_collection_node(a, b) check_hidp_link_collection_node_(__LINE__, a, b) +static inline void check_hidp_link_collection_node_(int line, HIDP_LINK_COLLECTION_NODE *node, + const HIDP_LINK_COLLECTION_NODE *exp) +{ + check_member_(__FILE__, line, *node, *exp, "%04x", LinkUsage); + check_member_(__FILE__, line, *node, *exp, "%04x", LinkUsagePage); + check_member_(__FILE__, line, *node, *exp, "%d", Parent); + check_member_(__FILE__, line, *node, *exp, "%d", NumberOfChildren); + check_member_(__FILE__, line, *node, *exp, "%d", NextSibling); + check_member_(__FILE__, line, *node, *exp, "%d", FirstChild); + check_member_(__FILE__, line, *node, *exp, "%d", CollectionType); + check_member_(__FILE__, line, *node, *exp, "%d", IsAlias); +} + #define check_hidp_button_caps(a, b) check_hidp_button_caps_(__LINE__, a, b) static inline void check_hidp_button_caps_(int line, HIDP_BUTTON_CAPS *caps, const HIDP_BUTTON_CAPS *exp) { @@ -1850,16 +1864,7 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_collections); ++i) { winetest_push_context("collections[%d]", i); - check_member(collections[i], expect_collections[i], "%04x", LinkUsage); - check_member(collections[i], expect_collections[i], "%04x", LinkUsagePage); - check_member(collections[i], expect_collections[i], "%d", Parent); - check_member(collections[i], expect_collections[i], "%d", NumberOfChildren); - todo_wine_if(i == 1) - check_member(collections[i], expect_collections[i], "%d", NextSibling); - todo_wine_if(i == 0) - check_member(collections[i], expect_collections[i], "%d", FirstChild); - check_member(collections[i], expect_collections[i], "%d", CollectionType); - check_member(collections[i], expect_collections[i], "%d", IsAlias); + check_hidp_link_collection_node(&collections[i], &expect_collections[i]); winetest_pop_context(); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 54 ++++------------------------------ 1 file changed, 5 insertions(+), 49 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index f7fcccf55d4..f1232137b83 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -95,17 +95,6 @@ struct feature {
HIDP_REPORT_TYPE type; BOOLEAN isData; - BOOLEAN isArray; - BOOLEAN IsAbsolute; - BOOLEAN Wrap; - BOOLEAN Linear; - BOOLEAN prefState; - BOOLEAN HasNull; - BOOLEAN Volatile; - BOOLEAN BitField; - - unsigned int index; - struct collection *collection; };
static const char* const collection_string[] = { @@ -186,18 +175,7 @@ static void debug_feature(struct feature *feature) { if (!feature) return; - TRACE("[Feature type %s [%i]; %s; %s; %s; %s; %s; %s; %s; %s; %s]\n", - feature_string[feature->type], - feature->index, - (feature->isData)?"Data":"Const", - (feature->isArray)?"Array":"Var", - (feature->IsAbsolute)?"Abs":"Rel", - (feature->Wrap)?"Wrap":"NoWrap", - (feature->Linear)?"Linear":"NonLinear", - (feature->prefState)?"PrefStat":"NoPrefState", - (feature->HasNull)?"HasNull":"NoNull", - (feature->Volatile)?"Volatile":"NonVolatile", - (feature->BitField)?"BitField":"Buffered"); + TRACE( "[Feature type %s %s]\n", feature_string[feature->type], (feature->isData) ? "Data" : "Const" );
TRACE("Feature %s\n", debugstr_hidp_value_caps(&feature->caps)); } @@ -441,7 +419,6 @@ static void free_parser_state( struct hid_parser_state *state ) }
static void parse_io_feature(unsigned int bSize, int itemVal, int bTag, - unsigned int *feature_index, struct feature *feature) { if (bSize == 0) @@ -451,23 +428,6 @@ static void parse_io_feature(unsigned int bSize, int itemVal, int bTag, else { feature->isData = ((itemVal & INPUT_DATA_CONST) == 0); - feature->isArray = ((itemVal & INPUT_ARRAY_VAR) == 0); - feature->IsAbsolute = ((itemVal & INPUT_ABS_REL) == 0); - feature->Wrap = ((itemVal & INPUT_WRAP) != 0); - feature->Linear = ((itemVal & INPUT_LINEAR) == 0); - feature->prefState = ((itemVal & INPUT_PREFSTATE) == 0); - feature->HasNull = ((itemVal & INPUT_NULL) != 0); - - if (bTag != TAG_MAIN_INPUT) - { - feature->Volatile = ((itemVal & INPUT_VOLATILE) != 0); - } - if (bSize > 1) - { - feature->BitField = ((itemVal & INPUT_BITFIELD) == 0); - } - feature->index = *feature_index; - *feature_index = *feature_index + 1; } }
@@ -487,8 +447,7 @@ static void parse_collection(unsigned int bSize, int itemVal, } }
-static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int length, - unsigned int *feature_index, unsigned int *collection_index, +static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int length, unsigned int *collection_index, struct collection *collection, struct hid_parser_state *state ) { int i, j; @@ -538,11 +497,10 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int feature->type = HidP_Output; else feature->type = HidP_Feature; - parse_io_feature(size, value, tag, feature_index, feature); + parse_io_feature( size, value, tag, feature ); if (j < state->usages_size) state->items.usage_min = state->usages[j]; copy_hidp_value_caps( &feature->caps, &state->items ); feature->caps.ReportCount = 1; - feature->collection = collection; if (j + 1 >= state->usages_size) { feature->caps.ReportCount += state->items.report_count - (j + 1); @@ -569,8 +527,7 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int parse_collection(size, value, subcollection); if (!parse_new_collection( state )) return -1;
- if ((i = parse_descriptor( descriptor, i, length, feature_index, collection_index, - subcollection, state )) < 0) + if ((i = parse_descriptor( descriptor, i, length, collection_index, subcollection, state )) < 0) return i; continue; } @@ -870,7 +827,6 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) struct collection *base; int i;
- unsigned int feature_count = 0; unsigned int cidx;
if (TRACE_ON(hid)) @@ -895,7 +851,7 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) list_init(&base->collections);
cidx = 0; - if (parse_descriptor( descriptor, 0, length, &feature_count, &cidx, base, state ) < 0) + if (parse_descriptor( descriptor, 0, length, &cidx, base, state ) < 0) { free_collection(base); free_parser_state( state );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index f1232137b83..f10ec40abec 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -109,8 +109,6 @@ static const char* const collection_string[] = {
struct collection { struct list entry; - HIDP_VALUE_CAPS caps; - unsigned int index; unsigned int type; struct collection *parent; struct list features; @@ -186,15 +184,14 @@ static void debug_collection(struct collection *collection) struct collection *centry; if (TRACE_ON(hid)) { - TRACE("START Collection %i <<< %s, parent: %p, %i features, %i collections\n", - collection->index, collection_string[collection->type], collection->parent, - list_count(&collection->features), list_count(&collection->collections)); - TRACE("Collection %s\n", debugstr_hidp_value_caps(&collection->caps)); + TRACE( "START Collection <<< %s, parent: %p, %i features, %i collections\n", + collection_string[collection->type], collection->parent, + list_count( &collection->features ), list_count( &collection->collections ) ); LIST_FOR_EACH_ENTRY(fentry, &collection->features, struct feature, entry) debug_feature(fentry); LIST_FOR_EACH_ENTRY(centry, &collection->collections, struct collection, entry) debug_collection(centry); - TRACE(">>> END Collection %i\n", collection->index); + TRACE( ">>> END Collection\n" ); } }
@@ -447,7 +444,7 @@ static void parse_collection(unsigned int bSize, int itemVal, } }
-static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int length, unsigned int *collection_index, +static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int length, struct collection *collection, struct hid_parser_state *state ) { int i, j; @@ -518,17 +515,12 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int /* Only set our collection once... We do not properly handle composite devices yet. */ if (state->usages_size) state->items.usage_min = state->usages[state->usages_size - 1]; - if (*collection_index == 0) copy_hidp_value_caps( &collection->caps, &state->items ); - copy_hidp_value_caps( &subcollection->caps, &state->items ); - subcollection->index = *collection_index; - *collection_index = *collection_index + 1; list_init(&subcollection->features); list_init(&subcollection->collections); parse_collection(size, value, subcollection); if (!parse_new_collection( state )) return -1;
- if ((i = parse_descriptor( descriptor, i, length, collection_index, subcollection, state )) < 0) - return i; + if ((i = parse_descriptor( descriptor, i, length, subcollection, state )) < 0) return i; continue; } case SHORT_ITEM(TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN): @@ -827,8 +819,6 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) struct collection *base; int i;
- unsigned int cidx; - if (TRACE_ON(hid)) { TRACE("descriptor %p, length %u:\n", descriptor, length); @@ -846,12 +836,10 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) free( state ); return NULL; } - base->index = 1; list_init(&base->features); list_init(&base->collections);
- cidx = 0; - if (parse_descriptor( descriptor, 0, length, &cidx, base, state ) < 0) + if (parse_descriptor( descriptor, 0, length, base, state ) < 0) { free_collection(base); free_parser_state( state );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 68 ++++++++++++++++------------------ 1 file changed, 31 insertions(+), 37 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index f10ec40abec..930dcd52715 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -406,6 +406,31 @@ static BOOL parse_end_collection( struct hid_parser_state *state ) return TRUE; }
+static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type, struct collection *collection ) +{ + struct feature *feature; + int j; + + for (j = 0; j < state->items.report_count; j++) + { + if (!(feature = calloc( 1, sizeof(*feature) ))) return -1; + list_add_tail( &collection->features, &feature->entry ); + feature->type = type; + feature->isData = ((state->items.bit_field & INPUT_DATA_CONST) == 0); + if (j < state->usages_size) state->items.usage_min = state->usages[j]; + copy_hidp_value_caps( &feature->caps, &state->items ); + feature->caps.ReportCount = 1; + if (j + 1 >= state->usages_size) + { + feature->caps.ReportCount += state->items.report_count - (j + 1); + break; + } + } + + reset_local_items( state ); + return TRUE; +} + static void free_parser_state( struct hid_parser_state *state ) { if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx ); @@ -415,19 +440,6 @@ static void free_parser_state( struct hid_parser_state *state ) free( state ); }
-static void parse_io_feature(unsigned int bSize, int itemVal, int bTag, - struct feature *feature) -{ - if (bSize == 0) - { - return; - } - else - { - feature->isData = ((itemVal & INPUT_DATA_CONST) == 0); - } -} - static void parse_collection(unsigned int bSize, int itemVal, struct collection *collection) { @@ -447,15 +459,13 @@ static void parse_collection(unsigned int bSize, int itemVal, static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int length, struct collection *collection, struct hid_parser_state *state ) { - int i, j; + int i; UINT32 value; INT32 signed_value; - struct feature *feature;
for (i = index; i < length;) { BYTE item = descriptor[i++]; - BYTE tag = item >> 4; int size = item & 0x03;
if (size == 3) size = 4; @@ -482,29 +492,13 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int switch (item & SHORT_ITEM(0xf,0x3)) { case SHORT_ITEM(TAG_MAIN_INPUT, TAG_TYPE_MAIN): + if (!parse_new_value_caps( state, HidP_Input, collection )) return -1; + break; case SHORT_ITEM(TAG_MAIN_OUTPUT, TAG_TYPE_MAIN): + if (!parse_new_value_caps( state, HidP_Output, collection )) return -1; + break; case SHORT_ITEM(TAG_MAIN_FEATURE, TAG_TYPE_MAIN): - for (j = 0; j < state->items.report_count; j++) - { - 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 ); - if (j < state->usages_size) state->items.usage_min = state->usages[j]; - copy_hidp_value_caps( &feature->caps, &state->items ); - feature->caps.ReportCount = 1; - if (j + 1 >= state->usages_size) - { - feature->caps.ReportCount += state->items.report_count - (j + 1); - break; - } - } - reset_local_items( state ); + if (!parse_new_value_caps( state, HidP_Feature, collection )) return -1; break; case SHORT_ITEM(TAG_MAIN_COLLECTION, TAG_TYPE_MAIN): {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 50 ++++++++++++++++++++++++------ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 2 +- 2 files changed, 41 insertions(+), 11 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 930dcd52715..26edb102034 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -272,7 +272,9 @@ struct hid_parser_state { HIDP_CAPS caps;
- USAGE usages[256]; + USAGE usages_page[256]; + USAGE usages_min[256]; + USAGE usages_max[256]; DWORD usages_size;
struct hid_value_caps items; @@ -352,14 +354,42 @@ static BOOL parse_global_pop( struct hid_parser_state *state ) return TRUE; }
-static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage ) +static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage_page, USAGE usage ) { - state->usages[state->usages_size] = usage; + if (!usage_page) usage_page = state->items.usage_page; + if (state->items.is_range) state->usages_size = 0; + state->usages_page[state->usages_size] = usage_page; + state->usages_min[state->usages_size] = usage; + state->usages_max[state->usages_size] = usage; + state->items.usage_min = usage; + state->items.usage_max = usage; state->items.is_range = FALSE; if (state->usages_size++ == 255) ERR( "HID parser usages stack overflow!\n" ); return state->usages_size <= 255; }
+static void parse_local_usage_min( struct hid_parser_state *state, USAGE usage_page, USAGE usage ) +{ + if (!usage_page) usage_page = state->items.usage_page; + if (!state->items.is_range) state->usages_max[0] = 0; + state->usages_page[0] = usage_page; + state->usages_min[0] = usage; + state->items.usage_min = usage; + state->items.is_range = TRUE; + state->usages_size = 1; +} + +static void parse_local_usage_max( struct hid_parser_state *state, USAGE usage_page, USAGE usage ) +{ + if (!usage_page) usage_page = state->items.usage_page; + if (!state->items.is_range) state->usages_min[0] = 0; + state->usages_page[0] = usage_page; + state->usages_max[0] = usage; + state->items.usage_max = usage; + state->items.is_range = TRUE; + state->usages_size = 1; +} + static BOOL parse_new_collection( struct hid_parser_state *state ) { if (!array_reserve( &state->stack, &state->stack_size, state->collection_idx )) @@ -377,6 +407,9 @@ static BOOL parse_new_collection( struct hid_parser_state *state ) copy_collection_items( state->stack + state->collection_idx, &state->items ); state->collection_idx++;
+ state->items.usage_min = state->usages_min[0]; + state->items.usage_max = state->usages_max[0]; + state->collections[state->caps.NumberLinkCollectionNodes] = state->items; state->items.link_collection = state->caps.NumberLinkCollectionNodes; state->items.link_usage_page = state->items.usage_page; @@ -417,8 +450,8 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY list_add_tail( &collection->features, &feature->entry ); feature->type = type; feature->isData = ((state->items.bit_field & INPUT_DATA_CONST) == 0); - if (j < state->usages_size) state->items.usage_min = state->usages[j]; copy_hidp_value_caps( &feature->caps, &state->items ); + if (j < state->usages_size) feature->caps.NotRange.Usage = state->usages_min[j]; feature->caps.ReportCount = 1; if (j + 1 >= state->usages_size) { @@ -508,7 +541,6 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int subcollection->parent = collection; /* Only set our collection once... We do not properly handle composite devices yet. */ - if (state->usages_size) state->items.usage_min = state->usages[state->usages_size - 1]; list_init(&subcollection->features); list_init(&subcollection->collections); parse_collection(size, value, subcollection); @@ -559,15 +591,13 @@ static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int break;
case SHORT_ITEM(TAG_LOCAL_USAGE, TAG_TYPE_LOCAL): - if (!parse_local_usage( state, value )) return -1; + if (!parse_local_usage( state, value >> 16, value & 0xffff )) return -1; break; case SHORT_ITEM(TAG_LOCAL_USAGE_MINIMUM, TAG_TYPE_LOCAL): - state->items.usage_min = value; - state->items.is_range = TRUE; + parse_local_usage_min( state, value >> 16, value & 0xffff ); break; case SHORT_ITEM(TAG_LOCAL_USAGE_MAXIMUM, TAG_TYPE_LOCAL): - state->items.usage_max = value; - state->items.is_range = TRUE; + parse_local_usage_max( state, value >> 16, value & 0xffff ); break; case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL): state->items.designator_min = state->items.designator_max = value; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 19099a5a19c..24782a733ff 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2026,7 +2026,7 @@ static void test_hidp(HANDLE file, int report_id) check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMax); todo_wine check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMin); - todo_wine + todo_wine_if(i >= 1) check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMax); check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMin); check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMax);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92735
Your paranoid android.
=== debiant2 (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:2030: Test failed: report 0: value_caps[0]: got Range.UsageMax 0000, expected 0031 ntoskrnl.c:2030: Test failed: report 1: value_caps[0]: got Range.UsageMax 0000, expected 0031
=== debiant2 (32 bit Arabic:Egypt report) ===
ntoskrnl.exe: ntoskrnl.c:2030: Test failed: report 0: value_caps[0]: got Range.UsageMax 0000, expected 0031 ntoskrnl.c:2030: Test failed: report 1: value_caps[0]: got Range.UsageMax 0000, expected 0031
=== debiant2 (32 bit French report) ===
ntoskrnl.exe: ntoskrnl.c:2030: Test failed: report 0: value_caps[0]: got Range.UsageMax 0000, expected 0031 ntoskrnl.c:2030: Test failed: report 1: value_caps[0]: got Range.UsageMax 0000, expected 0031
=== debiant2 (32 bit Hebrew:Israel report) ===
ntoskrnl.exe: ntoskrnl.c:2030: Test failed: report 0: value_caps[0]: got Range.UsageMax 0000, expected 0031 ntoskrnl.c:2030: Test failed: report 1: value_caps[0]: got Range.UsageMax 0000, expected 0031
=== debiant2 (32 bit Japanese:Japan report) ===
ntoskrnl.exe: ntoskrnl.c:2030: Test failed: report 0: value_caps[0]: got Range.UsageMax 0000, expected 0031 ntoskrnl.c:2030: Test failed: report 1: value_caps[0]: got Range.UsageMax 0000, expected 0031
=== debiant2 (32 bit Chinese:China report) ===
ntoskrnl.exe: ntoskrnl.c:2030: Test failed: report 0: value_caps[0]: got Range.UsageMax 0000, expected 0031 ntoskrnl.c:2030: Test failed: report 1: value_caps[0]: got Range.UsageMax 0000, expected 0031
On 6/18/21 9:55 AM, Marvin wrote:
Sorry, please ignore the last two patches, I'll resend them with the next batch.
I moved this one early in the series and I think I had some missing todo_wine change at some point, but either I put it in the wrong place or it was only when combined with a later patch.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 26edb102034..9bde61c4289 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -286,6 +286,9 @@ struct hid_parser_state
struct hid_value_caps *collections; DWORD collections_size; + + ULONG bit_size[3][256]; + USHORT *byte_size[3]; /* pointers to caps */ };
static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index ) @@ -441,6 +444,8 @@ static BOOL parse_end_collection( struct hid_parser_state *state )
static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type, struct collection *collection ) { + USHORT *byte_size = state->byte_size[type]; + ULONG *bit_size = &state->bit_size[type][state->items.report_id]; struct feature *feature; int j;
@@ -460,10 +465,22 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY } }
+ if (!*bit_size) *bit_size = 8; + *bit_size += state->items.bit_size * state->items.report_count; + *byte_size = max( *byte_size, (*bit_size + 7) / 8 ); + reset_local_items( state ); return TRUE; }
+static void init_parser_state( struct hid_parser_state *state ) +{ + memset( state, 0, sizeof(*state) ); + state->byte_size[HidP_Input] = &state->caps.InputReportByteLength; + state->byte_size[HidP_Output] = &state->caps.OutputReportByteLength; + state->byte_size[HidP_Feature] = &state->caps.FeatureReportByteLength; +} + static void free_parser_state( struct hid_parser_state *state ) { if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx ); @@ -744,20 +761,14 @@ static void preparse_collection(const struct collection *root, const struct coll case HidP_Input: build_elements(report, elem, f, &data->caps.NumberInputDataIndices); count_elements(f, &data->caps.NumberInputButtonCaps, &data->caps.NumberInputValueCaps); - data->caps.InputReportByteLength = - max(data->caps.InputReportByteLength, (report->bitSize + 7) / 8); break; case HidP_Output: build_elements(report, elem, f, &data->caps.NumberOutputDataIndices); count_elements(f, &data->caps.NumberOutputButtonCaps, &data->caps.NumberOutputValueCaps); - data->caps.OutputReportByteLength = - max(data->caps.OutputReportByteLength, (report->bitSize + 7) / 8); break; case HidP_Feature: build_elements(report, elem, f, &data->caps.NumberFeatureDataIndices); count_elements(f, &data->caps.NumberFeatureButtonCaps, &data->caps.NumberFeatureValueCaps); - data->caps.FeatureReportByteLength = - max(data->caps.FeatureReportByteLength, (report->bitSize + 7) / 8); break; } } @@ -862,6 +873,7 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) } list_init(&base->features); list_init(&base->collections); + init_parser_state( state );
if (parse_descriptor( descriptor, 0, length, base, state ) < 0) {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92731
Your paranoid android.
=== w7u_el (32 bit report) ===
ntoskrnl.exe: driver.c:272: Test failed: Got unexpected test_load_image_notify_count 0.