From: srinivas pandruvada <srinivas.pandruvada@linux.intel.com>
To: Philipp Jungkamp <p.jungkamp@gmx.net>,
Jiri Kosina <jikos@kernel.org>,
Jonathan Cameron <jic23@kernel.org>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH v2 1/4] HID: hid-sensor-custom: Allow more custom iio sensors
Date: Fri, 18 Nov 2022 12:11:44 -0800 [thread overview]
Message-ID: <ab3dec07603f4edd2e77db3e3278fd204aa279ab.camel@linux.intel.com> (raw)
In-Reply-To: <20221117234302.3875-1-p.jungkamp@gmx.net>
On Fri, 2022-11-18 at 00:42 +0100, Philipp Jungkamp wrote:
> The known LUID table for established/known custom HID sensors was
> limited to sensors with "INTEL" as manufacturer. But some vendors
> such
> as Lenovo also include fairly standard iio sensors (e.g. ambient
> light)
> in their custom sensors.
>
> Expand the known custom sensors table by a tag used for the platform
> device name and match sensors based on the LUID as well as optionally
> on model and manufacturer properties.
> Introduce sensors from Lenovo's "Intelligent Sensing Solution" on the
> Lenovo Yoga 9 14IAP7 as an example.
>
> Signed-off-by: Philipp Jungkamp <p.jungkamp@gmx.net>
> ---
> Hello,
>
> here's a short summary of changes compared to v1:
>
> Added an additional commit which adds the LISS entries to the known
> custom sensors.
>
> Removed all unnecessary linebreaks from modified function calls and
> stayed
> below the 80 columns.
>
> Revisited the matching logic and removed the explicit error codes
> in favor of bools and forwarding the inner error.
>
> I noticed that the strange ENODATA return code was already redundant
> with
> the **known out parameter. So I removed it.
>
> Regards,
> Philipp Jungkamp
>
> drivers/hid/hid-sensor-custom.c | 211 +++++++++++++++++++++---------
> --
> include/linux/hid-sensor-ids.h | 1 +
> 2 files changed, 142 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-
> sensor-custom.c
> index 32c2306e240d..89e56913c92e 100644
> --- a/drivers/hid/hid-sensor-custom.c
> +++ b/drivers/hid/hid-sensor-custom.c
> @@ -5,6 +5,7 @@
> */
>
> #include <linux/ctype.h>
> +#include <linux/dmi.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/init.h>
> @@ -750,114 +751,184 @@ static void
> hid_sensor_custom_dev_if_remove(struct hid_sensor_custom
>
> }
>
> -/* luid defined in FW (e.g. ISH). Maybe used to identify sensor. */
> -static const char *const known_sensor_luid[] = { "020B000000000000"
> };
> +/*
> + * Match a known custom sensor.
> + * tag and luid is mandatory.
> + */
> +struct hid_sensor_custom_match {
> + const char *tag;
> + const char *luid;
> + const char *model;
> + const char *manufacturer;
> + bool check_dmi;
> + struct dmi_system_id dmi;
> +};
>
> -static int get_luid_table_index(unsigned char *usage_str)
> -{
> - int i;
> +/*
> + * Custom sensor properties used for matching.
> + */
> +struct hid_sensor_custom_properties {
> + u16 serial_num[HID_CUSTOM_MAX_FEATURE_BYTES];
> + u16 model[HID_CUSTOM_MAX_FEATURE_BYTES];
> + u16 manufacturer[HID_CUSTOM_MAX_FEATURE_BYTES];
> +};
> +
> +static const struct hid_sensor_custom_match
> hid_sensor_custom_known_table[] = {
> + /*
> + * Intel Integrated Sensor Hub (ISH)
> + */
> + { /* Intel ISH hinge */
> + .tag = "INT",
> + .luid = "020B000000000000",
> + .manufacturer = "INTEL",
> + },
> + {}
> +};
>
> - for (i = 0; i < ARRAY_SIZE(known_sensor_luid); i++) {
> - if (!strncmp(usage_str, known_sensor_luid[i],
> - strlen(known_sensor_luid[i])))
> - return i;
> +static bool hid_sensor_custom_prop_match_str(const u16 *prop, const
> char *match,
> + size_t count)
> +{
> + while (count-- && *prop && *match) {
> + if (*prop & 0xFF00 ||
> + *match != (char) *prop)
> + return false;
> + prop++;
> + match++;
> }
>
> - return -ENODEV;
> + return (count == -1) || *prop == (u16)*match;
> }
>
> -static int get_known_custom_sensor_index(struct
> hid_sensor_hub_device *hsdev)
> +static bool hid_sensor_custom_get_prop(struct hid_sensor_hub_device
> *hsdev,
> + u32 prop_usage_id, size_t
> prop_size,
> + u16 *prop)
> {
> - struct hid_sensor_hub_attribute_info sensor_manufacturer = {
> 0 };
> - struct hid_sensor_hub_attribute_info sensor_luid_info = { 0
> };
> + struct hid_sensor_hub_attribute_info prop_attr = { 0 };
> int report_size;
> int ret;
> - static u16 w_buf[HID_CUSTOM_MAX_FEATURE_BYTES];
> - static char buf[HID_CUSTOM_MAX_FEATURE_BYTES];
> - int i;
>
> - memset(w_buf, 0, sizeof(w_buf));
> - memset(buf, 0, sizeof(buf));
> + memset(prop, 0, prop_size);
>
> - /* get manufacturer info */
> - ret = sensor_hub_input_get_attribute_info(hsdev,
> - HID_FEATURE_REPORT, hsdev->usage,
> - HID_USAGE_SENSOR_PROP_MANUFACTURER,
> &sensor_manufacturer);
> + ret = sensor_hub_input_get_attribute_info(hsdev,
> HID_FEATURE_REPORT,
> + hsdev->usage,
> prop_usage_id,
> + &prop_attr);
> if (ret < 0)
> - return ret;
> + return 0;
>
> - report_size =
> - sensor_hub_get_feature(hsdev,
> sensor_manufacturer.report_id,
> - sensor_manufacturer.index,
> sizeof(w_buf),
> - w_buf);
> + report_size = sensor_hub_get_feature(hsdev,
> prop_attr.report_id,
> + prop_attr.index,
> prop_size, prop);
> if (report_size <= 0) {
> hid_err(hsdev->hdev,
> - "Failed to get sensor manufacturer info
> %d\n",
> + "Failed to get sensor property %08x %d\n",
> + prop_usage_id,
> report_size);
> - return -ENODEV;
> + return report_size;
> }
>
> - /* convert from wide char to char */
> - for (i = 0; i < ARRAY_SIZE(buf) - 1 && w_buf[i]; i++)
> - buf[i] = (char)w_buf[i];
> + return 0;
> +}
> +
> +static bool
> +hid_sensor_custom_do_match(struct hid_sensor_hub_device *hsdev,
> + const struct hid_sensor_custom_match
> *match,
> + const struct hid_sensor_custom_properties
> *prop)
> +{
> + struct dmi_system_id dmi[] = { match->dmi, { 0 } };
> +
> + if (!hid_sensor_custom_prop_match_str(prop->serial_num,
> "LUID:", 5) ||
> + !hid_sensor_custom_prop_match_str(prop->serial_num + 5,
> match->luid,
> +
> HID_CUSTOM_MAX_FEATURE_BYTES - 5))
> + return false;
> +
> + if (match->model &&
> + !hid_sensor_custom_prop_match_str(prop->model, match-
> >model,
> +
> HID_CUSTOM_MAX_FEATURE_BYTES))
> + return false;
>
> - /* ensure it's ISH sensor */
> - if (strncmp(buf, "INTEL", strlen("INTEL")))
> - return -ENODEV;
> + if (match->manufacturer &&
> + !hid_sensor_custom_prop_match_str(prop->manufacturer,
> match->manufacturer,
> +
> HID_CUSTOM_MAX_FEATURE_BYTES))
> + return false;
>
> - memset(w_buf, 0, sizeof(w_buf));
> - memset(buf, 0, sizeof(buf));
> + if (match->check_dmi && !dmi_check_system(dmi))
> + return false;
>
> - /* get real usage id */
> - ret = sensor_hub_input_get_attribute_info(hsdev,
> - HID_FEATURE_REPORT, hsdev->usage,
> - HID_USAGE_SENSOR_PROP_SERIAL_NUM,
> &sensor_luid_info);
> + return true;
> +}
> +
> +static int
> +hid_sensor_custom_properties_get(struct hid_sensor_hub_device
> *hsdev,
> + struct hid_sensor_custom_properties
> *prop)
> +{
> + int ret;
> +
> + ret = hid_sensor_custom_get_prop(hsdev,
> +
> HID_USAGE_SENSOR_PROP_SERIAL_NUM,
> +
> HID_CUSTOM_MAX_FEATURE_BYTES,
> + prop->serial_num);
> if (ret < 0)
> return ret;
>
> - report_size = sensor_hub_get_feature(hsdev,
> sensor_luid_info.report_id,
> - sensor_luid_info.index,
> sizeof(w_buf),
> - w_buf);
> - if (report_size <= 0) {
> - hid_err(hsdev->hdev, "Failed to get real usage info
> %d\n",
> - report_size);
> - return -ENODEV;
> - }
> + ret = hid_sensor_custom_get_prop(hsdev,
> + HID_USAGE_SENSOR_PROP_MODEL,
> +
> HID_CUSTOM_MAX_FEATURE_BYTES,
> + prop->model);
> + if (ret < 0)
> + return ret;
>
> - /* convert from wide char to char */
> - for (i = 0; i < ARRAY_SIZE(buf) - 1 && w_buf[i]; i++)
> - buf[i] = (char)w_buf[i];
> + ret = hid_sensor_custom_get_prop(hsdev,
> +
> HID_USAGE_SENSOR_PROP_MANUFACTURER,
> +
> HID_CUSTOM_MAX_FEATURE_BYTES,
> + prop->manufacturer);
> + if (ret < 0)
> + return ret;
>
> - if (strlen(buf) != strlen(known_sensor_luid[0]) + 5) {
> - hid_err(hsdev->hdev,
> - "%s luid length not match %zu != (%zu +
> 5)\n", __func__,
> - strlen(buf), strlen(known_sensor_luid[0]));
> - return -ENODEV;
> + return 0;
> +}
> +
> +static int
> +hid_sensor_custom_get_known(struct hid_sensor_hub_device *hsdev,
> + const struct hid_sensor_custom_match
> **known)
> +{
> + int ret;
> + const struct hid_sensor_custom_match *match =
> + hid_sensor_custom_known_table;
> + struct hid_sensor_custom_properties prop;
> +
> + ret = hid_sensor_custom_properties_get(hsdev, &prop);
> + if (ret < 0)
> + return ret;
> +
> + while (match->tag) {
> + if (hid_sensor_custom_do_match(hsdev, match, &prop))
> {
> + *known = match;
> + return 0;
> + }
> + match++;
> }
>
> - /* get table index with luid (not matching 'LUID: ' in luid)
> */
> - return get_luid_table_index(&buf[5]);
> + *known = NULL;
> + return 0;
The function returns 0, means success. The caller needn't look at some
other param to check if there was some known sensor exists.
return -ENODATA;
The caller will be simplified also. He doesn't have to check "match"
address.
> }
>
> static struct platform_device *
> hid_sensor_register_platform_device(struct platform_device *pdev,
> struct hid_sensor_hub_device
> *hsdev,
> - int index)
> + const struct
> hid_sensor_custom_match *match)
> {
> - char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
> + char real_usage[HID_SENSOR_USAGE_LENGTH];
> struct platform_device *custom_pdev;
> const char *dev_name;
> char *c;
>
> - /* copy real usage id */
> - memcpy(real_usage, known_sensor_luid[index], 4);
> + memcpy(real_usage, match->luid, 4);
> + real_usage[4] = '\0';
You already did init whole array above. Do you need this?
>
> - /* usage id are all lowcase */
> for (c = real_usage; *c != '\0'; c++)
> *c = tolower(*c);
>
> - /* HID-SENSOR-INT-REAL_USAGE_ID */
> - dev_name = kasprintf(GFP_KERNEL, "HID-SENSOR-INT-%s",
> real_usage);
> + dev_name = kasprintf(GFP_KERNEL, "HID-SENSOR-%s-%s",
> + match->tag, real_usage);
> if (!dev_name)
> return ERR_PTR(-ENOMEM);
>
> @@ -873,7 +944,7 @@ static int hid_sensor_custom_probe(struct
> platform_device *pdev)
> struct hid_sensor_custom *sensor_inst;
> struct hid_sensor_hub_device *hsdev = pdev-
> >dev.platform_data;
> int ret;
> - int index;
> + const struct hid_sensor_custom_match *match = NULL;
Not necessary to initialize, if you follow above advise to return error
for hid_sensor_custom_get_known()
>
> sensor_inst = devm_kzalloc(&pdev->dev, sizeof(*sensor_inst),
> GFP_KERNEL);
> @@ -888,10 +959,10 @@ static int hid_sensor_custom_probe(struct
> platform_device *pdev)
> mutex_init(&sensor_inst->mutex);
> platform_set_drvdata(pdev, sensor_inst);
>
> - index = get_known_custom_sensor_index(hsdev);
> - if (index >= 0 && index < ARRAY_SIZE(known_sensor_luid)) {
> + ret = hid_sensor_custom_get_known(hsdev, &match);
If hid_sensor_custom_get_known() returns error you don't need to check
validity of "match" in below if.
Thanks,
Srinivas
> + if (!ret && match) {
> sensor_inst->custom_pdev =
> - hid_sensor_register_platform_device(pdev,
> hsdev, index);
> + hid_sensor_register_platform_device(pdev,
> hsdev, match);
>
> ret = PTR_ERR_OR_ZERO(sensor_inst->custom_pdev);
> if (ret) {
> diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-
> sensor-ids.h
> index ac631159403a..13b1e65fbdcc 100644
> --- a/include/linux/hid-sensor-ids.h
> +++ b/include/linux/hid-sensor-ids.h
> @@ -132,6 +132,7 @@
> #define
> HID_USAGE_SENSOR_PROP_FRIENDLY_NAME 0x200301
> #define
> HID_USAGE_SENSOR_PROP_SERIAL_NUM 0x200307
> #define
> HID_USAGE_SENSOR_PROP_MANUFACTURER 0x200305
> +#define
> HID_USAGE_SENSOR_PROP_MODEL 0x200306
> #define
> HID_USAGE_SENSOR_PROP_REPORT_INTERVAL 0x20030E
> #define
> HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS 0x20030F
> #define
> HID_USAGE_SENSOR_PROP_SENSITIVITY_RANGE_PCT 0x200310
> --
> 2.38.1
>
next prev parent reply other threads:[~2022-11-18 20:12 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-16 12:11 PROBLEM: Lenovo ALS sensor disguised under custom usage Philipp Jungkamp
2022-11-16 23:19 ` [PATCH 1/3] HID: hid-sensor-custom: More custom iio sensors Philipp Jungkamp
2022-11-16 23:19 ` [PATCH 2/3] IIO: hid-sensor-als: Use generic usage Philipp Jungkamp
2022-11-17 15:09 ` Jonathan Cameron
2022-11-16 23:19 ` [PATCH 3/3] IIO: hid-sensor-prox: " Philipp Jungkamp
2022-11-17 15:14 ` Jonathan Cameron
2022-11-17 15:05 ` [PATCH 1/3] HID: hid-sensor-custom: More custom iio sensors Jonathan Cameron
2022-11-17 23:42 ` [PATCH v2 1/4] HID: hid-sensor-custom: Allow more " Philipp Jungkamp
2022-11-17 23:43 ` [PATCH v2 2/4] HID: hid-sensor-custom: Add LISS custom sensors Philipp Jungkamp
2022-11-18 20:16 ` srinivas pandruvada
2022-11-17 23:43 ` [PATCH v2 3/4] IIO: hid-sensor-als: Use generic usage Philipp Jungkamp
2022-11-17 23:43 ` [PATCH v2 4/4] IIO: hid-sensor-prox: " Philipp Jungkamp
2022-11-18 20:11 ` srinivas pandruvada [this message]
2022-11-17 23:48 ` [PATCH v3 1/4] HID: hid-sensor-custom: Allow more custom iio sensors Philipp Jungkamp
2022-11-17 23:48 ` [PATCH v3 2/4] HID: hid-sensor-custom: Add LISS custom sensors Philipp Jungkamp
2022-11-17 23:48 ` [PATCH v3 3/4] IIO: hid-sensor-als: Use generic usage Philipp Jungkamp
2022-11-18 20:23 ` srinivas pandruvada
2022-11-21 17:59 ` Jiri Kosina
2022-11-21 19:55 ` srinivas pandruvada
2022-11-23 17:16 ` Jonathan Cameron
2022-11-17 23:48 ` [PATCH v3 4/4] IIO: hid-sensor-prox: " Philipp Jungkamp
2022-11-18 20:26 ` srinivas pandruvada
2022-11-23 17:17 ` Jonathan Cameron
2022-11-23 17:08 ` [PATCH v3 1/4] HID: hid-sensor-custom: Allow more custom iio sensors Jonathan Cameron
2022-11-23 17:10 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ab3dec07603f4edd2e77db3e3278fd204aa279ab.camel@linux.intel.com \
--to=srinivas.pandruvada@linux.intel.com \
--cc=jic23@kernel.org \
--cc=jikos@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=p.jungkamp@gmx.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).