2002-04-16 13:37:50 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2002 by Daniel Stenberg
|
|
|
|
*
|
2008-06-28 18:10:04 +00:00
|
|
|
* 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.
|
2002-04-16 13:37:50 +00:00
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
2004-12-01 00:33:18 +00:00
|
|
|
|
2002-04-16 13:37:50 +00:00
|
|
|
/*
|
2004-12-01 00:33:18 +00:00
|
|
|
* Rockbox button functions
|
2002-04-16 13:37:50 +00:00
|
|
|
*/
|
|
|
|
|
2002-05-23 09:26:20 +00:00
|
|
|
#include <stdlib.h>
|
2002-04-16 13:37:50 +00:00
|
|
|
#include "config.h"
|
2002-06-26 21:31:47 +00:00
|
|
|
#include "system.h"
|
2002-04-16 13:37:50 +00:00
|
|
|
#include "button.h"
|
2002-05-23 09:26:20 +00:00
|
|
|
#include "kernel.h"
|
2007-03-11 10:52:36 +00:00
|
|
|
#include "thread.h"
|
2002-06-24 13:50:39 +00:00
|
|
|
#include "backlight.h"
|
2002-09-30 08:55:22 +00:00
|
|
|
#include "serial.h"
|
2002-10-16 12:40:30 +00:00
|
|
|
#include "power.h"
|
2004-06-22 07:16:31 +00:00
|
|
|
#include "powermgmt.h"
|
2010-06-21 16:53:00 +00:00
|
|
|
#ifdef HAVE_SDL
|
2009-09-23 16:59:56 +00:00
|
|
|
#include "button-sdl.h"
|
|
|
|
#else
|
2006-11-27 02:16:32 +00:00
|
|
|
#include "button-target.h"
|
2009-09-23 16:59:56 +00:00
|
|
|
#endif
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
2006-02-20 20:08:27 +00:00
|
|
|
#include "lcd-remote.h"
|
|
|
|
#endif
|
|
|
|
|
2007-10-16 22:00:51 +00:00
|
|
|
struct event_queue button_queue;
|
2002-05-23 09:26:20 +00:00
|
|
|
|
2005-01-27 11:49:29 +00:00
|
|
|
static long lastbtn; /* Last valid button status */
|
|
|
|
static long last_read; /* Last button status, for debouncing/filtering */
|
2007-07-22 21:02:24 +00:00
|
|
|
static intptr_t button_data; /* data value from last message dequeued */
|
2004-12-01 00:33:18 +00:00
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
|
|
static bool flipped; /* buttons can be flipped to match the LCD flip */
|
2003-12-20 10:00:37 +00:00
|
|
|
#endif
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-24 13:47:24 +00:00
|
|
|
static bool filter_first_keypress;
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
|
|
static bool remote_filter_first_keypress;
|
|
|
|
#endif
|
2007-04-12 22:12:13 +00:00
|
|
|
#endif /* HAVE_BACKLIGHT */
|
2006-11-27 02:16:32 +00:00
|
|
|
#ifdef HAVE_HEADPHONE_DETECTION
|
2008-01-27 21:13:04 +00:00
|
|
|
static bool phones_present = false;
|
2006-03-24 13:47:24 +00:00
|
|
|
#endif
|
2002-09-23 11:33:04 +00:00
|
|
|
|
2010-09-15 07:43:55 +00:00
|
|
|
/* how long until repeat kicks in, in centiseconds */
|
|
|
|
#define REPEAT_START (30*HZ/100)
|
2002-09-05 22:41:22 +00:00
|
|
|
|
2010-09-22 23:01:51 +00:00
|
|
|
#ifndef HAVE_TOUCHSCREEN
|
|
|
|
/* the next two make repeat "accelerate", which is nice for lists
|
|
|
|
* which begin to scroll a bit faster when holding until the
|
|
|
|
* real list accerelation kicks in (this smoothes acceleration)
|
|
|
|
*/
|
|
|
|
|
2010-09-15 07:43:55 +00:00
|
|
|
/* the speed repeat starts at, in centiseconds */
|
|
|
|
#define REPEAT_INTERVAL_START (16*HZ/100)
|
|
|
|
/* speed repeat finishes at, in centiseconds */
|
|
|
|
#define REPEAT_INTERVAL_FINISH (5*HZ/100)
|
2010-09-22 23:01:51 +00:00
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* on touchscreen it's different, scrolling is done by swiping over the
|
|
|
|
* screen (potentially very quickly) and is completely different from button
|
|
|
|
* targets
|
|
|
|
* So, on touchscreen we don't want to artifically slow down early repeats,
|
|
|
|
* it'd have the contrary effect of making rockbox appear lagging
|
|
|
|
*/
|
2010-09-22 23:28:26 +00:00
|
|
|
#define REPEAT_INTERVAL_START (5*HZ/100)
|
|
|
|
#define REPEAT_INTERVAL_FINISH (5*HZ/100)
|
2010-09-22 23:01:51 +00:00
|
|
|
#endif
|
2002-05-23 09:26:20 +00:00
|
|
|
|
2007-10-22 07:01:59 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
static int button_read(int *data);
|
|
|
|
#else
|
2002-05-23 09:26:20 +00:00
|
|
|
static int button_read(void);
|
2007-10-22 07:01:59 +00:00
|
|
|
#endif
|
2005-11-23 22:34:11 +00:00
|
|
|
|
2009-04-20 01:41:56 +00:00
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
2009-09-23 16:59:56 +00:00
|
|
|
static int last_touchscreen_touch;
|
2009-10-05 02:09:00 +00:00
|
|
|
static int lastdata = 0;
|
2009-04-20 01:41:56 +00:00
|
|
|
#endif
|
2009-09-23 17:26:42 +00:00
|
|
|
#if defined(HAVE_HEADPHONE_DETECTION)
|
2008-01-27 21:13:04 +00:00
|
|
|
static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */
|
|
|
|
/* This callback can be used for many different functions if needed -
|
|
|
|
just check to which object tmo points */
|
2009-01-21 02:44:20 +00:00
|
|
|
static int btn_detect_callback(struct timeout *tmo)
|
2008-01-27 21:13:04 +00:00
|
|
|
{
|
|
|
|
/* 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);
|
2009-01-21 02:44:20 +00:00
|
|
|
return 0;
|
2008-01-27 21:13:04 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-09-22 23:01:51 +00:00
|
|
|
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 */
|
2010-11-14 13:13:06 +00:00
|
|
|
const bool force_post = true;
|
2010-09-22 23:01:51 +00:00
|
|
|
#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
|
2010-11-14 13:13:06 +00:00
|
|
|
* processed yet - but always post releases */
|
|
|
|
const bool force_post = button & BUTTON_REL;
|
2010-09-22 23:01:51 +00:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2002-05-23 09:26:20 +00:00
|
|
|
static void button_tick(void)
|
|
|
|
{
|
2002-09-30 08:55:22 +00:00
|
|
|
static int count = 0;
|
|
|
|
static int repeat_speed = REPEAT_INTERVAL_START;
|
2003-02-25 03:03:55 +00:00
|
|
|
static int repeat_count = 0;
|
2002-09-30 08:55:22 +00:00
|
|
|
static bool repeat = false;
|
2006-02-19 13:34:12 +00:00
|
|
|
static bool post = false;
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-25 19:16:45 +00:00
|
|
|
static bool skip_release = false;
|
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
|
|
static bool skip_remote_release = false;
|
|
|
|
#endif
|
|
|
|
#endif
|
2002-07-27 11:24:22 +00:00
|
|
|
int diff;
|
2002-09-30 08:55:22 +00:00
|
|
|
int btn;
|
2007-10-22 07:01:59 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
int data = 0;
|
|
|
|
#else
|
|
|
|
const int data = 0;
|
|
|
|
#endif
|
2002-05-23 09:26:20 +00:00
|
|
|
|
2009-09-23 17:39:14 +00:00
|
|
|
#if defined(HAS_SERIAL_REMOTE) && !defined(SIMULATOR)
|
2002-09-30 08:55:22 +00:00
|
|
|
/* Post events for the remote control */
|
|
|
|
btn = remote_control_rx();
|
|
|
|
if(btn)
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(btn, 0);
|
2004-09-20 22:15:35 +00:00
|
|
|
#endif
|
2004-12-01 00:33:18 +00:00
|
|
|
|
2007-10-22 07:01:59 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
btn = button_read(&data);
|
|
|
|
#else
|
2006-04-06 18:58:42 +00:00
|
|
|
btn = button_read();
|
2007-10-22 07:01:59 +00:00
|
|
|
#endif
|
2008-01-27 21:13:04 +00:00
|
|
|
#if defined(HAVE_HEADPHONE_DETECTION)
|
|
|
|
if (headphones_inserted() != phones_present)
|
|
|
|
{
|
|
|
|
/* Use the autoresetting oneshot to debounce the detection signal */
|
|
|
|
phones_present = !phones_present;
|
|
|
|
timeout_register(&hp_detect_timeout, btn_detect_callback,
|
|
|
|
HZ, phones_present);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-04-06 18:58:42 +00:00
|
|
|
/* Find out if a key has been released */
|
|
|
|
diff = btn ^ lastbtn;
|
|
|
|
if(diff && (btn & diff) == 0)
|
|
|
|
{
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
2006-04-06 18:58:42 +00:00
|
|
|
if(diff & BUTTON_REMOTE)
|
|
|
|
if(!skip_remote_release)
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(BUTTON_REL | diff, data);
|
2006-03-25 19:16:45 +00:00
|
|
|
else
|
2006-04-06 18:58:42 +00:00
|
|
|
skip_remote_release = false;
|
|
|
|
else
|
2006-03-25 19:16:45 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
if(!skip_release)
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(BUTTON_REL | diff, data);
|
2006-04-06 18:58:42 +00:00
|
|
|
else
|
|
|
|
skip_release = false;
|
2006-03-25 19:16:45 +00:00
|
|
|
#else
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(BUTTON_REL | diff, data);
|
2006-03-25 19:16:45 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( btn )
|
2002-07-27 11:24:22 +00:00
|
|
|
{
|
2006-04-06 18:58:42 +00:00
|
|
|
/* normal keypress */
|
|
|
|
if ( btn != lastbtn )
|
2002-07-27 19:38:20 +00:00
|
|
|
{
|
2006-04-06 18:58:42 +00:00
|
|
|
post = true;
|
|
|
|
repeat = false;
|
|
|
|
repeat_speed = REPEAT_INTERVAL_START;
|
|
|
|
}
|
|
|
|
else /* repeat? */
|
|
|
|
{
|
|
|
|
if ( repeat )
|
2004-07-24 20:38:56 +00:00
|
|
|
{
|
2006-04-06 18:58:42 +00:00
|
|
|
if (!post)
|
|
|
|
count--;
|
|
|
|
if (count == 0) {
|
|
|
|
post = true;
|
|
|
|
/* yes we have repeat */
|
|
|
|
if (repeat_speed > REPEAT_INTERVAL_FINISH)
|
2004-07-24 20:38:56 +00:00
|
|
|
repeat_speed--;
|
2006-04-06 18:58:42 +00:00
|
|
|
count = repeat_speed;
|
2005-01-10 21:47:55 +00:00
|
|
|
|
2006-04-06 18:58:42 +00:00
|
|
|
repeat_count++;
|
2005-01-10 21:47:55 +00:00
|
|
|
|
2006-04-06 18:58:42 +00:00
|
|
|
/* Send a SYS_POWEROFF event if we have a device
|
|
|
|
which doesn't shut down easily with the OFF
|
|
|
|
key */
|
2004-10-12 11:00:19 +00:00
|
|
|
#ifdef HAVE_SW_POWEROFF
|
2010-05-29 21:54:14 +00:00
|
|
|
if ((btn & POWEROFF_BUTTON
|
2006-11-27 02:16:32 +00:00
|
|
|
#ifdef RC_POWEROFF_BUTTON
|
2006-09-12 15:56:31 +00:00
|
|
|
|| btn == RC_POWEROFF_BUTTON
|
2005-06-08 18:01:14 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
) &&
|
2007-02-18 05:32:06 +00:00
|
|
|
#if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING)
|
2006-04-06 18:58:42 +00:00
|
|
|
!charger_inserted() &&
|
2003-02-25 03:03:55 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
repeat_count > POWEROFF_COUNT)
|
|
|
|
{
|
|
|
|
/* Tell the main thread that it's time to
|
|
|
|
power off */
|
|
|
|
sys_poweroff();
|
|
|
|
|
|
|
|
/* Safety net for players without hardware
|
|
|
|
poweroff */
|
2010-06-21 16:53:00 +00:00
|
|
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
2006-04-06 18:58:42 +00:00
|
|
|
if(repeat_count > POWEROFF_COUNT * 10)
|
|
|
|
power_off();
|
2009-09-23 16:59:56 +00:00
|
|
|
#endif
|
2004-07-24 20:38:56 +00:00
|
|
|
}
|
2006-04-06 18:58:42 +00:00
|
|
|
#endif
|
2002-05-23 11:59:30 +00:00
|
|
|
}
|
2006-04-06 18:58:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (count++ > REPEAT_START)
|
2002-07-24 15:21:08 +00:00
|
|
|
{
|
2006-04-06 18:58:42 +00:00
|
|
|
post = true;
|
|
|
|
repeat = true;
|
|
|
|
repeat_count = 0;
|
|
|
|
/* initial repeat */
|
|
|
|
count = REPEAT_INTERVAL_START;
|
2002-07-27 19:38:20 +00:00
|
|
|
}
|
2010-09-22 23:01:51 +00:00
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
|
|
else if (lastdata != data && btn == lastbtn)
|
|
|
|
{ /* only coordinates changed, post anyway */
|
|
|
|
if (touchscreen_get_mode() == TOUCHSCREEN_POINT)
|
|
|
|
post = true;
|
|
|
|
}
|
|
|
|
#endif
|
2002-05-23 11:59:30 +00:00
|
|
|
}
|
2006-04-06 18:58:42 +00:00
|
|
|
}
|
|
|
|
if ( post )
|
|
|
|
{
|
|
|
|
if (repeat)
|
2004-07-24 20:38:56 +00:00
|
|
|
{
|
2006-04-06 18:58:42 +00:00
|
|
|
/* Only post repeat events if the queue is empty,
|
|
|
|
* to avoid afterscroll effects. */
|
2010-09-22 23:01:51 +00:00
|
|
|
if (button_try_post(BUTTON_REPEAT | btn, data))
|
2006-02-19 13:34:12 +00:00
|
|
|
{
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
2006-04-06 18:58:42 +00:00
|
|
|
skip_remote_release = false;
|
2006-03-25 19:16:45 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
skip_release = false;
|
|
|
|
#endif
|
|
|
|
post = false;
|
2006-02-19 13:34:12 +00:00
|
|
|
}
|
2006-04-06 18:58:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
2006-04-06 18:58:42 +00:00
|
|
|
if (btn & BUTTON_REMOTE) {
|
2008-04-02 22:16:14 +00:00
|
|
|
if (!remote_filter_first_keypress
|
|
|
|
|| is_remote_backlight_on(false)
|
2006-03-25 19:16:45 +00:00
|
|
|
#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
|
2008-04-02 22:16:14 +00:00
|
|
|
|| (remote_type()==REMOTETYPE_H300_NONLCD)
|
2006-03-25 19:16:45 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
)
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(btn, data);
|
2006-04-06 18:58:42 +00:00
|
|
|
else
|
|
|
|
skip_remote_release = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
2008-04-02 22:16:14 +00:00
|
|
|
if (!filter_first_keypress || is_backlight_on(false)
|
2007-05-20 14:03:42 +00:00
|
|
|
#if BUTTON_REMOTE
|
2008-04-02 22:16:14 +00:00
|
|
|
|| (btn & BUTTON_REMOTE)
|
2007-05-20 14:03:42 +00:00
|
|
|
#endif
|
|
|
|
)
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(btn, data);
|
2006-03-25 19:16:45 +00:00
|
|
|
else
|
2006-04-06 18:58:42 +00:00
|
|
|
skip_release = true;
|
2006-03-25 19:16:45 +00:00
|
|
|
#else /* no backlight, nothing to skip */
|
2010-09-22 23:01:51 +00:00
|
|
|
button_try_post(btn, data);
|
2006-03-24 13:47:24 +00:00
|
|
|
#endif
|
2006-04-06 18:58:42 +00:00
|
|
|
post = false;
|
|
|
|
}
|
2005-04-15 16:16:26 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
2006-04-06 18:58:42 +00:00
|
|
|
if(btn & BUTTON_REMOTE)
|
|
|
|
remote_backlight_on();
|
|
|
|
else
|
2005-04-15 16:16:26 +00:00
|
|
|
#endif
|
2007-09-25 20:24:38 +00:00
|
|
|
{
|
2006-04-06 18:58:42 +00:00
|
|
|
backlight_on();
|
2007-09-25 20:24:38 +00:00
|
|
|
#ifdef HAVE_BUTTON_LIGHT
|
2007-10-07 15:02:02 +00:00
|
|
|
buttonlight_on();
|
2007-09-25 20:24:38 +00:00
|
|
|
#endif
|
|
|
|
}
|
2005-01-10 21:47:55 +00:00
|
|
|
|
2006-04-06 18:58:42 +00:00
|
|
|
reset_poweroff_timer();
|
2002-06-24 13:50:39 +00:00
|
|
|
}
|
2002-05-23 11:59:30 +00:00
|
|
|
}
|
2006-04-06 18:58:42 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
repeat = false;
|
|
|
|
count = 0;
|
|
|
|
}
|
2002-05-23 09:26:20 +00:00
|
|
|
}
|
2006-04-06 18:58:42 +00:00
|
|
|
lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT);
|
2009-10-05 02:17:27 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
2009-10-05 02:09:00 +00:00
|
|
|
lastdata = data;
|
2009-10-05 02:17:27 +00:00
|
|
|
#endif
|
2002-05-23 09:26:20 +00:00
|
|
|
}
|
|
|
|
|
2007-03-11 22:27:35 +00:00
|
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
|
|
|
static void button_boost(bool state)
|
2007-03-11 10:52:36 +00:00
|
|
|
{
|
|
|
|
static bool boosted = false;
|
|
|
|
|
|
|
|
if (state && !boosted)
|
|
|
|
{
|
|
|
|
cpu_boost(true);
|
|
|
|
boosted = true;
|
|
|
|
}
|
|
|
|
else if (!state && boosted)
|
|
|
|
{
|
|
|
|
cpu_boost(false);
|
|
|
|
boosted = false;
|
|
|
|
}
|
|
|
|
}
|
2007-03-11 22:27:35 +00:00
|
|
|
#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
|
2007-03-11 10:52:36 +00:00
|
|
|
|
2007-10-09 21:28:51 +00:00
|
|
|
int button_queue_count( void )
|
2007-10-09 20:42:20 +00:00
|
|
|
{
|
|
|
|
return queue_count(&button_queue);
|
|
|
|
}
|
|
|
|
|
2005-02-07 22:57:05 +00:00
|
|
|
long button_get(bool block)
|
2002-05-23 09:26:20 +00:00
|
|
|
{
|
2007-10-16 01:25:17 +00:00
|
|
|
struct queue_event ev;
|
2007-03-11 10:52:36 +00:00
|
|
|
int pending_count = queue_count(&button_queue);
|
2007-03-11 22:27:35 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
2007-03-11 10:52:36 +00:00
|
|
|
/* Control the CPU boost trying to keep queue empty. */
|
|
|
|
if (pending_count == 0)
|
|
|
|
button_boost(false);
|
|
|
|
else if (pending_count > 2)
|
|
|
|
button_boost(true);
|
2007-03-11 22:27:35 +00:00
|
|
|
#endif
|
2007-03-11 10:52:36 +00:00
|
|
|
|
|
|
|
if ( block || pending_count )
|
2004-12-01 00:33:18 +00:00
|
|
|
{
|
2002-05-23 09:26:20 +00:00
|
|
|
queue_wait(&button_queue, &ev);
|
2007-03-26 16:55:17 +00:00
|
|
|
|
2007-07-22 21:02:24 +00:00
|
|
|
button_data = ev.data;
|
2002-05-23 11:59:30 +00:00
|
|
|
return ev.id;
|
|
|
|
}
|
2007-03-11 10:52:36 +00:00
|
|
|
|
2002-05-23 11:59:30 +00:00
|
|
|
return BUTTON_NONE;
|
2002-05-23 09:26:20 +00:00
|
|
|
}
|
2002-04-16 13:37:50 +00:00
|
|
|
|
2005-02-07 22:57:05 +00:00
|
|
|
long button_get_w_tmo(int ticks)
|
2002-08-07 07:22:44 +00:00
|
|
|
{
|
2007-10-16 01:25:17 +00:00
|
|
|
struct queue_event ev;
|
2007-03-11 10:52:36 +00:00
|
|
|
|
2007-03-11 22:27:35 +00:00
|
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
2007-03-11 10:52:36 +00:00
|
|
|
/* Be sure to keep boosted state. */
|
|
|
|
if (!queue_empty(&button_queue))
|
|
|
|
return button_get(true);
|
|
|
|
|
|
|
|
button_boost(false);
|
2007-03-11 22:27:35 +00:00
|
|
|
#endif
|
2007-03-11 10:52:36 +00:00
|
|
|
|
2003-02-14 09:44:34 +00:00
|
|
|
queue_wait_w_tmo(&button_queue, &ev, ticks);
|
2007-07-22 21:02:24 +00:00
|
|
|
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;
|
2002-08-07 07:22:44 +00:00
|
|
|
}
|
|
|
|
|
2004-12-01 00:33:18 +00:00
|
|
|
void button_init(void)
|
2004-11-18 23:22:45 +00:00
|
|
|
{
|
2008-01-27 21:13:04 +00:00
|
|
|
/* Init used objects first */
|
|
|
|
queue_init(&button_queue, true);
|
|
|
|
|
2007-10-22 07:01:59 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
int temp;
|
|
|
|
#endif
|
2004-12-01 00:33:18 +00:00
|
|
|
/* hardware inits */
|
2006-07-27 13:27:31 +00:00
|
|
|
button_init_device();
|
2006-11-27 02:16:32 +00:00
|
|
|
|
2007-10-22 07:01:59 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
button_read(&temp);
|
|
|
|
lastbtn = button_read(&temp);
|
|
|
|
#else
|
2005-06-29 12:23:09 +00:00
|
|
|
button_read();
|
|
|
|
lastbtn = button_read();
|
2007-10-22 07:01:59 +00:00
|
|
|
#endif
|
|
|
|
|
2004-11-18 23:22:45 +00:00
|
|
|
reset_poweroff_timer();
|
2004-12-01 00:33:18 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
2004-11-18 23:22:45 +00:00
|
|
|
flipped = false;
|
2004-12-01 00:33:18 +00:00
|
|
|
#endif
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-24 13:47:24 +00:00
|
|
|
filter_first_keypress = false;
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
|
|
remote_filter_first_keypress = false;
|
|
|
|
#endif
|
2006-03-24 13:47:24 +00:00
|
|
|
#endif
|
2009-04-20 01:41:56 +00:00
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
|
|
last_touchscreen_touch = 0xffff;
|
|
|
|
#endif
|
2008-01-27 21:13:04 +00:00
|
|
|
/* Start polling last */
|
|
|
|
tick_add_task(button_tick);
|
2004-11-18 23:22:45 +00:00
|
|
|
}
|
|
|
|
|
2008-05-10 18:00:11 +00:00
|
|
|
#ifdef BUTTON_DRIVER_CLOSE
|
|
|
|
void button_close(void)
|
|
|
|
{
|
|
|
|
tick_remove_task(button_tick);
|
|
|
|
}
|
|
|
|
#endif /* BUTTON_DRIVER_CLOSE */
|
|
|
|
|
2009-09-23 16:59:56 +00:00
|
|
|
#ifdef HAVE_LCD_FLIP
|
2004-11-18 23:22:45 +00:00
|
|
|
/*
|
2006-04-01 23:48:03 +00:00
|
|
|
* helper function to swap LEFT/RIGHT, UP/DOWN (if present), and F1/F3 (Recorder)
|
2004-11-18 23:22:45 +00:00
|
|
|
*/
|
2009-10-05 17:53:45 +00:00
|
|
|
static int button_flip(int button)
|
2004-11-18 23:22:45 +00:00
|
|
|
{
|
2010-05-15 21:02:47 +00:00
|
|
|
int newbutton = button;
|
2004-11-18 23:22:45 +00:00
|
|
|
|
2010-06-21 16:53:00 +00:00
|
|
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
2010-05-15 21:02:47 +00:00
|
|
|
newbutton &=
|
2006-04-01 23:48:03 +00:00
|
|
|
~(BUTTON_LEFT | BUTTON_RIGHT
|
|
|
|
#if defined(BUTTON_UP) && defined(BUTTON_DOWN)
|
|
|
|
| BUTTON_UP | BUTTON_DOWN
|
|
|
|
#endif
|
2008-01-10 08:08:31 +00:00
|
|
|
#if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD)
|
|
|
|
| BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD
|
2006-09-25 18:45:03 +00:00
|
|
|
#endif
|
2004-12-01 00:33:18 +00:00
|
|
|
#if CONFIG_KEYPAD == RECORDER_PAD
|
|
|
|
| BUTTON_F1 | BUTTON_F3
|
2008-09-03 22:30:30 +00:00
|
|
|
#endif
|
|
|
|
#if CONFIG_KEYPAD == SANSA_C200_PAD
|
|
|
|
| BUTTON_VOL_UP | BUTTON_VOL_DOWN
|
2009-07-07 03:26:57 +00:00
|
|
|
#endif
|
|
|
|
#if CONFIG_KEYPAD == PHILIPS_SA9200_PAD
|
|
|
|
| BUTTON_VOL_UP | BUTTON_VOL_DOWN
|
|
|
|
| BUTTON_NEXT | BUTTON_PREV
|
2004-12-01 00:33:18 +00:00
|
|
|
#endif
|
|
|
|
);
|
2004-11-18 23:22:45 +00:00
|
|
|
|
|
|
|
if (button & BUTTON_LEFT)
|
|
|
|
newbutton |= BUTTON_RIGHT;
|
|
|
|
if (button & BUTTON_RIGHT)
|
|
|
|
newbutton |= BUTTON_LEFT;
|
2006-04-01 23:48:03 +00:00
|
|
|
#if defined(BUTTON_UP) && defined(BUTTON_DOWN)
|
|
|
|
if (button & BUTTON_UP)
|
|
|
|
newbutton |= BUTTON_DOWN;
|
|
|
|
if (button & BUTTON_DOWN)
|
|
|
|
newbutton |= BUTTON_UP;
|
|
|
|
#endif
|
2008-01-10 08:08:31 +00:00
|
|
|
#if defined(BUTTON_SCROLL_BACK) && defined(BUTTON_SCROLL_FWD)
|
|
|
|
if (button & BUTTON_SCROLL_BACK)
|
|
|
|
newbutton |= BUTTON_SCROLL_FWD;
|
|
|
|
if (button & BUTTON_SCROLL_FWD)
|
|
|
|
newbutton |= BUTTON_SCROLL_BACK;
|
2006-09-25 18:45:03 +00:00
|
|
|
#endif
|
2004-12-01 00:33:18 +00:00
|
|
|
#if CONFIG_KEYPAD == RECORDER_PAD
|
|
|
|
if (button & BUTTON_F1)
|
|
|
|
newbutton |= BUTTON_F3;
|
|
|
|
if (button & BUTTON_F3)
|
|
|
|
newbutton |= BUTTON_F1;
|
|
|
|
#endif
|
2008-09-03 22:30:30 +00:00
|
|
|
#if CONFIG_KEYPAD == SANSA_C200_PAD
|
|
|
|
if (button & BUTTON_VOL_UP)
|
|
|
|
newbutton |= BUTTON_VOL_DOWN;
|
|
|
|
if (button & BUTTON_VOL_DOWN)
|
|
|
|
newbutton |= BUTTON_VOL_UP;
|
|
|
|
#endif
|
2009-07-07 03:26:57 +00:00
|
|
|
#if CONFIG_KEYPAD == PHILIPS_SA9200_PAD
|
|
|
|
if (button & BUTTON_VOL_UP)
|
|
|
|
newbutton |= BUTTON_VOL_DOWN;
|
|
|
|
if (button & BUTTON_VOL_DOWN)
|
|
|
|
newbutton |= BUTTON_VOL_UP;
|
|
|
|
if (button & BUTTON_NEXT)
|
|
|
|
newbutton |= BUTTON_PREV;
|
|
|
|
if (button & BUTTON_PREV)
|
|
|
|
newbutton |= BUTTON_NEXT;
|
|
|
|
#endif
|
2010-05-15 21:02:47 +00:00
|
|
|
#endif /* !SIMULATOR */
|
2004-11-18 23:22:45 +00:00
|
|
|
return newbutton;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set the flip attribute
|
|
|
|
* better only call this when the queue is empty
|
|
|
|
*/
|
2009-10-05 17:53:45 +00:00
|
|
|
void button_set_flip(bool flip)
|
2004-11-18 23:22:45 +00:00
|
|
|
{
|
|
|
|
if (flip != flipped) /* not the current setting */
|
|
|
|
{
|
|
|
|
/* avoid race condition with the button_tick() */
|
2008-03-26 01:50:41 +00:00
|
|
|
int oldlevel = disable_irq_save();
|
2009-10-05 17:53:45 +00:00
|
|
|
lastbtn = button_flip(lastbtn);
|
2004-11-18 23:22:45 +00:00
|
|
|
flipped = flip;
|
2008-03-26 01:50:41 +00:00
|
|
|
restore_irq(oldlevel);
|
2004-11-18 23:22:45 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-23 16:59:56 +00:00
|
|
|
#endif /* HAVE_LCD_FLIP */
|
2004-12-01 00:33:18 +00:00
|
|
|
|
2007-04-12 22:12:13 +00:00
|
|
|
#ifdef HAVE_BACKLIGHT
|
2006-03-24 13:47:24 +00:00
|
|
|
void set_backlight_filter_keypress(bool value)
|
|
|
|
{
|
|
|
|
filter_first_keypress = value;
|
|
|
|
}
|
2006-03-25 19:16:45 +00:00
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
|
|
void set_remote_backlight_filter_keypress(bool value)
|
|
|
|
{
|
|
|
|
remote_filter_first_keypress = value;
|
|
|
|
}
|
|
|
|
#endif
|
2006-03-24 13:47:24 +00:00
|
|
|
#endif
|
|
|
|
|
2004-11-18 23:22:45 +00:00
|
|
|
/*
|
|
|
|
* Get button pressed from hardware
|
|
|
|
*/
|
2007-10-22 07:01:59 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
static int button_read(int *data)
|
|
|
|
{
|
|
|
|
int btn = button_read_device(data);
|
|
|
|
#else
|
2004-11-18 23:22:45 +00:00
|
|
|
static int button_read(void)
|
|
|
|
{
|
2006-11-27 02:16:32 +00:00
|
|
|
int btn = button_read_device();
|
2007-10-22 07:01:59 +00:00
|
|
|
#endif
|
2004-11-18 23:22:45 +00:00
|
|
|
int retval;
|
2004-12-01 00:33:18 +00:00
|
|
|
|
2009-09-23 16:59:56 +00:00
|
|
|
#ifdef HAVE_LCD_FLIP
|
2004-10-08 17:02:16 +00:00
|
|
|
if (btn && flipped)
|
2009-10-05 17:53:45 +00:00
|
|
|
btn = button_flip(btn); /* swap upside down */
|
2009-09-23 16:59:56 +00:00
|
|
|
#endif /* HAVE_LCD_FLIP */
|
|
|
|
|
2009-04-20 01:41:56 +00:00
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
|
|
if (btn & BUTTON_TOUCHSCREEN)
|
|
|
|
last_touchscreen_touch = current_tick;
|
|
|
|
#endif
|
2004-09-23 22:36:15 +00:00
|
|
|
/* Filter the button status. It is only accepted if we get the same
|
|
|
|
status twice in a row. */
|
2008-08-23 09:46:38 +00:00
|
|
|
#ifndef HAVE_TOUCHSCREEN
|
2004-12-01 00:33:18 +00:00
|
|
|
if (btn != last_read)
|
2007-10-22 07:01:59 +00:00
|
|
|
retval = lastbtn;
|
2004-09-23 22:36:15 +00:00
|
|
|
else
|
2007-10-22 07:01:59 +00:00
|
|
|
#endif
|
2004-09-23 22:36:15 +00:00
|
|
|
retval = btn;
|
|
|
|
last_read = btn;
|
|
|
|
|
|
|
|
return retval;
|
2004-09-10 10:51:54 +00:00
|
|
|
}
|
|
|
|
|
2004-07-21 08:02:23 +00:00
|
|
|
int button_status(void)
|
|
|
|
{
|
2005-01-27 11:53:13 +00:00
|
|
|
return lastbtn;
|
2004-07-21 08:02:23 +00:00
|
|
|
}
|
|
|
|
|
2009-10-05 02:09:00 +00:00
|
|
|
#ifdef HAVE_BUTTON_DATA
|
|
|
|
int button_status_wdata(int *pdata)
|
|
|
|
{
|
|
|
|
*pdata = lastdata;
|
|
|
|
return lastbtn;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-07-21 08:02:23 +00:00
|
|
|
void button_clear_queue(void)
|
|
|
|
{
|
2004-09-01 06:24:57 +00:00
|
|
|
queue_clear(&button_queue);
|
2004-07-21 08:02:23 +00:00
|
|
|
}
|
2007-07-22 21:02:24 +00:00
|
|
|
|
2009-04-20 01:41:56 +00:00
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
|
|
int touchscreen_last_touch(void)
|
|
|
|
{
|
|
|
|
return last_touchscreen_touch;
|
|
|
|
}
|
|
|
|
#endif
|
2007-08-12 19:49:03 +00:00
|
|
|
|
2009-03-02 19:25:50 +00:00
|
|
|
#ifdef HAVE_WHEEL_ACCELERATION
|
2007-11-19 11:05:54 +00:00
|
|
|
/* WHEEL_ACCEL_FACTOR = 2^16 / WHEEL_ACCEL_START */
|
|
|
|
#define WHEEL_ACCEL_FACTOR (1<<16)/WHEEL_ACCEL_START
|
2007-07-22 21:02:24 +00:00
|
|
|
/**
|
|
|
|
* data:
|
|
|
|
* [31] Use acceleration
|
|
|
|
* [30:24] Message post count (skipped + 1) (1-127)
|
2007-11-19 11:05:54 +00:00
|
|
|
* [23:0] Velocity - degree/sec
|
2007-07-22 21:02:24 +00:00
|
|
|
*
|
2007-11-19 11:05:54 +00:00
|
|
|
* WHEEL_ACCEL_FACTOR:
|
|
|
|
* Value in degree/sec -- configurable via settings -- above which
|
|
|
|
* the accelerated scrolling starts. Factor is internally scaled by
|
|
|
|
* 1<<16 in respect to the following 32bit integer operations.
|
2007-07-22 21:02:24 +00:00
|
|
|
*/
|
2007-11-19 11:05:54 +00:00
|
|
|
int button_apply_acceleration(const unsigned int data)
|
2007-07-22 21:02:24 +00:00
|
|
|
{
|
|
|
|
int delta = (data >> 24) & 0x7f;
|
|
|
|
|
|
|
|
if ((data & (1 << 31)) != 0)
|
|
|
|
{
|
2007-11-19 11:05:54 +00:00
|
|
|
/* read driver's velocity from data */
|
2007-07-22 21:02:24 +00:00
|
|
|
unsigned int v = data & 0xffffff;
|
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
/* v = 28.4 fixed point */
|
|
|
|
v = (WHEEL_ACCEL_FACTOR * v)>>(16-4);
|
|
|
|
|
|
|
|
/* Calculate real numbers item to scroll based upon acceleration
|
|
|
|
* setting, use correct roundoff */
|
|
|
|
#if (WHEEL_ACCELERATION == 1)
|
|
|
|
v = (v*v + (1<< 7))>> 8;
|
|
|
|
#elif (WHEEL_ACCELERATION == 2)
|
|
|
|
v = (v*v*v + (1<<11))>>12;
|
|
|
|
#elif (WHEEL_ACCELERATION == 3)
|
|
|
|
v = (v*v*v*v + (1<<15))>>16;
|
|
|
|
#endif
|
2007-07-22 21:02:24 +00:00
|
|
|
|
|
|
|
if (v > 1)
|
|
|
|
delta *= v;
|
|
|
|
}
|
|
|
|
|
|
|
|
return delta;
|
|
|
|
}
|
2009-03-02 19:25:50 +00:00
|
|
|
#endif /* HAVE_WHEEL_ACCELERATION */
|