Button queue handling is split from main button driver

First half of
https://gerrit.rockbox.org/r/c/rockbox/+/570

Change-Id: Icc64dfd8194c18f69564ed5f8bf7dd70a4330eb9
This commit is contained in:
William Wilgus 2024-11-27 17:11:03 -05:00
parent 5954a2fd48
commit da9d67a0fe
30 changed files with 266 additions and 221 deletions

View file

@ -45,11 +45,8 @@
#include "lcd.h" /* lcd_active() prototype */
#endif
struct event_queue button_queue SHAREDBSS_ATTR;
static long lastbtn; /* Last valid button status */
static long last_read; /* Last button status, for debouncing/filtering */
static intptr_t button_data; /* data value from last message dequeued */
static bool flipped; /* buttons can be flipped to match the LCD flip */
#ifdef HAVE_BACKLIGHT /* Filter first keypress function pointer */
@ -95,7 +92,7 @@ static void button_remote_post(void)
/* Post events for the remote control */
int btn = remote_control_rx();
if(btn)
button_try_post(btn, 0);
button_queue_try_post(btn, 0);
#endif
}
@ -104,8 +101,7 @@ static int hp_detect_callback(struct timeout *tmo)
{
/* Try to post only transistions */
const long id = tmo->data ? SYS_PHONE_PLUGGED : SYS_PHONE_UNPLUGGED;
queue_remove_from_head(&button_queue, id);
queue_post(&button_queue, id, 0);
button_queue_post_remove_head(id, 0);
return 0;
/*misc.c:hp_unplug_change*/
}
@ -116,8 +112,7 @@ static int lo_detect_callback(struct timeout *tmo)
{
/* Try to post only transistions */
const long id = tmo->data ? SYS_LINEOUT_PLUGGED : SYS_LINEOUT_UNPLUGGED;
queue_remove_from_head(&button_queue, id);
queue_post(&button_queue, id, 0);
button_queue_post_remove_head(id, 0);
return 0;
/*misc.c:lo_unplug_change*/
}
@ -151,40 +146,11 @@ static void check_audio_peripheral_state(void)
#endif
}
static bool button_try_post(int button, int data)
{
#ifdef HAVE_TOUCHSCREEN
/* one can swipe over the scren very quickly,
* for this to work we want to forget about old presses and
* only respect the very latest ones */
const bool force_post = true;
#else
/* Only post events if the queue is empty,
* to avoid afterscroll effects.
* i.e. don't post new buttons if previous ones haven't been
* processed yet - but always post releases */
const bool force_post = button & BUTTON_REL;
#endif
bool ret = queue_empty(&button_queue);
if (!ret && force_post)
{
queue_remove_from_head(&button_queue, button);
ret = true;
}
if (ret)
queue_post(&button_queue, button, data);
/* on touchscreen we posted unconditionally */
return ret;
}
#ifdef HAVE_BACKLIGHT
/* disabled function is shared between Main & Remote LCDs */
static bool filter_first_keypress_disabled(int button, int data)
{
button_try_post(button, data);
button_queue_try_post(button, data);
return false;
}
@ -248,17 +214,17 @@ static void button_tick(void)
#ifdef HAVE_REMOTE_LCD
if(diff & BUTTON_REMOTE)
if(!skip_remote_release)
button_try_post(BUTTON_REL | diff, data);
button_queue_try_post(BUTTON_REL | diff, data);
else
skip_remote_release = false;
else
#endif
if(!skip_release)
button_try_post(BUTTON_REL | diff, data);
button_queue_try_post(BUTTON_REL | diff, data);
else
skip_release = false;
#else
button_try_post(BUTTON_REL | diff, data);
button_queue_try_post(BUTTON_REL | diff, data);
#endif
}
else
@ -367,7 +333,7 @@ static void button_tick(void)
{
/* Only post repeat events if the queue is empty,
* to avoid afterscroll effects. */
if (button_try_post(BUTTON_REPEAT | btn, data))
if (button_queue_try_post(BUTTON_REPEAT | btn, data))
{
#ifdef HAVE_BACKLIGHT
#ifdef HAVE_REMOTE_LCD
@ -394,7 +360,7 @@ static void button_tick(void)
buttonlight_on();
}
#else /* no backlight, nothing to skip */
button_try_post(btn, data);
button_queue_try_post(btn, data);
#endif
post = false;
}
@ -412,119 +378,11 @@ static void button_tick(void)
lastdata = data;
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
static bool button_boosted = false;
static long button_unboost_tick;
#define BUTTON_UNBOOST_TMO HZ
static void button_boost(bool state)
{
if (state)
{
button_unboost_tick = current_tick + BUTTON_UNBOOST_TMO;
if (!button_boosted)
{
button_boosted = true;
cpu_boost(true);
}
}
else if (!state && button_boosted)
{
button_boosted = false;
cpu_boost(false);
}
}
static void button_queue_wait(struct queue_event *evp, int timeout)
{
/* Loop once after wait time if boosted in order to unboost and wait the
full remaining time */
do
{
int ticks = timeout;
if (ticks == 0) /* TIMEOUT_NOBLOCK */
;
else if (ticks > 0)
{
if (button_boosted && ticks > BUTTON_UNBOOST_TMO)
ticks = BUTTON_UNBOOST_TMO;
timeout -= ticks;
}
else /* TIMEOUT_BLOCK (ticks < 0) */
{
if (button_boosted)
ticks = BUTTON_UNBOOST_TMO;
}
queue_wait_w_tmo(&button_queue, evp, ticks);
if (evp->id != SYS_TIMEOUT)
{
/* GUI boost build gets immediate kick, otherwise at least 3
messages had to be there */
#ifndef HAVE_GUI_BOOST
if (queue_count(&button_queue) >= 2)
#endif
button_boost(true);
break;
}
if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
button_boost(false);
}
while (timeout);
}
#else /* ndef HAVE_ADJUSTABLE_CPU_FREQ */
static inline void button_queue_wait(struct queue_event *evp, int timeout)
{
queue_wait_w_tmo(&button_queue, evp, timeout);
}
#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
int button_queue_count( void )
{
return queue_count(&button_queue);
}
long button_get(bool block)
{
struct queue_event ev;
button_queue_wait(&ev, block ? TIMEOUT_BLOCK : TIMEOUT_NOBLOCK);
if (ev.id == SYS_TIMEOUT)
ev.id = BUTTON_NONE;
else
button_data = ev.data;
return ev.id;
}
long button_get_w_tmo(int ticks)
{
struct queue_event ev;
button_queue_wait(&ev, ticks);
if (ev.id == SYS_TIMEOUT)
ev.id = BUTTON_NONE;
else
button_data = ev.data;
return ev.id;
}
intptr_t button_get_data(void)
{
return button_data;
}
void button_init(void)
{
int temp;
/* Init used objects first */
queue_init(&button_queue, true);
button_queue_init();
/* hardware inits */
button_init_device();
@ -714,11 +572,6 @@ int button_status_wdata(int *pdata)
}
#endif
void button_clear_queue(void)
{
queue_clear(&button_queue);
}
#ifdef HAVE_TOUCHSCREEN
long touchscreen_last_touch(void)
{

View file

@ -0,0 +1,185 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Daniel Stenberg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "kernel.h"
#include "button.h"
static struct event_queue button_queue SHAREDBSS_ATTR;
static intptr_t button_data; /* data value from last message dequeued */
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
static bool button_boosted = false;
static long button_unboost_tick;
#define BUTTON_UNBOOST_TMO HZ
static void button_boost(bool state)
{
if (state)
{
/* update the unboost time each button_boost(true) call */
button_unboost_tick = current_tick + BUTTON_UNBOOST_TMO;
if (!button_boosted)
{
button_boosted = true;
cpu_boost(true);
}
}
else if (!button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
{
button_boosted = false;
cpu_boost(false);
}
}
static void button_queue_wait(struct queue_event *evp, int timeout)
{
/* Loop once after wait time if boosted in order to unboost and wait the
full remaining time */
do
{
int ticks = timeout;
if (ticks == TIMEOUT_NOBLOCK)
;
else if (ticks > 0)
{
if (button_boosted && ticks > BUTTON_UNBOOST_TMO)
ticks = BUTTON_UNBOOST_TMO;
timeout -= ticks;
}
else if (button_boosted) /* TIMEOUT_BLOCK (ticks < 0) */
{
ticks = BUTTON_UNBOOST_TMO;
}
queue_wait_w_tmo(&button_queue, evp, ticks);
if (evp->id != SYS_TIMEOUT)
{
/* GUI boost build gets immediate kick, otherwise at least 3
messages had to be there */
#ifndef HAVE_GUI_BOOST
if (queue_count(&button_queue) >= 2)
#endif
button_boost(true);
break;
}
button_boost(false);
}
while (timeout);
}
#else /* ndef HAVE_ADJUSTABLE_CPU_FREQ */
static inline void button_queue_wait(struct queue_event *evp, int timeout)
{
queue_wait_w_tmo(&button_queue, evp, timeout);
}
#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
void button_queue_post(long id, intptr_t data)
{
queue_post(&button_queue, id, data);
}
void button_queue_post_remove_head(long id, intptr_t data)
{
queue_remove_from_head(&button_queue, id);
queue_post(&button_queue, id, data);
}
bool button_queue_try_post(long button, int data)
{
#ifdef HAVE_TOUCHSCREEN
/* one can swipe over the scren very quickly,
* for this to work we want to forget about old presses and
* only respect the very latest ones */
const bool force_post = true;
#else
/* Only post events if the queue is empty,
* to avoid afterscroll effects.
* i.e. don't post new buttons if previous ones haven't been
* processed yet - but always post releases */
const bool force_post = button & BUTTON_REL;
#endif
if (!queue_empty(&button_queue))
{
if (force_post)
queue_remove_from_head(&button_queue, button);
else
return false;
}
queue_post(&button_queue, button, data);
/* on touchscreen we posted unconditionally */
return true;
}
int button_queue_count(void)
{
return queue_count(&button_queue);
}
bool button_queue_empty(void)
{
return queue_empty(&button_queue);
}
bool button_queue_full(void)
{
return queue_full(&button_queue);
}
void button_clear_queue(void)
{
queue_clear(&button_queue);
}
long button_get_w_tmo(int ticks)
{
struct queue_event ev;
button_queue_wait(&ev, ticks);
if (ev.id == SYS_TIMEOUT)
ev.id = BUTTON_NONE;
else
button_data = ev.data;
return ev.id;
}
long button_get(bool block)
{
return button_get_w_tmo(block ? TIMEOUT_BLOCK : TIMEOUT_NOBLOCK);
}
intptr_t button_get_data(void)
{
return button_data;
}
void INIT_ATTR button_queue_init(void)
{
queue_init(&button_queue, true);
}