Thank you Tomek!

I devices to change the name from Dual Action to Multi Actions as
you suggested, two is already multi! :-D

I implemented all improvements suggested and added debouncing and the
option to let the user define the codes for keys being generated.

BR,

Alan


On Fri, Jul 11, 2025 at 8:13 PM Tomek CEDRO <to...@cedro.info> wrote:

> Very cool thank you Alan :-)
>
> On Sat, Jul 12, 2025 at 12:57 AM Alan C. Assis <acas...@gmail.com> wrote:
> >
> > Hi Tomek,
> >
> > I agree with you, but in this first "incarnation" it will support only
> two
> > actions, but people are invited to improve it later.
> >
> > Notice that I used INPUT_SBUTTON, so the "Dual Action" is just a Kconfig
> > message, easy to change. :-)
> >
> > Now my idea is just to add the improvements that Michał Łyszczek added in
> > the review and add a debouncing, because after more tests I discovered
> that
> > sometimes it was returning invalid key press.
> >
> > The driver itself is very simple, less than 300 LoC, so I hope everybody
> > can understand how it works.
> >
> > BR,
> >
> > Alan
> >
> > On Fri, Jul 11, 2025 at 7:39 PM Tomek CEDRO <to...@cedro.info> wrote:
> >
> > > Very cool thanks Alan! :-)
> > >
> > > I think there may be more actions with one button:
> > > 1. single click.
> > > 2. double click.
> > > 3. triple click.
> > > 4. short press.
> > > 5. long press.
> > > etc
> > >
> > > So it is not only dual action button, there may be more actions :-)
> > >
> > > It would be great if the driver could return event code or have return
> > > codes configurable (build time?) on selected actions. That would make
> > > things really versatile :-)
> > >
> > > Thanks :-)
> > > Tomek
> > >
> > >
> > > On Fri, Jul 11, 2025 at 11:26 PM Alan C. Assis <acas...@gmail.com>
> wrote:
> > > >
> > > > Hi Everyone,
> > > >
> > > > The driver is done: https://github.com/apache/nuttx/pull/16714
> > > >
> > > > I started using drivers/input/spq10kbd.c as reference, but then I
> > > realized
> > > > that there was already a keyboard_upper.c that I could use to send
> key
> > > > events/strokes.
> > > >
> > > > After that the driver was easier to implement than I thought
> initially.
> > > >
> > > > BR,
> > > >
> > > > Alan
> > > >
> > > > On Wed, Jul 9, 2025 at 10:16 AM Alan C. Assis <acas...@gmail.com>
> wrote:
> > > >
> > > > > Hi Everyone,
> > > > >
> > > > > Some years ago a customer asked me to develop a project with NuttX
> for
> > > > > this board that used a small OLED display and a single button.
> > > > > That button should be used to navigate in the menu, as a side note:
> > > > > initially he suggested: quick press and release will work as a
> ENTER
> > > and
> > > > > long press will work as TAB (move to other option),
> > > > > but while testing the application I released the was faster if
> quick
> > > press
> > > > > work as TAB and long press as enter.
> > > > >
> > > > > This video implements the same idea on a ESP32-Devkit board that
> also
> > > has
> > > > > only a single button: https://www.youtube.com/shorts/vfQLW-a2JhA
> > > > >
> > > > > The daemon that detect the button and define the type of input is
> > > > > something like this:
> > > > >
> > > > >   /* Define the notifications events */
> > > > >
> > > > >   btnevents.bn_press   = supported;
> > > > >   btnevents.bn_release = supported;
> > > > >
> > > > >   btnevents.bn_event.sigev_notify = SIGEV_SIGNAL;
> > > > >   btnevents.bn_event.sigev_signo  = CONFIG_INPUT_BUTTONS_SIGNO;
> > > > >
> > > > >   /* Register to receive a signal when buttons are
> pressed/released */
> > > > >
> > > > >   ret = ioctl(fd, BTNIOC_REGISTER,
> > > > >               (unsigned long)((uintptr_t)&btnevents));
> > > > >   if (ret < 0)
> > > > >     {
> > > > >       int errcode = errno;
> > > > >       printf("button_daemon: ERROR: ioctl(BTNIOC_SUPPORTED) failed:
> > > %d\n",
> > > > >              errcode);
> > > > >       goto errout_with_fd;
> > > > >     }
> > > > >
> > > > >   /* Ignore the default signal action */
> > > > >
> > > > >   signal(CONFIG_INPUT_BUTTONS_SIGNO, SIG_IGN);
> > > > >
> > > > >   /* Now loop forever, waiting BUTTONs events */
> > > > >
> > > > >   for (; ; )
> > > > >     {
> > > > >       struct siginfo value;
> > > > >       sigset_t set;
> > > > >
> > > > >       bool timeout;
> > > > >       int nbytes;
> > > > >
> > > > >       /* Wait for a signal */
> > > > >
> > > > >       sigemptyset(&set);
> > > > >       sigaddset(&set, CONFIG_INPUT_BUTTONS_SIGNO);
> > > > >       ret = sigwaitinfo(&set, &value);
> > > > >       if (ret < 0)
> > > > >         {
> > > > >           int errcode = errno;
> > > > >           printf("ERROR: sigwaitinfo() failed: %d\n", errcode);
> > > > >           goto errout_with_fd;
> > > > >         }
> > > > >
> > > > >       sample = (btn_buttonset_t)value.si_value.sival_int;
> > > > >
> > > > >       if (sample & 0x01)
> > > > >         {
> > > > >           /* Button pressed, start measuring time */
> > > > >
> > > > >           clock_gettime(CLOCK_REALTIME, &start);
> > > > >         }
> > > > >       else
> > > > >         {
> > > > >           /* Button released, calculate the elapsed time */
> > > > >
> > > > >           clock_gettime(CLOCK_REALTIME, &curr);
> > > > >
> > > > >           elapsed.tv_sec  = curr.tv_sec - start.tv_sec;
> > > > >           if (curr.tv_nsec >= start.tv_nsec)
> > > > >             {
> > > > >               elapsed.tv_nsec = curr.tv_nsec - start.tv_nsec;
> > > > >             }
> > > > >           else
> > > > >             {
> > > > >               unsigned long borrow = 1000000000 - start.tv_nsec;
> > > > >               elapsed.tv_sec--;
> > > > >               elapsed.tv_nsec = curr.tv_nsec + borrow;
> > > > >             }
> > > > >
> > > > >  unsigned long ftime = (elapsed.tv_sec * 1000000000) +
> elapsed.tv_nsec;
> > > > >
> > > > >  /*printf("Elapsed miliseconds = %d\n", ftime / 1000000);*/
> > > > >  if (ftime < 500000000)
> > > > >             {
> > > > >               input_event(INPUT_TAB);
> > > > >             }
> > > > >  else
> > > > >             {
> > > > >               input_event(INPUT_ENTER);
> > > > >             }
> > > > >         }
> > > > >
> > > > >       /* Make sure that everything is displayed */
> > > > >
> > > > >       fflush(stdout);
> > > > >
> > > > >       usleep(1000);
> > > > >     }
> > > > >
> > > > > But today while taking a shower and thinking about other subjects
> that
> > > > > fact came to mind and I asked myself: how to develop that thing in
> a
> > > more
> > > > > standard way to avoid the "kludge" above? (in fact it is not
> kludge,
> > > but we
> > > > > can improve, right?)
> > > > >
> > > > > So, I realized it would be nice to have a kind of "action button"
> > > driver
> > > > > that generates this kind of event (detecting long press and short
> > > press)
> > > > > automatically returning INPUT_ENTER or INPUT_TAB.
> > > > >
> > > > > In fact the driver will be more similar to djoystick.c than the
> > > ordinary
> > > > > buttons driver itself (for simplicity).
> > > > >
> > > > > Please let me know if someone already implemented something
> similar or
> > > > > other suggestions before I implement it.
> > > > >
> > > > > BR,
> > > > >
> > > > > Alan
> > > > >
> > >
> > >
> > >
> > > --
> > > CeDeROM, SQ7MHZ, http://www.tomek.cedro.info
> > >
>
>
>
> --
> CeDeROM, SQ7MHZ, http://www.tomek.cedro.info
>

Reply via email to