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