forked from len0rd/rockbox
First half of https://gerrit.rockbox.org/r/c/rockbox/+/570 Change-Id: Icc64dfd8194c18f69564ed5f8bf7dd70a4330eb9
185 lines
4.7 KiB
C
185 lines
4.7 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* 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);
|
|
}
|