Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp272248ybi; Wed, 29 May 2019 21:06:58 -0700 (PDT) X-Google-Smtp-Source: APXvYqyKj45hZQ2ca7PqoKDH4kSTM6ij5UhyGXEgfWhFtZktUMwgcOCjmB2jT5tlq3mkUGe1bvN1 X-Received: by 2002:a17:902:b70b:: with SMTP id d11mr1877947pls.84.1559189218718; Wed, 29 May 2019 21:06:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559189218; cv=none; d=google.com; s=arc-20160816; b=Fo8X9MXhuRN+BhYW7VWi5pD5slZJAj2lihxoDVL0qUcy38dTgISSz9P2UQskYHJ9fY xhTEGphRFDyRpig0yjeKypM8fsUgeKYWHH1U+Ojy2nrI01OMsd1FAvH5T8gEd3wgs49q /3A7ACjpKkY2SbBLR/Bocw1zJQMELYH/P+eo6XzhK3iMSHleVhi+TZNhPgvn9EqSZ46T UMDLYpxE725rPGCDM1rrxNwf+VaXhyEgz4j7LoK3DKO9PsoHzVnyUuCOGc73Bm59Krj7 ic/13R0EuoDuxTAtdWbE4AdgQQZnrHnKFhiYtwDAY7EmIFbPjzQDBZIv78vzcpHqCBHW WzQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=KChAy4nMS7TzyUoles/7qkLs1935Xkf1FVbC+PYJgr4=; b=a1jkfIhRiNuvxlDoL0Bz1cYoHwo4fAxu/CxZATkjppsXfXsQwgpCmhseD3i062Is+u O0s6znXeGI3zybFARzRrpdwPnfRWaVQaiqXcKsxIwFimhXdztAksZbj/PGGPb/eNwRif UX0jPb99NM8djvqaFV4iHpwDKp/qGRS8tWRHHaP7DAS6l1+dQ92LUKhQJsIZ4UWSGZ5X KWRwA3ZMPbca71/NBUwDXEC9xayybOfZOJd0U3fbZErsEUwaOM1OyzGBHIOOqAUA+8X9 VUUnLc0k9wxQEh6OQzd0zHEQvWeKD+caFrKVX3WwcBqFnpfZTM7Y4I7dQajffUDPdsHb ckhQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=KAf+3+aq; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t7si1989145pgu.3.2019.05.29.21.06.41; Wed, 29 May 2019 21:06:58 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=KAf+3+aq; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732035AbfE3EEL (ORCPT + 99 others); Thu, 30 May 2019 00:04:11 -0400 Received: from mail.kernel.org ([198.145.29.99]:48276 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731317AbfE3DRx (ORCPT ); Wed, 29 May 2019 23:17:53 -0400 Received: from localhost (ip67-88-213-2.z213-88-67.customer.algx.net [67.88.213.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B7B6C2473B; Thu, 30 May 2019 03:17:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559186272; bh=wSuc4b6uTiISnE3BZXVFg0KIQizJKVckQn+jaVcmCpc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KAf+3+aq4t/JZjP4AUcnBSEDhAXJeyFI8JGXDJM9Deys9g1NL43Ig7KCdDihFTQMa oymw2O/6R9jRfz0alJuW87guXzq7OMn8nOletfWhxxarJdNAEE13kbeFB+5wwawwbF odq8TXHDStnhGHmeqjqVkFm5i9U9Bj4IBNNByhYw= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Nicolas Saenz Julienne , Terry Junge , Benjamin Tissoires , Sasha Levin Subject: [PATCH 4.19 213/276] HID: core: move Usage Page concatenation to Main item Date: Wed, 29 May 2019 20:06:11 -0700 Message-Id: <20190530030538.454681387@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190530030523.133519668@linuxfoundation.org> References: <20190530030523.133519668@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [ Upstream commit 58e75155009cc800005629955d3482f36a1e0eec ] As seen on some USB wireless keyboards manufactured by Primax, the HID parser was using some assumptions that are not always true. In this case it's s the fact that, inside the scope of a main item, an Usage Page will always precede an Usage. The spec is not pretty clear as 6.2.2.7 states "Any usage that follows is interpreted as a Usage ID and concatenated with the Usage Page". While 6.2.2.8 states "When the parser encounters a main item it concatenates the last declared Usage Page with a Usage to form a complete usage value." Being somewhat contradictory it was decided to match Window's implementation, which follows 6.2.2.8. In summary, the patch moves the Usage Page concatenation from the local item parsing function to the main item parsing function. Signed-off-by: Nicolas Saenz Julienne Reviewed-by: Terry Junge Signed-off-by: Benjamin Tissoires Signed-off-by: Sasha Levin --- drivers/hid/hid-core.c | 36 ++++++++++++++++++++++++------------ include/linux/hid.h | 1 + 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 44564f61e9cc3..861375561156c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -215,13 +215,14 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) * Add a usage to the temporary parser table. */ -static int hid_add_usage(struct hid_parser *parser, unsigned usage) +static int hid_add_usage(struct hid_parser *parser, unsigned usage, u8 size) { if (parser->local.usage_index >= HID_MAX_USAGES) { hid_err(parser->device, "usage index exceeded\n"); return -1; } parser->local.usage[parser->local.usage_index] = usage; + parser->local.usage_size[parser->local.usage_index] = size; parser->local.collection_index[parser->local.usage_index] = parser->collection_stack_ptr ? parser->collection_stack[parser->collection_stack_ptr - 1] : 0; @@ -482,10 +483,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - return hid_add_usage(parser, data); + return hid_add_usage(parser, data, item->size); case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: @@ -494,9 +492,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - parser->local.usage_minimum = data; return 0; @@ -507,9 +502,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - count = data - parser->local.usage_minimum; if (count + parser->local.usage_index >= HID_MAX_USAGES) { /* @@ -529,7 +521,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) } for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { + if (hid_add_usage(parser, n, item->size)) { dbg_hid("hid_add_usage failed\n"); return -1; } @@ -543,6 +535,22 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } +/* + * Concatenate Usage Pages into Usages where relevant: + * As per specification, 6.2.2.8: "When the parser encounters a main item it + * concatenates the last declared Usage Page with a Usage to form a complete + * usage value." + */ + +static void hid_concatenate_usage_page(struct hid_parser *parser) +{ + int i; + + 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; +} + /* * Process a main item. */ @@ -552,6 +560,8 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) __u32 data; int ret; + hid_concatenate_usage_page(parser); + data = item_udata(item); switch (item->tag) { @@ -761,6 +771,8 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) __u32 data; int i; + hid_concatenate_usage_page(parser); + data = item_udata(item); switch (item->tag) { diff --git a/include/linux/hid.h b/include/linux/hid.h index d44a783629425..8b3e5e8a72fbc 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -414,6 +414,7 @@ struct hid_global { struct hid_local { unsigned usage[HID_MAX_USAGES]; /* usage array */ + u8 usage_size[HID_MAX_USAGES]; /* usage size array */ unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ unsigned usage_index; unsigned usage_minimum; -- 2.20.1