return 0; /* we know nothing about this usage type */
 }
 
+/*
+ * Concatenate usage which defines 16 bits or less with the
+ * currently defined usage page to form a 32 bit usage
+ */
+
+static void complete_usage(struct hid_parser *parser, unsigned int index)
+{
+       parser->local.usage[index] &= 0xFFFF;
+       parser->local.usage[index] |=
+               (parser->global.usage_page & 0xFFFF) << 16;
+}
+
 /*
  * Add a usage to the temporary parser table.
  */
                return -1;
        }
        parser->local.usage[parser->local.usage_index] = usage;
+
+       /*
+        * If Usage item only includes usage id, concatenate it with
+        * currently defined usage page
+        */
+       if (size <= 2)
+               complete_usage(parser, parser->local.usage_index);
+
        parser->local.usage_size[parser->local.usage_index] = size;
        parser->local.collection_index[parser->local.usage_index] =
                parser->collection_stack_ptr ?
  * usage value."
  */
 
-static void hid_concatenate_usage_page(struct hid_parser *parser)
+static void hid_concatenate_last_usage_page(struct hid_parser *parser)
 {
        int i;
+       unsigned int usage_page;
+       unsigned int current_page;
 
-       for (i = 0; i < parser->local.usage_index; i++)
-               if (parser->local.usage_size[i] <= 2)
-                       parser->local.usage[i] += parser->global.usage_page << 16;
+       if (!parser->local.usage_index)
+               return;
+
+       usage_page = parser->global.usage_page;
+
+       /*
+        * Concatenate usage page again only if last declared Usage Page
+        * has not been already used in previous usages concatenation
+        */
+       for (i = parser->local.usage_index - 1; i >= 0; i--) {
+               if (parser->local.usage_size[i] > 2)
+                       /* Ignore extended usages */
+                       continue;
+
+               current_page = parser->local.usage[i] >> 16;
+               if (current_page == usage_page)
+                       break;
+
+               complete_usage(parser, i);
+       }
 }
 
 /*
        __u32 data;
        int ret;
 
-       hid_concatenate_usage_page(parser);
+       hid_concatenate_last_usage_page(parser);
 
        data = item_udata(item);
 
        __u32 data;
        int i;
 
-       hid_concatenate_usage_page(parser);
+       hid_concatenate_last_usage_page(parser);
 
        data = item_udata(item);