From: srinivas pandruvada <srinivas.pandruvada@linux.intel.com>
To: Daniel Paul Perinchery <danielpaulperinchery07012005@gmail.com>
Cc: Jiri Kosina <jikos@kernel.org>,
Jonathan Cameron <jic23@kernel.org>,
Benjamin Tissoires <bentiss@kernel.org>,
linux-input@vger.kernel.org, linux-iio@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: hid-sensor-custom: async notification for input-report sysfs attributes? (human presence / attention sensors)
Date: Mon, 27 Jul 2026 08:09:55 -0700 [thread overview]
Message-ID: <ec3395f45c07ae8afee181768828eb1c5f43c6f9.camel@linux.intel.com> (raw)
In-Reply-To: <CA+8Hp=Pv_zsYiPOhxTQ4NtQ-rMSyPKbWrGyU0d+d--BHpT87YQ@mail.gmail.com>
On Mon, 2026-07-27 at 11:38 +0530, Daniel Paul Perinchery wrote:
> Apologies — my last message went to Srinivas directly instead of the
> whole thread. Reposting here so it's visible to everyone and gets
> archived properly:
>
Hi,
> Hi,
>
> Thanks, this does help. I got it running and poll()/read() on
> /dev/HID-SENSOR-2000e1.3.auto does work. Two things I wasn't
> expecting, and wanted to check with you before going further:
>
> 1. The reports arrive continuously, roughly every 100ms, whether or
> not anything actually changed (matches property-report-interval on
> this device, which reads 100). property-reporting-state reads 2
> ("Threshold Events" per the HID sensor usage table), which I'd
> assumed
> meant the async path would only push on a real threshold crossing --
> but empirically it's a steady ~10Hz stream throughout, including long
> stretches where the sensor value isn't changing. Is that expected for
> this reporting-state value on the async report path specifically, or
> is there a separate control I'm missing to actually get
> sparse/event-only pushes out of the misc device (vs. it just always
> streaming at the configured report interval regardless of
> reporting-state)?
>
That is up to the hub. The reporting interval just tells that it should
not report less that that interval.
There is a sensitivity usage IDs 0x20030F , 0x200310 or 0x200310.
But they are optional, but if hub provides then, you can try that.
> 2. Every sample's usage_id field comes back as 0x002000e1, i.e. the
> collection's own usage (hsdev->usage), not the usage of whichever
> individual input field the report is carrying. This instance
> (2000e1.3.auto) has five input fields under it in sysfs
> (input-0-200201 through input-4-2004b1), so I think each 11-byte
> payload is a packed report containing some/all of those fields
> together, keyed by byte offset rather than by usage_id per sample. Is
> there a way to get the per-field usage or offset table from userspace
> (something under sysfs or a report-descriptor dump via hidraw) so I
> don't have to reverse-engineer the byte layout empirically by
> correlating against the -value sysfs files field by field?
>
There is no individual field reporting by the hub.
Thanks,
Srinivas
> My use case is specifically the human-presence input (2004b1) for a
> walk-away lock/dim daemon, so what I actually want is: wake up only
> when *that* field changes, ideally without also waking up for the
> other four fields' updates every 100ms if they're unrelated to
> presence. Let me know if that's realistically achievable with this
> interface as-is, or if it'd need something added on the kernel side
> after all (which circles back to my original question -- happy to go
> either direction depending on what you'd recommend).
>
> Thanks again for the pointer, this is a big step forward from polling
> sysfs.
>
> Daniel Paul
>
> On Fri, Jul 24, 2026 at 9:00 PM srinivas pandruvada
> <srinivas.pandruvada@linux.intel.com> wrote:
> >
> > Hi,
> >
> > On Fri, 2026-07-24 at 12:42 +0530, Daniel Paul Perinchery wrote:
> > > Hi,
> > >
> > > I've been investigating why userspace can't efficiently watch a
> > > hid-sensor-custom input-report value (specifically a human-
> > > presence
> > > sensor, HID usage 2000e1, on an AMD Sensor Fusion Hub / amd_sfh
> > > platform) for changes without polling, and wanted to check
> > > whether
> > > there's interest in closing this gap before I try to write
> > > anything.
> > >
> > > Setup: Lenovo IdeaPad Pro 5 14AKP10, AMD Ryzen AI 7 350, kernel
> > > 7.0.13
> > > (Debian/Parrot, but this is stock hid-sensor-custom.c). Presence
> > > and
> > > gaze/attention are exposed as separate logical sensors under the
> > > same
> > > physical hub (HID-SENSOR-2000e1.x.auto), each with the usual
> > > auto-generated input-N-<usage>-value sysfs attribute.
> > >
> > > What I found tracing show_value() in hid-sensor-custom.c: for
> > > input
> > > reports, it calls sensor_hub_input_attr_get_raw_value(...,
> > > report_id,
> > > SENSOR_HUB_SYNC, false) -- i.e. every read of the -value file
> > > issues
> > > a
> > > synchronous GET_REPORT to the hub and returns the live answer.
> > > There's
> > > no cached field backing that attribute, so there's nothing for a
> > > notify-on-change mechanism to attach to on that path.
> > >
> > > Separately, hid_sensor_capture_sample() *is* a genuine async
> > > callback
> > > fired on hub-pushed input reports, but as far as I can tell it
> > > only
> > > feeds the raw kfifo behind the driver's misc-device streaming
> > > interface (custom_dev), gated on test_bit(0,
> > > &sensor_inst->misc_opened). It doesn't appear to update any per-
> > > field
> > > cached value, so it isn't reachable from the sysfs show_value()
> > > path
> > > either.
> > >
> > > Net effect: there's no way for a userspace consumer to poll()/
> > > select() on the -value file and be woken only on real hardware
> > > events.
> >
> >
> > I have a test program for poll(). Attached poll part.
> >
> > #define DEVICE_PATH "/dev/HID-SENSOR-2000e1.2.auto"
> > #define BUFFER_SIZE 256
> >
> > int main(int argc, char *argv[])
> > {
> > int fd;
> > struct pollfd pfd;
> > char buffer[BUFFER_SIZE];
> > int ret;
> > struct sigaction sa;
> >
> > if (argc < 2) {
> > printf("syntax %s sample_interval\n", argv[0]);
> > exit(0);
> > }
> >
> >
> > // 1. Set up Ctrl+C signal handler
> > sa.sa_handler = handle_sigint;
> > sigemptyset(&sa.sa_mask);
> > sa.sa_flags = 0; // Don't use SA_RESTART so poll() unblocks
> > on
> > signal
> > if (sigaction(SIGINT, &sa, NULL) < 0) {
> > perror("Error setting up signal handler");
> > return -1;
> > }
> >
> > enable_sensor(1);
> >
> > // 2. Open the misc device
> > fd = open(DEVICE_PATH, O_RDONLY | O_NONBLOCK);
> > if (fd < 0) {
> > perror("Failed to open device");
> > return -1;
> > }
> >
> > // 3. Configure poll structure
> > pfd.fd = fd;
> > pfd.events = POLLIN;
> >
> > printf("Polling loop started. Press Ctrl+C to exit
> > safely.\n");
> >
> > // 4. Main event loop
> > while (keep_running) {
> > printf("Waiting for data...\n");
> >
> > ret = poll(&pfd, 1, -1);
> >
> > if (ret < 0) {
> > // Signal interrupted poll, loop will exit
> > if
> > it was SIGINT
> > continue;
> > }
> >
> > if (ret == 0) {
> > // Timeout reached with no data
> > continue;
> > }
> >
> > // 5. Handle readable data event
> > if (pfd.revents & POLLIN) {
> > rx_tsc = read_rdtsc();
> > ssize_t bytes_read = read(fd, buffer,
> > sizeof(buffer) - 1);
> > if (bytes_read > 0) {
> > time_t tm;
> >
> > buffer[bytes_read] = '\0'; // Null-
> > terminate string
> > printf("tm:%ld Received %ld bytes:
> > %s\n", time(&tm), (long)bytes_read, buffer);
> > read_time_stamp(buffer,
> > bytes_read);
> > } else if (bytes_read < 0) {
> > perror("Read error");
> > }
> > }
> > }
> >
> > // 6. Cleanup
> > printf("\nExiting program cleanly...\n");
> > close(fd);
> >
> > enable_sensor(0);
> >
> > return 0;
> > }
> >
> > Does it help.
> >
> > Thanks,
> > Srinivas
> >
> >
> > > The hub itself is already configured for threshold-based
> > > reporting
> > > (property-reporting-state = 2, i.e. "Threshold Events") in my
> > > case,
> > > so
> > > the inefficiency is entirely on the kernel/sysfs side --
> > > userspace
> > > has
> > > to fall back to timed re-reads of a synchronous, firmware-round-
> > > trip
> > > attribute, which is more expensive per-read than a typical cached
> > > sysfs value and awkward to size a safe polling interval for.
> > >
> > > This seems like a real gap for the presence/proximity use case
> > > specifically (walk-away lock, auto-dim, etc.), which is
> > > inherently
> > > event-oriented and is exactly the kind of feature vendors
> > > implement
> > > natively on Windows via push notifications from the same class of
> > > sensor.
> > >
> > > Before I put together a patch I wanted to ask: is there interest
> > > in
> > > adding async caching + sysfs_notify() (or sysfs_notify_dirent(),
> > > if
> > > attrs end up carrying a stored kernfs_node) for input-report
> > > values
> > > specifically, sourced from hid_sensor_capture_sample()'s existing
> > > async path? Rough shape as I see it:
> > >
> > > - add a cached "last input value" (+ a bool "valid") per
> > > relevant
> > > field in struct hid_sensor_custom_field
> > > - in hid_sensor_capture_sample(), in addition to (or instead
> > > of,
> > > behind a config/attr) feeding the misc-device fifo, decode and
> > > store
> > > the value for the matching field, then sysfs_notify() its -value
> > > attribute
> > > - leave show_value()'s SENSOR_HUB_SYNC path untouched for
> > > feature
> > > reports and for any input attrs that never get an async report,
> > > so
> > > nothing regresses for existing consumers
> > >
> > > Happy to be told this already exists via a different interface
> > > I've
> > > missed (I did look at whether this should just go through the IIO
> > > buffered/trigger interface instead, given some other hid-sensor-*
> > > drivers are IIO-backed -- but hid-sensor-custom exposes
> > > vendor/custom
> > > usages directly via this sysfs shape rather than IIO channels, so
> > > I
> > > wasn't sure that's the right layer to add it at). Also open to
> > > being
> > > told the misc-device/fifo interface is meant to be the async
> > > consumption path already and userspace tools should be using that
> > > instead of polling -value -- if so, is there existing
> > > tooling/docs
> > > for
> > > that path I should be pointing presence-detection use cases at?
> > >
> > > Not attaching a patch yet since I'd rather get a read on the
> > > right
> > > approach (and whether it's wanted at all) before writing one.
> > >
> > > Thanks,
> > > Daniel Paul
prev parent reply other threads:[~2026-07-27 15:10 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-24 7:12 hid-sensor-custom: async notification for input-report sysfs attributes? (human presence / attention sensors) Daniel Paul Perinchery
2026-07-24 15:30 ` srinivas pandruvada
2026-07-27 6:08 ` Daniel Paul Perinchery
2026-07-27 15:09 ` srinivas pandruvada [this message]
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=ec3395f45c07ae8afee181768828eb1c5f43c6f9.camel@linux.intel.com \
--to=srinivas.pandruvada@linux.intel.com \
--cc=bentiss@kernel.org \
--cc=danielpaulperinchery07012005@gmail.com \
--cc=jic23@kernel.org \
--cc=jikos@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/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